Compare commits

..

13 Commits

Author SHA1 Message Date
Caten
23968eb1fc Update README.md 2025-09-14 16:28:22 +08:00
Caten
2aac0e57d7 Simple build script 2025-09-14 13:36:43 +08:00
Caten
ed1c4aa9b1 Fix termux:x11 start & scale 2025-09-14 13:36:20 +08:00
Caten
f2eb3e0491 For English, fix locale, remove CAJViewer, set edmax to English 2025-09-13 12:31:29 +08:00
Caten
d17e515981 Fix IE name 2025-09-12 21:47:37 +08:00
Caten
10f481f976 Fix some text, update code to v1.0.100 2025-09-12 20:39:21 +08:00
Caten
c10d2b733f More English localization 2025-09-12 16:49:40 +08:00
Caten
417cf7feef Remove remaining "fix-to-Chinese" commands 2025-09-12 12:56:28 +08:00
Caten
7b219facfe Update hangover, disable dxvk by default, update bootstrap package 2025-09-12 12:55:47 +08:00
Caten
ed3ec63212 Update hint text 2025-09-10 20:22:41 +08:00
Caten
8f26ed77e7 Update text and version 2025-09-10 17:51:29 +08:00
Caten
db4431d4c7 Add AVNC screen scale feature 2025-09-10 17:32:08 +08:00
Caten
0793f589f2 Update strings.xml 2025-09-09 22:18:38 +08:00
13 changed files with 372 additions and 108 deletions

View File

