diff --git a/.codex b/.codex new file mode 100644 index 00000000..e69de29b diff --git a/.fvmrc b/.fvmrc new file mode 100644 index 00000000..d8a11548 --- /dev/null +++ b/.fvmrc @@ -0,0 +1,3 @@ +{ + "flutter": "3.35.3" +} \ No newline at end of file diff --git a/.github/workflows/build-arch-x86.yml b/.github/workflows/build-arch-x86.yml new file mode 100644 index 00000000..7caf4596 --- /dev/null +++ b/.github/workflows/build-arch-x86.yml @@ -0,0 +1,149 @@ +name: build-linux-bin + +permissions: + contents: read + +on: + push: + branches: + - fix/wayland-clipboard # 測試完合併後可以刪掉這段 + workflow_dispatch: + workflow_call: + outputs: + artifact-name: + description: Name of the uploaded Linux binary artifact + value: ${{ jobs.build.outputs.artifact_name }} + +env: + FLUTTER_VERSION: 3.35.3 + +jobs: + build: + name: Build Linux binary in Arch + # GitHub-hosted runners use Ubuntu as the host. All build commands below + # run inside the Arch Linux container. + runs-on: ubuntu-latest + container: + image: archlinux:base-devel + outputs: + artifact_name: ${{ steps.artifact.outputs.name }} + + steps: + - name: Verify Arch environment + run: | + cat /etc/os-release + uname -a + + - name: Install system dependencies + run: | + pacman -Syu --noconfirm + pacman -S --needed --noconfirm \ + git \ + curl \ + unzip \ + xz \ + zip \ + clang \ + cmake \ + ninja \ + pkgconf \ + gtk3 \ + libkeybinder3 \ + libayatana-appindicator \ + libayatana-indicator \ + ayatana-ido \ + libdbusmenu-glib \ + libdbusmenu-gtk3 \ + libxtst \ + wayland \ + wayland-protocols + ldconfig # ← 新增:刷新 so 快取,讓後續 ldconfig -p 能找到庫 + + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: false + + - name: Checkout ClipboardListener submodule + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + git submodule sync ClipboardListener + git submodule update --init --force --depth=1 ClipboardListener + git config --global --add safe.directory "$GITHUB_WORKSPACE/ClipboardListener" + + - name: Setup Flutter + run: | + git clone --depth 1 --branch "$FLUTTER_VERSION" https://github.com/flutter/flutter.git /opt/flutter + git config --global --add safe.directory /opt/flutter + echo "/opt/flutter/bin" >> "$GITHUB_PATH" + /opt/flutter/bin/flutter --version + /opt/flutter/bin/flutter config --enable-linux-desktop + + - name: Flutter pub get + run: flutter pub get + + - name: Build Linux release + run: flutter build linux --release + + - name: Package Linux binary + shell: bash + run: | + set -euo pipefail + + version="$(awk '/^version:/ {print $2; exit}' pubspec.yaml | cut -d'+' -f1)" + arch="$(uname -m)" + bundle_dir="build/linux/x64/release/bundle" + package_name="ClipShare-${version}-linux-${arch}" + + if [[ ! -x "${bundle_dir}/clipshare" ]]; then + echo "Linux release binary not found: ${bundle_dir}/clipshare" >&2 + exit 1 + fi + + rm -rf output "${package_name}" + mkdir -p output "${package_name}" + cp -a "${bundle_dir}/." "${package_name}/" + chmod +x "${package_name}/clipshare" + + runtime_libs=( + "libkeybinder-3.0.so.0" + "libayatana-appindicator3.so.1" + "libayatana-indicator3.so.7" + "libayatana-ido3-0.4.so.0" + "libdbusmenu-glib.so.4" + "libdbusmenu-gtk3.so.4" + "libXtst.so.6" + "libwayland-client.so.0" + "libwayland-cursor.so.0" + "libwayland-egl.so.1" + ) + mkdir -p "${package_name}/lib" + for soname in "${runtime_libs[@]}"; do + if [[ -f "${package_name}/lib/${soname}" ]]; then + continue + fi + lib_path="$(ldconfig -p | awk -v name="${soname}" '$1 == name { print $NF; exit }')" + if [[ -n "${lib_path}" && -f "${lib_path}" ]]; then + cp -L "${lib_path}" "${package_name}/lib/${soname}" + else + echo "Warning: runtime library not found: ${soname}" >&2 + fi + done + + tar -czf "output/${package_name}.tar.gz" "${package_name}" + ( + cd output + sha256sum "${package_name}.tar.gz" > "${package_name}.tar.gz.sha256" + sha256sum *.tar.gz > SHA256SUMS.txt + ) + + - name: Set artifact name + id: artifact + run: echo "name=linux-bin" >> "$GITHUB_OUTPUT" + + - name: Upload Linux binary artifact + uses: actions/upload-artifact@v4 + with: + name: linux-bin + path: output/* + overwrite: true diff --git a/.gitignore b/.gitignore index 0a2c21af..271a715f 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +# FVM Version Cache +.fvm/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..120c7ca1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ClipboardListener"] + path = ClipboardListener + url = https://github.com/JianGangLi/ClipboardListener diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..b810045e --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dart.flutterSdkPath": ".fvm/versions/3.35.3" +} \ No newline at end of file diff --git a/ClipboardListener b/ClipboardListener new file mode 160000 index 00000000..ae3f2a48 --- /dev/null +++ b/ClipboardListener @@ -0,0 +1 @@ +Subproject commit ae3f2a4854ce002e3480281b9dcb19b525baf25c diff --git a/lib/app/modules/settings_module/settings_page.dart b/lib/app/modules/settings_module/settings_page.dart index 048d313c..3273175b 100644 --- a/lib/app/modules/settings_module/settings_page.dart +++ b/lib/app/modules/settings_module/settings_page.dart @@ -92,10 +92,13 @@ class SettingsPage extends GetView { return EnvironmentStatusCard( icon: Obx(() => controller.envStatusIcon.value), backgroundColor: controller.envStatusBgColor.value, - tipContent: Obx(() => controller.envStatusTipContent.value), + tipContent: Obx( + () => controller.envStatusTipContent.value, + ), tipDesc: Obx(() => controller.envStatusTipDesc.value), action: Obx(() { - return controller.envStatusAction.value ?? const SizedBox.shrink(); + return controller.envStatusAction.value ?? + const SizedBox.shrink(); }), onTap: controller.onEnvironmentStatusCardClick, ); @@ -103,7 +106,9 @@ class SettingsPage extends GetView { if (Platform.isAndroid) Obx( () => Visibility( - visible: appConfig.workingMode == EnvironmentType.shizuku || appConfig.workingMode == EnvironmentType.root, + visible: + appConfig.workingMode == EnvironmentType.shizuku || + appConfig.workingMode == EnvironmentType.root, child: SettingHeader( icon: const Icon( Icons.developer_mode, @@ -124,7 +129,9 @@ class SettingsPage extends GetView { onTap: () async { Global.showTipsDialog( context: context, - text: TranslationKey.clipboardListeningWayTipsDetail.tr, + text: TranslationKey + .clipboardListeningWayTipsDetail + .tr, ); }, ), @@ -136,31 +143,49 @@ class SettingsPage extends GetView { if (Platform.isAndroid) Obx( () => Visibility( - visible: appConfig.workingMode == EnvironmentType.shizuku || appConfig.workingMode == EnvironmentType.root, + visible: + appConfig.workingMode == EnvironmentType.shizuku || + appConfig.workingMode == EnvironmentType.root, child: Row( children: [ Expanded( child: Obx( () => ClipboardListeningWaySettingCard( - cardMargin: const EdgeInsets.only(left: 0, right: 3), + cardMargin: const EdgeInsets.only( + left: 0, + right: 3, + ), icon: Icons.visibility_off, name: ClipboardListeningWay.hiddenApi.tr, - selected: appConfig.clipboardListeningWay == ClipboardListeningWay.hiddenApi, + selected: + appConfig.clipboardListeningWay == + ClipboardListeningWay.hiddenApi, onTap: () { - if (appConfig.clipboardListeningWay == ClipboardListeningWay.hiddenApi) { + if (appConfig.clipboardListeningWay == + ClipboardListeningWay.hiddenApi) { return; } Global.showTipsDialog( context: context, - text: TranslationKey.clipboardListeningWayToggleConfirmContent.trParams({"way": ClipboardListeningWay.hiddenApi.tr}), + text: TranslationKey + .clipboardListeningWayToggleConfirmContent + .trParams({ + "way": ClipboardListeningWay + .hiddenApi + .tr, + }), showCancel: true, onOk: () async { - appConfig.setClipboardListeningWay(ClipboardListeningWay.hiddenApi); + appConfig.setClipboardListeningWay( + ClipboardListeningWay.hiddenApi, + ); await clipboardManager.stopListening(); clipboardManager.startListening( env: appConfig.workingMode, way: ClipboardListeningWay.hiddenApi, - notificationContentConfig: ClipboardService.defaultNotificationContentConfig, + notificationContentConfig: + ClipboardService + .defaultNotificationContentConfig, ); }, ); @@ -171,25 +196,39 @@ class SettingsPage extends GetView { Expanded( child: Obx( () => ClipboardListeningWaySettingCard( - cardMargin: const EdgeInsets.only(right: 0, left: 3), + cardMargin: const EdgeInsets.only( + right: 0, + left: 3, + ), icon: Icons.list_alt, name: ClipboardListeningWay.logs.tr, - selected: appConfig.clipboardListeningWay == ClipboardListeningWay.logs, + selected: + appConfig.clipboardListeningWay == + ClipboardListeningWay.logs, onTap: () { - if (appConfig.clipboardListeningWay == ClipboardListeningWay.logs) { + if (appConfig.clipboardListeningWay == + ClipboardListeningWay.logs) { return; } Global.showTipsDialog( context: context, - text: TranslationKey.clipboardListeningWayToggleConfirmContent.trParams({"way": ClipboardListeningWay.logs.tr}), + text: TranslationKey + .clipboardListeningWayToggleConfirmContent + .trParams({ + "way": ClipboardListeningWay.logs.tr, + }), showCancel: true, onOk: () async { - appConfig.setClipboardListeningWay(ClipboardListeningWay.logs); + appConfig.setClipboardListeningWay( + ClipboardListeningWay.logs, + ); await clipboardManager.stopListening(); clipboardManager.startListening( env: appConfig.workingMode, way: ClipboardListeningWay.logs, - notificationContentConfig: ClipboardService.defaultNotificationContentConfig, + notificationContentConfig: + ClipboardService + .defaultNotificationContentConfig, ); }, ); @@ -211,14 +250,17 @@ class SettingsPage extends GetView { icon: const Icon(Icons.discount_outlined), cardList: [ SettingCard( - title: Text(TranslationKey.commonSettingsRunAtStartup.tr), + title: Text( + TranslationKey.commonSettingsRunAtStartup.tr, + ), value: appConfig.launchAtStartup, action: (v) => Switch( value: v, onChanged: (checked) async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); + PackageInfo packageInfo = + await PackageInfo.fromPlatform(); final appName = packageInfo.appName; - final appPath = Platform.resolvedExecutable; + final appPath = PlatformExt.startupExecutablePath; launchAtStartup.setup( appName: appName, appPath: appPath, @@ -234,7 +276,9 @@ class SettingsPage extends GetView { show: (v) => PlatformExt.isDesktop, ), SettingCard( - title: Text(TranslationKey.commonSettingsRunMinimize.tr), + title: Text( + TranslationKey.commonSettingsRunMinimize.tr, + ), value: appConfig.startMini, action: (v) => Switch( value: v, @@ -245,7 +289,11 @@ class SettingsPage extends GetView { show: (v) => PlatformExt.isDesktop, ), SettingCard( - title: Text(TranslationKey.commonSettingsShowHistoriesFloatWindow.tr), + title: Text( + TranslationKey + .commonSettingsShowHistoriesFloatWindow + .tr, + ), value: appConfig.showHistoryFloat, action: (v) => Switch( value: appConfig.showHistoryFloat, @@ -263,7 +311,9 @@ class SettingsPage extends GetView { ), SettingCard( title: Text( - TranslationKey.commonSettingsLockHistoriesFloatWindowPosition.tr, + TranslationKey + .commonSettingsLockHistoriesFloatWindowPosition + .tr, ), value: appConfig.lockHistoryFloatLoc, action: (v) => Switch( @@ -276,7 +326,8 @@ class SettingsPage extends GetView { appConfig.setLockHistoryFloatLoc(checked); }, ), - show: (v) => Platform.isAndroid && appConfig.showHistoryFloat, + show: (v) => + Platform.isAndroid && appConfig.showHistoryFloat, ), SettingCard( title: Text(TranslationKey.commonSettingsTheme.tr), @@ -298,7 +349,9 @@ class SettingsPage extends GetView { child: MouseRegion( cursor: SystemMouseCursors.click, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 5), + padding: const EdgeInsets.symmetric( + vertical: 5, + ), child: Icon(icon), ), ), @@ -316,16 +369,27 @@ class SettingsPage extends GetView { icon: icon, enabled: mode != v, onSelected: () async { - await appConfig.setAppTheme(mode, context, () { - final currentBg = controller.envStatusBgColor.value; - if (currentBg != null) { - controller.envStatusBgColor.value = controller.warningBgColor; - } - }); + await appConfig.setAppTheme( + mode, + context, + () { + final currentBg = controller + .envStatusBgColor + .value; + if (currentBg != null) { + controller + .envStatusBgColor + .value = + controller.warningBgColor; + } + }, + ); }, ); }).toList(), - position: details.globalPosition - const Offset(0, 50), + position: + details.globalPosition - + const Offset(0, 50), padding: const EdgeInsets.all(8.0), borderRadius: BorderRadius.circular(8), ); @@ -377,8 +441,12 @@ class SettingsPage extends GetView { icon: const Icon(Icons.admin_panel_settings), cardList: [ SettingCard( - title: Text(TranslationKey.permissionSettingsNotificationTitle.tr), - description: Text(TranslationKey.permissionSettingsNotificationDesc.tr), + title: Text( + TranslationKey.permissionSettingsNotificationTitle.tr, + ), + description: Text( + TranslationKey.permissionSettingsNotificationDesc.tr, + ), value: controller.hasNotifyPerm.value, action: (val) => Icon( val ? Icons.check_circle : Icons.help, @@ -392,8 +460,12 @@ class SettingsPage extends GetView { }, ), SettingCard( - title: Text(TranslationKey.permissionSettingsFloatTitle.tr), - description: Text(TranslationKey.permissionSettingsFloatDesc.tr), + title: Text( + TranslationKey.permissionSettingsFloatTitle.tr, + ), + description: Text( + TranslationKey.permissionSettingsFloatDesc.tr, + ), value: controller.hasFloatPerm.value, action: (val) => Icon( val ? Icons.check_circle : Icons.help, @@ -407,8 +479,16 @@ class SettingsPage extends GetView { }, ), SettingCard( - title: Text(TranslationKey.permissionSettingsBatteryOptimiseTitle.tr), - description: Text(TranslationKey.permissionSettingsBatteryOptimiseDesc.tr), + title: Text( + TranslationKey + .permissionSettingsBatteryOptimiseTitle + .tr, + ), + description: Text( + TranslationKey + .permissionSettingsBatteryOptimiseDesc + .tr, + ), value: controller.hasIgnoreBattery.value, action: (val) => Icon( val ? Icons.check_circle : Icons.help, @@ -422,8 +502,12 @@ class SettingsPage extends GetView { }, ), SettingCard( - title: Text(TranslationKey.permissionSettingsSmsTitle.tr), - description: Text(TranslationKey.permissionSettingsSmsDesc.tr), + title: Text( + TranslationKey.permissionSettingsSmsTitle.tr, + ), + description: Text( + TranslationKey.permissionSettingsSmsDesc.tr, + ), value: controller.hasSmsReadPerm.value, action: (val) => Icon( val ? Icons.check_circle : Icons.help, @@ -435,9 +519,18 @@ class SettingsPage extends GetView { }, ), SettingCard( - title: Text(TranslationKey.permissionSettingsAccessibilityTitle.tr), - description: Text(TranslationKey.permissionSettingsAccessibilityDesc.tr), - value: !controller.hasAccessibilityPerm.value && appConfig.sourceRecord && !appConfig.ignoreAccessibility, + title: Text( + TranslationKey + .permissionSettingsAccessibilityTitle + .tr, + ), + description: Text( + TranslationKey.permissionSettingsAccessibilityDesc.tr, + ), + value: + !controller.hasAccessibilityPerm.value && + appConfig.sourceRecord && + !appConfig.ignoreAccessibility, action: (val) => const Icon( Icons.help, color: Colors.orange, @@ -448,9 +541,21 @@ class SettingsPage extends GetView { }, ), SettingCard( - title: Text(TranslationKey.permissionSettingsNotificationRecordTitle.tr), - description: Text(TranslationKey.permissionSettingsNotificationRecordDesc.tr), - value: (!controller.hasNotificationRecordPerm.value && appConfig.enableRecordNotification) || (controller.hasNotificationRecordPerm.value && !appConfig.enableRecordNotification), + title: Text( + TranslationKey + .permissionSettingsNotificationRecordTitle + .tr, + ), + description: Text( + TranslationKey + .permissionSettingsNotificationRecordDesc + .tr, + ), + value: + (!controller.hasNotificationRecordPerm.value && + appConfig.enableRecordNotification) || + (controller.hasNotificationRecordPerm.value && + !appConfig.enableRecordNotification), action: (val) => const Icon( Icons.help, color: Colors.orange, @@ -461,8 +566,12 @@ class SettingsPage extends GetView { }, ), SettingCard( - title: Text(TranslationKey.permissionSettingsClipboardTitle.tr), - description: Text(TranslationKey.permissionSettingsClipboardDesc.tr), + title: Text( + TranslationKey.permissionSettingsClipboardTitle.tr, + ), + description: Text( + TranslationKey.permissionSettingsClipboardDesc.tr, + ), value: controller.hasClipboardPerm.value, action: (val) => const Icon( Icons.help, @@ -470,18 +579,38 @@ class SettingsPage extends GetView { ), show: (v) => Platform.isAndroid && !v, onTap: () async { - final isValidWorkingMode = appConfig.workingMode == EnvironmentType.shizuku ||appConfig.workingMode == EnvironmentType.root; - if(!isValidWorkingMode){ - Global.showTipsDialog(context: context, text: TranslationKey.clipboardPermissionRequestFailed.tr); + final isValidWorkingMode = + appConfig.workingMode == + EnvironmentType.shizuku || + appConfig.workingMode == EnvironmentType.root; + if (!isValidWorkingMode) { + Global.showTipsDialog( + context: context, + text: TranslationKey + .clipboardPermissionRequestFailed + .tr, + ); return; - }else{ + } else { try { - await clipboardManager.requestClipboardPermission(); - controller.hasClipboardPerm.value = await clipboardManager.checkClipboardPermission(); - final tips = controller.hasClipboardPerm.value ? TranslationKey.requestSuccess.tr : TranslationKey.requestFailed.tr; - Global.showSnackBarSuc(context: context, text: tips); + await clipboardManager + .requestClipboardPermission(); + controller.hasClipboardPerm.value = + await clipboardManager + .checkClipboardPermission(); + final tips = controller.hasClipboardPerm.value + ? TranslationKey.requestSuccess.tr + : TranslationKey.requestFailed.tr; + Global.showSnackBarSuc( + context: context, + text: tips, + ); } catch (err, stack) { - Global.showTipsDialog(context: context, text: "$err,$stack", title: TranslationKey.requestFailed.tr); + Global.showTipsDialog( + context: context, + text: "$err,$stack", + title: TranslationKey.requestFailed.tr, + ); } } }, @@ -500,7 +629,9 @@ class SettingsPage extends GetView { cardList: [ SettingCard( title: Text( - TranslationKey.preferenceSettingsRememberWindowSize.tr, + TranslationKey + .preferenceSettingsRememberWindowSize + .tr, ), description: Text( "${appConfig.rememberWindowSize ? "${TranslationKey.preferenceSettingsWindowSizeRecordValue.tr}: ${appConfig.windowSize}," : ""}${TranslationKey.preferenceSettingsWindowSizeDefaultValue.tr}: ${Constants.defaultWindowSize}", @@ -518,9 +649,13 @@ class SettingsPage extends GetView { //弹窗记住上次位置 SettingCard( title: Text( - TranslationKey.preferenceSettingsRecordsDialogLocation.tr, + TranslationKey + .preferenceSettingsRecordsDialogLocation + .tr, + ), + description: Text( + "${TranslationKey.current.tr}: ${appConfig.recordHistoryDialogPosition ? TranslationKey.rememberLastPos.tr : TranslationKey.followMousePos.tr}", ), - description: Text("${TranslationKey.current.tr}: ${appConfig.recordHistoryDialogPosition ? TranslationKey.rememberLastPos.tr : TranslationKey.followMousePos.tr}"), value: appConfig.recordHistoryDialogPosition, action: (v) => Switch( value: v, @@ -551,18 +686,22 @@ class SettingsPage extends GetView { ), SettingCard( title: Text(TranslationKey.showOnRecentTasks.tr), - description: Text(TranslationKey.showOnRecentTasksDesc.tr), + description: Text( + TranslationKey.showOnRecentTasksDesc.tr, + ), value: appConfig.showOnRecentTasks, action: (v) { return Switch( value: v, onChanged: (checked) { HapticFeedback.mediumImpact(); - androidChannelService.showOnRecentTasks(checked).then((v) { - if (v) { - appConfig.setShowOnRecentTasks(checked); - } - }); + androidChannelService + .showOnRecentTasks(checked) + .then((v) { + if (v) { + appConfig.setShowOnRecentTasks(checked); + } + }); }, ); }, @@ -570,7 +709,9 @@ class SettingsPage extends GetView { ), SettingCard( title: Text(TranslationKey.showMoreItemsInRow.tr), - description: Text(TranslationKey.showMoreItemsInRowDesc.tr), + description: Text( + TranslationKey.showMoreItemsInRowDesc.tr, + ), value: appConfig.showMoreItemsInRow, action: (v) { return Switch( @@ -585,7 +726,9 @@ class SettingsPage extends GetView { ), SettingCard( title: Text(TranslationKey.closeOnSameHotKeyTitle.tr), - description: Text(TranslationKey.closeOnSameHotKeyDesc.tr), + description: Text( + TranslationKey.closeOnSameHotKeyDesc.tr, + ), value: appConfig.closeOnSameHotKey, action: (v) { return Switch( @@ -617,22 +760,30 @@ class SettingsPage extends GetView { value: v, onChanged: (checked) async { HapticFeedback.mediumImpact(); - final androidNotificationListenerService = Get.find(); + final androidNotificationListenerService = + Get.find(); if (checked) { - var isGranted = await NotificationListenerService.isPermissionGranted(); + var isGranted = + await NotificationListenerService.isPermissionGranted(); if (!isGranted) { await NotificationListenerService.requestPermission(); - isGranted = await NotificationListenerService.isPermissionGranted(); + isGranted = + await NotificationListenerService.isPermissionGranted(); if (isGranted) { - appConfig.setEnableRecordNotification(checked); - androidNotificationListenerService.startListening(); + appConfig.setEnableRecordNotification( + checked, + ); + androidNotificationListenerService + .startListening(); } return; } else { - androidNotificationListenerService.startListening(); + androidNotificationListenerService + .startListening(); } } else { - androidNotificationListenerService.stopListening(); + androidNotificationListenerService + .stopListening(); } appConfig.setEnableRecordNotification(checked); }, @@ -641,7 +792,9 @@ class SettingsPage extends GetView { ), SettingCard( title: Text( - TranslationKey.preferenceSettingsDevConnNotification.tr, + TranslationKey + .preferenceSettingsDevConnNotification + .tr, ), value: appConfig.notifyOnDevConn, action: (v) => Switch( @@ -655,7 +808,9 @@ class SettingsPage extends GetView { ), SettingCard( title: Text( - TranslationKey.preferenceSettingsDevDisconnNotification.tr, + TranslationKey + .preferenceSettingsDevDisconnNotification + .tr, ), value: appConfig.notifyOnDevDisconn, action: (v) => Switch( @@ -668,8 +823,16 @@ class SettingsPage extends GetView { show: (v) => true, ), SettingCard( - title: Text(TranslationKey.preferenceSettingsShowMobileNotificationTitle.tr), - description: Text(TranslationKey.preferenceSettingsShowMobileNotificationDesc.tr), + title: Text( + TranslationKey + .preferenceSettingsShowMobileNotificationTitle + .tr, + ), + description: Text( + TranslationKey + .preferenceSettingsShowMobileNotificationDesc + .tr, + ), value: appConfig.enableShowMobileNotification, action: (v) => Switch( value: v, @@ -694,10 +857,16 @@ class SettingsPage extends GetView { cardList: [ SettingCard( title: Text( - TranslationKey.stopListeningOnScreenClosedSettingTitle.tr, + TranslationKey + .stopListeningOnScreenClosedSettingTitle + .tr, maxLines: 1, ), - description: Text(TranslationKey.stopListeningOnScreenClosedSettingDesc.tr), + description: Text( + TranslationKey + .stopListeningOnScreenClosedSettingDesc + .tr, + ), value: appConfig.stopListeningOnScreenClosed, show: (v) => Platform.isAndroid, action: (v) { @@ -714,14 +883,18 @@ class SettingsPage extends GetView { title: Row( children: [ Text( - TranslationKey.clipboardSettingsSourceRecordTitle.tr, + TranslationKey + .clipboardSettingsSourceRecordTitle + .tr, maxLines: 1, ), if (Platform.isAndroid) Container( margin: const EdgeInsets.only(left: 5), child: Tooltip( - message: TranslationKey.clipboardSettingsSourceRecordTitleTooltip.tr, + message: TranslationKey + .clipboardSettingsSourceRecordTitleTooltip + .tr, child: GestureDetector( child: const MouseRegion( cursor: SystemMouseCursors.click, @@ -734,7 +907,9 @@ class SettingsPage extends GetView { onTap: () async { Global.showTipsDialog( context: context, - text: TranslationKey.clipboardSettingsSourceRecordTitleTooltipDialogContent.tr, + text: TranslationKey + .clipboardSettingsSourceRecordTitleTooltipDialogContent + .tr, ); }, ), @@ -744,7 +919,11 @@ class SettingsPage extends GetView { ), description: Visibility( visible: Platform.isAndroid, - child: Text(TranslationKey.clipboardSettingsSourceRecordAndroidDesc.tr), + child: Text( + TranslationKey + .clipboardSettingsSourceRecordAndroidDesc + .tr, + ), ), value: appConfig.sourceRecord, action: (v) { @@ -753,11 +932,15 @@ class SettingsPage extends GetView { onChanged: (checked) { HapticFeedback.mediumImpact(); appConfig.setEnableSourceRecord(checked); - if (Platform.isAndroid && checked && !controller.hasAccessibilityPerm.value && !appConfig.ignoreAccessibility) { + if (Platform.isAndroid && + checked && + !controller.hasAccessibilityPerm.value && + !appConfig.ignoreAccessibility) { //检查无障碍 Global.showTipsDialog( context: context, - text: TranslationKey.noAccessibilityPermTips.tr, + text: + TranslationKey.noAccessibilityPermTips.tr, showCancel: true, okText: TranslationKey.goAuthorize.tr, onOk: () { @@ -778,12 +961,16 @@ class SettingsPage extends GetView { title: Row( children: [ Text( - TranslationKey.clipboardSettingsSourceRecordViaDumpsysTitle.tr, + TranslationKey + .clipboardSettingsSourceRecordViaDumpsysTitle + .tr, maxLines: 1, ), const SizedBox(width: 5), Tooltip( - message: TranslationKey.clipboardSettingsSourceRecordViaDumpsysTitleTooltip.tr, + message: TranslationKey + .clipboardSettingsSourceRecordViaDumpsysTitleTooltip + .tr, child: GestureDetector( child: const MouseRegion( cursor: SystemMouseCursors.click, @@ -796,25 +983,34 @@ class SettingsPage extends GetView { onTap: () async { Global.showTipsDialog( context: context, - text: TranslationKey.clipboardSettingsSourceRecordViaDumpsysTitleTooltipDialogContent.tr, + text: TranslationKey + .clipboardSettingsSourceRecordViaDumpsysTitleTooltipDialogContent + .tr, ); }, ), ), ], ), - description: Text(TranslationKey.clipboardSettingsSourceRecordViaDumpsysAndroidDesc.tr), + description: Text( + TranslationKey + .clipboardSettingsSourceRecordViaDumpsysAndroidDesc + .tr, + ), value: appConfig.sourceRecordViaDumpsys, action: (v) { return Switch( value: v, onChanged: (checked) async { HapticFeedback.mediumImpact(); - appConfig.setEnableSourceRecordViaDumpsys(checked); + appConfig.setEnableSourceRecordViaDumpsys( + checked, + ); }, ); }, - show: (v) => Platform.isAndroid && appConfig.sourceRecord, + show: (v) => + Platform.isAndroid && appConfig.sourceRecord, ), SettingCard( title: Row( @@ -838,14 +1034,18 @@ class SettingsPage extends GetView { onTap: () async { Global.showTipsDialog( context: context, - text: TranslationKey.sendBroadcastOnAddDataTips.tr, + text: TranslationKey + .sendBroadcastOnAddDataTips + .tr, ); }, ), ), ], ), - description: Text(TranslationKey.sendBroadcastOnAddDataDesc.tr), + description: Text( + TranslationKey.sendBroadcastOnAddDataDesc.tr, + ), value: appConfig.sendBroadcastOnAdd, action: (v) { return Switch( @@ -863,7 +1063,9 @@ class SettingsPage extends GetView { TranslationKey.excludePrivateFormat.tr, maxLines: 1, ), - description: Text(TranslationKey.excludePrivateFormatTips.tr), + description: Text( + TranslationKey.excludePrivateFormatTips.tr, + ), value: appConfig.isExcludeFormat, action: (v) { return Switch( @@ -892,7 +1094,9 @@ class SettingsPage extends GetView { title: Row( children: [ Text( - TranslationKey.discoveringSettingsLocalDeviceName.tr, + TranslationKey + .discoveringSettingsLocalDeviceName + .tr, maxLines: 1, ), const SizedBox(width: 5), @@ -906,7 +1110,9 @@ class SettingsPage extends GetView { ); Global.showSnackBarSuc( context: context, - text: TranslationKey.discoveringSettingsDeviceNameCopyTip.tr, + text: TranslationKey + .discoveringSettingsDeviceNameCopyTip + .tr, ); }, tooltip: TranslationKey.copyDeviceId.tr, @@ -929,7 +1135,9 @@ class SettingsPage extends GetView { appConfig.setLocalName(str); Global.showSnackBarSuc( context: context, - text: TranslationKey.modifyDeviceNameCompletedTooltip.tr, + text: TranslationKey + .modifyDeviceNameCompletedTooltip + .tr, ); }, ), @@ -941,7 +1149,9 @@ class SettingsPage extends GetView { TranslationKey.port.tr, maxLines: 1, ), - description: Text(TranslationKey.discoveringSettingsPortDesc.tr), + description: Text( + TranslationKey.discoveringSettingsPortDesc.tr, + ), value: appConfig.port, action: (v) => Text(v.toString()), onTap: () { @@ -961,7 +1171,9 @@ class SettingsPage extends GetView { appConfig.setPort(str.toInt()); Global.showSnackBarSuc( context: context, - text: TranslationKey.discoveringSettingsModifyPortCompletedTooltip.tr, + text: TranslationKey + .discoveringSettingsModifyPortCompletedTooltip + .tr, ); }, ), @@ -973,7 +1185,11 @@ class SettingsPage extends GetView { TranslationKey.allowDiscovering.tr, maxLines: 1, ), - description: Text(TranslationKey.discoveringSettingsAllowDiscoveringDesc.tr), + description: Text( + TranslationKey + .discoveringSettingsAllowDiscoveringDesc + .tr, + ), value: appConfig.allowDiscover, action: (v) => Switch( value: v, @@ -986,10 +1202,16 @@ class SettingsPage extends GetView { ), SettingCard( title: Text( - TranslationKey.discoveringSettingsOnlyForwardDiscoveringTitle.tr, + TranslationKey + .discoveringSettingsOnlyForwardDiscoveringTitle + .tr, maxLines: 1, ), - description: Text(TranslationKey.discoveringSettingsOnlyForwardDiscoveringDesc.tr), + description: Text( + TranslationKey + .discoveringSettingsOnlyForwardDiscoveringDesc + .tr, + ), value: appConfig.onlyForwardMode, action: (v) => Switch( value: v, @@ -1004,14 +1226,18 @@ class SettingsPage extends GetView { title: Row( children: [ Text( - TranslationKey.discoveringSettingsHeartbeatIntervalTitle.tr, + TranslationKey + .discoveringSettingsHeartbeatIntervalTitle + .tr, maxLines: 1, ), const SizedBox( width: 5, ), Tooltip( - message: TranslationKey.discoveringSettingsHeartbeatIntervalTooltip.tr, + message: TranslationKey + .discoveringSettingsHeartbeatIntervalTooltip + .tr, child: GestureDetector( child: const MouseRegion( cursor: SystemMouseCursors.click, @@ -1024,29 +1250,44 @@ class SettingsPage extends GetView { onTap: () async { Global.showTipsDialog( context: context, - text: TranslationKey.discoveringSettingsHeartbeatIntervalTooltipDialogContent.tr, + text: TranslationKey + .discoveringSettingsHeartbeatIntervalTooltipDialogContent + .tr, ); }, ), ), ], ), - description: Text(TranslationKey.discoveringSettingsHeartbeatIntervalDesc.tr), + description: Text( + TranslationKey + .discoveringSettingsHeartbeatIntervalDesc + .tr, + ), value: appConfig.heartbeatInterval, - action: (v) => Text(v <= 0 ? TranslationKey.dontDetect.tr : '${v}s'), + action: (v) => Text( + v <= 0 ? TranslationKey.dontDetect.tr : '${v}s', + ), onTap: () { Global.showDialog( context, TextEditDialog( - title: TranslationKey.discoveringSettingsModifyHeartbeatDialogTitle.tr, - labelText: TranslationKey.discoveringSettingsModifyHeartbeatDialogInputLabel.tr, - initStr: "${appConfig.heartbeatInterval <= 0 ? '' : appConfig.heartbeatInterval}", + title: TranslationKey + .discoveringSettingsModifyHeartbeatDialogTitle + .tr, + labelText: TranslationKey + .discoveringSettingsModifyHeartbeatDialogInputLabel + .tr, + initStr: + "${appConfig.heartbeatInterval <= 0 ? '' : appConfig.heartbeatInterval}", verify: (str) { var port = int.tryParse(str); if (port == null) return false; return true; }, - errorText: TranslationKey.discoveringSettingsModifyHeartbeatDialogInputErrorText.tr, + errorText: TranslationKey + .discoveringSettingsModifyHeartbeatDialogInputErrorText + .tr, onOk: (str) async { await appConfig.setHeartbeatInterval(str); var enable = str.toInt() > 0; @@ -1065,7 +1306,9 @@ class SettingsPage extends GetView { TranslationKey.syncAutoCloseSettingTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.syncAutoCloseSettingDesc.tr), + description: Text( + TranslationKey.syncAutoCloseSettingDesc.tr, + ), value: appConfig.autoCloseConnAfterScreenOff, show: (v) => Platform.isAndroid, action: (v) { @@ -1083,7 +1326,9 @@ class SettingsPage extends GetView { TranslationKey.enableAutoSyncOnScreenOpenedTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.enableAutoSyncOnScreenOpenedDesc.tr), + description: Text( + TranslationKey.enableAutoSyncOnScreenOpenedDesc.tr, + ), value: appConfig.enableAutoSyncOnScreenOpened, show: (v) => Platform.isAndroid, action: (v) { @@ -1091,17 +1336,25 @@ class SettingsPage extends GetView { value: v, onChanged: (checked) async { HapticFeedback.mediumImpact(); - appConfig.setEnableAutoSyncOnScreenOpened(checked); + appConfig.setEnableAutoSyncOnScreenOpened( + checked, + ); }, ); }, ), SettingCard( title: Text( - TranslationKey.onlyManualDiscoverySubNetSettingTitle.tr, + TranslationKey + .onlyManualDiscoverySubNetSettingTitle + .tr, maxLines: 1, ), - description: Text(TranslationKey.onlyManualDiscoverySubNetSettingDesc.tr), + description: Text( + TranslationKey + .onlyManualDiscoverySubNetSettingDesc + .tr, + ), value: appConfig.onlyManualDiscoverySubNet, action: (v) { return Switch( @@ -1118,7 +1371,9 @@ class SettingsPage extends GetView { TranslationKey.noDiscoveryIfsSettingTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.noDiscoveryIfsSettingDesc.tr), + description: Text( + TranslationKey.noDiscoveryIfsSettingDesc.tr, + ), value: appConfig.noDiscoveryIfs, action: (v) { return TextButton( @@ -1127,9 +1382,18 @@ class SettingsPage extends GetView { final interfaces = await NetworkInterface.list(); final selections = interfaces.map((itf) { var showTextList = [itf.name]; - var ipList = itf.addresses.where((address) => address.type == InternetAddressType.IPv4).map((address) => address.address); + var ipList = itf.addresses + .where( + (address) => + address.type == + InternetAddressType.IPv4, + ) + .map((address) => address.address); showTextList.addAll(ipList); - return CheckboxData(value: itf.name, text: showTextList.join('\n')); + return CheckboxData( + value: itf.name, + text: showTextList.join('\n'), + ); }).toList(); DialogController? dialog; dialog = MultiSelectDialog.show( @@ -1147,7 +1411,9 @@ class SettingsPage extends GetView { minSelectedCnt: 0, selections: selections, textStyle: const TextStyle(fontSize: 13), - title: Text(TranslationKey.noDiscoveryIfsSettingTitle.tr), + title: Text( + TranslationKey.noDiscoveryIfsSettingTitle.tr, + ), ); }, ); @@ -1198,9 +1464,12 @@ class SettingsPage extends GetView { enabled: v != ForwardWay.server, onSelected: () async { void setup() async { - await appConfig.setForwardWay(ForwardWay.server); + await appConfig.setForwardWay( + ForwardWay.server, + ); await storageService.stop(); - if (!appConfig.enableForward || appConfig.forwardServer == null) { + if (!appConfig.enableForward || + appConfig.forwardServer == null) { //若无配置,关闭中转 await appConfig.setEnableForward(false); return; @@ -1208,13 +1477,16 @@ class SettingsPage extends GetView { sktService.connectForwardServer(true); } - if (appConfig.forwardWay == ForwardWay.none || !appConfig.enableForward) { + if (appConfig.forwardWay == ForwardWay.none || + !appConfig.enableForward) { setup(); return; } Global.showTipsDialog( context: context, - text: TranslationKey.changeForwardWayConfirm.tr, + text: TranslationKey + .changeForwardWayConfirm + .tr, showCancel: true, onOk: setup, ); @@ -1226,9 +1498,12 @@ class SettingsPage extends GetView { enabled: v != ForwardWay.webdav, onSelected: () { void setup() async { - await appConfig.setForwardWay(ForwardWay.webdav); + await appConfig.setForwardWay( + ForwardWay.webdav, + ); await sktService.disConnectForwardServer(); - if (!appConfig.enableForward || appConfig.webDAVConfig == null) { + if (!appConfig.enableForward || + appConfig.webDAVConfig == null) { //若无配置,关闭中转 await appConfig.setEnableForward(false); return; @@ -1236,13 +1511,16 @@ class SettingsPage extends GetView { storageService.restart(); } - if (appConfig.forwardWay == ForwardWay.none || !appConfig.enableForward) { + if (appConfig.forwardWay == ForwardWay.none || + !appConfig.enableForward) { setup(); return; } Global.showTipsDialog( context: context, - text: TranslationKey.changeForwardWayConfirm.tr, + text: TranslationKey + .changeForwardWayConfirm + .tr, showCancel: true, onOk: setup, ); @@ -1254,9 +1532,12 @@ class SettingsPage extends GetView { enabled: v != ForwardWay.s3, onSelected: () async { void setup() async { - await appConfig.setForwardWay(ForwardWay.s3); + await appConfig.setForwardWay( + ForwardWay.s3, + ); await sktService.disConnectForwardServer(); - if (!appConfig.enableForward || appConfig.s3Config == null) { + if (!appConfig.enableForward || + appConfig.s3Config == null) { //若无配置,关闭中转 await appConfig.setEnableForward(false); return; @@ -1264,13 +1545,16 @@ class SettingsPage extends GetView { storageService.restart(); } - if (appConfig.forwardWay == ForwardWay.none || !appConfig.enableForward) { + if (appConfig.forwardWay == ForwardWay.none || + !appConfig.enableForward) { setup(); return; } Global.showTipsDialog( context: context, - text: TranslationKey.changeForwardWayConfirm.tr, + text: TranslationKey + .changeForwardWayConfirm + .tr, showCancel: true, onOk: setup, ); @@ -1283,7 +1567,9 @@ class SettingsPage extends GetView { onSelected: () async { Future setup() async { await appConfig.setEnableForward(false); - await appConfig.setForwardWay(ForwardWay.none); + await appConfig.setForwardWay( + ForwardWay.none, + ); await sktService.disConnectForwardServer(); await storageService.stop(); } @@ -1294,7 +1580,9 @@ class SettingsPage extends GetView { } Global.showTipsDialog( context: context, - text: TranslationKey.changeForwardWayConfirm.tr, + text: TranslationKey + .changeForwardWayConfirm + .tr, showCancel: true, onOk: () async { setup(); @@ -1303,7 +1591,10 @@ class SettingsPage extends GetView { }, ), ], - position: Offset(Get.size.width, details.globalPosition.dy - 50), + position: Offset( + Get.size.width, + details.globalPosition.dy - 50, + ), padding: 8.insetAll, borderRadius: BorderRadius.circular(8), ); @@ -1316,7 +1607,11 @@ class SettingsPage extends GetView { title: Row( children: [ Text( - appConfig.forwardWay == ForwardWay.server ? TranslationKey.forwardServerStatus.tr : TranslationKey.notificationServerStatus.tr, + appConfig.forwardWay == ForwardWay.server + ? TranslationKey.forwardServerStatus.tr + : TranslationKey + .notificationServerStatus + .tr, maxLines: 1, ), if (appConfig.forwardWay != ForwardWay.server) @@ -1334,7 +1629,9 @@ class SettingsPage extends GetView { onTap: () async { Global.showTipsDialog( context: context, - text: TranslationKey.notificationServerTips.tr, + text: TranslationKey + .notificationServerTips + .tr, ); }, ), @@ -1345,7 +1642,8 @@ class SettingsPage extends GetView { children: [ Dot( radius: 6.0, - color: controller.forwardServerStatus.value.color, + color: + controller.forwardServerStatus.value.color, ), const SizedBox(width: 5), Text(controller.forwardServerStatus.value.tr), @@ -1361,14 +1659,23 @@ class SettingsPage extends GetView { Global.showDialog( context, NotificationServerEditDialog( - title: TranslationKey.notificationServerConfigure.tr, - labelText: TranslationKey.notificationServerAddress.tr, + title: TranslationKey + .notificationServerConfigure + .tr, + labelText: TranslationKey + .notificationServerAddress + .tr, initStr: appConfig.notificationServer, hint: 'ws://', - verify: (s) => s.matchRegExp(Constants.wsUrlRegex), - errorText: TranslationKey.pleaseInputCorrectWsURL.tr, + verify: (s) => + s.matchRegExp(Constants.wsUrlRegex), + errorText: TranslationKey + .pleaseInputCorrectWsURL + .tr, onOk: (result) { - appConfig.setNotificationServer(result.trimEnd('/')); + appConfig.setNotificationServer( + result.trimEnd('/'), + ); if (appConfig.enableForward) { storageService.reconnectWs(); } @@ -1392,7 +1699,9 @@ class SettingsPage extends GetView { const SizedBox(width: 5), if (appConfig.forwardWay == ForwardWay.server) Tooltip( - message: TranslationKey.forwardSettingsForwardDownloadTooltip.tr, + message: TranslationKey + .forwardSettingsForwardDownloadTooltip + .tr, child: GestureDetector( child: const MouseRegion( cursor: SystemMouseCursors.click, @@ -1409,35 +1718,48 @@ class SettingsPage extends GetView { ), ], ), - description: Text(TranslationKey.forwardSettingsForwardDesc.tr), + description: Text( + TranslationKey.forwardSettingsForwardDesc.tr, + ), value: appConfig.enableForward, action: (v) { return Switch( value: v, onChanged: (checked) async { HapticFeedback.mediumImpact(); - final useServer = appConfig.forwardWay == ForwardWay.server; + final useServer = + appConfig.forwardWay == ForwardWay.server; //启用中转服务器前先校验是否填写服务器地址 - if (useServer && appConfig.forwardServer == null) { + if (useServer && + appConfig.forwardServer == null) { Global.showSnackBarErr( context: context, - text: TranslationKey.forwardSettingsForwardEnableRequiredText.tr, + text: TranslationKey + .forwardSettingsForwardEnableRequiredText + .tr, ); return; } - final useWebdav = appConfig.forwardWay == ForwardWay.webdav; - if (useWebdav && appConfig.webDAVConfig == null) { + final useWebdav = + appConfig.forwardWay == ForwardWay.webdav; + if (useWebdav && + appConfig.webDAVConfig == null) { Global.showSnackBarErr( context: context, - text: TranslationKey.forwardSettingsForwardEnableRequiredWebDAVText.tr, + text: TranslationKey + .forwardSettingsForwardEnableRequiredWebDAVText + .tr, ); return; } - final useS3 = appConfig.forwardWay == ForwardWay.s3; + final useS3 = + appConfig.forwardWay == ForwardWay.s3; if (useS3 && appConfig.s3Config == null) { Global.showSnackBarErr( context: context, - text: TranslationKey.forwardSettingsForwardEnableRequiredS3Text.tr, + text: TranslationKey + .forwardSettingsForwardEnableRequiredS3Text + .tr, ); return; } @@ -1462,10 +1784,14 @@ class SettingsPage extends GetView { if (appConfig.forwardWay == ForwardWay.server) SettingCard( title: Text( - TranslationKey.forwardSettingsForwardAddressTitle.tr, + TranslationKey + .forwardSettingsForwardAddressTitle + .tr, maxLines: 1, ), - description: Text(TranslationKey.forwardSettingsForwardAddressDesc.tr), + description: Text( + TranslationKey.forwardSettingsForwardAddressDesc.tr, + ), value: appConfig.forwardServer, action: (v) { String text = TranslationKey.change.tr; @@ -1480,12 +1806,19 @@ class SettingsPage extends GetView { Global.showDialog( context, QrImageDialog( - title: Text(TranslationKey.forwardServer.tr), - data: jsonEncode(appConfig.forwardServer!), + title: Text( + TranslationKey.forwardServer.tr, + ), + data: jsonEncode( + appConfig.forwardServer!, + ), ), ); }, - icon: const Icon(Icons.qr_code, color: Colors.blueGrey), + icon: const Icon( + Icons.qr_code, + color: Colors.blueGrey, + ), ), TextButton( onPressed: () { @@ -1511,7 +1844,11 @@ class SettingsPage extends GetView { TranslationKey.forwardSettingsWebDAVTitle.tr, maxLines: 1, ), - description: Text(appConfig.webDAVConfig?.displayName ?? TranslationKey.noConfig.tr, maxLines: 1), + description: Text( + appConfig.webDAVConfig?.displayName ?? + TranslationKey.noConfig.tr, + maxLines: 1, + ), value: appConfig.webDAVConfig, action: (v) { String text = TranslationKey.change.tr; @@ -1527,11 +1864,16 @@ class SettingsPage extends GetView { context, QrImageDialog( title: const Text("WebDAV"), - data: jsonEncode(appConfig.webDAVConfig!), + data: jsonEncode( + appConfig.webDAVConfig!, + ), ), ); }, - icon: const Icon(Icons.qr_code, color: Colors.blueGrey), + icon: const Icon( + Icons.qr_code, + color: Colors.blueGrey, + ), ), TextButton( onPressed: () { @@ -1560,7 +1902,11 @@ class SettingsPage extends GetView { TranslationKey.forwardSettingsS3Title.tr, maxLines: 1, ), - description: Text(appConfig.s3Config?.displayName ?? TranslationKey.noConfig.tr, maxLines: 1), + description: Text( + appConfig.s3Config?.displayName ?? + TranslationKey.noConfig.tr, + maxLines: 1, + ), value: appConfig.s3Config, action: (v) { String text = TranslationKey.change.tr; @@ -1580,7 +1926,10 @@ class SettingsPage extends GetView { ), ); }, - icon: const Icon(Icons.qr_code, color: Colors.blueGrey), + icon: const Icon( + Icons.qr_code, + color: Colors.blueGrey, + ), ), TextButton( onPressed: () { @@ -1620,7 +1969,9 @@ class SettingsPage extends GetView { TranslationKey.securitySettingsEnableSecurityTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.securitySettingsEnableSecurityDesc.tr), + description: Text( + TranslationKey.securitySettingsEnableSecurityDesc.tr, + ), value: appConfig.useAuthentication, action: (v) { return Switch( @@ -1630,9 +1981,13 @@ class SettingsPage extends GetView { if (appConfig.appPassword == null && checked) { Global.showTipsDialog( context: context, - text: TranslationKey.securitySettingsEnableSecurityAppPwdRequiredDialogContent.tr, + text: TranslationKey + .securitySettingsEnableSecurityAppPwdRequiredDialogContent + .tr, onOk: controller.gotoSetPwd, - okText: TranslationKey.securitySettingsEnableSecurityAppPwdRequiredDialogOkText.tr, + okText: TranslationKey + .securitySettingsEnableSecurityAppPwdRequiredDialogOkText + .tr, showCancel: true, ); appConfig.setUseAuthentication(false); @@ -1645,10 +2000,16 @@ class SettingsPage extends GetView { ), SettingCard( title: Text( - TranslationKey.securitySettingsEnableSecurityAppPwdModifyTitle.tr, + TranslationKey + .securitySettingsEnableSecurityAppPwdModifyTitle + .tr, maxLines: 1, ), - description: Text(appConfig.appPassword == null ? TranslationKey.createAppPwd.tr : TranslationKey.changeAppPwd.tr), + description: Text( + appConfig.appPassword == null + ? TranslationKey.createAppPwd.tr + : TranslationKey.changeAppPwd.tr, + ), value: appConfig.appPassword, action: (v) { return TextButton( @@ -1658,7 +2019,8 @@ class SettingsPage extends GetView { } else { //第一步验证 appConfig.authenticating.value = true; - final homeController = Get.find(); + final homeController = + Get.find(); homeController .gotoAuthenticationPage( TranslationKey.authenticationPageTitle.tr, @@ -1672,7 +2034,11 @@ class SettingsPage extends GetView { }); } }, - child: Text(appConfig.appPassword == null ? TranslationKey.create.tr : TranslationKey.change.tr), + child: Text( + appConfig.appPassword == null + ? TranslationKey.create.tr + : TranslationKey.change.tr, + ), ); }, ), @@ -1681,7 +2047,9 @@ class SettingsPage extends GetView { TranslationKey.securitySettingsReverificationTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.securitySettingsReverificationDesc.tr), + description: Text( + TranslationKey.securitySettingsReverificationDesc.tr, + ), value: appConfig.appRevalidateDuration, onTap: () { DialogController? dialog; @@ -1697,24 +2065,38 @@ class SettingsPage extends GetView { ); }, selections: Constants.authBackEndTimeSelections, - title: Text(TranslationKey.securitySettingsReverificationTitle.tr), + title: Text( + TranslationKey + .securitySettingsReverificationTitle + .tr, + ), ); }, action: (v) { var duration = appConfig.appRevalidateDuration; return Text( - duration <= 0 ? TranslationKey.immediately.tr : TranslationKey.securitySettingsReverificationValue.trParams({"value": duration.toString()}), + duration <= 0 + ? TranslationKey.immediately.tr + : TranslationKey + .securitySettingsReverificationValue + .trParams({"value": duration.toString()}), ); }, ), SettingCard( title: Row( children: [ - Text(TranslationKey.dhKeySettingName.tr, maxLines: 1), + Text( + TranslationKey.dhKeySettingName.tr, + maxLines: 1, + ), const SizedBox(width: 5), GestureDetector( onTap: () { - Global.showTipsDialog(context: context, text: TranslationKey.dhKeySettingTips.tr); + Global.showTipsDialog( + context: context, + text: TranslationKey.dhKeySettingTips.tr, + ); }, child: const Icon( Icons.info_outline, @@ -1728,14 +2110,22 @@ class SettingsPage extends GetView { value: appConfig.dhEncryptKey, action: (v) { return TextButton( - child: Text(v.isNullOrEmpty ? TranslationKey.configure.tr : TranslationKey.change.tr), + child: Text( + v.isNullOrEmpty + ? TranslationKey.configure.tr + : TranslationKey.change.tr, + ), onPressed: () { if (appConfig.appPassword == null) { Global.showTipsDialog( context: context, - text: TranslationKey.securitySettingsEnableSecurityAppPwdRequiredDialogContent.tr, + text: TranslationKey + .securitySettingsEnableSecurityAppPwdRequiredDialogContent + .tr, onOk: controller.gotoSetPwd, - okText: TranslationKey.securitySettingsEnableSecurityAppPwdRequiredDialogOkText.tr, + okText: TranslationKey + .securitySettingsEnableSecurityAppPwdRequiredDialogOkText + .tr, showCancel: true, ); return; @@ -1751,33 +2141,62 @@ class SettingsPage extends GetView { ) ?.then((v) { if (v == null) { - Global.showSnackBarWarn(text: TranslationKey.authFailed.tr, context: context); + Global.showSnackBarWarn( + text: TranslationKey.authFailed.tr, + context: context, + ); return; } Global.showDialog( context, TextEditDialog( title: TranslationKey.encryptKey.tr, - labelText: TranslationKey.pleaseInput.tr, - initStr: appConfig.dhEncryptKey.isEmpty ? '' : appConfig.dhEncryptKey, + labelText: + TranslationKey.pleaseInput.tr, + initStr: appConfig.dhEncryptKey.isEmpty + ? '' + : appConfig.dhEncryptKey, verify: (str) { - return (str.isEmpty && (appConfig.dhAesKey ?? '').isNotEmpty) || str.replaceAll('\\s+', '').length >= 8; + return (str.isEmpty && + (appConfig.dhAesKey ?? '') + .isNotEmpty) || + str + .replaceAll('\\s+', '') + .length >= + 8; }, - errorText: TranslationKey.encryptKeyErrorTip.tr, + errorText: TranslationKey + .encryptKeyErrorTip + .tr, onOk: (str) async { if (str.isEmpty) { Global.showTipsDialog( context: context, - text: TranslationKey.confirmClearEncryptKey.tr, + text: TranslationKey + .confirmClearEncryptKey + .tr, showCancel: true, onOk: () async { - await appConfig.setDHEncryptKey(str); - Global.showSnackBarSuc(text: TranslationKey.clearSuccess.tr, context: context); + await appConfig.setDHEncryptKey( + str, + ); + Global.showSnackBarSuc( + text: TranslationKey + .clearSuccess + .tr, + context: context, + ); }, ); } else { - await appConfig.setDHEncryptKey(str); - Global.showSnackBarSuc(text: TranslationKey.saveSuccess.tr, context: context); + await appConfig.setDHEncryptKey( + str, + ); + Global.showSnackBarSuc( + text: + TranslationKey.saveSuccess.tr, + context: context, + ); } }, ), @@ -1804,10 +2223,14 @@ class SettingsPage extends GetView { TranslationKey.hotKeySettingsHistoryTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.hotKeySettingsHistoryDesc.tr), + description: Text( + TranslationKey.hotKeySettingsHistoryDesc.tr, + ), value: appConfig.historyWindowHotKeys, action: (v) { - final desc = AppHotKeyHandler.getByType(HotKeyType.historyWindow)?.desc; + final desc = AppHotKeyHandler.getByType( + HotKeyType.historyWindow, + )?.desc; final dialog = HotKeyEditorDialog( hotKeyType: HotKeyType.historyWindow, initContent: desc ?? "", @@ -1821,7 +2244,9 @@ class SettingsPage extends GetView { .catchError((err) { Global.showTipsDialog( context: context, - text: TranslationKey.hotKeySettingsSaveKeysFailedText.trParams({"err": err}), + text: TranslationKey + .hotKeySettingsSaveKeysFailedText + .trParams({"err": err}), ); }); }, @@ -1832,7 +2257,9 @@ class SettingsPage extends GetView { showCancel: true, onOk: () { appConfig.setHistoryWindowHotKeys(""); - AppHotKeyHandler.unRegister(HotKeyType.historyWindow); + AppHotKeyHandler.unRegister( + HotKeyType.historyWindow, + ); Get.back(); }, ); @@ -1863,10 +2290,14 @@ class SettingsPage extends GetView { TranslationKey.sendFile.tr, maxLines: 1, ), - description: Text(TranslationKey.hotKeySettingsFileDesc.tr), + description: Text( + TranslationKey.hotKeySettingsFileDesc.tr, + ), value: appConfig.syncFileHotKeys, action: (v) { - final desc = AppHotKeyHandler.getByType(HotKeyType.fileSender)?.desc; + final desc = AppHotKeyHandler.getByType( + HotKeyType.fileSender, + )?.desc; final dialog = HotKeyEditorDialog( hotKeyType: HotKeyType.fileSender, initContent: desc ?? "", @@ -1880,7 +2311,9 @@ class SettingsPage extends GetView { .catchError((err) { Global.showTipsDialog( context: context, - text: TranslationKey.hotKeySettingsSaveKeysFailedText.trParams({"err": err}), + text: TranslationKey + .hotKeySettingsSaveKeysFailedText + .trParams({"err": err}), ); }); }, @@ -1891,7 +2324,9 @@ class SettingsPage extends GetView { showCancel: true, onOk: () { appConfig.setSyncFileHotKeys(""); - AppHotKeyHandler.unRegister(HotKeyType.fileSender); + AppHotKeyHandler.unRegister( + HotKeyType.fileSender, + ); Get.back(); }, ); @@ -1921,7 +2356,9 @@ class SettingsPage extends GetView { title: Text(TranslationKey.showMainWindow.tr), value: appConfig.showMainWindowHotKeys, action: (v) { - final desc = AppHotKeyHandler.getByType(HotKeyType.showMainWindows)?.desc; + final desc = AppHotKeyHandler.getByType( + HotKeyType.showMainWindows, + )?.desc; final dialog = HotKeyEditorDialog( hotKeyType: HotKeyType.showMainWindows, initContent: desc ?? "", @@ -1930,7 +2367,9 @@ class SettingsPage extends GetView { AppHotKeyHandler.registerShowMainWindow(hotKey) .then((v) { //设置为新值 - appConfig.setShowMainWindowHotKeys(keyCodes); + appConfig.setShowMainWindowHotKeys( + keyCodes, + ); //更新托盘菜单 final trayService = Get.find(); trayService.updateTrayMenus(false); @@ -1938,7 +2377,9 @@ class SettingsPage extends GetView { .catchError((err) { Global.showTipsDialog( context: context, - text: TranslationKey.hotKeySettingsSaveKeysFailedText.trParams({"err": err}), + text: TranslationKey + .hotKeySettingsSaveKeysFailedText + .trParams({"err": err}), ); }); }, @@ -1949,7 +2390,9 @@ class SettingsPage extends GetView { showCancel: true, onOk: () { appConfig.setShowMainWindowHotKeys(""); - AppHotKeyHandler.unRegister(HotKeyType.showMainWindows); + AppHotKeyHandler.unRegister( + HotKeyType.showMainWindows, + ); final trayService = Get.find(); trayService.updateTrayMenus(false); Get.back(); @@ -1981,7 +2424,9 @@ class SettingsPage extends GetView { title: Text(TranslationKey.exitApp.tr), value: appConfig.exitAppHotKeys, action: (v) { - final desc = AppHotKeyHandler.getByType(HotKeyType.exitApp)?.desc; + final desc = AppHotKeyHandler.getByType( + HotKeyType.exitApp, + )?.desc; final dialog = HotKeyEditorDialog( hotKeyType: HotKeyType.exitApp, initContent: desc ?? "", @@ -1998,7 +2443,9 @@ class SettingsPage extends GetView { .catchError((err) { Global.showTipsDialog( context: context, - text: TranslationKey.hotKeySettingsSaveKeysFailedText.trParams({"err": err}), + text: TranslationKey + .hotKeySettingsSaveKeysFailedText + .trParams({"err": err}), ); }); }, @@ -2009,7 +2456,9 @@ class SettingsPage extends GetView { showCancel: true, onOk: () { appConfig.setExitAppHotKeys(""); - AppHotKeyHandler.unRegister(HotKeyType.exitApp); + AppHotKeyHandler.unRegister( + HotKeyType.exitApp, + ); final trayService = Get.find(); trayService.updateTrayMenus(false); Get.back(); @@ -2051,10 +2500,14 @@ class SettingsPage extends GetView { cardList: [ SettingCard( title: Text( - TranslationKey.syncSettingsAutoSyncMissingDataTitle.tr, + TranslationKey + .syncSettingsAutoSyncMissingDataTitle + .tr, maxLines: 1, ), - description: Text(TranslationKey.syncSettingsAutoSyncMissingDataDesc.tr), + description: Text( + TranslationKey.syncSettingsAutoSyncMissingDataDesc.tr, + ), value: appConfig.autoSyncMissingData, show: (v) => true, action: (v) { @@ -2072,7 +2525,9 @@ class SettingsPage extends GetView { TranslationKey.recopyOnScreenUnlockedTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.recopyOnScreenUnlockedTitleDesc.tr), + description: Text( + TranslationKey.recopyOnScreenUnlockedTitleDesc.tr, + ), value: appConfig.reCopyOnScreenUnlocked, show: (v) => Platform.isAndroid, action: (v) { @@ -2090,7 +2545,9 @@ class SettingsPage extends GetView { TranslationKey.syncSettingsSmsTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.syncSettingsSmsDesc.tr), + description: Text( + TranslationKey.syncSettingsSmsDesc.tr, + ), value: appConfig.enableSmsSync, show: (v) => Platform.isAndroid, action: (v) { @@ -2099,14 +2556,19 @@ class SettingsPage extends GetView { onChanged: (checked) async { HapticFeedback.mediumImpact(); if (checked) { - var isGranted = await PermissionHelper.testAndroidReadSms(); + var isGranted = + await PermissionHelper.testAndroidReadSms(); if (isGranted) { androidChannelService.startSmsListen(); } else { Global.showTipsDialog( context: context, - text: TranslationKey.syncSettingsSmsPermissionRequired.tr, - okText: TranslationKey.dialogAuthorizationButtonText.tr, + text: TranslationKey + .syncSettingsSmsPermissionRequired + .tr, + okText: TranslationKey + .dialogAuthorizationButtonText + .tr, showCancel: true, onOk: () async { await PermissionHelper.reqAndroidReadSms(); @@ -2131,7 +2593,9 @@ class SettingsPage extends GetView { TranslationKey.syncSettingsStoreImg2PicturesTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.syncSettingsStoreImg2PicturesDesc.tr), + description: Text( + TranslationKey.syncSettingsStoreImg2PicturesDesc.tr, + ), value: appConfig.saveToPictures, action: (v) { return Switch( @@ -2139,8 +2603,12 @@ class SettingsPage extends GetView { onChanged: (checked) async { HapticFeedback.mediumImpact(); if (checked) { - var path = "${Constants.androidPicturesPath}/${Constants.appName}"; - var res = await PermissionHelper.testAndroidStoragePerm(path); + var path = + "${Constants.androidPicturesPath}/${Constants.appName}"; + var res = + await PermissionHelper.testAndroidStoragePerm( + path, + ); if (res) { appConfig.setSaveToPictures(true); return; @@ -2148,23 +2616,33 @@ class SettingsPage extends GetView { DialogController? dialog; dialog = Global.showTipsDialog( context: context, - text: TranslationKey.syncSettingsStoreImg2PicturesNoPermText.tr, + text: TranslationKey + .syncSettingsStoreImg2PicturesNoPermText + .tr, showCancel: true, onOk: () async { await dialog!.close(); - await PermissionHelper.reqAndroidStoragePerm(path); - if (!await PermissionHelper.testAndroidStoragePerm(path)) { + await PermissionHelper.reqAndroidStoragePerm( + path, + ); + if (!await PermissionHelper.testAndroidStoragePerm( + path, + )) { appConfig.setSaveToPictures(false); Global.showTipsDialog( context: context, - text: TranslationKey.syncSettingsStoreImg2PicturesCancelPerm.tr, + text: TranslationKey + .syncSettingsStoreImg2PicturesCancelPerm + .tr, ); } else { //授权成功 appConfig.setSaveToPictures(true); } }, - okText: TranslationKey.dialogAuthorizationButtonText.tr, + okText: TranslationKey + .dialogAuthorizationButtonText + .tr, ); } else { appConfig.setSaveToPictures(false); @@ -2191,10 +2669,14 @@ class SettingsPage extends GetView { action: (v) { return TextButton( onPressed: () async { - String? directory = await FilePicker.platform.getDirectoryPath(lockParentWindow: true); + String? directory = await FilePicker.platform + .getDirectoryPath(lockParentWindow: true); if (directory != null) { if (!FileUtil.testWriteable(directory)) { - Global.showTipsDialog(context: context, text: TranslationKey.unWriteablePathTips.tr); + Global.showTipsDialog( + context: context, + text: TranslationKey.unWriteablePathTips.tr, + ); return; } appConfig.setFileStorePath(directory); @@ -2221,7 +2703,9 @@ class SettingsPage extends GetView { TranslationKey.syncSettingsAutoCopyImgTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.syncSettingsAutoCopyImgDesc.tr), + description: Text( + TranslationKey.syncSettingsAutoCopyImgDesc.tr, + ), show: (v) => true, value: appConfig.autoCopyImageAfterSync, action: (v) { @@ -2238,15 +2722,20 @@ class SettingsPage extends GetView { TranslationKey.syncSettingsAutoCopyScreenShotTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.syncSettingsAutoCopyScreenShotDesc.tr), + description: Text( + TranslationKey.syncSettingsAutoCopyScreenShotDesc.tr, + ), show: (v) => Platform.isAndroid, value: appConfig.autoCopyImageAfterScreenShot, action: (v) { return Switch( value: v, onChanged: (checked) async { - appConfig.setAutoCopyImageAfterScreenShot(checked); - final clipboardService = Get.find(); + appConfig.setAutoCopyImageAfterScreenShot( + checked, + ); + final clipboardService = + Get.find(); if (checked) { clipboardService.startListenScreenshot(); } else { @@ -2274,16 +2763,23 @@ class SettingsPage extends GetView { ), SettingCard( title: Text(TranslationKey.syncOutDateSettingTitle.tr), - description: Text(TranslationKey.syncOutDateSettingDesc.tr), + description: Text( + TranslationKey.syncOutDateSettingDesc.tr, + ), value: appConfig.syncOutdateLimitTime, - action: (v) => Text(v == 0 ? TranslationKey.noLimits.tr : v.timeSpanStr), + action: (v) => Text( + v == 0 ? TranslationKey.noLimits.tr : v.timeSpanStr, + ), onTap: () { Global.showDialog( context, OutdateTimeInputDialog( initValue: appConfig.syncOutdateLimitTime, onConfirm: (value) { - appConfig.setNewPairedDeviceSyncOldDataLimitTime(value); + appConfig + .setNewPairedDeviceSyncOldDataLimitTime( + value, + ); }, ), ); @@ -2305,7 +2801,9 @@ class SettingsPage extends GetView { TranslationKey.ruleSettingsTagRuleTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.ruleSettingsTagRuleDesc.tr), + description: Text( + TranslationKey.ruleSettingsTagRuleDesc.tr, + ), value: false, action: (v) { return TextButton( @@ -2331,7 +2829,9 @@ class SettingsPage extends GetView { TranslationKey.ruleSettingsSmsRuleTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.ruleSettingsSmsRuleDesc.tr), + description: Text( + TranslationKey.ruleSettingsSmsRuleDesc.tr, + ), value: false, show: (v) => Platform.isAndroid, action: (v) { @@ -2411,7 +2911,9 @@ class SettingsPage extends GetView { ), ), onTap: () async { - Directory(appConfig.logsDirPath).createSync(recursive: true); + Directory( + appConfig.logsDirPath, + ).createSync(recursive: true); try { await OpenFile.open(appConfig.logsDirPath); } catch (e) { @@ -2425,7 +2927,9 @@ class SettingsPage extends GetView { description: Obx(() { final tmp = controller.updater; final emptyStr = tmp.value != 0 ? "" : ""; - final size = FileUtil.getDirectorySize(appConfig.logsDirPath); + final size = FileUtil.getDirectorySize( + appConfig.logsDirPath, + ); return Text( "${TranslationKey.logSettingsEnableDesc.trParams({ "size": size.sizeStr, @@ -2451,13 +2955,20 @@ class SettingsPage extends GetView { title: Row( children: [ Text( - TranslationKey.logSettingsAutoUploadCrashLogTitle.tr, + TranslationKey + .logSettingsAutoUploadCrashLogTitle + .tr, maxLines: 1, ), const SizedBox(width: 5), GestureDetector( onTap: () { - Global.showTipsDialog(context: context, text: TranslationKey.logSettingsAutoUploadCrashLogTips.tr); + Global.showTipsDialog( + context: context, + text: TranslationKey + .logSettingsAutoUploadCrashLogTips + .tr, + ); }, child: const Icon( Icons.info_outline, @@ -2467,7 +2978,9 @@ class SettingsPage extends GetView { ), ], ), - description: Text(TranslationKey.logSettingsAutoUploadCrashLogDesc.tr), + description: Text( + TranslationKey.logSettingsAutoUploadCrashLogDesc.tr, + ), value: appConfig.enableAutoUploadCrashLogs, action: (v) { return Switch( @@ -2475,7 +2988,9 @@ class SettingsPage extends GetView { onChanged: (checked) { HapticFeedback.mediumImpact(); appConfig.setEnableAutoUploadCrashLogs(checked); - androidChannelService.setAutoReportCrashes(checked); + androidChannelService.setAutoReportCrashes( + checked, + ); }, ); }, @@ -2497,7 +3012,9 @@ class SettingsPage extends GetView { TranslationKey.statisticsSettingsTitle.tr, maxLines: 1, ), - description: Text(TranslationKey.statisticsSettingsDesc.tr), + description: Text( + TranslationKey.statisticsSettingsDesc.tr, + ), value: null, onTap: () { controller.gotoStatisticPage(); diff --git a/lib/app/modules/splash_module/splash_controller.dart b/lib/app/modules/splash_module/splash_controller.dart index 410a5668..fae4c46a 100644 --- a/lib/app/modules/splash_module/splash_controller.dart +++ b/lib/app/modules/splash_module/splash_controller.dart @@ -95,7 +95,7 @@ class SplashController extends GetxController { PackageInfo packageInfo = await PackageInfo.fromPlatform(); launchAtStartup.setup( appName: packageInfo.appName, - appPath: Platform.resolvedExecutable, + appPath: PlatformExt.startupExecutablePath, ); var isLaunchAtStartup = await launchAtStartup.isEnabled(); final isSystem = isLaunchAtStartup; @@ -116,8 +116,14 @@ class SplashController extends GetxController { isLaunchAtStartup = isLaunchAtStartup || hasShortcut; } } - Log.debug(tag, "isLaunchAtStartup $isLaunchAtStartup, isSystem $isSystem"); - appConfig.setLaunchAtStartup(isLaunchAtStartup, isLaunchAtStartup && isSystem); + Log.debug( + tag, + "isLaunchAtStartup $isLaunchAtStartup, isSystem $isSystem", + ); + appConfig.setLaunchAtStartup( + isLaunchAtStartup, + isLaunchAtStartup && isSystem, + ); var updateDir = Directory(appConfig.updateDownloadFileDirPath); Log.debug(tag, "updateDir = $updateDir"); if (await updateDir.exists()) { @@ -125,7 +131,9 @@ class SplashController extends GetxController { } } if (Platform.isAndroid) { - androidChannelService.setAutoReportCrashes(appConfig.enableAutoUploadCrashLogs); + androidChannelService.setAutoReportCrashes( + appConfig.enableAutoUploadCrashLogs, + ); } // 初始化channel initChannel(); @@ -142,10 +150,15 @@ class SplashController extends GetxController { } Future initWindowsManager() async { - final [width, height] = appConfig.windowSize.split("x").map((e) => e.toDouble()).toList(); + final [width, height] = appConfig.windowSize + .split("x") + .map((e) => e.toDouble()) + .toList(); WindowOptions windowOptions = WindowOptions( size: Size(width, height), - minimumSize: kReleaseMode ? const Size(Constants.showHistoryRightWidth * 1.0, 200) : null, + minimumSize: kReleaseMode + ? const Size(Constants.showHistoryRightWidth * 1.0, 200) + : null, center: true, skipTaskbar: false, titleBarStyle: TitleBarStyle.hidden, @@ -154,8 +167,6 @@ class SplashController extends GetxController { if (!appConfig.startMini) { windowManager.show(); windowManager.focus(); - } else if (Platform.isLinux) { - windowManager.hide(); } }); } @@ -164,7 +175,9 @@ class SplashController extends GetxController { initHotKey() async { await AppHotKeyHandler.unRegisterAll(); if (appConfig.historyWindowHotKeys.isNotEmpty) { - var hotKey = AppHotKeyHandler.toSystemHotKey(appConfig.historyWindowHotKeys); + var hotKey = AppHotKeyHandler.toSystemHotKey( + appConfig.historyWindowHotKeys, + ); AppHotKeyHandler.registerHistoryWindow(hotKey); } if (appConfig.syncFileHotKeys.isNotEmpty) { @@ -201,7 +214,9 @@ class SplashController extends GetxController { return jsonEncode(res); case MultiWindowMethod.getAllDevices: //加载所有设备 - final devices = await dbService.deviceDao.getAllDevices(appConfig.userId); + final devices = await dbService.deviceDao.getAllDevices( + appConfig.userId, + ); return jsonEncode([appConfig.device, ...devices]); case MultiWindowMethod.getAllTagNames: //加载所有标签名 @@ -227,7 +242,9 @@ class SplashController extends GetxController { return jsonEncode(devices); case MultiWindowMethod.syncFiles: final paths = (args["files"] as List).cast(); - final items = paths.map((path) => DropItemFile(path)).toList(growable: false); + final items = paths + .map((path) => DropItemFile(path)) + .toList(growable: false); final files = await pendingFileService.resolvePendingItems(items); var devices = List.empty(growable: true); for (var devMap in (args["devices"] as List)) { @@ -257,7 +274,10 @@ class SplashController extends GetxController { break; } final type = WindowType.parse(args["type"]); - final [width, height] = (args["size"] as String).split("x").map((item) => item.toDouble()).toList(); + final [width, height] = (args["size"] as String) + .split("x") + .map((item) => item.toDouble()) + .toList(); final size = Size(width, height); await appConfig.updatePopupWindowSize(type, size); break; @@ -302,7 +322,11 @@ class SplashController extends GetxController { } var contentLst = lst // 过滤掉非通知数据 - .where((e) => !e.type.containsIgnoreCase(HistoryContentType.notification.name)) + .where( + (e) => !e.type.containsIgnoreCase( + HistoryContentType.notification.name, + ), + ) .map( (e) => { "id": e.id, @@ -329,7 +353,11 @@ class SplashController extends GetxController { break; case AndroidChannelMethod.onSmsChanged: final content = call.arguments["content"]!; - HistoryDataListener.inst.onChanged(HistoryContentType.sms, content, null); + HistoryDataListener.inst.onChanged( + HistoryContentType.sms, + content, + null, + ); break; default: } @@ -344,8 +372,13 @@ class SplashController extends GetxController { } final handler = ShareHandlerPlatform.instance; appConfig.shareHandlerStream?.cancel(); - appConfig.shareHandlerStream = handler.sharedMediaStream.listen((SharedMedia media) async { - Log.info(tag, "ShareMedia: ${media.attachments}, content: ${media.content}"); + appConfig.shareHandlerStream = handler.sharedMediaStream.listen(( + SharedMedia media, + ) async { + Log.info( + tag, + "ShareMedia: ${media.attachments}, content: ${media.content}", + ); if (media.attachments != null) { var files = media.attachments! .where((attachment) => attachment != null) @@ -369,9 +402,14 @@ class SplashController extends GetxController { final fileName = fileInfo.fileName; final size = fileInfo.size; Log.info(tag, "ShareMedia fileName $fileName, size $size"); - gotoOnlineDevicesPage([DropItemFileUri(media.content!, fileName, size)]); + gotoOnlineDevicesPage([ + DropItemFileUri(media.content!, fileName, size), + ]); } else { - Global.showTipsDialog(context: Get.context!, text: TranslationKey.saveFileNotSupportDialogText.tr); + Global.showTipsDialog( + context: Get.context!, + text: TranslationKey.saveFileNotSupportDialogText.tr, + ); return; } }); @@ -394,7 +432,10 @@ class SplashController extends GetxController { ); pendingFileService.clearPendingInfo(); Navigator.pop(context); - Global.showSnackBarSuc(text: TranslationKey.startSendFileToast.tr, context: Get.context!); + Global.showSnackBarSuc( + text: TranslationKey.startSendFileToast.tr, + context: Get.context!, + ); }, onItemRemove: (DropItem item) { pendingFileService.removeDropItem(item); diff --git a/lib/app/services/config_service.dart b/lib/app/services/config_service.dart index 804b7f28..c88ed115 100644 --- a/lib/app/services/config_service.dart +++ b/lib/app/services/config_service.dart @@ -395,7 +395,9 @@ class ConfigService extends GetxService { bool get autoCopyImageAfterScreenShot => _autoCopyImageAfterScreenShot.value; //中转服务器地址 - final Rx _forwardServer = Rx(null); + final Rx _forwardServer = Rx( + null, + ); ForwardServerConfig? get forwardServer => _forwardServer.value; @@ -420,9 +422,11 @@ class ConfigService extends GetxService { String? get ignoreUpdateVersion => _ignoreUpdateVersion.value; //剪贴板监听方式 - final Rx _clipboardListeningWay = Rx(null); + final Rx _clipboardListeningWay = + Rx(null); - ClipboardListeningWay get clipboardListeningWay => _clipboardListeningWay.value ?? ClipboardListeningWay.hiddenApi; + ClipboardListeningWay get clipboardListeningWay => + _clipboardListeningWay.value ?? ClipboardListeningWay.hiddenApi; //屏幕亮起时发现设备 final _enableAutoSyncOnScreenOpened = true.obs; @@ -437,7 +441,8 @@ class ConfigService extends GetxService { //剪贴板来源记录(通过dumpsys) final _sourceRecordViaDumpsys = false.obs; - bool get sourceRecordViaDumpsys => _sourceRecordViaDumpsys.value && sourceRecord; + bool get sourceRecordViaDumpsys => + _sourceRecordViaDumpsys.value && sourceRecord; //设备断开连接后通知 final _notifyOnDevDisconn = true.obs; @@ -472,7 +477,8 @@ class ConfigService extends GetxService { //通知黑白名单模式 final _currentNotificationWhiteBlackMode = WhiteBlackMode.black.obs; - WhiteBlackMode get currentNotificationWhiteBlackMode => _currentNotificationWhiteBlackMode.value; + WhiteBlackMode get currentNotificationWhiteBlackMode => + _currentNotificationWhiteBlackMode.value; //通知黑名单列表 final _notificationBlackList = [].obs; @@ -513,14 +519,20 @@ class ConfigService extends GetxService { String get notificationServer => _notificationServer.value; //移动设备id生成方式 - final _mobileDevIdGenerateWay = Rx(DeviceIdGenerateWay.unknown); + final _mobileDevIdGenerateWay = Rx( + DeviceIdGenerateWay.unknown, + ); - DeviceIdGenerateWay get mobileDevIdGenerateWay => _mobileDevIdGenerateWay.value; + DeviceIdGenerateWay get mobileDevIdGenerateWay => + _mobileDevIdGenerateWay.value; //设备状态筛选过滤器 - final _devicePairedStatusFilter = Rx(DevicePairedStatusFilter.all); + final _devicePairedStatusFilter = Rx( + DevicePairedStatusFilter.all, + ); - DevicePairedStatusFilter get devicePairedStatusFilter => _devicePairedStatusFilter.value; + DevicePairedStatusFilter get devicePairedStatusFilter => + _devicePairedStatusFilter.value; //上次编辑的SQL内容 final _lastSqlEditContent = ''.obs; @@ -603,10 +615,22 @@ class ConfigService extends GetxService { _port = (await cfg.getConfigByKey(ConfigKey.port, Constants.port)).obs; _localName = (await cfg.getConfigByKey(ConfigKey.localName, '')).obs; _startMini = (await cfg.getConfigByKey(ConfigKey.startMini, false)).obs; - _allowDiscover = (await cfg.getConfigByKey(ConfigKey.allowDiscover, true)).obs; - _showHistoryFloat = (await cfg.getConfigByKey(ConfigKey.showHistoryFloat, false)).obs; - _firstStartup = (await cfg.getConfigByKey(ConfigKey.firstStartup, true)).obs; - _rememberWindowSize = (await cfg.getConfigByKey(ConfigKey.rememberWindowSize, false)).obs; + _allowDiscover = (await cfg.getConfigByKey( + ConfigKey.allowDiscover, + true, + )).obs; + _showHistoryFloat = (await cfg.getConfigByKey( + ConfigKey.showHistoryFloat, + false, + )).obs; + _firstStartup = (await cfg.getConfigByKey( + ConfigKey.firstStartup, + true, + )).obs; + _rememberWindowSize = (await cfg.getConfigByKey( + ConfigKey.rememberWindowSize, + false, + )).obs; _windowSize = (await cfg.getConfigByKey( ConfigKey.windowSize, Constants.defaultWindowSize, @@ -617,29 +641,83 @@ class ConfigService extends GetxService { return Constants.defaultWindowSize; }, )).obs; - _lockHistoryFloatLoc = (await cfg.getConfigByKey(ConfigKey.lockHistoryFloatLoc, true)).obs; - _enableLogsRecord = (await cfg.getConfigByKey(ConfigKey.enableLogsRecord, false)).obs; - _enableAutoUploadCrashLogs = (await cfg.getConfigByKey(ConfigKey.enableAutoUploadCrashLogs, false)).obs; - _tagRules.value = (await cfg.getConfigByKey(ConfigKey.tagRules, null)); - _smsRules.value = (await cfg.getConfigByKey(ConfigKey.smsRules, null)); - _historyWindowHotKeys = (await cfg.getConfigByKey(ConfigKey.historyWindowHotKeys, Constants.defaultHistoryWindowKeys)).obs; - _syncFileHotKeys = (await cfg.getConfigByKey(ConfigKey.syncFileHotKeys, Constants.defaultSyncFileHotKeys)).obs; - _showMainWindowHotKeys = (await cfg.getConfigByKey(ConfigKey.showMainWindowHotKeys, "")).obs; - _exitAppHotKeys = (await cfg.getConfigByKey(ConfigKey.exitAppHotKeys, "")).obs; - _heartbeatInterval = (await cfg.getConfigByKey(ConfigKey.heartbeatInterval, Constants.heartbeatInterval)).obs; + _lockHistoryFloatLoc = (await cfg.getConfigByKey( + ConfigKey.lockHistoryFloatLoc, + true, + )).obs; + _enableLogsRecord = (await cfg.getConfigByKey( + ConfigKey.enableLogsRecord, + false, + )).obs; + _enableAutoUploadCrashLogs = (await cfg.getConfigByKey( + ConfigKey.enableAutoUploadCrashLogs, + false, + )).obs; + _tagRules.value = (await cfg.getConfigByKey( + ConfigKey.tagRules, + null, + )); + _smsRules.value = (await cfg.getConfigByKey( + ConfigKey.smsRules, + null, + )); + _historyWindowHotKeys = (await cfg.getConfigByKey( + ConfigKey.historyWindowHotKeys, + Constants.defaultHistoryWindowKeys, + )).obs; + _syncFileHotKeys = (await cfg.getConfigByKey( + ConfigKey.syncFileHotKeys, + Constants.defaultSyncFileHotKeys, + )).obs; + _showMainWindowHotKeys = (await cfg.getConfigByKey( + ConfigKey.showMainWindowHotKeys, + "", + )).obs; + _exitAppHotKeys = (await cfg.getConfigByKey( + ConfigKey.exitAppHotKeys, + "", + )).obs; + _heartbeatInterval = (await cfg.getConfigByKey( + ConfigKey.heartbeatInterval, + Constants.heartbeatInterval, + )).obs; _fileStorePath = (await cfg.getConfigByKey( ConfigKey.fileStorePath, defaultFileStorePath, convert: (value) => Directory(fileStorePath).absolute.normalizePath, )).obs; - _saveToPictures = (await cfg.getConfigByKey(ConfigKey.saveToPictures, false)).obs; - _ignoreShizuku = (await cfg.getConfigByKey(ConfigKey.ignoreShizuku, false)).obs; - _useAuthentication = (await cfg.getConfigByKey(ConfigKey.useAuthentication, false)).obs; - _appRevalidateDuration = (await cfg.getConfigByKey(ConfigKey.appRevalidateDuration, 0)).obs; - _appPassword = (await cfg.getConfigByKey(ConfigKey.appPassword, null)).obs; - _enableSmsSync = (await cfg.getConfigByKey(ConfigKey.enableSmsSync, false)).obs; - _enableForward = (await cfg.getConfigByKey(ConfigKey.enableForward, false)).obs; - _notificationServer.value = await cfg.getConfigByKey(ConfigKey.notificationServer, Constants.defaultNotificationServer); + _saveToPictures = (await cfg.getConfigByKey( + ConfigKey.saveToPictures, + false, + )).obs; + _ignoreShizuku = (await cfg.getConfigByKey( + ConfigKey.ignoreShizuku, + false, + )).obs; + _useAuthentication = (await cfg.getConfigByKey( + ConfigKey.useAuthentication, + false, + )).obs; + _appRevalidateDuration = (await cfg.getConfigByKey( + ConfigKey.appRevalidateDuration, + 0, + )).obs; + _appPassword = (await cfg.getConfigByKey( + ConfigKey.appPassword, + null, + )).obs; + _enableSmsSync = (await cfg.getConfigByKey( + ConfigKey.enableSmsSync, + false, + )).obs; + _enableForward = (await cfg.getConfigByKey( + ConfigKey.enableForward, + false, + )).obs; + _notificationServer.value = await cfg.getConfigByKey( + ConfigKey.notificationServer, + Constants.defaultNotificationServer, + ); _forwardWay.value = await cfg.getConfigByKey( ConfigKey.forwardWay, ForwardWay.none, @@ -685,17 +763,48 @@ class ConfigService extends GetxService { } }, ); - _workingMode = (await cfg.getConfigByKey(ConfigKey.workingMode, null, convert: EnvironmentType.parse)).obs; - _onlyForwardMode = (await cfg.getConfigByKey(ConfigKey.onlyForwardMode, false)).obs; - _appTheme = (await cfg.getConfigByKey(ConfigKey.appTheme, ThemeMode.system.name)).obs; - _autoCopyImageAfterSync = (await cfg.getConfigByKey(ConfigKey.autoCopyImageAfterSync, false)).obs; - _autoCopyImageAfterScreenShot = (await cfg.getConfigByKey(ConfigKey.autoCopyImageAfterScreenShot, true)).obs; - _ignoreUpdateVersion.value = (await cfg.getConfigByKey(ConfigKey.ignoreUpdateVersion, null)); + _workingMode = (await cfg.getConfigByKey( + ConfigKey.workingMode, + null, + convert: EnvironmentType.parse, + )).obs; + _onlyForwardMode = (await cfg.getConfigByKey( + ConfigKey.onlyForwardMode, + false, + )).obs; + _appTheme = (await cfg.getConfigByKey( + ConfigKey.appTheme, + ThemeMode.system.name, + )).obs; + _autoCopyImageAfterSync = (await cfg.getConfigByKey( + ConfigKey.autoCopyImageAfterSync, + false, + )).obs; + _autoCopyImageAfterScreenShot = (await cfg.getConfigByKey( + ConfigKey.autoCopyImageAfterScreenShot, + true, + )).obs; + _ignoreUpdateVersion.value = (await cfg.getConfigByKey( + ConfigKey.ignoreUpdateVersion, + null, + )); _language.value = (await cfg.getConfigByKey(ConfigKey.appLanguage, 'auto')); - _recordHistoryDialogPosition.value = (await cfg.getConfigByKey(ConfigKey.recordHistoryDialogPosition, false)); - _historyDialogPosition.value = (await cfg.getConfigByKey(ConfigKey.historyDialogPosition, "")); - _showOnRecentTasks.value = await cfg.getConfigByKey(ConfigKey.showOnRecentTasks, true); - _autoCloseConnAfterScreenOff.value = (await cfg.getConfigByKey(ConfigKey.autoCloseConnAfterScreenOff, true)); + _recordHistoryDialogPosition.value = (await cfg.getConfigByKey( + ConfigKey.recordHistoryDialogPosition, + false, + )); + _historyDialogPosition.value = (await cfg.getConfigByKey( + ConfigKey.historyDialogPosition, + "", + )); + _showOnRecentTasks.value = await cfg.getConfigByKey( + ConfigKey.showOnRecentTasks, + true, + ); + _autoCloseConnAfterScreenOff.value = (await cfg.getConfigByKey( + ConfigKey.autoCloseConnAfterScreenOff, + true, + )); _cleanDataConfig.value = (await cfg.getConfigByKey( ConfigKey.cleanDataConfig, null, @@ -709,26 +818,54 @@ class ConfigService extends GetxService { } }, )); - _showMoreItemsInRow.value = (await cfg.getConfigByKey(ConfigKey.showMoreItemsInRow, true)); + _showMoreItemsInRow.value = (await cfg.getConfigByKey( + ConfigKey.showMoreItemsInRow, + true, + )); _clipboardListeningWay.value = await cfg.getConfigByKey( ConfigKey.clipboardListeningWay, ClipboardListeningWay.logs, convert: ClipboardListeningWay.parse, ); - _closeOnSameHotKey.value = (await cfg.getConfigByKey(ConfigKey.closeOnSameHotKey, false)); - _enableAutoSyncOnScreenOpened.value = (await cfg.getConfigByKey(ConfigKey.enableAutoSyncOnScreenOpened, true)); - _sourceRecord.value = (await cfg.getConfigByKey(ConfigKey.sourceRecord, PlatformExt.isDesktop)); - _sourceRecordViaDumpsys.value = (await cfg.getConfigByKey(ConfigKey.sourceRecordViaDumpsys, false)); - _notifyOnDevDisconn.value = (await cfg.getConfigByKey(ConfigKey.notifyOnDevDisconn, true)); - _notifyOnDevConn.value = (await cfg.getConfigByKey(ConfigKey.notifyOnDevConn, true)); - _autoSyncMissingData.value = (await cfg.getConfigByKey(ConfigKey.autoSyncMissingData, true)); - _enableContentBlackList.value = (await cfg.getConfigByKey(ConfigKey.enableContentBlackList, false)); + _closeOnSameHotKey.value = (await cfg.getConfigByKey( + ConfigKey.closeOnSameHotKey, + false, + )); + _enableAutoSyncOnScreenOpened.value = (await cfg.getConfigByKey( + ConfigKey.enableAutoSyncOnScreenOpened, + true, + )); + _sourceRecord.value = (await cfg.getConfigByKey( + ConfigKey.sourceRecord, + PlatformExt.isDesktop, + )); + _sourceRecordViaDumpsys.value = (await cfg.getConfigByKey( + ConfigKey.sourceRecordViaDumpsys, + false, + )); + _notifyOnDevDisconn.value = (await cfg.getConfigByKey( + ConfigKey.notifyOnDevDisconn, + true, + )); + _notifyOnDevConn.value = (await cfg.getConfigByKey( + ConfigKey.notifyOnDevConn, + true, + )); + _autoSyncMissingData.value = (await cfg.getConfigByKey( + ConfigKey.autoSyncMissingData, + true, + )); + _enableContentBlackList.value = (await cfg.getConfigByKey( + ConfigKey.enableContentBlackList, + false, + )); _contentBlackList.value = (await cfg.getConfigByKey( ConfigKey.blacklist, [], convert: (value) { try { - List> jsonList = (jsonDecode(value) as List).cast(); + List> jsonList = + (jsonDecode(value) as List).cast(); return jsonList.map((item) => FilterRule.fromJson(item)).toList(); } catch (err, stack) { debugPrint(err.toString()); @@ -737,18 +874,34 @@ class ConfigService extends GetxService { } }, )); - _enableRecordNotification.value = (await cfg.getConfigByKey(ConfigKey.enableRecordNotification, false)); - _enableShowMobileNotification.value = (await cfg.getConfigByKey(ConfigKey.enableShowMobileNotification, false)); - final notificationBlackWhiteList = await cfg.getConfigByKey(ConfigKey.notificationBlackWhiteList, ""); + _enableRecordNotification.value = (await cfg.getConfigByKey( + ConfigKey.enableRecordNotification, + false, + )); + _enableShowMobileNotification.value = (await cfg.getConfigByKey( + ConfigKey.enableShowMobileNotification, + false, + )); + final notificationBlackWhiteList = await cfg.getConfigByKey( + ConfigKey.notificationBlackWhiteList, + "", + ); try { if (notificationBlackWhiteList.isNullOrEmpty) { _notificationWhiteList.value = []; _notificationBlackList.value = []; } else { - final map = jsonDecode(notificationBlackWhiteList) as Map; - _currentNotificationWhiteBlackMode.value = WhiteBlackMode.values.byName(map["mode"].toString()); - _notificationBlackList.value = (map["blacklist"]! as List).map((item) => FilterRule.fromJson(item)).toList(); - _notificationWhiteList.value = (map["whitelist"]! as List).map((item) => FilterRule.fromJson(item)).toList(); + final map = + jsonDecode(notificationBlackWhiteList) as Map; + _currentNotificationWhiteBlackMode.value = WhiteBlackMode.values.byName( + map["mode"].toString(), + ); + _notificationBlackList.value = (map["blacklist"]! as List) + .map((item) => FilterRule.fromJson(item)) + .toList(); + _notificationWhiteList.value = (map["whitelist"]! as List) + .map((item) => FilterRule.fromJson(item)) + .toList(); } } catch (err, stack) { debugPrint(err.toString()); @@ -774,29 +927,57 @@ class ConfigService extends GetxService { DevicePairedStatusFilter.all, convert: DevicePairedStatusFilter.parse, ); - _lastSqlEditContent.value = await cfg.getConfigByKey(ConfigKey.lastSqlEditContent, ''); + _lastSqlEditContent.value = await cfg.getConfigByKey( + ConfigKey.lastSqlEditContent, + '', + ); _dhEncryptKey.value = await cfg.getConfigByKey(ConfigKey.dhEncryptKey, ''); if (_dhEncryptKey.value.isNotNullAndEmpty) { _dhAesKey = await _updateDhAesKey(); } - _syncOutdateLimitTime.value = await cfg.getConfigByKey(ConfigKey.syncOutdateLimitTime, 0); + _syncOutdateLimitTime.value = await cfg.getConfigByKey( + ConfigKey.syncOutdateLimitTime, + 0, + ); _noDiscoveryIfs.value = await cfg.getConfigByKey( ConfigKey.noDiscoveryIfs, [], - convert: (content) => content.split(',').where(((item) => item.isNotEmpty)).toList(), - ); - _onlyManualDiscoverySubNet.value = await cfg.getConfigByKey(ConfigKey.onlyManualDiscoverySubNet, false); - _stopListeningOnScreenClosed.value = await cfg.getConfigByKey(ConfigKey.stopListeningOnScreenClosed, false); - _sendBroadcastOnAdd.value = await cfg.getConfigByKey(ConfigKey.sendBroadcastOnAdd, false); - _recopyOnScreenUnlocked.value = await cfg.getConfigByKey(ConfigKey.recopyOnScreenUnlocked, false); - _excludeFormat.value = await cfg.getConfigByKey(ConfigKey.excludeFormat, true); - _rememberPopupWindowSize.value = await cfg.getConfigByKey(ConfigKey.rememberPopupWindowSize, false); + convert: (content) => + content.split(',').where(((item) => item.isNotEmpty)).toList(), + ); + _onlyManualDiscoverySubNet.value = await cfg.getConfigByKey( + ConfigKey.onlyManualDiscoverySubNet, + false, + ); + _stopListeningOnScreenClosed.value = await cfg.getConfigByKey( + ConfigKey.stopListeningOnScreenClosed, + false, + ); + _sendBroadcastOnAdd.value = await cfg.getConfigByKey( + ConfigKey.sendBroadcastOnAdd, + false, + ); + _recopyOnScreenUnlocked.value = await cfg.getConfigByKey( + ConfigKey.recopyOnScreenUnlocked, + false, + ); + _excludeFormat.value = await cfg.getConfigByKey( + ConfigKey.excludeFormat, + true, + ); + _rememberPopupWindowSize.value = await cfg.getConfigByKey( + ConfigKey.rememberPopupWindowSize, + false, + ); _historyWindowSize.value = await cfg.getConfigByKey( ConfigKey.historyWindowSize, null, convert: (sizeStr) { try { - final [width, height] = sizeStr.split("x").map((e) => e.toDouble()).toList(); + final [width, height] = sizeStr + .split("x") + .map((e) => e.toDouble()) + .toList(); return Size(width, height); } catch (_) { //ignored @@ -809,7 +990,10 @@ class ConfigService extends GetxService { null, convert: (sizeStr) { try { - final [width, height] = sizeStr.split("x").map((e) => e.toDouble()).toList(); + final [width, height] = sizeStr + .split("x") + .map((e) => e.toDouble()) + .toList(); return Size(width, height); } catch (_) { //ignored @@ -836,14 +1020,22 @@ class ConfigService extends GetxService { updateDownloadFileDirPath = Constants.androidDownloadPath; } else { cachePath = (await getApplicationCacheDirectory()).path; - documentsPath = "${(await getApplicationDocumentsDirectory()).path}/ClipShare/"; + if (Platform.isLinux) { + documentsPath = await _linuxDataDirPath(); + } else { + documentsPath = + "${(await getApplicationDocumentsDirectory()).path}/ClipShare/"; + } updateDownloadFileDirPath = "$documentsPath/update"; if (Platform.isWindows) { final username = Platform.environment['USERNAME']; if (username == null) { windowsUserStartUpPath = null; } else { - windowsUserStartUpPath = r'C:\Users\' + username + r'\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup'; + windowsUserStartUpPath = + r'C:\Users\' + + username + + r'\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup'; } } } @@ -852,11 +1044,26 @@ class ConfigService extends GetxService { await _initDefaultFileStorePath(); } + Future _linuxDataDirPath() async { + final xdgDataHome = Platform.environment['XDG_DATA_HOME']; + if (xdgDataHome != null && xdgDataHome.isNotEmpty) { + return "$xdgDataHome/${Constants.appName}/".normalizePath; + } + final home = Platform.environment['HOME']; + if (home != null && home.isNotEmpty) { + return "$home/.local/share/${Constants.appName}/".normalizePath; + } + return "${(await getApplicationSupportDirectory()).path}/${Constants.appName}/" + .normalizePath; + } + ///文件默认存储路径 Future _initDefaultFileStorePath() async { late String path; if (Platform.isAndroid) { path = "${Constants.androidDownloadPath}/${Constants.appName}"; + } else if (Platform.isLinux) { + path = "$documentsPath/files".normalizePath; } else if (Platform.isMacOS && kReleaseMode) { var dir = await getApplicationDocumentsDirectory(); path = dir.path + "/${Constants.appName}/files".normalizePath; @@ -911,7 +1118,10 @@ class ConfigService extends GetxService { var type = ""; if (Platform.isAndroid) { var androidInfo = await deviceInfo.androidInfo; - final useAndroidId = [DeviceIdGenerateWay.unknown, DeviceIdGenerateWay.androidId].contains(_mobileDevIdGenerateWay.value); + final useAndroidId = [ + DeviceIdGenerateWay.unknown, + DeviceIdGenerateWay.androidId, + ].contains(_mobileDevIdGenerateWay.value); if (useAndroidId && !firstStartup) { //使用 Android id guid = CryptoUtil.toMD5(androidInfo.id); @@ -922,7 +1132,9 @@ class ConfigService extends GetxService { await PersistentDeviceId.getDeviceId().then((id) async { if (id != null) { guid = CryptoUtil.toMD5(id); - await setMobileDeviceIdGenerateWay(DeviceIdGenerateWay.persistentDeviceId); + await setMobileDeviceIdGenerateWay( + DeviceIdGenerateWay.persistentDeviceId, + ); } else { //获取失败,仍然使用Android id兜底 guid = CryptoUtil.toMD5(androidInfo.id); @@ -982,7 +1194,10 @@ class ConfigService extends GetxService { //region 更新存储于数据库的配置 Future setAllowDiscover(bool allowDiscover) async { - await configDao.addOrUpdate(ConfigKey.allowDiscover, allowDiscover.toString()); + await configDao.addOrUpdate( + ConfigKey.allowDiscover, + allowDiscover.toString(), + ); _allowDiscover.value = allowDiscover; } @@ -991,9 +1206,15 @@ class ConfigService extends GetxService { _startMini.value = startMini; } - Future setLaunchAtStartup(bool launchAtStartup, [bool deleteWindowsShortcut = false]) async { + Future setLaunchAtStartup( + bool launchAtStartup, [ + bool deleteWindowsShortcut = false, + ]) async { _launchAtStartup.value = launchAtStartup; - Log.debug(tag, "launchAtStartup $launchAtStartup, deleteWindowsShortcut $deleteWindowsShortcut"); + Log.debug( + tag, + "launchAtStartup $launchAtStartup, deleteWindowsShortcut $deleteWindowsShortcut", + ); if (launchAtStartup && !deleteWindowsShortcut) return; if (Platform.isWindows) { final startupPaths = [ @@ -1025,12 +1246,18 @@ class ConfigService extends GetxService { } Future setShowHistoryFloat(bool showHistoryFloat) async { - await configDao.addOrUpdate(ConfigKey.showHistoryFloat, showHistoryFloat.toString()); + await configDao.addOrUpdate( + ConfigKey.showHistoryFloat, + showHistoryFloat.toString(), + ); _showHistoryFloat.value = showHistoryFloat; } Future setLockHistoryFloatLoc(bool lockHistoryFloatLoc) async { - await configDao.addOrUpdate(ConfigKey.lockHistoryFloatLoc, lockHistoryFloatLoc.toString()); + await configDao.addOrUpdate( + ConfigKey.lockHistoryFloatLoc, + lockHistoryFloatLoc.toString(), + ); _lockHistoryFloatLoc.value = lockHistoryFloatLoc; } @@ -1040,7 +1267,10 @@ class ConfigService extends GetxService { } Future setRememberWindowSize(bool rememberWindowSize) async { - await configDao.addOrUpdate(ConfigKey.rememberWindowSize, rememberWindowSize.toString()); + await configDao.addOrUpdate( + ConfigKey.rememberWindowSize, + rememberWindowSize.toString(), + ); Size size = await windowManager.getSize(); _rememberWindowSize.value = rememberWindowSize; _windowSize.value = "${size.width.toInt()}x${size.height.toInt()}"; @@ -1055,21 +1285,32 @@ class ConfigService extends GetxService { Future setRecordHistoryDialogPosition( bool recordHistoryDialogPosition, ) async { - await configDao.addOrUpdate(ConfigKey.recordHistoryDialogPosition, recordHistoryDialogPosition.toString()); + await configDao.addOrUpdate( + ConfigKey.recordHistoryDialogPosition, + recordHistoryDialogPosition.toString(), + ); _recordHistoryDialogPosition.value = recordHistoryDialogPosition; } Future setHistoryDialogPosition(String historyDialogPosition) async { - await configDao.addOrUpdate(ConfigKey.historyDialogPosition, historyDialogPosition); + await configDao.addOrUpdate( + ConfigKey.historyDialogPosition, + historyDialogPosition, + ); _historyDialogPosition.value = historyDialogPosition; } Future setShowOnRecentTasks(bool showOnRecentTasks) async { - await configDao.addOrUpdate(ConfigKey.showOnRecentTasks, showOnRecentTasks.toString()); + await configDao.addOrUpdate( + ConfigKey.showOnRecentTasks, + showOnRecentTasks.toString(), + ); _showOnRecentTasks.value = showOnRecentTasks; } - Future setAutoCloseConnAfterScreenOff(bool autoCloseConnAfterScreenOff) async { + Future setAutoCloseConnAfterScreenOff( + bool autoCloseConnAfterScreenOff, + ) async { await configDao.addOrUpdate( ConfigKey.autoCloseConnAfterScreenOff, autoCloseConnAfterScreenOff.toString(), @@ -1078,12 +1319,20 @@ class ConfigService extends GetxService { } Future setEnableLogsRecord(bool enableLogsRecord) async { - await configDao.addOrUpdate(ConfigKey.enableLogsRecord, enableLogsRecord.toString()); + await configDao.addOrUpdate( + ConfigKey.enableLogsRecord, + enableLogsRecord.toString(), + ); _enableLogsRecord.value = enableLogsRecord; } - Future setEnableAutoUploadCrashLogs(bool enableAutoUploadCrashLogs) async { - await configDao.addOrUpdate(ConfigKey.enableAutoUploadCrashLogs, enableAutoUploadCrashLogs.toString()); + Future setEnableAutoUploadCrashLogs( + bool enableAutoUploadCrashLogs, + ) async { + await configDao.addOrUpdate( + ConfigKey.enableAutoUploadCrashLogs, + enableAutoUploadCrashLogs.toString(), + ); _enableAutoUploadCrashLogs.value = enableAutoUploadCrashLogs; } @@ -1102,7 +1351,10 @@ class ConfigService extends GetxService { } Future setHistoryWindowHotKeys(String historyWindowHotKeys) async { - await configDao.addOrUpdate(ConfigKey.historyWindowHotKeys, historyWindowHotKeys); + await configDao.addOrUpdate( + ConfigKey.historyWindowHotKeys, + historyWindowHotKeys, + ); _historyWindowHotKeys.value = historyWindowHotKeys; } @@ -1112,7 +1364,10 @@ class ConfigService extends GetxService { } Future setShowMainWindowHotKeys(String showMainWindowHotKeys) async { - await configDao.addOrUpdate(ConfigKey.showMainWindowHotKeys, showMainWindowHotKeys); + await configDao.addOrUpdate( + ConfigKey.showMainWindowHotKeys, + showMainWindowHotKeys, + ); _showMainWindowHotKeys.value = showMainWindowHotKeys; } @@ -1132,7 +1387,10 @@ class ConfigService extends GetxService { } Future setSaveToPictures(bool saveToPictures) async { - await configDao.addOrUpdate(ConfigKey.saveToPictures, saveToPictures.toString()); + await configDao.addOrUpdate( + ConfigKey.saveToPictures, + saveToPictures.toString(), + ); _saveToPictures.value = saveToPictures; } @@ -1142,7 +1400,10 @@ class ConfigService extends GetxService { } Future setUseAuthentication(bool useAuthentication) async { - await configDao.addOrUpdate(ConfigKey.useAuthentication, useAuthentication.toString()); + await configDao.addOrUpdate( + ConfigKey.useAuthentication, + useAuthentication.toString(), + ); _useAuthentication.value = useAuthentication; if (PlatformExt.isMobile) { if (useAuthentication) { @@ -1154,7 +1415,10 @@ class ConfigService extends GetxService { } Future setAppRevalidateDuration(int appRevalidateDuration) async { - await configDao.addOrUpdate(ConfigKey.appRevalidateDuration, appRevalidateDuration.toString()); + await configDao.addOrUpdate( + ConfigKey.appRevalidateDuration, + appRevalidateDuration.toString(), + ); _appRevalidateDuration.value = appRevalidateDuration; } @@ -1165,17 +1429,26 @@ class ConfigService extends GetxService { } Future setEnableSmsSync(bool enableSmsSync) async { - await configDao.addOrUpdate(ConfigKey.enableSmsSync, enableSmsSync.toString()); + await configDao.addOrUpdate( + ConfigKey.enableSmsSync, + enableSmsSync.toString(), + ); _enableSmsSync.value = enableSmsSync; } Future setEnableForward(bool enableForward) async { - await configDao.addOrUpdate(ConfigKey.enableForward, enableForward.toString()); + await configDao.addOrUpdate( + ConfigKey.enableForward, + enableForward.toString(), + ); _enableForward.value = enableForward; } Future setForwardServer(ForwardServerConfig serverConfig) async { - await configDao.addOrUpdate(ConfigKey.forwardServer, serverConfig.toString()); + await configDao.addOrUpdate( + ConfigKey.forwardServer, + serverConfig.toString(), + ); _forwardServer.value = serverConfig; } @@ -1185,7 +1458,10 @@ class ConfigService extends GetxService { } Future setOnlyForwardMode(bool onlyForwardMode) async { - await configDao.addOrUpdate(ConfigKey.onlyForwardMode, onlyForwardMode.toString()); + await configDao.addOrUpdate( + ConfigKey.onlyForwardMode, + onlyForwardMode.toString(), + ); _onlyForwardMode.value = onlyForwardMode; if (!onlyForwardMode) return; final sktService = Get.find(); @@ -1252,27 +1528,42 @@ class ConfigService extends GetxService { } Future setCleanDataConfig(CleanDataConfig cleanDataConfig) async { - await configDao.addOrUpdate(ConfigKey.cleanDataConfig, cleanDataConfig.toString()); + await configDao.addOrUpdate( + ConfigKey.cleanDataConfig, + cleanDataConfig.toString(), + ); _cleanDataConfig.value = cleanDataConfig; } Future setShowMoreItemsInRow(bool showMoreItemsInRow) async { - await configDao.addOrUpdate(ConfigKey.showMoreItemsInRow, showMoreItemsInRow.toString()); + await configDao.addOrUpdate( + ConfigKey.showMoreItemsInRow, + showMoreItemsInRow.toString(), + ); _showMoreItemsInRow.value = showMoreItemsInRow; } Future setClipboardListeningWay(ClipboardListeningWay way) async { - await configDao.addOrUpdate(ConfigKey.clipboardListeningWay, way.name.toString()); + await configDao.addOrUpdate( + ConfigKey.clipboardListeningWay, + way.name.toString(), + ); _clipboardListeningWay.value = way; } Future setCloseOnSameHotKey(bool closeOnSameHotKey) async { - await configDao.addOrUpdate(ConfigKey.closeOnSameHotKey, closeOnSameHotKey.toString()); + await configDao.addOrUpdate( + ConfigKey.closeOnSameHotKey, + closeOnSameHotKey.toString(), + ); _closeOnSameHotKey.value = closeOnSameHotKey; } Future setEnableAutoSyncOnScreenOpened(bool enable) async { - await configDao.addOrUpdate(ConfigKey.enableAutoSyncOnScreenOpened, enable.toString()); + await configDao.addOrUpdate( + ConfigKey.enableAutoSyncOnScreenOpened, + enable.toString(), + ); _enableAutoSyncOnScreenOpened.value = enable; } @@ -1282,12 +1573,18 @@ class ConfigService extends GetxService { } Future setEnableSourceRecordViaDumpsys(bool enable) async { - await configDao.addOrUpdate(ConfigKey.sourceRecordViaDumpsys, enable.toString()); + await configDao.addOrUpdate( + ConfigKey.sourceRecordViaDumpsys, + enable.toString(), + ); _sourceRecordViaDumpsys.value = enable; } Future setNotifyOnDevDisconn(bool enable) async { - await configDao.addOrUpdate(ConfigKey.notifyOnDevDisconn, enable.toString()); + await configDao.addOrUpdate( + ConfigKey.notifyOnDevDisconn, + enable.toString(), + ); _notifyOnDevDisconn.value = enable; } @@ -1297,12 +1594,18 @@ class ConfigService extends GetxService { } Future setAutoSyncMissingData(bool enable) async { - await configDao.addOrUpdate(ConfigKey.autoSyncMissingData, enable.toString()); + await configDao.addOrUpdate( + ConfigKey.autoSyncMissingData, + enable.toString(), + ); _autoSyncMissingData.value = enable; } Future setEnableContentBlackList(bool enable) async { - await configDao.addOrUpdate(ConfigKey.enableContentBlackList, enable.toString()); + await configDao.addOrUpdate( + ConfigKey.enableContentBlackList, + enable.toString(), + ); _enableContentBlackList.value = enable; } @@ -1313,7 +1616,11 @@ class ConfigService extends GetxService { } ///更新通知黑白名单数据 - Future setNotificationBlackWhiteList(WhiteBlackMode mode, List blacklist, List whitelist) async { + Future setNotificationBlackWhiteList( + WhiteBlackMode mode, + List blacklist, + List whitelist, + ) async { await configDao.addOrUpdate( ConfigKey.notificationBlackWhiteList, jsonEncode({ @@ -1329,13 +1636,19 @@ class ConfigService extends GetxService { ///启用通知历史记录 Future setEnableRecordNotification(bool enabled) async { - await configDao.addOrUpdate(ConfigKey.enableRecordNotification, enabled.toString()); + await configDao.addOrUpdate( + ConfigKey.enableRecordNotification, + enabled.toString(), + ); _enableRecordNotification.value = enabled; } ///显示移动设备的通知 Future setEnableShowMobileNotification(bool enabled) async { - await configDao.addOrUpdate(ConfigKey.enableShowMobileNotification, enabled.toString()); + await configDao.addOrUpdate( + ConfigKey.enableShowMobileNotification, + enabled.toString(), + ); _enableShowMobileNotification.value = enabled; } @@ -1370,8 +1683,13 @@ class ConfigService extends GetxService { } ///设置设备状态筛选过滤器 - Future setDevicePairedStatusFilter(DevicePairedStatusFilter filter) async { - await configDao.addOrUpdate(ConfigKey.devicePairedStatusFilter, filter.name); + Future setDevicePairedStatusFilter( + DevicePairedStatusFilter filter, + ) async { + await configDao.addOrUpdate( + ConfigKey.devicePairedStatusFilter, + filter.name, + ); _devicePairedStatusFilter.value = filter; } @@ -1390,7 +1708,10 @@ class ConfigService extends GetxService { ///设置 过时数据同步时间限制 Future setNewPairedDeviceSyncOldDataLimitTime(int seconds) async { - await configDao.addOrUpdate(ConfigKey.syncOutdateLimitTime, seconds.toString()); + await configDao.addOrUpdate( + ConfigKey.syncOutdateLimitTime, + seconds.toString(), + ); _syncOutdateLimitTime.value = seconds; } @@ -1401,17 +1722,27 @@ class ConfigService extends GetxService { } ///仅手动子网扫描发现设备 - Future setOnlyManualDiscoverySubNet(bool onlyManualDiscoverySubNet) async { - await configDao.addOrUpdate(ConfigKey.onlyManualDiscoverySubNet, onlyManualDiscoverySubNet.toString()); + Future setOnlyManualDiscoverySubNet( + bool onlyManualDiscoverySubNet, + ) async { + await configDao.addOrUpdate( + ConfigKey.onlyManualDiscoverySubNet, + onlyManualDiscoverySubNet.toString(), + ); _onlyManualDiscoverySubNet.value = onlyManualDiscoverySubNet; } ///仅 Android,屏幕关闭后停止监听 - Future setStopListeningOnScreenClosed(bool stopListeningOnScreenClosed) async { + Future setStopListeningOnScreenClosed( + bool stopListeningOnScreenClosed, + ) async { if (!Platform.isAndroid) { return; } - await configDao.addOrUpdate(ConfigKey.stopListeningOnScreenClosed, stopListeningOnScreenClosed.toString()); + await configDao.addOrUpdate( + ConfigKey.stopListeningOnScreenClosed, + stopListeningOnScreenClosed.toString(), + ); _stopListeningOnScreenClosed.value = stopListeningOnScreenClosed; } @@ -1429,7 +1760,10 @@ class ConfigService extends GetxService { if (!Platform.isAndroid) { return; } - await configDao.addOrUpdate(ConfigKey.recopyOnScreenUnlocked, value.toString()); + await configDao.addOrUpdate( + ConfigKey.recopyOnScreenUnlocked, + value.toString(), + ); _recopyOnScreenUnlocked.value = value; } @@ -1449,7 +1783,10 @@ class ConfigService extends GetxService { if (!Platform.isWindows) { return; } - await configDao.addOrUpdate(ConfigKey.rememberPopupWindowSize, value.toString()); + await configDao.addOrUpdate( + ConfigKey.rememberPopupWindowSize, + value.toString(), + ); _rememberPopupWindowSize.value = value; } @@ -1469,7 +1806,10 @@ class ConfigService extends GetxService { default: return; } - await configDao.addOrUpdate(key, "${size.width.toStringAsFixed(2)}x${size.height.toStringAsFixed(2)}"); + await configDao.addOrUpdate( + key, + "${size.width.toStringAsFixed(2)}x${size.height.toStringAsFixed(2)}", + ); } //endregion @@ -1541,7 +1881,11 @@ class ConfigService extends GetxService { } ///判断是否命中内容黑名单 - FilterRuleMatchResult matchesContentBlacklist(HistoryContentType type, String content, ClipboardSource? source) { + FilterRuleMatchResult matchesContentBlacklist( + HistoryContentType type, + String content, + ClipboardSource? source, + ) { if (!enableContentBlackList) { return FilterRuleMatchResult.notMatched; } @@ -1559,7 +1903,10 @@ class ConfigService extends GetxService { } ///判断是否命中通知黑白名单规则 - FilterRuleMatchResult matchesNotificationRuleList(String content, String pkgName) { + FilterRuleMatchResult matchesNotificationRuleList( + String content, + String pkgName, + ) { //未启用 if (!enableRecordNotification) { return FilterRuleMatchResult.notMatched; @@ -1572,8 +1919,15 @@ class ConfigService extends GetxService { } catch (err, stack) { Log.error(tag, "matchesNotificationRuleList error: $err,$stack"); } - final ruleList = currentNotificationWhiteBlackMode == WhiteBlackMode.black ? notificationBlackList : notificationWhiteList; - final source = ClipboardSource(id: pkgName, name: "", time: null, iconB64: ""); + final ruleList = currentNotificationWhiteBlackMode == WhiteBlackMode.black + ? notificationBlackList + : notificationWhiteList; + final source = ClipboardSource( + id: pkgName, + name: "", + time: null, + iconB64: "", + ); for (var rule in ruleList) { // 跳过未启用的规则 if (!rule.enable) continue; @@ -1608,7 +1962,9 @@ class ConfigService extends GetxService { final dirPath = await getJiebaSegmentFileDirPath(); final dictFilePath = "$dirPath/dict.txt".normalizePath; final probEmitFilePath = "$dirPath/prob_emit.txt".normalizePath; - final result = await File(dictFilePath).exists() && await File(probEmitFilePath).exists(); + final result = + await File(dictFilePath).exists() && + await File(probEmitFilePath).exists(); if (!result) return false; await JiebaSegmenter.init(dirPath); _jiebaInited = true; diff --git a/lib/app/services/db_service.dart b/lib/app/services/db_service.dart index c5b7d231..a0aeefb3 100644 --- a/lib/app/services/db_service.dart +++ b/lib/app/services/db_service.dart @@ -105,7 +105,9 @@ class DbService extends GetxService { Future _queue = Future.value(); void execSequentially(Future Function() f) { - _queue = _queue.whenComplete(() => f().catchError((err) => Log.error(tag, err))); + _queue = _queue.whenComplete( + () => f().catchError((err) => Log.error(tag, err)), + ); } Future init() async { @@ -114,7 +116,7 @@ class DbService extends GetxService { var dbPath = "clipshare.db"; //桌面端如果当前路径可写则使用当前路径,如开发环境或者便携版本 if (PlatformExt.isDesktop) { - if (Platform.isMacOS) { + if (Platform.isMacOS || Platform.isLinux) { var dirPath = appConfig.documentsPath; dbPath = "$dirPath/$dbPath".normalizePath; } else { @@ -146,8 +148,14 @@ class DbService extends GetxService { return _db.close(); } - static Future hasColumnInTable(sqflite.Database database, String tableName, String columnName) async { - final result = await database.rawQuery("SELECT COUNT(*) as cnt FROM pragma_table_info('$tableName') WHERE name='$columnName'"); + static Future hasColumnInTable( + sqflite.Database database, + String tableName, + String columnName, + ) async { + final result = await database.rawQuery( + "SELECT COUNT(*) as cnt FROM pragma_table_info('$tableName') WHERE name='$columnName'", + ); if (result.isEmpty) return false; if (!result.first.containsKey("cnt")) { return false; @@ -161,7 +169,9 @@ class DbService extends GetxService { ///操作记录表新增设备id字段,用于从连接设备同步其他已配对设备数据 final migration1to2 = Migration(1, 2, (database) async { if (!await hasColumnInTable(database, 'OperationRecord', 'devId')) { - await database.execute('ALTER TABLE OperationRecord ADD COLUMN devId TEXT'); + await database.execute( + 'ALTER TABLE OperationRecord ADD COLUMN devId TEXT', + ); } }); @@ -193,7 +203,9 @@ class DbService extends GetxService { ///历史表增加更新时间字段 final migration3to4 = Migration(3, 4, (database) async { if (!await hasColumnInTable(database, 'History', 'updateTime')) { - await database.execute("ALTER TABLE `History` ADD COLUMN `updateTime` TEXT;"); + await database.execute( + "ALTER TABLE `History` ADD COLUMN `updateTime` TEXT;", + ); } }); @@ -204,15 +216,21 @@ class DbService extends GetxService { if (!await hasColumnInTable(database, 'History', 'source')) { await database.execute("ALTER TABLE `History` ADD COLUMN `source` TEXT;"); } - await database.execute("CREATE TABLE IF NOT EXISTS `AppInfo` (`id` INTEGER NOT NULL, `appId` TEXT NOT NULL, `devId` TEXT NOT NULL, `name` TEXT NOT NULL, `iconB64` TEXT NOT NULL, PRIMARY KEY (`id`));"); - await database.execute('CREATE UNIQUE INDEX IF NOT EXISTS `index_AppInfo_appId_devId` ON `AppInfo` (`appId`, `devId`);'); + await database.execute( + "CREATE TABLE IF NOT EXISTS `AppInfo` (`id` INTEGER NOT NULL, `appId` TEXT NOT NULL, `devId` TEXT NOT NULL, `name` TEXT NOT NULL, `iconB64` TEXT NOT NULL, PRIMARY KEY (`id`));", + ); + await database.execute( + 'CREATE UNIQUE INDEX IF NOT EXISTS `index_AppInfo_appId_devId` ON `AppInfo` (`appId`, `devId`);', + ); }); ///数据库版本 5 -> 6 ///支持存储服务为中转方式,操作记录表新增存储同步标记字段 final migration5to6 = Migration(5, 6, (database) async { if (!await hasColumnInTable(database, 'OperationRecord', 'storageSync')) { - await database.execute("ALTER TABLE `OperationRecord` ADD COLUMN `storageSync` INTEGER;"); + await database.execute( + "ALTER TABLE `OperationRecord` ADD COLUMN `storageSync` INTEGER;", + ); } //todo 后续移除 UID 字段的时候这里需要改 try { @@ -235,15 +253,21 @@ class DbService extends GetxService { ///v1.4.0 数据库版本 6 -> 7 ///为历史表增加设备id和来源字段的索引,避免删除速度过慢 final migration6to7 = Migration(6, 7, (database) async { - await database.execute('CREATE INDEX IF NOT EXISTS `index_History_devId` ON `History` (`devId`)'); - await database.execute('CREATE INDEX IF NOT EXISTS `index_History_devId_source` ON `History` (`devId`, `source`)'); + await database.execute( + 'CREATE INDEX IF NOT EXISTS `index_History_devId` ON `History` (`devId`)', + ); + await database.execute( + 'CREATE INDEX IF NOT EXISTS `index_History_devId_source` ON `History` (`devId`, `source`)', + ); }); ///v1.4.3 新增字段记录内网地址 7 -> 8 ///为历史表增加设备id和来源字段的索引,避免删除速度过慢 final migration7to8 = Migration(7, 8, (database) async { if (!await hasColumnInTable(database, 'Device', 'internalAddress')) { - await database.execute("ALTER TABLE `Device` ADD COLUMN `internalAddress` TEXT;"); + await database.execute( + "ALTER TABLE `Device` ADD COLUMN `internalAddress` TEXT;", + ); } }); } diff --git a/lib/app/services/tray_service.dart b/lib/app/services/tray_service.dart index c7b3dea9..df82fe5c 100644 --- a/lib/app/services/tray_service.dart +++ b/lib/app/services/tray_service.dart @@ -1,16 +1,15 @@ import 'dart:async'; import 'dart:io'; -import 'package:clipshare/app/data/enums/hot_key_type.dart'; import 'package:clipshare/app/data/enums/translation_key.dart'; import 'package:clipshare/app/handlers/hot_key_handler.dart'; import 'package:clipshare/app/services/config_service.dart'; import 'package:clipshare/app/utils/constants.dart'; +import 'package:clipshare/app/utils/extensions/keyboard_key_extension.dart'; import 'package:clipshare/app/utils/extensions/number_extension.dart'; import 'package:clipshare/app/utils/log.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; -import 'package:hotkey_manager/hotkey_manager.dart'; import 'package:tray_manager/tray_manager.dart'; import 'window_service.dart'; @@ -29,52 +28,103 @@ class TrayService extends GetxService with TrayListener { ///初始化托盘 Future _initTrayManager() async { trayManager.addListener(this); - if(!Platform.isLinux) { - trayManager.setToolTip(Constants.appName); + await _setTrayIcon(); + if (Platform.isLinux) { + await trayManager.setTitle(Constants.appName); + } else { + await trayManager.setToolTip(Constants.appName); } - await trayManager.setIcon( - Platform.isWindows ? Constants.logoIcoPath : Constants.logoPngPath, - ); - updateTrayMenus(); + await updateTrayMenus(); + } + + Future _setTrayIcon() async { + if (!Platform.isLinux) { + await trayManager.setIcon( + Platform.isWindows ? Constants.logoIcoPath : Constants.logoPngPath, + ); + return; + } + + final iconPath = [ + File(Platform.resolvedExecutable).parent.path, + 'data', + 'flutter_assets', + Constants.logoPngPath, + ].join(Platform.pathSeparator); + await const MethodChannel('tray_manager').invokeMethod('setIcon', { + 'id': Constants.appName, + 'iconPath': iconPath, + }); } Future updateTrayMenus([bool registerKey = true]) async { final showMainWindowKeys = appConfig.showMainWindowHotKeys; final exitAppKeys = appConfig.exitAppHotKeys; + var showWindowLabel = _menuLabel( + TranslationKey.showMainWindow.tr, + _hotKeyDesc(showMainWindowKeys), + ); + var exitAppLabel = _menuLabel( + TranslationKey.exitApp.tr, + _hotKeyDesc(exitAppKeys), + ); + List items = [ + MenuItem( + key: 'show_window', + label: showWindowLabel, + ), + MenuItem.separator(), + MenuItem( + key: 'exit_app', + label: exitAppLabel, + ), + ]; + await trayManager.setContextMenu(Menu(items: items)); + if (registerKey) { try { if (showMainWindowKeys.isNotEmpty) { - await AppHotKeyHandler.registerShowMainWindow(AppHotKeyHandler.toSystemHotKey(showMainWindowKeys)); + await AppHotKeyHandler.registerShowMainWindow( + AppHotKeyHandler.toSystemHotKey(showMainWindowKeys), + ); } } catch (err, stack) { Log.error(tag, err, stack); } try { if (exitAppKeys.isNotEmpty) { - await AppHotKeyHandler.registerExitApp(AppHotKeyHandler.toSystemHotKey(exitAppKeys)); + await AppHotKeyHandler.registerExitApp( + AppHotKeyHandler.toSystemHotKey(exitAppKeys), + ); } } catch (err, stack) { Log.error(tag, err, stack); } } - var showWindowLabel = '${TranslationKey.showMainWindow.tr} ${HotKeyType.showMainWindows.hotKeyDesc ?? ""}'; - var exitAppLabel = '${TranslationKey.exitApp.tr} ${HotKeyType.exitApp.hotKeyDesc ?? ""}'; - List items = [ - MenuItem( - key: 'show_window', - label: showWindowLabel, - ), - MenuItem.separator(), - MenuItem( - key: 'exit_app', - label: exitAppLabel, - ), - ]; - await trayManager.setContextMenu(Menu(items: items)); + } + + String _hotKeyDesc(String keyCodes) { + if (keyCodes.isEmpty) { + return ""; + } + try { + return AppHotKeyHandler.toSystemHotKey(keyCodes).desc; + } catch (err, stack) { + Log.error(tag, err, stack); + return ""; + } + } + + String _menuLabel(String label, String hotKeyDesc) { + return hotKeyDesc.isEmpty ? label : '$label $hotKeyDesc'; } @override void onTrayIconRightMouseDown() async { + if (Platform.isLinux) { + await updateTrayMenus(false); + return; + } await trayManager.popUpContextMenu(); } diff --git a/lib/app/utils/extensions/platform_extension.dart b/lib/app/utils/extensions/platform_extension.dart index f2e24abb..e1869d5b 100644 --- a/lib/app/utils/extensions/platform_extension.dart +++ b/lib/app/utils/extensions/platform_extension.dart @@ -8,4 +8,14 @@ extension PlatformExt on Platform { static bool get isDesktop { return Platform.isMacOS || Platform.isLinux || Platform.isWindows; } + + static String get startupExecutablePath { + if (Platform.isLinux) { + final appImagePath = Platform.environment['APPIMAGE']; + if (appImagePath != null && appImagePath.isNotEmpty) { + return appImagePath; + } + } + return Platform.resolvedExecutable; + } } diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index afbd442e..c3773e8f 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -76,6 +76,7 @@ add_executable(${BINARY_NAME} # Apply the standard set of build settings. This can be removed for applications # that need different build settings. apply_standard_settings(${BINARY_NAME}) +set_property(TARGET ${BINARY_NAME} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--disable-new-dtags") # Add dependency libraries. Add any application-specific dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter) @@ -98,6 +99,18 @@ set_target_properties(${BINARY_NAME} # them to the application. include(flutter/generated_plugins.cmake) +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + # Flutter copies plugin build outputs into the bundle as files, so their + # build-time RUNPATH is preserved. Make the copied plugins resolve sibling + # libraries from bundle/lib instead of the ephemeral build directory. + set_target_properties(${plugin}_plugin PROPERTIES + BUILD_RPATH "$ORIGIN" + INSTALL_RPATH "$ORIGIN" + BUILD_WITH_INSTALL_RPATH TRUE + ) + set_property(TARGET ${plugin}_plugin APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--disable-new-dtags") +endforeach(plugin) + # === Installation === # By default, "installing" just makes a relocatable bundle in the build @@ -130,6 +143,38 @@ foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) COMPONENT Runtime) endforeach(bundled_library) +# Extra runtime libraries used by Linux plugins that are not available on many +# clean desktop installs. Copy them with their sonames so the bundle's RPATH can +# resolve them from lib/ without requiring development packages on the target. +find_library(KEYBINDER_LIBRARY NAMES libkeybinder-3.0.so.0 keybinder-3.0) +find_library(AYATANA_APPINDICATOR_LIBRARY NAMES libayatana-appindicator3.so.1 ayatana-appindicator3) +find_library(AYATANA_INDICATOR_LIBRARY NAMES libayatana-indicator3.so.7 ayatana-indicator3) +find_library(AYATANA_IDO_LIBRARY NAMES libayatana-ido3-0.4.so.0 ayatana-ido3-0.4) +find_library(DBUSMENU_GLIB_LIBRARY NAMES libdbusmenu-glib.so.4 dbusmenu-glib) +find_library(DBUSMENU_GTK3_LIBRARY NAMES libdbusmenu-gtk3.so.4 dbusmenu-gtk3) +find_library(XTST_LIBRARY NAMES libXtst.so.6 Xtst) +find_library(WAYLAND_CLIENT_LIBRARY NAMES libwayland-client.so.0 wayland-client) + +function(INSTALL_EXTRA_RUNTIME_LIBRARY LIBRARY_VAR SONAME) + if(${LIBRARY_VAR}) + install(CODE " + file(MAKE_DIRECTORY \"${INSTALL_BUNDLE_LIB_DIR}\") + execute_process(COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different \"${${LIBRARY_VAR}}\" \"${INSTALL_BUNDLE_LIB_DIR}/${SONAME}\") + " COMPONENT Runtime) + else() + message(WARNING "Runtime library ${SONAME} was not found; packages may still need the system dependency.") + endif() +endfunction() + +install_extra_runtime_library(KEYBINDER_LIBRARY "libkeybinder-3.0.so.0") +install_extra_runtime_library(AYATANA_APPINDICATOR_LIBRARY "libayatana-appindicator3.so.1") +install_extra_runtime_library(AYATANA_INDICATOR_LIBRARY "libayatana-indicator3.so.7") +install_extra_runtime_library(AYATANA_IDO_LIBRARY "libayatana-ido3-0.4.so.0") +install_extra_runtime_library(DBUSMENU_GLIB_LIBRARY "libdbusmenu-glib.so.4") +install_extra_runtime_library(DBUSMENU_GTK3_LIBRARY "libdbusmenu-gtk3.so.4") +install_extra_runtime_library(XTST_LIBRARY "libXtst.so.6") +install_extra_runtime_library(WAYLAND_CLIENT_LIBRARY "libwayland-client.so.0") + # Copy the native assets provided by the build.dart from all packages. set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") install(DIRECTORY "${NATIVE_ASSETS_DIR}" diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 6ad2f4fd..5666a12d 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -16,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni zip_flutter ) diff --git a/linux/my_application.cc b/linux/my_application.cc index 1f7fb08d..a8902e72 100644 --- a/linux/my_application.cc +++ b/linux/my_application.cc @@ -1,6 +1,7 @@ #include "my_application.h" #include #include +#include #ifdef GDK_WINDOWING_X11 #include #endif @@ -10,7 +11,7 @@ #include "window_manager/window_manager_plugin.h" #include "desktop_drop/desktop_drop_plugin.h" -const char* PID_FILE_NAME = "pid.txt"; +const char* PID_FILE_NAME = "clipshare.pid"; struct _MyApplication { GtkApplication parent_instance; char** dart_entrypoint_arguments; @@ -20,6 +21,8 @@ G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) void write_pid_to_file(const char *filename) { pid_t pid = getpid(); + g_autofree gchar* dir_name = g_path_get_dirname(filename); + g_mkdir_with_parents(dir_name, 0700); FILE *file = fopen(filename, "w"); if (file == NULL) { perror("can not open file!"); @@ -81,6 +84,18 @@ gchar* get_process_name_by_pid(pid_t pid) { return g_strdup(buf); } +gchar* get_pid_file_path() { + const char* runtime_dir = g_getenv("XDG_RUNTIME_DIR"); + if (runtime_dir && runtime_dir[0] != '\0') { + return g_build_filename(runtime_dir, PID_FILE_NAME, nullptr); + } + const char* home = g_getenv("HOME"); + if (home && home[0] != '\0') { + return g_build_filename(home, ".cache", PID_FILE_NAME, nullptr); + } + return g_build_filename("/tmp", PID_FILE_NAME, nullptr); +} + static void init_desktop_multi_window_plugin_window_created(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) window_manager_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin"); @@ -121,7 +136,7 @@ static void my_application_activate(GApplication* application) { gtk_window_set_title(window, "ClipShare"); } gtk_window_set_default_size(window, 1000, 650); - gtk_widget_show(GTK_WIDGET(window)); + gtk_widget_realize(GTK_WIDGET(window)); g_autoptr(FlDartProject) project = fl_dart_project_new(); fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); @@ -176,7 +191,8 @@ static void handle_sigusr1(int sig) { } } MyApplication* my_application_new() { - pid_t pid = read_pid_from_file(PID_FILE_NAME); + g_autofree gchar* pid_file_path = get_pid_file_path(); + pid_t pid = read_pid_from_file(pid_file_path); gchar* my_process_name = get_process_name_by_pid(getpid()); if(pid){ gchar* process_name = get_process_name_by_pid(pid); @@ -189,7 +205,7 @@ MyApplication* my_application_new() { } } signal(SIGUSR1, handle_sigusr1); - write_pid_to_file(PID_FILE_NAME); + write_pid_to_file(pid_file_path); return MY_APPLICATION(g_object_new(my_application_get_type(), "application-id", APPLICATION_ID, "flags", G_APPLICATION_NON_UNIQUE, diff --git a/linux/packaging/appimage/make_config.yaml b/linux/packaging/appimage/make_config.yaml index edd56382..bb97496e 100644 --- a/linux/packaging/appimage/make_config.yaml +++ b/linux/packaging/appimage/make_config.yaml @@ -33,5 +33,12 @@ keywords: # # 以下示例展示了如何将 libcurl 库与您的应用捆绑在一起 # -# include: -# - libcurl.so.4 \ No newline at end of file +include: + - libkeybinder-3.0.so.0 + - libayatana-appindicator3.so.1 + - libayatana-indicator3.so.7 + - libayatana-ido3-0.4.so.0 + - libdbusmenu-glib.so.4 + - libdbusmenu-gtk3.so.4 + - libXtst.so.6 + - libwayland-client.so.0 diff --git a/linux/packaging/deb/make_config.yaml b/linux/packaging/deb/make_config.yaml index fb4effbb..46627c99 100644 --- a/linux/packaging/deb/make_config.yaml +++ b/linux/packaging/deb/make_config.yaml @@ -16,8 +16,14 @@ essential: false icon: assets/images/logo/logo.png dependencies: - - libayatana-appindicator3-dev - - libkeybinder-3.0-dev + - libgtk-3-0 + - libayatana-appindicator3-1 + - libkeybinder-3.0-0 + - libx11-6 + - libxext6 + - libxtst6 + - libwayland-client0 + - libsqlite3-0 keywords: - Clipboard @@ -30,4 +36,4 @@ keywords: - Manager - Enhanced Clipboard - Paste History -startup_notify: true \ No newline at end of file +startup_notify: true diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 6e1ac059..cc0afece 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -16,7 +16,6 @@ import hotkey_manager_macos import local_auth_darwin import no_screenshot import package_info_plus -import path_provider_foundation import screen_retriever_macos import share_plus import smart_auth @@ -39,7 +38,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) MacOSNoScreenshotPlugin.register(with: registry.registrar(forPlugin: "MacOSNoScreenshotPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SmartAuthPlugin.register(with: registry.registrar(forPlugin: "SmartAuthPlugin")) diff --git a/packaging/aur/clipshare-bin b/packaging/aur/clipshare-bin new file mode 160000 index 00000000..fba9430e --- /dev/null +++ b/packaging/aur/clipshare-bin @@ -0,0 +1 @@ +Subproject commit fba9430e9285a9711da63019cabba954cbd42cee diff --git a/pid.txt b/pid.txt new file mode 100644 index 00000000..763dc280 --- /dev/null +++ b/pid.txt @@ -0,0 +1 @@ +11459 \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 5602d6aa..129c88b4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: _fe_analyzer_shared sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "67.0.0" analyzer: @@ -14,7 +14,7 @@ packages: description: name: analyzer sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.4.1" animated_snack_bar: @@ -22,7 +22,7 @@ packages: description: name: animated_snack_bar sha256: "9ec2d79507546f65b82038c9ac5ddfc3c2fccf285def43070606b0ec0fc56d34" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.4.0" animated_theme_switcher: @@ -30,7 +30,7 @@ packages: description: name: animated_theme_switcher sha256: "24ccd74437b8db78f6d1ec701804702817bced5f925b1b3419c7a93071e3d3e9" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.10" archive: @@ -38,7 +38,7 @@ packages: description: name: archive sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.6.1" args: @@ -46,7 +46,7 @@ packages: description: name: args sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.7.0" asn1lib: @@ -54,23 +54,23 @@ packages: description: name: asn1lib sha256: "9a8f69025044eb466b9b60ef3bc3ac99b4dc6c158ae9c56d25eeccf5bc56d024" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.6.5" async: dependency: transitive description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" - url: "https://pub.flutter-io.cn" + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" source: hosted - version: "2.13.0" + version: "2.13.1" basic_utils: dependency: "direct main" description: name: basic_utils sha256: "2064b21d3c41ed7654bc82cc476fd65542e04d60059b74d5eed490a4da08fc6c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.7.0" boolean_selector: @@ -78,7 +78,7 @@ packages: description: name: boolean_selector sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" buffer: @@ -86,7 +86,7 @@ packages: description: name: buffer sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.3" build: @@ -94,7 +94,7 @@ packages: description: name: build sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.1" build_config: @@ -102,7 +102,7 @@ packages: description: name: build_config sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.2" build_daemon: @@ -110,7 +110,7 @@ packages: description: name: build_daemon sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.1" build_resolvers: @@ -118,7 +118,7 @@ packages: description: name: build_resolvers sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2" build_runner: @@ -126,7 +126,7 @@ packages: description: name: build_runner sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.13" build_runner_core: @@ -134,7 +134,7 @@ packages: description: name: build_runner_core sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.3.2" built_collection: @@ -142,39 +142,39 @@ packages: description: name: built_collection sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - sha256: "7931c90b84bc573fef103548e354258ae4c9d28d140e41961df6843c5d60d4d8" - url: "https://pub.flutter-io.cn" + sha256: "0730c18c770d05636a8f945c32a4d7d81cb6e0f0148c8db4ad12e7748f7e49af" + url: "https://pub.dev" source: hosted - version: "8.12.3" + version: "8.12.5" calendar_date_picker2: dependency: "direct main" description: name: calendar_date_picker2 sha256: "7b5f20f2a02768df70b3d1fb181c217ab9f8992f39fd6c3fc2ff95b0885820a2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.9" characters: dependency: transitive description: name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.flutter-io.cn" + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" charcode: dependency: transitive description: name: charcode sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" checked_yaml: @@ -182,7 +182,7 @@ packages: description: name: checked_yaml sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.4" cli_util: @@ -190,30 +190,38 @@ packages: description: name: cli_util sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.4.2" clipshare_clipboard_listener: dependency: "direct main" description: - path: "../clipboard_listener" + path: ClipboardListener relative: true source: path - version: "1.2.13" + version: "1.2.15" clock: dependency: transitive description: name: clock sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" code_builder: dependency: transitive description: name: code_builder sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.11.1" collection: @@ -221,7 +229,7 @@ packages: description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.19.1" connectivity_plus: @@ -229,7 +237,7 @@ packages: description: name: connectivity_plus sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.2" connectivity_plus_platform_interface: @@ -237,7 +245,7 @@ packages: description: name: connectivity_plus_platform_interface sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.4" convert: @@ -245,7 +253,7 @@ packages: description: name: convert sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.2" cross_file: @@ -253,7 +261,7 @@ packages: description: name: cross_file sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.3.5+2" crypto: @@ -261,17 +269,17 @@ packages: description: name: crypto sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.7" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.flutter-io.cn" + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" + url: "https://pub.dev" source: hosted - version: "1.0.8" + version: "1.0.9" dart_aliyun_oss: dependency: "direct main" description: @@ -286,7 +294,7 @@ packages: description: name: dart_style sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.6" dbus: @@ -294,7 +302,7 @@ packages: description: name: dbus sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.12" desktop_drop: @@ -302,7 +310,7 @@ packages: description: name: desktop_drop sha256: "03abf1c0443afdd1d65cf8fa589a2f01c67a11da56bbb06f6ea1de79d5628e94" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.0" desktop_multi_window: @@ -310,23 +318,23 @@ packages: description: name: desktop_multi_window sha256: "3ea2d696e50c3df696aabfddbd98c220ab4dde38f12c2ab12d1103bfe00ae79b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.1" dev_build: dependency: transitive description: name: dev_build - sha256: "1d9aa167c05cbe4be9fbaf863c76dcee9bec302fb861270672beb6d6be0bc8f4" - url: "https://pub.flutter-io.cn" + sha256: b8f6c8c6e4179bf749652efa2f4fd44f1f07cdab2c4f078b777d9bf2320765cf + url: "https://pub.dev" source: hosted - version: "1.1.3+1" + version: "1.1.5+2" device_info_plus: dependency: "direct main" description: name: device_info_plus sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "11.5.0" device_info_plus_platform_interface: @@ -334,31 +342,31 @@ packages: description: name: device_info_plus_platform_interface sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.3" dio: dependency: "direct main" description: name: dio - sha256: b9d46faecab38fc8cc286f80bc4d61a3bb5d4ac49e51ed877b4d6706efe57b25 - url: "https://pub.flutter-io.cn" + sha256: aff32c08f92787a557dd5c0145ac91536481831a01b4648136373cddb0e64f8c + url: "https://pub.dev" source: hosted - version: "5.9.1" + version: "5.9.2" dio_web_adapter: dependency: transitive description: name: dio_web_adapter - sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" - url: "https://pub.flutter-io.cn" + sha256: "2f9e64323a7c3c7ef69567d5c800424a11f8337b8b228bad02524c9fb3c1f340" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" easy_cron: dependency: "direct main" description: name: easy_cron sha256: "0a3c9115047b8e93ba26d9f2b1805b12d9f977437e7a6de81fe242ecd30794cb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.9.2" encrypt: @@ -366,7 +374,7 @@ packages: description: name: encrypt sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.3" equatable: @@ -374,7 +382,7 @@ packages: description: name: equatable sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.8" fake_async: @@ -382,7 +390,7 @@ packages: description: name: fake_async sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.3" ffi: @@ -390,7 +398,7 @@ packages: description: name: ffi sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" file: @@ -398,7 +406,7 @@ packages: description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.1" file_picker: @@ -415,7 +423,7 @@ packages: description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" floor: @@ -423,7 +431,7 @@ packages: description: name: floor sha256: c1b06023912b5b8e49deb6a9d867863c535ae1a232d991c3582bba3ee8687867 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" floor_annotation: @@ -431,7 +439,7 @@ packages: description: name: floor_annotation sha256: a40949580a7ab0eee572686e2d3b1638fd6bd6a753e661d792ab4236b365b23b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" floor_common: @@ -439,7 +447,7 @@ packages: description: name: floor_common sha256: "41c9914862f83a821815e1b1ffd47a1e1ae2130c35ff882ba2d000a67713ba64" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" floor_generator: @@ -447,7 +455,7 @@ packages: description: name: floor_generator sha256: "1499b3ab878a807e6fbe6f140dc014124845cd1df3090a113aae5fa7577a1e77" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" flutter: @@ -460,7 +468,7 @@ packages: description: name: flutter_context_menu sha256: "31fd331e1ca2c0136940294ac26f641e4377aa4413ad823d198719feaebc9b83" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.5" flutter_expandable_fab: @@ -468,7 +476,7 @@ packages: description: name: flutter_expandable_fab sha256: "2a488600924fd2a041679ad889807ee5670414a7a518cf11d4854b9898b3504f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.5.2" flutter_highlighting: @@ -476,7 +484,7 @@ packages: description: name: flutter_highlighting sha256: "426770b1453e8302f8cc58455ebcaad33e3049e73ca18f9d3c83554552bf3baf" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.9.0+11.8.0" flutter_launcher_icons: @@ -484,7 +492,7 @@ packages: description: name: flutter_launcher_icons sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.13.1" flutter_linkify: @@ -492,7 +500,7 @@ packages: description: name: flutter_linkify sha256: "74669e06a8f358fee4512b4320c0b80e51cffc496607931de68d28f099254073" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.0.0" flutter_lints: @@ -500,7 +508,7 @@ packages: description: name: flutter_lints sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.2" flutter_local_notifications: @@ -508,7 +516,7 @@ packages: description: name: flutter_local_notifications sha256: "19ffb0a8bb7407875555e5e98d7343a633bb73707bae6c6a5f37c90014077875" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "19.5.0" flutter_local_notifications_linux: @@ -516,7 +524,7 @@ packages: description: name: flutter_local_notifications_linux sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.0.0" flutter_local_notifications_platform_interface: @@ -524,7 +532,7 @@ packages: description: name: flutter_local_notifications_platform_interface sha256: "277d25d960c15674ce78ca97f57d0bae2ee401c844b6ac80fcd972a9c99d09fe" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "9.1.0" flutter_local_notifications_windows: @@ -532,7 +540,7 @@ packages: description: name: flutter_local_notifications_windows sha256: "8d658f0d367c48bd420e7cf2d26655e2d1130147bca1eea917e576ca76668aaf" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.3" flutter_localizations: @@ -545,17 +553,17 @@ packages: description: name: flutter_markdown sha256: "04c4722cc36ec5af38acc38ece70d22d3c2123c61305d555750a091517bbe504" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.6.23" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1 - url: "https://pub.flutter-io.cn" + sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0" + url: "https://pub.dev" source: hosted - version: "2.0.33" + version: "2.0.34" flutter_screenshot_detect: dependency: "direct main" description: @@ -570,7 +578,7 @@ packages: description: name: flutter_slidable sha256: ea369262929d3cc6ebf9d8a00c196127966f117fe433a5e5cb47fb08008ca203 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.3" flutter_staggered_grid_view: @@ -578,7 +586,7 @@ packages: description: name: flutter_staggered_grid_view sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.0" flutter_test: @@ -596,7 +604,7 @@ packages: description: name: frontend_server_client sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.0" get: @@ -604,7 +612,7 @@ packages: description: name: get sha256: "5ed34a7925b85336e15d472cc4cfe7d9ebf4ab8e8b9f688585bf6b50f4c3d79a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.7.3" get_apps: @@ -621,23 +629,23 @@ packages: description: name: glob sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.3" graphic: dependency: "direct main" description: name: graphic - sha256: af3a5a967d95ce2c2c9f7dee83c21f8bd6e6a458341820920cf15c0311cdaddc - url: "https://pub.flutter-io.cn" + sha256: f0028af737f7fdd5fd50c043af85242d72638ae040a820470208bc885a229d04 + url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.0" graphs: dependency: transitive description: name: graphs sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.2" highlighting: @@ -645,15 +653,23 @@ packages: description: name: highlighting sha256: "196005ed9c98ee559939fcecd466fa941b9e99b3a93394691b86780ad4da50f3" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.9.0+11.8.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 + url: "https://pub.dev" + source: hosted + version: "1.0.2" hotkey_manager: dependency: "direct main" description: name: hotkey_manager sha256: "06f0655b76c8dd322fb7101dc615afbdbf39c3d3414df9e059c33892104479cd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.3" hotkey_manager_linux: @@ -661,7 +677,7 @@ packages: description: name: hotkey_manager_linux sha256: "83676bda8210a3377bc6f1977f193bc1dbdd4c46f1bdd02875f44b6eff9a8473" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" hotkey_manager_macos: @@ -669,7 +685,7 @@ packages: description: name: hotkey_manager_macos sha256: "03b5967e64357b9ac05188ea4a5df6fe4ed4205762cb80aaccf8916ee1713c96" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" hotkey_manager_platform_interface: @@ -677,7 +693,7 @@ packages: description: name: hotkey_manager_platform_interface sha256: "98ffca25b8cc9081552902747b2942e3bc37855389a4218c9d50ca316b653b13" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" hotkey_manager_windows: @@ -685,7 +701,7 @@ packages: description: name: hotkey_manager_windows sha256: "0d03ced9fe563ed0b68f0a0e1b22c9ffe26eb8053cb960e401f68a4f070e0117" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" http: @@ -693,7 +709,7 @@ packages: description: name: http sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.6.0" http_multi_server: @@ -701,7 +717,7 @@ packages: description: name: http_multi_server sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.2" http_parser: @@ -709,7 +725,7 @@ packages: description: name: http_parser sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.2" image: @@ -717,7 +733,7 @@ packages: description: name: image sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.3.0" intl: @@ -725,7 +741,7 @@ packages: description: name: intl sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.20.2" io: @@ -733,7 +749,7 @@ packages: description: name: io sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.5" isolate_contactor: @@ -741,7 +757,7 @@ packages: description: name: isolate_contactor sha256: "6ba8434ceb58238a1389d6365111a3efe7baa1c68a66f4db6d63d351cf6c3a0f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.0" isolate_manager: @@ -749,7 +765,7 @@ packages: description: name: isolate_manager sha256: "22ed0c25f80ec3b5f21e3a55d060f4650afff33f27c2dff34c0f9409d5759ae5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.5+1" jieba_flutter: @@ -766,31 +782,47 @@ packages: description: name: jiffy sha256: e6f3b2aaec032f95ae917268edcbf007a5b834b57a602d39eb0ab17995a9c64a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.4.4" + jni: + dependency: transitive + description: + name: jni + sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f + url: "https://pub.dev" + source: hosted + version: "1.0.0" + jni_flutter: + dependency: transitive + description: + name: jni_flutter + sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6" + url: "https://pub.dev" + source: hosted + version: "1.0.1" js: dependency: transitive description: name: js sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.6.7" json_annotation: dependency: transitive description: name: json_annotation - sha256: "805fa86df56383000f640384b282ce0cb8431f1a7a2396de92fb66186d8c57df" - url: "https://pub.flutter-io.cn" + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 + url: "https://pub.dev" source: hosted - version: "4.10.0" + version: "4.11.0" launch_at_startup: dependency: "direct main" description: name: launch_at_startup sha256: "7db33398b76ec0ed9e27f9f4640553e239977437564046625e215be89c91f084" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.1" leak_tracker: @@ -798,7 +830,7 @@ packages: description: name: leak_tracker sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "11.0.2" leak_tracker_flutter_testing: @@ -806,7 +838,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.10" leak_tracker_testing: @@ -814,7 +846,7 @@ packages: description: name: leak_tracker_testing sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.2" linkify: @@ -822,7 +854,7 @@ packages: description: name: linkify sha256: "4139ea77f4651ab9c315b577da2dd108d9aa0bd84b5d03d33323f1970c645832" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.0" lints: @@ -830,7 +862,7 @@ packages: description: name: lints sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.0" lists: @@ -838,7 +870,7 @@ packages: description: name: lists sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.1" local_auth: @@ -846,7 +878,7 @@ packages: description: name: local_auth sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.0" local_auth_android: @@ -854,7 +886,7 @@ packages: description: name: local_auth_android sha256: a0bdfcc0607050a26ef5b31d6b4b254581c3d3ce3c1816ab4d4f4a9173e84467 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.56" local_auth_darwin: @@ -862,7 +894,7 @@ packages: description: name: local_auth_darwin sha256: "699873970067a40ef2f2c09b4c72eb1cfef64224ef041b3df9fdc5c4c1f91f49" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.6.1" local_auth_platform_interface: @@ -870,7 +902,7 @@ packages: description: name: local_auth_platform_interface sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" local_auth_windows: @@ -878,55 +910,55 @@ packages: description: name: local_auth_windows sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.11" logger: dependency: "direct main" description: name: logger - sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3 - url: "https://pub.flutter-io.cn" + sha256: "25aee487596a6257655a1e091ec2ae66bc30e7af663592cc3a27e6591e05035c" + url: "https://pub.dev" source: hosted - version: "2.6.2" + version: "2.7.0" logging: dependency: transitive description: name: logging sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.0" markdown: dependency: transitive description: name: markdown - sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" - url: "https://pub.flutter-io.cn" + sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9 + url: "https://pub.dev" source: hosted - version: "7.3.0" + version: "7.3.1" matcher: dependency: transitive description: name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.flutter-io.cn" + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + url: "https://pub.dev" source: hosted - version: "0.12.17" + version: "0.12.18" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.flutter-io.cn" + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" material_design_icons_flutter: dependency: "direct main" description: name: material_design_icons_flutter sha256: "6f986b7a51f3ad4c00e33c5c84e8de1bdd140489bbcdc8b66fc1283dad4dea5a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.7296" menu_base: @@ -934,23 +966,23 @@ packages: description: name: menu_base sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.1" meta: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.flutter-io.cn" + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: transitive description: name: mime sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.0" minio: @@ -958,7 +990,7 @@ packages: description: name: minio sha256: ee2ce47766e46c7d164f960f2f5ed6a9a82844d877f6b82574f6876ec50c56d1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.5.8" month_picker_dialog: @@ -966,7 +998,7 @@ packages: description: name: month_picker_dialog sha256: eced16a01a3a324d6b6fd965e6c21811be2678c64143c6326256adb0eece7445 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.2.0" msgpack_dart: @@ -974,15 +1006,23 @@ packages: description: name: msgpack_dart sha256: c2d235ed01f364719b5296aecf43ac330f0d7bc865fa134d0d7910a40454dffb - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.1" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" + url: "https://pub.dev" + source: hosted + version: "0.17.6" nested: dependency: transitive description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.0" nm: @@ -990,7 +1030,7 @@ packages: description: name: nm sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.0" no_screenshot: @@ -1011,6 +1051,14 @@ packages: url: "https://github.com/aa2013/notification_listener_service" source: git version: "0.3.4" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" + url: "https://pub.dev" + source: hosted + version: "9.3.0" open_file_plus: dependency: "direct main" description: @@ -1025,7 +1073,7 @@ packages: description: name: package_config sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" package_info_plus: @@ -1033,7 +1081,7 @@ packages: description: name: package_info_plus sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "8.3.1" package_info_plus_platform_interface: @@ -1041,7 +1089,7 @@ packages: description: name: package_info_plus_platform_interface sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.1" path: @@ -1049,7 +1097,7 @@ packages: description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.9.1" path_drawing: @@ -1057,7 +1105,7 @@ packages: description: name: path_drawing sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.1" path_parsing: @@ -1065,7 +1113,7 @@ packages: description: name: path_parsing sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" path_provider: @@ -1073,31 +1121,31 @@ packages: description: name: path_provider sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e - url: "https://pub.flutter-io.cn" + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" + url: "https://pub.dev" source: hosted - version: "2.2.22" + version: "2.3.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4" - url: "https://pub.flutter-io.cn" + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.0" path_provider_linux: dependency: transitive description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -1105,7 +1153,7 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" path_provider_windows: @@ -1113,7 +1161,7 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.0" permission_handler: @@ -1121,7 +1169,7 @@ packages: description: name: permission_handler sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "11.4.0" permission_handler_android: @@ -1129,7 +1177,7 @@ packages: description: name: permission_handler_android sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "12.1.0" permission_handler_apple: @@ -1137,7 +1185,7 @@ packages: description: name: permission_handler_apple sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "9.4.7" permission_handler_html: @@ -1145,7 +1193,7 @@ packages: description: name: permission_handler_html sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.3+5" permission_handler_platform_interface: @@ -1153,7 +1201,7 @@ packages: description: name: permission_handler_platform_interface sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.3.0" permission_handler_windows: @@ -1161,7 +1209,7 @@ packages: description: name: permission_handler_windows sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.1" persistent_device_id: @@ -1169,23 +1217,23 @@ packages: description: name: persistent_device_id sha256: b9f95798a551a85d0781d24f2acbb9e443e3802c6a49c59f725ec4d4537ac8ac - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" petitparser: dependency: transitive description: name: petitparser - sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" - url: "https://pub.flutter-io.cn" + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.2" pinput: dependency: "direct main" description: name: pinput sha256: a92b55ecf9c25d1b9e100af45905385d5bc34fc9b6b04177a9e82cb88fe4d805 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.1" platform: @@ -1193,7 +1241,7 @@ packages: description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.6" plugin_platform_interface: @@ -1201,7 +1249,7 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.8" pointycastle: @@ -1209,7 +1257,7 @@ packages: description: name: pointycastle sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.9.1" pool: @@ -1217,23 +1265,23 @@ packages: description: name: pool sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.2" process_run: dependency: transitive description: name: process_run - sha256: "6ec839cdd3e6de4685318e7686cd4abb523c3d3a55af0e8d32a12ae19bc66622" - url: "https://pub.flutter-io.cn" + sha256: "8bdbe7ec335391ad32e5119cdcecaa7f679bc924fc5a5d7e8bc7a8fbd22592a1" + url: "https://pub.dev" source: hosted - version: "1.2.4" + version: "1.3.2" provider: dependency: transitive description: name: provider sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.1.5+1" pub_semver: @@ -1241,7 +1289,7 @@ packages: description: name: pub_semver sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" pubspec_parse: @@ -1249,7 +1297,7 @@ packages: description: name: pubspec_parse sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" qr: @@ -1257,23 +1305,23 @@ packages: description: name: qr sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.2" qr_code_scanner_plus: dependency: "direct main" description: name: qr_code_scanner_plus - sha256: "11a91e185fbcd3314b470369878bcae7ecd233d0c3d78f864b67fa9a264f22c3" - url: "https://pub.flutter-io.cn" + sha256: dae0596b2763c2fd0294f5cfddb1d3a21577ae4dc7fc1449eb5aafc957872f61 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" qr_flutter: dependency: "direct main" description: name: qr_flutter sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.0" quiver: @@ -1281,7 +1329,7 @@ packages: description: name: quiver sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.2" re_editor: @@ -1289,7 +1337,7 @@ packages: description: name: re_editor sha256: dd4e6ca7350a8fa0cda4e425b82a0c3c010f0f6b3f618c74223e05b8129ab629 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.8.0" re_highlight: @@ -1297,7 +1345,7 @@ packages: description: name: re_highlight sha256: "6c4ac3f76f939fb7ca9df013df98526634e17d8f7460e028bd23a035870024f2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.0.3" resolve_windows_shortcut: @@ -1305,7 +1353,7 @@ packages: description: name: resolve_windows_shortcut sha256: "5055a52a04449274832d51b116792a5d981b2b69eb9577a878517d668eccf5ff" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.0" screen_retriever: @@ -1313,7 +1361,7 @@ packages: description: name: screen_retriever sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" screen_retriever_linux: @@ -1321,7 +1369,7 @@ packages: description: name: screen_retriever_linux sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" screen_retriever_macos: @@ -1329,7 +1377,7 @@ packages: description: name: screen_retriever_macos sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" screen_retriever_platform_interface: @@ -1337,7 +1385,7 @@ packages: description: name: screen_retriever_platform_interface sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" screen_retriever_windows: @@ -1345,7 +1393,7 @@ packages: description: name: screen_retriever_windows sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" share_handler: @@ -1353,7 +1401,7 @@ packages: description: name: share_handler sha256: "0a6d007f0e44fbee27164adcd159ecbc88238864313f4e5c58161cae2180328d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.0.25" share_handler_android: @@ -1361,7 +1409,7 @@ packages: description: name: share_handler_android sha256: caf555b933dc72783aa37fef75688c7b86bd6f7bc17d80fbf585bc42f123cc8d - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.0.11" share_handler_ios: @@ -1369,7 +1417,7 @@ packages: description: name: share_handler_ios sha256: cdc21f88f336a944157a8e9ceb191525cee3b082d6eb6c2082488e4f09dc3ece - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.0.15" share_handler_platform_interface: @@ -1377,7 +1425,7 @@ packages: description: name: share_handler_platform_interface sha256: "7a4df95a87b326b2f07458d937f2281874567c364b7b7ebe4e7d50efaae5f106" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.0.6" share_plus: @@ -1385,7 +1433,7 @@ packages: description: name: share_plus sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "10.1.4" share_plus_platform_interface: @@ -1393,7 +1441,7 @@ packages: description: name: share_plus_platform_interface sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.2" shelf: @@ -1401,7 +1449,7 @@ packages: description: name: shelf sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.2" shelf_web_socket: @@ -1409,7 +1457,7 @@ packages: description: name: shelf_web_socket sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.1" shortid: @@ -1417,7 +1465,7 @@ packages: description: name: shortid sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.2" sky_engine: @@ -1429,16 +1477,16 @@ packages: dependency: "direct main" description: name: sliver_sticky_collapsable_panel - sha256: d4e8a50d811925d324f6b6cdde287a53bf99464dcfc200dba5977da09f8e777c - url: "https://pub.flutter-io.cn" + sha256: "7a4841e568f4e556bb941e3ed4041e056a2867a399bd72ecea415a00a194fd8b" + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.4" smart_auth: dependency: transitive description: name: smart_auth sha256: a25229b38c02f733d0a4e98d941b42bed91a976cb589e934895e60ccfa674cf6 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" source_gen: @@ -1446,7 +1494,7 @@ packages: description: name: source_gen sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.5.0" source_span: @@ -1454,7 +1502,7 @@ packages: description: name: source_span sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.10.2" sqflite: @@ -1462,39 +1510,39 @@ packages: description: name: sqflite sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2" sqflite_android: dependency: transitive description: name: sqflite_android - sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88 - url: "https://pub.flutter-io.cn" + sha256: "881e28efdcc9950fd8e9bb42713dcf1103e62a2e7168f23c9338d82db13dec40" + url: "https://pub.dev" source: hosted - version: "2.4.2+2" + version: "2.4.2+3" sqflite_common: dependency: transitive description: name: sqflite_common sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.5.6" sqflite_common_ffi: dependency: transitive description: name: sqflite_common_ffi - sha256: "8d7b8749a516cbf6e9057f9b480b716ad14fc4f3d3873ca6938919cc626d9025" - url: "https://pub.flutter-io.cn" + sha256: c59fcdc143839a77581f7a7c4de018e53682408903a0a0800b95ef2dc4033eff + url: "https://pub.dev" source: hosted - version: "2.3.7+1" + version: "2.4.0+2" sqflite_common_ffi_web: dependency: transitive description: name: sqflite_common_ffi_web sha256: "61ea702e7aba727f28be7ead00b84c19c745cd4a4934d0c41473303df11ac9ea" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.4.5+4" sqflite_darwin: @@ -1502,7 +1550,7 @@ packages: description: name: sqflite_darwin sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2" sqflite_platform_interface: @@ -1510,23 +1558,23 @@ packages: description: name: sqflite_platform_interface sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.0" sqlite3: dependency: transitive description: name: sqlite3 - sha256: "3145bd74dcdb4fd6f5c6dda4d4e4490a8087d7f286a14dee5d37087290f0f8a2" - url: "https://pub.flutter-io.cn" + sha256: "56da3e13ed7d28a66f930aa2b2b29db6736a233f08283326e96321dd812030f5" + url: "https://pub.dev" source: hosted - version: "2.9.4" + version: "3.3.1" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs sha256: "69c80d812ef2500202ebd22002cbfc1b6565e9ff56b2f971e757fac5d42294df" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.40" sqlparser: @@ -1534,7 +1582,7 @@ packages: description: name: sqlparser sha256: "7b20045d1ccfb7bc1df7e8f9fee5ae58673fce6ff62cefbb0e0fd7214e90e5a0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.34.1" stack_trace: @@ -1542,7 +1590,7 @@ packages: description: name: stack_trace sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.12.1" stream_channel: @@ -1550,7 +1598,7 @@ packages: description: name: stream_channel sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.4" stream_transform: @@ -1558,7 +1606,7 @@ packages: description: name: stream_transform sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" string_scanner: @@ -1566,7 +1614,7 @@ packages: description: name: string_scanner sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.1" strings: @@ -1574,7 +1622,7 @@ packages: description: name: strings sha256: "052836499f03897d3860a603b330c1ea3c8a14177b21f34b15a1295f36024aae" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.2" syncfusion_flutter_core: @@ -1582,7 +1630,7 @@ packages: description: name: syncfusion_flutter_core sha256: bee87cdfe527b31705190162e3bd27bf468d591ae7c68182244bdfd94e21f737 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "29.2.11" syncfusion_flutter_xlsio: @@ -1590,7 +1638,7 @@ packages: description: name: syncfusion_flutter_xlsio sha256: "71d6d34cb39c626c82c1066f085f9087adc9b39507f2acbfeb653c2a4ea0916b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "29.2.11" syncfusion_officecore: @@ -1598,7 +1646,7 @@ packages: description: name: syncfusion_officecore sha256: "2c5f64d307d39f3c1e7c1ed2de07f04bc93365d590cee03e2f0307acb47ccc47" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "29.2.11" synchronized: @@ -1606,7 +1654,7 @@ packages: description: name: synchronized sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.4.0" term_glyph: @@ -1614,17 +1662,17 @@ packages: description: name: term_glyph sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" - url: "https://pub.flutter-io.cn" + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" + url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.9" timer_snackbar: dependency: "direct main" description: @@ -1639,7 +1687,7 @@ packages: description: name: timezone sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.10.1" timing: @@ -1647,7 +1695,7 @@ packages: description: name: timing sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.2" tray_manager: @@ -1655,7 +1703,7 @@ packages: description: name: tray_manager sha256: c5fd83b0ae4d80be6eaedfad87aaefab8787b333b8ebd064b0e442a81006035b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.2" tuple: @@ -1663,7 +1711,7 @@ packages: description: name: tuple sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.2" typed_data: @@ -1671,7 +1719,7 @@ packages: description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" uni_platform: @@ -1679,7 +1727,7 @@ packages: description: name: uni_platform sha256: e02213a7ee5352212412ca026afd41d269eb00d982faa552f419ffc2debfad84 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.1.3" unicode: @@ -1687,7 +1735,7 @@ packages: description: name: unicode sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.3.1" universal_platform: @@ -1695,7 +1743,7 @@ packages: description: name: universal_platform sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" uri_file_reader: @@ -1703,7 +1751,7 @@ packages: description: name: uri_file_reader sha256: "4a47f0feb0d52c78ac0d35ba809fe01dfc52dd8178f1693b21a0a0e3e6ca9cd0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.3" url_launcher: @@ -1711,31 +1759,31 @@ packages: description: name: url_launcher sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.3.2" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611" - url: "https://pub.flutter-io.cn" + sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572" + url: "https://pub.dev" source: hosted - version: "6.3.28" + version: "6.3.29" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad - url: "https://pub.flutter-io.cn" + sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" + url: "https://pub.dev" source: hosted - version: "6.3.6" + version: "6.4.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.2" url_launcher_macos: @@ -1743,7 +1791,7 @@ packages: description: name: url_launcher_macos sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.2.5" url_launcher_platform_interface: @@ -1751,23 +1799,23 @@ packages: description: name: url_launcher_platform_interface sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.flutter-io.cn" + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" url_launcher_windows: dependency: transitive description: name: url_launcher_windows sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.5" uuid: @@ -1775,7 +1823,7 @@ packages: description: name: uuid sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.5.3" vector_math: @@ -1783,7 +1831,7 @@ packages: description: name: vector_math sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" vm_service: @@ -1791,7 +1839,7 @@ packages: description: name: vm_service sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "15.0.2" wakelock_plus: @@ -1799,23 +1847,23 @@ packages: description: name: wakelock_plus sha256: "61713aa82b7f85c21c9f4cd0a148abd75f38a74ec645fcb1e446f882c82fd09b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.3" wakelock_plus_platform_interface: dependency: transitive description: name: wakelock_plus_platform_interface - sha256: "036deb14cd62f558ca3b73006d52ce049fabcdcb2eddfe0bf0fe4e8a943b5cf2" - url: "https://pub.flutter-io.cn" + sha256: "24b84143787220a403491c2e5de0877fbbb87baf3f0b18a2a988973863db4b03" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" watcher: dependency: transitive description: name: watcher sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" web: @@ -1823,7 +1871,7 @@ packages: description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" web_socket: @@ -1831,7 +1879,7 @@ packages: description: name: web_socket sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.1" web_socket_channel: @@ -1839,7 +1887,7 @@ packages: description: name: web_socket_channel sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.3" webdav_client: @@ -1856,7 +1904,7 @@ packages: description: name: win32 sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.15.0" win32_registry: @@ -1864,7 +1912,7 @@ packages: description: name: win32_registry sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.0" window_manager: @@ -1872,7 +1920,7 @@ packages: description: name: window_manager sha256: "7eb6d6c4164ec08e1bf978d6e733f3cebe792e2a23fb07cbca25c2872bfdbdcd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.1" xdg_directories: @@ -1880,7 +1928,7 @@ packages: description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" xml: @@ -1888,7 +1936,7 @@ packages: description: name: xml sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.6.1" yaml: @@ -1896,7 +1944,7 @@ packages: description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.3" zip_flutter: @@ -1909,5 +1957,5 @@ packages: source: git version: "0.0.13" sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" + dart: ">=3.10.3 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index 7bda5a6f..de5b8b2b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -113,9 +113,10 @@ dependencies: # 月份选择 month_picker_dialog: ^5.1.2 # 剪贴板监听 - clipshare_clipboard_listener: ^1.2.14 -# clipshare_clipboard_listener: -# path: ../clipboard_listener + # 先使用本地源码调试 Wayland/XWayland 剪贴板问题 + clipshare_clipboard_listener: + path: ClipboardListener +# clipshare_clipboard_listener: ^1.2.14 # 主题切换动画 animated_theme_switcher: ^2.0.8 # 大文本编辑器 diff --git a/scripts/build_linux.sh b/scripts/build_linux.sh index f74db7d8..a1af47e0 100755 --- a/scripts/build_linux.sh +++ b/scripts/build_linux.sh @@ -13,6 +13,57 @@ BUILD_NUMBER=$(grep "version:" ${PROJECT_ROOT}/pubspec.yaml | head -1 | awk '{pr # 构建 Flutter Linux Release 版本 BUILD_DIR="${PROJECT_ROOT}/build/linux/x64/release" BUNDLE_DIR="${BUILD_DIR}/bundle" +APPIMAGE_RUNTIME_LIBS=( + "libkeybinder-3.0.so.0" + "libayatana-appindicator3.so.1" + "libayatana-indicator3.so.7" + "libayatana-ido3-0.4.so.0" + "libdbusmenu-glib.so.4" + "libdbusmenu-gtk3.so.4" + "libXtst.so.6" + "libwayland-client.so.0" +) + +find_shared_library() { + local soname="$1" + local path="" + + if command -v ldconfig &> /dev/null; then + path=$(ldconfig -p 2>/dev/null | awk -v name="$soname" '$1 == name {print $NF; exit}') + fi + + if [ -z "$path" ]; then + for candidate in "/usr/lib/$soname" "/usr/lib64/$soname" "/lib/$soname" "/lib64/$soname"; do + if [ -f "$candidate" ]; then + path="$candidate" + break + fi + done + fi + + printf '%s' "$path" +} + +copy_runtime_libraries() { + local target_dir="$1" + mkdir -p "$target_dir" + + for soname in "${APPIMAGE_RUNTIME_LIBS[@]}"; do + if [ -f "${target_dir}/${soname}" ]; then + continue + fi + + local source_path + source_path=$(find_shared_library "$soname") + if [ -n "$source_path" ]; then + cp -L "$source_path" "${target_dir}/${soname}" + echo " + ${soname}" + else + echo "警告: 未找到运行库 ${soname},目标系统可能需要自行安装" + fi + done +} + build_flutter() { echo "=========================================" echo "构建 Flutter Linux Release" @@ -108,24 +159,23 @@ pack_appimage() { cp -r ${BUNDLE_DIR}/lib ${APPDIR}/usr/bin/ fi + echo "补充干净系统常缺的运行库..." + copy_runtime_libraries "${APPDIR}/usr/bin/lib" + # 复制数据目录(Flutter 期望数据在相对于可执行文件的 data/ 目录下) if [ -d "${BUNDLE_DIR}/data" ]; then echo "复制数据目录..." cp -r ${BUNDLE_DIR}/data ${APPDIR}/usr/bin/ fi - # 复制 files 目录(如果存在) - if [ -d "${BUNDLE_DIR}/files" ]; then - echo "复制 files 目录..." - cp -r ${BUNDLE_DIR}/files ${APPDIR}/usr/bin/ - fi + # 不复制运行时 files 目录;AppImage 挂载后是只读的,用户数据应落到应用文档目录。 # 创建 AppRun 脚本 echo "创建 AppRun 脚本..." if [ -f "${APPIMAGE_DIR}/AppRun" ]; then cp ${APPIMAGE_DIR}/AppRun ${APPDIR}/AppRun else - printf '#!/bin/bash\nSELF=$(readlink -f "$0")\nHERE=${SELF%%/*}\nexport PATH="${HERE}/usr/bin:${PATH}"\nexport LD_LIBRARY_PATH="${HERE}/usr/bin/lib:${LD_LIBRARY_PATH}"\nexec "${HERE}/usr/bin/clipshare" "$@"\n' > ${APPDIR}/AppRun + printf '#!/bin/bash\nSELF=$(readlink -f "$0")\nHERE=${SELF%%/AppRun}\nexport PATH="${HERE}/usr/bin:${PATH}"\nexport LD_LIBRARY_PATH="${HERE}/usr/bin/lib:${LD_LIBRARY_PATH}"\nexec "${HERE}/usr/bin/clipshare" "$@"\n' > ${APPDIR}/AppRun fi chmod +x ${APPDIR}/AppRun @@ -162,7 +212,12 @@ pack_appimage() { OUTPUT_FILE="${APPIMAGE_OUTPUT_DIR}/ClipShare-${VERSION}.AppImage" ARCH=$(uname -m) - ${APPIAGETOOL} ${APPDIR} ${OUTPUT_FILE} + RUNTIME_FILE="${APPIMAGE_OUTPUT_DIR}/runtime-x86_64" + if [ -f "${RUNTIME_FILE}" ]; then + ${APPIAGETOOL} --runtime-file ${RUNTIME_FILE} ${APPDIR} ${OUTPUT_FILE} + else + ${APPIAGETOOL} ${APPDIR} ${OUTPUT_FILE} + fi if [ -f "${OUTPUT_FILE}" ]; then echo "" diff --git a/scripts/quick-appimage/appimage.yml b/scripts/quick-appimage/appimage.yml index af7a8020..8d36f424 100644 --- a/scripts/quick-appimage/appimage.yml +++ b/scripts/quick-appimage/appimage.yml @@ -21,6 +21,10 @@ build: - liblzma-dev - libstdc++-12-dev - libayatana-appindicator3-dev + - libkeybinder-3.0-dev + - libx11-dev + - libxtst-dev + - libwayland-dev - libnotify-dev - libxkbcommon-dev - libsecret-1-dev @@ -87,6 +91,44 @@ script: cp -r ${BUNDLE_DIR}/lib ${APPDIR}/usr/bin/ fi + # 补充干净系统常缺的运行库 + - echo "补充运行库..." + - | + copy_runtime_lib() { + soname="$1" + target="${APPDIR}/usr/bin/lib/${soname}" + if [ -f "$target" ]; then + return 0 + fi + + source_path="$(ldconfig -p 2>/dev/null | awk -v name="$soname" '$1 == name {print $NF; exit}')" + if [ -z "$source_path" ]; then + for candidate in "/usr/lib/$soname" "/usr/lib64/$soname" "/lib/$soname" "/lib64/$soname"; do + if [ -f "$candidate" ]; then + source_path="$candidate" + break + fi + done + fi + + if [ -n "$source_path" ]; then + cp -L "$source_path" "$target" + echo " + ${soname}" + else + echo "警告: 未找到运行库 ${soname}" + fi + } + + mkdir -p ${APPDIR}/usr/bin/lib + copy_runtime_lib libkeybinder-3.0.so.0 + copy_runtime_lib libayatana-appindicator3.so.1 + copy_runtime_lib libayatana-indicator3.so.7 + copy_runtime_lib libayatana-ido3-0.4.so.0 + copy_runtime_lib libdbusmenu-glib.so.4 + copy_runtime_lib libdbusmenu-gtk3.so.4 + copy_runtime_lib libXtst.so.6 + copy_runtime_lib libwayland-client.so.0 + # 复制 files 目录(如果存在) - | if [ -d "${BUNDLE_DIR}/files" ]; then diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 12c3f2f3..eb357327 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -21,6 +21,7 @@ list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST flutter_local_notifications_windows + jni zip_flutter )