Compare commits

..

3 Commits

Author SHA1 Message Date
Caten
3e443ceedc Update code to v1.0.15 2024-03-12 22:06:10 +08:00
Caten
b50622787d Various fixes 2024-03-10 18:20:48 +08:00
Caten
231d1167e0 Change default settings 2024-03-05 22:20:37 +08:00
8 changed files with 110 additions and 126 deletions

View File

@@ -40,7 +40,7 @@ class AppPreferences(context: Context) {
} }
inner class Gesture { inner class Gesture {
val style; get() = prefs.getString("gesture_style", "touchscreen")!! val style; get() = prefs.getString("gesture_style", "touchpad")!!
val tap1 = "left-click" //Preference UI was removed val tap1 = "left-click" //Preference UI was removed
val tap2; get() = prefs.getString("gesture_tap2", "open-keyboard")!! val tap2; get() = prefs.getString("gesture_tap2", "open-keyboard")!!
val doubleTap; get() = prefs.getString("gesture_double_tap", "double-click")!! val doubleTap; get() = prefs.getString("gesture_double_tap", "double-click")!!

View File

@@ -15,7 +15,7 @@
app:title="@string/pref_gesture"> app:title="@string/pref_gesture">
<com.gaurav.avnc.ui.prefs.ListPreferenceEx <com.gaurav.avnc.ui.prefs.ListPreferenceEx
app:defaultValue="touchscreen" app:defaultValue="touchpad"
app:entries="@array/gesture_style_entries" app:entries="@array/gesture_style_entries"
app:entryValues="@array/gesture_style_values" app:entryValues="@array/gesture_style_values"
app:key="gesture_style" app:key="gesture_style"

Binary file not shown.

View File

@@ -34,8 +34,8 @@ cd $HOME/.local/share/tiny/tmp
MIRROR_SITE=https://mirror.ghproxy.com MIRROR_SITE=https://mirror.ghproxy.com
RELEASE_PAGE=https://github.com/Kron4ek/Wine-Builds/releases RELEASE_PAGE=https://github.com/Kron4ek/Wine-Builds/releases
LATEST_WINE_TAG=proton-$(curl -L $RELEASE_PAGE | grep -oP 'Proton \K[^"]*</h2>' | cut -d "<" -f 1 | head -n 1) #proton #LATEST_WINE_TAG=proton-$(curl -L $RELEASE_PAGE | grep -oP 'Proton \K[^"]*</h2>' | cut -d "<" -f 1 | head -n 1) #proton
#LATEST_WINE_TAG=$(curl -L $RELEASE_PAGE | grep -oP 'Wine \K[^"]*</h2>' | cut -d "<" -f 1 | head -n 1) #vanilla LATEST_WINE_TAG=$(curl -L $RELEASE_PAGE | grep -oP 'Wine \K[^"]*</h2>' | cut -d "<" -f 1 | head -n 1) #vanilla
if [ -z "$LATEST_WINE_TAG" ] || [ "$LATEST_WINE_TAG" == "proton-" ] if [ -z "$LATEST_WINE_TAG" ] || [ "$LATEST_WINE_TAG" == "proton-" ]
then then
LATEST_WINE_TAG=proton-8.0-4 LATEST_WINE_TAG=proton-8.0-4

View File

@@ -31,7 +31,7 @@ import 'package:flutter_pty/flutter_pty.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:network_info_plus/network_info_plus.dart'; import 'package:network_info_plus/network_info_plus.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
//import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wakelock_plus/wakelock_plus.dart';
@@ -149,26 +149,26 @@ class _SettingPageState extends State<SettingPage> {
]); ]);
}); });
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
TextFormField(maxLines: null, initialValue: Util.getCurrentProp("name"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "容器名称"), onChanged: (value) async { TextFormField(maxLines: null, initialValue: Util.getCurrentProp("name"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "容器名称"), onChanged: (value) async {
await Util.setCurrentProp("name", value); await Util.setCurrentProp("name", value);
//setState(() {}); //setState(() {});
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
ValueListenableBuilder(valueListenable: G.bootTextChange, builder:(context, v, child) { ValueListenableBuilder(valueListenable: G.bootTextChange, builder:(context, v, child) {
return TextFormField(maxLines: null, initialValue: Util.getCurrentProp("boot"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "启动命令"), onChanged: (value) async { return TextFormField(maxLines: null, initialValue: Util.getCurrentProp("boot"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "启动命令"), onChanged: (value) async {
await Util.setCurrentProp("boot", value); await Util.setCurrentProp("boot", value);
}); });
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
TextFormField(maxLines: null, initialValue: Util.getCurrentProp("vnc"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "vnc启动命令"), onChanged: (value) async { TextFormField(maxLines: null, initialValue: Util.getCurrentProp("vnc"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "vnc启动命令"), onChanged: (value) async {
await Util.setCurrentProp("vnc", value); await Util.setCurrentProp("vnc", value);
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
const Divider(height: 2, indent: 8, endIndent: 8), const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Text("你可以在当前所有同一网络下的设备连接同一WiFi的手机电脑等里使用小小电脑。\n\n点击下面的按钮分享链接到其他设备后使用浏览器打开即可。"), const Text("你可以在当前所有同一网络下的设备连接同一WiFi的手机电脑等里使用小小电脑。\n\n点击下面的按钮分享链接到其他设备后使用浏览器打开即可。"),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [ Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [
OutlinedButton(style: D.commandButtonStyle, child: const Text("复制分享链接"), onPressed: () async { OutlinedButton(style: D.commandButtonStyle, child: const Text("复制分享链接"), onPressed: () async {
final String? ip = await NetworkInfo().getWifiIP(); final String? ip = await NetworkInfo().getWifiIP();
@@ -180,7 +180,7 @@ class _SettingPageState extends State<SettingPage> {
); );
return; return;
} }
FlutterClipboard.copy((Util.getCurrentProp("vncUrl") as String).replaceFirst(RegExp.escape("localhost"), ip)).then((value) { FlutterClipboard.copy((Util.getCurrentProp("vncUrl") as String).replaceAll(RegExp.escape("localhost"), ip)).then((value) {
ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("已复制分享链接")) const SnackBar(content: Text("已复制分享链接"))
@@ -188,15 +188,15 @@ class _SettingPageState extends State<SettingPage> {
}); });
}), }),
]), ]),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
TextFormField(maxLines: null, initialValue: Util.getCurrentProp("vncUrl"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "网页跳转地址"), onChanged: (value) async { TextFormField(maxLines: null, initialValue: Util.getCurrentProp("vncUrl"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "网页跳转地址"), onChanged: (value) async {
await Util.setCurrentProp("vncUrl", value); await Util.setCurrentProp("vncUrl", value);
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
TextFormField(maxLines: null, initialValue: Util.getCurrentProp("vncUri"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "vnc链接"), onChanged: (value) async { TextFormField(maxLines: null, initialValue: Util.getCurrentProp("vncUri"), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "vnc链接"), onChanged: (value) async {
await Util.setCurrentProp("vncUri", value); await Util.setCurrentProp("vncUri", value);
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
],))), ],))),
ExpansionPanel( ExpansionPanel(
isExpanded: _expandState[1], isExpanded: _expandState[1],
@@ -218,7 +218,7 @@ class _SettingPageState extends State<SettingPage> {
await G.prefs.setInt("termMaxLines", int.parse(value!)); await G.prefs.setInt("termMaxLines", int.parse(value!));
}); });
},), },),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: (Util.getGlobal("defaultAudioPort") as int).toString(), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "pulseaudio接收端口"), TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: (Util.getGlobal("defaultAudioPort") as int).toString(), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "pulseaudio接收端口"),
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
validator: (value) { validator: (value) {
@@ -227,7 +227,7 @@ class _SettingPageState extends State<SettingPage> {
}); });
} }
), ),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
SwitchListTile(title: const Text("关闭横幅广告"), value: Util.getGlobal("isBannerAdsClosed") as bool, onChanged:(value) { SwitchListTile(title: const Text("关闭横幅广告"), value: Util.getGlobal("isBannerAdsClosed") as bool, onChanged:(value) {
if (value && Util.shouldWatchAds(D.adsRequired["closeBannerAds"]!)) { if (value && Util.shouldWatchAds(D.adsRequired["closeBannerAds"]!)) {
ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldMessenger.of(context).hideCurrentSnackBar();
@@ -241,7 +241,7 @@ class _SettingPageState extends State<SettingPage> {
G.bannerAdsChange.value = !G.bannerAdsChange.value; G.bannerAdsChange.value = !G.bannerAdsChange.value;
}); });
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("启用终端"), value: Util.getGlobal("isTerminalWriteEnabled") as bool, onChanged:(value) { SwitchListTile(title: const Text("启用终端"), value: Util.getGlobal("isTerminalWriteEnabled") as bool, onChanged:(value) {
if (value && Util.shouldWatchAds(D.adsRequired["enableTerminalWrite"]!)) { if (value && Util.shouldWatchAds(D.adsRequired["enableTerminalWrite"]!)) {
ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldMessenger.of(context).hideCurrentSnackBar();
@@ -256,7 +256,7 @@ class _SettingPageState extends State<SettingPage> {
G.prefs.setBool("isTerminalWriteEnabled", value); G.prefs.setBool("isTerminalWriteEnabled", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("启用终端小键盘"), value: Util.getGlobal("isTerminalCommandsEnabled") as bool, onChanged:(value) { SwitchListTile(title: const Text("启用终端小键盘"), value: Util.getGlobal("isTerminalCommandsEnabled") as bool, onChanged:(value) {
if (value && Util.shouldWatchAds(D.adsRequired["enableTerminalCommands"]!)) { if (value && Util.shouldWatchAds(D.adsRequired["enableTerminalCommands"]!)) {
ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldMessenger.of(context).hideCurrentSnackBar();
@@ -270,37 +270,37 @@ class _SettingPageState extends State<SettingPage> {
G.terminalPageChange.value = !G.terminalPageChange.value; G.terminalPageChange.value = !G.terminalPageChange.value;
}); });
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("终端粘滞键"), value: Util.getGlobal("isStickyKey") as bool, onChanged:(value) { SwitchListTile(title: const Text("终端粘滞键"), value: Util.getGlobal("isStickyKey") as bool, onChanged:(value) {
G.prefs.setBool("isStickyKey", value); G.prefs.setBool("isStickyKey", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("屏幕常亮"), value: Util.getGlobal("wakelock") as bool, onChanged:(value) { SwitchListTile(title: const Text("屏幕常亮"), value: Util.getGlobal("wakelock") as bool, onChanged:(value) {
G.prefs.setBool("wakelock", value); G.prefs.setBool("wakelock", value);
WakelockPlus.toggle(enable: value); WakelockPlus.toggle(enable: value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
const Divider(height: 2, indent: 8, endIndent: 8), const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Text("以下选项修改后将在下次启动软件时生效。"), const Text("以下选项修改后将在下次启动软件时生效。"),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("开启时启动图形界面"), value: Util.getGlobal("autoLaunchVnc") as bool, onChanged:(value) { SwitchListTile(title: const Text("开启时启动图形界面"), value: Util.getGlobal("autoLaunchVnc") as bool, onChanged:(value) {
G.prefs.setBool("autoLaunchVnc", value); G.prefs.setBool("autoLaunchVnc", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("重新安装引导包"), value: Util.getGlobal("reinstallBootstrap") as bool, onChanged:(value) { SwitchListTile(title: const Text("重新安装引导包"), value: Util.getGlobal("reinstallBootstrap") as bool, onChanged:(value) {
G.prefs.setBool("reinstallBootstrap", value); G.prefs.setBool("reinstallBootstrap", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("getifaddrs桥接"), subtitle: const Text("修复安卓13设备getifaddrs无权限"), value: Util.getGlobal("getifaddrsBridge") as bool, onChanged:(value) { SwitchListTile(title: const Text("getifaddrs桥接"), subtitle: const Text("修复安卓13设备getifaddrs无权限"), value: Util.getGlobal("getifaddrsBridge") as bool, onChanged:(value) {
G.prefs.setBool("getifaddrsBridge", value); G.prefs.setBool("getifaddrsBridge", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("伪装系统为UOS"), subtitle: const Text("修复UOS微信无法启动"), value: Util.getGlobal("uos") as bool, onChanged:(value) { SwitchListTile(title: const Text("伪装系统为UOS"), subtitle: const Text("修复UOS微信无法启动"), value: Util.getGlobal("uos") as bool, onChanged:(value) {
G.prefs.setBool("uos", value); G.prefs.setBool("uos", value);
setState(() {}); setState(() {});
@@ -311,16 +311,27 @@ class _SettingPageState extends State<SettingPage> {
headerBuilder: ((context, isExpanded) { headerBuilder: ((context, isExpanded) {
return const ListTile(title: Text("显示设置")); return const ListTile(title: Text("显示设置"));
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [ }), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Text("""AVNC可以带来获得更好的操控体验 const Text("""AVNC可以带来获得更好的操控体验
如触摸板触控,双击弹出键盘,自动剪切板,画中画模式等等。这是一个实验性功能。"""), 如触摸板触控,双指单击弹出键盘,自动剪切板,画中画模式等等。这是一个实验性功能。"""),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [ Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [
OutlinedButton(style: D.commandButtonStyle, child: const Text("AVNC设置"), onPressed: () async {
await D.avncChannel.invokeMethod("launchPrefsPage", {});
}),
OutlinedButton(style: D.commandButtonStyle, child: const Text("关于AVNC"), onPressed: () async {
await D.avncChannel.invokeMethod("launchAboutPage", {});
}),
OutlinedButton(style: D.commandButtonStyle, child: const Text("AVNC启动时分辨率设置"), onPressed: () async { OutlinedButton(style: D.commandButtonStyle, child: const Text("AVNC启动时分辨率设置"), onPressed: () async {
String w = "1440"; final s = WidgetsBinding.instance.platformDispatcher.views.first.physicalSize;
String h = "720"; final w0 = max(s.width, s.height);
final h0 = min(s.width, s.height);
String w = (w0 * 0.6).round().toString();
String h = (h0 * 0.6).round().toString();
showDialog(context: context, builder: (context) { showDialog(context: context, builder: (context) {
return AlertDialog(title: const Text("分辨率设置"), content: SingleChildScrollView(child: Column(children: [ return AlertDialog(title: const Text("分辨率设置"), content: SingleChildScrollView(child: Column(children: [
Text("你的设备屏幕分辨率是${w0.round()}x${h0.round()}"),
const SizedBox.square(dimension: 8),
TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: w, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: ""), keyboardType: TextInputType.number, TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: w, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: ""), keyboardType: TextInputType.number,
validator: (value) { validator: (value) {
return Util.validateBetween(value, 200, 7680, () { return Util.validateBetween(value, 200, 7680, () {
@@ -328,7 +339,7 @@ class _SettingPageState extends State<SettingPage> {
}); });
} }
), ),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: h, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: ""), keyboardType: TextInputType.number, TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: h, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: ""), keyboardType: TextInputType.number,
validator: (value) { validator: (value) {
return Util.validateBetween(value, 200, 7680, () { return Util.validateBetween(value, 200, 7680, () {
@@ -353,29 +364,22 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
]); ]);
}); });
}), }),
OutlinedButton(style: D.commandButtonStyle, child: const Text("AVNC设置"), onPressed: () async {
await D.avncChannel.invokeMethod("launchPrefsPage", {});
}),
OutlinedButton(style: D.commandButtonStyle, child: const Text("关于AVNC"), onPressed: () async {
await D.avncChannel.invokeMethod("launchAboutPage", {});
}),
]), ]),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("默认使用AVNC"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("useAvnc") as bool, onChanged:(value) { SwitchListTile(title: const Text("默认使用AVNC"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("useAvnc") as bool, onChanged:(value) {
G.prefs.setBool("useAvnc", value); G.prefs.setBool("useAvnc", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8), const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Text("""高分辨率支持可以为大屏幕设备带来更高清的体验! const Text("""高分辨率支持可以为大屏幕设备带来更高清的体验!
注意: 注意:
选项开启后显示会变得很大,请在图形界面的左栏设置里手动调整缩放到一个你认为合适的值 选项开启后显示会变得很大,请设置一个合适的分辨率
如果使用AVNC可以在上面设置一个更大的分辨率。
一些软件可能会存在显示问题,或者显示速度变慢。"""), 一些软件可能会存在显示问题,或者显示速度变慢。"""),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultHidpiOpt") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "HiDPI环境变量"), readOnly: Util.shouldWatchAds(D.adsRequired["changeHidpiOpt"]!), TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultHidpiOpt") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "HiDPI环境变量"), readOnly: Util.shouldWatchAds(D.adsRequired["changeHidpiOpt"]!),
onTap: () { onTap: () {
if (Util.shouldWatchAds(D.adsRequired["changeHidpiOpt"]!)) { if (Util.shouldWatchAds(D.adsRequired["changeHidpiOpt"]!)) {
@@ -389,12 +393,12 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
await G.prefs.setString("defaultHidpiOpt", value); await G.prefs.setString("defaultHidpiOpt", value);
}, },
), ),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("高分辨率支持"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("isHidpiEnabled") as bool, onChanged:(value) { SwitchListTile(title: const Text("高分辨率支持"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("isHidpiEnabled") as bool, onChanged:(value) {
G.prefs.setBool("isHidpiEnabled", value); G.prefs.setBool("isHidpiEnabled", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
],))), ],))),
ExpansionPanel( ExpansionPanel(
isExpanded: _expandState[3], isExpanded: _expandState[3],
@@ -469,7 +473,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.isStreamServerStarted = value; G.isStreamServerStarted = value;
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("启动推流"), value: G.isStreaming, onChanged:(value) { SwitchListTile(title: const Text("启动推流"), value: G.isStreaming, onChanged:(value) {
switch (value) { switch (value) {
case true: { case true: {
@@ -490,7 +494,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.isStreaming = value; G.isStreaming = value;
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(8)) const SizedBox.square(dimension: 8)
],))), ],))),
ExpansionPanel( ExpansionPanel(
isExpanded: _expandState[4], isExpanded: _expandState[4],
@@ -498,7 +502,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
return const ListTile(title: Text("文件访问")); return const ListTile(title: Text("文件访问"));
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [ }), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
const Text("通过这里获取更多文件权限,以实现对特殊目录的访问。"), const Text("通过这里获取更多文件权限,以实现对特殊目录的访问。"),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [ Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [
OutlinedButton(style: D.commandButtonStyle, child: const Text("申请存储权限"), onPressed: () { OutlinedButton(style: D.commandButtonStyle, child: const Text("申请存储权限"), onPressed: () {
Permission.storage.request(); Permission.storage.request();
@@ -507,7 +511,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
Permission.manageExternalStorage.request(); Permission.manageExternalStorage.request();
}), }),
]), ]),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
],))), ],))),
ExpansionPanel( ExpansionPanel(
isExpanded: _expandState[5], isExpanded: _expandState[5],
@@ -520,13 +524,13 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
不过运行情况依然无法保证。 不过运行情况依然无法保证。
"""), """),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultVirglCommand") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "virgl服务器参数"), TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultVirglCommand") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "virgl服务器参数"),
onChanged: (value) async { onChanged: (value) async {
await G.prefs.setString("defaultVirglCommand", value); await G.prefs.setString("defaultVirglCommand", value);
}, },
), ),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("测试"), subtitle: const Text("启动virgl_test_server"), value: G.isVirglServerStarted, onChanged:(value) { SwitchListTile(title: const Text("测试"), subtitle: const Text("启动virgl_test_server"), value: G.isVirglServerStarted, onChanged:(value) {
switch (value) { switch (value) {
case true: { case true: {
@@ -546,13 +550,13 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.isVirglServerStarted = value; G.isVirglServerStarted = value;
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultVirglOpt") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "图形环境变量"), TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultVirglOpt") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "图形环境变量"),
onChanged: (value) async { onChanged: (value) async {
await G.prefs.setString("defaultVirglOpt", value); await G.prefs.setString("defaultVirglOpt", value);
}, },
), ),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("启用virgl加速"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("virgl") as bool, onChanged:(value) { SwitchListTile(title: const Text("启用virgl加速"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("virgl") as bool, onChanged:(value) {
if (value && Util.shouldWatchAds(D.adsRequired["enableVirgl"]!)) { if (value && Util.shouldWatchAds(D.adsRequired["enableVirgl"]!)) {
ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldMessenger.of(context).hideCurrentSnackBar();
@@ -564,7 +568,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.prefs.setBool("virgl", value); G.prefs.setBool("virgl", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
],))), ],))),
ExpansionPanel( ExpansionPanel(
isExpanded: _expandState[6], isExpanded: _expandState[6],
@@ -585,7 +589,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
跨架构/跨系统提供类似binfmt_misc的支持。 跨架构/跨系统提供类似binfmt_misc的支持。
你可以直接执行x86或x64的elf系统会自动调用box86/box64也可以直接执行exe文件系统会自动调用wine64 你可以直接执行x86或x64的elf系统会自动调用box86/box64也可以直接执行exe文件系统会自动调用wine64
前提是这些文件拥有可执行权限。"""), 前提是这些文件拥有可执行权限。"""),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [ Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [
OutlinedButton(style: D.commandButtonStyle, child: const Text("安装box86和box64"), onPressed: () { OutlinedButton(style: D.commandButtonStyle, child: const Text("安装box86和box64"), onPressed: () {
Util.termWrite("bash ~/.local/share/tiny/extra/install-box"); Util.termWrite("bash ~/.local/share/tiny/extra/install-box");
@@ -632,9 +636,9 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.pageIndex.value = 0; G.pageIndex.value = 0;
}), }),
]), ]),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8), const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Text("""开启wine后的常用指令点击后前往图形界面耐心等待。 const Text("""开启wine后的常用指令点击后前往图形界面耐心等待。
任意程序启动参考时间: 任意程序启动参考时间:
@@ -645,7 +649,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
初始化时间: 初始化时间:
可能比本软件初始化还长 可能比本软件初始化还长
"""), """),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: D.wineCommands.asMap().entries.map<Widget>( Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: D.wineCommands.asMap().entries.map<Widget>(
(e) { (e) {
return OutlinedButton(style: D.commandButtonStyle, child: Text(e.value["name"]!), onPressed: () { return OutlinedButton(style: D.commandButtonStyle, child: Text(e.value["name"]!), onPressed: () {
@@ -654,11 +658,11 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
}); });
} }
).toList()), ).toList()),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8), const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
const Text("以下选项修改后将在下次启动软件时生效。"), const Text("以下选项修改后将在下次启动软件时生效。"),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("启用box86/box64"), subtitle: const Text("运行跨架构软件"), value: Util.getGlobal("isBoxEnabled") as bool, onChanged:(value) async { SwitchListTile(title: const Text("启用box86/box64"), subtitle: const Text("运行跨架构软件"), value: Util.getGlobal("isBoxEnabled") as bool, onChanged:(value) async {
//检测box64是否存在存在才开启 //检测box64是否存在存在才开启
if (value && !await File("${G.dataPath}/tiny/cross/box64").exists()) { if (value && !await File("${G.dataPath}/tiny/cross/box64").exists()) {
@@ -698,7 +702,7 @@ fi""");
G.prefs.setBool("isWineEnabled", value); G.prefs.setBool("isWineEnabled", value);
setState(() {}); setState(() {});
},), },),
SizedBox.fromSize(size: const Size.square(16)), const SizedBox.square(dimension: 16),
],))), ],))),
ExpansionPanel( ExpansionPanel(
isExpanded: _expandState[7], isExpanded: _expandState[7],
@@ -771,7 +775,8 @@ class _InfoPageState extends State<InfoPage> {
正常情况下,加载完成后软件会自动跳转到图形界面 正常情况下,加载完成后软件会自动跳转到图形界面
在图形界面时,点击即鼠标左键 在图形界面时,点击即鼠标左键
双指点击为鼠标右键 长按为鼠标右键
双指点击弹出键盘
双指划动为鼠标滚轮 双指划动为鼠标滚轮
在图形界面返回,可以回到终端界面和控制界面 在图形界面返回,可以回到终端界面和控制界面
@@ -810,19 +815,15 @@ bilibili客户端等等不可用
如果你给了存储权限 如果你给了存储权限
那么通过主目录下的文件夹 那么通过主目录下的文件夹
就可以访问手机存储 就可以访问设备存储
要访问整个设备存储可以访问sd文件夹
此外主文件夹的很多文件夹与设备文件夹绑定
比如主文件夹的下载文件夹就是设备的下载文件夹
有一些设备做了更多访问限制 如果没有给存储权限
比如下载文件夹可能不可写入 文件保存到下载文件夹可能出现问题
这样会导致把文件保存到下载目录时出现问题
(火狐浏览器可能因此无法下载文件) (火狐浏览器可能因此无法下载文件)
不过这个很好解决 你也可以选择换一个文件夹保存
换个文件夹保存就行了
如果认为界面大小比例不合适
可以通过调整图形界面左栏设置-高级里的屏幕缩放比例
如果感觉界面卡卡的
可以适当调低图像质量或压缩等级
如果你想安装其他软件 如果你想安装其他软件
可以使用容器自带的tmoe 可以使用容器自带的tmoe
@@ -841,7 +842,7 @@ VSCode、输入法
如果你需要更多字体 如果你需要更多字体
在给了存储权限的情况下 在给了存储权限的情况下
直接将字体复制到手机存储的Fonts文件夹即可 直接将字体复制到设备存储的Fonts文件夹即可
一些常用的办公字体 一些常用的办公字体
可以在Windows电脑的C:\\Windows\\Fonts文件夹找到 可以在Windows电脑的C:\\Windows\\Fonts文件夹找到
由于可能的版权问题 由于可能的版权问题
@@ -852,23 +853,14 @@ VSCode、输入法
而是使用英文键盘通过容器的输入法(Ctrl+空格切换)输入中文 而是使用英文键盘通过容器的输入法(Ctrl+空格切换)输入中文
避免丢字错字 避免丢字错字
在之前的版本中有网友反馈过这些问题 如果你遇到了问题
还请注意: 可以去https://github.com/Cateners/tiny_computer/issues/
三星Galaxy S21 Ultra, 安卓13, 黑屏 留言反馈
红米Note 12, 安卓13miui14, 黑屏
红米Note 11T Pro+ miui13.0.4,“无法连接”
Vivo Pad安卓13看不见鼠标移动可以去左栏设置开启显示原系统光标替代
关于这些
我目前没有什么好的解决办法
(毕竟我没有这些设备
也不方便定位原因)
如果你遇到了类似问题
不管解没解决
都可以去https://github.com/Cateners/tiny_computer/issues/留个言
如果软件里有程序正在正常运行 如果软件里有程序正在正常运行
请不要强行关闭本软件 请不要强行关闭本软件
否则可能会损坏容器 否则可能会损坏容器
(如dpkg被中断)
特别是在安装某些比较大的软件的时候 特别是在安装某些比较大的软件的时候
感谢使用! 感谢使用!
@@ -1461,14 +1453,14 @@ class TerminalPage extends StatelessWidget {
children: const [Text('Ctrl'), Text('Alt'), Text('Shift')], children: const [Text('Ctrl'), Text('Alt'), Text('Shift')],
), ),
), ),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
Expanded(child: SizedBox(height: 24, child: ListView.separated(scrollDirection: Axis.horizontal, itemBuilder:(context, index) { Expanded(child: SizedBox(height: 24, child: ListView.separated(scrollDirection: Axis.horizontal, itemBuilder:(context, index) {
return OutlinedButton(style: D.controlButtonStyle, onPressed: () { return OutlinedButton(style: D.controlButtonStyle, onPressed: () {
G.termPtys[G.currentContainer]!.terminal.keyInput(D.termCommands[index]["key"]! as TerminalKey); G.termPtys[G.currentContainer]!.terminal.keyInput(D.termCommands[index]["key"]! as TerminalKey);
}, child: Text(D.termCommands[index]["name"]! as String)); }, child: Text(D.termCommands[index]["name"]! as String));
}, separatorBuilder:(context, index) { }, separatorBuilder:(context, index) {
return SizedBox.fromSize(size: const Size.square(4)); return const SizedBox.square(dimension: 4);
}, itemCount: D.termCommands.length))), SizedBox.fromSize(size: const Size(72, 0))])):SizedBox.fromSize(size: const Size.square(0)); }, itemCount: D.termCommands.length))), SizedBox.fromSize(size: const Size(72, 0))])):const SizedBox.square(dimension: 0);
}) })
]); ]);
} }
@@ -1498,7 +1490,7 @@ class _FastCommandsState extends State<FastCommands> {
TextFormField(initialValue: name, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令名称"), onChanged: (value) { TextFormField(initialValue: name, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令名称"), onChanged: (value) {
name = value; name = value;
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
TextFormField(maxLines: null, initialValue: command, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令内容"), onChanged: (value) { TextFormField(maxLines: null, initialValue: command, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令内容"), onChanged: (value) {
command = value; command = value;
}), }),
@@ -1531,7 +1523,7 @@ class _FastCommandsState extends State<FastCommands> {
TextFormField(initialValue: name, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令名称"), onChanged: (value) { TextFormField(initialValue: name, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令名称"), onChanged: (value) {
name = value; name = value;
}), }),
SizedBox.fromSize(size: const Size.square(8)), const SizedBox.square(dimension: 8),
TextFormField(maxLines: null, initialValue: command, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令内容"), onChanged: (value) { TextFormField(maxLines: null, initialValue: command, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令内容"), onChanged: (value) {
command = value; command = value;
}), }),
@@ -1597,13 +1589,15 @@ class _MyHomePageState extends State<MyHomePage> {
} }
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky,overlays: []);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(isLoadingComplete?Util.getCurrentProp("name"):widget.title), title: Text(isLoadingComplete?Util.getCurrentProp("name"):widget.title),
), ),
body: isLoadingComplete?Column(mainAxisSize: MainAxisSize.min, children: [ body: isLoadingComplete?Column(mainAxisSize: MainAxisSize.min, children: [
ValueListenableBuilder(valueListenable: G.bannerAdsChange, builder:(context, value, child) { ValueListenableBuilder(valueListenable: G.bannerAdsChange, builder:(context, value, child) {
return (Util.getGlobal("isBannerAdsClosed") as bool)||bannerAdsFailedToLoad?SizedBox.fromSize(size: const Size.square(0)):UnityBannerAd( return (Util.getGlobal("isBannerAdsClosed") as bool)||bannerAdsFailedToLoad?const SizedBox.square(dimension: 0):UnityBannerAd(
placementId: AdManager.bannerAdPlacementId, placementId: AdManager.bannerAdPlacementId,
onLoad: (placementId) => debugPrint('Banner loaded: $placementId'), onLoad: (placementId) => debugPrint('Banner loaded: $placementId'),
onClick: (placementId) => debugPrint('Banner clicked: $placementId'), onClick: (placementId) => debugPrint('Banner clicked: $placementId'),
@@ -1615,11 +1609,11 @@ class _MyHomePageState extends State<MyHomePage> {
}, },
); );
}), Expanded(child: ValueListenableBuilder(valueListenable: G.pageIndex, builder: (context, value, child) { }), Expanded(child: ValueListenableBuilder(valueListenable: G.pageIndex, builder: (context, value, child) {
return IndexedStack(index: G.pageIndex.value, children: [const TerminalPage(), Padding( return IndexedStack(index: G.pageIndex.value, children: const [TerminalPage(), Padding(
padding: const EdgeInsets.all(8), padding: EdgeInsets.all(8),
child: Scrollbar(child: SingleChildScrollView(restorationId: "control-scroll", child: Column( child: Scrollbar(child: SingleChildScrollView(restorationId: "control-scroll", child: Column(
children: [ children: [
const Padding( Padding(
padding: EdgeInsets.all(16), padding: EdgeInsets.all(16),
child: FractionallySizedBox( child: FractionallySizedBox(
widthFactor: 0.4, widthFactor: 0.4,
@@ -1628,16 +1622,12 @@ class _MyHomePageState extends State<MyHomePage> {
) )
), ),
), ),
/*Padding( FastCommands(),
padding: const EdgeInsets.fromLTRB(0, 0, 0, 8), Padding(padding: EdgeInsets.all(8), child: Card(child: Padding(padding: EdgeInsets.all(8), child:
child: Text(Util.getCurrentProp("name"), textScaleFactor: 2),
),*/
const FastCommands(),
Padding(padding: const EdgeInsets.all(8), child: Card(child: Padding(padding: const EdgeInsets.all(8), child:
Column(children: [ Column(children: [
const SettingPage(), SettingPage(),
SizedBox.fromSize(size: const Size.square(8)), SizedBox.square(dimension: 8),
const InfoPage(openFirstInfo: false) InfoPage(openFirstInfo: false)
]) ])
))) )))
] ]

View File

@@ -130,10 +130,10 @@ class Util {
case "virgl" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "virgl" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
case "wakelock" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "wakelock" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
case "isHidpiEnabled" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "isHidpiEnabled" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
case "useAvnc" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "useAvnc" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(true);
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 -camera_index 0 -i 0:0 -vf scale=iw/2:-1 -rtsp_transport udp -f rtsp rtsp://127.0.0.1:8554/stream"); 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 -camera_index 0 -i 0:0 -vf scale=iw/2:-1 -rtsp_transport udp -f rtsp rtsp://127.0.0.1:8554/stream");
case "defaultVirglCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("--socket-path=\$CONTAINER_DIR/tmp/.virgl_test"); case "defaultVirglCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("--socket-path=\$CONTAINER_DIR/tmp/.virgl_test");
case "defaultVirglOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GALLIUM_DRIVER=virpipe MESA_GL_VERSION_OVERRIDE=4.0"); case "defaultVirglOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GALLIUM_DRIVER=virpipe");
case "defaultHidpiOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GDK_SCALE=2 QT_FONT_DPI=192"); case "defaultHidpiOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GDK_SCALE=2 QT_FONT_DPI=192");
case "containersInfo" : return G.prefs.getStringList(key)!; case "containersInfo" : return G.prefs.getStringList(key)!;
case "adsBonus" : return b ? G.prefs.getStringList(key)! : (value){G.prefs.setStringList(key, value); return value;}([].cast<String>()); case "adsBonus" : return b ? G.prefs.getStringList(key)! : (value){G.prefs.setStringList(key, value); return value;}([].cast<String>());
@@ -390,7 +390,6 @@ class D {
static const commands = [{"name":"检查更新并升级", "command":"sudo apt update && sudo apt upgrade -y"}, static const commands = [{"name":"检查更新并升级", "command":"sudo apt update && sudo apt upgrade -y"},
{"name":"查看系统信息", "command":"neofetch -L && neofetch --off"}, {"name":"查看系统信息", "command":"neofetch -L && neofetch --off"},
{"name":"清屏", "command":"clear"}, {"name":"清屏", "command":"clear"},
{"name":"查看IP", "command":"hostname -I # 如果显示无权限(Permission denied)请在全局设置里开启getifaddrs桥接"},
{"name":"中断任务", "command":"\x03"}, {"name":"中断任务", "command":"\x03"},
{"name":"安装图形处理软件Krita", "command":"sudo apt update && sudo apt install -y krita krita-l10n"}, {"name":"安装图形处理软件Krita", "command":"sudo apt update && sudo apt install -y krita krita-l10n"},
{"name":"卸载Krita", "command":"sudo apt autoremove --purge -y krita krita-l10n"}, {"name":"卸载Krita", "command":"sudo apt autoremove --purge -y krita krita-l10n"},
@@ -408,14 +407,14 @@ rm /tmp/wps.deb"""},
{"name":"卸载CAJViewer", "command":"sudo apt autoremove --purge -y net.cnki.cajviewer && bash /home/tiny/.local/share/tiny/caj/postrm"}, {"name":"卸载CAJViewer", "command":"sudo apt autoremove --purge -y net.cnki.cajviewer && bash /home/tiny/.local/share/tiny/caj/postrm"},
{"name":"安装亿图图示", "command":"wget https://www.edrawsoft.cn/2download/aarch64/edrawmax_12.6.1-1_arm64_binner.deb -O /tmp/edraw.deb && sudo apt update && sudo apt install -y /tmp/edraw.deb && bash /home/tiny/.local/share/tiny/edraw/postinst; rm /tmp/edraw.deb"}, {"name":"安装亿图图示", "command":"wget https://www.edrawsoft.cn/2download/aarch64/edrawmax_12.6.1-1_arm64_binner.deb -O /tmp/edraw.deb && sudo apt update && sudo apt install -y /tmp/edraw.deb && bash /home/tiny/.local/share/tiny/edraw/postinst; rm /tmp/edraw.deb"},
{"name":"卸载亿图图示", "command":"sudo apt autoremove --purge -y edrawmax libldap-2.4-2"}, {"name":"卸载亿图图示", "command":"sudo apt autoremove --purge -y edrawmax libldap-2.4-2"},
{"name":"安装QQ", "command":"""wget \$(curl -L https://cdn-go.cn/qq-web/im.qq.com_new/latest/rainbow/linuxQQDownload.js | grep -oP 'deb":"\\K[^"]*arm64\\.deb' | head -n 1) -O /tmp/qq.deb && sudo apt update && sudo apt install -y /tmp/qq.deb && sed -i 's#Exec=/opt/QQ/qq %U#Exec=/opt/QQ/qq --no-sandbox %U#g' /usr/share/applications/qq.desktop; rm /tmp/qq.deb"""}, {"name":"安装QQ", "command":"""wget \$(curl -L https://cdn-go.cn/qq-web/im.qq.com_new/latest/rainbow/linuxQQDownload.js | grep -oP '(?<=armDownloadUrl":\\{"deb":")[^"]+') -O /tmp/qq.deb && sudo apt update && sudo apt install -y /tmp/qq.deb && sed -i 's#Exec=/opt/QQ/qq %U#Exec=/opt/QQ/qq --no-sandbox %U#g' /usr/share/applications/qq.desktop; rm /tmp/qq.deb"""},
{"name":"卸载QQ", "command":"sudo apt autoremove --purge -y linuxqq"}, {"name":"卸载QQ", "command":"sudo apt autoremove --purge -y linuxqq"},
{"name":"安装UOS微信", "command":"wget https://home-store-packages.uniontech.com/appstore/pool/appstore/c/com.tencent.weixin/com.tencent.weixin_2.1.10_arm64.deb -O /tmp/wechat.deb && sudo apt update && sudo apt install -y /tmp/wechat.deb /home/tiny/.local/share/tiny/wechat/deepin-elf-verify_all.deb /home/tiny/.local/share/tiny/wechat/libssl1.1_1.1.1n-0+deb10u6_arm64.deb && sed -i 's#/opt/apps/com.tencent.weixin/files/weixin/weixin#/opt/apps/com.tencent.weixin/files/weixin/weixin --no-sandbox#g' /opt/apps/com.tencent.weixin/files/weixin/weixin.sh && echo '该微信为UOS特供版只有账号实名且在UOS系统上运行时可用。在使用前请前往全局设置开启UOS伪装。\n如果你使用微信只是为了传输文件那么可以考虑使用支持SAF的文件管理器质感文件直接访问小小电脑所有文件。'; rm /tmp/wechat.deb"}, {"name":"安装UOS微信", "command":"wget https://home-store-packages.uniontech.com/appstore/pool/appstore/c/com.tencent.weixin/com.tencent.weixin_2.1.10_arm64.deb -O /tmp/wechat.deb && sudo apt update && sudo apt install -y /tmp/wechat.deb /home/tiny/.local/share/tiny/wechat/deepin-elf-verify_all.deb /home/tiny/.local/share/tiny/wechat/libssl1.1_1.1.1n-0+deb10u6_arm64.deb && sed -i 's#/opt/apps/com.tencent.weixin/files/weixin/weixin#/opt/apps/com.tencent.weixin/files/weixin/weixin --no-sandbox#g' /opt/apps/com.tencent.weixin/files/weixin/weixin.sh && echo '该微信为UOS特供版只有账号实名且在UOS系统上运行时可用。在使用前请前往全局设置开启UOS伪装。\n如果你使用微信只是为了传输文件那么可以考虑使用支持SAF的文件管理器质感文件直接访问小小电脑所有文件。'; rm /tmp/wechat.deb"},
{"name":"卸载UOS微信", "command":"sudo apt autoremove --purge -y com.tencent.weixin deepin-elf-verify"}, {"name":"卸载UOS微信", "command":"sudo apt autoremove --purge -y com.tencent.weixin deepin-elf-verify"},
{"name":"安装钉钉", "command":"""wget \$(curl -L https://g.alicdn.com/dingding/h5-home-download/0.2.4/js/index.js | grep -oP 'url:"\\K[^"]*arm64\\.deb' | head -n 1) -O /tmp/dingtalk.deb && sudo apt update && sudo apt install -y /tmp/dingtalk.deb && sed -i 's#\\./com.alibabainc.dingtalk#\\./com.alibabainc.dingtalk --no-sandbox#g' /opt/apps/com.alibabainc.dingtalk/files/Elevator.sh; rm /tmp/dingtalk.deb"""}, {"name":"安装钉钉", "command":"""wget \$(curl -L https://g.alicdn.com/dingding/h5-home-download/0.2.4/js/index.js | grep -oP 'url:"\\K[^"]*arm64\\.deb' | head -n 1) -O /tmp/dingtalk.deb && sudo apt update && sudo apt install -y /tmp/dingtalk.deb libglut3.12 libglu1-mesa && sed -i 's#\\./com.alibabainc.dingtalk#\\./com.alibabainc.dingtalk --no-sandbox#g' /opt/apps/com.alibabainc.dingtalk/files/Elevator.sh; rm /tmp/dingtalk.deb"""},
{"name":"卸载钉钉", "command":"sudo apt autoremove --purge -y com.alibabainc.dingtalk"}, {"name":"卸载钉钉", "command":"sudo apt autoremove --purge -y com.alibabainc.dingtalk"},
{"name":"修复无法编译C语言程序", "command":"sudo apt update && sudo apt reinstall -y libc6-dev"}, {"name":"修复无法编译C语言程序", "command":"sudo apt update && sudo apt reinstall -y libc6-dev"},
{"name":"修复系统语言到中文", "command":"sudo localedef -c -i zh_CN -f UTF-8 zh_CN.UTF-8"}, {"name":"修复系统语言到中文", "command":"sudo localedef -c -i zh_CN -f UTF-8 zh_CN.UTF-8 #重启生效"},
{"name":"启用回收站", "command":"sudo apt update && sudo apt install -y gvfs && echo '安装完成, 重启软件即可使用回收站。'"}, {"name":"启用回收站", "command":"sudo apt update && sudo apt install -y gvfs && echo '安装完成, 重启软件即可使用回收站。'"},
{"name":"拉流测试", "command":"ffplay rtsp://127.0.0.1:8554/stream &"}, {"name":"拉流测试", "command":"ffplay rtsp://127.0.0.1:8554/stream &"},
{"name":"关机", "command":"stopvnc\nexit\nexit"}, {"name":"关机", "command":"stopvnc\nexit\nexit"},
@@ -892,11 +891,6 @@ clear""");
static Future<void> launchBrowser() async { static Future<void> launchBrowser() async {
G.controller.loadRequest(Uri.parse(Util.getCurrentProp("vncUrl"))); G.controller.loadRequest(Uri.parse(Util.getCurrentProp("vncUrl")));
Navigator.push(G.homePageStateContext, MaterialPageRoute(builder: (context) { Navigator.push(G.homePageStateContext, MaterialPageRoute(builder: (context) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky,overlays: []);
SystemChrome.setSystemUIChangeCallback((systemOverlaysAreVisible) async {
await Future.delayed(const Duration(seconds: 1));
SystemChrome.restoreSystemUIOverlays();
});
return Focus( return Focus(
onKeyEvent: (node, event) { onKeyEvent: (node, event) {
// Allow webview to handle cursor keys. Without this, the // Allow webview to handle cursor keys. Without this, the

View File

@@ -77,10 +77,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: dynamic_color name: dynamic_color
sha256: a866f1f8947bfdaf674d7928e769eac7230388a2e7a2542824fad4bb5b87be3b sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.6.9" version: "1.7.0"
equatable: equatable:
dependency: transitive dependency: transitive
description: description:
@@ -665,10 +665,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad" sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.5.1"
webview_flutter: webview_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -705,10 +705,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.2.0" version: "5.3.0"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

View File

@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.14+10 version: 1.0.15+11
environment: environment:
sdk: '>=3.1.0 <4.0.0' sdk: '>=3.1.0 <4.0.0'