diff --git a/lib/core/route.dart b/lib/core/route.dart index a6965807c..9a92b0aca 100644 --- a/lib/core/route.dart +++ b/lib/core/route.dart @@ -1,9 +1,7 @@ -import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:server_box/data/model/server/private_key_info.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; -import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/backup.dart'; import 'package:server_box/view/page/container.dart'; @@ -152,16 +150,6 @@ class AppRoutes { return AppRoutes(BackupPage(key: key), 'backup'); } - static AppRoutes debug({Key? key}) { - return AppRoutes( - DebugPage( - key: key, - args: const DebugPageArgs(title: 'Logs(${BuildData.build})'), - ), - 'debug', - ); - } - static AppRoutes docker({Key? key, required ServerPrivateInfo spi}) { return AppRoutes(ContainerPage(key: key, spi: spi), 'docker'); } diff --git a/lib/view/page/home/appbar.dart b/lib/view/page/home/appbar.dart index 08b959541..d407fece2 100644 --- a/lib/view/page/home/appbar.dart +++ b/lib/view/page/home/appbar.dart @@ -14,22 +14,22 @@ final class _AppBar extends CustomAppBar { @override Widget build(BuildContext context) { - if (isDesktop) return super.build(context); - final placeholder = SizedBox( height: CustomAppBar.barHeight ?? 0 + MediaQuery.of(context).padding.top, ); - return ValBuilder( - listenable: landscape, - builder: (ls) { - if (ls) return placeholder; + return selectIndex.listenVal( + (idx) { + if (idx == AppTab.ssh.index) { + return placeholder; + } + + if (isDesktop) return super.build(context); return ValBuilder( - listenable: selectIndex, - builder: (idx) { - if (idx == AppTab.ssh.index) { - return placeholder; - } + listenable: landscape, + builder: (ls) { + if (ls) return placeholder; + return super.build(context); }, ); diff --git a/lib/view/page/home/home.dart b/lib/view/page/home/home.dart index 493958705..b4ec1c99e 100644 --- a/lib/view/page/home/home.dart +++ b/lib/view/page/home/home.dart @@ -14,7 +14,6 @@ import 'package:server_box/data/res/misc.dart'; import 'package:server_box/data/res/provider.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/url.dart'; -import 'package:server_box/view/page/ssh/page.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; part 'appbar.dart'; @@ -128,7 +127,10 @@ class _HomePageState extends State IconButton( icon: const Icon(Icons.developer_mode, size: 21), tooltip: 'Debug', - onPressed: () => AppRoutes.debug().go(context), + onPressed: () => DebugPage.route.go( + context, + args: const DebugPageArgs(title: 'Debug(${BuildData.build})'), + ), ), ], ); @@ -141,7 +143,7 @@ class _HomePageState extends State physics: const NeverScrollableScrollPhysics(), itemBuilder: (_, index) => AppTab.values[index].page, onPageChanged: (value) { - SSHPage.focusNode.unfocus(); + FocusScope.of(context).unfocus(); if (!_switchingPage) { _selectIndex.value = value; } diff --git a/lib/view/page/ssh/page.dart b/lib/view/page/ssh/page.dart index a2d93af6a..b8ebbcee4 100644 --- a/lib/view/page/ssh/page.dart +++ b/lib/view/page/ssh/page.dart @@ -32,6 +32,7 @@ class SSHPage extends StatefulWidget { final bool notFromTab; final Function()? onSessionEnd; final GlobalKey? terminalKey; + final FocusNode? focusNode; const SSHPage({ super.key, @@ -41,10 +42,9 @@ class SSHPage extends StatefulWidget { this.notFromTab = true, this.onSessionEnd, this.terminalKey, + this.focusNode, }); - static final focusNode = FocusNode(); - @override State createState() => SSHPageState(); } @@ -158,7 +158,7 @@ class SSHPageState extends State CustomAppBar.barHeight ?? _media.padding.top, ), hideScrollBar: false, - focusNode: SSHPage.focusNode, + focusNode: widget.focusNode, ), ), ); @@ -432,7 +432,7 @@ class SSHPageState extends State widget.initSnippet!.runInTerm(_terminal, widget.spi); } - SSHPage.focusNode.requestFocus(); + widget.focusNode?.requestFocus(); await session.done; if (mounted && widget.notFromTab) { diff --git a/lib/view/page/ssh/tab.dart b/lib/view/page/ssh/tab.dart index 3b68bc226..0f2bcec03 100644 --- a/lib/view/page/ssh/tab.dart +++ b/lib/view/page/ssh/tab.dart @@ -17,12 +17,12 @@ class SSHTabPage extends StatefulWidget { State createState() => _SSHTabPageState(); } -typedef _TabMap = Map? key})>; +typedef _TabMap = Map; class _SSHTabPageState extends State with TickerProviderStateMixin, AutomaticKeepAliveClientMixin { late final _TabMap _tabMap = { - libL10n.add: (page: _buildAddPage(), key: null), + libL10n.add: (page: _buildAddPage(), focus: null), }; final _pageCtrl = PageController(); final _fabVN = 0.vn; @@ -61,12 +61,9 @@ class _SSHTabPageState extends State void _onTapTab(int idx) async { await _toPage(idx); - SSHPage.focusNode.unfocus(); } void _onTapClose(String name) async { - SSHPage.focusNode.unfocus(); - final confirm = await showDialog( context: context, builder: (context) { @@ -95,8 +92,11 @@ class _SSHTabPageState extends State child: Text(libL10n.empty, textAlign: TextAlign.center), ); } + + final ratio = context.media.size.aspectRatio; return GridView.builder( padding: const EdgeInsets.all(7), + cacheExtent: 50, itemBuilder: (context, idx) { final spi = Pros.server.pick(id: pro.serverOrder[idx])?.spi; if (spi == null) return UIs.placeholder; @@ -109,10 +109,7 @@ class _SSHTabPageState extends State child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - spi.name, - style: Theme.of(context).textTheme.bodyLarge, - ), + Text(spi.name, style: UIs.text18), const Icon(Icons.chevron_right) ], ), @@ -121,9 +118,9 @@ class _SSHTabPageState extends State ); }, itemCount: pro.servers.length, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, - childAspectRatio: 3, + childAspectRatio: 3 * (ratio / (9 / 16)), crossAxisSpacing: 3, mainAxisSpacing: 3, ), @@ -178,7 +175,7 @@ class _SSHTabPageState extends State _tabMap.remove(name); }, ), - key: key, + focus: FocusNode(), ); _tabRN.notify(); // Wait for the page to be built @@ -187,8 +184,14 @@ class _SSHTabPageState extends State await _toPage(idx); } - Future _toPage(int idx) => _pageCtrl.animateToPage(idx, - duration: Durations.short3, curve: Curves.fastEaseInToSlowEaseOut); + Future _toPage(int idx) async { + await _pageCtrl.animateToPage(idx, + duration: Durations.short3, curve: Curves.fastEaseInToSlowEaseOut); + final focus = _tabMap.values.elementAt(idx).focus; + if (focus != null) { + FocusScope.of(context).requestFocus(focus); + } + } @override bool get wantKeepAlive => true; diff --git a/macos/Podfile.lock b/macos/Podfile.lock index dcd684b39..634186826 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -6,6 +6,9 @@ PODS: - FlutterMacOS (1.0.0) - icloud_storage (0.0.1): - FlutterMacOS + - local_auth_darwin (0.0.1): + - Flutter + - FlutterMacOS - package_info_plus (0.0.1): - FlutterMacOS - path_provider_foundation (0.0.1): @@ -30,6 +33,7 @@ DEPENDENCIES: - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - icloud_storage (from `Flutter/ephemeral/.symlinks/plugins/icloud_storage/macos`) + - local_auth_darwin (from `Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) @@ -48,6 +52,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral icloud_storage: :path: Flutter/ephemeral/.symlinks/plugins/icloud_storage/macos + local_auth_darwin: + :path: Flutter/ephemeral/.symlinks/plugins/local_auth_darwin/darwin package_info_plus: :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos path_provider_foundation: @@ -70,6 +76,7 @@ SPEC CHECKSUMS: dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 icloud_storage: 33b05299e26d1391d724da8d62860e702380a1cd + local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index d53ef6437..8e02df288 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true diff --git a/pubspec.lock b/pubspec.lock index 413727990..f5e4f5f5b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -277,10 +277,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "93429694c9253d2871b3af80cf11b3cbb5c65660d402ed7bf69854ce4a089f82" + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 url: "https://pub.dev" source: hosted - version: "10.1.1" + version: "10.1.2" device_info_plus_platform_interface: dependency: transitive description: @@ -859,10 +859,10 @@ packages: dependency: transitive description: name: package_info_plus - sha256: "4de6c36df77ffbcef0a5aefe04669d33f2d18397fea228277b852a2d4e58e860" + sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918 url: "https://pub.dev" source: hosted - version: "8.0.1" + version: "8.0.2" package_info_plus_platform_interface: dependency: transitive description: @@ -1108,26 +1108,26 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "041be4d9d2dc6079cf342bc8b761b03787e3b71192d658220a56cac9c04a0294" + sha256: a7e8467e9181cef109f601e3f65765685786c1a738a83d7fbbde377589c0d974 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "671e7a931f55a08aa45be2a13fe7247f2a41237897df434b30d2012388191833" + sha256: "776786cff96324851b656777648f36ac772d88bc4c669acff97b7fce5de3c849" url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.5.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1" + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" shared_preferences_platform_interface: dependency: transitive description: @@ -1140,18 +1140,18 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "59dc807b94d29d52ddbb1b3c0d3b9d0a67fc535a64e62a5542c8db0513fcb6c2" + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2" + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" shelf: dependency: transitive description: