mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
Merge pull request #137 from lollipopkit/lollipopkit/issue136
Lollipopkit/issue136
This commit is contained in:
@@ -566,6 +566,12 @@ abstract class S {
|
||||
/// **'Getting token...'**
|
||||
String get gettingToken;
|
||||
|
||||
/// No description provided for @goBackQ.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Go back?'**
|
||||
String get goBackQ;
|
||||
|
||||
/// No description provided for @goto.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -254,6 +254,9 @@ class SDe extends S {
|
||||
@override
|
||||
String get gettingToken => 'Getting token...';
|
||||
|
||||
@override
|
||||
String get goBackQ => 'Zurückkommen?';
|
||||
|
||||
@override
|
||||
String get goto => 'Pfad öffnen';
|
||||
|
||||
|
||||
@@ -254,6 +254,9 @@ class SEn extends S {
|
||||
@override
|
||||
String get gettingToken => 'Getting token...';
|
||||
|
||||
@override
|
||||
String get goBackQ => 'Go back?';
|
||||
|
||||
@override
|
||||
String get goto => 'Go to';
|
||||
|
||||
|
||||
@@ -254,6 +254,9 @@ class SId extends S {
|
||||
@override
|
||||
String get gettingToken => 'Mendapatkan token ...';
|
||||
|
||||
@override
|
||||
String get goBackQ => 'Datang kembali?';
|
||||
|
||||
@override
|
||||
String get goto => 'Pergi ke';
|
||||
|
||||
|
||||
@@ -254,6 +254,9 @@ class SZh extends S {
|
||||
@override
|
||||
String get gettingToken => '正在获取Token...';
|
||||
|
||||
@override
|
||||
String get goBackQ => '返回?';
|
||||
|
||||
@override
|
||||
String get goto => '前往';
|
||||
|
||||
@@ -953,6 +956,9 @@ class SZhTw extends SZh {
|
||||
@override
|
||||
String get gettingToken => '正在獲取Token...';
|
||||
|
||||
@override
|
||||
String get goBackQ => '返回?';
|
||||
|
||||
@override
|
||||
String get goto => '前往';
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ SPEC CHECKSUMS:
|
||||
file_picker: 1d63c4949e05e386da864365f8c13e1e64787675
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
plain_notification_token: b36467dc91939a7b6754267c701bbaca14996ee1
|
||||
r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114
|
||||
share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
|
||||
|
||||
@@ -470,7 +470,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -478,7 +478,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -602,7 +602,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -610,7 +610,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -628,7 +628,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -636,7 +636,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -657,7 +657,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -670,7 +670,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
@@ -696,7 +696,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -709,7 +709,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -732,7 +732,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -745,7 +745,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
49
lib/app.dart
49
lib/app.dart
@@ -28,8 +28,7 @@ class MyApp extends StatelessWidget {
|
||||
// Issue #57
|
||||
// if not [ok] -> [AMOLED] mode, use [ThemeMode.dark]
|
||||
final themeMode = isAMOLED ? ThemeMode.values[tMode] : ThemeMode.dark;
|
||||
final localeStr = _setting.locale.fetch();
|
||||
final locale = localeStr?.toLocale;
|
||||
final locale = _setting.locale.fetch()?.toLocale;
|
||||
final darkTheme = ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.dark,
|
||||
@@ -47,39 +46,25 @@ class MyApp extends StatelessWidget {
|
||||
useMaterial3: true,
|
||||
colorSchemeSeed: primaryColor,
|
||||
),
|
||||
darkTheme: isAMOLED
|
||||
? darkTheme
|
||||
: darkTheme.copyWith(
|
||||
scaffoldBackgroundColor: Colors.black,
|
||||
dialogBackgroundColor: Colors.black,
|
||||
drawerTheme: const DrawerThemeData(
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
dialogTheme: const DialogTheme(
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
bottomSheetTheme: const BottomSheetThemeData(
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
listTileTheme: const ListTileThemeData(
|
||||
tileColor: Colors.black12,
|
||||
),
|
||||
cardTheme: const CardTheme(
|
||||
color: Colors.black12,
|
||||
),
|
||||
navigationBarTheme: const NavigationBarThemeData(
|
||||
backgroundColor: Colors.black,
|
||||
),
|
||||
popupMenuTheme: const PopupMenuThemeData(
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
darkTheme: isAMOLED ? darkTheme : _getAmoledTheme(darkTheme),
|
||||
home: fullScreen ? const FullScreenPage() : const HomePage(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ThemeData _getAmoledTheme(ThemeData darkTheme) => darkTheme.copyWith(
|
||||
scaffoldBackgroundColor: Colors.black,
|
||||
dialogBackgroundColor: Colors.black,
|
||||
drawerTheme: const DrawerThemeData(backgroundColor: Colors.black),
|
||||
appBarTheme: const AppBarTheme(backgroundColor: Colors.black),
|
||||
dialogTheme: const DialogTheme(backgroundColor: Colors.black),
|
||||
bottomSheetTheme:
|
||||
const BottomSheetThemeData(backgroundColor: Colors.black),
|
||||
listTileTheme: const ListTileThemeData(tileColor: Colors.black12),
|
||||
cardTheme: const CardTheme(color: Colors.black12),
|
||||
navigationBarTheme:
|
||||
const NavigationBarThemeData(backgroundColor: Colors.black),
|
||||
popupMenuTheme: const PopupMenuThemeData(color: Colors.black),
|
||||
);
|
||||
|
||||
@@ -80,7 +80,8 @@ List<OneTimeCpuStatus> parseCPU(String raw) {
|
||||
if (item == '') break;
|
||||
final id = item.split(' ').first;
|
||||
final matches = item.replaceFirst(id, '').trim().split(' ');
|
||||
cpus.add(OneTimeCpuStatus(
|
||||
cpus.add(
|
||||
OneTimeCpuStatus(
|
||||
id,
|
||||
int.parse(matches[0]),
|
||||
int.parse(matches[1]),
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 476;
|
||||
static const int build = 477;
|
||||
static const String engine = "3.10.6";
|
||||
static const String buildAt = "2023-08-17 18:45:06.973608";
|
||||
static const int modifications = 5;
|
||||
static const String buildAt = "2023-08-17 21:39:55.328086";
|
||||
static const int modifications = 14;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"fullScreenJitterHelp": "Einbrennen des Bildschirms verhindern",
|
||||
"getPushTokenFailed": "Push-Token kann nicht abgerufen werden",
|
||||
"gettingToken": "Getting token...",
|
||||
"goBackQ": "Zurückkommen?",
|
||||
"goto": "Pfad öffnen",
|
||||
"homeWidgetUrlConfig": "Home-Widget-Link konfigurieren",
|
||||
"host": "Host",
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"fullScreenJitterHelp": "To avoid screen burn-in",
|
||||
"getPushTokenFailed": "Can't fetch push token",
|
||||
"gettingToken": "Getting token...",
|
||||
"goBackQ": "Go back?",
|
||||
"goto": "Go to",
|
||||
"homeWidgetUrlConfig": "Config home widget url",
|
||||
"host": "Host",
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"fullScreenJitterHelp": "Untuk menghindari pembakaran layar",
|
||||
"getPushTokenFailed": "Tidak bisa mengambil token dorong",
|
||||
"gettingToken": "Mendapatkan token ...",
|
||||
"goBackQ": "Datang kembali?",
|
||||
"goto": "Pergi ke",
|
||||
"homeWidgetUrlConfig": "Konfigurasi URL Widget Rumah",
|
||||
"host": "Host",
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"fullScreenJitterHelp": "防止烧屏",
|
||||
"getPushTokenFailed": "未能获取到推送token",
|
||||
"gettingToken": "正在获取Token...",
|
||||
"goBackQ": "返回?",
|
||||
"goto": "前往",
|
||||
"homeWidgetUrlConfig": "桌面部件链接配置",
|
||||
"host": "主机",
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"fullScreenJitterHelp": "防止燒屏",
|
||||
"getPushTokenFailed": "未能獲取到推送token",
|
||||
"gettingToken": "正在獲取Token...",
|
||||
"goBackQ": "返回?",
|
||||
"goto": "前往",
|
||||
"homeWidgetUrlConfig": "桌面部件鏈接配置",
|
||||
"host": "主機",
|
||||
|
||||
@@ -18,11 +18,11 @@ import 'data/store/snippet.dart';
|
||||
|
||||
GetIt locator = GetIt.instance;
|
||||
|
||||
void setupLocatorForServices() {
|
||||
void _setupLocatorForServices() {
|
||||
locator.registerLazySingleton(() => AppService());
|
||||
}
|
||||
|
||||
void setupLocatorForProviders() {
|
||||
void _setupLocatorForProviders() {
|
||||
locator.registerSingleton(AppProvider());
|
||||
locator.registerSingleton(PkgProvider());
|
||||
locator.registerSingleton(DebugProvider());
|
||||
@@ -34,7 +34,7 @@ void setupLocatorForProviders() {
|
||||
locator.registerSingleton(SftpProvider());
|
||||
}
|
||||
|
||||
Future<void> setupLocatorForStores() async {
|
||||
Future<void> _setupLocatorForStores() async {
|
||||
final setting = SettingStore();
|
||||
await setting.init(boxName: 'setting');
|
||||
locator.registerSingleton(setting);
|
||||
@@ -57,7 +57,7 @@ Future<void> setupLocatorForStores() async {
|
||||
}
|
||||
|
||||
Future<void> setupLocator() async {
|
||||
await setupLocatorForStores();
|
||||
setupLocatorForProviders();
|
||||
setupLocatorForServices();
|
||||
await _setupLocatorForStores();
|
||||
_setupLocatorForProviders();
|
||||
_setupLocatorForServices();
|
||||
}
|
||||
|
||||
153
lib/main.dart
153
lib/main.dart
@@ -3,17 +3,20 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:macos_window_utils/window_manipulator.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:toolbox/data/model/app/net_view.dart';
|
||||
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
||||
import 'package:toolbox/view/widget/custom_appbar.dart';
|
||||
|
||||
import 'app.dart';
|
||||
import 'core/analysis.dart';
|
||||
import 'core/utils/platform.dart';
|
||||
import 'core/utils/ui.dart';
|
||||
import 'data/model/app/net_view.dart';
|
||||
import 'data/model/server/private_key_info.dart';
|
||||
import 'data/model/server/server_private_info.dart';
|
||||
import 'data/model/server/snippet.dart';
|
||||
import 'data/model/ssh/virtual_key.dart';
|
||||
import 'data/provider/app.dart';
|
||||
import 'data/provider/debug.dart';
|
||||
import 'data/provider/docker.dart';
|
||||
@@ -27,69 +30,10 @@ import 'data/store/setting.dart';
|
||||
import 'locator.dart';
|
||||
import 'view/widget/rebuild.dart';
|
||||
|
||||
late final DebugProvider _debug;
|
||||
|
||||
Future<void> initApp() async {
|
||||
await initHive();
|
||||
await setupLocator();
|
||||
|
||||
_debug = locator<DebugProvider>();
|
||||
locator<SnippetProvider>().loadData();
|
||||
locator<PrivateKeyProvider>().loadData();
|
||||
|
||||
final settings = locator<SettingStore>();
|
||||
await loadFontFile(settings.fontPath.fetch());
|
||||
|
||||
SharedPreferences.setPrefix('');
|
||||
|
||||
Logger.root.level = Level.ALL;
|
||||
Logger.root.onRecord.listen((record) {
|
||||
var str = '[${record.loggerName}][${record.level.name}]: ${record.message}';
|
||||
if (record.error != null) {
|
||||
str += '\n${record.error}';
|
||||
_debug.addMultiline(record.error.toString(), Colors.red);
|
||||
}
|
||||
if (record.stackTrace != null) {
|
||||
str += '\n${record.stackTrace}';
|
||||
_debug.addMultiline(record.stackTrace.toString(), Colors.white);
|
||||
}
|
||||
// ignore: avoid_print
|
||||
print(str);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> initHive() async {
|
||||
await Hive.initFlutter();
|
||||
// 以 typeId 为顺序
|
||||
Hive.registerAdapter(PrivateKeyInfoAdapter());
|
||||
Hive.registerAdapter(SnippetAdapter());
|
||||
Hive.registerAdapter(ServerPrivateInfoAdapter());
|
||||
Hive.registerAdapter(VirtKeyAdapter());
|
||||
Hive.registerAdapter(NetViewTypeAdapter());
|
||||
}
|
||||
|
||||
void runInZone(void Function() body) {
|
||||
final zoneSpec = ZoneSpecification(
|
||||
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
|
||||
parent.print(zone, line);
|
||||
// This is a hack to avoid
|
||||
// `setState() or markNeedsBuild() called during build`
|
||||
// error.
|
||||
Future.delayed(const Duration(milliseconds: 1), () {
|
||||
_debug.addText(line);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
runZonedGuarded(
|
||||
body,
|
||||
(obj, trace) => Analysis.recordException(trace),
|
||||
zoneSpecification: zoneSpec,
|
||||
);
|
||||
}
|
||||
DebugProvider? _debug;
|
||||
|
||||
Future<void> main() async {
|
||||
runInZone(() async {
|
||||
_runInZone(() async {
|
||||
await initApp();
|
||||
runApp(
|
||||
MultiProvider(
|
||||
@@ -111,3 +55,86 @@ Future<void> main() async {
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void _runInZone(void Function() body) {
|
||||
final zoneSpec = ZoneSpecification(
|
||||
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
|
||||
parent.print(zone, line);
|
||||
// This is a hack to avoid
|
||||
// `setState() or markNeedsBuild() called during build`
|
||||
// error.
|
||||
Future.delayed(const Duration(milliseconds: 1), () {
|
||||
_debug?.addText(line);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
runZonedGuarded(
|
||||
body,
|
||||
(obj, trace) => Analysis.recordException(trace),
|
||||
zoneSpecification: zoneSpec,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> initApp() async {
|
||||
await _initMacOSWindow();
|
||||
|
||||
// Base of all data.
|
||||
await _initHive();
|
||||
await setupLocator();
|
||||
|
||||
// Setup [DebugProvider] first to catch all logs.
|
||||
_debug = locator<DebugProvider>();
|
||||
_setupLogger();
|
||||
_setupProviders();
|
||||
|
||||
// Load font
|
||||
final settings = locator<SettingStore>();
|
||||
loadFontFile(settings.fontPath.fetch());
|
||||
|
||||
// SharedPreferences is only used on Android for saving home widgets settings.
|
||||
if (!isAndroid) return;
|
||||
SharedPreferences.setPrefix('');
|
||||
}
|
||||
|
||||
void _setupProviders() {
|
||||
locator<SnippetProvider>().loadData();
|
||||
locator<PrivateKeyProvider>().loadData();
|
||||
}
|
||||
|
||||
Future<void> _initHive() async {
|
||||
await Hive.initFlutter();
|
||||
// 以 typeId 为顺序
|
||||
Hive.registerAdapter(PrivateKeyInfoAdapter());
|
||||
Hive.registerAdapter(SnippetAdapter());
|
||||
Hive.registerAdapter(ServerPrivateInfoAdapter());
|
||||
Hive.registerAdapter(VirtKeyAdapter());
|
||||
Hive.registerAdapter(NetViewTypeAdapter());
|
||||
}
|
||||
|
||||
void _setupLogger() {
|
||||
Logger.root.level = Level.ALL;
|
||||
Logger.root.onRecord.listen((record) {
|
||||
var str = '[${record.loggerName}][${record.level.name}]: ${record.message}';
|
||||
if (record.error != null) {
|
||||
str += '\n${record.error}';
|
||||
_debug?.addMultiline(record.error.toString(), Colors.red);
|
||||
}
|
||||
if (record.stackTrace != null) {
|
||||
str += '\n${record.stackTrace}';
|
||||
_debug?.addMultiline(record.stackTrace.toString(), Colors.white);
|
||||
}
|
||||
// ignore: avoid_print
|
||||
print(str);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _initMacOSWindow() async {
|
||||
if (!isMacOS) return;
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await WindowManipulator.initialize();
|
||||
WindowManipulator.makeTitlebarTransparent();
|
||||
WindowManipulator.enableFullSizeContentView();
|
||||
WindowManipulator.hideTitle();
|
||||
await CustomAppBar.updateTitlebarHeight();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import '../../data/store/private_key.dart';
|
||||
import '../../data/store/server.dart';
|
||||
import '../../data/store/snippet.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/custom_appbar.dart';
|
||||
|
||||
const backupFormatVersion = 1;
|
||||
|
||||
@@ -34,7 +35,7 @@ class BackupPage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context)!;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
title: Text(s.backupAndRestore, style: textSize18),
|
||||
),
|
||||
body: _buildBody(context, s),
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:toolbox/data/res/ui.dart';
|
||||
import 'package:toolbox/view/widget/value_notifier.dart';
|
||||
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../widget/custom_appbar.dart';
|
||||
import '../widget/input_field.dart';
|
||||
import '../widget/popup_menu.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
@@ -52,7 +53,7 @@ class _ConvertPageState extends State<ConvertPage>
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
title: Text(_s.convert),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
|
||||
@@ -3,6 +3,8 @@ import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/extension/navigator.dart';
|
||||
import 'package:toolbox/data/provider/debug.dart';
|
||||
|
||||
import '../widget/custom_appbar.dart';
|
||||
|
||||
class DebugPage extends StatefulWidget {
|
||||
const DebugPage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -14,7 +16,7 @@ class _DebugPageState extends State<DebugPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
leading: IconButton(
|
||||
onPressed: () => context.pop(),
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
|
||||
@@ -18,6 +18,7 @@ import '../../data/res/ui.dart';
|
||||
import '../../data/res/url.dart';
|
||||
import '../../data/store/docker.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/custom_appbar.dart';
|
||||
import '../widget/popup_menu.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
import '../widget/two_line_text.dart';
|
||||
@@ -64,7 +65,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<DockerProvider>(builder: (_, ___, __) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: 'Docker', down: widget.spi.name),
|
||||
actions: [
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:toolbox/data/res/highlight.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
|
||||
import '../widget/custom_appbar.dart';
|
||||
import '../widget/two_line_text.dart';
|
||||
|
||||
class EditorPage extends StatefulWidget {
|
||||
@@ -68,55 +69,9 @@ class _EditorPageState extends State<EditorPage> with AfterLayoutMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: () {
|
||||
if (_codeTheme != null) {
|
||||
return _codeTheme!['root']!.backgroundColor;
|
||||
}
|
||||
return null;
|
||||
}(),
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: getFileName(widget.path) ?? '', down: _s.editor),
|
||||
actions: [
|
||||
PopupMenuButton<String>(
|
||||
icon: const Icon(Icons.language),
|
||||
onSelected: (value) {
|
||||
_controller.language = suffix2HighlightMap[value];
|
||||
_langCode = value;
|
||||
},
|
||||
initialValue: _langCode,
|
||||
itemBuilder: (BuildContext context) {
|
||||
return suffix2HighlightMap.keys.map((e) {
|
||||
return PopupMenuItem(
|
||||
value: e,
|
||||
child: Text(e),
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
body: Visibility(
|
||||
visible: (_codeTheme != null),
|
||||
replacement: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: CodeTheme(
|
||||
data: CodeThemeData(
|
||||
styles: _codeTheme ??
|
||||
(isDarkMode(context) ? monokaiTheme : a11yLightTheme)),
|
||||
child: CodeField(
|
||||
focusNode: _focusNode,
|
||||
controller: _controller,
|
||||
lineNumberStyle: const LineNumberStyle(
|
||||
width: 47,
|
||||
margin: 7,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
backgroundColor: _codeTheme?['root']?.backgroundColor,
|
||||
appBar: _buildAppBar(),
|
||||
body: _buildBody(),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Icons.done),
|
||||
onPressed: () {
|
||||
@@ -126,6 +81,54 @@ class _EditorPageState extends State<EditorPage> with AfterLayoutMixin {
|
||||
);
|
||||
}
|
||||
|
||||
PreferredSizeWidget _buildAppBar() {
|
||||
return CustomAppBar(
|
||||
title: TwoLineText(up: getFileName(widget.path) ?? '', down: _s.editor),
|
||||
actions: [
|
||||
PopupMenuButton<String>(
|
||||
icon: const Icon(Icons.language),
|
||||
onSelected: (value) {
|
||||
_controller.language = suffix2HighlightMap[value];
|
||||
_langCode = value;
|
||||
},
|
||||
initialValue: _langCode,
|
||||
itemBuilder: (BuildContext context) {
|
||||
return suffix2HighlightMap.keys.map((e) {
|
||||
return PopupMenuItem(
|
||||
value: e,
|
||||
child: Text(e),
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return Visibility(
|
||||
visible: _codeTheme != null,
|
||||
replacement: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: CodeTheme(
|
||||
data: CodeThemeData(
|
||||
styles: _codeTheme ??
|
||||
(isDarkMode(context) ? monokaiTheme : a11yLightTheme)),
|
||||
child: CodeField(
|
||||
focusNode: _focusNode,
|
||||
controller: _controller,
|
||||
lineNumberStyle: const LineNumberStyle(
|
||||
width: 47,
|
||||
margin: 7,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<void> afterFirstLayout(BuildContext context) async {
|
||||
if (widget.path != null) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import '../../data/res/ui.dart';
|
||||
import '../../data/res/url.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/custom_appbar.dart';
|
||||
import '../widget/url_text.dart';
|
||||
import 'backup.dart';
|
||||
import 'convert.dart';
|
||||
@@ -109,31 +110,10 @@ class _HomePageState extends State<HomePage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
final actions = <Widget>[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.developer_mode, size: 23),
|
||||
tooltip: _s.debug,
|
||||
onPressed: () => AppRoute(
|
||||
const DebugPage(),
|
||||
'Debug Page',
|
||||
).go(context),
|
||||
),
|
||||
];
|
||||
if (isDesktop && _selectIndex.value == AppTab.server.index) {
|
||||
actions.add(
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh, size: 23),
|
||||
tooltip: 'Refresh',
|
||||
onPressed: () => _serverProvider.refreshData(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
drawer: _buildDrawer(),
|
||||
appBar: AppBar(
|
||||
title: const Text(BuildData.name),
|
||||
actions: actions,
|
||||
),
|
||||
appBar: _buildAppBar(),
|
||||
body: PageView.builder(
|
||||
controller: _pageController,
|
||||
itemCount: AppTab.values.length,
|
||||
@@ -151,9 +131,44 @@ class _HomePageState extends State<HomePage>
|
||||
);
|
||||
}
|
||||
|
||||
PreferredSizeWidget _buildAppBar() {
|
||||
final actions = <Widget>[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.developer_mode, size: 23),
|
||||
tooltip: _s.debug,
|
||||
onPressed: () => AppRoute(
|
||||
const DebugPage(),
|
||||
'Debug Page',
|
||||
).go(context),
|
||||
),
|
||||
];
|
||||
if (isDesktop && _selectIndex.value == AppTab.server.index) {
|
||||
actions.add(
|
||||
ValueBuilder(
|
||||
listenable: _selectIndex,
|
||||
build: () {
|
||||
if (_selectIndex.value != AppTab.server.index) {
|
||||
return const SizedBox();
|
||||
}
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.refresh, size: 23),
|
||||
tooltip: 'Refresh',
|
||||
onPressed: () => _serverProvider.refreshData(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
return CustomAppBar(
|
||||
title: const Text(BuildData.name),
|
||||
actions: actions,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBottomBar() {
|
||||
return NavigationBar(
|
||||
selectedIndex: _selectIndex.value,
|
||||
height: kBottomNavigationBarHeight * 1.2,
|
||||
animationDuration: const Duration(milliseconds: 250),
|
||||
onDestinationSelected: (int index) {
|
||||
if (_selectIndex.value == index) return;
|
||||
|
||||
@@ -12,6 +12,7 @@ import '../../data/provider/pkg.dart';
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../data/res/ui.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/custom_appbar.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
import '../widget/two_line_text.dart';
|
||||
|
||||
@@ -72,7 +73,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<PkgProvider>(builder: (_, pkg, __) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: _s.pkg, down: widget.spi.name),
|
||||
),
|
||||
|
||||
@@ -17,6 +17,7 @@ import '../../../data/model/server/private_key_info.dart';
|
||||
import '../../../data/provider/private_key.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
|
||||
const _format = 'text/plain';
|
||||
|
||||
@@ -89,7 +90,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
];
|
||||
return AppBar(
|
||||
return CustomAppBar(
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: actions,
|
||||
);
|
||||
|
||||
@@ -14,6 +14,7 @@ import '../../../core/utils/platform.dart';
|
||||
import '../../../data/model/server/private_key_info.dart';
|
||||
import '../../../data/provider/private_key.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
import 'edit.dart';
|
||||
import '../../../view/widget/round_rect_card.dart';
|
||||
|
||||
@@ -37,7 +38,7 @@ class _PrivateKeyListState extends State<PrivateKeysListPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
title: Text(_s.privateKey, style: textSize18),
|
||||
),
|
||||
body: _buildBody(),
|
||||
|
||||
@@ -15,6 +15,7 @@ import 'package:toolbox/view/widget/two_line_text.dart';
|
||||
|
||||
import '../../data/provider/server.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/custom_appbar.dart';
|
||||
|
||||
class ProcessPage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
@@ -124,7 +125,7 @@ class _ProcessPageState extends State<ProcessPage> {
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
centerTitle: true,
|
||||
title: TwoLineText(up: widget.spi.name, down: _s.process),
|
||||
actions: actions,
|
||||
|
||||
@@ -14,6 +14,7 @@ import '../../../data/res/default.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../../data/store/setting.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
import '../../widget/round_rect_card.dart';
|
||||
|
||||
class ServerDetailPage extends StatefulWidget {
|
||||
@@ -75,7 +76,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
|
||||
Widget _buildMainPage(Server si) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
title: Text(si.spi.name, style: textSize18),
|
||||
),
|
||||
body: ReorderableListView.builder(
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../../../data/provider/server.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../../data/store/private_key.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
import '../../widget/tag/editor.dart';
|
||||
import '../private_key/edit.dart';
|
||||
|
||||
@@ -116,7 +117,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
icon: const Icon(Icons.delete),
|
||||
);
|
||||
final actions = widget.spi != null ? [delBtn] : null;
|
||||
return AppBar(
|
||||
return CustomAppBar(
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: actions,
|
||||
);
|
||||
|
||||
@@ -29,6 +29,7 @@ import '../../data/res/ui.dart';
|
||||
import '../../data/store/server.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
import '../../locator.dart';
|
||||
import '../widget/custom_appbar.dart';
|
||||
import '../widget/future_widget.dart';
|
||||
import '../widget/round_rect_card.dart';
|
||||
|
||||
@@ -100,7 +101,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
title: Text(_s.setting),
|
||||
),
|
||||
body: ListView(
|
||||
|
||||
@@ -9,6 +9,7 @@ import '../../../data/model/server/snippet.dart';
|
||||
import '../../../data/provider/snippet.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
import '../../widget/tag/editor.dart';
|
||||
|
||||
class SnippetEditPage extends StatefulWidget {
|
||||
@@ -54,7 +55,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
title: Text(_s.edit, style: textSize18),
|
||||
actions: _buildAppBarActions(),
|
||||
),
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/extension/navigator.dart';
|
||||
import 'package:toolbox/core/extension/uint8list.dart';
|
||||
import 'package:xterm/xterm.dart';
|
||||
|
||||
import '../../../core/route.dart';
|
||||
@@ -341,19 +340,7 @@ class _SSHPageState extends State<SSHPage> {
|
||||
),
|
||||
);
|
||||
|
||||
_discontinuityTimer = Timer.periodic(
|
||||
const Duration(seconds: 5),
|
||||
(_) async {
|
||||
var throwTimeout = true;
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
if (throwTimeout) {
|
||||
_catchTimeout();
|
||||
}
|
||||
});
|
||||
await _client?.run('echo 1').string;
|
||||
throwTimeout = false;
|
||||
},
|
||||
);
|
||||
_setupDiscontinuityTimer();
|
||||
|
||||
if (_session == null) {
|
||||
showSnackBar(context, const Text('Null session'));
|
||||
@@ -394,14 +381,30 @@ class _SSHPageState extends State<SSHPage> {
|
||||
.listen(_terminal.write);
|
||||
}
|
||||
|
||||
void _setupDiscontinuityTimer() {
|
||||
_discontinuityTimer = Timer.periodic(
|
||||
const Duration(seconds: 5),
|
||||
(_) async {
|
||||
var throwTimeout = true;
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
if (throwTimeout) {
|
||||
_catchTimeout();
|
||||
}
|
||||
});
|
||||
await _client?.ping();
|
||||
throwTimeout = false;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _catchTimeout() {
|
||||
_discontinuityTimer?.cancel();
|
||||
if (!mounted) return;
|
||||
_write('\n\nConnection lost\r\n');
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
title: Text(_s.disconnected),
|
||||
child: Text('Go back?'),
|
||||
title: Text(_s.attention),
|
||||
child: Text('${_s.disconnected}\n${_s.goBackQ}'),
|
||||
barrierDismiss: false,
|
||||
actions: [
|
||||
TextButton(
|
||||
|
||||
@@ -9,6 +9,8 @@ import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||
|
||||
import '../../widget/custom_appbar.dart';
|
||||
|
||||
class SSHVirtKeySettingPage extends StatefulWidget {
|
||||
const SSHVirtKeySettingPage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -29,7 +31,7 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
title: Text(_s.editVirtKeys),
|
||||
),
|
||||
body: _buildBody(),
|
||||
|
||||
@@ -22,6 +22,7 @@ import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/app/path_with_prefix.dart';
|
||||
import '../../../data/res/path.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
import '../../widget/fade_in.dart';
|
||||
import 'sftp_mission.dart';
|
||||
|
||||
@@ -64,7 +65,7 @@ class _LocalStoragePageState extends State<LocalStoragePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
leading: IconButton(
|
||||
icon: const BackButtonIcon(),
|
||||
onPressed: () {
|
||||
|
||||
@@ -26,6 +26,7 @@ import '../../../data/provider/sftp.dart';
|
||||
import '../../../data/res/path.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
import '../../widget/fade_in.dart';
|
||||
import '../../widget/input_field.dart';
|
||||
import '../../widget/two_line_text.dart';
|
||||
@@ -74,7 +75,7 @@ class _SftpPageState extends State<SftpPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
appBar: CustomAppBar(
|
||||
leading: IconButton(
|
||||
icon: const BackButtonIcon(),
|
||||
onPressed: () {
|
||||
|
||||
@@ -13,6 +13,7 @@ import '../../../core/utils/ui.dart';
|
||||
import '../../../data/model/sftp/req.dart';
|
||||
import '../../../data/provider/sftp.dart';
|
||||
import '../../../data/res/ui.dart';
|
||||
import '../../widget/custom_appbar.dart';
|
||||
import '../../widget/round_rect_card.dart';
|
||||
|
||||
class SftpMissionPage extends StatefulWidget {
|
||||
@@ -34,11 +35,8 @@ class _SftpMissionPageState extends State<SftpMissionPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
_s.mission,
|
||||
style: textSize18,
|
||||
),
|
||||
appBar: CustomAppBar(
|
||||
title: Text(_s.mission, style: textSize18),
|
||||
),
|
||||
body: _buildBody(),
|
||||
);
|
||||
|
||||
22
lib/view/widget/custom_appbar.dart
Normal file
22
lib/view/widget/custom_appbar.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:macos_window_utils/window_manipulator.dart';
|
||||
|
||||
double? _titlebarHeight;
|
||||
|
||||
class CustomAppBar extends AppBar implements PreferredSizeWidget {
|
||||
CustomAppBar({
|
||||
super.key,
|
||||
super.title,
|
||||
super.actions,
|
||||
super.centerTitle,
|
||||
super.leading,
|
||||
super.backgroundColor,
|
||||
}) : super(toolbarHeight: (_titlebarHeight ?? 0) + kToolbarHeight);
|
||||
|
||||
static Future<void> updateTitlebarHeight() async {
|
||||
final newTitlebarHeight = await WindowManipulator.getTitlebarHeight();
|
||||
if (_titlebarHeight != newTitlebarHeight) {
|
||||
_titlebarHeight = newTitlebarHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,14 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import macos_window_utils
|
||||
import path_provider_foundation
|
||||
import share_plus
|
||||
import shared_preferences_foundation
|
||||
import url_launcher_macos
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
MacOSWindowUtilsPlugin.register(with: registry.registrar(forPlugin: "MacOSWindowUtilsPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
platform :osx, '10.14'
|
||||
platform :osx, '10.15'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
PODS:
|
||||
- FlutterMacOS (1.0.0)
|
||||
- macos_window_utils (1.0.0):
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -13,6 +15,7 @@ PODS:
|
||||
|
||||
DEPENDENCIES:
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- macos_window_utils (from `Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
@@ -21,6 +24,8 @@ DEPENDENCIES:
|
||||
EXTERNAL SOURCES:
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
macos_window_utils:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
share_plus:
|
||||
@@ -32,11 +37,12 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
macos_window_utils: 933f91f64805e2eb91a5bd057cf97cd097276663
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||
|
||||
PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
|
||||
PODFILE CHECKSUM: 9ebaf0ce3d369aaa26a9ea0e159195ed94724cf3
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
|
||||
@@ -195,7 +195,6 @@
|
||||
15AF97DF993E8968098D6EBE /* Pods-RunnerTests.release.xcconfig */,
|
||||
7CFA7DE7FABA75685DFB6948 /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -475,9 +474,9 @@
|
||||
baseConfigurationReference = C1C758C41C4E208965A68933 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -490,9 +489,9 @@
|
||||
baseConfigurationReference = 15AF97DF993E8968098D6EBE /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -505,9 +504,9 @@
|
||||
baseConfigurationReference = 7CFA7DE7FABA75685DFB6948 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 476;
|
||||
CURRENT_PROJECT_VERSION = 477;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.476;
|
||||
MARKETING_VERSION = 1.0.477;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -575,6 +574,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
@@ -701,6 +701,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -721,6 +722,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
|
||||
@@ -510,6 +510,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
macos_window_utils:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: macos_window_utils
|
||||
sha256: "43a90473f8786f00f07203e6819dab67e032f8896dafa4a6f85fbc71fba32c0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -45,6 +45,7 @@ dependencies:
|
||||
code_text_field: ^1.1.0
|
||||
shared_preferences: ^2.1.1
|
||||
crypto: ^3.0.3
|
||||
macos_window_utils: ^1.2.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_native_splash: ^2.1.6
|
||||
|
||||
Reference in New Issue
Block a user