mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
i18n support
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:toolbox/data/res/build_data.dart';
|
import 'package:toolbox/data/res/build_data.dart';
|
||||||
import 'package:toolbox/data/store/setting.dart';
|
import 'package:toolbox/data/store/setting.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/page/home.dart';
|
import 'package:toolbox/view/page/home.dart';
|
||||||
|
|
||||||
@@ -30,6 +32,13 @@ class MyApp extends StatelessWidget {
|
|||||||
final primaryColor = Color(value);
|
final primaryColor = Color(value);
|
||||||
final textStyle = TextStyle(color: primaryColor);
|
final textStyle = TextStyle(color: primaryColor);
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
localizationsDelegates: const [
|
||||||
|
S.delegate,
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
supportedLocales: S.delegate.supportedLocales,
|
||||||
title: BuildData.name,
|
title: BuildData.name,
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ 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:toolbox/core/persistant_store.dart';
|
import 'package:toolbox/core/persistant_store.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/view/widget/card_dialog.dart';
|
import 'package:toolbox/view/widget/card_dialog.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:toolbox/core/extension/stringx.dart';
|
import 'package:toolbox/core/extension/stringx.dart';
|
||||||
@@ -82,3 +83,17 @@ void setTransparentNavigationBar(BuildContext context) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String tabTitleName(BuildContext context, int i) {
|
||||||
|
final s = S.of(context);
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return s.server;
|
||||||
|
case 1:
|
||||||
|
return s.convert;
|
||||||
|
case 2:
|
||||||
|
return s.ping;
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
3
lib/data/res/font_style.dart
Normal file
3
lib/data/res/font_style.dart
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const TextStyle size18 = TextStyle(fontSize: 18);
|
||||||
66
lib/generated/intl/messages_all.dart
Normal file
66
lib/generated/intl/messages_all.dart
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||||
|
// This is a library that looks up messages for specific locales by
|
||||||
|
// delegating to the appropriate library.
|
||||||
|
|
||||||
|
// Ignore issues from commonly used lints in this file.
|
||||||
|
// ignore_for_file:implementation_imports, file_names, unnecessary_new
|
||||||
|
// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering
|
||||||
|
// ignore_for_file:argument_type_not_assignable, invalid_assignment
|
||||||
|
// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases
|
||||||
|
// ignore_for_file:comment_references
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:intl/message_lookup_by_library.dart';
|
||||||
|
import 'package:intl/src/intl_helpers.dart';
|
||||||
|
|
||||||
|
import 'messages_en.dart' as messages_en;
|
||||||
|
import 'messages_zh.dart' as messages_zh;
|
||||||
|
|
||||||
|
typedef Future<dynamic> LibraryLoader();
|
||||||
|
Map<String, LibraryLoader> _deferredLibraries = {
|
||||||
|
'en': () => new Future.value(null),
|
||||||
|
'zh': () => new Future.value(null),
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageLookupByLibrary? _findExact(String localeName) {
|
||||||
|
switch (localeName) {
|
||||||
|
case 'en':
|
||||||
|
return messages_en.messages;
|
||||||
|
case 'zh':
|
||||||
|
return messages_zh.messages;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// User programs should call this before using [localeName] for messages.
|
||||||
|
Future<bool> initializeMessages(String localeName) async {
|
||||||
|
var availableLocale = Intl.verifiedLocale(
|
||||||
|
localeName, (locale) => _deferredLibraries[locale] != null,
|
||||||
|
onFailure: (_) => null);
|
||||||
|
if (availableLocale == null) {
|
||||||
|
return new Future.value(false);
|
||||||
|
}
|
||||||
|
var lib = _deferredLibraries[availableLocale];
|
||||||
|
await (lib == null ? new Future.value(false) : lib());
|
||||||
|
initializeInternalMessageLookup(() => new CompositeMessageLookup());
|
||||||
|
messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
|
||||||
|
return new Future.value(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _messagesExistFor(String locale) {
|
||||||
|
try {
|
||||||
|
return _findExact(locale) != null;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) {
|
||||||
|
var actualLocale =
|
||||||
|
Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null);
|
||||||
|
if (actualLocale == null) return null;
|
||||||
|
return _findExact(actualLocale);
|
||||||
|
}
|
||||||
140
lib/generated/intl/messages_en.dart
Normal file
140
lib/generated/intl/messages_en.dart
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||||
|
// This is a library that provides messages for a en locale. All the
|
||||||
|
// messages from the main program should be duplicated here with the same
|
||||||
|
// function name.
|
||||||
|
|
||||||
|
// Ignore issues from commonly used lints in this file.
|
||||||
|
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
|
||||||
|
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
|
||||||
|
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
|
||||||
|
// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
|
||||||
|
// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
|
||||||
|
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:intl/message_lookup_by_library.dart';
|
||||||
|
|
||||||
|
final messages = new MessageLookup();
|
||||||
|
|
||||||
|
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
|
||||||
|
|
||||||
|
class MessageLookup extends MessageLookupByLibrary {
|
||||||
|
String get localeName => 'en';
|
||||||
|
|
||||||
|
static String m0(rainSunMeGithub) =>
|
||||||
|
"\nThanks ${rainSunMeGithub} for participating in the test.\n\nAll rights reserved.";
|
||||||
|
|
||||||
|
static String m1(code) => "request failed, status code: ${code}";
|
||||||
|
|
||||||
|
static String m2(myGithub) => "\nMade with ❤️ by ${myGithub}";
|
||||||
|
|
||||||
|
static String m3(server) => "Are you sure to delete server [${server}]?";
|
||||||
|
|
||||||
|
static String m4(build) => "Found: v1.0.${build}, click to update";
|
||||||
|
|
||||||
|
static String m5(build) => "Current: v1.0.${build}";
|
||||||
|
|
||||||
|
static String m6(build) => "Current: v1.0.${build}, is up to date";
|
||||||
|
|
||||||
|
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||||
|
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||||
|
"aboutThanks": m0,
|
||||||
|
"addAServer": MessageLookupByLibrary.simpleMessage("add a server"),
|
||||||
|
"addPrivateKey":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Add private key"),
|
||||||
|
"appPrimaryColor":
|
||||||
|
MessageLookupByLibrary.simpleMessage("App primary color"),
|
||||||
|
"attention": MessageLookupByLibrary.simpleMessage("Attention"),
|
||||||
|
"cancel": MessageLookupByLibrary.simpleMessage("Cancel"),
|
||||||
|
"choose": MessageLookupByLibrary.simpleMessage("Choose"),
|
||||||
|
"chooseDestination":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Choose destination"),
|
||||||
|
"choosePrivateKey":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Choose private key"),
|
||||||
|
"clear": MessageLookupByLibrary.simpleMessage("Clear"),
|
||||||
|
"close": MessageLookupByLibrary.simpleMessage("Close"),
|
||||||
|
"convert": MessageLookupByLibrary.simpleMessage("Convert"),
|
||||||
|
"copy": MessageLookupByLibrary.simpleMessage("Copy"),
|
||||||
|
"currentMode": MessageLookupByLibrary.simpleMessage("Current Mode"),
|
||||||
|
"debug": MessageLookupByLibrary.simpleMessage("Debug"),
|
||||||
|
"decode": MessageLookupByLibrary.simpleMessage("Decode"),
|
||||||
|
"delete": MessageLookupByLibrary.simpleMessage("Delete"),
|
||||||
|
"edit": MessageLookupByLibrary.simpleMessage("Edit"),
|
||||||
|
"encode": MessageLookupByLibrary.simpleMessage("Encode"),
|
||||||
|
"exampleName": MessageLookupByLibrary.simpleMessage("Example name"),
|
||||||
|
"export": MessageLookupByLibrary.simpleMessage("Export"),
|
||||||
|
"fieldMustNotEmpty": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"These fields must not be empty."),
|
||||||
|
"go": MessageLookupByLibrary.simpleMessage("Go"),
|
||||||
|
"host": MessageLookupByLibrary.simpleMessage("Host"),
|
||||||
|
"httpFailedWithCode": m1,
|
||||||
|
"import": MessageLookupByLibrary.simpleMessage("Import"),
|
||||||
|
"importAndExport":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Import and Export"),
|
||||||
|
"keyAuth": MessageLookupByLibrary.simpleMessage("Key Auth"),
|
||||||
|
"launchPage": MessageLookupByLibrary.simpleMessage("Launch page"),
|
||||||
|
"license": MessageLookupByLibrary.simpleMessage("License"),
|
||||||
|
"loss": MessageLookupByLibrary.simpleMessage("Loss"),
|
||||||
|
"madeWithLove": m2,
|
||||||
|
"max": MessageLookupByLibrary.simpleMessage("max"),
|
||||||
|
"min": MessageLookupByLibrary.simpleMessage("min"),
|
||||||
|
"ms": MessageLookupByLibrary.simpleMessage("ms"),
|
||||||
|
"name": MessageLookupByLibrary.simpleMessage("Name"),
|
||||||
|
"noResult": MessageLookupByLibrary.simpleMessage("No result"),
|
||||||
|
"noSavedPrivateKey":
|
||||||
|
MessageLookupByLibrary.simpleMessage("No saved private keys."),
|
||||||
|
"noSavedSnippet":
|
||||||
|
MessageLookupByLibrary.simpleMessage("No saved snippets."),
|
||||||
|
"noServerAvailable":
|
||||||
|
MessageLookupByLibrary.simpleMessage("No server available."),
|
||||||
|
"ok": MessageLookupByLibrary.simpleMessage("OK"),
|
||||||
|
"ping": MessageLookupByLibrary.simpleMessage("Ping"),
|
||||||
|
"pingAvg": MessageLookupByLibrary.simpleMessage("Avg:"),
|
||||||
|
"pingInputIP": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please input a target IP/domain."),
|
||||||
|
"plzEnterHost":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Please enter host."),
|
||||||
|
"plzEnterPwd":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Please enter password."),
|
||||||
|
"plzSelectKey":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Please select a key."),
|
||||||
|
"port": MessageLookupByLibrary.simpleMessage("Port"),
|
||||||
|
"privateKey": MessageLookupByLibrary.simpleMessage("Private Key"),
|
||||||
|
"pwd": MessageLookupByLibrary.simpleMessage("Password"),
|
||||||
|
"result": MessageLookupByLibrary.simpleMessage("Result"),
|
||||||
|
"run": MessageLookupByLibrary.simpleMessage("Run"),
|
||||||
|
"save": MessageLookupByLibrary.simpleMessage("Save"),
|
||||||
|
"second": MessageLookupByLibrary.simpleMessage("s"),
|
||||||
|
"server": MessageLookupByLibrary.simpleMessage("Server"),
|
||||||
|
"serverTabConnecting":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Connecting..."),
|
||||||
|
"serverTabEmpty": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"There is no server.\nClick the fab to add one."),
|
||||||
|
"serverTabFailed": MessageLookupByLibrary.simpleMessage("Failed"),
|
||||||
|
"serverTabLoading": MessageLookupByLibrary.simpleMessage("Loading..."),
|
||||||
|
"serverTabPlzSave": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Please \'save\' this private key again."),
|
||||||
|
"serverTabUnkown":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Unknown state"),
|
||||||
|
"setting": MessageLookupByLibrary.simpleMessage("Setting"),
|
||||||
|
"snippet": MessageLookupByLibrary.simpleMessage("Snippet"),
|
||||||
|
"start": MessageLookupByLibrary.simpleMessage("Start"),
|
||||||
|
"stop": MessageLookupByLibrary.simpleMessage("Stop"),
|
||||||
|
"sureToDeleteServer": m3,
|
||||||
|
"ttl": MessageLookupByLibrary.simpleMessage("TTL"),
|
||||||
|
"unknown": MessageLookupByLibrary.simpleMessage("unknown"),
|
||||||
|
"unkownConvertMode":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Unknown convert mode"),
|
||||||
|
"updateIntervalEqual0": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"You set to 0, will not update automatically.\nYou can pull to refresh manually."),
|
||||||
|
"updateServerStatusInterval": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Server status update interval"),
|
||||||
|
"upsideDown": MessageLookupByLibrary.simpleMessage("Upside Down"),
|
||||||
|
"urlOrJson": MessageLookupByLibrary.simpleMessage("URL or JSON"),
|
||||||
|
"user": MessageLookupByLibrary.simpleMessage("User"),
|
||||||
|
"versionHaveUpdate": m4,
|
||||||
|
"versionUnknownUpdate": m5,
|
||||||
|
"versionUpdated": m6,
|
||||||
|
"willTakEeffectImmediately":
|
||||||
|
MessageLookupByLibrary.simpleMessage("Will take effect immediately")
|
||||||
|
};
|
||||||
|
}
|
||||||
123
lib/generated/intl/messages_zh.dart
Normal file
123
lib/generated/intl/messages_zh.dart
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||||
|
// This is a library that provides messages for a zh locale. All the
|
||||||
|
// messages from the main program should be duplicated here with the same
|
||||||
|
// function name.
|
||||||
|
|
||||||
|
// Ignore issues from commonly used lints in this file.
|
||||||
|
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
|
||||||
|
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
|
||||||
|
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
|
||||||
|
// ignore_for_file:unused_import, file_names, avoid_escaping_inner_quotes
|
||||||
|
// ignore_for_file:unnecessary_string_interpolations, unnecessary_string_escapes
|
||||||
|
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:intl/message_lookup_by_library.dart';
|
||||||
|
|
||||||
|
final messages = new MessageLookup();
|
||||||
|
|
||||||
|
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
|
||||||
|
|
||||||
|
class MessageLookup extends MessageLookupByLibrary {
|
||||||
|
String get localeName => 'zh';
|
||||||
|
|
||||||
|
static String m0(rainSunMeGithub) =>
|
||||||
|
"\n感谢 ${rainSunMeGithub} 参与软件测试。\n\n保留所有权利。";
|
||||||
|
|
||||||
|
static String m1(code) => "请求失败, 状态码: ${code}";
|
||||||
|
|
||||||
|
static String m2(myGithub) => "\n用❤️制作 by ${myGithub}";
|
||||||
|
|
||||||
|
static String m3(server) => "你确定要删除服务器 [${server}] 吗?";
|
||||||
|
|
||||||
|
static String m4(build) => "找到新版本:v1.0.${build}, 点击更新";
|
||||||
|
|
||||||
|
static String m5(build) => "当前:v1.0.${build}";
|
||||||
|
|
||||||
|
static String m6(build) => "当前:v1.0.${build}, 已是最新版本";
|
||||||
|
|
||||||
|
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||||
|
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||||
|
"aboutThanks": m0,
|
||||||
|
"addAServer": MessageLookupByLibrary.simpleMessage("添加服务器"),
|
||||||
|
"addPrivateKey": MessageLookupByLibrary.simpleMessage("添加一个私钥"),
|
||||||
|
"appPrimaryColor": MessageLookupByLibrary.simpleMessage("App主要色"),
|
||||||
|
"attention": MessageLookupByLibrary.simpleMessage("注意"),
|
||||||
|
"cancel": MessageLookupByLibrary.simpleMessage("取消"),
|
||||||
|
"choose": MessageLookupByLibrary.simpleMessage("选择"),
|
||||||
|
"chooseDestination": MessageLookupByLibrary.simpleMessage("选择目标"),
|
||||||
|
"choosePrivateKey": MessageLookupByLibrary.simpleMessage("选择私钥"),
|
||||||
|
"clear": MessageLookupByLibrary.simpleMessage("清除"),
|
||||||
|
"close": MessageLookupByLibrary.simpleMessage("关闭"),
|
||||||
|
"convert": MessageLookupByLibrary.simpleMessage("转换"),
|
||||||
|
"copy": MessageLookupByLibrary.simpleMessage("复制到剪切板"),
|
||||||
|
"currentMode": MessageLookupByLibrary.simpleMessage("当前模式"),
|
||||||
|
"debug": MessageLookupByLibrary.simpleMessage("调试"),
|
||||||
|
"decode": MessageLookupByLibrary.simpleMessage("解码"),
|
||||||
|
"delete": MessageLookupByLibrary.simpleMessage("删除"),
|
||||||
|
"edit": MessageLookupByLibrary.simpleMessage("编辑"),
|
||||||
|
"encode": MessageLookupByLibrary.simpleMessage("编码"),
|
||||||
|
"exampleName": MessageLookupByLibrary.simpleMessage("名称示例"),
|
||||||
|
"export": MessageLookupByLibrary.simpleMessage("导出"),
|
||||||
|
"fieldMustNotEmpty": MessageLookupByLibrary.simpleMessage("这些输入框不能为空。"),
|
||||||
|
"go": MessageLookupByLibrary.simpleMessage("开始"),
|
||||||
|
"host": MessageLookupByLibrary.simpleMessage("主机"),
|
||||||
|
"httpFailedWithCode": m1,
|
||||||
|
"import": MessageLookupByLibrary.simpleMessage("导入"),
|
||||||
|
"importAndExport": MessageLookupByLibrary.simpleMessage("导入或导出"),
|
||||||
|
"keyAuth": MessageLookupByLibrary.simpleMessage("公钥认证"),
|
||||||
|
"launchPage": MessageLookupByLibrary.simpleMessage("启动页"),
|
||||||
|
"license": MessageLookupByLibrary.simpleMessage("开源证书"),
|
||||||
|
"loss": MessageLookupByLibrary.simpleMessage("丢包率"),
|
||||||
|
"madeWithLove": m2,
|
||||||
|
"max": MessageLookupByLibrary.simpleMessage("最大"),
|
||||||
|
"min": MessageLookupByLibrary.simpleMessage("最小"),
|
||||||
|
"ms": MessageLookupByLibrary.simpleMessage("毫秒"),
|
||||||
|
"name": MessageLookupByLibrary.simpleMessage("名称"),
|
||||||
|
"noResult": MessageLookupByLibrary.simpleMessage("无结果"),
|
||||||
|
"noSavedPrivateKey": MessageLookupByLibrary.simpleMessage("没有已保存的私钥。"),
|
||||||
|
"noSavedSnippet": MessageLookupByLibrary.simpleMessage("没有已保存的代码片段。"),
|
||||||
|
"noServerAvailable": MessageLookupByLibrary.simpleMessage("没有可用的服务器。"),
|
||||||
|
"ok": MessageLookupByLibrary.simpleMessage("好"),
|
||||||
|
"ping": MessageLookupByLibrary.simpleMessage("Ping"),
|
||||||
|
"pingAvg": MessageLookupByLibrary.simpleMessage("平均:"),
|
||||||
|
"pingInputIP": MessageLookupByLibrary.simpleMessage("请输入目标IP或域名"),
|
||||||
|
"plzEnterHost": MessageLookupByLibrary.simpleMessage("请输入主机"),
|
||||||
|
"plzEnterPwd": MessageLookupByLibrary.simpleMessage("请输入密码"),
|
||||||
|
"plzSelectKey": MessageLookupByLibrary.simpleMessage("请选择私钥"),
|
||||||
|
"port": MessageLookupByLibrary.simpleMessage("端口"),
|
||||||
|
"privateKey": MessageLookupByLibrary.simpleMessage("私钥"),
|
||||||
|
"pwd": MessageLookupByLibrary.simpleMessage("密码"),
|
||||||
|
"result": MessageLookupByLibrary.simpleMessage("结果"),
|
||||||
|
"run": MessageLookupByLibrary.simpleMessage("运行"),
|
||||||
|
"save": MessageLookupByLibrary.simpleMessage("保存"),
|
||||||
|
"second": MessageLookupByLibrary.simpleMessage("秒"),
|
||||||
|
"server": MessageLookupByLibrary.simpleMessage("服务器"),
|
||||||
|
"serverTabConnecting": MessageLookupByLibrary.simpleMessage("连接中..."),
|
||||||
|
"serverTabEmpty":
|
||||||
|
MessageLookupByLibrary.simpleMessage("现在没有服务器。\n点击右下方按钮来添加。"),
|
||||||
|
"serverTabFailed": MessageLookupByLibrary.simpleMessage("失败"),
|
||||||
|
"serverTabLoading": MessageLookupByLibrary.simpleMessage("加载中..."),
|
||||||
|
"serverTabPlzSave": MessageLookupByLibrary.simpleMessage("请再次保存该私钥"),
|
||||||
|
"serverTabUnkown": MessageLookupByLibrary.simpleMessage("未知状态"),
|
||||||
|
"setting": MessageLookupByLibrary.simpleMessage("设置"),
|
||||||
|
"snippet": MessageLookupByLibrary.simpleMessage("代码片段"),
|
||||||
|
"start": MessageLookupByLibrary.simpleMessage("开始"),
|
||||||
|
"stop": MessageLookupByLibrary.simpleMessage("停止"),
|
||||||
|
"sureToDeleteServer": m3,
|
||||||
|
"ttl": MessageLookupByLibrary.simpleMessage("缓存时间"),
|
||||||
|
"unknown": MessageLookupByLibrary.simpleMessage("未知"),
|
||||||
|
"unkownConvertMode": MessageLookupByLibrary.simpleMessage("未知转换模式"),
|
||||||
|
"updateIntervalEqual0": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"你设置为0,服务器状态不会自动刷新。\n你可以手动下拉刷新。"),
|
||||||
|
"updateServerStatusInterval":
|
||||||
|
MessageLookupByLibrary.simpleMessage("服务器状态刷新间隔"),
|
||||||
|
"upsideDown": MessageLookupByLibrary.simpleMessage("上下交换"),
|
||||||
|
"urlOrJson": MessageLookupByLibrary.simpleMessage("链接或JSON"),
|
||||||
|
"user": MessageLookupByLibrary.simpleMessage("用户"),
|
||||||
|
"versionHaveUpdate": m4,
|
||||||
|
"versionUnknownUpdate": m5,
|
||||||
|
"versionUpdated": m6,
|
||||||
|
"willTakEeffectImmediately":
|
||||||
|
MessageLookupByLibrary.simpleMessage("更改将会立即生效")
|
||||||
|
};
|
||||||
|
}
|
||||||
859
lib/generated/l10n.dart
Normal file
859
lib/generated/l10n.dart
Normal file
@@ -0,0 +1,859 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'intl/messages_all.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// Generator: Flutter Intl IDE plugin
|
||||||
|
// Made by Localizely
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// ignore_for_file: non_constant_identifier_names, lines_longer_than_80_chars
|
||||||
|
// ignore_for_file: join_return_with_assignment, prefer_final_in_for_each
|
||||||
|
// ignore_for_file: avoid_redundant_argument_values, avoid_escaping_inner_quotes
|
||||||
|
|
||||||
|
class S {
|
||||||
|
S();
|
||||||
|
|
||||||
|
static S? _current;
|
||||||
|
|
||||||
|
static S get current {
|
||||||
|
assert(_current != null,
|
||||||
|
'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.');
|
||||||
|
return _current!;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const AppLocalizationDelegate delegate = AppLocalizationDelegate();
|
||||||
|
|
||||||
|
static Future<S> load(Locale locale) {
|
||||||
|
final name = (locale.countryCode?.isEmpty ?? false)
|
||||||
|
? locale.languageCode
|
||||||
|
: locale.toString();
|
||||||
|
final localeName = Intl.canonicalizedLocale(name);
|
||||||
|
return initializeMessages(localeName).then((_) {
|
||||||
|
Intl.defaultLocale = localeName;
|
||||||
|
final instance = S();
|
||||||
|
S._current = instance;
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static S of(BuildContext context) {
|
||||||
|
final instance = S.maybeOf(context);
|
||||||
|
assert(instance != null,
|
||||||
|
'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?');
|
||||||
|
return instance!;
|
||||||
|
}
|
||||||
|
|
||||||
|
static S? maybeOf(BuildContext context) {
|
||||||
|
return Localizations.of<S>(context, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Server`
|
||||||
|
String get server {
|
||||||
|
return Intl.message(
|
||||||
|
'Server',
|
||||||
|
name: 'server',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Convert`
|
||||||
|
String get convert {
|
||||||
|
return Intl.message(
|
||||||
|
'Convert',
|
||||||
|
name: 'convert',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Ping`
|
||||||
|
String get ping {
|
||||||
|
return Intl.message(
|
||||||
|
'Ping',
|
||||||
|
name: 'ping',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Debug`
|
||||||
|
String get debug {
|
||||||
|
return Intl.message(
|
||||||
|
'Debug',
|
||||||
|
name: 'debug',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `add a server`
|
||||||
|
String get addAServer {
|
||||||
|
return Intl.message(
|
||||||
|
'add a server',
|
||||||
|
name: 'addAServer',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Setting`
|
||||||
|
String get setting {
|
||||||
|
return Intl.message(
|
||||||
|
'Setting',
|
||||||
|
name: 'setting',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `License`
|
||||||
|
String get license {
|
||||||
|
return Intl.message(
|
||||||
|
'License',
|
||||||
|
name: 'license',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Snippet`
|
||||||
|
String get snippet {
|
||||||
|
return Intl.message(
|
||||||
|
'Snippet',
|
||||||
|
name: 'snippet',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Private Key`
|
||||||
|
String get privateKey {
|
||||||
|
return Intl.message(
|
||||||
|
'Private Key',
|
||||||
|
name: 'privateKey',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `\nMade with ❤️ by {myGithub}`
|
||||||
|
String madeWithLove(Object myGithub) {
|
||||||
|
return Intl.message(
|
||||||
|
'\nMade with ❤️ by $myGithub',
|
||||||
|
name: 'madeWithLove',
|
||||||
|
desc: '',
|
||||||
|
args: [myGithub],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `\nThanks {rainSunMeGithub} for participating in the test.\n\nAll rights reserved.`
|
||||||
|
String aboutThanks(Object rainSunMeGithub) {
|
||||||
|
return Intl.message(
|
||||||
|
'\nThanks $rainSunMeGithub for participating in the test.\n\nAll rights reserved.',
|
||||||
|
name: 'aboutThanks',
|
||||||
|
desc: '',
|
||||||
|
args: [rainSunMeGithub],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `There is no server.\nClick the fab to add one.`
|
||||||
|
String get serverTabEmpty {
|
||||||
|
return Intl.message(
|
||||||
|
'There is no server.\nClick the fab to add one.',
|
||||||
|
name: 'serverTabEmpty',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Loading...`
|
||||||
|
String get serverTabLoading {
|
||||||
|
return Intl.message(
|
||||||
|
'Loading...',
|
||||||
|
name: 'serverTabLoading',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Please 'save' this private key again.`
|
||||||
|
String get serverTabPlzSave {
|
||||||
|
return Intl.message(
|
||||||
|
'Please \'save\' this private key again.',
|
||||||
|
name: 'serverTabPlzSave',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Failed`
|
||||||
|
String get serverTabFailed {
|
||||||
|
return Intl.message(
|
||||||
|
'Failed',
|
||||||
|
name: 'serverTabFailed',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Unknown state`
|
||||||
|
String get serverTabUnkown {
|
||||||
|
return Intl.message(
|
||||||
|
'Unknown state',
|
||||||
|
name: 'serverTabUnkown',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Connecting...`
|
||||||
|
String get serverTabConnecting {
|
||||||
|
return Intl.message(
|
||||||
|
'Connecting...',
|
||||||
|
name: 'serverTabConnecting',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Decode`
|
||||||
|
String get decode {
|
||||||
|
return Intl.message(
|
||||||
|
'Decode',
|
||||||
|
name: 'decode',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Encode`
|
||||||
|
String get encode {
|
||||||
|
return Intl.message(
|
||||||
|
'Encode',
|
||||||
|
name: 'encode',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Current Mode`
|
||||||
|
String get currentMode {
|
||||||
|
return Intl.message(
|
||||||
|
'Current Mode',
|
||||||
|
name: 'currentMode',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Unknown convert mode`
|
||||||
|
String get unkownConvertMode {
|
||||||
|
return Intl.message(
|
||||||
|
'Unknown convert mode',
|
||||||
|
name: 'unkownConvertMode',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Copy`
|
||||||
|
String get copy {
|
||||||
|
return Intl.message(
|
||||||
|
'Copy',
|
||||||
|
name: 'copy',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Upside Down`
|
||||||
|
String get upsideDown {
|
||||||
|
return Intl.message(
|
||||||
|
'Upside Down',
|
||||||
|
name: 'upsideDown',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Avg:`
|
||||||
|
String get pingAvg {
|
||||||
|
return Intl.message(
|
||||||
|
'Avg:',
|
||||||
|
name: 'pingAvg',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `unknown`
|
||||||
|
String get unknown {
|
||||||
|
return Intl.message(
|
||||||
|
'unknown',
|
||||||
|
name: 'unknown',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `min`
|
||||||
|
String get min {
|
||||||
|
return Intl.message(
|
||||||
|
'min',
|
||||||
|
name: 'min',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `max`
|
||||||
|
String get max {
|
||||||
|
return Intl.message(
|
||||||
|
'max',
|
||||||
|
name: 'max',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `ms`
|
||||||
|
String get ms {
|
||||||
|
return Intl.message(
|
||||||
|
'ms',
|
||||||
|
name: 'ms',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `TTL`
|
||||||
|
String get ttl {
|
||||||
|
return Intl.message(
|
||||||
|
'TTL',
|
||||||
|
name: 'ttl',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Loss`
|
||||||
|
String get loss {
|
||||||
|
return Intl.message(
|
||||||
|
'Loss',
|
||||||
|
name: 'loss',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `No result`
|
||||||
|
String get noResult {
|
||||||
|
return Intl.message(
|
||||||
|
'No result',
|
||||||
|
name: 'noResult',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Please input a target IP/domain.`
|
||||||
|
String get pingInputIP {
|
||||||
|
return Intl.message(
|
||||||
|
'Please input a target IP/domain.',
|
||||||
|
name: 'pingInputIP',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Clear`
|
||||||
|
String get clear {
|
||||||
|
return Intl.message(
|
||||||
|
'Clear',
|
||||||
|
name: 'clear',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Start`
|
||||||
|
String get start {
|
||||||
|
return Intl.message(
|
||||||
|
'Start',
|
||||||
|
name: 'start',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `App primary color`
|
||||||
|
String get appPrimaryColor {
|
||||||
|
return Intl.message(
|
||||||
|
'App primary color',
|
||||||
|
name: 'appPrimaryColor',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Server status update interval`
|
||||||
|
String get updateServerStatusInterval {
|
||||||
|
return Intl.message(
|
||||||
|
'Server status update interval',
|
||||||
|
name: 'updateServerStatusInterval',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Will take effect immediately`
|
||||||
|
String get willTakEeffectImmediately {
|
||||||
|
return Intl.message(
|
||||||
|
'Will take effect immediately',
|
||||||
|
name: 'willTakEeffectImmediately',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Launch page`
|
||||||
|
String get launchPage {
|
||||||
|
return Intl.message(
|
||||||
|
'Launch page',
|
||||||
|
name: 'launchPage',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Current: v1.0.{build}, is up to date`
|
||||||
|
String versionUpdated(Object build) {
|
||||||
|
return Intl.message(
|
||||||
|
'Current: v1.0.$build, is up to date',
|
||||||
|
name: 'versionUpdated',
|
||||||
|
desc: '',
|
||||||
|
args: [build],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Current: v1.0.{build}`
|
||||||
|
String versionUnknownUpdate(Object build) {
|
||||||
|
return Intl.message(
|
||||||
|
'Current: v1.0.$build',
|
||||||
|
name: 'versionUnknownUpdate',
|
||||||
|
desc: '',
|
||||||
|
args: [build],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Found: v1.0.{build}, click to update`
|
||||||
|
String versionHaveUpdate(Object build) {
|
||||||
|
return Intl.message(
|
||||||
|
'Found: v1.0.$build, click to update',
|
||||||
|
name: 'versionHaveUpdate',
|
||||||
|
desc: '',
|
||||||
|
args: [build],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `s`
|
||||||
|
String get second {
|
||||||
|
return Intl.message(
|
||||||
|
's',
|
||||||
|
name: 'second',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `You set to 0, will not update automatically.\nYou can pull to refresh manually.`
|
||||||
|
String get updateIntervalEqual0 {
|
||||||
|
return Intl.message(
|
||||||
|
'You set to 0, will not update automatically.\nYou can pull to refresh manually.',
|
||||||
|
name: 'updateIntervalEqual0',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Edit`
|
||||||
|
String get edit {
|
||||||
|
return Intl.message(
|
||||||
|
'Edit',
|
||||||
|
name: 'edit',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `No saved private keys.`
|
||||||
|
String get noSavedPrivateKey {
|
||||||
|
return Intl.message(
|
||||||
|
'No saved private keys.',
|
||||||
|
name: 'noSavedPrivateKey',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Name`
|
||||||
|
String get name {
|
||||||
|
return Intl.message(
|
||||||
|
'Name',
|
||||||
|
name: 'name',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Password`
|
||||||
|
String get pwd {
|
||||||
|
return Intl.message(
|
||||||
|
'Password',
|
||||||
|
name: 'pwd',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Save`
|
||||||
|
String get save {
|
||||||
|
return Intl.message(
|
||||||
|
'Save',
|
||||||
|
name: 'save',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Delete`
|
||||||
|
String get delete {
|
||||||
|
return Intl.message(
|
||||||
|
'Delete',
|
||||||
|
name: 'delete',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `These fields must not be empty.`
|
||||||
|
String get fieldMustNotEmpty {
|
||||||
|
return Intl.message(
|
||||||
|
'These fields must not be empty.',
|
||||||
|
name: 'fieldMustNotEmpty',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Import and Export`
|
||||||
|
String get importAndExport {
|
||||||
|
return Intl.message(
|
||||||
|
'Import and Export',
|
||||||
|
name: 'importAndExport',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Choose`
|
||||||
|
String get choose {
|
||||||
|
return Intl.message(
|
||||||
|
'Choose',
|
||||||
|
name: 'choose',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Import`
|
||||||
|
String get import {
|
||||||
|
return Intl.message(
|
||||||
|
'Import',
|
||||||
|
name: 'import',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Export`
|
||||||
|
String get export {
|
||||||
|
return Intl.message(
|
||||||
|
'Export',
|
||||||
|
name: 'export',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `OK`
|
||||||
|
String get ok {
|
||||||
|
return Intl.message(
|
||||||
|
'OK',
|
||||||
|
name: 'ok',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Cancel`
|
||||||
|
String get cancel {
|
||||||
|
return Intl.message(
|
||||||
|
'Cancel',
|
||||||
|
name: 'cancel',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `URL or JSON`
|
||||||
|
String get urlOrJson {
|
||||||
|
return Intl.message(
|
||||||
|
'URL or JSON',
|
||||||
|
name: 'urlOrJson',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Go`
|
||||||
|
String get go {
|
||||||
|
return Intl.message(
|
||||||
|
'Go',
|
||||||
|
name: 'go',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `request failed, status code: {code}`
|
||||||
|
String httpFailedWithCode(Object code) {
|
||||||
|
return Intl.message(
|
||||||
|
'request failed, status code: $code',
|
||||||
|
name: 'httpFailedWithCode',
|
||||||
|
desc: '',
|
||||||
|
args: [code],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Run`
|
||||||
|
String get run {
|
||||||
|
return Intl.message(
|
||||||
|
'Run',
|
||||||
|
name: 'run',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `No saved snippets.`
|
||||||
|
String get noSavedSnippet {
|
||||||
|
return Intl.message(
|
||||||
|
'No saved snippets.',
|
||||||
|
name: 'noSavedSnippet',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Choose destination`
|
||||||
|
String get chooseDestination {
|
||||||
|
return Intl.message(
|
||||||
|
'Choose destination',
|
||||||
|
name: 'chooseDestination',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `No server available.`
|
||||||
|
String get noServerAvailable {
|
||||||
|
return Intl.message(
|
||||||
|
'No server available.',
|
||||||
|
name: 'noServerAvailable',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Result`
|
||||||
|
String get result {
|
||||||
|
return Intl.message(
|
||||||
|
'Result',
|
||||||
|
name: 'result',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Close`
|
||||||
|
String get close {
|
||||||
|
return Intl.message(
|
||||||
|
'Close',
|
||||||
|
name: 'close',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Attention`
|
||||||
|
String get attention {
|
||||||
|
return Intl.message(
|
||||||
|
'Attention',
|
||||||
|
name: 'attention',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Are you sure to delete server [{server}]?`
|
||||||
|
String sureToDeleteServer(Object server) {
|
||||||
|
return Intl.message(
|
||||||
|
'Are you sure to delete server [$server]?',
|
||||||
|
name: 'sureToDeleteServer',
|
||||||
|
desc: '',
|
||||||
|
args: [server],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Host`
|
||||||
|
String get host {
|
||||||
|
return Intl.message(
|
||||||
|
'Host',
|
||||||
|
name: 'host',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Port`
|
||||||
|
String get port {
|
||||||
|
return Intl.message(
|
||||||
|
'Port',
|
||||||
|
name: 'port',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `User`
|
||||||
|
String get user {
|
||||||
|
return Intl.message(
|
||||||
|
'User',
|
||||||
|
name: 'user',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Key Auth`
|
||||||
|
String get keyAuth {
|
||||||
|
return Intl.message(
|
||||||
|
'Key Auth',
|
||||||
|
name: 'keyAuth',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Add private key`
|
||||||
|
String get addPrivateKey {
|
||||||
|
return Intl.message(
|
||||||
|
'Add private key',
|
||||||
|
name: 'addPrivateKey',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Choose private key`
|
||||||
|
String get choosePrivateKey {
|
||||||
|
return Intl.message(
|
||||||
|
'Choose private key',
|
||||||
|
name: 'choosePrivateKey',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Please enter host.`
|
||||||
|
String get plzEnterHost {
|
||||||
|
return Intl.message(
|
||||||
|
'Please enter host.',
|
||||||
|
name: 'plzEnterHost',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Please enter password.`
|
||||||
|
String get plzEnterPwd {
|
||||||
|
return Intl.message(
|
||||||
|
'Please enter password.',
|
||||||
|
name: 'plzEnterPwd',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Please select a key.`
|
||||||
|
String get plzSelectKey {
|
||||||
|
return Intl.message(
|
||||||
|
'Please select a key.',
|
||||||
|
name: 'plzSelectKey',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Example name`
|
||||||
|
String get exampleName {
|
||||||
|
return Intl.message(
|
||||||
|
'Example name',
|
||||||
|
name: 'exampleName',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Stop`
|
||||||
|
String get stop {
|
||||||
|
return Intl.message(
|
||||||
|
'Stop',
|
||||||
|
name: 'stop',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||||
|
const AppLocalizationDelegate();
|
||||||
|
|
||||||
|
List<Locale> get supportedLocales {
|
||||||
|
return const <Locale>[
|
||||||
|
Locale.fromSubtags(languageCode: 'en'),
|
||||||
|
Locale.fromSubtags(languageCode: 'zh'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isSupported(Locale locale) => _isSupported(locale);
|
||||||
|
@override
|
||||||
|
Future<S> load(Locale locale) => S.load(locale);
|
||||||
|
@override
|
||||||
|
bool shouldReload(AppLocalizationDelegate old) => false;
|
||||||
|
|
||||||
|
bool _isSupported(Locale locale) {
|
||||||
|
for (var supportedLocale in supportedLocales) {
|
||||||
|
if (supportedLocale.languageCode == locale.languageCode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
80
lib/l10n/intl_en.arb
Normal file
80
lib/l10n/intl_en.arb
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"server": "Server",
|
||||||
|
"convert": "Convert",
|
||||||
|
"ping": "Ping",
|
||||||
|
"debug": "Debug",
|
||||||
|
"addAServer": "add a server",
|
||||||
|
"setting": "Setting",
|
||||||
|
"license": "License",
|
||||||
|
"snippet": "Snippet",
|
||||||
|
"privateKey": "Private Key",
|
||||||
|
"madeWithLove": "\nMade with ❤️ by {myGithub}",
|
||||||
|
"aboutThanks": "\nThanks {rainSunMeGithub} for participating in the test.\n\nAll rights reserved.",
|
||||||
|
"serverTabEmpty": "There is no server.\nClick the fab to add one.",
|
||||||
|
"serverTabLoading": "Loading...",
|
||||||
|
"serverTabPlzSave": "Please 'save' this private key again.",
|
||||||
|
"serverTabFailed": "Failed",
|
||||||
|
"serverTabUnkown": "Unknown state",
|
||||||
|
"serverTabConnecting": "Connecting...",
|
||||||
|
"decode": "Decode",
|
||||||
|
"encode": "Encode",
|
||||||
|
"currentMode": "Current Mode",
|
||||||
|
"unkownConvertMode": "Unknown convert mode",
|
||||||
|
"copy": "Copy",
|
||||||
|
"upsideDown": "Upside Down",
|
||||||
|
"pingAvg": "Avg:",
|
||||||
|
"unknown": "unknown",
|
||||||
|
"min": "min",
|
||||||
|
"max": "max",
|
||||||
|
"ms": "ms",
|
||||||
|
"ttl": "TTL",
|
||||||
|
"loss": "Loss",
|
||||||
|
"noResult": "No result",
|
||||||
|
"pingInputIP": "Please input a target IP/domain.",
|
||||||
|
"clear": "Clear",
|
||||||
|
"start": "Start",
|
||||||
|
"appPrimaryColor": "App primary color",
|
||||||
|
"updateServerStatusInterval": "Server status update interval",
|
||||||
|
"willTakEeffectImmediately": "Will take effect immediately",
|
||||||
|
"launchPage": "Launch page",
|
||||||
|
"versionUpdated": "Current: v1.0.{build}, is up to date",
|
||||||
|
"versionUnknownUpdate": "Current: v1.0.{build}",
|
||||||
|
"versionHaveUpdate": "Found: v1.0.{build}, click to update",
|
||||||
|
"second": "s",
|
||||||
|
"updateIntervalEqual0": "You set to 0, will not update automatically.\nYou can pull to refresh manually.",
|
||||||
|
"edit": "Edit",
|
||||||
|
"noSavedPrivateKey": "No saved private keys.",
|
||||||
|
"name": "Name",
|
||||||
|
"pwd": "Password",
|
||||||
|
"save": "Save",
|
||||||
|
"delete": "Delete",
|
||||||
|
"fieldMustNotEmpty": "These fields must not be empty.",
|
||||||
|
"importAndExport": "Import and Export",
|
||||||
|
"choose": "Choose",
|
||||||
|
"import": "Import",
|
||||||
|
"export": "Export",
|
||||||
|
"ok": "OK",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"urlOrJson": "URL or JSON",
|
||||||
|
"go": "Go",
|
||||||
|
"httpFailedWithCode": "request failed, status code: {code}",
|
||||||
|
"run": "Run",
|
||||||
|
"noSavedSnippet": "No saved snippets.",
|
||||||
|
"chooseDestination": "Choose destination",
|
||||||
|
"noServerAvailable": "No server available.",
|
||||||
|
"result": "Result",
|
||||||
|
"close": "Close",
|
||||||
|
"attention": "Attention",
|
||||||
|
"sureToDeleteServer": "Are you sure to delete server [{server}]?",
|
||||||
|
"host": "Host",
|
||||||
|
"port": "Port",
|
||||||
|
"user": "User",
|
||||||
|
"keyAuth": "Key Auth",
|
||||||
|
"addPrivateKey": "Add private key",
|
||||||
|
"choosePrivateKey": "Choose private key",
|
||||||
|
"plzEnterHost": "Please enter host.",
|
||||||
|
"plzEnterPwd": "Please enter password.",
|
||||||
|
"plzSelectKey": "Please select a key.",
|
||||||
|
"exampleName": "Example name",
|
||||||
|
"stop": "Stop"
|
||||||
|
}
|
||||||
80
lib/l10n/intl_zh.arb
Normal file
80
lib/l10n/intl_zh.arb
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"server": "服务器",
|
||||||
|
"convert": "转换",
|
||||||
|
"ping": "Ping",
|
||||||
|
"debug": "调试",
|
||||||
|
"addAServer": "添加服务器",
|
||||||
|
"setting": "设置",
|
||||||
|
"license": "开源证书",
|
||||||
|
"snippet": "代码片段",
|
||||||
|
"privateKey": "私钥",
|
||||||
|
"madeWithLove": "\n用❤️制作 by {myGithub}",
|
||||||
|
"aboutThanks": "\n感谢 {rainSunMeGithub} 参与软件测试。\n\n保留所有权利。",
|
||||||
|
"serverTabEmpty": "现在没有服务器。\n点击右下方按钮来添加。",
|
||||||
|
"serverTabLoading": "加载中...",
|
||||||
|
"serverTabPlzSave": "请再次保存该私钥",
|
||||||
|
"serverTabFailed": "失败",
|
||||||
|
"serverTabUnkown": "未知状态",
|
||||||
|
"serverTabConnecting": "连接中...",
|
||||||
|
"decode": "解码",
|
||||||
|
"encode": "编码",
|
||||||
|
"currentMode": "当前模式",
|
||||||
|
"unkownConvertMode": "未知转换模式",
|
||||||
|
"copy": "复制到剪切板",
|
||||||
|
"upsideDown": "上下交换",
|
||||||
|
"pingAvg": "平均:",
|
||||||
|
"unknown": "未知",
|
||||||
|
"min": "最小",
|
||||||
|
"max": "最大",
|
||||||
|
"ms": "毫秒",
|
||||||
|
"ttl": "缓存时间",
|
||||||
|
"loss": "丢包率",
|
||||||
|
"noResult": "无结果",
|
||||||
|
"pingInputIP": "请输入目标IP或域名",
|
||||||
|
"clear": "清除",
|
||||||
|
"start": "开始",
|
||||||
|
"appPrimaryColor": "App主要色",
|
||||||
|
"updateServerStatusInterval": "服务器状态刷新间隔",
|
||||||
|
"willTakEeffectImmediately": "更改将会立即生效",
|
||||||
|
"launchPage": "启动页",
|
||||||
|
"versionUpdated": "当前:v1.0.{build}, 已是最新版本",
|
||||||
|
"versionUnknownUpdate": "当前:v1.0.{build}",
|
||||||
|
"versionHaveUpdate": "找到新版本:v1.0.{build}, 点击更新",
|
||||||
|
"second": "秒",
|
||||||
|
"updateIntervalEqual0": "你设置为0,服务器状态不会自动刷新。\n你可以手动下拉刷新。",
|
||||||
|
"edit": "编辑",
|
||||||
|
"noSavedPrivateKey": "没有已保存的私钥。",
|
||||||
|
"name": "名称",
|
||||||
|
"pwd": "密码",
|
||||||
|
"save": "保存",
|
||||||
|
"delete": "删除",
|
||||||
|
"fieldMustNotEmpty": "这些输入框不能为空。",
|
||||||
|
"importAndExport": "导入或导出",
|
||||||
|
"choose": "选择",
|
||||||
|
"import": "导入",
|
||||||
|
"export": "导出",
|
||||||
|
"ok": "好",
|
||||||
|
"cancel": "取消",
|
||||||
|
"urlOrJson": "链接或JSON",
|
||||||
|
"go": "开始",
|
||||||
|
"httpFailedWithCode": "请求失败, 状态码: {code}",
|
||||||
|
"run": "运行",
|
||||||
|
"noSavedSnippet": "没有已保存的代码片段。",
|
||||||
|
"chooseDestination": "选择目标",
|
||||||
|
"noServerAvailable": "没有可用的服务器。",
|
||||||
|
"result": "结果",
|
||||||
|
"close": "关闭",
|
||||||
|
"attention": "注意",
|
||||||
|
"sureToDeleteServer": "你确定要删除服务器 [{server}] 吗?",
|
||||||
|
"host": "主机",
|
||||||
|
"port": "端口",
|
||||||
|
"user": "用户",
|
||||||
|
"keyAuth": "公钥认证",
|
||||||
|
"addPrivateKey": "添加一个私钥",
|
||||||
|
"choosePrivateKey": "选择私钥",
|
||||||
|
"plzEnterHost": "请输入主机",
|
||||||
|
"plzEnterPwd": "请输入密码",
|
||||||
|
"plzSelectKey": "请选择私钥",
|
||||||
|
"exampleName": "名称示例",
|
||||||
|
"stop": "停止"
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import 'package:clipboard/clipboard.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:toolbox/core/utils.dart';
|
import 'package:toolbox/core/utils.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
|
|
||||||
@@ -20,13 +21,8 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
late TextEditingController _textEditingControllerResult;
|
late TextEditingController _textEditingControllerResult;
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
late ThemeData _theme;
|
late ThemeData _theme;
|
||||||
|
late S s;
|
||||||
|
|
||||||
static const List<String> _typeOption = [
|
|
||||||
'base64 decode',
|
|
||||||
'base64 encode',
|
|
||||||
'URL encode',
|
|
||||||
'URL decode'
|
|
||||||
];
|
|
||||||
int _typeOptionIndex = 0;
|
int _typeOptionIndex = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -41,6 +37,7 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_theme = Theme.of(context);
|
_theme = Theme.of(context);
|
||||||
|
s = S.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -67,7 +64,7 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
showSnackBar(context, Text('Error: \n$e'));
|
showSnackBar(context, Text('Error: \n$e'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tooltip: 'convert',
|
tooltip: s.convert,
|
||||||
child: const Icon(Icons.send),
|
child: const Icon(Icons.send),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -85,7 +82,7 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
case 3:
|
case 3:
|
||||||
return Uri.decodeFull(text);
|
return Uri.decodeFull(text);
|
||||||
default:
|
default:
|
||||||
return 'Unknown Convert Method';
|
return s.unkownConvertMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +94,14 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTypeOption() {
|
Widget _buildTypeOption() {
|
||||||
|
final decode = s.decode;
|
||||||
|
final encode = s.encode;
|
||||||
|
final List<String> _typeOption = [
|
||||||
|
'Base64 $decode',
|
||||||
|
'Base64 $encode',
|
||||||
|
'URL $encode',
|
||||||
|
'URL $decode'
|
||||||
|
];
|
||||||
return RoundRectCard(
|
return RoundRectCard(
|
||||||
ExpansionTile(
|
ExpansionTile(
|
||||||
tilePadding: const EdgeInsets.only(left: 7, right: 27),
|
tilePadding: const EdgeInsets.only(left: 7, right: 27),
|
||||||
@@ -106,7 +111,7 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
TextButton(
|
TextButton(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||||
child: const Icon(Icons.change_circle),
|
child: Icon(Icons.change_circle, semanticLabel: s.upsideDown),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final temp = _textEditingController.text;
|
final temp = _textEditingController.text;
|
||||||
_textEditingController.text = _textEditingControllerResult.text;
|
_textEditingController.text = _textEditingControllerResult.text;
|
||||||
@@ -116,7 +121,7 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
TextButton(
|
TextButton(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||||
child: const Icon(Icons.copy),
|
child: Icon(Icons.copy, semanticLabel: s.copy),
|
||||||
onPressed: () => FlutterClipboard.copy(
|
onPressed: () => FlutterClipboard.copy(
|
||||||
_textEditingControllerResult.text == ''
|
_textEditingControllerResult.text == ''
|
||||||
? ' '
|
? ' '
|
||||||
@@ -137,11 +142,11 @@ class _ConvertPageState extends State<ConvertPage>
|
|||||||
fontSize: 16.0,
|
fontSize: 16.0,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: primaryColor)),
|
color: primaryColor)),
|
||||||
const Text(
|
Text(
|
||||||
'Current Mode',
|
s.currentMode,
|
||||||
textScaleFactor: 1.0,
|
textScaleFactor: 1.0,
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
style: TextStyle(fontSize: 9.0, color: Colors.grey),
|
style: const TextStyle(fontSize: 9.0, color: Colors.grey),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ import 'package:toolbox/data/model/app/navigation_item.dart';
|
|||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/res/build_data.dart';
|
import 'package:toolbox/data/res/build_data.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
import 'package:toolbox/data/res/icon/common.dart';
|
import 'package:toolbox/data/res/icon/common.dart';
|
||||||
import 'package:toolbox/data/res/tab.dart';
|
import 'package:toolbox/data/res/tab.dart';
|
||||||
import 'package:toolbox/data/res/url.dart';
|
import 'package:toolbox/data/res/url.dart';
|
||||||
import 'package:toolbox/data/store/setting.dart';
|
import 'package:toolbox/data/store/setting.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/page/convert.dart';
|
import 'package:toolbox/view/page/convert.dart';
|
||||||
import 'package:toolbox/view/page/debug.dart';
|
import 'package:toolbox/view/page/debug.dart';
|
||||||
@@ -44,6 +46,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
late final AdvancedDrawerController _advancedDrawerController;
|
late final AdvancedDrawerController _advancedDrawerController;
|
||||||
late int _selectIndex;
|
late int _selectIndex;
|
||||||
late double _width;
|
late double _width;
|
||||||
|
late S s;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -58,6 +61,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
s = S.of(context);
|
||||||
_width = MediaQuery.of(context).size.width;
|
_width = MediaQuery.of(context).size.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,11 +119,11 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
drawer: _buildDrawer(),
|
drawer: _buildDrawer(),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(tabItems[_selectIndex].title),
|
title: Text(tabTitleName(context, _selectIndex), style: size18),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.developer_mode, size: 23),
|
icon: const Icon(Icons.developer_mode, size: 23),
|
||||||
tooltip: 'Debug',
|
tooltip: s.debug,
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
AppRoute(const DebugPage(), 'Debug Page').go(context),
|
AppRoute(const DebugPage(), 'Debug Page').go(context),
|
||||||
),
|
),
|
||||||
@@ -171,7 +175,7 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
borderRadius: const BorderRadius.all(Radius.circular(50))),
|
borderRadius: const BorderRadius.all(Radius.circular(50))),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(item.icon),
|
icon: Icon(item.icon),
|
||||||
tooltip: item.title,
|
tooltip: tabTitleName(context, idx),
|
||||||
splashRadius: width / 3.3,
|
splashRadius: width / 3.3,
|
||||||
padding: const EdgeInsets.only(left: 17, right: 17),
|
padding: const EdgeInsets.only(left: 17, right: 17),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -218,36 +222,35 @@ class _MyHomePageState extends State<MyHomePage>
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.settings),
|
leading: const Icon(Icons.settings),
|
||||||
title: const Text('Setting'),
|
title: Text(s.setting),
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
AppRoute(const SettingPage(), 'Setting').go(context),
|
AppRoute(const SettingPage(), 'Setting').go(context),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.vpn_key),
|
leading: const Icon(Icons.vpn_key),
|
||||||
title: const Text('Private Key'),
|
title: Text(s.privateKey),
|
||||||
onTap: () => AppRoute(
|
onTap: () => AppRoute(
|
||||||
const StoredPrivateKeysPage(), 'private key list')
|
const StoredPrivateKeysPage(), 'private key list')
|
||||||
.go(context),
|
.go(context),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.snippet_folder),
|
leading: const Icon(Icons.snippet_folder),
|
||||||
title: const Text('Snippet'),
|
title: Text(s.snippet),
|
||||||
onTap: () => AppRoute(const SnippetListPage(), 'snippet list')
|
onTap: () => AppRoute(const SnippetListPage(), 'snippet list')
|
||||||
.go(context),
|
.go(context),
|
||||||
),
|
),
|
||||||
AboutListTile(
|
AboutListTile(
|
||||||
icon: const Icon(Icons.text_snippet),
|
icon: const Icon(Icons.text_snippet),
|
||||||
child: const Text('Licences'),
|
child: Text(s.license),
|
||||||
applicationName: BuildData.name,
|
applicationName: BuildData.name,
|
||||||
applicationVersion: _buildVersionStr(),
|
applicationVersion: _buildVersionStr(),
|
||||||
applicationIcon: _buildIcon(),
|
applicationIcon: _buildIcon(),
|
||||||
aboutBoxChildren: const [
|
aboutBoxChildren: [
|
||||||
UrlText(
|
UrlText(
|
||||||
text: '\nMade with ❤️ by $myGithub',
|
text: s.madeWithLove(myGithub),
|
||||||
replace: 'LollipopKit'),
|
replace: 'LollipopKit'),
|
||||||
UrlText(
|
UrlText(
|
||||||
text:
|
text: s.aboutThanks(rainSunMeGithub),
|
||||||
'\nThanks $rainSunMeGithub for participating in the test.\n\nAll rights reserved.',
|
|
||||||
replace: 'RainSunMe',
|
replace: 'RainSunMe',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:toolbox/core/utils.dart';
|
|||||||
import 'package:toolbox/data/model/server/ping_result.dart';
|
import 'package:toolbox/data/model/server/ping_result.dart';
|
||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
@@ -20,6 +21,10 @@ class _PingPageState extends State<PingPage>
|
|||||||
late TextEditingController _textEditingController;
|
late TextEditingController _textEditingController;
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
final List<PingResult> _results = [];
|
final List<PingResult> _results = [];
|
||||||
|
late S s;
|
||||||
|
static const summaryTextStyle = TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -31,6 +36,7 @@ class _PingPageState extends State<PingPage>
|
|||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
|
s = S.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -62,37 +68,39 @@ class _PingPageState extends State<PingPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildResultItem(PingResult result) {
|
Widget _buildResultItem(PingResult result) {
|
||||||
|
final unknown = s.unknown;
|
||||||
|
final ms = s.ms;
|
||||||
return RoundRectCard(ListTile(
|
return RoundRectCard(ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||||
title: Text(result.serverName,
|
title: Text(result.serverName,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18, fontWeight: FontWeight.bold, color: primaryColor)),
|
fontSize: 18, fontWeight: FontWeight.bold, color: primaryColor)),
|
||||||
subtitle: Text(_buildPingSummary(result)),
|
subtitle: Text(_buildPingSummary(result, unknown, ms), style: summaryTextStyle,),
|
||||||
trailing: Text(
|
trailing: Text(
|
||||||
'Avg: ' +
|
s.pingAvg +
|
||||||
(result.statistic?.avg?.toStringAsFixed(2) ?? 'unkown') +
|
(result.statistic?.avg?.toStringAsFixed(2) ?? s.unknown) +
|
||||||
' ms',
|
' $ms',
|
||||||
style: TextStyle(fontSize: 14, color: primaryColor)),
|
style: TextStyle(fontSize: 14, color: primaryColor)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
String _buildPingSummary(PingResult result) {
|
String _buildPingSummary(PingResult result, String unknown, String ms) {
|
||||||
final ip = result.ip ?? 'unkown';
|
final ip = result.ip ?? unknown;
|
||||||
if (result.results == null || result.results!.isEmpty) {
|
if (result.results == null || result.results!.isEmpty) {
|
||||||
return '$ip - no results';
|
return '$ip - ${s.noResult}';
|
||||||
}
|
}
|
||||||
final ttl = result.results?.first.ttl ?? 'unkown';
|
final ttl = result.results?.first.ttl ?? unknown;
|
||||||
final loss = result.statistic?.loss ?? 'unkown';
|
final loss = result.statistic?.loss ?? unknown;
|
||||||
final min = result.statistic?.min ?? 'unkown';
|
final min = result.statistic?.min ?? unknown;
|
||||||
final max = result.statistic?.max ?? 'unkown';
|
final max = result.statistic?.max ?? unknown;
|
||||||
return '$ip\nttl: $ttl, loss: $loss%\nmin: $min ms, max: $max ms';
|
return '$ip\n${s.ttl}: $ttl, ${s.loss}: $loss%\n${s.min}: $min $ms, ${s.max}: $max $ms';
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> doPing() async {
|
Future<void> doPing() async {
|
||||||
_results.clear();
|
_results.clear();
|
||||||
final target = _textEditingController.text.trim();
|
final target = _textEditingController.text.trim();
|
||||||
if (target.isEmpty) {
|
if (target.isEmpty) {
|
||||||
showSnackBar(context, const Text('Please input a target'));
|
showSnackBar(context, Text(s.pingInputIP));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,12 +127,12 @@ class _PingPageState extends State<PingPage>
|
|||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: const [
|
children: [
|
||||||
Icon(Icons.delete),
|
const Icon(Icons.delete),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 7,
|
width: 7,
|
||||||
),
|
),
|
||||||
Text('Clear')
|
Text(s.clear)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -136,12 +144,12 @@ class _PingPageState extends State<PingPage>
|
|||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
foregroundColor: MaterialStateProperty.all(primaryColor)),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: const [
|
children: [
|
||||||
Icon(Icons.play_arrow),
|
const Icon(Icons.play_arrow),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 7,
|
width: 7,
|
||||||
),
|
),
|
||||||
Text('Start')
|
Text(s.start)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:toolbox/core/utils.dart';
|
import 'package:toolbox/core/utils.dart';
|
||||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||||
import 'package:toolbox/data/provider/private_key.dart';
|
import 'package:toolbox/data/provider/private_key.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/widget/input_decoration.dart';
|
import 'package:toolbox/view/widget/input_decoration.dart';
|
||||||
|
|
||||||
@@ -25,6 +27,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
|
|
||||||
late PrivateKeyProvider _provider;
|
late PrivateKeyProvider _provider;
|
||||||
late Widget loading;
|
late Widget loading;
|
||||||
|
late S s;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -33,12 +36,19 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
loading = const SizedBox();
|
loading = const SizedBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
s = S.of(context);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('Edit'), actions: [
|
appBar: AppBar(title: Text(s.edit, style: size18), actions: [
|
||||||
widget.info != null
|
widget.info != null
|
||||||
? IconButton(
|
? IconButton(
|
||||||
|
tooltip: s.delete,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_provider.delInfo(widget.info!);
|
_provider.delInfo(widget.info!);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@@ -52,7 +62,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
TextField(
|
TextField(
|
||||||
controller: nameController,
|
controller: nameController,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
decoration: buildDecoration('Name', icon: Icons.info),
|
decoration: buildDecoration(s.name, icon: Icons.info),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: keyController,
|
controller: keyController,
|
||||||
@@ -61,14 +71,14 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
maxLines: 10,
|
maxLines: 10,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
enableSuggestions: false,
|
enableSuggestions: false,
|
||||||
decoration: buildDecoration('Private Key', icon: Icons.vpn_key),
|
decoration: buildDecoration(s.privateKey, icon: Icons.vpn_key),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: pwdController,
|
controller: pwdController,
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: buildDecoration('Password', icon: Icons.password),
|
decoration: buildDecoration(s.pwd, icon: Icons.password),
|
||||||
),
|
),
|
||||||
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
||||||
loading
|
loading
|
||||||
@@ -76,13 +86,14 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
child: const Icon(Icons.save),
|
child: const Icon(Icons.save),
|
||||||
|
tooltip: s.save,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final name = nameController.text;
|
final name = nameController.text;
|
||||||
final key = keyController.text;
|
final key = keyController.text;
|
||||||
final pwd = pwdController.text;
|
final pwd = pwdController.text;
|
||||||
if (name.isEmpty || key.isEmpty) {
|
if (name.isEmpty || key.isEmpty) {
|
||||||
showSnackBar(
|
showSnackBar(
|
||||||
context, const Text('Name and Key must not be empty.'));
|
context, Text(s.fieldMustNotEmpty));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:toolbox/core/route.dart';
|
import 'package:toolbox/core/route.dart';
|
||||||
import 'package:toolbox/data/provider/private_key.dart';
|
import 'package:toolbox/data/provider/private_key.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
import 'package:toolbox/data/res/padding.dart';
|
import 'package:toolbox/data/res/padding.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/view/page/private_key/edit.dart';
|
import 'package:toolbox/view/page/private_key/edit.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
|
|
||||||
@@ -16,11 +18,19 @@ class StoredPrivateKeysPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _PrivateKeyListState extends State<StoredPrivateKeysPage> {
|
class _PrivateKeyListState extends State<StoredPrivateKeysPage> {
|
||||||
final _textStyle = TextStyle(color: primaryColor);
|
final _textStyle = TextStyle(color: primaryColor);
|
||||||
|
late S s;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
s = S.of(context);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Private Keys'),
|
title: Text(s.privateKey, style: size18),
|
||||||
),
|
),
|
||||||
body: Consumer<PrivateKeyProvider>(
|
body: Consumer<PrivateKeyProvider>(
|
||||||
builder: (_, key, __) {
|
builder: (_, key, __) {
|
||||||
@@ -46,14 +56,14 @@ class _PrivateKeyListState extends State<StoredPrivateKeysPage> {
|
|||||||
'private key edit page')
|
'private key edit page')
|
||||||
.go(context),
|
.go(context),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Edit',
|
s.edit,
|
||||||
style: _textStyle,
|
style: _textStyle,
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
})
|
})
|
||||||
: const Center(child: Text('No saved private keys.'));
|
: Center(child: Text(s.noSavedPrivateKey));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:toolbox/data/model/server/server.dart';
|
|||||||
import 'package:toolbox/data/model/server/server_status.dart';
|
import 'package:toolbox/data/model/server/server_status.dart';
|
||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
import 'package:toolbox/data/res/icon/linux_icons.dart';
|
import 'package:toolbox/data/res/icon/linux_icons.dart';
|
||||||
import 'package:toolbox/data/res/padding.dart';
|
import 'package:toolbox/data/res/padding.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
@@ -43,7 +44,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
Widget _buildMainPage(ServerInfo si) {
|
Widget _buildMainPage(ServerInfo si) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(si.info.name),
|
title: Text(si.info.name, style: size18),
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
padding: const EdgeInsets.all(13),
|
padding: const EdgeInsets.all(13),
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import 'package:toolbox/data/model/server/server_private_info.dart';
|
|||||||
import 'package:toolbox/data/provider/private_key.dart';
|
import 'package:toolbox/data/provider/private_key.dart';
|
||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
import 'package:toolbox/data/store/private_key.dart';
|
import 'package:toolbox/data/store/private_key.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/page/private_key/edit.dart';
|
import 'package:toolbox/view/page/private_key/edit.dart';
|
||||||
import 'package:toolbox/view/widget/input_decoration.dart';
|
import 'package:toolbox/view/widget/input_decoration.dart';
|
||||||
@@ -32,6 +34,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
|
|
||||||
late ServerProvider _serverProvider;
|
late ServerProvider _serverProvider;
|
||||||
|
|
||||||
|
late S s;
|
||||||
|
|
||||||
bool usePublicKey = false;
|
bool usePublicKey = false;
|
||||||
|
|
||||||
int _pubKeyIndex = -1;
|
int _pubKeyIndex = -1;
|
||||||
@@ -43,10 +47,16 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
_serverProvider = locator<ServerProvider>();
|
_serverProvider = locator<ServerProvider>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
s = S.of(context);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('Edit'), actions: [
|
appBar: AppBar(title: Text(s.edit, style: size18), actions: [
|
||||||
widget.spi != null
|
widget.spi != null
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -54,7 +64,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
context,
|
context,
|
||||||
'Attention',
|
'Attention',
|
||||||
Text(
|
Text(
|
||||||
'Are you sure to delete server [${widget.spi!.name}]'),
|
s.sureToDeleteServer(widget.spi!.name)),
|
||||||
[
|
[
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -62,13 +72,13 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: Text(
|
||||||
'Yes',
|
s.ok,
|
||||||
style: TextStyle(color: Colors.red),
|
style: const TextStyle(color: Colors.red),
|
||||||
)),
|
)),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: const Text('No'))
|
child: Text(s.cancel))
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.delete))
|
icon: const Icon(Icons.delete))
|
||||||
@@ -84,20 +94,20 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
controller: nameController,
|
controller: nameController,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
decoration:
|
decoration:
|
||||||
buildDecoration('Name', icon: Icons.info, hint: 'Example'),
|
buildDecoration(s.name, icon: Icons.info, hint: s.exampleName),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: ipController,
|
controller: ipController,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
enableSuggestions: false,
|
enableSuggestions: false,
|
||||||
decoration: buildDecoration('Host',
|
decoration: buildDecoration(s.host,
|
||||||
icon: Icons.storage, hint: 'example.com'),
|
icon: Icons.storage, hint: 'example.com'),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: portController,
|
controller: portController,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
decoration: buildDecoration('Port',
|
decoration: buildDecoration(s.port,
|
||||||
icon: Icons.format_list_numbered, hint: '22'),
|
icon: Icons.format_list_numbered, hint: '22'),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
@@ -105,13 +115,13 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
enableSuggestions: false,
|
enableSuggestions: false,
|
||||||
decoration: buildDecoration('User',
|
decoration: buildDecoration(s.user,
|
||||||
icon: Icons.account_box, hint: 'root'),
|
icon: Icons.account_box, hint: 'root'),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 7),
|
const SizedBox(height: 7),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Text('Key Auth'),
|
Text(s.keyAuth),
|
||||||
Switch(
|
Switch(
|
||||||
value: usePublicKey,
|
value: usePublicKey,
|
||||||
onChanged: (val) => setState(() => usePublicKey = val)),
|
onChanged: (val) => setState(() => usePublicKey = val)),
|
||||||
@@ -122,8 +132,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
controller: passwordController,
|
controller: passwordController,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
decoration: buildDecoration('Pwd',
|
decoration: buildDecoration(s.pwd,
|
||||||
icon: Icons.password, hint: 'Password'),
|
icon: Icons.password, hint: s.pwd),
|
||||||
onSubmitted: (_) => {},
|
onSubmitted: (_) => {},
|
||||||
)
|
)
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
@@ -143,7 +153,7 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
tiles.add(ListTile(
|
tiles.add(ListTile(
|
||||||
title: const Text('Add a Private Key'),
|
title: Text(s.addPrivateKey),
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
@@ -157,9 +167,9 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
iconColor: primaryColor,
|
iconColor: primaryColor,
|
||||||
tilePadding: EdgeInsets.zero,
|
tilePadding: EdgeInsets.zero,
|
||||||
childrenPadding: EdgeInsets.zero,
|
childrenPadding: EdgeInsets.zero,
|
||||||
title: const Text(
|
title: Text(
|
||||||
'Choose Key',
|
s.choosePrivateKey,
|
||||||
style: TextStyle(fontSize: 14),
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
children: tiles,
|
children: tiles,
|
||||||
);
|
);
|
||||||
@@ -172,15 +182,15 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
|||||||
child: const Icon(Icons.send),
|
child: const Icon(Icons.send),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (ipController.text == '') {
|
if (ipController.text == '') {
|
||||||
showSnackBar(context, const Text('Please enter host.'));
|
showSnackBar(context, Text(s.plzEnterHost));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!usePublicKey && passwordController.text == '') {
|
if (!usePublicKey && passwordController.text == '') {
|
||||||
showSnackBar(context, const Text('Please enter password.'));
|
showSnackBar(context, Text(s.plzEnterPwd));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (usePublicKey && _pubKeyIndex == -1) {
|
if (usePublicKey && _pubKeyIndex == -1) {
|
||||||
showSnackBar(context, const Text('Please select a private key.'));
|
showSnackBar(context, Text(s.plzSelectKey));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (usernameController.text == '') {
|
if (usernameController.text == '') {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import 'package:toolbox/data/model/server/server_status.dart';
|
|||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
import 'package:toolbox/data/store/setting.dart';
|
import 'package:toolbox/data/store/setting.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/page/apt.dart';
|
import 'package:toolbox/view/page/apt.dart';
|
||||||
import 'package:toolbox/view/page/docker.dart';
|
import 'package:toolbox/view/page/docker.dart';
|
||||||
@@ -39,6 +40,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
late RefreshController _refreshController;
|
late RefreshController _refreshController;
|
||||||
|
|
||||||
late ServerProvider _serverProvider;
|
late ServerProvider _serverProvider;
|
||||||
|
late S s;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -53,6 +55,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_theme = Theme.of(context);
|
_theme = Theme.of(context);
|
||||||
_primaryColor = primaryColor;
|
_primaryColor = primaryColor;
|
||||||
|
s = S.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -62,9 +65,9 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
locator<SettingStore>().serverStatusUpdateInterval.fetch() != 0;
|
locator<SettingStore>().serverStatusUpdateInterval.fetch() != 0;
|
||||||
final child = Consumer<ServerProvider>(builder: (_, pro, __) {
|
final child = Consumer<ServerProvider>(builder: (_, pro, __) {
|
||||||
if (pro.servers.isEmpty) {
|
if (pro.servers.isEmpty) {
|
||||||
return const Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'There is no server.\nClick the fab to add one.',
|
s.serverTabEmpty,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -99,7 +102,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
AppRoute(const ServerEditPage(), 'Add server info page')
|
AppRoute(const ServerEditPage(), 'Add server info page')
|
||||||
.go(context),
|
.go(context),
|
||||||
tooltip: 'add a server',
|
tooltip: s.addAServer,
|
||||||
heroTag: 'server page fab',
|
heroTag: 'server page fab',
|
||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
),
|
),
|
||||||
@@ -302,7 +305,7 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
case ServerConnectionState.connected:
|
case ServerConnectionState.connected:
|
||||||
if (temp == '') {
|
if (temp == '') {
|
||||||
if (upTime == '') {
|
if (upTime == '') {
|
||||||
return 'Loading...';
|
return s.serverTabLoading;
|
||||||
} else {
|
} else {
|
||||||
return upTime;
|
return upTime;
|
||||||
}
|
}
|
||||||
@@ -314,17 +317,17 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ServerConnectionState.connecting:
|
case ServerConnectionState.connecting:
|
||||||
return 'Connecting...';
|
return s.serverTabConnecting;
|
||||||
case ServerConnectionState.failed:
|
case ServerConnectionState.failed:
|
||||||
if (failedInfo == null) {
|
if (failedInfo == null) {
|
||||||
return 'Failed';
|
return s.serverTabFailed;
|
||||||
}
|
}
|
||||||
if (failedInfo.contains('encypted')) {
|
if (failedInfo.contains('encypted')) {
|
||||||
return 'Please "save" this private key again.';
|
return s.serverTabPlzSave;
|
||||||
}
|
}
|
||||||
return failedInfo;
|
return failedInfo;
|
||||||
default:
|
default:
|
||||||
return 'Unknown State';
|
return s.serverTabUnkown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,16 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:toolbox/core/update.dart';
|
import 'package:toolbox/core/update.dart';
|
||||||
|
import 'package:toolbox/core/utils.dart';
|
||||||
import 'package:toolbox/data/provider/app.dart';
|
import 'package:toolbox/data/provider/app.dart';
|
||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/res/build_data.dart';
|
import 'package:toolbox/data/res/build_data.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
import 'package:toolbox/data/res/padding.dart';
|
import 'package:toolbox/data/res/padding.dart';
|
||||||
import 'package:toolbox/data/res/tab.dart';
|
import 'package:toolbox/data/res/tab.dart';
|
||||||
import 'package:toolbox/data/store/setting.dart';
|
import 'package:toolbox/data/store/setting.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
|
|
||||||
@@ -29,6 +32,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
late final ServerProvider _serverProvider;
|
late final ServerProvider _serverProvider;
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
late ThemeData _theme;
|
late ThemeData _theme;
|
||||||
|
late S s;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
@@ -36,6 +40,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
priColor = primaryColor;
|
priColor = primaryColor;
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_theme = Theme.of(context);
|
_theme = Theme.of(context);
|
||||||
|
s = S.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -51,7 +56,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Setting'),
|
title: Text(s.setting, style: size18),
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
padding: const EdgeInsets.all(17),
|
padding: const EdgeInsets.all(17),
|
||||||
@@ -70,12 +75,12 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
String display;
|
String display;
|
||||||
if (app.newestBuild != null) {
|
if (app.newestBuild != null) {
|
||||||
if (app.newestBuild! > BuildData.build) {
|
if (app.newestBuild! > BuildData.build) {
|
||||||
display = 'Found: v1.0.${app.newestBuild}, click to update';
|
display = s.versionHaveUpdate(app.newestBuild!);
|
||||||
} else {
|
} else {
|
||||||
display = 'Current: v1.0.${BuildData.build},is up to date';
|
display = s.versionUpdated(BuildData.build);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
display = 'Current: v1.0.${BuildData.build}';
|
display = s.versionUnknownUpdate(BuildData.build);
|
||||||
}
|
}
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: roundRectCardPadding,
|
contentPadding: roundRectCardPadding,
|
||||||
@@ -94,16 +99,16 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
tilePadding: roundRectCardPadding,
|
tilePadding: roundRectCardPadding,
|
||||||
childrenPadding: roundRectCardPadding,
|
childrenPadding: roundRectCardPadding,
|
||||||
textColor: priColor,
|
textColor: priColor,
|
||||||
title: const Text(
|
title: Text(
|
||||||
'Server status update interval',
|
s.updateServerStatusInterval,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
),
|
),
|
||||||
subtitle: const Text(
|
subtitle: Text(
|
||||||
'Will take effect immediately.',
|
s.willTakEeffectImmediately,
|
||||||
style: TextStyle(color: Colors.grey),
|
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
||||||
),
|
),
|
||||||
trailing: Text('${_intervalValue.toInt()} s'),
|
trailing: Text('${_intervalValue.toInt()} ${s.second}'),
|
||||||
children: [
|
children: [
|
||||||
Slider(
|
Slider(
|
||||||
thumbColor: priColor,
|
thumbColor: priColor,
|
||||||
@@ -120,16 +125,16 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
_store.serverStatusUpdateInterval.put(val.toInt());
|
_store.serverStatusUpdateInterval.put(val.toInt());
|
||||||
_serverProvider.startAutoRefresh();
|
_serverProvider.startAutoRefresh();
|
||||||
},
|
},
|
||||||
label: '${_intervalValue.toInt()} seconds',
|
label: '${_intervalValue.toInt()} ${s.second}',
|
||||||
divisions: 10,
|
divisions: 10,
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 3,
|
height: 3,
|
||||||
),
|
),
|
||||||
_intervalValue == 0.0
|
_intervalValue == 0.0
|
||||||
? const Text(
|
? Text(
|
||||||
'You set to 0, will not update automatically.\nYou can pull to refresh manually.',
|
s.updateIntervalEqual0,
|
||||||
style: TextStyle(color: Colors.grey),
|
style: const TextStyle(color: Colors.grey, fontSize: 12),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
)
|
)
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
@@ -156,8 +161,8 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
width: 27,
|
width: 27,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: const Text(
|
title: Text(
|
||||||
'App primary color',
|
s.appPrimaryColor,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -186,14 +191,14 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
textColor: priColor,
|
textColor: priColor,
|
||||||
tilePadding: roundRectCardPadding,
|
tilePadding: roundRectCardPadding,
|
||||||
childrenPadding: roundRectCardPadding,
|
childrenPadding: roundRectCardPadding,
|
||||||
title: const Text(
|
title: Text(
|
||||||
'Launch page',
|
s.launchPage,
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
),
|
),
|
||||||
trailing: ConstrainedBox(
|
trailing: ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
constraints: BoxConstraints(maxWidth: _media.size.width * 0.35),
|
||||||
child: Text(
|
child: Text(
|
||||||
tabs[_launchPageIdx],
|
tabTitleName(context, _launchPageIdx),
|
||||||
style: textStyle,
|
style: textStyle,
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
),
|
),
|
||||||
@@ -202,7 +207,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
.map((e) => ListTile(
|
.map((e) => ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
title: Text(
|
title: Text(
|
||||||
e,
|
tabTitleName(context, tabs.indexOf(e)),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: _theme.textTheme.bodyText2!.color!.withAlpha(177)),
|
color: _theme.textTheme.bodyText2!.color!.withAlpha(177)),
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:toolbox/core/utils.dart';
|
import 'package:toolbox/core/utils.dart';
|
||||||
import 'package:toolbox/data/model/server/snippet.dart';
|
import 'package:toolbox/data/model/server/snippet.dart';
|
||||||
import 'package:toolbox/data/provider/snippet.dart';
|
import 'package:toolbox/data/provider/snippet.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/widget/input_decoration.dart';
|
import 'package:toolbox/view/widget/input_decoration.dart';
|
||||||
|
|
||||||
@@ -21,23 +23,31 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
final scriptController = TextEditingController();
|
final scriptController = TextEditingController();
|
||||||
|
|
||||||
late SnippetProvider _provider;
|
late SnippetProvider _provider;
|
||||||
|
late S s;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_provider = locator<SnippetProvider>();
|
_provider = locator<SnippetProvider>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
s = S.of(context);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('Edit'), actions: [
|
appBar: AppBar(title: Text(s.edit, style: size18), actions: [
|
||||||
widget.snippet != null
|
widget.snippet != null
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_provider.del(widget.snippet!);
|
_provider.del(widget.snippet!);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
|
tooltip: s.delete,
|
||||||
icon: const Icon(Icons.delete))
|
icon: const Icon(Icons.delete))
|
||||||
: const SizedBox()
|
: const SizedBox()
|
||||||
]),
|
]),
|
||||||
@@ -47,7 +57,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
TextField(
|
TextField(
|
||||||
controller: nameController,
|
controller: nameController,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
decoration: buildDecoration('Name', icon: Icons.info),
|
decoration: buildDecoration(s.name, icon: Icons.info),
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: scriptController,
|
controller: scriptController,
|
||||||
@@ -56,7 +66,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
maxLines: 10,
|
maxLines: 10,
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
enableSuggestions: false,
|
enableSuggestions: false,
|
||||||
decoration: buildDecoration('Snippet', icon: Icons.code),
|
decoration: buildDecoration(s.snippet, icon: Icons.code),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -66,7 +76,7 @@ class _SnippetEditPageState extends State<SnippetEditPage>
|
|||||||
final name = nameController.text;
|
final name = nameController.text;
|
||||||
final script = scriptController.text;
|
final script = scriptController.text;
|
||||||
if (name.isEmpty || script.isEmpty) {
|
if (name.isEmpty || script.isEmpty) {
|
||||||
showSnackBar(context, const Text('Two fields must not be empty.'));
|
showSnackBar(context, Text(s.fieldMustNotEmpty));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final snippet = Snippet(name, script);
|
final snippet = Snippet(name, script);
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import 'package:toolbox/data/model/server/snippet.dart';
|
|||||||
import 'package:toolbox/data/provider/server.dart';
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/provider/snippet.dart';
|
import 'package:toolbox/data/provider/snippet.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/data/res/font_style.dart';
|
||||||
import 'package:toolbox/data/res/padding.dart';
|
import 'package:toolbox/data/res/padding.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/page/snippet/edit.dart';
|
import 'package:toolbox/view/page/snippet/edit.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
@@ -28,14 +30,24 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
final _exportFieldController = TextEditingController();
|
final _exportFieldController = TextEditingController();
|
||||||
|
|
||||||
final _textStyle = TextStyle(color: primaryColor);
|
final _textStyle = TextStyle(color: primaryColor);
|
||||||
|
|
||||||
|
late S s;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
s = S.of(context);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Snippet List'),
|
title: Text(s.snippet, style: size18),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => _showImportExport(),
|
onPressed: () => _showImportExport(),
|
||||||
|
tooltip: s.importAndExport,
|
||||||
icon: const Icon(Icons.import_export)),
|
icon: const Icon(Icons.import_export)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -51,17 +63,17 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
Future<void> _showImportExport() async {
|
Future<void> _showImportExport() async {
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context,
|
||||||
'Choose',
|
s.choose,
|
||||||
Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Import'),
|
title: Text(s.import),
|
||||||
leading: const Icon(Icons.download),
|
leading: const Icon(Icons.download),
|
||||||
onTap: () => _showImportDialog(),
|
onTap: () => _showImportDialog(),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Export'),
|
title: Text(s.export),
|
||||||
leading: const Icon(Icons.file_upload),
|
leading: const Icon(Icons.file_upload),
|
||||||
onTap: () => _showExportDialog(),
|
onTap: () => _showExportDialog(),
|
||||||
),
|
),
|
||||||
@@ -75,7 +87,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
_exportFieldController.text = locator<SnippetProvider>().export;
|
_exportFieldController.text = locator<SnippetProvider>().export;
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context,
|
||||||
'Export',
|
s.export,
|
||||||
TextField(
|
TextField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'JSON',
|
labelText: 'JSON',
|
||||||
@@ -85,7 +97,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
),
|
),
|
||||||
[
|
[
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('OK'),
|
child: Text(s.ok),
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
@@ -95,10 +107,10 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
await showRoundDialog(
|
await showRoundDialog(
|
||||||
context,
|
context,
|
||||||
'Import',
|
s.import,
|
||||||
TextField(
|
TextField(
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Url or JSON',
|
labelText: s.urlOrJson,
|
||||||
),
|
),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
controller: _importFieldController,
|
controller: _importFieldController,
|
||||||
@@ -106,18 +118,18 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
[
|
[
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: const Text('Cancel')),
|
child: Text(s.cancel)),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async =>
|
onPressed: () async =>
|
||||||
await _import(_importFieldController.text.trim()),
|
await _import(_importFieldController.text.trim()),
|
||||||
child: const Text('GO'),
|
child: Text('GO'),
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _import(String text) async {
|
Future<void> _import(String text) async {
|
||||||
if (text.isEmpty) {
|
if (text.isEmpty) {
|
||||||
showSnackBar(context, const Text('field can not be empty'));
|
showSnackBar(context, Text(s.fieldMustNotEmpty));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final snippetProvider = locator<SnippetProvider>();
|
final snippetProvider = locator<SnippetProvider>();
|
||||||
@@ -125,7 +137,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
final resp = await Dio().get(text);
|
final resp = await Dio().get(text);
|
||||||
if (resp.statusCode != 200) {
|
if (resp.statusCode != 200) {
|
||||||
showSnackBar(
|
showSnackBar(
|
||||||
context, Text('request failed, status code: ${resp.statusCode}'));
|
context, Text(s.httpFailedWithCode(resp.statusCode ?? '-1')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (final snippet in getSnippetList(resp.data)) {
|
for (final snippet in getSnippetList(resp.data)) {
|
||||||
@@ -166,7 +178,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
'snippet edit page')
|
'snippet edit page')
|
||||||
.go(context),
|
.go(context),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Edit',
|
s.edit,
|
||||||
style: _textStyle,
|
style: _textStyle,
|
||||||
)),
|
)),
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -179,7 +191,7 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
run(context, snippet);
|
run(context, snippet);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Run',
|
s.run,
|
||||||
style: _textStyle,
|
style: _textStyle,
|
||||||
))
|
))
|
||||||
])
|
])
|
||||||
@@ -187,16 +199,16 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
})
|
})
|
||||||
: const Center(child: Text('No saved snippets.'));
|
: Center(child: Text(s.noSavedSnippet));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showRunDialog(Snippet snippet) {
|
void _showRunDialog(Snippet snippet) {
|
||||||
showRoundDialog(context, 'Choose destination',
|
showRoundDialog(context, s.chooseDestination,
|
||||||
Consumer<ServerProvider>(builder: (_, provider, __) {
|
Consumer<ServerProvider>(builder: (_, provider, __) {
|
||||||
if (provider.servers.isEmpty) {
|
if (provider.servers.isEmpty) {
|
||||||
return const Text('No server available');
|
return Text(s.noServerAvailable);
|
||||||
}
|
}
|
||||||
_selectedIndex = provider.servers.first.info;
|
_selectedIndex = provider.servers.first.info;
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
@@ -235,10 +247,10 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
}), [
|
}), [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async => run(context, snippet),
|
onPressed: () async => run(context, snippet),
|
||||||
child: const Text('Run')),
|
child: Text(s.run)),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: const Text('Cancel')),
|
child: Text(s.cancel)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,11 +258,11 @@ class _SnippetListPageState extends State<SnippetListPage> {
|
|||||||
final result = await locator<ServerProvider>()
|
final result = await locator<ServerProvider>()
|
||||||
.runSnippet(widget.spi ?? _selectedIndex, snippet);
|
.runSnippet(widget.spi ?? _selectedIndex, snippet);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
showRoundDialog(context, 'Result',
|
showRoundDialog(context, s.result,
|
||||||
Text(result, style: const TextStyle(fontSize: 13)), [
|
Text(result, style: const TextStyle(fontSize: 13)), [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
child: const Text('Close'))
|
child: Text(s.close))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
pubspec.lock
12
pubspec.lock
@@ -199,6 +199,11 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.4"
|
||||||
|
flutter_localizations:
|
||||||
|
dependency: "direct main"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
flutter_material_color_picker:
|
flutter_material_color_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -279,6 +284,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
|
intl:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: intl
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.17.0"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
27
pubspec.yaml
27
pubspec.yaml
@@ -29,7 +29,8 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_localizations:
|
||||||
|
sdk: flutter
|
||||||
provider: ^6.0.0
|
provider: ^6.0.0
|
||||||
get_it: ^7.2.0
|
get_it: ^7.2.0
|
||||||
hive: ^2.0.0
|
hive: ^2.0.0
|
||||||
@@ -39,14 +40,14 @@ dependencies:
|
|||||||
extended_image: ^6.0.3
|
extended_image: ^6.0.3
|
||||||
url_launcher: ^6.0.9
|
url_launcher: ^6.0.9
|
||||||
countly_flutter:
|
countly_flutter:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Countly/countly-sdk-flutter-bridge.git
|
url: https://github.com/Countly/countly-sdk-flutter-bridge.git
|
||||||
ref: master
|
ref: master
|
||||||
dartssh2: ^2.3.1-pre
|
dartssh2: ^2.3.1-pre
|
||||||
logging: ^1.0.2
|
logging: ^1.0.2
|
||||||
flutter_material_color_picker: ^1.1.0+2
|
flutter_material_color_picker: ^1.1.0+2
|
||||||
circle_chart:
|
circle_chart:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/LollipopKit/circle_chart
|
url: https://github.com/LollipopKit/circle_chart
|
||||||
ref: main
|
ref: main
|
||||||
# path: ../circle_chart
|
# path: ../circle_chart
|
||||||
@@ -57,7 +58,6 @@ dependencies:
|
|||||||
dropdown_button2: ^1.1.1
|
dropdown_button2: ^1.1.1
|
||||||
flutter_advanced_drawer: ^1.3.0
|
flutter_advanced_drawer: ^1.3.0
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_native_splash: ^2.1.6
|
flutter_native_splash: ^2.1.6
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -72,7 +72,6 @@ dev_dependencies:
|
|||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
# The following section is specific to Flutter.
|
# The following section is specific to Flutter.
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
@@ -93,13 +92,10 @@ flutter:
|
|||||||
- assets/linux/opensuse.png
|
- assets/linux/opensuse.png
|
||||||
# - images/a_dot_burr.jpeg
|
# - images/a_dot_burr.jpeg
|
||||||
# - images/a_dot_ham.jpeg
|
# - images/a_dot_ham.jpeg
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
# An image asset can refer to one or more resolution-specific "variants", see
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||||
|
|
||||||
# For details regarding adding assets from package dependencies, see
|
# For details regarding adding assets from package dependencies, see
|
||||||
# https://flutter.dev/assets-and-images/#from-packages
|
# https://flutter.dev/assets-and-images/#from-packages
|
||||||
|
|
||||||
# To add custom fonts to your application, add a fonts section here,
|
# To add custom fonts to your application, add a fonts section here,
|
||||||
# in this "flutter" section. Each entry in this list should have a
|
# in this "flutter" section. Each entry in this list should have a
|
||||||
# "family" key with the font family name, and a "fonts" key with a
|
# "family" key with the font family name, and a "fonts" key with a
|
||||||
@@ -119,7 +115,6 @@ flutter:
|
|||||||
#
|
#
|
||||||
# For details regarding fonts from package dependencies,
|
# For details regarding fonts from package dependencies,
|
||||||
# see https://flutter.dev/custom-fonts/#from-packages
|
# see https://flutter.dev/custom-fonts/#from-packages
|
||||||
|
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
# This package generates native code to customize Flutter's default white native splash screen
|
# This package generates native code to customize Flutter's default white native splash screen
|
||||||
# with background color and splash image.
|
# with background color and splash image.
|
||||||
@@ -127,17 +122,14 @@ flutter_native_splash:
|
|||||||
# flutter pub run flutter_native_splash:create
|
# flutter pub run flutter_native_splash:create
|
||||||
# To restore Flutter's default white splash screen, run the following command in the terminal:
|
# To restore Flutter's default white splash screen, run the following command in the terminal:
|
||||||
# flutter pub run flutter_native_splash:remove
|
# flutter pub run flutter_native_splash:remove
|
||||||
|
|
||||||
# color or background_image is the only required parameter. Use color to set the background
|
# color or background_image is the only required parameter. Use color to set the background
|
||||||
# of your splash screen to a solid color. Use background_image to set the background of your
|
# of your splash screen to a solid color. Use background_image to set the background of your
|
||||||
# splash screen to a png image. This is useful for gradients. The image will be stretch to the
|
# splash screen to a png image. This is useful for gradients. The image will be stretch to the
|
||||||
# size of the app. Only one parameter can be used, color and background_image cannot both be set.
|
# size of the app. Only one parameter can be used, color and background_image cannot both be set.
|
||||||
color: "#ffffff"
|
color: "#ffffff"
|
||||||
#background_image: "assets/background.png"
|
#background_image: "assets/background.png"
|
||||||
|
|
||||||
# Optional parameters are listed below. To enable a parameter, uncomment the line by removing
|
# Optional parameters are listed below. To enable a parameter, uncomment the line by removing
|
||||||
# the leading # character.
|
# the leading # character.
|
||||||
|
|
||||||
# The image parameter allows you to specify an image used in the splash screen. It must be a
|
# The image parameter allows you to specify an image used in the splash screen. It must be a
|
||||||
# png file and should be sized for 4x pixel density.
|
# png file and should be sized for 4x pixel density.
|
||||||
image: assets/app_icon.png
|
image: assets/app_icon.png
|
||||||
@@ -150,13 +142,11 @@ flutter_native_splash:
|
|||||||
color_dark: "#121212"
|
color_dark: "#121212"
|
||||||
#background_image_dark: "assets/dark-background.png"
|
#background_image_dark: "assets/dark-background.png"
|
||||||
#image_dark: assets/splash-invert.png
|
#image_dark: assets/splash-invert.png
|
||||||
|
|
||||||
# The android, ios and web parameters can be used to disable generating a splash screen on a given
|
# The android, ios and web parameters can be used to disable generating a splash screen on a given
|
||||||
# platform.
|
# platform.
|
||||||
#android: false
|
#android: false
|
||||||
#ios: false
|
#ios: false
|
||||||
#web: false
|
#web: false
|
||||||
|
|
||||||
# The position of the splash image can be set with android_gravity, ios_content_mode, and
|
# The position of the splash image can be set with android_gravity, ios_content_mode, and
|
||||||
# web_image_mode parameters. All default to center.
|
# web_image_mode parameters. All default to center.
|
||||||
#
|
#
|
||||||
@@ -174,7 +164,6 @@ flutter_native_splash:
|
|||||||
#
|
#
|
||||||
# web_image_mode can be one of the following modes: center, contain, stretch, and cover.
|
# web_image_mode can be one of the following modes: center, contain, stretch, and cover.
|
||||||
#web_image_mode: center
|
#web_image_mode: center
|
||||||
|
|
||||||
# To hide the notification bar, use the fullscreen parameter. Has no affect in web since web
|
# To hide the notification bar, use the fullscreen parameter. Has no affect in web since web
|
||||||
# has no notification bar. Defaults to false.
|
# has no notification bar. Defaults to false.
|
||||||
# NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads.
|
# NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads.
|
||||||
@@ -182,13 +171,13 @@ flutter_native_splash:
|
|||||||
# WidgetsFlutterBinding.ensureInitialized();
|
# WidgetsFlutterBinding.ensureInitialized();
|
||||||
# SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom, SystemUiOverlay.top]);
|
# SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom, SystemUiOverlay.top]);
|
||||||
#fullscreen: true
|
#fullscreen: true
|
||||||
|
|
||||||
# If you have changed the name(s) of your info.plist file(s), you can specify the filename(s)
|
# If you have changed the name(s) of your info.plist file(s), you can specify the filename(s)
|
||||||
# with the info_plist_files parameter. Remove only the # characters in the three lines below,
|
# with the info_plist_files parameter. Remove only the # characters in the three lines below,
|
||||||
# do not remove any spaces:
|
# do not remove any spaces:
|
||||||
#info_plist_files:
|
#info_plist_files:
|
||||||
# - 'ios/Runner/Info-Debug.plist'
|
# - 'ios/Runner/Info-Debug.plist'
|
||||||
# - 'ios/Runner/Info-Release.plist'
|
# - 'ios/Runner/Info-Release.plist'
|
||||||
|
|
||||||
# To enable support for Android 12, set the following parameter to true. Defaults to false.
|
# To enable support for Android 12, set the following parameter to true. Defaults to false.
|
||||||
#android12: true
|
#android12: true
|
||||||
|
flutter_intl:
|
||||||
|
enabled: true
|
||||||
|
|||||||
Reference in New Issue
Block a user