From 6e51e5b2d2e0a205f7358f5eb76aca122428c31c Mon Sep 17 00:00:00 2001 From: Caten Date: Thu, 19 Oct 2023 23:45:33 +0800 Subject: [PATCH] fix tab key eaten --- lib/main.dart | 116 +--------------------------------------------- lib/workflow.dart | 9 ++-- 2 files changed, 5 insertions(+), 120 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 324ca3e..f334ab7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -27,7 +27,6 @@ import 'package:clipboard/clipboard.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter_pty/flutter_pty.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:saf/saf.dart'; //import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; @@ -1248,120 +1247,7 @@ class _MyHomePageState extends State { Permission.manageExternalStorage.request(); }), ]), - const Text("这里可以将设备上的文件夹与软件容器内的文件夹绑定,在下次启动软件时生效。"), - ListView.builder(itemBuilder: (context, index) { - final Map e = jsonDecode(Util.getGlobal("customMounts")[index]); - return GestureDetector(onLongPress: () { - String name = e["name"]!; - bool isNameValid = false; - Saf pathSaf = Saf(e["path"]!); - bool isPathValid = false; - showDialog(context: context, builder: (context) { - return AlertDialog(title: const Text("选项编辑"), content: SingleChildScrollView(child: Column(children: [ - TextFormField(initialValue: name, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "挂载到主文件夹的名称"), validator: (value) { - if (!RegExp("[^\\s\\\\/:\\*\\?\\\"<>\\|](\\x20|[^\\s\\\\/:\\*\\?\\\"<>\\|])*[^\\s\\\\/:\\*\\?\\\"<>\\|\\.]\$").hasMatch(value!)) { - return "非法文件名"; - } - isNameValid = true; - return null; - }), - SizedBox.fromSize(size: const Size.square(8)), - TextFormField(maxLines: null, initialValue: pathSaf.directory, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "在本机的路径"), readOnly: true, onTap: () async { - isPathValid = (await pathSaf.getDirectoryPermission(isDynamic: true))??false; - }), - ])), actions: [ - TextButton(onPressed:() async { - await G.prefs.setStringList("customMounts", Util.getGlobal("customMounts") - ..removeAt(index)); - setState(() {}); - if (!context.mounted) return; - Navigator.of(context).pop(); - }, child: const Text("删除该项")), - TextButton(onPressed:() { - Navigator.of(context).pop(); - }, child: const Text("取消")), - TextButton(onPressed:() async { - if (!isNameValid || !isPathValid) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("名称非法或路径无效")) - ); - return; - } - await G.prefs.setStringList("customMounts", Util.getGlobal("customMounts") - ..setAll(index, [{"name": name, "path": pathSaf.directory, "isEnabled": e["isEnabled"]}])); - setState(() {}); - if (!context.mounted) return; - Navigator.of(context).pop(); - }, child: const Text("保存")), - ]); - },); - - }, child: CheckboxListTile(title: Text(e["name"]), subtitle: Text(e["path"]), value: e["isEnabled"], onChanged: (value) async { - await G.prefs.setStringList("customMounts", Util.getGlobal("customMounts")..setAll(index, [jsonEncode(e..update("isEnabled", (v) { - return value!; - }))])); - setState(() {}); - })); - }, shrinkWrap: true, itemCount: Util.getGlobal("customMounts").length), - ListTile(title: const Text("添加路径"), onTap: () async { - Saf pathSaf = Saf("/storage/self/primary/Download"); - bool hasPermission = (await pathSaf.getDirectoryPermission(isDynamic: true))??false; - if (!hasPermission) { - return; - } - String name = "新路径"; - bool isNameValid = false; - bool isPathValid = false; - if (!context.mounted) return; - showDialog(context: context, builder: (context) { - return AlertDialog(title: const Text("选项编辑"), content: SingleChildScrollView(child: Column(children: [ - TextFormField(initialValue: name, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "挂载到主文件夹的名称"), validator: (value) { - if (!RegExp("[^\\s\\\\/:\\*\\?\\\"<>\\|](\\x20|[^\\s\\\\/:\\*\\?\\\"<>\\|])*[^\\s\\\\/:\\*\\?\\\"<>\\|\\.]\$").hasMatch(value!)) { - return "非法文件名"; - } - isNameValid = true; - return null; - }), - SizedBox.fromSize(size: const Size.square(8)), - TextFormField(maxLines: null, initialValue: pathSaf.directory, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "在本机的路径"), readOnly: true, onTap: () async { - isPathValid = (await pathSaf.getDirectoryPermission(isDynamic: true))??false; - }), - ])), actions: [ - TextButton(onPressed:() { - Navigator.of(context).pop(); - }, child: const Text("取消")), - TextButton(onPressed:() async { - if (!isNameValid || !isPathValid) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("名称非法或路径无效")) - ); - return; - } - await G.prefs.setStringList("customMounts", Util.getGlobal("customMounts") - ..add({"name": name, "path": pathSaf.directory, "isEnabled": true})); - setState(() {}); - if (!context.mounted) return; - Navigator.of(context).pop(); - }, child: const Text("保存")), - ]); - }); - }, onLongPress: () { - showDialog(context: context, builder: (context) { - return AlertDialog(content: const Text("是否清空所有路径?"), actions: [ - TextButton(onPressed:() { - Navigator.of(context).pop(); - }, child: const Text("取消")), - TextButton(onPressed:() async { - await G.prefs.setStringList("customMounts", []); - setState(() {}); - if (!context.mounted) return; - Navigator.of(context).pop(); - }, child: const Text("是")), - ]); - }); - }) + SizedBox.fromSize(size: const Size.square(16)), ],))), ExpansionPanel( isExpanded: _expandState[4], diff --git a/lib/workflow.dart b/lib/workflow.dart index 4250706..e2ebd68 100644 --- a/lib/workflow.dart +++ b/lib/workflow.dart @@ -91,8 +91,6 @@ class Util { // bind:[{name:"U盘", src:"/storage/xxxx", dst:"/media/meow"}]...]} //String[] adsBonus: 观看广告获取的奖励(json) //{name: "xxx", amount: xxx} - //String[] customMounts: 自定义挂载地址(json) - //{name: "xxx", path: "xxx", isEnabled: true} //TODO: 这么写还是不对劲,有空改成类试试? static dynamic getGlobal(String key) { bool b = G.prefs.containsKey(key); @@ -113,7 +111,6 @@ class Util { case "defaultFFmpegCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("-hide_banner -an -max_delay 1000000 -r 30 -f android_camera -i 0:0 -vf scale=iw/2:-1 -rtsp_transport udp -f rtsp rtsp://127.0.0.1:8554/stream"); case "containersInfo" : return G.prefs.getStringList(key)!; case "adsBonus" : return b ? G.prefs.getStringList(key)! : (value){G.prefs.setStringList(key, value); return value;}([].cast()); - case "customMounts" : return b ? G.prefs.getStringList(key)! : (value){G.prefs.setStringList(key, value); return value;}([].cast()); } } @@ -524,6 +521,7 @@ ln -s \$DATA_DIR/busybox \$DATA_DIR/bin/xz """ export DATA_DIR=${G.dataPath} export CONTAINER_DIR=\$DATA_DIR/containers/0 +export EXTRA_OPT="" cd \$DATA_DIR export PATH=\$DATA_DIR/bin:\$PATH export PROOT_TMP_DIR=\$DATA_DIR/proot_tmp @@ -551,7 +549,7 @@ done //$DATA_DIR是数据文件夹, $CONTAINER_DIR是容器根目录 await G.prefs.setStringList("containersInfo", ["""{ "name":"Debian Bookworm", -"boot":"\$DATA_DIR/bin/proot -H --change-id=1000:1000 --pwd=/home/tiny --rootfs=\$CONTAINER_DIR --mount=/system --mount=/apex --kill-on-exit --mount=/storage:/storage --sysvipc -L --link2symlink --mount=/proc:/proc --mount=/dev:/dev --mount=\$CONTAINER_DIR/tmp:/dev/shm --mount=/dev/urandom:/dev/random --mount=/proc/self/fd:/dev/fd --mount=/proc/self/fd/0:/dev/stdin --mount=/proc/self/fd/1:/dev/stdout --mount=/proc/self/fd/2:/dev/stderr --mount=/dev/null:/dev/tty0 --mount=/dev/null:/proc/sys/kernel/cap_last_cap --mount=/storage/self/primary:/media/sd --mount=\$DATA_DIR/share:/home/tiny/公共 --mount=/storage/self/primary/Fonts:/usr/share/fonts/wpsm --mount=/storage/self/primary/AppFiles/Fonts:/usr/share/fonts/yozom --mount=/system/fonts:/usr/share/fonts/androidm --mount=/storage/self/primary/Pictures:/home/tiny/图片 --mount=/storage/self/primary/Music:/home/tiny/音乐 --mount=/storage/self/primary/Movies:/home/tiny/视频 --mount=/storage/self/primary/Download:/home/tiny/下载 --mount=/storage/self/primary/DCIM:/home/tiny/照片 --mount=/storage/self/primary/Documents:/home/tiny/文档 --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/.tmoe-container.stat:/proc/stat --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/.tmoe-container.version:/proc/version --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/bus:/proc/bus --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/buddyinfo:/proc/buddyinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/cgroups:/proc/cgroups --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/consoles:/proc/consoles --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/crypto:/proc/crypto --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/devices:/proc/devices --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/diskstats:/proc/diskstats --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/execdomains:/proc/execdomains --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/fb:/proc/fb --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/filesystems:/proc/filesystems --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/interrupts:/proc/interrupts --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/iomem:/proc/iomem --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/ioports:/proc/ioports --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/kallsyms:/proc/kallsyms --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/keys:/proc/keys --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/key-users:/proc/key-users --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/kpageflags:/proc/kpageflags --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/loadavg:/proc/loadavg --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/locks:/proc/locks --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/misc:/proc/misc --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/modules:/proc/modules --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/pagetypeinfo:/proc/pagetypeinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/partitions:/proc/partitions --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/sched_debug:/proc/sched_debug --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/softirqs:/proc/softirqs --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/timer_list:/proc/timer_list --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/uptime:/proc/uptime --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/vmallocinfo:/proc/vmallocinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/vmstat:/proc/vmstat --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/zoneinfo:/proc/zoneinfo /usr/bin/env -i HOSTNAME=TINY HOME=/home/tiny USER=tiny TERM=xterm-256color SDL_IM_MODULE=fcitx XMODIFIERS=@im=fcitx QT_IM_MODULE=fcitx GTK_IM_MODULE=fcitx TMOE_CHROOT=false TMOE_PROOT=true TMPDIR=/tmp MOZ_FAKE_NO_SANDBOX=1 DISPLAY=:4 PULSE_SERVER=tcp:127.0.0.1:4718 LANG=zh_CN.UTF-8 SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/games:/usr/local/games /bin/bash -l", +"boot":"\$DATA_DIR/bin/proot -H --change-id=1000:1000 --pwd=/home/tiny --rootfs=\$CONTAINER_DIR --mount=/system --mount=/apex --kill-on-exit --mount=/storage:/storage --sysvipc -L --link2symlink --mount=/proc:/proc --mount=/dev:/dev --mount=\$CONTAINER_DIR/tmp:/dev/shm --mount=/dev/urandom:/dev/random --mount=/proc/self/fd:/dev/fd --mount=/proc/self/fd/0:/dev/stdin --mount=/proc/self/fd/1:/dev/stdout --mount=/proc/self/fd/2:/dev/stderr --mount=/dev/null:/dev/tty0 --mount=/dev/null:/proc/sys/kernel/cap_last_cap --mount=/storage/self/primary:/media/sd --mount=\$DATA_DIR/share:/home/tiny/公共 --mount=/storage/self/primary/Fonts:/usr/share/fonts/wpsm --mount=/storage/self/primary/AppFiles/Fonts:/usr/share/fonts/yozom --mount=/system/fonts:/usr/share/fonts/androidm --mount=/storage/self/primary/Pictures:/home/tiny/图片 --mount=/storage/self/primary/Music:/home/tiny/音乐 --mount=/storage/self/primary/Movies:/home/tiny/视频 --mount=/storage/self/primary/Download:/home/tiny/下载 --mount=/storage/self/primary/DCIM:/home/tiny/照片 --mount=/storage/self/primary/Documents:/home/tiny/文档 --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/.tmoe-container.stat:/proc/stat --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/.tmoe-container.version:/proc/version --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/bus:/proc/bus --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/buddyinfo:/proc/buddyinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/cgroups:/proc/cgroups --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/consoles:/proc/consoles --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/crypto:/proc/crypto --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/devices:/proc/devices --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/diskstats:/proc/diskstats --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/execdomains:/proc/execdomains --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/fb:/proc/fb --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/filesystems:/proc/filesystems --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/interrupts:/proc/interrupts --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/iomem:/proc/iomem --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/ioports:/proc/ioports --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/kallsyms:/proc/kallsyms --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/keys:/proc/keys --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/key-users:/proc/key-users --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/kpageflags:/proc/kpageflags --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/loadavg:/proc/loadavg --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/locks:/proc/locks --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/misc:/proc/misc --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/modules:/proc/modules --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/pagetypeinfo:/proc/pagetypeinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/partitions:/proc/partitions --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/sched_debug:/proc/sched_debug --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/softirqs:/proc/softirqs --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/timer_list:/proc/timer_list --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/uptime:/proc/uptime --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/vmallocinfo:/proc/vmallocinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/vmstat:/proc/vmstat --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/zoneinfo:/proc/zoneinfo /usr/bin/env -i HOSTNAME=TINY HOME=/home/tiny USER=tiny TERM=xterm-256color SDL_IM_MODULE=fcitx XMODIFIERS=@im=fcitx QT_IM_MODULE=fcitx GTK_IM_MODULE=fcitx TMOE_CHROOT=false TMOE_PROOT=true TMPDIR=/tmp MOZ_FAKE_NO_SANDBOX=1 DISPLAY=:4 PULSE_SERVER=tcp:127.0.0.1:4718 LANG=zh_CN.UTF-8 SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/games:/usr/local/games \$EXTRA_OPT /bin/bash -l", "vnc":"startnovnc &", "vncUrl":"http://localhost:36082/vnc.html?host=localhost&port=36082&autoconnect=true&resize=remote&password=12345678", "commands":${jsonEncode(D.commands)} @@ -698,7 +696,8 @@ clear"""); LogicalKeyboardKey.arrowLeft, LogicalKeyboardKey.arrowRight, LogicalKeyboardKey.arrowUp, - LogicalKeyboardKey.arrowDown + LogicalKeyboardKey.arrowDown, + LogicalKeyboardKey.tab }.contains(event.logicalKey)) { return KeyEventResult.skipRemainingHandlers; }