mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
#15 support: select font
This commit is contained in:
@@ -189,6 +189,12 @@ abstract class S {
|
|||||||
/// **'Choose destination'**
|
/// **'Choose destination'**
|
||||||
String get chooseDestination;
|
String get chooseDestination;
|
||||||
|
|
||||||
|
/// No description provided for @chooseFontFile.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Choose a font file'**
|
||||||
|
String get chooseFontFile;
|
||||||
|
|
||||||
/// No description provided for @choosePrivateKey.
|
/// No description provided for @choosePrivateKey.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -1106,6 +1112,12 @@ abstract class S {
|
|||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Will take effect immediately'**
|
/// **'Will take effect immediately'**
|
||||||
String get willTakEeffectImmediately;
|
String get willTakEeffectImmediately;
|
||||||
|
|
||||||
|
/// No description provided for @notSelected.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Not selected'**
|
||||||
|
String get notSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SDelegate extends LocalizationsDelegate<S> {
|
class _SDelegate extends LocalizationsDelegate<S> {
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ class SEn extends S {
|
|||||||
@override
|
@override
|
||||||
String get chooseDestination => 'Choose destination';
|
String get chooseDestination => 'Choose destination';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chooseFontFile => 'Choose a font file';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get choosePrivateKey => 'Choose private key';
|
String get choosePrivateKey => 'Choose private key';
|
||||||
|
|
||||||
@@ -554,4 +557,7 @@ class SEn extends S {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get willTakEeffectImmediately => 'Will take effect immediately';
|
String get willTakEeffectImmediately => 'Will take effect immediately';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get notSelected => 'Not selected';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ class SZh extends S {
|
|||||||
@override
|
@override
|
||||||
String get chooseDestination => '选择目标';
|
String get chooseDestination => '选择目标';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get chooseFontFile => '选择字体文件';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get choosePrivateKey => '选择私钥';
|
String get choosePrivateKey => '选择私钥';
|
||||||
|
|
||||||
@@ -554,4 +557,7 @@ class SZh extends S {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get willTakEeffectImmediately => '更改将会立即生效';
|
String get willTakEeffectImmediately => '更改将会立即生效';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get notSelected => '未选择';
|
||||||
}
|
}
|
||||||
|
|||||||
31
lib/app.dart
31
lib/app.dart
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
|
|
||||||
import '/core/extension/colorx.dart';
|
import '/core/extension/colorx.dart';
|
||||||
import 'core/utils/ui.dart';
|
import 'core/utils/ui.dart';
|
||||||
@@ -17,6 +18,7 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
setTransparentNavigationBar(context);
|
setTransparentNavigationBar(context);
|
||||||
|
final fontName = getFileName(_setting.fontPath.fetch());
|
||||||
return ValueListenableBuilder<int>(
|
return ValueListenableBuilder<int>(
|
||||||
valueListenable: _setting.primaryColor.listenable(),
|
valueListenable: _setting.primaryColor.listenable(),
|
||||||
builder: (_, colorValue, __) {
|
builder: (_, colorValue, __) {
|
||||||
@@ -48,14 +50,10 @@ class MyApp extends StatelessWidget {
|
|||||||
builder: (_, tMode, __) {
|
builder: (_, tMode, __) {
|
||||||
final ok = tMode >= 0 && tMode <= ThemeMode.values.length - 1;
|
final ok = tMode >= 0 && tMode <= ThemeMode.values.length - 1;
|
||||||
final themeMode = ok ? ThemeMode.values[tMode] : ThemeMode.system;
|
final themeMode = ok ? ThemeMode.values[tMode] : ThemeMode.system;
|
||||||
return MaterialApp(
|
|
||||||
debugShowCheckedModeBanner: false,
|
final theme = ThemeData(
|
||||||
localizationsDelegates: S.localizationsDelegates,
|
|
||||||
supportedLocales: S.supportedLocales,
|
|
||||||
title: BuildData.name,
|
|
||||||
themeMode: themeMode,
|
|
||||||
theme: ThemeData(
|
|
||||||
useMaterial3: false,
|
useMaterial3: false,
|
||||||
|
fontFamily: fontName,
|
||||||
primaryColor: primaryColor,
|
primaryColor: primaryColor,
|
||||||
primarySwatch: primaryColor.materialColor,
|
primarySwatch: primaryColor.materialColor,
|
||||||
appBarTheme: appBarTheme,
|
appBarTheme: appBarTheme,
|
||||||
@@ -65,15 +63,16 @@ class MyApp extends StatelessWidget {
|
|||||||
switchTheme: switchTheme,
|
switchTheme: switchTheme,
|
||||||
inputDecorationTheme: inputDecorationTheme,
|
inputDecorationTheme: inputDecorationTheme,
|
||||||
radioTheme: radioTheme,
|
radioTheme: radioTheme,
|
||||||
),
|
);
|
||||||
darkTheme: ThemeData.dark().copyWith(
|
|
||||||
useMaterial3: false,
|
return MaterialApp(
|
||||||
floatingActionButtonTheme: fabTheme,
|
debugShowCheckedModeBanner: false,
|
||||||
iconTheme: iconTheme,
|
localizationsDelegates: S.localizationsDelegates,
|
||||||
primaryIconTheme: iconTheme,
|
supportedLocales: S.supportedLocales,
|
||||||
switchTheme: switchTheme,
|
title: BuildData.name,
|
||||||
inputDecorationTheme: inputDecorationTheme,
|
themeMode: themeMode,
|
||||||
radioTheme: radioTheme,
|
theme: theme,
|
||||||
|
darkTheme: theme.copyWith(
|
||||||
colorScheme: ColorScheme.fromSwatch(
|
colorScheme: ColorScheme.fromSwatch(
|
||||||
primarySwatch: primaryColor.materialColor,
|
primarySwatch: primaryColor.materialColor,
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:plain_notification_token/plain_notification_token.dart';
|
import 'package:plain_notification_token/plain_notification_token.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:toolbox/core/extension/uint8list.dart';
|
|
||||||
|
|
||||||
import 'platform.dart';
|
import 'platform.dart';
|
||||||
|
|
||||||
@@ -49,8 +48,9 @@ Future<String?> getToken() async {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadFontFile(String localPath, String name) async {
|
String? getFileName(String? path) {
|
||||||
var fontLoader = FontLoader(name);
|
if (path == null) {
|
||||||
fontLoader.addFont(File(localPath).readAsBytes().byteData);
|
return null;
|
||||||
await fontLoader.load();
|
}
|
||||||
|
return path.split('/').last;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:toolbox/core/extension/stringx.dart';
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
import '../../view/widget/card_dialog.dart';
|
import '../../view/widget/card_dialog.dart';
|
||||||
import '../persistant_store.dart';
|
import '../persistant_store.dart';
|
||||||
import 'platform.dart';
|
import 'platform.dart';
|
||||||
|
import '../extension/stringx.dart';
|
||||||
|
import '../extension/uint8list.dart';
|
||||||
|
|
||||||
bool isDarkMode(BuildContext context) =>
|
bool isDarkMode(BuildContext context) =>
|
||||||
Theme.of(context).brightness == Brightness.dark;
|
Theme.of(context).brightness == Brightness.dark;
|
||||||
@@ -100,3 +104,11 @@ String tabTitleName(BuildContext context, int i) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> loadFontFile(String? localPath) async {
|
||||||
|
if (localPath == null) return;
|
||||||
|
final name = getFileName(localPath)!;
|
||||||
|
var fontLoader = FontLoader(name);
|
||||||
|
fontLoader.addFont(File(localPath).readAsBytes().byteData);
|
||||||
|
await fontLoader.load();
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
class BuildData {
|
class BuildData {
|
||||||
static const String name = "ServerBox";
|
static const String name = "ServerBox";
|
||||||
static const int build = 237;
|
static const int build = 237;
|
||||||
static const String engine = "Flutter 3.7.7 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 2ad6cd72c0 (10 days ago) • 2023-03-08 09:41:59 -0800\nEngine • revision 1837b5be5f\nTools • Dart 2.19.4 • DevTools 2.20.1\n";
|
static const String engine =
|
||||||
|
"Flutter 3.7.7 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 2ad6cd72c0 (10 days ago) • 2023-03-08 09:41:59 -0800\nEngine • revision 1837b5be5f\nTools • Dart 2.19.4 • DevTools 2.20.1\n";
|
||||||
static const String buildAt = "2023-03-18 17:38:10.546482";
|
static const String buildAt = "2023-03-18 17:38:10.546482";
|
||||||
static const int modifications = 4;
|
static const int modifications = 4;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,7 @@ class SettingStore extends PersistentStore {
|
|||||||
|
|
||||||
/// Night mode: 0 -> auto, 1 -> light, 2 -> dark
|
/// Night mode: 0 -> auto, 1 -> light, 2 -> dark
|
||||||
StoreProperty<int> get themeMode => property('themeMode', defaultValue: 0);
|
StoreProperty<int> get themeMode => property('themeMode', defaultValue: 0);
|
||||||
|
|
||||||
|
/// Font file path
|
||||||
|
StoreProperty<String> get fontPath => property('fontPath');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"choose": "Choose",
|
"choose": "Choose",
|
||||||
"chooseDestination": "Choose destination",
|
"chooseDestination": "Choose destination",
|
||||||
|
"chooseFontFile": "Choose a font file",
|
||||||
"choosePrivateKey": "Choose private key",
|
"choosePrivateKey": "Choose private key",
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"clickSee": "Click here",
|
"clickSee": "Click here",
|
||||||
@@ -167,5 +168,6 @@
|
|||||||
"versionUnknownUpdate": "Current: v1.0.{build}",
|
"versionUnknownUpdate": "Current: v1.0.{build}",
|
||||||
"versionUpdated": "Current: v1.0.{build}, is up to date",
|
"versionUpdated": "Current: v1.0.{build}, is up to date",
|
||||||
"waitConnection": "Please wait for the connection to be established.",
|
"waitConnection": "Please wait for the connection to be established.",
|
||||||
"willTakEeffectImmediately": "Will take effect immediately"
|
"willTakEeffectImmediately": "Will take effect immediately",
|
||||||
|
"notSelected": "Not selected"
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
"cancel": "取消",
|
"cancel": "取消",
|
||||||
"choose": "选择",
|
"choose": "选择",
|
||||||
"chooseDestination": "选择目标",
|
"chooseDestination": "选择目标",
|
||||||
|
"chooseFontFile": "选择字体文件",
|
||||||
"choosePrivateKey": "选择私钥",
|
"choosePrivateKey": "选择私钥",
|
||||||
"clear": "清除",
|
"clear": "清除",
|
||||||
"clickSee": "点击查看",
|
"clickSee": "点击查看",
|
||||||
@@ -167,5 +168,6 @@
|
|||||||
"versionUnknownUpdate": "当前:v1.0.{build}",
|
"versionUnknownUpdate": "当前:v1.0.{build}",
|
||||||
"versionUpdated": "当前:v1.0.{build}, 已是最新版本",
|
"versionUpdated": "当前:v1.0.{build}, 已是最新版本",
|
||||||
"waitConnection": "请等待连接建立",
|
"waitConnection": "请等待连接建立",
|
||||||
"willTakEeffectImmediately": "更改将会立即生效"
|
"willTakEeffectImmediately": "更改将会立即生效",
|
||||||
|
"notSelected": "未选择"
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:toolbox/core/utils/ui.dart';
|
||||||
|
import 'package:toolbox/data/store/setting.dart';
|
||||||
|
|
||||||
import 'app.dart';
|
import 'app.dart';
|
||||||
import 'core/analysis.dart';
|
import 'core/analysis.dart';
|
||||||
@@ -31,6 +33,9 @@ Future<void> initApp() async {
|
|||||||
locator<SnippetProvider>().loadData();
|
locator<SnippetProvider>().loadData();
|
||||||
locator<PrivateKeyProvider>().loadData();
|
locator<PrivateKeyProvider>().loadData();
|
||||||
|
|
||||||
|
final settings = locator<SettingStore>();
|
||||||
|
await loadFontFile(settings.fontPath.fetch());
|
||||||
|
|
||||||
///设置Logger
|
///设置Logger
|
||||||
Logger.root.level = Level.ALL; // defaults to Level.INFO
|
Logger.root.level = Level.ALL; // defaults to Level.INFO
|
||||||
Logger.root.onRecord.listen((record) {
|
Logger.root.onRecord.listen((record) {
|
||||||
|
|||||||
@@ -47,10 +47,7 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final client = locator<ServerProvider>()
|
final client = locator<ServerProvider>().getServer(widget.spi.id).client;
|
||||||
.servers
|
|
||||||
.firstWhere((element) => element.spi == widget.spi)
|
|
||||||
.client;
|
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
showSnackBar(context, Text(_s.noClient));
|
showSnackBar(context, Text(_s.noClient));
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ class _PkgManagePageState extends State<PkgManagePage>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final si = locator<ServerProvider>()
|
final si = locator<ServerProvider>().getServer(widget.spi.id);
|
||||||
.servers
|
|
||||||
.firstWhere((e) => e.spi == widget.spi);
|
|
||||||
if (si.client == null) {
|
if (si.client == null) {
|
||||||
showSnackBar(context, Text(_s.waitConnection));
|
showSnackBar(context, Text(_s.waitConnection));
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@@ -179,8 +177,9 @@ class _PkgManagePageState extends State<PkgManagePage>
|
|||||||
}
|
}
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(13),
|
padding: const EdgeInsets.all(13),
|
||||||
children:
|
children: [
|
||||||
[_buildUpdatePanel(apt)].map((e) => RoundRectCard(e)).toList(),
|
_buildUpdatePanel(apt),
|
||||||
|
].map((e) => RoundRectCard(e)).toList(),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -41,9 +41,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
return Consumer<ServerProvider>(builder: (_, provider, __) {
|
||||||
return _buildMainPage(
|
return _buildMainPage(
|
||||||
provider.servers.firstWhere(
|
provider.getServer(widget.id),
|
||||||
(e) => e.spi.id == widget.id,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_buildAppColorPreview(),
|
_buildAppColorPreview(),
|
||||||
_buildLaunchPage(),
|
_buildLaunchPage(),
|
||||||
_buildCheckUpdate(),
|
_buildCheckUpdate(),
|
||||||
|
_buildFont(),
|
||||||
];
|
];
|
||||||
if (isIOS) {
|
if (isIOS) {
|
||||||
children.add(_buildPushToken());
|
children.add(_buildPushToken());
|
||||||
@@ -445,4 +446,20 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildFont() {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(_s.chooseFontFile),
|
||||||
|
subtitle: Text(getFileName(_setting.fontPath.fetch()) ?? _s.notSelected),
|
||||||
|
trailing: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final path = await pickOneFile();
|
||||||
|
if (path != null) {
|
||||||
|
_setting.fontPath.put(path);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(_s.pickFile)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final serverProvider = locator<ServerProvider>();
|
final serverProvider = locator<ServerProvider>();
|
||||||
_si = serverProvider.servers.firstWhere((s) => s.spi == widget.spi);
|
_si = serverProvider.getServer(widget.spi.id);
|
||||||
_client = _si?.client;
|
_client = _si?.client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user