diff --git a/assets/patch.tar.gz b/assets/patch.tar.gz index f6678cc..340ff0c 100644 Binary files a/assets/patch.tar.gz and b/assets/patch.tar.gz differ diff --git a/extra/cross/install-box b/extra/cross/install-box index 21c598a..cb9eda1 100644 --- a/extra/cross/install-box +++ b/extra/cross/install-box @@ -8,12 +8,13 @@ sudo apt reinstall -y libc6-dev mkdir $HOME/.local/share/tiny/cross +rm -rf $HOME/.local/share/tiny/tmp mkdir $HOME/.local/share/tiny/tmp cd $HOME/.local/share/tiny/tmp -git clone https://github.com/ptitSeb/box86 +git clone https://mirror.ghproxy.com/https://github.com/ptitSeb/box86 if [ $? -ne 0 ]; then - git clone https://mirror.ghproxy.com/https://github.com/ptitSeb/box86 + git clone https://github.com/ptitSeb/box86 if [ $? -ne 0 ]; then rm -rf $HOME/.local/share/tiny/tmp echo '仓库克隆失败...退出安装...' @@ -21,9 +22,9 @@ if [ $? -ne 0 ]; then fi fi -git clone https://github.com/ptitSeb/box64 +git clone https://mirror.ghproxy.com/https://github.com/ptitSeb/box64 if [ $? -ne 0 ]; then - git clone https://mirror.ghproxy.com/https://github.com/ptitSeb/box64 + git clone https://github.com/ptitSeb/box64 if [ $? -ne 0 ]; then rm -rf $HOME/.local/share/tiny/tmp echo '仓库克隆失败...退出安装...' @@ -35,17 +36,19 @@ cd box86 mkdir build cd build cmake .. -DARM64=1 -DBAD_SIGNAL=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -make +make -j cd ../.. mv box86/build/box86 ../cross +mv box86/x86lib ../cross cd box64 mkdir build cd build cmake .. -DARM64=1 -DBAD_SIGNAL=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -make +make -j cd ../.. mv box64/build/box64 ../cross +mv box64/x64lib ../cross cd .. rm -rf tmp diff --git a/extra/cross/install-wine b/extra/cross/install-wine index 9467096..16e4600 100644 --- a/extra/cross/install-wine +++ b/extra/cross/install-wine @@ -4,12 +4,23 @@ sudo apt update sudo apt upgrade -y sudo apt install -y nano cabextract libfreetype6 libfreetype6:armhf libfontconfig libfontconfig:armhf libxext6 libxext6:armhf libxinerama-dev libxinerama-dev:armhf libxxf86vm1 libxxf86vm1:armhf libxrender1 libxrender1:armhf libxcomposite1 libxcomposite1:armhf libxrandr2 libxrandr2:armhf libxi6 libxi6:armhf libxcursor1 libxcursor1:armhf libvulkan-dev libvulkan-dev:armhf zenity +rm -rf $HOME/.local/share/tiny/tmp mkdir $HOME/.local/share/tiny/tmp cd $HOME/.local/share/tiny/tmp -wget https://github.com/Kron4ek/Wine-Builds/releases/download/8.20/wine-8.20-x86.tar.xz +MIRROR_SITE=https://mirror.ghproxy.com +LATEST_WINE_NAME=$(curl -L https://github.com/Kron4ek/Wine-Builds/releases | grep "amd64\.tar\.xz" | grep "proton" | head -n 1 | awk '{print $NF}') +LATEST_WINE_TAG=$(echo $LATEST_WINE_NAME | cut -d "-" -f 2) + +if [ $LATEST_WINE_TAG == proton ]; then + LATEST_WINE_TAG=proton-$(echo $LATEST_WINE_NAME | cut -d "-" -f 3)-$(echo $LATEST_WINE_NAME | cut -d "-" -f 4) +fi + +LATEST_WINE_LINK=https://github.com/Kron4ek/Wine-Builds/releases/download/$LATEST_WINE_TAG/$LATEST_WINE_NAME + +wget $MIRROR_SITE/$LATEST_WINE_LINK if [ $? -ne 0 ]; then - wget https://mirror.ghproxy.com/https://github.com/Kron4ek/Wine-Builds/releases/download/8.20/wine-8.20-x86.tar.xz + wget $LATEST_WINE_LINK if [ $? -ne 0 ]; then rm -rf $HOME/.local/share/tiny/tmp echo '下载失败...退出安装...' @@ -17,9 +28,9 @@ if [ $? -ne 0 ]; then fi fi -wget https://github.com/Kron4ek/Wine-Builds/releases/download/8.20/wine-8.20-amd64.tar.xz +wget $MIRROR_SITE/https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks if [ $? -ne 0 ]; then - wget https://mirror.ghproxy.com/https://github.com/Kron4ek/Wine-Builds/releases/download/8.20/wine-8.20-amd64.tar.xz + wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks if [ $? -ne 0 ]; then rm -rf $HOME/.local/share/tiny/tmp echo '下载失败...退出安装...' @@ -27,52 +38,28 @@ if [ $? -ne 0 ]; then fi fi -wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks -if [ $? -ne 0 ]; then - wget https://mirror.ghproxy.com/https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks - if [ $? -ne 0 ]; then - rm -rf $HOME/.local/share/tiny/tmp - echo '下载失败...退出安装...' - exit - fi -fi - -tar xvf wine-8.20-x86.tar.xz -tar xvf wine-8.20-amd64.tar.xz -mv wine-8.20-x86 ../cross/wine32 -mv wine-8.20-amd64 ../cross/wine64 +tar xvf $LATEST_WINE_NAME +mv wine-$LATEST_WINE_TAG-amd64 ../cross/wine mv winetricks ../cross/winetricks-executable chmod +x $HOME/.local/share/tiny/cross/winetricks-executable cd .. rm -rf tmp echo '#!/bin/bash -export WINEPREFIX=~/.wine32 -box86 '"$HOME/.local/share/tiny/cross/wine32 "'"$@"' > $HOME/.local/share/tiny/cross/wine32-executable -chmod +x $HOME/.local/share/tiny/cross/wine32-executable +export WINEPREFIX=~/.wine +box86 '"$HOME/.local/share/tiny/cross/wine/bin/wine "'"$@"' > $HOME/.local/share/tiny/cross/wine-executable +chmod +x $HOME/.local/share/tiny/cross/wine-executable echo '#!/bin/bash -export WINEPREFIX=~/.wine64 -box64 '"$HOME/.local/share/tiny/cross/wine64 "'"$@"' > $HOME/.local/share/tiny/cross/wine64-executable +export WINEPREFIX=~/.wine +box64 '"$HOME/.local/share/tiny/cross/wine/bin/wine64 "'"$@"' > $HOME/.local/share/tiny/cross/wine64-executable chmod +x $HOME/.local/share/tiny/cross/wine64-executable echo '#!/bin/bash -export BOX86_NOBANNER=1 WINE=wine32 WINEPREFIX=~/.wine32 WINESERVER=~/.local/share/tiny/cross/wine32/bin/wineserver -wine32 '"$HOME/.local/share/tiny/cross/winetricks-executable "'"$@"' > $HOME/.local/share/tiny/cross/winetricks32-executable -chmod +x $HOME/.local/share/tiny/cross/winetricks32-executable - -echo '#!/bin/bash -export BOX64_NOBANNER=1 WINE=wine64 WINEPREFIX=~/.wine64 WINESERVER=~/.local/share/tiny/cross/wine64/bin/wineserver +export BOX64_NOBANNER=1 WINE=wine64 WINEPREFIX=~/.wine WINESERVER=~/.local/share/tiny/cross/wine/bin/wineserver wine64 '"$HOME/.local/share/tiny/cross/winetricks-executable "'"$@"' > $HOME/.local/share/tiny/cross/winetricks64-executable chmod +x $HOME/.local/share/tiny/cross/winetricks64-executable -echo '[Desktop Entry] -Name=Wine32 启动器 -Exec=wine32 start /unix %F -Icon=wine -Type=Application' > $HOME/.local/share/tiny/cross/wine32.desktop -chmod +x $HOME/.local/share/tiny/cross/wine32.desktop - echo '[Desktop Entry] Name=Wine64 启动器 Exec=wine64 start /unix %F @@ -80,13 +67,6 @@ Icon=wine Type=Application' > $HOME/.local/share/tiny/cross/wine64.desktop chmod +x $HOME/.local/share/tiny/cross/wine64.desktop -echo '[Desktop Entry] -Name=Wine32 winetricks 实用工具 -Exec=winetricks32 -Icon=wine -Type=Application' > $HOME/.local/share/tiny/cross/winetricks32.desktop -chmod +x $HOME/.local/share/tiny/cross/winetricks32.desktop - echo '[Desktop Entry] Name=Wine64 winetricks 实用工具 Exec=winetricks64 @@ -94,4 +74,6 @@ Icon=wine Type=Application' > $HOME/.local/share/tiny/cross/winetricks64.desktop chmod +x $HOME/.local/share/tiny/cross/winetricks64.desktop -echo '安装完成' \ No newline at end of file +echo '安装完成,在启用wine后可以点击exe文件选择用wine启动。' +echo '程序的运行可能依赖一些配置或组件。比如,一些使用directx的游戏可能需要安装dxvk。' +echo '如果缺失可以尝试使用winetricks安装。请务必保持耐心。' diff --git a/lib/main.dart b/lib/main.dart index 7810d8d..a3ec0b4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,6 +18,7 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'dart:math'; //import 'dart:convert'; @@ -103,7 +104,7 @@ class SettingPage extends StatefulWidget { class _SettingPageState extends State { - final List _expandState = [false, false, false, false, false, false]; + final List _expandState = [false, false, false, false, false, false, false]; @override Widget build(BuildContext context) { @@ -120,25 +121,6 @@ class _SettingPageState extends State { headerBuilder: ((context, isExpanded) { return const ListTile(title: Text("高级设置"), subtitle: Text("修改后重启生效")); }), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [ - 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)), - 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)), - 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)), - 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)), OutlinedButton(style: D.commandButtonStyle, child: const Text("重置启动命令"), onPressed: () { showDialog(context: context, builder: (context) { return AlertDialog(title: const Text("注意"), content: const Text("是否重置启动命令?"), actions: [ @@ -154,6 +136,30 @@ class _SettingPageState extends State { ]); }); }), + SizedBox.fromSize(size: const Size.square(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)), + 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)), + 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 Divider(height: 2, indent: 8, endIndent: 8), + SizedBox.fromSize(size: const Size.square(16)), + const Text("你可以在当前所有同一网络下的设备(如:连接同一路由器的手机,电脑等)里使用小小电脑。\n\n将下面的链接复制到其他设备,在其他设备上把链接localhost字样改为当前设备的IP地址(可以通过快捷指令查看),然后使用浏览器打开链接即可。"), + SizedBox.fromSize(size: const Size.square(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)), ],))), ExpansionPanel( isExpanded: _expandState[1], @@ -429,6 +435,104 @@ class _SettingPageState extends State { ],))), ExpansionPanel( isExpanded: _expandState[5], + headerBuilder: ((context, isExpanded) { + return const ListTile(title: Text("跨架构/跨系统支持"), subtitle: Text("实验性功能"),); + }), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [ + const Text("""你的梦想是在你的小小电脑上,运行着那些你熟悉的x86/x64或windows的程序。你不惧怕任何困难,你勇敢地使用box86/box64或wine,让你的梦想成为现实。但是,你也要知道,这是一条漫长而艰辛的道路,你需要付出很多的代价。你的程序要经过两层的模拟,就像穿越两个世界,它们的速度会变得缓慢而沉重。你需要有足够的耐心,即使你的眼前一片空白,你的终端还在默默地工作。你要时刻关注它的输出,看看它是否还在前进,还是遇到了难以逾越的障碍。或者,你也可以选择另一条路,去寻找那些为linux arm64而生的程序,它们或许能让你的梦想更加顺畅。 + +你的选择就在下面,你只需勾选你想要的选项,然后重新启动你的小小电脑,你的梦想就会有所不同。 + +......人话: + +使用box86/box64运行x86/x64架构的程序,或使用wine运行windows程序。 + +运行windows程序需要经过架构和系统两层模拟,不要对运行速度抱有期待。程序崩溃也是常有的。 + +你需要耐心。即使图形界面什么也没显示。看看终端,还在继续输出吗?还是停止在某个报错? + +或者寻找该windows软件官方是否提供linux arm64版本。 + +以下选项启用后下次启动时生效。 +"""), + SizedBox.fromSize(size: const Size.square(16)), + 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"); + G.pageIndex.value = 0; + }), + OutlinedButton(style: D.commandButtonStyle, child: const Text("安装wine与winetricks"), onPressed: () async { + if (!await File("${G.dataPath}/tiny/cross/box64").exists()) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("请先安装box86/box64")) + ); + return; + } + Util.termWrite("bash ~/.local/share/tiny/extra/install-wine"); + G.pageIndex.value = 0; + }), + OutlinedButton(style: D.commandButtonStyle, child: const Text("移除所有安装"), onPressed: () async { + if (G.wasBoxEnabled) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("请关闭跨架构支持后重试")) + ); + return; + } + Util.termWrite("rm -rf ~/.local/share/tiny/cross"); + G.pageIndex.value = 0; + }), + OutlinedButton(style: D.commandButtonStyle, child: const Text("清空wine数据"), onPressed: () async { + Util.termWrite("rm -rf ~/.wine"); + G.pageIndex.value = 0; + }), + OutlinedButton(style: D.commandButtonStyle, child: const Text("配置wine"), onPressed: () async { + Util.termWrite("wine64 winecfg"); + G.pageIndex.value = 0; + Workflow.launchBrowser(); + }), + OutlinedButton(style: D.commandButtonStyle, child: const Text("启动winetricks"), onPressed: () async { + Util.termWrite("winetricks64"); + G.pageIndex.value = 0; + Workflow.launchBrowser(); + }), + ]), + SizedBox.fromSize(size: const Size.square(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()) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("请先安装box86/box64")) + ); + return; + } + G.prefs.setBool("isBoxEnabled", value); + if (!value && Util.getGlobal("isWineEnabled")) { + G.prefs.setBool("isWineEnabled", false); + } + setState(() {}); + },), + SwitchListTile(title: const Text("启用wine"), subtitle: const Text("运行windows exe软件"), value: Util.getGlobal("isWineEnabled") as bool, onChanged:(value) async { + //检测wine是否存在且box64是否开启 + if (value && !(Util.getGlobal("isBoxEnabled") && await File("${G.dataPath}/tiny/cross/wine64-executable").exists())) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("请先安装wine并启用box86/box64")) + ); + return; + } + G.prefs.setBool("isWineEnabled", value); + setState(() {}); + },), + SizedBox.fromSize(size: const Size.square(16)), + ],))), + ExpansionPanel( + isExpanded: _expandState[6], headerBuilder: ((context, isExpanded) { return const ListTile(title: Text("广告记录"), subtitle: Text("在这里看广告")); }), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [ diff --git a/lib/workflow.dart b/lib/workflow.dart index 6f27e7a..7f1e3e0 100644 --- a/lib/workflow.dart +++ b/lib/workflow.dart @@ -90,6 +90,8 @@ class Util { //bool reinstallBootstrap = false 下次启动是否重装引导包 //bool getifaddrsBridge = false 下次启动是否桥接getifaddrsBridge //bool uos = false 下次启动是否伪装UOS + //bool isBoxEnabled = false 下次启动是否开启box86/box64 + //bool isWineEnabled = false 下次启动是否开启wine //bool virgl = false 下次启动是否启用virgl //? int bootstrapVersion: 启动包版本 //String[] containersInfo: 所有容器信息(json) @@ -117,6 +119,8 @@ class Util { case "reinstallBootstrap" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "getifaddrsBridge" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "uos" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); + case "isBoxEnabled" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); + case "isWineEnabled" : 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 "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"); @@ -344,23 +348,24 @@ 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 | awk '{print \$NF}' # 如果显示无权限(Permission denied),请在全局设置里开启getifaddrs桥接"}, {"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"}, {"name":"安装视频剪辑软件Kdenlive", "command":"sudo apt update && sudo apt install -y kdenlive"}, -{"name":"卸载视频剪辑软件Kdenlive", "command":"sudo apt autoremove --purge -y kdenlive"}, +{"name":"卸载Kdenlive", "command":"sudo apt autoremove --purge -y kdenlive"}, {"name":"安装科学计算软件Octave", "command":"sudo apt update && sudo apt install -y octave"}, -{"name":"卸载科学计算软件Octave", "command":"sudo apt autoremove --purge -y octave"}, -{"name":"安装WPS", "command":"wget https://wps-linux-personal.wpscdn.cn/wps/download/ep/Linux2019/11708/wps-office_11.1.0.11708_arm64.deb -O /tmp/wps.deb && sudo apt update && sudo apt install -y /tmp/wps.deb; rm /tmp/wps.deb"}, +{"name":"卸载Octave", "command":"sudo apt autoremove --purge -y octave"}, +{"name":"安装WPS", "command":"""wget \$(curl -L https://linux.wps.cn/ | grep -oP 'href="\\K[^"]*arm64\\.deb' | head -n 1) -O /tmp/wps.deb && sudo apt update && sudo apt install -y /tmp/wps.deb; rm /tmp/wps.deb"""}, {"name":"卸载WPS", "command":"sudo apt autoremove --purge -y wps-office"}, {"name":"安装CAJViewer", "command":"wget https://download.cnki.net/net.cnki.cajviewer_1.3.20-1_arm64.deb -O /tmp/caj.deb && sudo apt update && sudo apt install -y /tmp/caj.deb && bash /home/tiny/.local/share/tiny/caj/postinst; rm /tmp/caj.deb"}, {"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_11.5.6-3_arm64.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":"安装QQ", "command":"wget https://dldir1.qq.com/qqfile/qq/QQNT/fd2e886e/linuxqq_3.2.2-18394_arm64.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":"""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":"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.9_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伪装。\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.9_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 libssl1.1 deepin-elf-verify"}, -{"name":"安装钉钉", "command":"wget https://dtapp-pub.dingtalk.com/dingtalk-desktop/xc_dingtalk_update/linux_deb/Release/com.alibabainc.dingtalk_7.1.0.31017_arm64.deb -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 && 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"}, @@ -469,6 +474,8 @@ class G { static ValueNotifier bootTextChange = ValueNotifier(true); //更改值,用于刷新启动命令 static ValueNotifier updateText = ValueNotifier("小小电脑"); //加载界面的说明文字 + static bool wasBoxEnabled = false; //本次启动时是否启用了box86/64 + static late SharedPreferences prefs; } @@ -760,6 +767,16 @@ export CONTAINER_DIR=\$DATA_DIR/containers/${G.currentContainer} ${G.dataPath}/bin/virgl_test_server ${Util.getGlobal("defaultVirglCommand")}"""); extraOpt += "${Util.getGlobal("defaultVirglOpt")} "; } + if (Util.getGlobal("isBoxEnabled")) { + G.wasBoxEnabled = true; + extraMount += "--mount=\$DATA_DIR/tiny/cross/box86:/home/tiny/.local/bin/box86 --mount=\$DATA_DIR/tiny/cross/box64:/home/tiny/.local/bin/box64 "; + } + if (Util.getGlobal("isWineEnabled")) { + extraOpt += "BOX86_PATH=/home/tiny/.local/share/tiny/cross/wine/bin/ BOX86_LD_LIBRARY_PATH=/home/tiny/.local/share/tiny/cross/wine/lib/wine/i386-unix/:/lib/i386-linux-gnu/:/lib/aarch64-linux-gnu/:/lib/arm-linux-gnueabihf/:/usr/lib/aarch64-linux-gnu/:/usr/lib/arm-linux-gnueabihf/:/usr/lib/i386-linux-gnu/:/home/tiny/.local/share/tiny/cross/x86lib/ "; + extraOpt += "BOX64_PATH=/home/tiny/.local/share/tiny/cross/wine/bin/ BOX64_LD_LIBRARY_PATH=/home/tiny/.local/share/tiny/cross/wine/lib/wine/i386-unix/:/home/tiny/.local/share/tiny/cross/wine/lib/wine/x86_64-unix/:/lib/i386-linux-gnu/:/lib/x86_64-linux-gnu:/lib/aarch64-linux-gnu/:/lib/arm-linux-gnueabihf/:/usr/lib/aarch64-linux-gnu/:/usr/lib/arm-linux-gnueabihf/:/usr/lib/i386-linux-gnu/:/usr/lib/x86_64-linux-gnu/:/home/tiny/.local/share/tiny/cross/x64lib/ "; + extraMount += "--mount=\$DATA_DIR/tiny/cross/wine-executable:/home/tiny/.local/bin/wine --mount=\$DATA_DIR/tiny/cross/wine64-executable:/home/tiny/.local/bin/wine64 --mount=\$DATA_DIR/tiny/cross/wine64.desktop:/usr/share/applications/wine64.desktop "; + extraMount += "--mount=\$DATA_DIR/tiny/cross/winetricks64-executable:/home/tiny/.local/bin/winetricks64 --mount=\$DATA_DIR/tiny/cross/winetricks64.desktop:/usr/share/applications/winetricks64.desktop "; + } Util.termWrite( """ export DATA_DIR=${G.dataPath} diff --git a/pubspec.lock b/pubspec.lock index 2a23436..2f2f896 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" convert: dependency: transitive description: @@ -114,10 +114,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "3.0.1" flutter_pty: dependency: "direct main" description: @@ -140,10 +140,10 @@ packages: dependency: "direct main" description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" http_parser: dependency: transitive description: @@ -164,10 +164,10 @@ packages: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "3.0.0" matcher: dependency: transitive description: @@ -188,10 +188,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" path: dependency: transitive description: @@ -252,42 +252,50 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 + sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78" url: "https://pub.dev" source: hosted - version: "10.4.5" + version: "11.1.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" + sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6" url: "https://pub.dev" source: hosted - version: "10.3.6" + version: "12.0.1" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" + sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306" url: "https://pub.dev" source: hosted - version: "9.1.4" + version: "9.2.0" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: d96ff56a757b7f04fa825c469d296c5aebc55f743e87bd639fef91a466a24da8 + url: "https://pub.dev" + source: hosted + version: "0.1.0+1" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" + sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1 url: "https://pub.dev" source: hosted - version: "3.12.0" + version: "4.0.2" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 + sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004" url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "0.2.0" platform: dependency: transitive description: @@ -372,10 +380,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_windows: dependency: transitive description: @@ -401,18 +409,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -433,10 +441,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" typed_data: dependency: transitive description: @@ -505,10 +513,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + sha256: "138bd45b3a456dcfafc46d1a146787424f8d2edfbf2809c9324361e58f851cf7" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" url_launcher_windows: dependency: transitive description: @@ -529,10 +537,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" webview_flutter: dependency: "direct main" description: @@ -553,10 +561,10 @@ packages: dependency: transitive description: name: webview_flutter_platform_interface - sha256: adb8c03c2be231bea5a8ed0e9039e9d18dbb049603376beaefa15393ede468a5 + sha256: "68e86162aa8fc646ae859e1585995c096c95fc2476881fa0c4a8d10f56013a5a" url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.8.0" webview_flutter_wkwebview: dependency: transitive description: @@ -590,5 +598,5 @@ packages: source: hosted version: "3.5.0" sdks: - dart: ">=3.1.0 <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.2.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index 75014c9..a736e33 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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 # 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. -version: 1.0.11+2 +version: 1.0.12+1 environment: sdk: '>=3.1.0 <4.0.0' @@ -34,7 +34,7 @@ dependencies: flutter_pty: ^0.4.0 path_provider: ^2.1.0 webview_flutter: ^4.4.2 - permission_handler: ^10.4.3 + permission_handler: ^11.0.1 http: ^1.1.0 retry: ^3.1.2 url_launcher: ^6.1.12 @@ -58,7 +58,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^3.0.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec