new: wear settings (#358) & opt.: android widget edit

This commit is contained in:
lollipopkit
2024-05-27 20:52:46 +08:00
parent 1a3cb09ca2
commit fbabd8c351
7 changed files with 119 additions and 43 deletions

View File

@@ -11,22 +11,32 @@ permissions:
jobs: jobs:
releaseAL: releaseAL:
name: Release android and linux name: Release android and linux
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: '0'
- name: Install Flutter - name: Install Flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
- uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: Fetch secrets
run: |
curl -u ${{ secrets.BASIC_AUTH }} -o android/app/app.key ${{ secrets.URL_PREFIX }}app.key
curl -u ${{ secrets.BASIC_AUTH }} -o android/key.properties ${{ secrets.URL_PREFIX }}key.properties
- name: Build - name: Build
run: dart run fl_build -p android,linux run: dart run fl_build -p android,linux
- name: Create Release - name: Create Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:
files: | files: |
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_arm64.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm64.apk
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_arm.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm.apk
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_amd64.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.apk
${{ env.APP_NAME }}_amd64.AppImage ${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.AppImage
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,6 +1,6 @@
import 'package:dynamic_color/dynamic_color.dart'; import 'package:dynamic_color/dynamic_color.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:fl_lib/l10n/gen/lib_l10n.dart'; import 'package:fl_lib/l10n/gen_l10n/lib_l10n.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/data/res/build_data.dart'; import 'package:toolbox/data/res/build_data.dart';

View File

@@ -246,4 +246,8 @@ class AppRoutes {
static AppRoutes pve({Key? key, required ServerPrivateInfo spi}) { static AppRoutes pve({Key? key, required ServerPrivateInfo spi}) {
return AppRoutes(PvePage(key: key, spi: spi), 'pve'); return AppRoutes(PvePage(key: key, spi: spi), 'pve');
} }
static AppRoutes kvEditor({Key? key, required Map<String, String> data}) {
return AppRoutes(KvEditor(key: key, data: data), 'kv_editor');
}
} }

View File

@@ -16,7 +16,7 @@ final class WearHome extends StatefulWidget {
const WearHome({super.key}); const WearHome({super.key});
@override @override
_WearHomeState createState() => _WearHomeState(); State<WearHome> createState() => _WearHomeState();
} }
final class _WearHomeState extends State<WearHome> with AfterLayoutMixin { final class _WearHomeState extends State<WearHome> with AfterLayoutMixin {
@@ -61,11 +61,30 @@ final class _WearHomeState extends State<WearHome> with AfterLayoutMixin {
} }
Widget _buildEachSever(Server srv) { Widget _buildEachSever(Server srv) {
return const Padding( final mem = () {
padding: EdgeInsets.all(7), final total = srv.status.mem.total;
final used = srv.status.mem.total - srv.status.mem.avail;
return '${used.bytes2Str} / ${total.bytes2Str}';
}();
final disk = () {
final total = srv.status.diskUsage?.size.kb2Str;
final used = srv.status.diskUsage?.used.kb2Str;
return '$used / $total';
}();
final net = '${srv.status.netSpeed.cachedRealVals.speedIn}'
'${srv.status.netSpeed.cachedRealVals.speedOut}';
return Padding(
padding: const EdgeInsets.all(7),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [], children: [
Text(srv.spi.name, style: UIs.text15Bold),
UIs.height7,
KvRow(k: 'CPU', v: '${srv.status.cpu.usedPercent()}%'),
KvRow(k: 'Mem', v: mem),
KvRow(k: 'Disk', v: disk),
KvRow(k: 'Net', v: net)
],
), ),
); );
} }

View File

