diff --git a/kitx_mobile/android/app/src/main/AndroidManifest.xml b/kitx_mobile/android/app/src/main/AndroidManifest.xml
index a5caa3b..f4c9f5a 100644
--- a/kitx_mobile/android/app/src/main/AndroidManifest.xml
+++ b/kitx_mobile/android/app/src/main/AndroidManifest.xml
@@ -94,4 +94,5 @@
+
diff --git a/kitx_mobile/android/app/src/main/res/drawable/app_icon.png b/kitx_mobile/android/app/src/main/res/drawable/app_icon.png
new file mode 100644
index 0000000..61be1b2
Binary files /dev/null and b/kitx_mobile/android/app/src/main/res/drawable/app_icon.png differ
diff --git a/kitx_mobile/android/build.gradle b/kitx_mobile/android/build.gradle
index bc157bd..590269b 100644
--- a/kitx_mobile/android/build.gradle
+++ b/kitx_mobile/android/build.gradle
@@ -1,3 +1,16 @@
+buildscript {
+ ext.kotlin_version = '1.7.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.android.tools.build:gradle:7.3.0'
+ }
+}
+
allprojects {
repositories {
google()
diff --git a/kitx_mobile/lib/instances.dart b/kitx_mobile/lib/instances.dart
index c178dc6..c83fd12 100644
--- a/kitx_mobile/lib/instances.dart
+++ b/kitx_mobile/lib/instances.dart
@@ -7,6 +7,7 @@ import 'package:kitx_mobile/data/local_device_info.dart';
import 'package:kitx_mobile/data/local_network_info.dart';
import 'package:kitx_mobile/services/devices_discovery_service.dart';
import 'package:kitx_mobile/services/devices_service.dart';
+import 'package:kitx_mobile/services/notification.dart';
import 'package:kitx_mobile/utils/config.dart';
import 'package:kitx_mobile/utils/handlers/tasks/delayed_task.dart';
import 'package:kitx_mobile/utils/handlers/url_handler.dart';
@@ -53,6 +54,9 @@ class Instances {
/// Instance for [DeviceService] class
var devicesService = DeviceService();
+ /// Instance for [NotificationService] class
+ var notificationService = NotificationService();
+
/// Is in debug mode
var isDebugMode = kDebugMode.obs;
@@ -62,6 +66,15 @@ class Instances {
deviceInfo = await LocalDeviceInfo.get();
networkInfo = await LocalNetworkInfo.get();
+ // Init WebService
+ await devicesDiscoveryService.init();
+
+ // Init DeviceService
+ await devicesService.init();
+
+ // Init NotificationService
+ await notificationService.initAsync();
+
connectivity.onConnectivityChanged.listen(
(result) async {
instances.deviceInfo = await LocalDeviceInfo.get();
@@ -69,12 +82,6 @@ class Instances {
restartDevicesServer();
},
);
-
- // Init WebService
- await devicesDiscoveryService.init();
-
- // Init DeviceService
- await devicesService.init();
}
/// Restart [devicesService] and [devicesDiscoveryService]
diff --git a/kitx_mobile/lib/main.dart b/kitx_mobile/lib/main.dart
index 8c3d494..168e81c 100644
--- a/kitx_mobile/lib/main.dart
+++ b/kitx_mobile/lib/main.dart
@@ -6,7 +6,7 @@ import 'package:kitx_mobile/pages/pages.dart';
import 'package:kitx_mobile/utils/config.dart';
import 'package:kitx_mobile/utils/log.dart';
import 'package:kitx_mobile/utils/themes/themes.dart';
-import 'package:kitx_mobile/utils/translation.dart';
+import 'package:kitx_mobile/utils/translation/translation.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
diff --git a/kitx_mobile/lib/pages/about_page.dart b/kitx_mobile/lib/pages/about_page.dart
index e0e1db0..c9f24f1 100644
--- a/kitx_mobile/lib/pages/about_page.dart
+++ b/kitx_mobile/lib/pages/about_page.dart
@@ -203,29 +203,34 @@ class _AboutPageState extends State {
).createShader(rect);
},
blendMode: BlendMode.dstOut,
- child: ListView(shrinkWrap: true, scrollDirection: Axis.horizontal, physics: BouncingScrollPhysics(), children: [
- GraduallySmallerSpacer(duration: 1200, width: contentEntering ? 15 : 800),
- const ContributorChip(
- name: 'Dynesshely',
- url: 'https://github.com/Dynesshely',
- ),
- const SizedBox(width: 10),
- const ContributorChip(
- name: 'Cranyozen',
- url: 'https://github.com/Cranyozen',
- ),
- const SizedBox(width: 10),
- const ContributorChip(
- name: 'orzMaster',
- url: 'https://github.com/orzMaster',
- ),
- const SizedBox(width: 10),
- const ContributorChip(
- name: 'Cronyet',
- url: 'https://github.com/Cronyet',
- ),
- const SizedBox(width: 15),
- ]),
+ child: ListView(
+ shrinkWrap: true,
+ scrollDirection: Axis.horizontal,
+ physics: BouncingScrollPhysics(),
+ children: [
+ GraduallySmallerSpacer(duration: 1200, width: contentEntering ? 15 : 800),
+ const ContributorChip(
+ name: 'Dynesshely',
+ url: 'https://github.com/Dynesshely',
+ ),
+ const SizedBox(width: 10),
+ const ContributorChip(
+ name: 'Cranyozen',
+ url: 'https://github.com/Cranyozen',
+ ),
+ const SizedBox(width: 10),
+ const ContributorChip(
+ name: 'orzMaster',
+ url: 'https://github.com/orzMaster',
+ ),
+ const SizedBox(width: 10),
+ const ContributorChip(
+ name: 'Cronyet',
+ url: 'https://github.com/Cronyet',
+ ),
+ const SizedBox(width: 15),
+ ],
+ ),
),
),
),
diff --git a/kitx_mobile/lib/pages/controls/device_card.dart b/kitx_mobile/lib/pages/controls/device_card.dart
index befc47b..f8bd7bc 100644
--- a/kitx_mobile/lib/pages/controls/device_card.dart
+++ b/kitx_mobile/lib/pages/controls/device_card.dart
@@ -147,7 +147,7 @@ class _DeviceCard extends State with TickerProviderStateMixin {
padding: EdgeInsets.only(bottom: width == null ? 20 : 8),
child: badges.Badge(
badgeContent: Text(
- 'DevicesPage_PluginsCountText'.tr.replaceAll('%count%', (info.pluginsCount).toString()),
+ 'DevicesPage_PluginsCountText'.trParams({'count': info.pluginsCount.toString()}),
style: const TextStyle(color: Colors.white),
),
position: badges.BadgePosition.topEnd(top: 70, end: 15),
diff --git a/kitx_mobile/lib/services/devices_discovery_service.dart b/kitx_mobile/lib/services/devices_discovery_service.dart
index 3cdd346..9b18aed 100644
--- a/kitx_mobile/lib/services/devices_discovery_service.dart
+++ b/kitx_mobile/lib/services/devices_discovery_service.dart
@@ -94,9 +94,7 @@ class DevicesDiscoveryService implements Service {
socket.broadcastEnabled = true;
socket.joinMulticast(InternetAddress(_udpBroadcastAddress));
- Timer.periodic(Duration(seconds: config.webServiceUdpSendFrequency), (timer) {
- sendTimer = timer;
-
+ sendTimer = Timer.periodic(Duration(seconds: config.webServiceUdpSendFrequency), (timer) {
try {
deviceInfo = deviceInfo.rebuild(
(b) => b
diff --git a/kitx_mobile/lib/services/devices_service.dart b/kitx_mobile/lib/services/devices_service.dart
index 245ddb2..41699a2 100644
--- a/kitx_mobile/lib/services/devices_service.dart
+++ b/kitx_mobile/lib/services/devices_service.dart
@@ -139,6 +139,12 @@ class DeviceService implements Service {
}
deviceInfoList.refresh();
+
+ // Update notification service.
+ instances.notificationService.updateStatusNotification(
+ deviceCount: deviceInfoList.length,
+ serviceStatus: serviceStatus.value,
+ );
});
serviceStatus.value = ServiceStatus.running;
diff --git a/kitx_mobile/lib/services/notification.dart b/kitx_mobile/lib/services/notification.dart
new file mode 100644
index 0000000..b44f4ca
--- /dev/null
+++ b/kitx_mobile/lib/services/notification.dart
@@ -0,0 +1,96 @@
+import 'dart:io';
+
+import 'package:awesome_notifications/awesome_notifications.dart';
+import 'package:flutter/services.dart';
+import 'package:get/get.dart';
+import 'package:kitx_mobile/services/public/service_status.dart';
+import 'package:kitx_mobile/utils/extensions/service_status_to_string.dart';
+import 'package:kitx_mobile/instances.dart';
+// import 'package:flutter/material.dart';
+
+/// [NotificationService] class
+class NotificationService {
+ /// Status notification id
+ var statusNotificationId = 10;
+
+ /// Status channel key
+ var statusChannelKey = "status_channel";
+
+ /// Initialize the notification service
+ Future initAsync() async {
+ // TODO: Adapt to iOS
+ AwesomeNotifications().initialize(
+ 'resource://drawable/app_icon',
+ [
+ // KitX status channel
+ NotificationChannel(
+ channelKey: statusChannelKey,
+ channelName: 'KitX Status Notifications',
+ channelDescription: 'KitX status',
+ locked: true, // Prevents the user from deleting the channel
+ playSound: false, // Do NOT play sound when the notification is displayed
+ enableVibration: false, // Do NOT vibrate when the notification is displayed
+ onlyAlertOnce: true, // Only alert once
+ // defaultColor: Color(0xFF9D50DD),
+ // ledColor: Colors.white,
+ ),
+ ],
+ );
+ AwesomeNotifications().setListeners(onActionReceivedMethod: onActionReceivedMethod);
+ }
+
+ /// On action received method
+ @pragma('vm:entry-point')
+ static Future onActionReceivedMethod(ReceivedAction receivedAction) async {
+ var key = receivedAction.buttonKeyPressed;
+ if (key == 'action_view_button') {
+ if (instances.devicesService.serviceStatus == ServiceStatus.running) {
+ // Stop service
+ instances.shutdownDevicesServer();
+ } else {
+ // Start service
+ instances.restartDevicesServer();
+ }
+ } else if (key == 'action_view_exit') {
+ // Exit app
+ instances.shutdownDevicesServer();
+
+ // Delete all notifications
+ AwesomeNotifications().cancelAll();
+
+ await SystemNavigator.pop(); // Probably not working on iOS (by Copilot)
+ exit(0);
+ }
+ }
+
+ /// Update status notification
+ Future updateStatusNotification({
+ required int deviceCount,
+ required ServiceStatus serviceStatus,
+ }) async {
+ AwesomeNotifications().createNotification(
+ content: NotificationContent(
+ id: statusNotificationId,
+ channelKey: statusChannelKey,
+ title: 'NotificationService_StatusNotificationTitle'.trParams({"status": serviceStatus.toText()}),
+ body: 'NotificationService_StatusNotificationBody'.trParams({'device_count': deviceCount.toString()}),
+ locked: true,
+ autoDismissible: false,
+ category: NotificationCategory.Status,
+ ),
+ actionButtons: [
+ NotificationActionButton(
+ key: 'action_view_button',
+ label: (serviceStatus == ServiceStatus.running) ? 'Public_Stop'.tr : 'Public_Launch'.tr,
+ actionType: ActionType.KeepOnTop,
+ autoDismissible: false,
+ ),
+ NotificationActionButton(
+ key: 'action_view_exit',
+ label: 'Public_Quit'.tr,
+ actionType: ActionType.SilentAction,
+ autoDismissible: false,
+ ),
+ ]);
+ }
+}
diff --git a/kitx_mobile/lib/utils/extensions/service_status_to_string.dart b/kitx_mobile/lib/utils/extensions/service_status_to_string.dart
new file mode 100644
index 0000000..dab0f31
--- /dev/null
+++ b/kitx_mobile/lib/utils/extensions/service_status_to_string.dart
@@ -0,0 +1,23 @@
+import 'package:get/get.dart';
+import 'package:kitx_mobile/services/public/service_status.dart';
+
+/// [ServiceStatus] Extensions
+extension ServiceStatusExtensions on ServiceStatus {
+ /// Convert [ServiceStatus] to [String]
+ String toText() {
+ switch (this) {
+ case ServiceStatus.error:
+ return 'Public_Error'.tr;
+ case ServiceStatus.starting:
+ return 'Public_Launching'.tr;
+ case ServiceStatus.stopping:
+ return 'Public_Stopping'.tr;
+ case ServiceStatus.running:
+ return 'Public_Running'.tr;
+ case ServiceStatus.pending:
+ return 'Public_Pending'.tr;
+ default:
+ return 'Unknown';
+ }
+ }
+}
diff --git a/kitx_mobile/lib/utils/log.dart b/kitx_mobile/lib/utils/log.dart
index 285f625..539f866 100644
--- a/kitx_mobile/lib/utils/log.dart
+++ b/kitx_mobile/lib/utils/log.dart
@@ -7,6 +7,7 @@ import 'package:f_logs/model/flog/flog_config.dart';
import 'package:f_logs/model/flog/log_level.dart';
import 'package:f_logs/utils/formatter/formate_type.dart';
import 'package:f_logs/utils/timestamp/timestamp_format.dart';
+import 'package:stack_trace/stack_trace.dart';
var _config = LogsConfig()
..isDebuggable = true
@@ -26,7 +27,11 @@ class Log {
void info(String message) => FLog.info(text: message);
/// Log a message at level [LogLevel.ERROR].
- void error(String message) => FLog.error(text: message);
+ void error(String message) {
+ var trace = Trace.current().frames;
+ var filteredTrace = trace.where((frame) => !frame.library.contains('package:kitx_mobile/utils/log.dart'));
+ FLog.error(text: message, stacktrace: Trace(filteredTrace));
+ }
/// Log a message at level [LogLevel.WARNING].
void warning(String message) => FLog.warning(text: message);
diff --git a/kitx_mobile/lib/utils/translation.dart b/kitx_mobile/lib/utils/translation.dart
deleted file mode 100644
index ae65099..0000000
--- a/kitx_mobile/lib/utils/translation.dart
+++ /dev/null
@@ -1,126 +0,0 @@
-import 'package:get/get.dart';
-
-/// Translation Data
-class Translation extends Translations {
- @override
- Map> get keys => {
- 'zh_CN': {
- 'Public_Enable': '启用',
- 'Public_Disable': '禁用',
- 'Public_Animation': '动画',
- 'Public_Additional': '额外的',
- 'Public_Log': '日志',
- 'Public_Reload': '重载',
- 'Public_Restart': '重启',
- 'Public_Chat': '聊天',
- 'Public_Closed': "已关闭",
- 'Public_Error': "错误",
- 'Public_Launch': "启动",
- 'Public_Launching': "启动中",
- 'Public_Stop': "停止",
- 'Public_Stopping': "停止中",
- 'Drawer_Title': 'KitX',
- 'Drawer_Devices': '设备管理',
- 'Drawer_Plugins': '插件列表',
- 'Drawer_Account': '账户',
- 'Drawer_Test': '测试',
- 'Drawer_Setting': '设置',
- 'Drawer_About': '关于',
- 'Option_RestartDevicesServer': '重启设备网络服务器',
- 'Option_ShutdownDevicesServer': '关闭设备网络服务器',
- 'IndexPage_Title': 'KitX',
- 'HomePage_DevicesCount': '设备在线',
- 'DevicesPage_Title': '设备管理',
- 'DevicesPage_PluginsCountText': '%count% 插件在线',
- 'DevicesPage_LocalDevice': '(本机)',
- 'DevicesPage_MainDevice': '(主控)',
- 'DeviceChatPage_Title': '聊天',
- 'PluginsPage_Title': '插件列表',
- 'PluginsPage_BuiltInPlugins': '内置插件',
- 'PluginsPage_ConnectedPlugins': '已连接的插件',
- 'AccountPage_Title': '账户',
- 'TestPage_Title': '测试',
- 'SettingsPage_Title': '设置',
- 'SettingsPage_Languages': '语言',
- 'SettingsPage_Theme': '主题',
- 'SettingsPage_Light': '浅',
- 'SettingsPage_Dark': '深',
- 'SettingsPage_FollowSystem': '跟随',
- 'SettingsPage_CleanLog': '清理日志',
- 'SettingsPage_Saved': '配置已保存!',
- 'AboutPage_Title': '关于',
- 'AboutPage_Version': '版本',
- 'AboutPage_VersionCode': '构建号',
- 'AboutPage_Contributors': '贡献者',
- 'AboutPage_Repos': '仓库',
- 'AboutPage_ThirdPartyLicenses': '第三方许可',
- 'AboutPage_ThirdPartyLicenses_DisplayAll': '显示全部',
- 'AboutPage_JoinUS': '加入我们',
- 'AboutPage_JoinUS_Text': ''
- '我们的项目都托管在 https://github.com/Crequency/, 欢迎 Fork 并贡献您宝贵的意见.'
- '\n\n'
- 'KitX Mobile 的源码全部位于 https://github.com/Crequency/KitX-Mobile/'
- '\n\n'
- 'KitX Mobile 是 KitX Project 一部分, KitX Project 的主仓库是 https://github.com/Crequency/KitX',
- },
- 'en_US': {
- 'Public_Enable': 'Enable',
- 'Public_Disable': 'Disable',
- 'Public_Animation': 'Animation',
- 'Public_Additional': 'Additional',
- 'Public_Log': 'Log',
- 'Public_Reload': 'Reload',
- 'Public_Restart': 'Restart',
- 'Public_Chat': 'Chat',
- 'Public_Closed': "Closed",
- 'Public_Error': "Error",
- 'Public_Launch': "Launch",
- 'Public_Launching': "Launching",
- 'Public_Stop': "Stop",
- 'Public_Stopping': "Stopping",
- 'Drawer_Title': 'KitX',
- 'Drawer_Devices': 'Devices',
- 'Drawer_Plugins': 'Plugins',
- 'Drawer_Account': 'Account',
- 'Drawer_Test': 'Test',
- 'Drawer_Setting': 'Settings',
- 'Drawer_About': 'About',
- 'Option_RestartDevicesServer': 'Restart Devices Server',
- 'Option_ShutdownDevicesServer': 'Shutdown Devices Server',
- 'IndexPage_Title': 'KitX',
- 'HomePage_DevicesCount': 'Devices found.',
- 'DevicesPage_Title': 'Devices',
- 'DevicesPage_PluginsCountText': '%count% Plugins Online',
- 'DevicesPage_LocalDevice': '(Local)',
- 'DevicesPage_MainDevice': '(Master)',
- 'DeviceChatPage_Title': 'Chat',
- 'PluginsPage_Title': 'Plugins',
- 'PluginsPage_BuiltInPlugins': 'Built-in Plugins',
- 'PluginsPage_ConnectedPlugins': 'Connected Plugins',
- 'AccountPage_Title': 'Account',
- 'TestPage_Title': 'Test',
- 'SettingsPage_Title': 'Settings',
- 'SettingsPage_Languages': 'Languages',
- 'SettingsPage_Theme': 'Theme',
- 'SettingsPage_Light': 'Light',
- 'SettingsPage_Dark': 'Dark',
- 'SettingsPage_FollowSystem': 'Follow system',
- 'SettingsPage_CleanLog': 'Clean Log',
- 'SettingsPage_Saved': 'Changes saved!',
- 'AboutPage_Title': 'About',
- 'AboutPage_Version': 'Version',
- 'AboutPage_VersionCode': 'Build Number',
- 'AboutPage_Contributors': 'Contributors',
- 'AboutPage_Repos': 'Repos',
- 'AboutPage_ThirdPartyLicenses': 'Third-Party Licenses',
- 'AboutPage_ThirdPartyLicenses_DisplayAll': 'Display all',
- 'AboutPage_JoinUS': 'Join US',
- 'AboutPage_JoinUS_Text': ''
- 'All our projects storage on https://github.com/Crequency/, welcome to fork and contribute to them.'
- '\n\n'
- 'Source code of KitX Mobile located at https://github.com/Crequency/KitX-Mobile/'
- '\n\n'
- 'KitX Mobile belongs to KitX Project, Main repo of KitX Project located at https://github.com/Crequency/KitX',
- }
- };
-}
diff --git a/kitx_mobile/lib/utils/translation/en_us.dart b/kitx_mobile/lib/utils/translation/en_us.dart
new file mode 100644
index 0000000..e4ce8b4
--- /dev/null
+++ b/kitx_mobile/lib/utils/translation/en_us.dart
@@ -0,0 +1,67 @@
+// ignore_for_file: constant_identifier_names
+
+/// English - United States (en_US) translation
+const Map en_us = {
+ 'Public_Enable': 'Enable',
+ 'Public_Disable': 'Disable',
+ 'Public_Animation': 'Animation',
+ 'Public_Additional': 'Additional',
+ 'Public_Log': 'Log',
+ 'Public_Reload': 'Reload',
+ 'Public_Restart': 'Restart',
+ 'Public_Chat': 'Chat',
+ 'Public_Closed': 'Closed',
+ 'Public_Error': 'Error',
+ 'Public_Launch': 'Launch',
+ 'Public_Launching': 'Launching',
+ 'Public_Stop': 'Stop',
+ 'Public_Stopping': 'Stopping',
+ 'Public_Running': 'Running',
+ 'Public_Pending': 'Pending',
+ 'Public_Quit': 'Quit',
+ 'NotificationService_StatusNotificationTitle': 'KitX @status',
+ 'NotificationService_StatusNotificationBody': '@device_count Devices Online',
+ 'Drawer_Title': 'KitX',
+ 'Drawer_Devices': 'Devices',
+ 'Drawer_Plugins': 'Plugins',
+ 'Drawer_Account': 'Account',
+ 'Drawer_Test': 'Test',
+ 'Drawer_Setting': 'Settings',
+ 'Drawer_About': 'About',
+ 'Option_RestartDevicesServer': 'Restart Devices Server',
+ 'Option_ShutdownDevicesServer': 'Shutdown Devices Server',
+ 'IndexPage_Title': 'KitX',
+ 'HomePage_DevicesCount': 'Devices found.',
+ 'DevicesPage_Title': 'Devices',
+ 'DevicesPage_PluginsCountText': '@count Plugins Online',
+ 'DevicesPage_LocalDevice': '(Local)',
+ 'DevicesPage_MainDevice': '(Master)',
+ 'DeviceChatPage_Title': 'Chat',
+ 'PluginsPage_Title': 'Plugins',
+ 'PluginsPage_BuiltInPlugins': 'Built-in Plugins',
+ 'PluginsPage_ConnectedPlugins': 'Connected Plugins',
+ 'AccountPage_Title': 'Account',
+ 'TestPage_Title': 'Test',
+ 'SettingsPage_Title': 'Settings',
+ 'SettingsPage_Languages': 'Languages',
+ 'SettingsPage_Theme': 'Theme',
+ 'SettingsPage_Light': 'Light',
+ 'SettingsPage_Dark': 'Dark',
+ 'SettingsPage_FollowSystem': 'Follow system',
+ 'SettingsPage_CleanLog': 'Clean Log',
+ 'SettingsPage_Saved': 'Changes saved!',
+ 'AboutPage_Title': 'About',
+ 'AboutPage_Version': 'Version',
+ 'AboutPage_VersionCode': 'Build Number',
+ 'AboutPage_Contributors': 'Contributors',
+ 'AboutPage_Repos': 'Repos',
+ 'AboutPage_ThirdPartyLicenses': 'Third-Party Licenses',
+ 'AboutPage_ThirdPartyLicenses_DisplayAll': 'Display all',
+ 'AboutPage_JoinUS': 'Join US',
+ 'AboutPage_JoinUS_Text': ''
+ 'All our projects storage on https://github.com/Crequency/, welcome to fork and contribute to them.'
+ '\n\n'
+ 'Source code of KitX Mobile located at https://github.com/Crequency/KitX-Mobile/'
+ '\n\n'
+ 'KitX Mobile belongs to KitX Project, Main repo of KitX Project located at https://github.com/Crequency/KitX',
+};
diff --git a/kitx_mobile/lib/utils/translation/translation.dart b/kitx_mobile/lib/utils/translation/translation.dart
new file mode 100644
index 0000000..b4082c8
--- /dev/null
+++ b/kitx_mobile/lib/utils/translation/translation.dart
@@ -0,0 +1,10 @@
+import 'package:get/get.dart';
+
+import 'package:kitx_mobile/utils/translation/en_us.dart';
+import 'package:kitx_mobile/utils/translation/zh_cn.dart';
+
+/// Translation Data
+class Translation extends Translations {
+ @override
+ Map> get keys => {'zh_CN': zh_cn, 'en_US': en_us};
+}
diff --git a/kitx_mobile/lib/utils/translation/zh_cn.dart b/kitx_mobile/lib/utils/translation/zh_cn.dart
new file mode 100644
index 0000000..bd68ee9
--- /dev/null
+++ b/kitx_mobile/lib/utils/translation/zh_cn.dart
@@ -0,0 +1,67 @@
+// ignore_for_file: constant_identifier_names
+
+/// Simplified Chinese (zh_CN) translation
+const Map zh_cn = {
+ 'Public_Enable': '启用',
+ 'Public_Disable': '禁用',
+ 'Public_Animation': '动画',
+ 'Public_Additional': '额外的',
+ 'Public_Log': '日志',
+ 'Public_Reload': '重载',
+ 'Public_Restart': '重启',
+ 'Public_Chat': '聊天',
+ 'Public_Closed': '已关闭',
+ 'Public_Error': '错误',
+ 'Public_Launch': '启动',
+ 'Public_Launching': '启动中',
+ 'Public_Stop': '停止',
+ 'Public_Stopping': '停止中',
+ 'Public_Running': '运行中',
+ 'Public_Pending': '等待中',
+ 'Public_Quit': '退出',
+ 'NotificationService_StatusNotificationTitle': 'KitX @status',
+ 'NotificationService_StatusNotificationBody': '当前设备数: @device_count',
+ 'Drawer_Title': 'KitX',
+ 'Drawer_Devices': '设备管理',
+ 'Drawer_Plugins': '插件列表',
+ 'Drawer_Account': '账户',
+ 'Drawer_Test': '测试',
+ 'Drawer_Setting': '设置',
+ 'Drawer_About': '关于',
+ 'Option_RestartDevicesServer': '重启设备网络服务器',
+ 'Option_ShutdownDevicesServer': '关闭设备网络服务器',
+ 'IndexPage_Title': 'KitX',
+ 'HomePage_DevicesCount': '设备在线',
+ 'DevicesPage_Title': '设备管理',
+ 'DevicesPage_PluginsCountText': '@count 插件在线',
+ 'DevicesPage_LocalDevice': '(本机)',
+ 'DevicesPage_MainDevice': '(主控)',
+ 'DeviceChatPage_Title': '聊天',
+ 'PluginsPage_Title': '插件列表',
+ 'PluginsPage_BuiltInPlugins': '内置插件',
+ 'PluginsPage_ConnectedPlugins': '已连接的插件',
+ 'AccountPage_Title': '账户',
+ 'TestPage_Title': '测试',
+ 'SettingsPage_Title': '设置',
+ 'SettingsPage_Languages': '语言',
+ 'SettingsPage_Theme': '主题',
+ 'SettingsPage_Light': '浅',
+ 'SettingsPage_Dark': '深',
+ 'SettingsPage_FollowSystem': '跟随',
+ 'SettingsPage_CleanLog': '清理日志',
+ 'SettingsPage_Saved': '配置已保存!',
+ 'AboutPage_Title': '关于',
+ 'AboutPage_Version': '版本',
+ 'AboutPage_VersionCode': '构建号',
+ 'AboutPage_Contributors': '贡献者',
+ 'AboutPage_Repos': '仓库',
+ 'AboutPage_ThirdPartyLicenses': '第三方许可',
+ 'AboutPage_ThirdPartyLicenses_DisplayAll': '显示全部',
+ 'AboutPage_JoinUS': '加入我们',
+ 'AboutPage_JoinUS_Text': ''
+ '我们的项目都托管在 https://github.com/Crequency/, 欢迎 Fork 并贡献您宝贵的意见.'
+ '\n\n'
+ 'KitX Mobile 的源码全部位于 https://github.com/Crequency/KitX-Mobile/'
+ '\n\n'
+ 'KitX Mobile 是 KitX Project 一部分, KitX Project 的主仓库是 https://github.com/Crequency/KitX',
+};
diff --git a/kitx_mobile/pubspec.lock b/kitx_mobile/pubspec.lock
index 52697ba..c3180f0 100644
--- a/kitx_mobile/pubspec.lock
+++ b/kitx_mobile/pubspec.lock
@@ -33,6 +33,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.11.0"
+ awesome_notifications:
+ dependency: "direct main"
+ description:
+ name: awesome_notifications
+ sha256: "2b430c75cc879d6cfd52bb6eb2b5c1591ed425347816408cdcbd3f6916bba14c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.4+1"
badges:
dependency: "direct main"
description:
diff --git a/kitx_mobile/pubspec.yaml b/kitx_mobile/pubspec.yaml
index 29cf925..9b9c5e6 100644
--- a/kitx_mobile/pubspec.yaml
+++ b/kitx_mobile/pubspec.yaml
@@ -9,10 +9,11 @@ environment:
sdk: ">=3.3.0 <4.0.0"
dependencies:
- badges: ^3.1.2
- battery_plus: ^5.0.3
- community_material_icon: ^5.9.55
- concentric_transition: ^1.0.3
+ awesome_notifications: ^0.7.4+1
+ badges: ^3.1.2 # 徽章
+ battery_plus: ^5.0.3 # 电池数据
+ community_material_icon: ^5.9.55 # Material Design Icons 社区贡献
+ concentric_transition: ^1.0.3 # 同心过渡动画
connectivity_plus: ^5.0.2
crypto: ^3.0.3
device_info_plus: ^9.1.1