mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.
This commit is contained in:
@@ -359,7 +359,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 287;
|
||||
CURRENT_PROJECT_VERSION = 288;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -367,7 +367,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.287;
|
||||
MARKETING_VERSION = 1.0.288;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -490,7 +490,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 287;
|
||||
CURRENT_PROJECT_VERSION = 288;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -498,7 +498,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.287;
|
||||
MARKETING_VERSION = 1.0.288;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -515,7 +515,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 287;
|
||||
CURRENT_PROJECT_VERSION = 288;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -523,7 +523,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.287;
|
||||
MARKETING_VERSION = 1.0.288;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
|
||||
@@ -166,9 +166,9 @@ void showSnippetDialog(
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
title: Text(s.chooseDestination),
|
||||
child: buildPicker(
|
||||
provider.snippets.map((e) => Text(e.name)).toList(),
|
||||
(idx) => snippet = provider.snippets[idx],
|
||||
child: Picker(
|
||||
items: provider.snippets.map((e) => Text(e.name)).toList(),
|
||||
onSelected: (idx) => snippet = provider.snippets[idx],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
|
||||
@@ -5,28 +5,29 @@ import 'package:toolbox/locator.dart';
|
||||
|
||||
class PrivateKeyProvider extends BusyProvider {
|
||||
List<PrivateKeyInfo> get infos => _infos;
|
||||
final _store = locator<PrivateKeyStore>();
|
||||
late List<PrivateKeyInfo> _infos;
|
||||
|
||||
void loadData() {
|
||||
_infos = locator<PrivateKeyStore>().fetch();
|
||||
_infos = _store.fetch();
|
||||
}
|
||||
|
||||
void addInfo(PrivateKeyInfo info) {
|
||||
_infos.add(info);
|
||||
locator<PrivateKeyStore>().put(info);
|
||||
_store.put(info);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void delInfo(PrivateKeyInfo info) {
|
||||
_infos.removeWhere((e) => e.id == info.id);
|
||||
locator<PrivateKeyStore>().delete(info);
|
||||
_store.delete(info);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void updateInfo(PrivateKeyInfo old, PrivateKeyInfo newInfo) {
|
||||
final idx = _infos.indexWhere((e) => e.id == old.id);
|
||||
_infos[idx] = newInfo;
|
||||
locator<PrivateKeyStore>().put(newInfo);
|
||||
_store.put(newInfo);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,15 +22,18 @@ typedef ServersMap = Map<String, Server>;
|
||||
class ServerProvider extends BusyProvider {
|
||||
final ServersMap _servers = {};
|
||||
ServersMap get servers => _servers;
|
||||
|
||||
final _limiter = TryLimiter();
|
||||
|
||||
Timer? _timer;
|
||||
|
||||
final _logger = Logger('SERVER');
|
||||
|
||||
final _store = locator<ServerStore>();
|
||||
|
||||
Future<void> loadLocalData() async {
|
||||
setBusyState(true);
|
||||
final infos = locator<ServerStore>().fetch();
|
||||
final infos = _store.fetch();
|
||||
for (final info in infos) {
|
||||
_servers[info.id] = genServer(info);
|
||||
}
|
||||
@@ -103,20 +106,20 @@ class ServerProvider extends BusyProvider {
|
||||
void addServer(ServerPrivateInfo spi) {
|
||||
_servers[spi.id] = genServer(spi);
|
||||
notifyListeners();
|
||||
locator<ServerStore>().put(spi);
|
||||
_store.put(spi);
|
||||
refreshData(spi: spi);
|
||||
}
|
||||
|
||||
void delServer(String id) {
|
||||
_servers.remove(id);
|
||||
notifyListeners();
|
||||
locator<ServerStore>().delete(id);
|
||||
_store.delete(id);
|
||||
}
|
||||
|
||||
Future<void> updateServer(
|
||||
ServerPrivateInfo old, ServerPrivateInfo newSpi) async {
|
||||
_servers.remove(old.id);
|
||||
locator<ServerStore>().update(old, newSpi);
|
||||
_store.update(old, newSpi);
|
||||
_servers[newSpi.id] = genServer(newSpi);
|
||||
_servers[newSpi.id]?.client = await genClient(newSpi);
|
||||
notifyListeners();
|
||||
|
||||
@@ -7,23 +7,24 @@ import 'package:toolbox/locator.dart';
|
||||
|
||||
class SnippetProvider extends BusyProvider {
|
||||
List<Snippet> get snippets => _snippets;
|
||||
final _store = locator<SnippetStore>();
|
||||
late List<Snippet> _snippets;
|
||||
|
||||
void loadData() {
|
||||
_snippets = locator<SnippetStore>().fetch();
|
||||
_snippets = _store.fetch();
|
||||
}
|
||||
|
||||
void add(Snippet snippet) {
|
||||
if (have(snippet)) return;
|
||||
_snippets.add(snippet);
|
||||
locator<SnippetStore>().put(snippet);
|
||||
_store.put(snippet);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void del(Snippet snippet) {
|
||||
if (!have(snippet)) return;
|
||||
_snippets.removeAt(index(snippet));
|
||||
locator<SnippetStore>().delete(snippet);
|
||||
_store.delete(snippet);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -38,7 +39,7 @@ class SnippetProvider extends BusyProvider {
|
||||
void update(Snippet old, Snippet newOne) {
|
||||
if (!have(old)) return;
|
||||
_snippets[index(old)] = newOne;
|
||||
locator<SnippetStore>().put(newOne);
|
||||
_store.put(newOne);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 287;
|
||||
static const int build = 288;
|
||||
static const String engine = "3.7.11";
|
||||
static const String buildAt = "2023-05-07 18:25:45.312302";
|
||||
static const int modifications = 2;
|
||||
static const String buildAt = "2023-05-07 20:47:03.124092";
|
||||
static const int modifications = 1;
|
||||
}
|
||||
|
||||
@@ -33,3 +33,15 @@ const popMenuChild = Padding(
|
||||
size: 21,
|
||||
),
|
||||
);
|
||||
|
||||
const centerLoading = Center(child: CircularProgressIndicator());
|
||||
|
||||
const centerSizedLoading = SizedBox(
|
||||
width: 77,
|
||||
height: 77,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
|
||||
const loadingIcon = IconButton(onPressed: null, icon: centerLoading);
|
||||
|
||||
@@ -6,6 +6,7 @@ const issueUrl = '$myGithub/flutter_server_box/issues';
|
||||
|
||||
// Thanks
|
||||
const thanksMap = {
|
||||
'its-tom': 'https://github.com/its-tom',
|
||||
'RainSunMe': 'https://github.com/RainSunMe',
|
||||
'fecture': 'https://github.com/fecture',
|
||||
'Tao173': 'https://github.com/Tao173',
|
||||
|
||||
@@ -32,74 +32,78 @@ class BackupPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final media = MediaQuery.of(context);
|
||||
final s = S.of(context)!;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(s.backupAndRestore, style: textSize18),
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(37),
|
||||
child: Text(
|
||||
s.backupTip,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 107,
|
||||
),
|
||||
_buildCard(s.restore, Icons.download, media, () async {
|
||||
final path = await pickOneFile();
|
||||
if (path == null) {
|
||||
showSnackBar(context, Text(s.notSelected));
|
||||
return;
|
||||
}
|
||||
final file = File(path);
|
||||
if (!file.existsSync()) {
|
||||
showSnackBar(context, Text(s.fileNotExist(path)));
|
||||
return;
|
||||
}
|
||||
final text = await file.readAsString();
|
||||
_import(text, context, s);
|
||||
}),
|
||||
const SizedBox(height: 17),
|
||||
const SizedBox(
|
||||
width: 37,
|
||||
child: Divider(),
|
||||
),
|
||||
const SizedBox(height: 17),
|
||||
_buildCard(
|
||||
s.backup,
|
||||
Icons.file_upload,
|
||||
media,
|
||||
() async {
|
||||
final result = _diyEncrtpt(
|
||||
json.encode(
|
||||
Backup(
|
||||
backupFormatVersion,
|
||||
DateTime.now().toString().split('.').first,
|
||||
_server.fetch(),
|
||||
_snippet.fetch(),
|
||||
_privateKey.fetch(),
|
||||
_dockerHosts.fetch(),
|
||||
),
|
||||
),
|
||||
);
|
||||
final path = '${(await docDir).path}/srvbox_bak.json';
|
||||
await File(path).writeAsString(result);
|
||||
await shareFiles(context, [path]);
|
||||
},
|
||||
)
|
||||
],
|
||||
)),
|
||||
body: _buildBody(context, s),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(BuildContext context, S s) {
|
||||
final media = MediaQuery.of(context);
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(37),
|
||||
child: Text(
|
||||
s.backupTip,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 107,
|
||||
),
|
||||
_buildCard(s.restore, Icons.download, media, () async {
|
||||
final path = await pickOneFile();
|
||||
if (path == null) {
|
||||
showSnackBar(context, Text(s.notSelected));
|
||||
return;
|
||||
}
|
||||
final file = File(path);
|
||||
if (!file.existsSync()) {
|
||||
showSnackBar(context, Text(s.fileNotExist(path)));
|
||||
return;
|
||||
}
|
||||
final text = await file.readAsString();
|
||||
_import(text, context, s);
|
||||
}),
|
||||
const SizedBox(height: 17),
|
||||
const SizedBox(
|
||||
width: 37,
|
||||
child: Divider(),
|
||||
),
|
||||
const SizedBox(height: 17),
|
||||
_buildCard(
|
||||
s.backup,
|
||||
Icons.file_upload,
|
||||
media,
|
||||
() async {
|
||||
final result = _diyEncrtpt(
|
||||
json.encode(
|
||||
Backup(
|
||||
backupFormatVersion,
|
||||
DateTime.now().toString().split('.').first,
|
||||
_server.fetch(),
|
||||
_snippet.fetch(),
|
||||
_privateKey.fetch(),
|
||||
_dockerHosts.fetch(),
|
||||
),
|
||||
),
|
||||
);
|
||||
final path = '${(await docDir).path}/srvbox_bak.json';
|
||||
await File(path).writeAsString(result);
|
||||
await shareFiles(context, [path]);
|
||||
},
|
||||
)
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
Widget _buildCard(String text, IconData icon, MediaQueryData media,
|
||||
FutureOr Function() onTap) {
|
||||
final textColor = primaryColor.isBrightColor ? Colors.black : Colors.white;
|
||||
|
||||
@@ -89,7 +89,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
Widget _buildInputTop() {
|
||||
return SizedBox(
|
||||
height: _media.size.height * 0.33,
|
||||
child: buildInput(controller: _textEditingController),
|
||||
child: Input(controller: _textEditingController),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
Widget _buildResult() {
|
||||
return SizedBox(
|
||||
height: _media.size.height * 0.33,
|
||||
child: buildInput(controller: _textEditingControllerResult),
|
||||
child: Input(controller: _textEditingControllerResult),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import '../../data/res/ui.dart';
|
||||
import '../../data/res/url.dart';
|
||||
import '../../data/store/docker.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/center_loading.dart';
|
||||
import '../widget/dropdown_menu.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
import '../widget/two_line_text.dart';
|
||||
@@ -95,26 +94,23 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
buildInput(
|
||||
Input(
|
||||
type: TextInputType.text,
|
||||
label: _s.dockerImage,
|
||||
hint: 'xxx:1.1',
|
||||
controller: imageCtrl,
|
||||
autoCorrect: false,
|
||||
),
|
||||
buildInput(
|
||||
Input(
|
||||
type: TextInputType.text,
|
||||
controller: nameCtrl,
|
||||
label: _s.dockerContainerName,
|
||||
hint: 'xxx',
|
||||
autoCorrect: false,
|
||||
),
|
||||
buildInput(
|
||||
Input(
|
||||
type: TextInputType.text,
|
||||
controller: argsCtrl,
|
||||
label: _s.extraArgs,
|
||||
hint: '-p 2222:22 -v ~/.xxx/:/xxx',
|
||||
autoCorrect: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -206,7 +202,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
await showRoundDialog(
|
||||
context: context,
|
||||
title: Text(widget.spi.user),
|
||||
child: buildInput(
|
||||
child: Input(
|
||||
controller: _textController,
|
||||
type: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
@@ -379,9 +375,8 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
await showRoundDialog(
|
||||
context: context,
|
||||
title: Text(_s.dockerEditHost),
|
||||
child: buildInput(
|
||||
child: Input(
|
||||
maxLines: 1,
|
||||
autoCorrect: false,
|
||||
controller:
|
||||
TextEditingController(text: 'unix:///run/user/1000/docker.sock'),
|
||||
onSubmitted: (value) {
|
||||
|
||||
@@ -57,7 +57,7 @@ class _PingPageState extends State<PingPage>
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 13),
|
||||
buildInput(
|
||||
Input(
|
||||
controller: _textEditingController,
|
||||
hint: s.inputDomainHere,
|
||||
maxLines: 1,
|
||||
|
||||
@@ -12,7 +12,6 @@ import '../../data/provider/pkg.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/ui.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/center_loading.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
import '../widget/two_line_text.dart';
|
||||
|
||||
@@ -31,7 +30,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
final _scrollController = ScrollController();
|
||||
final _scrollControllerUpdate = ScrollController();
|
||||
final _textController = TextEditingController();
|
||||
final _aptProvider = locator<PkgProvider>();
|
||||
final _pkgProvider = locator<PkgProvider>();
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
@@ -44,7 +43,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
locator<PkgProvider>().clear();
|
||||
_pkgProvider.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -57,7 +56,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
return;
|
||||
}
|
||||
|
||||
_aptProvider.init(
|
||||
_pkgProvider.init(
|
||||
si.client!,
|
||||
si.status.sysVer.dist,
|
||||
() =>
|
||||
@@ -67,7 +66,21 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
onPwdRequest,
|
||||
widget.spi.user,
|
||||
);
|
||||
_aptProvider.refresh();
|
||||
_pkgProvider.refresh();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<PkgProvider>(builder: (_, pkg, __) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: _s.pkg, down: widget.spi.name),
|
||||
),
|
||||
body: _buildBody(pkg),
|
||||
floatingActionButton: _buildFAB(pkg),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void onSubmitted() {
|
||||
@@ -92,7 +105,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
await showRoundDialog(
|
||||
context: context,
|
||||
title: Text(widget.spi.user),
|
||||
child: buildInput(
|
||||
child: Input(
|
||||
controller: _textController,
|
||||
type: TextInputType.visiblePassword,
|
||||
obscureText: true,
|
||||
@@ -118,20 +131,6 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
return _textController.text.trim();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<PkgProvider>(builder: (_, pkg, __) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: _s.pkg, down: widget.spi.name),
|
||||
),
|
||||
body: _buildBody(pkg),
|
||||
floatingActionButton: _buildFAB(pkg),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildFAB(PkgProvider pkg) {
|
||||
if (pkg.isBusy || (pkg.upgradeable?.isEmpty ?? true)) {
|
||||
return const SizedBox();
|
||||
|
||||
@@ -61,128 +61,138 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.info != null
|
||||
? IconButton(
|
||||
tooltip: _s.delete,
|
||||
onPressed: () {
|
||||
_provider.delInfo(widget.info!);
|
||||
context.pop();
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
buildInput(
|
||||
controller: _nameController,
|
||||
type: TextInputType.text,
|
||||
node: _nameNode,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_keyNode),
|
||||
label: _s.name,
|
||||
icon: Icons.info,
|
||||
),
|
||||
buildInput(
|
||||
controller: _keyController,
|
||||
autoCorrect: false,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
type: TextInputType.text,
|
||||
node: _keyNode,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_pwdNode),
|
||||
label: _s.privateKey,
|
||||
icon: Icons.vpn_key,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final path = await pickOneFile();
|
||||
if (path == null) {
|
||||
showSnackBar(context, const Text('path is null'));
|
||||
return;
|
||||
}
|
||||
appBar: _buildAppBar(),
|
||||
body: _buildBody(),
|
||||
floatingActionButton: _buildFAB(),
|
||||
);
|
||||
}
|
||||
|
||||
final file = File(path);
|
||||
if (!file.existsSync()) {
|
||||
showSnackBar(context, Text(_s.fileNotExist(path)));
|
||||
return;
|
||||
}
|
||||
final size = (await file.stat()).size;
|
||||
if (size > privateKeyMaxSize) {
|
||||
showSnackBar(
|
||||
context,
|
||||
Text(
|
||||
_s.fileTooLarge(
|
||||
path,
|
||||
size.convertBytes,
|
||||
privateKeyMaxSize.convertBytes,
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
PreferredSizeWidget _buildAppBar() {
|
||||
return AppBar(
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: [
|
||||
widget.info != null
|
||||
? IconButton(
|
||||
tooltip: _s.delete,
|
||||
onPressed: () {
|
||||
_provider.delInfo(widget.info!);
|
||||
context.pop();
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
: const SizedBox()
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
_keyController.text = await file.readAsString();
|
||||
},
|
||||
child: Text(_s.pickFile),
|
||||
),
|
||||
buildInput(
|
||||
controller: _pwdController,
|
||||
autoCorrect: false,
|
||||
type: TextInputType.text,
|
||||
node: _pwdNode,
|
||||
obscureText: true,
|
||||
label: _s.pwd,
|
||||
icon: Icons.password,
|
||||
),
|
||||
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
||||
_loading
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
tooltip: _s.save,
|
||||
onPressed: () async {
|
||||
final name = _nameController.text;
|
||||
final key = _keyController.text.trim();
|
||||
final pwd = _pwdController.text;
|
||||
if (name.isEmpty || key.isEmpty) {
|
||||
showSnackBar(context, Text(_s.fieldMustNotEmpty));
|
||||
return;
|
||||
}
|
||||
FocusScope.of(context).unfocus();
|
||||
Widget _buildFAB() {
|
||||
return FloatingActionButton(
|
||||
tooltip: _s.save,
|
||||
onPressed: () async {
|
||||
final name = _nameController.text;
|
||||
final key = _keyController.text.trim();
|
||||
final pwd = _pwdController.text;
|
||||
if (name.isEmpty || key.isEmpty) {
|
||||
showSnackBar(context, Text(_s.fieldMustNotEmpty));
|
||||
return;
|
||||
}
|
||||
FocusScope.of(context).unfocus();
|
||||
setState(() {
|
||||
_loading = const SizedBox(
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
});
|
||||
final info = PrivateKeyInfo(name, key, '');
|
||||
bool haveErr = false;
|
||||
try {
|
||||
info.privateKey = await compute(decyptPem, [key, pwd]);
|
||||
} catch (e) {
|
||||
showSnackBar(context, Text(e.toString()));
|
||||
haveErr = true;
|
||||
} finally {
|
||||
setState(() {
|
||||
_loading = const SizedBox(
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
_loading = const SizedBox();
|
||||
});
|
||||
final info = PrivateKeyInfo(name, key, '');
|
||||
bool haveErr = false;
|
||||
try {
|
||||
info.privateKey = await compute(decyptPem, [key, pwd]);
|
||||
} catch (e) {
|
||||
showSnackBar(context, Text(e.toString()));
|
||||
haveErr = true;
|
||||
} finally {
|
||||
setState(() {
|
||||
_loading = const SizedBox();
|
||||
});
|
||||
}
|
||||
if (haveErr) return;
|
||||
if (widget.info != null) {
|
||||
_provider.updateInfo(widget.info!, info);
|
||||
} else {
|
||||
_provider.addInfo(info);
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
child: const Icon(Icons.save),
|
||||
),
|
||||
}
|
||||
if (haveErr) return;
|
||||
if (widget.info != null) {
|
||||
_provider.updateInfo(widget.info!, info);
|
||||
} else {
|
||||
_provider.addInfo(info);
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
child: const Icon(Icons.save),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
Input(
|
||||
controller: _nameController,
|
||||
type: TextInputType.text,
|
||||
node: _nameNode,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_keyNode),
|
||||
label: _s.name,
|
||||
icon: Icons.info,
|
||||
),
|
||||
Input(
|
||||
controller: _keyController,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
type: TextInputType.text,
|
||||
node: _keyNode,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_pwdNode),
|
||||
label: _s.privateKey,
|
||||
icon: Icons.vpn_key,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final path = await pickOneFile();
|
||||
if (path == null) {
|
||||
showSnackBar(context, const Text('path is null'));
|
||||
return;
|
||||
}
|
||||
|
||||
final file = File(path);
|
||||
if (!file.existsSync()) {
|
||||
showSnackBar(context, Text(_s.fileNotExist(path)));
|
||||
return;
|
||||
}
|
||||
final size = (await file.stat()).size;
|
||||
if (size > privateKeyMaxSize) {
|
||||
showSnackBar(
|
||||
context,
|
||||
Text(
|
||||
_s.fileTooLarge(
|
||||
path,
|
||||
size.convertBytes,
|
||||
privateKeyMaxSize.convertBytes,
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
_keyController.text = await file.readAsString();
|
||||
},
|
||||
child: Text(_s.pickFile),
|
||||
),
|
||||
Input(
|
||||
controller: _pwdController,
|
||||
type: TextInputType.text,
|
||||
node: _pwdNode,
|
||||
obscureText: true,
|
||||
label: _s.pwd,
|
||||
icon: Icons.password,
|
||||
),
|
||||
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
||||
_loading
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,41 +30,44 @@ class _PrivateKeyListState extends State<PrivateKeysListPage> {
|
||||
appBar: AppBar(
|
||||
title: Text(_s.privateKey, style: textSize18),
|
||||
),
|
||||
body: Consumer<PrivateKeyProvider>(
|
||||
builder: (_, key, __) {
|
||||
if (key.infos.isEmpty) {
|
||||
return Center(
|
||||
child: Text(_s.noSavedPrivateKey),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(13),
|
||||
itemCount: key.infos.length,
|
||||
itemBuilder: (context, idx) {
|
||||
return RoundRectCard(
|
||||
ListTile(
|
||||
title: Text(
|
||||
key.infos[idx].id,
|
||||
),
|
||||
trailing: TextButton(
|
||||
onPressed: () => AppRoute(
|
||||
PrivateKeyEditPage(info: key.infos[idx]),
|
||||
'private key edit page',
|
||||
).go(context),
|
||||
child: Text(_s.edit),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
body: _buildBody(),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Icons.add),
|
||||
onPressed: () =>
|
||||
AppRoute(const PrivateKeyEditPage(), 'private key edit page')
|
||||
.go(context),
|
||||
onPressed: () => AppRoute(
|
||||
const PrivateKeyEditPage(),
|
||||
'private key edit page',
|
||||
).go(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return Consumer<PrivateKeyProvider>(
|
||||
builder: (_, key, __) {
|
||||
if (key.infos.isEmpty) {
|
||||
return Center(
|
||||
child: Text(_s.noSavedPrivateKey),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(13),
|
||||
itemCount: key.infos.length,
|
||||
itemBuilder: (context, idx) {
|
||||
return RoundRectCard(
|
||||
ListTile(
|
||||
title: Text(key.infos[idx].id),
|
||||
trailing: TextButton(
|
||||
onPressed: () => AppRoute(
|
||||
PrivateKeyEditPage(info: key.infos[idx]),
|
||||
'private key edit page',
|
||||
).go(context),
|
||||
child: Text(_s.edit),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildInput(
|
||||
Input(
|
||||
controller: _nameController,
|
||||
type: TextInputType.text,
|
||||
node: _nameFocus,
|
||||
@@ -117,17 +117,16 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
label: _s.name,
|
||||
icon: Icons.info,
|
||||
),
|
||||
buildInput(
|
||||
Input(
|
||||
controller: _ipController,
|
||||
type: TextInputType.text,
|
||||
onSubmitted: (_) => _focusScope.requestFocus(_portFocus),
|
||||
node: _ipFocus,
|
||||
autoCorrect: false,
|
||||
label: _s.host,
|
||||
icon: Icons.storage,
|
||||
hint: 'example.com',
|
||||
),
|
||||
buildInput(
|
||||
Input(
|
||||
controller: _portController,
|
||||
type: TextInputType.number,
|
||||
node: _portFocus,
|
||||
@@ -136,11 +135,10 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
icon: Icons.format_list_numbered,
|
||||
hint: '22',
|
||||
),
|
||||
buildInput(
|
||||
Input(
|
||||
controller: _usernameController,
|
||||
type: TextInputType.text,
|
||||
node: _usernameFocus,
|
||||
autoCorrect: false,
|
||||
label: _s.user,
|
||||
icon: Icons.account_box,
|
||||
hint: 'root',
|
||||
@@ -158,7 +156,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
],
|
||||
),
|
||||
!usePublicKey
|
||||
? buildInput(
|
||||
? Input(
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
type: TextInputType.text,
|
||||
|
||||
@@ -62,38 +62,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return Scaffold(
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () async =>
|
||||
await _serverProvider.refreshData(onlyFailed: true),
|
||||
child: Consumer<ServerProvider>(
|
||||
builder: (_, pro, __) {
|
||||
if (pro.servers.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
_s.serverTabEmpty,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
final keys = pro.servers.keys.toList();
|
||||
return ListView.separated(
|
||||
padding: const EdgeInsets.fromLTRB(7, 10, 7, 7),
|
||||
controller: ScrollController(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
itemBuilder: (ctx, idx) {
|
||||
if (idx == pro.servers.length) {
|
||||
return SizedBox(height: _media.padding.bottom);
|
||||
}
|
||||
return _buildEachServerCard(pro.servers[keys[idx]]);
|
||||
},
|
||||
itemCount: pro.servers.length,
|
||||
separatorBuilder: (_, __) => const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
body: _buildBody(),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () => AppRoute(
|
||||
const ServerEditPage(),
|
||||
@@ -106,6 +75,41 @@ class _ServerPageState extends State<ServerPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async =>
|
||||
await _serverProvider.refreshData(onlyFailed: true),
|
||||
child: Consumer<ServerProvider>(
|
||||
builder: (_, pro, __) {
|
||||
if (pro.servers.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
_s.serverTabEmpty,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
final keys = pro.servers.keys.toList();
|
||||
return ListView.separated(
|
||||
padding: const EdgeInsets.fromLTRB(7, 10, 7, 7),
|
||||
controller: ScrollController(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
itemBuilder: (ctx, idx) {
|
||||
if (idx == pro.servers.length) {
|
||||
return SizedBox(height: _media.padding.bottom);
|
||||
}
|
||||
return _buildEachServerCard(pro.servers[keys[idx]]);
|
||||
},
|
||||
itemCount: pro.servers.length,
|
||||
separatorBuilder: (_, __) => const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEachServerCard(Server? si) {
|
||||
if (si == null) {
|
||||
return const SizedBox();
|
||||
|
||||
@@ -8,7 +8,6 @@ import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/sftp/download_status.dart';
|
||||
import '../../../data/provider/sftp_download.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../widget/center_loading.dart';
|
||||
import '../../widget/round_rect_card.dart';
|
||||
|
||||
class SFTPDownloadingPage extends StatefulWidget {
|
||||
|
||||
@@ -18,9 +18,9 @@ import '../../../data/model/sftp/download_item.dart';
|
||||
import '../../../data/provider/server.dart';
|
||||
import '../../../data/provider/sftp_download.dart';
|
||||
import '../../../data/res/path.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../../data/store/private_key.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/center_loading.dart';
|
||||
import '../../widget/fade_in.dart';
|
||||
import '../../widget/two_line_text.dart';
|
||||
import 'downloading.dart';
|
||||
@@ -144,7 +144,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
buildInput(
|
||||
Input(
|
||||
label: _s.path,
|
||||
hint: '/',
|
||||
onSubmitted: (value) => context.pop(value),
|
||||
@@ -378,7 +378,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
title: Text(_s.createFolder),
|
||||
child: buildInput(
|
||||
child: Input(
|
||||
controller: textController,
|
||||
label: _s.name,
|
||||
),
|
||||
@@ -422,7 +422,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
title: Text(_s.createFile),
|
||||
child: buildInput(
|
||||
child: Input(
|
||||
controller: textController,
|
||||
label: _s.name,
|
||||
),
|
||||
@@ -467,7 +467,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
title: Text(_s.rename),
|
||||
child: buildInput(
|
||||
child: Input(
|
||||
controller: textController,
|
||||
label: _s.name,
|
||||
),
|
||||
|
||||
@@ -57,47 +57,53 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
buildInput(
|
||||
controller: _nameController,
|
||||
type: TextInputType.text,
|
||||
onSubmitted: (_) =>
|
||||
FocusScope.of(context).requestFocus(_scriptNode),
|
||||
label: _s.name,
|
||||
icon: Icons.info,
|
||||
),
|
||||
buildInput(
|
||||
controller: _scriptController,
|
||||
autoCorrect: false,
|
||||
node: _scriptNode,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
type: TextInputType.text,
|
||||
label: _s.snippet,
|
||||
icon: Icons.code,
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Icons.send),
|
||||
onPressed: () {
|
||||
final name = _nameController.text;
|
||||
final script = _scriptController.text;
|
||||
if (name.isEmpty || script.isEmpty) {
|
||||
showSnackBar(context, Text(_s.fieldMustNotEmpty));
|
||||
return;
|
||||
}
|
||||
final snippet = Snippet(name, script);
|
||||
if (widget.snippet != null) {
|
||||
_provider.update(widget.snippet!, snippet);
|
||||
} else {
|
||||
_provider.add(snippet);
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
body: _buildBody(),
|
||||
floatingActionButton: _buildFAB(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFAB() {
|
||||
return FloatingActionButton(
|
||||
child: const Icon(Icons.send),
|
||||
onPressed: () {
|
||||
final name = _nameController.text;
|
||||
final script = _scriptController.text;
|
||||
if (name.isEmpty || script.isEmpty) {
|
||||
showSnackBar(context, Text(_s.fieldMustNotEmpty));
|
||||
return;
|
||||
}
|
||||
final snippet = Snippet(name, script);
|
||||
if (widget.snippet != null) {
|
||||
_provider.update(widget.snippet!, snippet);
|
||||
} else {
|
||||
_provider.add(snippet);
|
||||
}
|
||||
context.pop();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(13),
|
||||
children: [
|
||||
Input(
|
||||
controller: _nameController,
|
||||
type: TextInputType.text,
|
||||
onSubmitted: (_) => FocusScope.of(context).requestFocus(_scriptNode),
|
||||
label: _s.name,
|
||||
icon: Icons.info,
|
||||
),
|
||||
Input(
|
||||
controller: _scriptController,
|
||||
node: _scriptNode,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
type: TextInputType.text,
|
||||
label: _s.snippet,
|
||||
icon: Icons.code,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,61 +76,6 @@ class _SSHPageState extends State<SSHPage> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _write(String p0) {
|
||||
_terminal.write('$p0\r\n');
|
||||
}
|
||||
|
||||
Future<void> initTerminal() async {
|
||||
_write('Connecting...\r\n');
|
||||
|
||||
_client = await genClient(
|
||||
widget.spi,
|
||||
onStatus: (p0) {
|
||||
switch (p0) {
|
||||
case GenSSHClientStatus.socket:
|
||||
_write('Destination: ${widget.spi.id}');
|
||||
return _write('Establishing socket...');
|
||||
case GenSSHClientStatus.key:
|
||||
return _write('Using private key to connect...');
|
||||
case GenSSHClientStatus.pwd:
|
||||
return _write('Sending password to auth...');
|
||||
}
|
||||
},
|
||||
);
|
||||
_write('Connected\r\n');
|
||||
_write('Terminal size: ${_terminal.viewWidth}x${_terminal.viewHeight}\r\n');
|
||||
_write('Starting shell...\r\n');
|
||||
|
||||
final session = await _client!.shell(
|
||||
pty: SSHPtyConfig(
|
||||
width: _terminal.viewWidth,
|
||||
height: _terminal.viewHeight,
|
||||
),
|
||||
);
|
||||
|
||||
_terminal.buffer.clear();
|
||||
_terminal.buffer.setCursor(0, 0);
|
||||
|
||||
_terminal.onOutput = (data) {
|
||||
session.write(utf8.encode(data) as Uint8List);
|
||||
};
|
||||
|
||||
_listen(session.stdout);
|
||||
_listen(session.stderr);
|
||||
|
||||
await session.done;
|
||||
if (mounted) {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void _listen(Stream<Uint8List> stream) {
|
||||
stream
|
||||
.cast<List<int>>()
|
||||
.transform(const Utf8Decoder())
|
||||
.listen(_terminal.write);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget child = Scaffold(
|
||||
@@ -357,4 +302,59 @@ class _SSHPageState extends State<SSHPage> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _write(String p0) {
|
||||
_terminal.write('$p0\r\n');
|
||||
}
|
||||
|
||||
Future<void> initTerminal() async {
|
||||
_write('Connecting...\r\n');
|
||||
|
||||
_client = await genClient(
|
||||
widget.spi,
|
||||
onStatus: (p0) {
|
||||
switch (p0) {
|
||||
case GenSSHClientStatus.socket:
|
||||
_write('Destination: ${widget.spi.id}');
|
||||
return _write('Establishing socket...');
|
||||
case GenSSHClientStatus.key:
|
||||
return _write('Using private key to connect...');
|
||||
case GenSSHClientStatus.pwd:
|
||||
return _write('Sending password to auth...');
|
||||
}
|
||||
},
|
||||
);
|
||||
_write('Connected\r\n');
|
||||
_write('Terminal size: ${_terminal.viewWidth}x${_terminal.viewHeight}\r\n');
|
||||
_write('Starting shell...\r\n');
|
||||
|
||||
final session = await _client!.shell(
|
||||
pty: SSHPtyConfig(
|
||||
width: _terminal.viewWidth,
|
||||
height: _terminal.viewHeight,
|
||||
),
|
||||
);
|
||||
|
||||
_terminal.buffer.clear();
|
||||
_terminal.buffer.setCursor(0, 0);
|
||||
|
||||
_terminal.onOutput = (data) {
|
||||
session.write(utf8.encode(data) as Uint8List);
|
||||
};
|
||||
|
||||
_listen(session.stdout);
|
||||
_listen(session.stderr);
|
||||
|
||||
await session.done;
|
||||
if (mounted) {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void _listen(Stream<Uint8List> stream) {
|
||||
stream
|
||||
.cast<List<int>>()
|
||||
.transform(const Utf8Decoder())
|
||||
.listen(_terminal.write);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
const centerLoading = Center(child: CircularProgressIndicator());
|
||||
|
||||
const centerSizedLoading = SizedBox(
|
||||
width: 77,
|
||||
height: 77,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
|
||||
final loadingIcon = IconButton(onPressed: () {}, icon: centerLoading);
|
||||
@@ -1,38 +1,59 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
Widget buildInput({
|
||||
TextEditingController? controller,
|
||||
int maxLines = 1,
|
||||
int? minLines,
|
||||
String? hint,
|
||||
String? label,
|
||||
Function(String)? onSubmitted,
|
||||
bool obscureText = false,
|
||||
IconData? icon,
|
||||
TextInputType? type,
|
||||
FocusNode? node,
|
||||
bool autoCorrect = true,
|
||||
}) {
|
||||
return RoundRectCard(
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 17),
|
||||
child: TextField(
|
||||
maxLines: maxLines,
|
||||
minLines: minLines,
|
||||
onSubmitted: onSubmitted,
|
||||
keyboardType: type,
|
||||
focusNode: node,
|
||||
autocorrect: autoCorrect,
|
||||
decoration: InputDecoration(
|
||||
label: label != null ? Text(label) : null,
|
||||
hintText: hint,
|
||||
icon: icon != null ? Icon(icon) : null,
|
||||
border: InputBorder.none,
|
||||
import 'round_rect_card.dart';
|
||||
|
||||
class Input extends StatelessWidget {
|
||||
final TextEditingController? controller;
|
||||
final int maxLines;
|
||||
final int? minLines;
|
||||
final String? hint;
|
||||
final String? label;
|
||||
final Function(String)? onSubmitted;
|
||||
final bool obscureText;
|
||||
final IconData? icon;
|
||||
final TextInputType? type;
|
||||
final FocusNode? node;
|
||||
final bool autoCorrect;
|
||||
final bool suggestiion;
|
||||
|
||||
const Input({
|
||||
super.key,
|
||||
this.controller,
|
||||
this.maxLines = 1,
|
||||
this.minLines,
|
||||
this.hint,
|
||||
this.label,
|
||||
this.onSubmitted,
|
||||
this.obscureText = false,
|
||||
this.icon,
|
||||
this.type,
|
||||
this.node,
|
||||
this.autoCorrect = false,
|
||||
this.suggestiion = false,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RoundRectCard(
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 17),
|
||||
child: TextField(
|
||||
maxLines: maxLines,
|
||||
minLines: minLines,
|
||||
onSubmitted: onSubmitted,
|
||||
keyboardType: type,
|
||||
focusNode: node,
|
||||
autocorrect: autoCorrect,
|
||||
enableSuggestions: suggestiion,
|
||||
decoration: InputDecoration(
|
||||
label: label != null ? Text(label!) : null,
|
||||
hintText: hint,
|
||||
icon: icon != null ? Icon(icon) : null,
|
||||
border: InputBorder.none,
|
||||
),
|
||||
controller: controller,
|
||||
obscureText: obscureText,
|
||||
),
|
||||
controller: controller,
|
||||
obscureText: obscureText,
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget buildPicker(
|
||||
List<Widget> items,
|
||||
Function(int idx) onSelected, {
|
||||
double height = 157,
|
||||
}) {
|
||||
final pad = (height - 37) / 2;
|
||||
return SizedBox(
|
||||
height: height,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: pad,
|
||||
bottom: pad,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 37,
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
color: Colors.black12,
|
||||
class Picker extends StatelessWidget {
|
||||
final List<Widget> items;
|
||||
final Function(int idx) onSelected;
|
||||
final double height;
|
||||
|
||||
const Picker({
|
||||
super.key,
|
||||
required this.items,
|
||||
required this.onSelected,
|
||||
this.height = 157,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final pad = (height - 37) / 2;
|
||||
return SizedBox(
|
||||
height: height,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: pad,
|
||||
bottom: pad,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 37,
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(7)),
|
||||
color: Colors.black12,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ListWheelScrollView.useDelegate(
|
||||
itemExtent: 37,
|
||||
diameterRatio: 2.7,
|
||||
controller: FixedExtentScrollController(initialItem: 0),
|
||||
onSelectedItemChanged: (idx) => onSelected(idx),
|
||||
physics: const FixedExtentScrollPhysics(),
|
||||
childDelegate: ListWheelChildBuilderDelegate(
|
||||
builder: (context, index) => Center(
|
||||
child: items[index],
|
||||
ListWheelScrollView.useDelegate(
|
||||
itemExtent: 37,
|
||||
diameterRatio: 2.7,
|
||||
controller: FixedExtentScrollController(initialItem: 0),
|
||||
onSelectedItemChanged: (idx) => onSelected(idx),
|
||||
physics: const FixedExtentScrollPhysics(),
|
||||
childDelegate: ListWheelChildBuilderDelegate(
|
||||
builder: (context, index) => Center(
|
||||
child: items[index],
|
||||
),
|
||||
childCount: items.length,
|
||||
),
|
||||
childCount: items.length,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
172
pubspec.lock
172
pubspec.lock
@@ -5,10 +5,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: e440ac42679dfc04bbbefb58ed225c994bc7e07fccc8a68ec7d3631a127e5da9
|
||||
sha256: "8880b4cfe7b5b17d57c052a5a3a8cc1d4f546261c7cc8fbd717bd53f48db0568"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "54.0.0"
|
||||
version: "59.0.0"
|
||||
after_layout:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -21,26 +21,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "2c2e3721ee9fb36de92faa060f3480c81b23e904352b087e5c64224b1a044427"
|
||||
sha256: a89627f49b0e70e068130a36571409726b04dab12da7e5625941d2c8ec278b96
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.6.0"
|
||||
version: "5.11.1"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d
|
||||
sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.6"
|
||||
version: "3.3.7"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
|
||||
sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
version: "2.4.1"
|
||||
asn1lib:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -125,10 +125,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725"
|
||||
sha256: "2f17434bd5d52a26762043d6b43bb53b3acd029b4d9071a329f46d67ef297e6d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.4.3"
|
||||
version: "8.5.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -141,10 +141,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311"
|
||||
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
version: "2.0.3"
|
||||
circle_chart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -206,10 +206,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
version: "3.0.3"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -222,10 +222,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4"
|
||||
sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
version: "2.3.1"
|
||||
dartssh2:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -270,10 +270,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: extended_image_library
|
||||
sha256: b1de389378589e4dffb3564d782373238f19064037458092c49b3043b2791b2b
|
||||
sha256: "550743b43ab093aed35ef234500fcc7a304cbac1eca47b0cc991e07e88750758"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "3.4.2"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -302,10 +302,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
sha256: d090ae03df98b0247b82e5928f44d1b959867049d18d73635e2e0bc3f49542b9
|
||||
sha256: b85eb92b175767fdaa0c543bf3b0d1f610fe966412ea72845fe5ba7801e763ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.2.5"
|
||||
version: "5.2.10"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -344,18 +344,18 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_native_splash
|
||||
sha256: e301ae206ff0fb09b67d3716009c6c28c2da57a0ad164827b178421bb9d601f7
|
||||
sha256: af665ef80a213a9ed502845a3d7a61b9acca4100ee7e9f067a7440bc3acd6730
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.18"
|
||||
version: "2.2.19"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2"
|
||||
sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
version: "2.0.14"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@@ -378,10 +378,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: get_it
|
||||
sha256: "290fde3a86072e4b37dbb03c07bec6126f0ecc28dad403c12ffe2e5a2d751ab7"
|
||||
sha256: "43133b45f32f1d96bbaeb43ea35a50ce854981baa80f47c3e26ee2ad23bef113"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.0"
|
||||
version: "7.5.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -426,26 +426,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269
|
||||
sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.15.1"
|
||||
version: "0.15.3"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482"
|
||||
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.5"
|
||||
version: "0.13.6"
|
||||
http_client_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_client_helper
|
||||
sha256: "1f32359bd07a064ad256d1f84ae5f973f69bc972e7287223fa198abe1d969c28"
|
||||
sha256: "14c6e756644339f561321dab021215475ba4779aa962466f59ccb3ecf66b36c3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
version: "2.0.4"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -466,10 +466,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: "483a389d6ccb292b570c31b3a193779b1b0178e7eb571986d9a49904b6861227"
|
||||
sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.15"
|
||||
version: "4.0.17"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -498,10 +498,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317
|
||||
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.0"
|
||||
version: "4.8.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -578,34 +578,34 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9"
|
||||
sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.13"
|
||||
version: "2.0.14"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e"
|
||||
sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.23"
|
||||
version: "2.0.27"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972
|
||||
sha256: ad4c4d011830462633f03eb34445a45345673dfd4faf1ab0b4735fbd93b19183
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.2.2"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a"
|
||||
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.9"
|
||||
version: "2.1.10"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -618,10 +618,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d"
|
||||
sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.1.6"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -682,10 +682,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.6.2"
|
||||
version: "3.7.3"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -714,18 +714,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.4"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a"
|
||||
sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.2.3"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -746,18 +746,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: share_plus
|
||||
sha256: "692261968a494e47323dcc8bc66d8d52e81bc27cb4b808e4e8d7e8079d4cc01a"
|
||||
sha256: b1f15232d41e9701ab2f04181f21610c36c83a12ae426b79b4bd011c567934b1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
version: "6.3.4"
|
||||
share_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus_platform_interface
|
||||
sha256: "82ddd4ab9260c295e6e39612d4ff00390b9a7a21f1bb1da771e2f232d80ab8a1"
|
||||
sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
version: "3.2.1"
|
||||
share_plus_web:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -770,18 +770,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.4.1"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8
|
||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "1.0.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -791,10 +791,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
sha256: c2bea18c95cfa0276a366270afaa2850b09b4a76db95d546f3d003dcc7011298
|
||||
sha256: b20e191de6964e98032573cecb1d2b169d96ba63fdb586d24dcd1003ba7e94f6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.7"
|
||||
version: "1.3.0"
|
||||
source_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -895,34 +895,34 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "1f4d9ebe86f333c15d318f81dcdc08b01d45da44af74552608455ebdc08d9732"
|
||||
sha256: "22f8db4a72be26e9e3a4aa3f194b1f7afbc76d20ec141f84be1d787db2155cbd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.24"
|
||||
version: "6.0.31"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: c9cd648d2f7ab56968e049d4e9116f96a85517f1dd806b96a86ea1018a3a82e5
|
||||
sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.1"
|
||||
version: "6.1.4"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682
|
||||
sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.5"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "2dddb3291a57b074dade66b5e07e64401dd2487caefd4e9e2f467138d8c7eb06"
|
||||
sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
version: "3.0.5"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -935,18 +935,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b"
|
||||
sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.15"
|
||||
version: "2.0.16"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b"
|
||||
sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.4"
|
||||
version: "3.0.6"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -975,18 +975,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b
|
||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
version: "2.4.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46
|
||||
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
version: "3.1.4"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1008,18 +1008,26 @@ packages:
|
||||
description:
|
||||
path: "."
|
||||
ref: master
|
||||
resolved-ref: "8039a582d855428cec49b23641bcfcafd6682574"
|
||||
resolved-ref: e945750b97a2f875befa37e0c483bc3f51e215b2
|
||||
url: "https://github.com/lollipopkit/xterm.dart"
|
||||
source: git
|
||||
version: "3.4.1"
|
||||
version: "3.6.1-pre"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370"
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
version: "3.1.2"
|
||||
zmodem:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: zmodem
|
||||
sha256: "3b7e5b29f3a7d8aee472029b05165a68438eff2f3f7766edf13daba1e297adbf"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.6"
|
||||
sdks:
|
||||
dart: ">=2.19.0 <3.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
|
||||
Reference in New Issue
Block a user