@@ -1163,20 +1163,30 @@ class _SettingPageState extends State<SettingPage> {
return ListTile( return ListTile(
leading: const Icon(Icons.image), leading: const Icon(Icons.image),
title: Text('Logo ${l10n.addr}'), title: Text('Logo ${l10n.addr}'),
subtitle: SimpleMarkdown(data: '[${l10n.doc}](${Urls.appWiki})'),
trailing: const Icon(Icons.keyboard_arrow_right), trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () { onTap: () {
final ctrl = final ctrl =
TextEditingController(text: _setting.serverLogoUrl.fetch()); TextEditingController(text: _setting.serverLogoUrl.fetch());
context.showRoundDialog( context.showRoundDialog(
title: 'Logo ${l10n.addr}', title: 'Logo ${l10n.addr}',
child: Input( child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Input(
controller: ctrl, controller: ctrl,
autoFocus: true, autoFocus: true,
hint: 'https://example.com/logo.png', hint: 'https://example.com/logo.png',
icon: Icons.link, icon: Icons.link,
maxLines: 3,
onSubmitted: onSave, onSubmitted: onSave,
), ),
ListTile(
title: Text(l10n.doc),
trailing: const Icon(Icons.open_in_new),
onTap: () => Urls.appWiki.launch(),
),
],
),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => onSave(ctrl.text), onPressed: () => onSave(ctrl.text),

View File

@@ -1,21 +1,22 @@
import 'dart:convert';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:toolbox/core/extension/context/locale.dart'; import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/core/route.dart';
import 'package:toolbox/data/res/store.dart'; import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/page/setting/platform/platform_pub.dart'; import 'package:toolbox/view/page/setting/platform/platform_pub.dart';
import 'package:watch_connectivity/watch_connectivity.dart';
class AndroidSettingsPage extends StatefulWidget { class AndroidSettingsPage extends StatefulWidget {
const AndroidSettingsPage({super.key}); const AndroidSettingsPage({super.key});
@override @override
_AndroidSettingsPageState createState() => _AndroidSettingsPageState(); State<AndroidSettingsPage> createState() => _AndroidSettingsPageState();
} }
class _AndroidSettingsPageState extends State<AndroidSettingsPage> { class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
late SharedPreferences _sp; late SharedPreferences _sp;
final wc = WatchConnectivity();
@override @override
void initState() { void initState() {
@@ -34,6 +35,7 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
children: [ children: [
_buildBgRun(), _buildBgRun(),
_buildAndroidWidgetSharedPreference(), _buildAndroidWidgetSharedPreference(),
_buildWatch(),
if (BioAuth.isPlatformSupported) if (BioAuth.isPlatformSupported)
PlatformPublicSettings.buildBioAuth(), PlatformPublicSettings.buildBioAuth(),
].map((e) => CardX(child: e)).toList(), ].map((e) => CardX(child: e)).toList(),
@@ -49,10 +51,9 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
); );
} }
void _saveWidgetSP(String data, Map<String, String> old) { void _saveWidgetSP(Map<String, String> map, Map<String, String> old) {
context.pop(); context.pop();
try { try {
final map = Map<String, String>.from(json.decode(data));
final keysDel = old.keys.toSet().difference(map.keys.toSet()); final keysDel = old.keys.toSet().difference(map.keys.toSet());
for (final key in keysDel) { for (final key in keysDel) {
_sp.remove(key); _sp.remove(key);
@@ -70,7 +71,7 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
return ListTile( return ListTile(
title: Text(l10n.homeWidgetUrlConfig), title: Text(l10n.homeWidgetUrlConfig),
trailing: const Icon(Icons.keyboard_arrow_right), trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () { onTap: () async {
final data = <String, String>{}; final data = <String, String>{};
_sp.getKeys().forEach((key) { _sp.getKeys().forEach((key) {
final val = _sp.getString(key); final val = _sp.getString(key);
@@ -78,25 +79,57 @@ class _AndroidSettingsPageState extends State<AndroidSettingsPage> {
data[key] = val; data[key] = val;
} }
}); });
final ctrl = TextEditingController(text: json.encode(data)); final result = await AppRoutes.kvEditor(data: data).go(context);
if (result != null) {
if (result is Map<String, String>) {
_saveWidgetSP(result, data);
} else {
final err = 'Save Android widget SharedPreference failed: '
'unexpected type: ${result.runtimeType}';
Loggers.app.warning(err);
context.showRoundDialog( context.showRoundDialog(
title: l10n.homeWidgetUrlConfig, title: l10n.error,
child: Input( child: SingleChildScrollView(
autoFocus: true, child: SimpleMarkdown(data: '$err\n\n```$result```'),
controller: ctrl,
label: 'JSON',
type: TextInputType.visiblePassword,
maxLines: 7,
onSubmitted: (p0) => _saveWidgetSP(p0, data),
), ),
actions: [ );
TextButton( }
onPressed: () { }
_saveWidgetSP(ctrl.text, data);
}, },
child: Text(l10n.ok), );
}
Widget _buildWatch() {
return FutureWidget(
future: wc.isReachable,
error: (e, s) {
Loggers.app.warning('WatchOS error', e, s);
return ListTile(
title: const Text('Watch app'),
subtitle: Text(l10n.viewErr, style: UIs.textGrey),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () {
context.showRoundDialog(
title: l10n.error,
child: SingleChildScrollView(
child: SimpleMarkdown(data: '${e.toString()}\n```$s```'),
), ),
], );
},
);
},
success: (val) {
if (val == null) {
return ListTile(
title: const Text('Watch app'),
subtitle: Text(l10n.watchNotPaired, style: UIs.textGrey),
);
}
return ListTile(
title: const Text('Watch app'),
subtitle: Text(l10n.sync, style: UIs.textGrey),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () async {},
); );
}, },
); );

View File

@@ -410,7 +410,7 @@ packages:
description: description:
path: "." path: "."
ref: main ref: main
resolved-ref: a2aa5359253ad83000ff2612ed2c5729cb0dcfc5 resolved-ref: "4a3ac8cec9b39a08790101e45ff80a42c6dfd36a"
url: "https://github.com/lollipopkit/fl_lib" url: "https://github.com/lollipopkit/fl_lib"
source: git source: git
version: "0.0.1" version: "0.0.1"