diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n.dart b/.dart_tool/flutter_gen/gen_l10n/l10n.dart index c895bd83..767a51bd 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n.dart @@ -372,6 +372,12 @@ abstract class S { /// **'Edit'** String get edit; + /// No description provided for @editor. + /// + /// In en, this message translates to: + /// **'Editor'** + String get editor; + /// No description provided for @encode. /// /// In en, this message translates to: diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart index 247faf42..2af102eb 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_de.dart @@ -152,6 +152,9 @@ class SDe extends S { @override String get edit => 'Bearbeiten'; + @override + String get editor => 'Redakteure'; + @override String get encode => 'Encode'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart index 0564c5f1..234c04fe 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart @@ -152,6 +152,9 @@ class SEn extends S { @override String get edit => 'Edit'; + @override + String get editor => 'Editor'; + @override String get encode => 'Encode'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart index 416fce16..81cf6336 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart @@ -152,6 +152,9 @@ class SZh extends S { @override String get edit => '编辑'; + @override + String get editor => '编辑器'; + @override String get encode => '编码'; @@ -741,6 +744,9 @@ class SZhTw extends SZh { @override String get edit => '編輯'; + @override + String get editor => '編輯器'; + @override String get encode => '編碼'; diff --git a/lib/data/res/highlight.dart b/lib/data/res/highlight.dart new file mode 100644 index 00000000..26a022f6 --- /dev/null +++ b/lib/data/res/highlight.dart @@ -0,0 +1,79 @@ +import 'package:highlight/highlight_core.dart'; +import 'package:highlight/languages/accesslog.dart'; +import 'package:highlight/languages/awk.dart'; +import 'package:highlight/languages/bash.dart'; +import 'package:highlight/languages/cmake.dart'; +import 'package:highlight/languages/cpp.dart'; +import 'package:highlight/languages/css.dart'; +import 'package:highlight/languages/dart.dart'; +import 'package:highlight/languages/diff.dart'; +import 'package:highlight/languages/go.dart'; +import 'package:highlight/languages/htmlbars.dart'; +import 'package:highlight/languages/ini.dart'; +import 'package:highlight/languages/java.dart'; +import 'package:highlight/languages/javascript.dart'; +import 'package:highlight/languages/json.dart'; +import 'package:highlight/languages/kotlin.dart'; +import 'package:highlight/languages/lisp.dart'; +import 'package:highlight/languages/lua.dart'; +import 'package:highlight/languages/nix.dart'; +import 'package:highlight/languages/objectivec.dart'; +import 'package:highlight/languages/perl.dart'; +import 'package:highlight/languages/php.dart'; +import 'package:highlight/languages/powershell.dart'; +import 'package:highlight/languages/python.dart'; +import 'package:highlight/languages/ruby.dart'; +import 'package:highlight/languages/rust.dart'; +import 'package:highlight/languages/sql.dart'; +import 'package:highlight/languages/swift.dart'; +import 'package:highlight/languages/tex.dart'; +import 'package:highlight/languages/typescript.dart'; +import 'package:highlight/languages/vim.dart'; +import 'package:highlight/languages/xml.dart'; +import 'package:highlight/languages/yaml.dart'; + +// KEY: fileNameSuffix +// VAL: highlight +final _suffix2HighlightMap = { + 'dart': dart, + 'go': go, + 'rust': rust, + 'lua': lua, + 'sh': bash, + 'py': python, + 'js': javascript, + 'ts': typescript, + 'java': java, + 'kt': kotlin, + 'swift': swift, + 'c': cpp, + 'oc': objectivec, + 'ruby': ruby, + 'perl': perl, + 'php': php, + 'nix': nix, + 'lisp': lisp, + 'sql': sql, + 'powershell': powershell, + 'log': accesslog, + 'ini': ini, + 'cmake': cmake, + 'awk': awk, + 'json': json, + 'yaml': yaml, + 'xml': xml, + 'cpp': cpp, + 'diff': diff, + 'css': css, + 'html': htmlbars, + 'tex': tex, + 'vim': vim, +}; + +extension HighlightString on String? { + Mode? get highlight { + if (this == null) return null; + final suffix = this!.split('.').last; + return _suffix2HighlightMap[suffix]; + } +} diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 9700d990..5738682d 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -72,4 +72,8 @@ class SettingStore extends PersistentStore { // SSH virtual key (ctrl | alt) auto turn off StoreProperty get sshVirtualKeyAutoOff => property('sshVirtualKeyAutoOff', defaultValue: true); + + // Editor theme + StoreProperty get editorTheme => + property('editorTheme', defaultValue: 'monokai'); } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 38160fe4..d7d9e08e 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -46,6 +46,7 @@ "downloadFinished": "Download abgeschlossen", "downloadStatus": "{percent}% von {size}", "edit": "Bearbeiten", + "editor": "Redakteure", "encode": "Encode", "error": "Fehler", "exampleName": "Servername", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 86be368d..67cb02b0 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -46,6 +46,7 @@ "downloadFinished": "Download finished", "downloadStatus": "{percent}% of {size}", "edit": "Edit", + "editor": "Editor", "encode": "Encode", "error": "Error", "exampleName": "Example name", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 1a1a0b0f..dd104a4e 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -46,6 +46,7 @@ "downloadFinished": "下载完成", "downloadStatus": "{size} 的 {percent}%", "edit": "编辑", + "editor": "编辑器", "encode": "编码", "error": "错误", "exampleName": "名称示例", diff --git a/lib/l10n/app_zh_tw.arb b/lib/l10n/app_zh_tw.arb index 15faa61f..9f0ca81f 100644 --- a/lib/l10n/app_zh_tw.arb +++ b/lib/l10n/app_zh_tw.arb @@ -46,6 +46,7 @@ "downloadFinished": "下載完成", "downloadStatus": "{size} 的 {percent}%", "edit": "編輯", + "editor": "編輯器", "encode": "編碼", "error": "錯誤", "exampleName": "名稱範例", diff --git a/lib/view/page/editor.dart b/lib/view/page/editor.dart index 6c217fd8..602995a7 100644 --- a/lib/view/page/editor.dart +++ b/lib/view/page/editor.dart @@ -1,12 +1,16 @@ +import 'package:code_text_field/code_text_field.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_code_editor/flutter_code_editor.dart'; -import 'package:flutter_highlight/themes/monokai-sublime.dart'; -import 'package:highlight/languages/java.dart'; +import 'package:flutter_highlight/theme_map.dart'; +import 'package:flutter_highlight/themes/monokai.dart'; import 'package:toolbox/core/extension/navigator.dart'; +import 'package:toolbox/data/res/highlight.dart'; +import 'package:toolbox/data/store/setting.dart'; +import 'package:toolbox/locator.dart'; class EditorPage extends StatefulWidget { final String? initCode; - const EditorPage({Key? key, this.initCode}) : super(key: key); + final String? fileName; + const EditorPage({Key? key, this.initCode, this.fileName}) : super(key: key); @override _EditorPageState createState() => _EditorPageState(); @@ -15,16 +19,18 @@ class EditorPage extends StatefulWidget { class _EditorPageState extends State { late CodeController _controller; late final _focusNode = FocusNode(); + final _setting = locator(); + late Map _codeTheme; @override void initState() { super.initState(); _focusNode.requestFocus(); _controller = CodeController( - text: widget.initCode, - language: java, - analyzer: const DefaultLocalAnalyzer(), -); + text: widget.initCode, + language: widget.fileName.highlight, + ); + _codeTheme = themeMap[_setting.editorTheme.fetch()] ?? monokaiTheme; } @override @@ -37,28 +43,23 @@ class _EditorPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: monokaiSublimeTheme['root']!.backgroundColor, + backgroundColor: _codeTheme['root']!.backgroundColor, appBar: AppBar( - title: const Text('Editor'), + title: Text(widget.fileName ?? ''), actions: [ IconButton( icon: const Icon(Icons.done), onPressed: () { - context.pop(_controller.fullText); + context.pop(_controller.text); }, ), ], ), body: CodeTheme( - data: CodeThemeData(styles: monokaiSublimeTheme), - child: SingleChildScrollView( - child: CodeField( - controller: _controller, - gutterStyle: const GutterStyle( - width: 37, - showLineNumbers: false, - ), - ), + data: CodeThemeData(styles: _codeTheme), + child: CodeField( + controller: _controller, + textStyle: const TextStyle(fontFamily: 'SourceCode'), ), ), ); diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index f206cb35..721ac25d 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_highlight/theme_map.dart'; import 'package:flutter_material_color_picker/flutter_material_color_picker.dart'; import 'package:provider/provider.dart'; import 'package:toolbox/core/extension/locale.dart'; @@ -39,6 +40,7 @@ class _SettingPageState extends State { final maxRetryKey = GlobalKey>(); final fontSizeKey = GlobalKey>(); final localeKey = GlobalKey>(); + final editorThemeKey = GlobalKey>(); late final SettingStore _setting; late final ServerProvider _serverProvider; @@ -52,6 +54,7 @@ class _SettingPageState extends State { late int _updateInterval; late double _fontSize; late String _localeCode; + late String _editorTheme; String? _pushToken; @@ -74,6 +77,7 @@ class _SettingPageState extends State { _maxRetryCount = _setting.maxRetryCount.fetch()!; _selectedColorValue = _setting.primaryColor.fetch()!; _fontSize = _setting.termFontSize.fetch()!; + _editorTheme = _setting.editorTheme.fetch()!; } @override @@ -94,6 +98,9 @@ class _SettingPageState extends State { // SSH _buildTitle('SSH'), _buildSSH(), + // Editor + _buildTitle('Editor'), + _buildEditor(), const SizedBox(height: 37), ], ), @@ -116,7 +123,7 @@ class _SettingPageState extends State { final children = [ _buildLocale(), _buildThemeMode(), - _buildAppColorPreview(), + _buildAppColor(), _buildLaunchPage(), _buildCheckUpdate(), ]; @@ -152,6 +159,14 @@ class _SettingPageState extends State { ); } + Widget _buildEditor() { + return Column( + children: [ + _buildEditorTheme(), + ].map((e) => RoundRectCard(e)).toList(), + ); + } + Widget _buildDistLogoSwitch() { return ListTile( title: Text( @@ -232,7 +247,7 @@ class _SettingPageState extends State { ); } - Widget _buildAppColorPreview() { + Widget _buildAppColor() { return ListTile( trailing: ClipOval( child: Container( @@ -247,6 +262,7 @@ class _SettingPageState extends State { onTap: () async { await showRoundDialog( context: context, + title: Text(_s.appPrimaryColor), child: MaterialColorPicker( shrinkWrap: true, allowShades: true, @@ -442,23 +458,21 @@ class _SettingPageState extends State { onTap: () { showRoundDialog( context: context, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - TextButton( - onPressed: () async => await _pickFontFile(), - child: Text(_s.pickFile), - ), - TextButton( - onPressed: () => setState(() { - _setting.fontPath.delete(); - context.pop(); - _showRestartSnackbar(); - }), - child: Text(_s.clear), - ) - ], - ), + title: Text(_s.font), + actions: [ + TextButton( + onPressed: () async => await _pickFontFile(), + child: Text(_s.pickFile), + ), + TextButton( + onPressed: () => setState(() { + _setting.fontPath.delete(); + context.pop(); + _showRestartSnackbar(); + }), + child: Text(_s.clear), + ) + ], ); }, ); @@ -606,4 +620,37 @@ class _SettingPageState extends State { trailing: buildSwitch(context, _setting.sshVirtualKeyAutoOff), ); } + + Widget _buildEditorTheme() { + final items = themeMap.keys.map( + (key) { + return PopupMenuItem( + value: key, + child: Text(key), + ); + }, + ).toList(); + return ListTile( + title: Text(_s.editor + _s.theme), + trailing: PopupMenuButton( + key: editorThemeKey, + itemBuilder: (BuildContext context) => items, + initialValue: _editorTheme, + onSelected: (String idx) { + setState(() { + _editorTheme = idx; + }); + _setting.editorTheme.put(idx); + _showRestartSnackbar(); + }, + child: Text( + _editorTheme, + style: textSize15, + ), + ), + onTap: () { + editorThemeKey.currentState?.showButtonMenu(); + }, + ); + } } diff --git a/lib/view/page/sftp/downloaded.dart b/lib/view/page/sftp/downloaded.dart index 9249fc5a..7555f60f 100644 --- a/lib/view/page/sftp/downloaded.dart +++ b/lib/view/page/sftp/downloaded.dart @@ -180,12 +180,14 @@ class _SFTPDownloadedPageState extends State { context.pop(); final stat = await file.stat(); if (stat.size > 1024 * 1024) { - showRoundDialog(context: context, child: Text('too big')); + showRoundDialog( + context: context, + child: Text(_s.fileTooLarge(fileName, stat.size, '1m')), + ); return; } final f = await File(file.absolute.path).readAsString(); - AppRoute(EditorPage(initCode: f), 'sftp dled editor') - .go(context); + AppRoute(EditorPage(initCode: f), 'sftp dled editor').go(context); }, ) ], diff --git a/pubspec.lock b/pubspec.lock index d73ea419..ec4a60a1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -57,14 +57,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" - autotrie: - dependency: transitive - description: - name: autotrie - sha256: "55da6faefb53cfcb0abb2f2ca8636123fb40e35286bb57440d2cf467568188f8" - url: "https://pub.dev" - source: hosted - version: "2.0.0" boolean_selector: dependency: transitive description: @@ -145,14 +137,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - charcode: - dependency: transitive - description: - name: charcode - sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 - url: "https://pub.dev" - source: hosted - version: "1.3.1" checked_yaml: dependency: transitive description: @@ -186,6 +170,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.4.0" + code_text_field: + dependency: "direct main" + description: + name: code_text_field + sha256: "0cbffbb2932cf82e1d022996388041de3493a476acad3fbb13e5917cac0fc5f2" + url: "https://pub.dev" + source: hosted + version: "1.1.0" collection: dependency: transitive description: @@ -210,14 +202,6 @@ packages: url: "https://pub.dev" source: hosted version: "22.09.0" - coverage: - dependency: transitive - description: - name: coverage - sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" - url: "https://pub.dev" - source: hosted - version: "1.6.3" cross_file: dependency: transitive description: @@ -343,14 +327,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_code_editor: - dependency: "direct main" - description: - name: flutter_code_editor - sha256: "5cd0337a24155dcac85d4f5b0cc8fa022ab19785a968a86726cdc62e363ee428" - url: "https://pub.dev" - source: hosted - version: "0.2.23" flutter_highlight: dependency: "direct main" description: @@ -606,14 +582,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" - mocktail: - dependency: transitive - description: - name: mocktail - sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" - url: "https://pub.dev" - source: hosted - version: "0.3.0" nested: dependency: transitive description: @@ -622,14 +590,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" package_config: dependency: transitive description: @@ -814,14 +774,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.8+2" - scrollable_positioned_list: - dependency: transitive - description: - name: scrollable_positioned_list - sha256: "1b54d5f1329a1e263269abc9e2543d90806131aa14fe7c6062a8054d57249287" - url: "https://pub.dev" - source: hosted - version: "0.3.8" share_plus: dependency: "direct main" description: @@ -854,22 +806,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e - url: "https://pub.dev" - source: hosted - version: "1.1.2" shelf_web_socket: dependency: transitive description: @@ -899,22 +835,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.3" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" - url: "https://pub.dev" - source: hosted - version: "0.10.12" source_span: dependency: transitive description: @@ -963,14 +883,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" - test: - dependency: transitive - description: - name: test - sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4" - url: "https://pub.dev" - source: hosted - version: "1.24.1" test_api: dependency: transitive description: @@ -979,14 +891,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" - test_core: - dependency: transitive - description: - name: test_core - sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93" - url: "https://pub.dev" - source: hosted - version: "0.5.1" timing: dependency: transitive description: @@ -995,14 +899,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - tuple: - dependency: transitive - description: - name: tuple - sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" - url: "https://pub.dev" - source: hosted - version: "2.0.1" typed_data: dependency: transitive description: @@ -1099,14 +995,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: f3743ca475e0c9ef71df4ba15eb2d7684eecd5c8ba20a462462e4e8b561b2e11 - url: "https://pub.dev" - source: hosted - version: "11.6.0" watcher: dependency: transitive description: @@ -1123,14 +1011,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" - url: "https://pub.dev" - source: hosted - version: "1.2.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 831b07fa..f355a719 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,7 +65,7 @@ dependencies: plain_notification_token: ^0.0.4 highlight: ^0.7.0 flutter_highlight: ^0.7.0 - flutter_code_editor: ^0.2.23 + code_text_field: ^1.1.0 dev_dependencies: flutter_native_splash: ^2.1.6