@@ -4,34 +4,36 @@
给所有安卓 9 以上 arm64 设备的“PC 应用引擎”平替。你可以在小小电脑上安装 PC 级 WPS、CAJ Viewer、亿图图示等软件。
Run Debian Bookworm with XFCE/LXQt/... on Android with just one click - optimized for Chinese users. This package comes preinstalled with the Fcitx Pinyin input method and doesn't require Termux.
To change the language in the container, simply run the "tmoe" command (this root filesystem was created using [tmoe](https://github.com/2moe/tmoe)). You'll need to remove the LANG=zh_CN.UTF-8 environment variable from the startup command (Control -> Advanced Settings -> Startup Command) when switching languages.
Run Debian Bookworm with XFCE, LXQt, or other desktop environments on Android—just with one click. Originally developed for Chinese users to run applications like WPS Office, it comes preinstalled with tools such as the Fcitx Pinyin input method. Please note that this app does not require Termux.
Note: Since version 1.0.23, English UI is supported, though some hint texts remain in Chinese.
To change the language inside the container, simply run the `tmoe` command, select “Manager” and navigate to the locale settings. The root filesystem was built using [tmoe](https://github.com/2moe/tmoe), so locale configuration is handled through it. You will also need to update the `LANG=zh_CN.UTF-8` environment variable in the startup command (go to Control → Advanced Settings → Startup Command) when switching to another language.
Note: English UI is supported since version 1.0.23, though some hint texts may still appear in Chinese.
As of version 1.0.100, the container will automatically switch to English if it detects that your device is not using Chinese.
## 特点
- 一键安装,即开即用
- 来自 kali-undercover 的 win10 主题(仅 xfce 版本),友好的界面
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img1.png)](https://github.com/Cateners/tiny_computer/blob/master/readme/img1.png)
![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img1.png)
- 提供常用软件的一键安装指令
- 提供常用软件的一键安装指令(点击图片可查看更多说明)
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img2.png)](https://github.com/Cateners/tiny_computer/blob/master/readme/img2.png)
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img2.png)](https://gitee.com/caten/tc-hints/blob/master/pool/solution.md)
- 可方便地改变屏幕缩放,不用担心屏幕过大或过小(仅 novnc)
- 可方便地改变屏幕缩放,不用担心屏幕过大或过小 (点击图片可查看更多说明)
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img3.gif)](https://github.com/Cateners/tiny_computer/blob/master/readme/img3.gif)
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img3.gif)](https://gitee.com/caten/tc-hints/blob/master/pool/scale.md)
- 便捷访问设备文件,或通过设备 SAF 访问软件文件
- 便捷访问设备文件,或通过设备 SAF 访问软件文件(点击图片可查看更多说明)
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img4.png)](https://github.com/Cateners/tiny_computer/blob/master/readme/img4.png)
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img4.png)](https://gitee.com/caten/tc-hints/blob/master/pool/fileaccess.md)
- 提供终端和众多可调节参数供高级用户使用
[![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img5.png)](https://github.com/Cateners/tiny_computer/blob/master/readme/img5.png)
![1](https://github.com/Cateners/tiny_computer/raw/master/readme/img5.png)
## 下载

View File

@@ -2,7 +2,7 @@
<resources>
<string name="tc_app_name">Tiny Computer</string>
<string name="tc_s9a_error_message">Terminal terminated abnormally with error code 9. This error is caused by Android 12+ system limiting the number of child processes and requires manual removal of the restriction.</string>
<string name="tc_s9a_error_message">Terminal terminated abnormally with signal 9. This error is caused by Android 12+ system limiting the number of child processes and requires manual removal of the restriction.</string>
<string name="tc_s9a_kaomoji">:(</string>
<string name="tc_s9a_solution_intro">You can use the following tool to fix:</string>
<string name="tc_s9a_solution_alternative">If the above tool cannot fix the issue, or if the device is a HarmonyOS device, please follow the tutorial below (requires a computer and data cable):</string>

147
build.ps1 Normal file
View File

@@ -0,0 +1,147 @@
param(
[Parameter(Mandatory=$true, ValueFromRemainingArguments=$true)]
[ValidateSet("xfce", "lxqt", "gxde")]
[string[]]$DesktopEnvs,
[string]$NameSuffix
)
# 设置路径
$SourceDir = "C:\Users\29513\Downloads"
$AssetsDir = "assets"
# 分割文件函数 - 使用xaa, xab, xac...命名
function Split-File {
param(
[string]$Path,
[long]$PartSizeBytes,
[string]$DestinationPath
)
$stream = [System.IO.File]::OpenRead($Path)
$buffer = New-Object byte[] $PartSizeBytes
$partNumber = 0
try {
while (($bytesRead = $stream.Read($buffer, 0, $buffer.Length)) -gt 0) {
# 生成类似xaa, xab, xac...的文件名
$partName = Get-SplitFileName $partNumber
$partPath = Join-Path $DestinationPath $partName
$partStream = [System.IO.File]::OpenWrite($partPath)
try {
$partStream.Write($buffer, 0, $bytesRead)
} finally {
$partStream.Close()
}
Write-Host "创建分片: $partName"
$partNumber++
}
} finally {
$stream.Close()
}
return $partNumber
}
# 生成split风格的文件名 (xaa, xab, xac, ..., xaz)
function Get-SplitFileName {
param([int]$index)
# 计算字母偏移量0-25对应a-z
$charOffset = $index % 26
# 将数字转换为对应的字母字符
$char = [char]([byte][char]'a' + $charOffset)
return "xa$char"
}
# 处理每个桌面环境
foreach ($DesktopEnv in $DesktopEnvs) {
Write-Host "`n开始处理 $DesktopEnv 桌面环境..." -ForegroundColor Green
# 设置文件路径
$TarFile = "debian-$DesktopEnv.tar.xz"
$SourcePath = Join-Path $SourceDir $TarFile
# 检查源文件是否存在
if (-not (Test-Path $SourcePath)) {
Write-Error "错误:找不到文件 $SourcePath"
continue
}
# 删除assets文件夹中已有的xa*文件
if (Test-Path $AssetsDir) {
Write-Host "正在清理assets文件夹中的旧文件..."
Get-ChildItem -Path $AssetsDir -Filter "xa*" | Remove-Item -Force
} else {
Write-Host "创建assets文件夹..."
New-Item -ItemType Directory -Path $AssetsDir | Out-Null
}
# 分割文件 (98MB = 98 * 1024 * 1024 = 102760448 bytes)
Write-Host "正在分割 $TarFile 文件..."
$partCount = Split-File -Path $SourcePath -PartSizeBytes 102760448 -DestinationPath $AssetsDir
Write-Host "文件分割完成,共创建 $partCount 个分片文件"
# 运行Flutter构建
Write-Host "正在运行Flutter构建..."
flutter build apk --target-platform android-arm64 --split-per-abi --obfuscate --split-debug-info=tiny_computer/sdi
if ($LASTEXITCODE -ne 0) {
Write-Error "错误Flutter构建失败"
continue
}
# 构建APK文件名
$ApkBaseName = "tiny-computer-$DesktopEnv"
if (-not [string]::IsNullOrEmpty($NameSuffix)) {
$ApkBaseName += "-$NameSuffix"
}
# 重命名APK和SHA1文件
$ApkSource = "build\app\outputs\flutter-apk\app-arm64-v8a-release.apk"
$Sha1Source = "build\app\outputs\flutter-apk\app-arm64-v8a-release.apk.sha1"
if (Test-Path $ApkSource) {
Rename-Item -Path $ApkSource -NewName "$ApkBaseName.apk"
Write-Host "已重命名APK文件: $ApkBaseName.apk"
} else {
Write-Error "错误找不到APK文件 $ApkSource"
continue
}
if (Test-Path $Sha1Source) {
Rename-Item -Path $Sha1Source -NewName "$ApkBaseName.apk.sha1"
Write-Host "已重命名SHA1文件: $ApkBaseName.apk.sha1"
} else {
Write-Warning "警告找不到SHA1文件 $Sha1Source"
}
Write-Host "$DesktopEnv 处理完成!" -ForegroundColor Green
}
Write-Host "`n所有桌面环境处理完成!" -ForegroundColor Cyan
# 既然是开源我认为应该把prompt开源出来才算毕竟这个脚本更像编译后的产物而不是源代码本身。
# 帮我写一个自动化脚本,做以下几件事:
# 1. 脚本所在目录是项目的根目录脚本应该运行在windows电脑上接收一个参数这个参数的值会是xfce, lxqt或gxde。
# 2. 在C:\Users\29513\Downloads文件夹有debian-xfce.tar.xzdebian-lxqt.tar.xz和debian-gxde.tar.xz需要根据之前的参数对应选择然后分成98MB的小份命名为xa*就像linux上的split -b 98M debian.tar.xz放到项目的assets文件夹。注意这个文件夹可能有之前残留的xa*文件需要先彻底删除这些xa*文件。
# 3. 然后在当前目录运行flutter build apk --target-platform android-arm64 --split-per-abi --obfuscate --split-debug-info=tiny_computer/sdi编译。
# 4. 在build\app\outputs\flutter-apk文件夹会有app-arm64-v8a-release.apk和app-arm64-v8a-release.apk.sha1两个文件需要重命名为tiny-computer-xfce.apk和tiny-computer-xfce.apk.sha1以xfce为例具体名称根据参数来定
# 直接写成一个ps1脚本行吗
# 请再添加一些功能首先可以传入多个选项比如传入xfce lxqt就可以自动进行这两个构建其实需要一个新参数允许在生成的apk名字加入后缀比如添加targetSdk35后缀就会生成tiny-computer-xfce-targetSdk35.apk和tiny-computer-xfce-targetSdk35.apk.sha1
# xa*文件的命名不对。要按照split命令默认的那样命名为xaaxabxac... 另外我确定分割后的文件数量不多不会超过xaz。
# Cannot convert value "97" to type "System.Char". Error: "Invalid cast from 'Decimal' to 'Char'."
# At C:\Users\29513\FlutterProjects\tiny_computer\build.ps1:52 char:5
# + $firstChar = [char](97 + [math]::Floor($index / 26)) # a-z
# + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# + CategoryInfo : InvalidArgument: (:) [], RuntimeException
# + FullyQualifiedErrorId : InvalidCastIConvertible

View File

@@ -22,6 +22,7 @@ echo "最新版本: $latest_version"
hangover_url="https://github.com/AndreRH/hangover/releases/download/hangover-${latest_version}/hangover_${latest_version}_debian12_bookworm_arm64.tar"
mirror_sites=(
"https://github.akams.cn/"
"https://gh.llkk.cc/"
"https://github.moeyy.xyz/"
"https://mirror.ghproxy.com/"
@@ -65,13 +66,6 @@ tar xvf dxvk-v*.tar.gz
mv dxvk-v*/x32/* /home/tiny/.wine/drive_c/windows/syswow64
mv dxvk-v*/arm64ec/* /home/tiny/.wine/drive_c/windows/system32
echo "自动配置 DLL 覆盖..."
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d8 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d9 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d10core /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d11 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v dxgi /d native /f >/dev/null 2>&1
echo "正在修复字体..."
regedit "Z:\\home\\tiny\\.local\\share\\tiny\\extra\\chn_fonts.reg" && wine reg delete "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes" /va /f

View File

@@ -4,10 +4,11 @@ echo "正在更新软件包..."
sudo apt update
sudo apt upgrade -y
hangover_url="https://github.com/AndreRH/hangover/releases/download/hangover-10.11/hangover_10.11_debian12_bookworm_arm64.tar"
latest_version="10.11"
hangover_url="https://github.com/AndreRH/hangover/releases/download/hangover-10.14/hangover_10.14_debian12_bookworm_arm64.tar"
latest_version="10.14"
mirror_sites=(
"https://github.akams.cn/"
"https://gh.llkk.cc/"
"https://github.moeyy.xyz/"
"https://mirror.ghproxy.com/"
@@ -51,13 +52,6 @@ tar xvf dxvk-v*.tar.gz
mv dxvk-v*/x32/* /home/tiny/.wine/drive_c/windows/syswow64
mv dxvk-v*/arm64ec/* /home/tiny/.wine/drive_c/windows/system32
echo "自动配置 DLL 覆盖..."
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d8 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d9 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d10core /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v d3d11 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v dxgi /d native /f >/dev/null 2>&1
echo "正在修复字体..."
regedit "Z:\\home\\tiny\\.local\\share\\tiny\\extra\\chn_fonts.reg" && wine reg delete "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes" /va /f

View File

@@ -1,3 +1,2 @@
synthetic-package: false
arb-dir: lib/l10n
template-arb-file: intl_en.arb

View File

@@ -33,7 +33,7 @@
"fixGetifaddrsPermission": "Fix getifaddrs permission on Android 13",
"fakeUOSSystem": "Pretend System as UOS",
"displaySettings": "Display Settings",
"avncAdvantages": "AVNC provides better control experience than noVNC:\nTouchpad controls, two-finger tap for keyboard, auto clipboard, picture-in-picture mode, etc. This is an experimental feature.",
"avncAdvantages": "AVNC provides better control experience than noVNC:\nTouchpad controls, two-finger tap for keyboard, auto clipboard, picture-in-picture mode, etc.",
"avncSettings": "AVNC Settings",
"aboutAVNC": "About AVNC",
"avncResolution": "AVNC Startup Resolution",
@@ -44,11 +44,11 @@
"save": "Save",
"applyOnNextLaunch": "Apply on next launch",
"useAVNCByDefault": "Use AVNC by default",
"termuxX11Advantages": "Termux:X11 provides faster performance than VNC with better compatibility in some cases.\nSupports DRI3 (enable in Graphics Acceleration) for significant performance boost.\nNow supports features like bidirectional clipboard.\nExperimental feature! If black screen occurs, try fully closing and restarting the app.",
"termuxX11Advantages": "Termux:X11 may provide faster speeds than VNC in certain scenarios.\n\nNote that Termux:X11 operates slightly differently from AVNC:\n- A two-finger tap acts as a right mouse click\n- Pressing the back button reveals the additional keyboard\n\nIf you encounter a black screen, try completely closing and restarting the application.",
"termuxX11Preferences": "Termux:X11 Preferences",
"useTermuxX11ByDefault": "Use Termux:X11 by default",
"disableVNC": "Disable VNC. Requires restart",
"hidpiAdvantages": "HiDPI support provides sharper display for high-resolution screens!\n\nNote:\nDisplay may appear too large - set appropriate resolution.\nSome apps may have display issues or slower rendering.",
"hidpiAdvantages": "One-click to enable HiDPI mode for clearer display... at the cost of reduced speed.",
"hidpiEnvVar": "HiDPI Environment Variables",
"hidpiSupport": "HiDPI Support",
"fileAccess": "File Access",
@@ -74,13 +74,13 @@
"installHangoverLatest": "Install Hangover Latest (may fail)",
"uninstallHangover": "Uninstall Hangover",
"clearWineData": "Clear Wine Data",
"wineCommandsHint": "Common Wine commands. Click to launch GUI and wait patiently.\n\nNote: DXVK is enabled by default. If the program crashes, try disabling it.\n\nTypical launch times:\nTiger T7510 6GB: over 1 minute\nSnapdragon 870 12GB: ~10 seconds",
"wineCommandsHint": "Common Wine commands. Click to launch GUI and wait patiently.\n\nTypical launch times:\nTiger T7510 6GB: over 1 minute\nSnapdragon 870 12GB: ~10 seconds",
"switchToJapanese": "Switch System to Japanese",
"userManual": "User Manual",
"openSourceLicenses": "Open Source Licenses",
"permissionUsage": "Permission Usage",
"privacyStatement": "\nThis app does not collect your private information.\n\nHowever, I cannot control behaviors of apps you install/use inside the container system (including via shortcut commands).\n\nRequested permissions are used for:\nFile permissions: accessing phone directories\nNotifications & accessibility: Required by Termux:X11",
"supportAuthor": "Support Author",
"supportAuthor": "Support Developers",
"recommendApp": "If you find it useful, please recommend to others!",
"projectUrl": "Project URL",
"commandEdit": "Command Edit",
@@ -98,14 +98,17 @@
"enterNumber": "Please enter a number",
"enterValidNumber": "Please enter a valid number",
"installingBootPackage": "Installing Boot Package",
"copyingContainerSystem": "Copying Container System",
"installingContainerSystem": "Installing Container System",
"copyingContainerSystem": "Copying System Files",
"installingContainerSystem": "Installing System Files",
"installationComplete": "Installation Complete",
"reinstallingBootPackage": "Reinstalling Boot Package",
"issueUrl": "Issue Report",
"faqUrl": "FAQ",
"solutionUrl": "Usage Guide",
"discussionUrl": "Discussion",
"firstLoadInstructions": "The first load may take about 5 to 10 minutes...\n\nNormally, the software will automatically redirect to the graphical interface after loading.\n\nIn the graphical interface:\n- Tap for left-click\n- Long press for right-click\n- Two-finger tap to open the keyboard\n- Two-finger swipe for mouse wheel\n\nPlease do not exit the software during installation.\n\nWhile waiting, you can click the button below to request permissions.\n\nMany folders in Tiny Computer (e.g., Downloads, Documents, Pictures) are bound to the corresponding device folders. Without these permissions, access to these folders will be denied.\n\nIf you don't need to access these folders, you can skip granting file permissions (but this may cause Firefox to fail when downloading files due to denied access to the Downloads folder).",
"updateRequest": "Please try to use the latest version. Visit the project address to check for the latest version."
"firstLoadInstructions": "The first load takes about 5 to 10 minutes... and does not require an internet connection.\n\nNormally, the software will automatically redirect to the graphical interface after loading.\n\nIn the graphical interface:\n- Tap for left-click\n- Long press for right-click\n- Two-finger tap to open the keyboard\n- Two-finger swipe for mouse wheel\n\nPlease do not exit the software during installation.\n\nWhile waiting, you can click the button below to request permissions.\n\nMany folders in Tiny Computer (e.g., Downloads, Documents, Pictures) are bound to the corresponding device folders. Without these permissions, access to these folders will be denied.\n\nIf you don't need to access these folders, you can skip granting file permissions (but this may cause Firefox to fail when downloading files due to denied access to the Downloads folder).",
"updateRequest": "Please try to use the latest version. Visit the project address to check for the latest version.",
"avncScreenResize": "Adaptive Screen Size",
"avncResizeFactor": "Screen Scaling Ratio",
"avncResizeFactorValue": "Current scaling is"
}

View File

@@ -33,7 +33,7 @@
"fixGetifaddrsPermission": "修复安卓13设备getifaddrs无权限",
"fakeUOSSystem": "伪装系统为UOS",
"displaySettings": "显示设置",
"avncAdvantages": "AVNC可以带来相比noVNC更好的操控体验\n如触摸板触控双指单击弹出键盘自动剪切板画中画模式等等。这是一个实验性功能。",
"avncAdvantages": "AVNC可以带来相比noVNC更好的操控体验\n如触摸板触控双指单击弹出键盘自动剪切板画中画模式等等。",
"avncSettings": "AVNC设置",
"aboutAVNC": "关于AVNC",
"avncResolution": "AVNC启动时分辨率设置",
@@ -44,11 +44,11 @@
"applyOnNextLaunch": "下次启动时生效",
"save": "保存",
"useAVNCByDefault": "默认使用AVNC",
"termuxX11Advantages": "Termux:X11可以带来比VNC更快的速度,某些情况下兼容性也会更好。\n支持使用DRI3需在图形加速中开启可以带来相当大的性能提升。\n随着版本的迭代Termux:X11如今也支持了双向剪切板等功能。\n这是一个实验性功能如果黑屏,请尝试彻底关闭本应用再重新启动。",
"termuxX11Advantages": "Termux:X11某些情况下可以带来比VNC更快的速度。\n\n注意Termux:X11的操作与AVNC略有不同。\n- 双指点击为鼠标右键\n- 返回弹出小键盘\n\n如果黑屏,请尝试彻底关闭本应用再重新启动。",
"termuxX11Preferences": "Termux:X11偏好设置",
"useTermuxX11ByDefault": "默认使用Termux:X11",
"disableVNC": "不使用VNC。重启生效",
"hidpiAdvantages": "高分辨率支持可以为拥有高分辨率屏幕的设备带来更高清的体验!\n\n注意\n选项开启后显示会变得很大请设置一个合适的分辨率。\n\n一些软件可能会存在显示问题或者显示速度变慢。",
"hidpiAdvantages": "一键开启高清模式,显示更清晰的同时...速度变慢。",
"hidpiEnvVar": "HiDPI环境变量",
"hidpiSupport": "高分辨率支持",
"fileAccess": "文件访问",
@@ -74,7 +74,7 @@
"installHangoverLatest": "安装Hangover最新版可能出错",
"uninstallHangover": "卸载Hangover",
"clearWineData": "清空Wine数据",
"wineCommandsHint": "Wine的常用指令。点击后前往图形界面耐心等待。\n\nDXVK默认为开启状态如程序崩溃可尝试关闭\n\n任意程序启动参考时间:\n虎贲T7510 6GB 超过一分钟\n骁龙870 12GB 约10秒\n",
"wineCommandsHint": "Wine的常用指令。点击后前往图形界面耐心等待。\n\n任意程序启动参考时间\n虎贲T7510 6GB 超过一分钟\n骁龙870 12GB 约10秒\n",
"switchToJapanese": "切换系统到日语",
"userManual": "使用说明",
"openSourceLicenses": "开源许可",
@@ -106,6 +106,9 @@
"faqUrl": "常见问题",
"solutionUrl": "典型场景使用指南",
"discussionUrl": "论坛与讨论",
"firstLoadInstructions": "第一次加载大概需要5到10分钟...\n\n正常情况下加载完成后软件会自动跳转到图形界面。\n\n在图形界面时\n- 点击为鼠标左键\n- 长按为鼠标右键\n- 双指点击可弹出键盘\n- 双指划动为鼠标滚轮\n\n请不要在安装时退出软件。\n\n在等待时可以点击下面的按钮申请一下权限。\n\n小小电脑的许多文件夹比如下载、文档、图片等等都和设备的对应文件夹绑定如果不授予这些权限会导致这些文件夹无权访问。\n\n但如果你不需要访问这些文件夹也可以不授予文件权限可能导致火狐浏览器下载文件失败因为无权访问下载文件夹。",
"updateRequest": "请尽量使用最新版本。前往项目地址可查看最新版本。"
"firstLoadInstructions": "第一次加载大概需要5到10分钟...并且不需要网络。\n\n正常情况下加载完成后软件会自动跳转到图形界面。\n\n在图形界面时\n- 点击为鼠标左键\n- 长按为鼠标右键\n- 双指点击可弹出键盘\n- 双指划动为鼠标滚轮\n\n请不要在安装时退出软件。\n\n在等待时可以点击下面的按钮申请一下权限。\n\n小小电脑的许多文件夹比如下载、文档、图片等等都和设备的对应文件夹绑定如果不授予这些权限会导致这些文件夹无权访问。\n\n但如果你不需要访问这些文件夹也可以不授予文件权限可能导致火狐浏览器下载文件失败因为无权访问下载文件夹。",
"updateRequest": "请尽量使用最新版本。前往项目地址可查看最新版本。",
"avncScreenResize": "自适应屏幕尺寸",
"avncResizeFactor": "屏幕缩放比",
"avncResizeFactorValue": "当前缩放为"
}

View File

@@ -33,7 +33,7 @@
"fixGetifaddrsPermission": "修復 Android 13 裝置 getifaddrs 無權限",
"fakeUOSSystem": "偽裝系統為 UOS",
"displaySettings": "顯示設定",
"avncAdvantages": "AVNC 可帶來比 noVNC 更好的操作體驗;如觸控板觸控、雙指單擊喚出鍵盤、自動剪貼簿、畫中畫模式等。這是一個實驗性功能。",
"avncAdvantages": "AVNC 可帶來比 noVNC 更好的操作體驗;如觸控板觸控、雙指單擊喚出鍵盤、自動剪貼簿、畫中畫模式等。",
"avncSettings": "AVNC 設定",
"aboutAVNC": "關於 AVNC",
"avncResolution": "AVNC 啟動時解析度設定",
@@ -44,11 +44,11 @@
"applyOnNextLaunch": "下次啟動時生效",
"save": "儲存",
"useAVNCByDefault": "預設使用 AVNC",
"termuxX11Advantages": "Termux:X11 可帶來比 VNC 更快的速度,有時兼容性也更好。\n支援使用 DRI3需在圖形加速中開啟可大幅提升效能。",
"termuxX11Advantages": "Termux:X11 在某些情況下可能比 VNC 提供更快的速度。\n\n請注意 Termux:X11 的操作與 AVNC 略有不同:\n- 雙指點擊相當於滑鼠右鍵\n- 返回鍵可彈出小鍵盤\n若出現黑屏請嘗試完全關閉本應用後重新啟動。",
"termuxX11Preferences": "Termux:X11 偏好設定",
"useTermuxX11ByDefault": "預設使用 Termux:X11",
"disableVNC": "停用 VNC。重啟生效",
"hidpiAdvantages": "高解析度支援可讓有高解析度螢幕的裝置獲得更清晰的體驗!\n\n注意\n啟用後顯示會變很大請設定合適的解析度。",
"hidpiAdvantages": "一鍵開啟高清模式,顯示更清晰的同時...速度會變慢。",
"hidpiEnvVar": "HiDPI 環境變數",
"hidpiSupport": "高解析度支援",
"fileAccess": "檔案存取",
@@ -74,7 +74,7 @@
"installHangoverLatest": "安裝 Hangover 最新版(可能有錯誤)",
"uninstallHangover": "解除安裝 Hangover",
"clearWineData": "清除 Wine 資料",
"wineCommandsHint": "Wine 常用指令。點擊後進入圖形介面,請耐心等候。\n\nDXVK預設為開啟狀態如程式崩潰可嘗試關閉\n\n不同裝置啟動程式參考時間:\n虎賁 T7510 6GB 超過一分鐘\n驍龍 870 12GB 約 10 秒\n",
"wineCommandsHint": "Wine 常用指令。點擊後進入圖形介面,請耐心等候。\n\n不同裝置啟動程式參考時間\n虎賁 T7510 6GB 超過一分鐘\n驍龍 870 12GB 約 10 秒\n",
"switchToJapanese": "切換系統為日語",
"userManual": "使用說明",
"openSourceLicenses": "開源授權",
@@ -106,6 +106,9 @@
"faqUrl": "常見問題",
"solutionUrl": "操作指南",
"discussionUrl": "討論",
"firstLoadInstructions": "第一次載大概需要5到10分鐘...\n\n正常情況下載入完成後軟體會自動跳轉到圖形介面。\n\n在圖形介面時\n- 點擊為滑鼠左鍵\n- 長按為滑鼠右鍵\n- 雙指點擊可彈出鍵盤\n- 雙指滑動為滑鼠滾輪\n\n請不要在安裝時退出軟體。\n\n在等待時可以點擊下面的按鈕申請權限。\n\n小小電腦的許多資料夾比如下載、文件、圖片等等都和裝置的這些資料夾綁定如果不授予這些權限會導致這些資料夾無權存取。\n\n但如果你不需要存取這些資料夾也可以不授予檔案權限可能導致火狐瀏覽器下載檔案失敗因為無權存取下載資料夾。",
"updateRequest": "請盡量使用最新版本。前往專案網址查看最新版本。"
"firstLoadInstructions": "第一次載大概需要5到10分鐘...並且不需要網絡。\n\n正常情況下載入完成後軟體會自動跳轉到圖形介面。\n\n在圖形介面時\n- 點擊為滑鼠左鍵\n- 長按為滑鼠右鍵\n- 雙指點擊可彈出鍵盤\n- 雙指滑動為滑鼠滾輪\n\n請不要在安裝時退出軟體。\n\n在等待時可以點擊下面的按鈕申請權限。\n\n小小電腦的許多資料夾比如下載、文件、圖片等等都和裝置的這些資料夾綁定如果不授予這些權限會導致這些資料夾無權存取。\n\n但如果你不需要存取這些資料夾也可以不授予檔案權限可能導致火狐瀏覽器下載檔案失敗因為無權存取下載資料夾。",
"updateRequest": "請盡量使用最新版本。前往專案網址查看最新版本。",
"avncScreenResize": "自適應螢幕尺寸",
"avncResizeFactor": "螢幕縮放比",
"avncResizeFactorValue": "目前縮放為"
}

View File

@@ -172,6 +172,8 @@ class _SettingPageState extends State<SettingPage> {
final List<bool> _expandState = [false, false, false, false, false, false];
double _avncScaleFactor = Util.getGlobal("avncScaleFactor") as double;
@override
Widget build(BuildContext context) {
return ExpansionPanelList(
@@ -195,7 +197,7 @@ class _SettingPageState extends State<SettingPage> {
Navigator.of(context).pop();
}, child: Text(AppLocalizations.of(context)!.cancel)),
TextButton(onPressed:() async {
await Util.setCurrentProp("boot", D.boot);
await Util.setCurrentProp("boot", Localizations.localeOf(context).languageCode == 'zh' ? D.boot : D.boot.replaceFirst('LANG=zh_CN.UTF-8', 'LANG=en_US.UTF-8').replaceFirst('公共', 'Public').replaceFirst('图片', 'Pictures').replaceFirst('音乐', 'Music').replaceFirst('视频', 'Videos').replaceFirst('下载', 'Downloads').replaceFirst('文档', 'Documents').replaceFirst('照片', 'Photos'));
G.bootTextChange.value = !G.bootTextChange.value;
if (!context.mounted) return;
Navigator.of(context).pop();
@@ -337,6 +339,27 @@ class _SettingPageState extends State<SettingPage> {
headerBuilder: ((context, isExpanded) {
return ListTile(title: Text(AppLocalizations.of(context)!.displaySettings));
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
const SizedBox.square(dimension: 16),
Text(AppLocalizations.of(context)!.hidpiAdvantages),
const SizedBox.square(dimension: 16),
TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultHidpiOpt") as String, decoration: InputDecoration(border: OutlineInputBorder(), labelText: AppLocalizations.of(context)!.hidpiEnvVar),
onChanged: (value) async {
await G.prefs.setString("defaultHidpiOpt", value);
},
),
const SizedBox.square(dimension: 8),
SwitchListTile(title: Text(AppLocalizations.of(context)!.hidpiSupport), subtitle: Text(AppLocalizations.of(context)!.applyOnNextLaunch), value: Util.getGlobal("isHidpiEnabled") as bool, onChanged:(value) {
G.prefs.setBool("isHidpiEnabled", value);
// 开启高分辨率后把缩放比调为原来的两倍 +log4(2) = 0.5
_avncScaleFactor += value ? 0.5 : -0.5;
_avncScaleFactor = _avncScaleFactor.clamp(-1, 1);
G.prefs.setDouble("avncScaleFactor", _avncScaleFactor);
// Termux:X11 并不是设置缩放比例本身,而是倍率
X11Flutter.setX11ScaleFactor(value ? 0.5 : 2.0);
setState(() {});
},),
const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8),
const SizedBox.square(dimension: 16),
Text(AppLocalizations.of(context)!.avncAdvantages),
const SizedBox.square(dimension: 16),
@@ -347,7 +370,7 @@ class _SettingPageState extends State<SettingPage> {
OutlinedButton(style: D.commandButtonStyle, child: Text(AppLocalizations.of(context)!.aboutAVNC), onPressed: () async {
await AvncFlutter.launchAboutPage();
}),
OutlinedButton(style: D.commandButtonStyle, child: Text(AppLocalizations.of(context)!.avncResolution), onPressed: () async {
OutlinedButton(style: D.commandButtonStyle, onPressed: Util.getGlobal("avncResizeDesktop") as bool ? null : () async {
final s = WidgetsBinding.instance.platformDispatcher.views.first.physicalSize;
final w0 = max(s.width, s.height);
final h0 = min(s.width, s.height);
@@ -388,13 +411,44 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
}, child: Text(AppLocalizations.of(context)!.save)),
]);
});
}),
}, child: Text(AppLocalizations.of(context)!.avncResolution)),
]),
const SizedBox.square(dimension: 8),
SwitchListTile(title: Text(AppLocalizations.of(context)!.useAVNCByDefault), subtitle: Text(AppLocalizations.of(context)!.applyOnNextLaunch), value: Util.getGlobal("useAvnc") as bool, onChanged:(value) {
G.prefs.setBool("useAvnc", value);
setState(() {});
},),
const SizedBox.square(dimension: 8),
SwitchListTile(title: Text(AppLocalizations.of(context)!.avncScreenResize), value: Util.getGlobal("avncResizeDesktop") as bool, onChanged:(value) {
G.prefs.setBool("avncResizeDesktop", value);
setState(() {});
},),
const SizedBox.square(dimension: 8),
ListTile(
title: Text(AppLocalizations.of(context)!.avncResizeFactor),
onTap: () {},
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8),
Text('${AppLocalizations.of(context)!.avncResizeFactorValue} ${pow(4, _avncScaleFactor).toStringAsFixed(2)}x'),
SizedBox(height: 12),
Slider(
value: _avncScaleFactor,
min: -1,
max: 1,
divisions: 96,
onChangeEnd: (double value) {
G.prefs.setDouble("avncScaleFactor", value);
},
onChanged: Util.getGlobal("avncResizeDesktop") as bool ? (double value) {
_avncScaleFactor = value;
setState(() {});
} : null,
),
],
),
),
const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8),
const SizedBox.square(dimension: 16),
@@ -414,21 +468,6 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
setState(() {});
},),
const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8),
const SizedBox.square(dimension: 16),
Text(AppLocalizations.of(context)!.hidpiAdvantages),
const SizedBox.square(dimension: 16),
TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultHidpiOpt") as String, decoration: InputDecoration(border: OutlineInputBorder(), labelText: AppLocalizations.of(context)!.hidpiEnvVar),
onChanged: (value) async {
await G.prefs.setString("defaultHidpiOpt", value);
},
),
const SizedBox.square(dimension: 8),
SwitchListTile(title: Text(AppLocalizations.of(context)!.hidpiSupport), subtitle: Text(AppLocalizations.of(context)!.applyOnNextLaunch), value: Util.getGlobal("isHidpiEnabled") as bool, onChanged:(value) {
G.prefs.setBool("isHidpiEnabled", value);
setState(() {});
},),
const SizedBox.square(dimension: 16),
],))),
ExpansionPanel(
isExpanded: _expandState[3],
@@ -514,7 +553,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
Text(AppLocalizations.of(context)!.hangoverDescription),
const SizedBox.square(dimension: 8),
Wrap(alignment: WrapAlignment.center, spacing: 4.0, runSpacing: 4.0, children: [
OutlinedButton(style: D.commandButtonStyle, child: Text("${AppLocalizations.of(context)!.installHangoverStable}10.11"), onPressed: () async {
OutlinedButton(style: D.commandButtonStyle, child: Text("${AppLocalizations.of(context)!.installHangoverStable}10.14"), onPressed: () async {
Util.termWrite("bash ~/.local/share/tiny/extra/install-hangover-stable");
G.pageIndex.value = 0;
}),
@@ -536,14 +575,24 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""");
const SizedBox.square(dimension: 16),
Text(AppLocalizations.of(context)!.wineCommandsHint),
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: () {
Util.termWrite("${e.value["command"]!} &");
G.pageIndex.value = 0;
});
}
).toList()),
Wrap(
alignment: WrapAlignment.center,
spacing: 4.0,
runSpacing: 4.0,
children: (Localizations.localeOf(context).languageCode == 'zh'
? D.wineCommands
: D.wineCommands4En
).asMap().entries.map<Widget>((e) {
return OutlinedButton(
style: D.commandButtonStyle,
child: Text(e.value["name"]!),
onPressed: () {
Util.termWrite("${e.value["command"]!} &");
G.pageIndex.value = 0;
},
);
}).toList(),
),
const SizedBox.square(dimension: 16),
const Divider(height: 2, indent: 8, endIndent: 8),
const SizedBox.square(dimension: 16),
@@ -1220,7 +1269,7 @@ class _FastCommandsState extends State<FastCommands> {
Navigator.of(context).pop();
}, child: Text(AppLocalizations.of(context)!.cancel)),
TextButton(onPressed:() async {
await Util.setCurrentProp("commands", D.commands);
await Util.setCurrentProp("commands", Localizations.localeOf(context).languageCode == 'zh' ? D.commands : D.commands4En);
setState(() {});
if (!context.mounted) return;
Navigator.of(context).pop();
@@ -1247,7 +1296,9 @@ class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
_initializeWorkflow();
Future.delayed(Duration.zero,() {
_initializeWorkflow();
});
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: []);
}

View File

@@ -92,6 +92,8 @@ class Util {
//bool isHidpiEnabled = false 是否开启高分辨率
//bool isJpEnabled = false 是否切换系统到日语
//bool useAvnc = false 是否默认使用AVNC
//bool avncResizeDesktop = true 是否默认AVNC按当前屏幕大小调整分辨率
//double avncScaleFactor = -0.5 AVNC在当前屏幕大小的基础上调整缩放的比例。范围-1~1对应比例4^-1~4^1
//String defaultHidpiOpt 默认HiDPI环境变量
//? int bootstrapVersion: 启动包版本
//String[] containersInfo: 所有容器信息(json)
@@ -120,6 +122,8 @@ class Util {
case "isHidpiEnabled" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
case "isJpEnabled" : 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 "avncResizeDesktop" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(true);
case "avncScaleFactor" : return b ? G.prefs.getDouble(key)!.clamp(-1.0, 1.0) : (value){G.prefs.setDouble(key, value); return value;}(-0.5);
case "useX11" : 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;}("--use-egl-surfaceless --use-gles --socket-path=\$CONTAINER_DIR/tmp/.virgl_test");
@@ -208,10 +212,10 @@ class Util {
while (true) {
bool isReady = await isXServerReady(host, port);
await Future.delayed(Duration(seconds: 1));
if (isReady) {
return;
}
await Future.delayed(Duration(seconds: 1));
}
}
@@ -352,7 +356,7 @@ class D {
];
//默认快捷指令
static const commands = [{"name":"检查更新并升级", "command":"sudo dpkg --configure -a && sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y && sudo localedef -c -i zh_CN -f UTF-8 zh_CN.UTF-8"},
static const commands = [{"name":"检查更新并升级", "command":"sudo dpkg --configure -a && sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y"},
{"name":"查看系统信息", "command":"neofetch -L && neofetch --off"},
{"name":"清屏", "command":"clear"},
{"name":"中断任务", "command":"\x03"},
@@ -383,6 +387,30 @@ rm /tmp/wps.deb"""},
{"name":"???", "command":"timeout 8 cmatrix"}
];
//默认快捷指令,英文版本
static const commands4En = [{"name":"Update Packages", "command":"sudo dpkg --configure -a && sudo apt update && sudo apt full-upgrade -y && sudo apt autoremove -y"},
{"name":"System Info", "command":"neofetch -L && neofetch --off"},
{"name":"Clear", "command":"clear"},
{"name":"Interrupt", "command":"\x03"},
{"name":"Install Painting Program Krita", "command":"sudo apt update && sudo apt install -y krita krita-l10n"},
{"name":"Uninstall Krita", "command":"sudo apt autoremove --purge -y krita krita-l10n"},
{"name":"Install KDE Non-Linear Video Editor", "command":"sudo apt update && sudo apt install -y kdenlive"},
{"name":"Uninstall Kdenlive", "command":"sudo apt autoremove --purge -y kdenlive"},
{"name":"Install LibreOffice", "command":"sudo apt update && sudo apt install -y libreoffice"},
{"name":"Uninstall LibreOffice", "command":"sudo apt autoremove --purge -y libreoffice"},
{"name":"Install WPS", "command":r"""cat << 'EOF' | sh && sudo dpkg --configure -a && sudo apt update && sudo apt install -y /tmp/wps.deb
wget https://github.com/tiny-computer/third-party-archives/releases/download/archives/wps-office_11.1.0.11720_arm64.deb -O /tmp/wps.deb
EOF
rm /tmp/wps.deb"""},
{"name":"Uninstall WPS", "command":"sudo apt autoremove --purge -y wps-office"},
{"name":"Install EdrawMax", "command":"""wget https://cc-download.wondershare.cc/business/prd/edrawmax_13.1.0-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 && sudo sed -i 's/<Language V="cn"\\/>/<Language V="en"\\/>/g' /opt/apps/edrawmax/config/settings.xml; rm /tmp/edraw.deb"""},
{"name":"Uninstall EdrawMax", "command":"sudo apt autoremove --purge -y edrawmax libldap-2.4-2"},
{"name":"Enable Recycle Bin", "command":"sudo apt update && sudo apt install -y gvfs && echo 'Restart the app to use Recycle Bin.'"},
{"name":"Clean Package Cache", "command":"sudo apt clean"},
{"name":"Power Off", "command":"stopvnc\nexit\nexit"},
{"name":"???", "command":"timeout 8 cmatrix"}
];
//默认wine快捷指令
static const wineCommands = [{"name":"Wine配置", "command":"winecfg"},
{"name":"修复方块字", "command":"regedit Z:\\\\home\\\\tiny\\\\.local\\\\share\\\\tiny\\\\extra\\\\chn_fonts.reg && wine reg delete \"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes\" /va /f"},
@@ -408,6 +436,31 @@ WINEDLLOVERRIDES="d3d8=b,d3d9=b,d3d10core=b,d3d11=b,dxgi=b" wine reg add 'HKEY_C
{"name":"强制关闭Wine", "command":"wineserver -k"}
];
//默认wine快捷指令英文版本
static const wineCommands4En = [{"name":"Wine Configuration", "command":"winecfg"},
{"name":"Fix CJK Characters", "command":"regedit Z:\\\\home\\\\tiny\\\\.local\\\\share\\\\tiny\\\\extra\\\\chn_fonts.reg && wine reg delete \"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes\" /va /f"},
{"name":"Start Menu Dir", "command":"wine explorer \"C:\\\\ProgramData\\\\Microsoft\\\\Windows\\\\Start Menu\\\\Programs\""},
{"name":"Enable DXVK", "command":"""WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d8 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d9 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d10core /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d11 /d native /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=n,d3d9=n,d3d10core=n,d3d11=n,dxgi=n" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v dxgi /d native /f >/dev/null 2>&1"""},
{"name":"Disable DXVK", "command":"""WINEDLLOVERRIDES="d3d8=b,d3d9=b,d3d10core=b,d3d11=b,dxgi=b" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d8 /d builtin /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=b,d3d9=b,d3d10core=b,d3d11=b,dxgi=b" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d9 /d builtin /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=b,d3d9=b,d3d10core=b,d3d11=b,dxgi=b" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d10core /d builtin /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=b,d3d9=b,d3d10core=b,d3d11=b,dxgi=b" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v d3d11 /d builtin /f >/dev/null 2>&1
WINEDLLOVERRIDES="d3d8=b,d3d9=b,d3d10core=b,d3d11=b,dxgi=b" wine reg add 'HKEY_CURRENT_USER\\Software\\Wine\\DllOverrides' /v dxgi /d builtin /f >/dev/null 2>&1"""},
{"name":"Explorer", "command":"wine explorer"},
{"name":"Notepad", "command":"notepad"},
{"name":"Minesweeper", "command":"winemine"},
{"name":"Regedit", "command":"regedit"},
{"name":"Control Panel", "command":"wine control"},
{"name":"File Manager", "command":"winefile"},
{"name":"Task Manager", "command":"wine taskmgr"},
{"name":"Internet Explorer", "command":"wine iexplore"},
{"name":"Kill Wine Process", "command":"wineserver -k"}
];
//默认小键盘
static const termCommands = [
{"name": "Esc", "key": TerminalKey.escape},
@@ -534,7 +587,7 @@ ln -sf ../applib/libexec_tar.so \$DATA_DIR/bin/tar
ln -sf ../applib/libexec_virgl_test_server.so \$DATA_DIR/bin/virgl_test_server
ln -sf ../applib/libexec_getifaddrs_bridge_server.so \$DATA_DIR/bin/getifaddrs_bridge_server
ln -sf ../applib/libexec_pulseaudio.so \$DATA_DIR/bin/pulseaudio
ln -sf ../applib/libbusybox.so \$DATA_DIR/lib/libbusybox.so.1.36.1
ln -sf ../applib/libbusybox.so \$DATA_DIR/lib/libbusybox.so.1.37.0
ln -sf ../applib/libtalloc.so \$DATA_DIR/lib/libtalloc.so.2
ln -sf ../applib/libvirglrenderer.so \$DATA_DIR/lib/libvirglrenderer.so
ln -sf ../applib/libepoxy.so \$DATA_DIR/lib/libepoxy.so
@@ -553,10 +606,10 @@ chmod 1777 tmp
//初次启动要做的事情
static Future<void> initForFirstTime() async {
//首先设置bootstrap
G.updateText.value = "正在安装引导包";
G.updateText.value = AppLocalizations.of(G.homePageStateContext)!.installingBootPackage;
await setupBootstrap();
G.updateText.value = "正在复制容器系统";
G.updateText.value = AppLocalizations.of(G.homePageStateContext)!.copyingContainerSystem;
//存放容器的文件夹0和存放硬链接的文件夹.l2s
Util.createDirFromString("${G.dataPath}/containers/0/.l2s");
//这个是容器rootfs被split命令分成了xa*放在assets里
@@ -565,7 +618,7 @@ chmod 1777 tmp
await Util.copyAsset("assets/$name", "${G.dataPath}/$name");
}
//-J
G.updateText.value = "正在安装容器系统";
G.updateText.value = AppLocalizations.of(G.homePageStateContext)!.installingContainerSystem;
await Util.execute(
"""
export DATA_DIR=${G.dataPath}
@@ -595,18 +648,19 @@ cat tmp3 | while read -r group_name group_id; do
fi
done
\$DATA_DIR/bin/busybox rm -rf xa* tmp1 tmp2 tmp3
${Localizations.localeOf(G.homePageStateContext).languageCode == 'zh' ? "" : "echo 'LANG=en_US.UTF-8' > \$CONTAINER_DIR/usr/local/etc/tmoe-linux/locale.txt"}
""");
//一些数据初始化
//$DATA_DIR是数据文件夹, $CONTAINER_DIR是容器根目录
//Termux:X11的启动命令并不在这里面而是写死了。这下成💩山代码了:P
await G.prefs.setStringList("containersInfo", ["""{
"name":"Debian Bookworm",
"boot":"${D.boot}",
"boot":"${Localizations.localeOf(G.homePageStateContext).languageCode == 'zh' ? D.boot : D.boot.replaceFirst('LANG=zh_CN.UTF-8', 'LANG=en_US.UTF-8').replaceFirst('公共', 'Public').replaceFirst('图片', 'Pictures').replaceFirst('音乐', 'Music').replaceFirst('视频', 'Videos').replaceFirst('下载', 'Downloads').replaceFirst('文档', 'Documents').replaceFirst('照片', 'Photos')}",
"vnc":"startnovnc &",
"vncUrl":"http://localhost:36082/vnc.html?host=localhost&port=36082&autoconnect=true&resize=remote&password=12345678",
"commands":${jsonEncode(D.commands)}
"commands":${jsonEncode(Localizations.localeOf(G.homePageStateContext).languageCode == 'zh' ? D.commands : D.commands4En)}
}"""]);
G.updateText.value = "安装完成";
G.updateText.value = AppLocalizations.of(G.homePageStateContext)!.installationComplete;
}
static Future<void> initData() async {
@@ -630,13 +684,21 @@ done
final String h = (min(s.width, s.height) * 0.75).round().toString();
G.postCommand = """sed -i -E "s@(geometry)=.*@\\1=${w}x${h}@" /etc/tigervnc/vncserver-config-tmoe
sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)""";
if (Localizations.localeOf(G.homePageStateContext).languageCode != 'zh') {
G.postCommand += "\nlocaledef -c -i en_US -f UTF-8 en_US.UTF-8";
// For English users, assume they need to enable terminal write
await G.prefs.setBool("isTerminalWriteEnabled", true);
await G.prefs.setBool("isTerminalCommandsEnabled", true);
await G.prefs.setBool("isStickyKey", false);
await G.prefs.setBool("wakelock", true);
}
await G.prefs.setBool("getifaddrsBridge", (await DeviceInfoPlugin().androidInfo).version.sdkInt >= 31);
}
G.currentContainer = Util.getGlobal("defaultContainer") as int;
//是否需要重新安装引导包?
if (Util.getGlobal("reinstallBootstrap")) {
G.updateText.value = "正在重新安装引导包";
G.updateText.value = AppLocalizations.of(G.homePageStateContext)!.reinstallingBootPackage;
await setupBootstrap();
G.prefs.setBool("reinstallBootstrap", false);
}
@@ -729,10 +791,14 @@ export PROOT_LOADER=\$DATA_DIR/applib/libproot-loader.so
export PROOT_LOADER_32=\$DATA_DIR/applib/libproot-loader32.so
${Util.getCurrentProp("boot")}
${G.postCommand}
${(Util.getGlobal("autoLaunchVnc") as bool)?((Util.getGlobal("useX11") as bool)?"""mkdir -p "\$HOME/.vnc" && bash /etc/X11/xinit/Xsession &> "\$HOME/.vnc/x.log" &""":Util.getCurrentProp("vnc")):""}
clear""");
}
static Future<void> launchGUIBackend() async {
Util.termWrite((Util.getGlobal("autoLaunchVnc") as bool)?((Util.getGlobal("useX11") as bool)?"""mkdir -p "\$HOME/.vnc" && bash /etc/X11/xinit/Xsession &> "\$HOME/.vnc/x.log" &""":Util.getCurrentProp("vnc")):"");
Util.termWrite("clear");
}
static Future<void> waitForConnection() async {
await retry(
// Make a GET request
@@ -771,7 +837,7 @@ clear""");
}
static Future<void> launchAvnc() async {
await AvncFlutter.launchUsingUri(Util.getCurrentProp("vncUri") as String);
await AvncFlutter.launchUsingUri(Util.getCurrentProp("vncUri") as String, resizeRemoteDesktop: Util.getGlobal("avncResizeDesktop") as bool, resizeRemoteDesktopScaleFactor: pow(4, Util.getGlobal("avncScaleFactor") as double).toDouble());
}
static Future<void> launchXServer() async {
@@ -791,9 +857,11 @@ clear""");
if (Util.getGlobal("autoLaunchVnc") as bool) {
if (G.wasX11Enabled) {
await Util.waitForXServer();
launchGUIBackend();
launchX11();
return;
}
launchGUIBackend();
waitForConnection().then((value) => G.wasAvncEnabled?launchAvnc():launchBrowser());
}
}

View File

@@ -21,8 +21,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "73f6672f955ae89606336e0a018d4958af3570e6"
resolved-ref: "73f6672f955ae89606336e0a018d4958af3570e6"
ref: "4008565259f88fe4613b885979f79e439bc5a420"
resolved-ref: "4008565259f88fe4613b885979f79e439bc5a420"
url: "https://github.com/tiny-computer/avnc_flutter.git"
source: git
version: "0.0.1"
@@ -202,26 +202,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
version: "11.0.1"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: transitive
description:
@@ -543,10 +543,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "0.7.6"
typed_data:
dependency: transitive
description:
@@ -623,10 +623,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.2.0"
vm_service:
dependency: transitive
description:
@@ -711,8 +711,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "778ae0873d9bf953d1fdbbd6bc4937ccf1020bb5"
resolved-ref: "778ae0873d9bf953d1fdbbd6bc4937ccf1020bb5"
ref: "3b92b515b1ebc32c93e18e8b3a2983656713e4dd"
resolved-ref: "3b92b515b1ebc32c93e18e8b3a2983656713e4dd"
url: "https://github.com/tiny-computer/x11_flutter.git"
source: git
version: "0.0.1"

View File

@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# 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.99+20250831
version: 1.0.100+20250912
environment:
sdk: '>=3.1.0 <4.0.0'
@@ -50,11 +50,11 @@ dependencies:
x11_flutter:
git:
url: https://github.com/tiny-computer/x11_flutter.git
ref: 778ae0873d9bf953d1fdbbd6bc4937ccf1020bb5
ref: 3b92b515b1ebc32c93e18e8b3a2983656713e4dd
avnc_flutter:
git:
url: https://github.com/tiny-computer/avnc_flutter.git
ref: 73f6672f955ae89606336e0a018d4958af3570e6
ref: 4008565259f88fe4613b885979f79e439bc5a420
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.