mirror of
https://github.com/Cateners/tiny_computer.git
synced 2026-05-20 16:35:47 +08:00
Compare commits
3 Commits
v1.0.14+10
...
v1.0.15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e443ceedc | ||
|
|
b50622787d | ||
|
|
231d1167e0 |
@@ -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")!!
|
||||||
|
|||||||
@@ -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.
@@ -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
|
||||||
|
|||||||
198
lib/main.dart
198
lib/main.dart
@@ -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, 安卓13(miui14), 黑屏
|
|
||||||
红米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)
|
||||||
])
|
])
|
||||||
)))
|
)))
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
12
pubspec.lock
12
pubspec.lock
@@ -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:
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
Reference in New Issue
Block a user