mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
apply font to ssh term
This commit is contained in:
@@ -411,6 +411,12 @@ abstract class S {
|
||||
/// **'Extra args'**
|
||||
String get extraArgs;
|
||||
|
||||
/// No description provided for @failed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed'**
|
||||
String get failed;
|
||||
|
||||
/// No description provided for @feedback.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -639,6 +645,12 @@ abstract class S {
|
||||
/// **'Name'**
|
||||
String get name;
|
||||
|
||||
/// No description provided for @needRestart.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Need to restart app'**
|
||||
String get needRestart;
|
||||
|
||||
/// No description provided for @newContainer.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -687,6 +699,12 @@ abstract class S {
|
||||
/// **'No update available'**
|
||||
String get noUpdateAvailable;
|
||||
|
||||
/// No description provided for @notSelected.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Not selected'**
|
||||
String get notSelected;
|
||||
|
||||
/// No description provided for @nullToken.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -819,6 +837,12 @@ abstract class S {
|
||||
/// **'Please report bugs on {url}'**
|
||||
String reportBugsOnGithubIssue(Object url);
|
||||
|
||||
/// No description provided for @restart.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Restart'**
|
||||
String get restart;
|
||||
|
||||
/// No description provided for @restore.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -1112,12 +1136,6 @@ abstract class S {
|
||||
/// In en, this message translates to:
|
||||
/// **'Will take effect immediately'**
|
||||
String get willTakEeffectImmediately;
|
||||
|
||||
/// No description provided for @notSelected.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Not selected'**
|
||||
String get notSelected;
|
||||
}
|
||||
|
||||
class _SDelegate extends LocalizationsDelegate<S> {
|
||||
|
||||
@@ -173,6 +173,9 @@ class SEn extends S {
|
||||
@override
|
||||
String get extraArgs => 'Extra args';
|
||||
|
||||
@override
|
||||
String get failed => 'Failed';
|
||||
|
||||
@override
|
||||
String get feedback => 'Feedback';
|
||||
|
||||
@@ -299,6 +302,9 @@ class SEn extends S {
|
||||
@override
|
||||
String get name => 'Name';
|
||||
|
||||
@override
|
||||
String get needRestart => 'Need to restart app';
|
||||
|
||||
@override
|
||||
String get newContainer => 'New container';
|
||||
|
||||
@@ -323,6 +329,9 @@ class SEn extends S {
|
||||
@override
|
||||
String get noUpdateAvailable => 'No update available';
|
||||
|
||||
@override
|
||||
String get notSelected => 'Not selected';
|
||||
|
||||
@override
|
||||
String get nullToken => 'Null token';
|
||||
|
||||
@@ -391,6 +400,9 @@ class SEn extends S {
|
||||
return 'Please report bugs on $url';
|
||||
}
|
||||
|
||||
@override
|
||||
String get restart => 'Restart';
|
||||
|
||||
@override
|
||||
String get restore => 'Restore';
|
||||
|
||||
@@ -557,7 +569,4 @@ class SEn extends S {
|
||||
|
||||
@override
|
||||
String get willTakEeffectImmediately => 'Will take effect immediately';
|
||||
|
||||
@override
|
||||
String get notSelected => 'Not selected';
|
||||
}
|
||||
|
||||
@@ -173,6 +173,9 @@ class SZh extends S {
|
||||
@override
|
||||
String get extraArgs => '额外参数';
|
||||
|
||||
@override
|
||||
String get failed => '失败';
|
||||
|
||||
@override
|
||||
String get feedback => '反馈';
|
||||
|
||||
@@ -299,6 +302,9 @@ class SZh extends S {
|
||||
@override
|
||||
String get name => '名称';
|
||||
|
||||
@override
|
||||
String get needRestart => '需要重启 App';
|
||||
|
||||
@override
|
||||
String get newContainer => '新建容器';
|
||||
|
||||
@@ -323,6 +329,9 @@ class SZh extends S {
|
||||
@override
|
||||
String get noUpdateAvailable => '没有可用更新';
|
||||
|
||||
@override
|
||||
String get notSelected => '未选择';
|
||||
|
||||
@override
|
||||
String get nullToken => '无Token';
|
||||
|
||||
@@ -391,6 +400,9 @@ class SZh extends S {
|
||||
return '请到 $url 提交问题';
|
||||
}
|
||||
|
||||
@override
|
||||
String get restart => '重启';
|
||||
|
||||
@override
|
||||
String get restore => '恢复';
|
||||
|
||||
@@ -557,7 +569,4 @@ class SZh extends S {
|
||||
|
||||
@override
|
||||
String get willTakEeffectImmediately => '更改将会立即生效';
|
||||
|
||||
@override
|
||||
String get notSelected => '未选择';
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 237;
|
||||
CURRENT_PROJECT_VERSION = 239;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -367,7 +367,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.237;
|
||||
MARKETING_VERSION = 1.0.239;
|
||||
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 = 237;
|
||||
CURRENT_PROJECT_VERSION = 239;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -498,7 +498,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.237;
|
||||
MARKETING_VERSION = 1.0.239;
|
||||
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 = 237;
|
||||
CURRENT_PROJECT_VERSION = 239;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -523,7 +523,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.237;
|
||||
MARKETING_VERSION = 1.0.239;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:plain_notification_token/plain_notification_token.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
import '../../view/widget/rebuild.dart';
|
||||
import 'platform.dart';
|
||||
|
||||
Future<bool> shareFiles(BuildContext context, List<String> filePaths) async {
|
||||
@@ -54,3 +55,7 @@ String? getFileName(String? path) {
|
||||
}
|
||||
return path.split('/').last;
|
||||
}
|
||||
|
||||
void rebuildAll(BuildContext context) {
|
||||
RebuildWidget.restartApp(context);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:toolbox/core/provider_base.dart';
|
||||
import '../model/sftp/download_item.dart';
|
||||
import '../model/sftp/download_status.dart';
|
||||
|
||||
class SftpDownloadProvider extends ProviderBase {
|
||||
class SftpProvider extends ProviderBase {
|
||||
final List<SftpDownloadStatus> _status = [];
|
||||
List<SftpDownloadStatus> get status => _status;
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 237;
|
||||
static const int build = 239;
|
||||
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 int modifications = 4;
|
||||
"Flutter 3.7.7 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 2ad6cd72c0 (13 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-21 14:03:13.656226";
|
||||
static const int modifications = 17;
|
||||
}
|
||||
|
||||
@@ -8,3 +8,8 @@ Future<Directory> get sftpDownloadDir async {
|
||||
final dir = Directory('${(await docDir).path}/sftp');
|
||||
return dir.create(recursive: true);
|
||||
}
|
||||
|
||||
Future<Directory> get fontDir async {
|
||||
final dir = Directory('${(await docDir).path}/font');
|
||||
return dir.create(recursive: true);
|
||||
}
|
||||
|
||||
@@ -34,5 +34,5 @@ class SettingStore extends PersistentStore {
|
||||
StoreProperty<int> get themeMode => property('themeMode', defaultValue: 0);
|
||||
|
||||
/// Font file path
|
||||
StoreProperty<String> get fontPath => property('fontPath');
|
||||
StoreProperty<String> get fontPath => property('fontPath2');
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"experimentalFeature": "Experimental feature",
|
||||
"export": "Export",
|
||||
"extraArgs": "Extra args",
|
||||
"failed": "Failed",
|
||||
"feedback": "Feedback",
|
||||
"feedbackOnGithub": "If you have any questions, please feedback on Github.",
|
||||
"fieldMustNotEmpty": "These fields must not be empty.",
|
||||
@@ -90,6 +91,7 @@
|
||||
"min": "min",
|
||||
"ms": "ms",
|
||||
"name": "Name",
|
||||
"needRestart": "Need to restart app",
|
||||
"newContainer": "New container",
|
||||
"noClient": "No client",
|
||||
"noInterface": "No interface",
|
||||
@@ -98,6 +100,7 @@
|
||||
"noSavedSnippet": "No saved snippets.",
|
||||
"noServerAvailable": "No server available.",
|
||||
"noUpdateAvailable": "No update available",
|
||||
"notSelected": "Not selected",
|
||||
"nullToken": "Null token",
|
||||
"ok": "OK",
|
||||
"onServerDetailPage": "On server detail page",
|
||||
@@ -120,6 +123,7 @@
|
||||
"pwd": "Password",
|
||||
"rename": "Rename",
|
||||
"reportBugsOnGithubIssue": "Please report bugs on {url}",
|
||||
"restart": "Restart",
|
||||
"restore": "Restore",
|
||||
"restoreSuccess": "Restore success. Restart app to apply.",
|
||||
"restoreSureWithDate": "Are you sure to restore from {date} ?",
|
||||
@@ -168,6 +172,5 @@
|
||||
"versionUnknownUpdate": "Current: v1.0.{build}",
|
||||
"versionUpdated": "Current: v1.0.{build}, is up to date",
|
||||
"waitConnection": "Please wait for the connection to be established.",
|
||||
"willTakEeffectImmediately": "Will take effect immediately",
|
||||
"notSelected": "Not selected"
|
||||
"willTakEeffectImmediately": "Will take effect immediately"
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"experimentalFeature": "实验性功能",
|
||||
"export": "导出",
|
||||
"extraArgs": "额外参数",
|
||||
"failed": "失败",
|
||||
"feedback": "反馈",
|
||||
"feedbackOnGithub": "如果你有任何问题,请在GitHub反馈",
|
||||
"fieldMustNotEmpty": "这些输入框不能为空。",
|
||||
@@ -90,6 +91,7 @@
|
||||
"min": "最小",
|
||||
"ms": "毫秒",
|
||||
"name": "名称",
|
||||
"needRestart": "需要重启 App",
|
||||
"newContainer": "新建容器",
|
||||
"noClient": "没有SSH连接",
|
||||
"noInterface": "没有可用的接口",
|
||||
@@ -98,6 +100,7 @@
|
||||
"noSavedSnippet": "没有已保存的代码片段。",
|
||||
"noServerAvailable": "没有可用的服务器。",
|
||||
"noUpdateAvailable": "没有可用更新",
|
||||
"notSelected": "未选择",
|
||||
"nullToken": "无Token",
|
||||
"ok": "好",
|
||||
"onServerDetailPage": "在服务器详情页",
|
||||
@@ -120,6 +123,7 @@
|
||||
"pwd": "密码",
|
||||
"rename": "重命名",
|
||||
"reportBugsOnGithubIssue": "请到 {url} 提交问题",
|
||||
"restart": "重启",
|
||||
"restore": "恢复",
|
||||
"restoreSuccess": "恢复成功,需要重启App来应用更改",
|
||||
"restoreSureWithDate": "确定恢复 {date} 的备份吗?",
|
||||
@@ -168,6 +172,5 @@
|
||||
"versionUnknownUpdate": "当前:v1.0.{build}",
|
||||
"versionUpdated": "当前:v1.0.{build}, 已是最新版本",
|
||||
"waitConnection": "请等待连接建立",
|
||||
"willTakEeffectImmediately": "更改将会立即生效",
|
||||
"notSelected": "未选择"
|
||||
"willTakEeffectImmediately": "更改将会立即生效"
|
||||
}
|
||||
@@ -31,7 +31,7 @@ void setupLocatorForProviders() {
|
||||
locator.registerSingleton(VirtualKeyboard());
|
||||
locator.registerSingleton(SnippetProvider());
|
||||
locator.registerSingleton(PrivateKeyProvider());
|
||||
locator.registerSingleton(SftpDownloadProvider());
|
||||
locator.registerSingleton(SftpProvider());
|
||||
}
|
||||
|
||||
Future<void> setupLocatorForStores() async {
|
||||
|
||||
@@ -4,11 +4,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/utils/ui.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
|
||||
import 'app.dart';
|
||||
import 'core/analysis.dart';
|
||||
import 'core/utils/ui.dart';
|
||||
import 'data/model/server/private_key_info.dart';
|
||||
import 'data/model/server/server_private_info.dart';
|
||||
import 'data/model/server/snippet.dart';
|
||||
@@ -21,7 +20,9 @@ import 'data/provider/server.dart';
|
||||
import 'data/provider/sftp_download.dart';
|
||||
import 'data/provider/snippet.dart';
|
||||
import 'data/provider/virtual_keyboard.dart';
|
||||
import 'data/store/setting.dart';
|
||||
import 'locator.dart';
|
||||
import 'view/widget/rebuild.dart';
|
||||
|
||||
late final DebugProvider _debug;
|
||||
|
||||
@@ -91,10 +92,11 @@ Future<void> main() async {
|
||||
ChangeNotifierProvider(create: (_) => locator<SnippetProvider>()),
|
||||
ChangeNotifierProvider(create: (_) => locator<VirtualKeyboard>()),
|
||||
ChangeNotifierProvider(create: (_) => locator<PrivateKeyProvider>()),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => locator<SftpDownloadProvider>()),
|
||||
ChangeNotifierProvider(create: (_) => locator<SftpProvider>()),
|
||||
],
|
||||
child: MyApp(),
|
||||
child: RebuildWidget(
|
||||
child: MyApp(),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -443,8 +443,10 @@ class _ServerPageState extends State<ServerPage>
|
||||
@override
|
||||
Future<void> afterFirstLayout(BuildContext context) async {
|
||||
await GetIt.I.allReady();
|
||||
await _serverProvider.loadLocalData();
|
||||
await _serverProvider.refreshData();
|
||||
_serverProvider.startAutoRefresh();
|
||||
if (_serverProvider.servers.isEmpty) {
|
||||
await _serverProvider.loadLocalData();
|
||||
await _serverProvider.refreshData();
|
||||
_serverProvider.startAutoRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/data/res/path.dart';
|
||||
|
||||
import '../../core/utils/misc.dart';
|
||||
import '../../core/utils/platform.dart';
|
||||
@@ -448,18 +451,52 @@ class _SettingPageState extends State<SettingPage> {
|
||||
}
|
||||
|
||||
Widget _buildFont() {
|
||||
return ListTile(
|
||||
return ExpansionTile(
|
||||
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)),
|
||||
trailing: Text(getFileName(_setting.fontPath.fetch()) ?? _s.notSelected),
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async => pickFontFile(),
|
||||
child: Text(_s.pickFile),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => setState(() {
|
||||
_setting.fontPath.delete();
|
||||
showSnackBarWithAction(
|
||||
context,
|
||||
'${_s.success}\n${_s.needRestart}',
|
||||
_s.restart,
|
||||
() => rebuildAll(context),
|
||||
);
|
||||
}),
|
||||
child: Text(_s.clear),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> pickFontFile() async {
|
||||
final path = await pickOneFile();
|
||||
if (path != null) {
|
||||
final fontDir_ = await fontDir;
|
||||
final fontFile = File(path);
|
||||
final newPath = '${fontDir_.path}/${path.split('/').last}';
|
||||
await fontFile.copy(newPath);
|
||||
_setting.fontPath.put(newPath);
|
||||
setState(() {});
|
||||
showSnackBarWithAction(
|
||||
context,
|
||||
'${_s.success}\n${_s.needRestart}',
|
||||
_s.restart,
|
||||
() => rebuildAll(context),
|
||||
);
|
||||
return;
|
||||
}
|
||||
showSnackBar(context, Text(_s.failed));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class _SFTPDownloadingPageState extends State<SFTPDownloadingPage> {
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
return Consumer<SftpDownloadProvider>(builder: (__, pro, _) {
|
||||
return Consumer<SftpProvider>(builder: (__, pro, _) {
|
||||
if (pro.status.isEmpty) {
|
||||
return Center(
|
||||
child: Text(_s.sftpNoDownloadTask),
|
||||
|
||||
@@ -305,7 +305,7 @@ class _SFTPPageState extends State<SFTPPage> {
|
||||
final local = '${(await sftpDownloadDir).path}$remotePath';
|
||||
final pubKeyId = widget.spi.pubKeyId;
|
||||
|
||||
locator<SftpDownloadProvider>().add(
|
||||
locator<SftpProvider>().add(
|
||||
DownloadItem(
|
||||
widget.spi,
|
||||
remotePath,
|
||||
|
||||
@@ -34,6 +34,7 @@ class _SSHPageState extends State<SSHPage> {
|
||||
late final _terminal = Terminal(inputHandler: _keyboard);
|
||||
SSHClient? _client;
|
||||
final _keyboard = locator<VirtualKeyboard>();
|
||||
final _setting = locator<SettingStore>();
|
||||
late MediaQueryData _media;
|
||||
final _virtualKeyboardHeight = 57.0;
|
||||
final TerminalController _terminalController = TerminalController();
|
||||
@@ -47,7 +48,7 @@ class _SSHPageState extends State<SSHPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final termColorIdx = locator<SettingStore>().termColorIdx.fetch()!;
|
||||
final termColorIdx = _setting.termColorIdx.fetch()!;
|
||||
_termColors = TerminalColorsPlatform.values[termColorIdx].colors;
|
||||
initTerminal();
|
||||
}
|
||||
@@ -149,6 +150,8 @@ class _SSHPageState extends State<SSHPage> {
|
||||
_terminal,
|
||||
controller: _terminalController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
textStyle: TerminalStyle.fromTextStyle(
|
||||
TextStyle(fontFamily: getFileName(_setting.fontPath.fetch()))),
|
||||
theme: termTheme,
|
||||
deleteDetection: isIOS,
|
||||
onTapUp: _onTapUp,
|
||||
|
||||
32
lib/view/widget/rebuild.dart
Normal file
32
lib/view/widget/rebuild.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RebuildWidget extends StatefulWidget {
|
||||
const RebuildWidget({super.key, required this.child});
|
||||
|
||||
final Widget child;
|
||||
|
||||
static void restartApp(BuildContext context) {
|
||||
context.findAncestorStateOfType<_RebuildWidgetState>()?.restartApp();
|
||||
}
|
||||
|
||||
@override
|
||||
_RebuildWidgetState createState() => _RebuildWidgetState();
|
||||
}
|
||||
|
||||
class _RebuildWidgetState extends State<RebuildWidget> {
|
||||
Key key = UniqueKey();
|
||||
|
||||
void restartApp() {
|
||||
setState(() {
|
||||
key = UniqueKey();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return KeyedSubtree(
|
||||
key: key,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user