Update code to v1.0.15

This commit is contained in:
Caten
2024-03-12 22:06:10 +08:00
parent b50622787d
commit 3e443ceedc
4 changed files with 96 additions and 112 deletions

View File

@@ -31,7 +31,7 @@ import 'package:flutter_pty/flutter_pty.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:network_info_plus/network_info_plus.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:flutter/material.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 {
await Util.setCurrentProp("name", value);
//setState(() {});
}),
SizedBox.fromSize(size: const Size.square(8)),
const SizedBox.square(dimension: 8),
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 {
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 {
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),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
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: [
OutlinedButton(style: D.commandButtonStyle, child: const Text("复制分享链接"), onPressed: () async {
final String? ip = await NetworkInfo().getWifiIP();
@@ -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 {
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 {
await Util.setCurrentProp("vncUri", value);
}),
SizedBox.fromSize(size: const Size.square(8)),
const SizedBox.square(dimension: 8),
],))),
ExpansionPanel(
isExpanded: _expandState[1],
@@ -218,7 +218,7 @@ class _SettingPageState extends State<SettingPage> {
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接收端口"),
keyboardType: TextInputType.number,
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) {
if (value && Util.shouldWatchAds(D.adsRequired["closeBannerAds"]!)) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
@@ -241,7 +241,7 @@ class _SettingPageState extends State<SettingPage> {
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) {
if (value && Util.shouldWatchAds(D.adsRequired["enableTerminalWrite"]!)) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
@@ -256,7 +256,7 @@ class _SettingPageState extends State<SettingPage> {
G.prefs.setBool("isTerminalWriteEnabled", value);
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) {
if (value && Util.shouldWatchAds(D.adsRequired["enableTerminalCommands"]!)) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
@@ -270,37 +270,37 @@ class _SettingPageState extends State<SettingPage> {
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) {
G.prefs.setBool("isStickyKey", value);
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) {
G.prefs.setBool("wakelock", value);
WakelockPlus.toggle(enable: value);
setState(() {});
},),
SizedBox.fromSize(size: const Size.square(8)),
const SizedBox.square(dimension: 8),
const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
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) {
G.prefs.setBool("autoLaunchVnc", value);
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) {
G.prefs.setBool("reinstallBootstrap", value);
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) {
G.prefs.setBool("getifaddrsBridge", value);
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) {
G.prefs.setBool("uos", value);
setState(() {});
@@ -311,10 +311,10 @@ class _SettingPageState extends State<SettingPage> {
headerBuilder: ((context, isExpanded) {
return const ListTile(title: Text("显示设置"));
}), 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可以带来获得更好的操控体验
如触摸板触控,双指单击弹出键盘,自动剪切板,画中画模式等等。这是一个实验性功能。"""),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
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", {});
@@ -323,10 +323,15 @@ class _SettingPageState extends State<SettingPage> {
await D.avncChannel.invokeMethod("launchAboutPage", {});
}),
OutlinedButton(style: D.commandButtonStyle, child: const Text("AVNC启动时分辨率设置"), onPressed: () async {
String w = "1440";
String h = "720";
final s = WidgetsBinding.instance.platformDispatcher.views.first.physicalSize;
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) {
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,
validator: (value) {
return Util.validateBetween(value, 200, 7680, () {
@@ -334,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,
validator: (value) {
return Util.validateBetween(value, 200, 7680, () {
@@ -360,22 +365,21 @@ 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),
SwitchListTile(title: const Text("默认使用AVNC"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("useAvnc") as bool, onChanged:(value) {
G.prefs.setBool("useAvnc", value);
setState(() {});
},),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
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"]!),
onTap: () {
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);
},
),
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) {
G.prefs.setBool("isHidpiEnabled", value);
setState(() {});
},),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
],))),
ExpansionPanel(
isExpanded: _expandState[3],
@@ -469,7 +473,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.isStreamServerStarted = value;
setState(() {});
},),
SizedBox.fromSize(size: const Size.square(8)),
const SizedBox.square(dimension: 8),
SwitchListTile(title: const Text("启动推流"), value: G.isStreaming, onChanged:(value) {
switch (value) {
case true: {
@@ -490,7 +494,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.isStreaming = value;
setState(() {});
},),
SizedBox.fromSize(size: const Size.square(8))
const SizedBox.square(dimension: 8)
],))),
ExpansionPanel(
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("文件访问"));
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
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: [
OutlinedButton(style: D.commandButtonStyle, child: const Text("申请存储权限"), onPressed: () {
Permission.storage.request();
@@ -507,7 +511,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
Permission.manageExternalStorage.request();
}),
]),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
],))),
ExpansionPanel(
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服务器参数"),
onChanged: (value) async {
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) {
switch (value) {
case true: {
@@ -546,13 +550,13 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
G.isVirglServerStarted = value;
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: "图形环境变量"),
onChanged: (value) async {
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) {
if (value && Util.shouldWatchAds(D.adsRequired["enableVirgl"]!)) {
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);
setState(() {});
},),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
],))),
ExpansionPanel(
isExpanded: _expandState[6],
@@ -585,7 +589,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
跨架构/跨系统提供类似binfmt_misc的支持。
你可以直接执行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: [
OutlinedButton(style: D.commandButtonStyle, child: const Text("安装box86和box64"), onPressed: () {
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;
}),
]),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
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>(
(e) {
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()),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
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 {
//检测box64是否存在存在才开启
if (value && !await File("${G.dataPath}/tiny/cross/box64").exists()) {
@@ -698,7 +702,7 @@ fi""");
G.prefs.setBool("isWineEnabled", value);
setState(() {});
},),
SizedBox.fromSize(size: const Size.square(16)),
const SizedBox.square(dimension: 16),
],))),
ExpansionPanel(
isExpanded: _expandState[7],
@@ -771,7 +775,8 @@ class _InfoPageState extends State<InfoPage> {
正常情况下,加载完成后软件会自动跳转到图形界面
在图形界面时,点击即鼠标左键
双指点击为鼠标右键
长按为鼠标右键
双指点击弹出键盘
双指划动为鼠标滚轮
在图形界面返回,可以回到终端界面和控制界面
@@ -810,19 +815,15 @@ bilibili客户端等等不可用
如果你给了存储权限
那么通过主目录下的文件夹
就可以访问手机存储
就可以访问设备存储
要访问整个设备存储可以访问sd文件夹
此外主文件夹的很多文件夹与设备文件夹绑定
比如主文件夹的下载文件夹就是设备的下载文件夹
有一些设备做了更多访问限制
比如下载文件夹可能不可写入
这样会导致把文件保存到下载目录时出现问题
如果没有给存储权限
文件保存到下载文件夹可能出现问题
(火狐浏览器可能因此无法下载文件)
不过这个很好解决
换个文件夹保存就行了
如果认为界面大小比例不合适
可以通过调整图形界面左栏设置-高级里的屏幕缩放比例
如果感觉界面卡卡的
可以适当调低图像质量或压缩等级
你也可以选择换一个文件夹保存
如果你想安装其他软件
可以使用容器自带的tmoe
@@ -841,7 +842,7 @@ VSCode、输入法
如果你需要更多字体
在给了存储权限的情况下
直接将字体复制到手机存储的Fonts文件夹即可
直接将字体复制到设备存储的Fonts文件夹即可
一些常用的办公字体
可以在Windows电脑的C:\\Windows\\Fonts文件夹找到
由于可能的版权问题
@@ -852,23 +853,14 @@ VSCode、输入法
而是使用英文键盘通过容器的输入法(Ctrl+空格切换)输入中文
避免丢字错字
在之前的版本中有网友反馈过这些问题
还请注意:
三星Galaxy S21 Ultra, 安卓13, 黑屏
红米Note 12, 安卓13miui14, 黑屏
红米Note 11T Pro+ miui13.0.4,“无法连接”
Vivo Pad安卓13看不见鼠标移动可以去左栏设置开启显示原系统光标替代
关于这些
我目前没有什么好的解决办法
(毕竟我没有这些设备
也不方便定位原因)
如果你遇到了类似问题
不管解没解决
都可以去https://github.com/Cateners/tiny_computer/issues/留个言
如果你遇到了问题
可以去https://github.com/Cateners/tiny_computer/issues/
留言反馈
如果软件里有程序正在正常运行
请不要强行关闭本软件
否则可能会损坏容器
(如dpkg被中断)
特别是在安装某些比较大的软件的时候
感谢使用!
@@ -1461,14 +1453,14 @@ class TerminalPage extends StatelessWidget {
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) {
return OutlinedButton(style: D.controlButtonStyle, onPressed: () {
G.termPtys[G.currentContainer]!.terminal.keyInput(D.termCommands[index]["key"]! as TerminalKey);
}, child: Text(D.termCommands[index]["name"]! as String));
}, separatorBuilder:(context, index) {
return SizedBox.fromSize(size: const Size.square(4));
}, itemCount: D.termCommands.length))), SizedBox.fromSize(size: const Size(72, 0))])):SizedBox.fromSize(size: const Size.square(0));
return const SizedBox.square(dimension: 4);
}, 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) {
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) {
command = value;
}),
@@ -1531,7 +1523,7 @@ class _FastCommandsState extends State<FastCommands> {
TextFormField(initialValue: name, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "指令名称"), onChanged: (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) {
command = value;
}),
@@ -1597,13 +1589,15 @@ class _MyHomePageState extends State<MyHomePage> {
}
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky,overlays: []);
return Scaffold(
appBar: AppBar(
title: Text(isLoadingComplete?Util.getCurrentProp("name"):widget.title),
),
body: isLoadingComplete?Column(mainAxisSize: MainAxisSize.min, children: [
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,
onLoad: (placementId) => debugPrint('Banner loaded: $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) {
return IndexedStack(index: G.pageIndex.value, children: [const TerminalPage(), Padding(
padding: const EdgeInsets.all(8),
return IndexedStack(index: G.pageIndex.value, children: const [TerminalPage(), Padding(
padding: EdgeInsets.all(8),
child: Scrollbar(child: SingleChildScrollView(restorationId: "control-scroll", child: Column(
children: [
const Padding(
Padding(
padding: EdgeInsets.all(16),
child: FractionallySizedBox(
widthFactor: 0.4,
@@ -1628,16 +1622,12 @@ class _MyHomePageState extends State<MyHomePage> {
)
),
),
/*Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 8),
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:
FastCommands(),
Padding(padding: EdgeInsets.all(8), child: Card(child: Padding(padding: EdgeInsets.all(8), child:
Column(children: [
const SettingPage(),
SizedBox.fromSize(size: const Size.square(8)),
const InfoPage(openFirstInfo: false)
SettingPage(),
SizedBox.square(dimension: 8),
InfoPage(openFirstInfo: false)
])
)))
]

View File

@@ -130,7 +130,7 @@ class Util {
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 "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 "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");
@@ -390,7 +390,6 @@ class D {
static const commands = [{"name":"检查更新并升级", "command":"sudo apt update && sudo apt upgrade -y"},
{"name":"查看系统信息", "command":"neofetch -L && neofetch --off"},
{"name":"清屏", "command":"clear"},
{"name":"查看IP", "command":"hostname -I # 如果显示无权限(Permission denied)请在全局设置里开启getifaddrs桥接"},
{"name":"中断任务", "command":"\x03"},
{"name":"安装图形处理软件Krita", "command":"sudo apt update && sudo apt install -y krita krita-l10n"},
{"name":"卸载Krita", "command":"sudo apt autoremove --purge -y krita krita-l10n"},
@@ -412,10 +411,10 @@ rm /tmp/wps.deb"""},
{"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":"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":"修复无法编译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":"ffplay rtsp://127.0.0.1:8554/stream &"},
{"name":"关机", "command":"stopvnc\nexit\nexit"},
@@ -892,11 +891,6 @@ clear""");
static Future<void> launchBrowser() async {
G.controller.loadRequest(Uri.parse(Util.getCurrentProp("vncUrl")));
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(
onKeyEvent: (node, event) {
// Allow webview to handle cursor keys. Without this, the