diff --git a/lib/main.dart b/lib/main.dart index a269dc5..517778e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -39,8 +39,6 @@ import 'package:xterm/xterm.dart'; //import 'package:xterm/flutter.dart'; import 'package:tiny_computer/workflow.dart'; -import 'package:unity_ads_plugin/unity_ads_plugin.dart'; - import 'package:ffmpeg_kit_flutter_full_gpl/ffmpeg_kit.dart'; void main() { @@ -117,7 +115,7 @@ class SettingPage extends StatefulWidget { class _SettingPageState extends State { - final List _expandState = [false, false, false, false, false, false, false, false]; + final List _expandState = [false, false, false, false, false, false, false]; @override Widget build(BuildContext context) { @@ -201,18 +199,10 @@ class _SettingPageState extends State { ExpansionPanel( isExpanded: _expandState[1], headerBuilder: ((context, isExpanded) { - return const ListTile(title: Text("全局设置"), subtitle: Text("在这里关广告、开启终端编辑")); + return const ListTile(title: Text("全局设置"), subtitle: Text("在这里开启终端编辑")); }), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [ - TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: (Util.getGlobal("termMaxLines") as int).toString(), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "终端最大行数(重启软件生效)"), readOnly: Util.shouldWatchAds(D.adsRequired["changeTermMaxLines"]!), + TextFormField(autovalidateMode: AutovalidateMode.onUserInteraction, initialValue: (Util.getGlobal("termMaxLines") as int).toString(), decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "终端最大行数(重启软件生效)"), keyboardType: TextInputType.number, - onTap: () { - if (Util.shouldWatchAds(D.adsRequired["changeTermMaxLines"]!)) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("观看六次视频广告永久解锁><")) - ); - } - }, validator: (value) { return Util.validateBetween(value, 1024, 2147483647, () async { await G.prefs.setInt("termMaxLines", int.parse(value!)); @@ -228,43 +218,12 @@ class _SettingPageState extends State { } ), 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(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("观看五次视频广告永久解锁><")) - ); - return; - } - G.prefs.setBool("isBannerAdsClosed", value); - setState(() { - G.bannerAdsChange.value = !G.bannerAdsChange.value; - }); - },), - 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(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: const Text("观看两次视频广告永久解锁><"), action: SnackBarAction(label: "啊?", onPressed: () { - G.prefs.setBool("isTerminalWriteEnabled", value); - setState(() {}); - },)) - ); - return; - } G.prefs.setBool("isTerminalWriteEnabled", value); setState(() {}); },), 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(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("观看三次视频广告永久解锁><")) - ); - return; - } G.prefs.setBool("isTerminalCommandsEnabled", value); setState(() { G.terminalPageChange.value = !G.terminalPageChange.value; @@ -380,15 +339,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)"""); 一些软件可能会存在显示问题,或者显示速度变慢。"""), 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"]!)) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("观看十二次视频广告永久解锁><")) - ); - } - }, + TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultHidpiOpt") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "HiDPI环境变量"), onChanged: (value) async { await G.prefs.setString("defaultHidpiOpt", value); }, @@ -440,15 +391,7 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)"""); }), ]), const SizedBox.square(dimension: 16), - TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultFFmpegCommand") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "ffmpeg推流命令"), readOnly: Util.shouldWatchAds(D.adsRequired["changeFFmpegCommand"]!), - onTap: () { - if (Util.shouldWatchAds(D.adsRequired["changeFFmpegCommand"]!)) { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("观看八次视频广告永久解锁><")) - ); - } - }, + TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultFFmpegCommand") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "ffmpeg推流命令"), onChanged: (value) async { await G.prefs.setString("defaultFFmpegCommand", value); }, @@ -558,13 +501,6 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)"""); ), 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(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("观看十次视频广告永久解锁><")) - ); - return; - } G.prefs.setBool("virgl", value); setState(() {}); },), @@ -579,9 +515,9 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)"""); 运行windows程序需要经过架构和系统两层模拟,不要对运行速度抱有期待。程序崩溃也是常有的。 -你需要耐心。即使图形界面什么也没显示。看看终端,还在继续输出吗?还是停止在某个报错? +建议将要运行的Windows程序连同程序文件夹移至桌面运行。 -如果不耐烦可以去看个广告消磨时间(bushi) +你需要耐心。即使图形界面什么也没显示。看看终端,还在继续输出吗?还是停止在某个报错? 或者寻找该windows软件官方是否提供linux arm64版本。 @@ -704,35 +640,6 @@ fi"""); },), const SizedBox.square(dimension: 16), ],))), - ExpansionPanel( - isExpanded: _expandState[7], - headerBuilder: ((context, isExpanded) { - return const ListTile(title: Text("广告记录"), subtitle: Text("在这里看广告")); - }), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [ - OutlinedButton(child: const Text("看一个广告"), onPressed: () { - if (AdManager.placements[AdManager.rewardedVideoAdPlacementId]!) { - AdManager.showAd(AdManager.rewardedVideoAdPlacementId, () { - final bonus = Util.getRandomBonus(); - Util.applyBonus(bonus); - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("你获得了 ${bonus["name"]}*${bonus["amount"]}")) - ); - setState(() {}); - }, () { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("已经看5个广告了, 今天也非常感谢><")) - ); - }); - } - }), - const SizedBox.square(dimension: 8), - Text(Util.getGlobal("adsBonus").map((element) { - final e = jsonDecode(element); - return e["amount"]==0?"":"${e["name"]}*${e["amount"]}\n"; - }).join()) - ],))), ],); } } @@ -1159,47 +1066,19 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------------- -unity_ads_plugin - -MIT License - -Copyright (c) 2021 Pavel Zaichyk - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. """))), ExpansionPanel( isExpanded: _expandState[2], headerBuilder: ((context, isExpanded) { return const ListTile(title: Text("隐私政策")); }), body: const Padding(padding: EdgeInsets.all(8), child: Text(""" -除由Unity提供的广告功能外, 本软件不会收集你的隐私信息。 +本软件不会收集你的隐私信息。 当然,你在容器系统内部安装或使用的软件行为(包括通过快捷指令)就不受我控制了,我不对其负责。 本软件申请的权限用于以下目的: 文件相关权限:用于系统访问手机目录; 相机和麦克风:用于推流,默认不会开启。 - -关于广告获取隐私信息的说明, 在第一次看广告时Unity会向你做出告知。 -届时你可以选择要向Unity提供哪些信息。 """))), ExpansionPanel( isExpanded: _expandState[3], @@ -1221,36 +1100,7 @@ SOFTWARE. }), body: Column( children: [ const Padding(padding: EdgeInsets.all(8), child: Text(""" -这个软件预计会有一些广告 -分为横幅广告和视频广告 -横幅广告在终端和控制页面的顶端出现 -(但不知道是不是因为代码没写对 -反正我从没见横幅广告成功加载过) -视频广告在需要解锁某些功能时自行观看 - -这些功能需要累计完整观看对应数目广告后永久解锁: -启用终端: 观看2个广告 -启用小键盘: 观看3个广告 -关闭横幅广告: 观看5个广告 -终端最大行数修改: 观看6个广告 -推流参数修改: 观看8个广告 -启用virgl加速: 观看10个广告 -HiDPI环境变量修改: 观看12个广告 - -我设置了每天最多可以看5个广告。 -只要看满1个广告, 就可以在本次使用期间临时解锁全部功能。 -只要看满2个广告, 就可以在当日使用期间临时解锁全部功能。 - -总之为了良好的体验 -在图形界面是不会出现广告的 -这点还请放心 - ----注意事项--- - -我注意到Unity提供了一些不那么合适的广告 -一般如果我看到这些广告就在后台直接禁了 -不过也可能有漏网之鱼 -可以联系我禁掉 +如果认为好用的话,可以推荐给其他人用噢! """)), ElevatedButton( onPressed: () { @@ -1506,20 +1356,8 @@ class _MyHomePageState extends State { 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?const SizedBox.square(dimension: 0):UnityBannerAd( - placementId: AdManager.bannerAdPlacementId, - onLoad: (placementId) => debugPrint('Banner loaded: $placementId'), - onClick: (placementId) => debugPrint('Banner clicked: $placementId'), - onFailed: (placementId, error, message) { - debugPrint('Banner Ad $placementId failed: $error $message'); - setState(() { - bannerAdsFailedToLoad = true; - }); - }, - ); - }), Expanded(child: ValueListenableBuilder(valueListenable: G.pageIndex, builder: (context, value, child) { + body: isLoadingComplete? + Expanded(child: ValueListenableBuilder(valueListenable: G.pageIndex, builder: (context, value, child) { return IndexedStack(index: G.pageIndex.value, children: const [TerminalPage(), Padding( padding: EdgeInsets.all(8), child: Scrollbar(child: SingleChildScrollView(restorationId: "control-scroll", child: Column( @@ -1544,7 +1382,7 @@ class _MyHomePageState extends State { ] ))) )]); - }))]):const LoadingPage(), + })):const LoadingPage(), bottomNavigationBar: ValueListenableBuilder(valueListenable: G.pageIndex, builder:(context, value, child) { return Visibility(visible: isLoadingComplete, // child: BottomNavigationBar(currentIndex: G.pageIndex.value, diff --git a/lib/workflow.dart b/lib/workflow.dart index 319b84e..5500f2a 100644 --- a/lib/workflow.dart +++ b/lib/workflow.dart @@ -39,8 +39,6 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:unity_ads_plugin/unity_ads_plugin.dart'; - import 'package:clipboard/clipboard.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; @@ -77,14 +75,10 @@ class Util { //int defaultAudioPort = 4718: 默认pulseaudio端口(为了避免和其它软件冲突改成4718了,原默认4713) //bool autoLaunchVnc = true: 是否自动启动VNC并跳转 //String lastDate: 上次启动软件的日期,yyyy-MM-dd - //int adsWatchedToday: 今日视频广告观看数量 - //int adsWatchedTotal: 视频广告观看数量 - //bool isBannerAdsClosed = false //bool isTerminalWriteEnabled = false //bool isTerminalCommandsEnabled = false //int termMaxLines = 4095 终端最大行数 //double termFontScale = 1 终端字体大小 - //int vip = 0 用户等级,vip免广告,你要改吗?(ToT) //bool isStickyKey = true 终端ctrl, shift, alt键是否粘滞 //String defaultFFmpegCommand 默认推流命令 //String defaultVirglCommand 默认virgl参数 @@ -103,8 +97,6 @@ class Util { //String[] containersInfo: 所有容器信息(json) //{name, boot:"\$DATA_DIR/bin/proot ...", vnc:"startnovnc", vncUrl:"...", commands:[{name:"更新和升级", command:"apt update -y && apt upgrade -y"}, // bind:[{name:"U盘", src:"/storage/xxxx", dst:"/media/meow"}]...]} - //String[] adsBonus: 观看广告获取的奖励(json) - //{name: "xxx", amount: xxx} //TODO: 这么写还是不对劲,有空改成类试试? static dynamic getGlobal(String key) { bool b = G.prefs.containsKey(key); @@ -113,14 +105,10 @@ class Util { case "defaultAudioPort" : return b ? G.prefs.getInt(key)! : (value){G.prefs.setInt(key, value); return value;}(4718); case "autoLaunchVnc" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(true); case "lastDate" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("1970-01-01"); - case "adsWatchedToday" : return b ? G.prefs.getInt(key)! : (value){G.prefs.setInt(key, value); return value;}(0); - case "adsWatchedTotal" : return b ? G.prefs.getInt(key)! : (value){G.prefs.setInt(key, value); return value;}(0); - case "isBannerAdsClosed" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "isTerminalWriteEnabled" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "isTerminalCommandsEnabled" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false); case "termMaxLines" : return b ? G.prefs.getInt(key)! : (value){G.prefs.setInt(key, value); return value;}(4095); case "termFontScale" : return b ? G.prefs.getDouble(key)! : (value){G.prefs.setDouble(key, value); return value;}(1.0); - case "vip" : return b ? G.prefs.getInt(key)! : (value){G.prefs.setInt(key, value); return value;}(1); case "isStickyKey" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(true); 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); @@ -136,7 +124,6 @@ class Util { case "defaultVirglOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GALLIUM_DRIVER=virpipe"); case "defaultHidpiOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GDK_SCALE=2 QT_FONT_DPI=192"); case "containersInfo" : return G.prefs.getStringList(key)!; - case "adsBonus" : return b ? G.prefs.getStringList(key)! : (value){G.prefs.setStringList(key, value); return value;}([].cast()); } } @@ -186,43 +173,6 @@ class Util { ); } - //返回单个G.bonusTable定义的item - static Map getRandomBonus() { - final random = Random(); - final totalWeight = D.bonusTable.fold(0.0, (sum, item) => sum + item['weight']); - final randomIndex = random.nextDouble() * totalWeight; - var cumulativeWeight = 0.0; - for (final item in D.bonusTable) { - cumulativeWeight += item['weight']; - if (randomIndex <= cumulativeWeight) { - return item; - } - } - return D.bonusTable[0]; - } - - //由getRandomBonus返回的数据 - static Future applyBonus(Map bonus) async { - bool flag = false; - List ret = Util.getGlobal("adsBonus").map((e) { - Map item = jsonDecode(e); - return (item["name"] == bonus["name"])? - jsonEncode(item..update("amount", (v) { - flag = true; - return v + bonus["amount"]; - })):e; - }).toList().cast(); - if (!flag) { - ret.add("""{"name": "${bonus["name"]}", "amount": ${bonus["amount"]}}"""); - } - await G.prefs.setStringList("adsBonus", ret); - } - - //根据已看广告量判断是否应该继续看广告 - static bool shouldWatchAds(int expectNum) { - return ((Util.getGlobal("adsWatchedTotal") as int) < expectNum) && ((Util.getGlobal("vip") as int) < 1) && ((Util.getGlobal("adsWatchedToday") as int) < D.adsRequired["unlockToday"]!) && (G.adsWatchedThisTime < D.adsRequired["unlockOnce"]!); - } - //限定字符串在min和max之间, 给文本框的validator static String? validateBetween(String? value, int min, int max, Function opr) { if (value == null || value.isEmpty) { @@ -524,34 +474,6 @@ rm /tmp/wps.deb"""}, {"name": "F12", "key": TerminalKey.f12}, ]; - //看广告可以获得的奖励。 - //weight抽奖权重,singleUse使用一次花费的数量,amount抽中可以获得的数量 - static const List> bonusTable = [ - {"name": "开发者的祝福", "subtitle": "支持开发者的证明", "description": "(*'v'*)\n开发者由衷地感谢你!", "weight": 10000, "amount": 1, "singleUse": 0}, - {"name": "记忆晶片", "subtitle": "看上去像平行四边形", "description": "组成记忆空间的基本元素。\n是从哪里掉下来的呢?", "weight": 50, "amount": 1, "singleUse": 0}, - {"name": "Wishes Flower Part", "subtitle": "为1个人献上祝福", "description": "希望之花的花瓣。在想好为谁祝福后, 点击使用", "weight": 500, "amount": 1, "singleUse": 1}, - {"name": "Wishes Flower Part", "subtitle": "为1个人献上祝福", "description": "希望之花的花瓣。在想好为谁祝福后, 点击使用", "weight": 100, "amount": 3, "singleUse": 1}, - {"name": "Wishes Flower", "subtitle": "为3个人献上祝福", "description": "希望之花。在想好为谁祝福后, 点击使用", "weight": 50, "amount": 1, "singleUse": 1}, - {"name": "Bonus Reward", "subtitle": "会有极好的事情发生", "description": "来自记忆空间的传说。\n使用后一天内必有极好的事情...\n就是你想象的那种事情...\n就会发生。\n不过, 大概只是个传说吧。", "weight": 10, "amount": 0.01, "singleUse": 1}, - {"name": "Bonus Reward", "subtitle": "会有极好的事情发生", "description": "来自记忆空间的传说。\n使用后一天内必有极好的事情...\n就是你想象的那种事情...\n就会发生。\n不过, 大概只是个传说吧。", "weight": 1, "amount": 0.1, "singleUse": 1}, - {"name": "Bonus Reward", "subtitle": "会有极好的事情发生", "description": "来自记忆空间的传说。\n使用后一天内必有极好的事情...\n就是你想象的那种事情...\n就会发生。\n不过, 大概只是个传说吧。", "weight": 1, "amount": 1, "singleUse": 1}, - ]; - - //某项功能开启需要的广告数。 - static const Map adsRequired = { - "closeBannerAds" : 5, - "enableTerminalWrite" : 2, - "enableTerminalCommands" : 3, - "changeTermMaxLines" : 6, - "changeFFmpegCommand" : 8, - "enableVirgl" : 10, - "changeHidpiOpt" : 12, - - "unlockOnce" : 1, //临时解锁需要看的广告数 - "unlockToday" : 2, //当日解锁需要看的广告数 - - }; - static const String boot = "\$DATA_DIR/bin/proot -H --change-id=1000:1000 --pwd=/home/tiny --rootfs=\$CONTAINER_DIR --mount=/system --mount=/apex --mount=/sys --kill-on-exit --mount=/storage:/storage --sysvipc -L --link2symlink --mount=/proc:/proc --mount=/dev:/dev --mount=\$CONTAINER_DIR/tmp:/dev/shm --mount=/dev/urandom:/dev/random --mount=/proc/self/fd:/dev/fd --mount=/proc/self/fd/0:/dev/stdin --mount=/proc/self/fd/1:/dev/stdout --mount=/proc/self/fd/2:/dev/stderr --mount=/dev/null:/dev/tty0 --mount=/dev/null:/proc/sys/kernel/cap_last_cap --mount=/storage/self/primary:/media/sd --mount=\$DATA_DIR/share:/home/tiny/公共 --mount=\$DATA_DIR/tiny:/home/tiny/.local/share/tiny --mount=/storage/self/primary/Fonts:/usr/share/fonts/wpsm --mount=/storage/self/primary/AppFiles/Fonts:/usr/share/fonts/yozom --mount=/system/fonts:/usr/share/fonts/androidm --mount=/storage/self/primary/Pictures:/home/tiny/图片 --mount=/storage/self/primary/Music:/home/tiny/音乐 --mount=/storage/self/primary/Movies:/home/tiny/视频 --mount=/storage/self/primary/Download:/home/tiny/下载 --mount=/storage/self/primary/DCIM:/home/tiny/照片 --mount=/storage/self/primary/Documents:/home/tiny/文档 --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/.tmoe-container.stat:/proc/stat --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/.tmoe-container.version:/proc/version --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/bus:/proc/bus --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/buddyinfo:/proc/buddyinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/cgroups:/proc/cgroups --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/consoles:/proc/consoles --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/crypto:/proc/crypto --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/devices:/proc/devices --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/diskstats:/proc/diskstats --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/execdomains:/proc/execdomains --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/fb:/proc/fb --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/filesystems:/proc/filesystems --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/interrupts:/proc/interrupts --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/iomem:/proc/iomem --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/ioports:/proc/ioports --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/kallsyms:/proc/kallsyms --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/keys:/proc/keys --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/key-users:/proc/key-users --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/kpageflags:/proc/kpageflags --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/loadavg:/proc/loadavg --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/locks:/proc/locks --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/misc:/proc/misc --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/modules:/proc/modules --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/pagetypeinfo:/proc/pagetypeinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/partitions:/proc/partitions --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/sched_debug:/proc/sched_debug --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/softirqs:/proc/softirqs --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/timer_list:/proc/timer_list --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/uptime:/proc/uptime --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/vmallocinfo:/proc/vmallocinfo --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/vmstat:/proc/vmstat --mount=\$CONTAINER_DIR/usr/local/etc/tmoe-linux/proot_proc/zoneinfo:/proc/zoneinfo \$EXTRA_MOUNT /usr/bin/env -i HOSTNAME=TINY HOME=/home/tiny USER=tiny TERM=xterm-256color SDL_IM_MODULE=fcitx XMODIFIERS=@im=fcitx QT_IM_MODULE=fcitx GTK_IM_MODULE=fcitx TMOE_CHROOT=false TMOE_PROOT=true TMPDIR=/tmp MOZ_FAKE_NO_SANDBOX=1 DISPLAY=:4 PULSE_SERVER=tcp:127.0.0.1:4718 LANG=zh_CN.UTF-8 SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/games:/usr/local/games \$EXTRA_OPT /bin/bash -l"; static final ButtonStyle commandButtonStyle = OutlinedButton.styleFrom( @@ -581,11 +503,9 @@ class G { static late BuildContext homePageStateContext; static late int currentContainer; //目前运行第几个容器 static late Map termPtys; //为容器存放TermPty数据 - static late AdManager ads; //广告实例 static late VirtualKeyboard keyboard; //存储ctrl, shift, alt状态 static bool maybeCtrlJ = false; //为了区分按下的ctrl+J和enter而准备的变量 static ValueNotifier termFontScale = ValueNotifier(1); //终端字体大小,存储为G.prefs的termFontScale - static int adsWatchedThisTime = 0; //本次启动应用看的广告数 static bool isStreamServerStarted = false; static bool isStreaming = false; //static int? streamingPid; @@ -596,7 +516,6 @@ class G { //static int? virglPid; static ValueNotifier pageIndex = ValueNotifier(0); //主界面索引 static ValueNotifier terminalPageChange = ValueNotifier(true); //更改值,用于刷新小键盘 - static ValueNotifier bannerAdsChange = ValueNotifier(true); //更改值,用于刷新banner广告 static ValueNotifier bootTextChange = ValueNotifier(true); //更改值,用于刷新启动命令 static ValueNotifier updateText = ValueNotifier("小小电脑"); //加载界面的说明文字 static ValueNotifier helpText = ValueNotifier(""" @@ -658,78 +577,6 @@ class G { static late SharedPreferences prefs; } -class AdManager { - - static Map placements = { - interstitialVideoAdPlacementId: false, - rewardedVideoAdPlacementId: false, - }; - - static void loadAds() { - for (var placementId in placements.keys) { - loadAd(placementId); - } - } - - static void loadAd(String placementId) { - UnityAds.load( - placementId: placementId, - onComplete: (placementId) { - debugPrint('Load Complete $placementId'); - placements[placementId] = true; - }, - onFailed: (placementId, error, message) => debugPrint('Load Failed $placementId: $error $message'), - ); - } - - static void showAd(String placementId, Function completeExtra, Function full) { - - if ((Util.getGlobal("adsWatchedToday") as int) >= 5) { - full(); - return; - } - - placements[placementId] = false; - UnityAds.showVideoAd( - placementId: placementId, - onComplete: (placementId) async { - debugPrint('Video Ad $placementId completed'); - loadAd(placementId); - G.adsWatchedThisTime++; - await G.prefs.setInt("adsWatchedTotal", (Util.getGlobal("adsWatchedTotal") as int)+1); - await G.prefs.setInt("adsWatchedToday", (Util.getGlobal("adsWatchedToday") as int)+1); - completeExtra(); - }, - onFailed: (placementId, error, message) { - debugPrint('Video Ad $placementId failed: $error $message'); - loadAd(placementId); - }, - onStart: (placementId) => debugPrint('Video Ad $placementId started'), - onClick: (placementId) => debugPrint('Video Ad $placementId click'), - onSkipped: (placementId) { - debugPrint('Video Ad $placementId skipped'); - loadAd(placementId); - }, - ); - } - - static String get gameId { - if (defaultTargetPlatform == TargetPlatform.android) { - return '5403132'; - } - if (defaultTargetPlatform == TargetPlatform.iOS) { - return '5403133'; - } - return ''; - } - - static String bannerAdPlacementId = 'Banner_Android'; - - static String interstitialVideoAdPlacementId = 'Interstitial_Android'; - - static String rewardedVideoAdPlacementId = 'Rewarded_Android'; -} - class Workflow { static Future grantPermissions() async { @@ -850,7 +697,7 @@ done final String currentDate = DateFormat("yyyy-MM-dd").format(DateTime.now()); if (currentDate != (Util.getGlobal("lastDate") as String)) { await G.prefs.setString("lastDate", currentDate); - await G.prefs.setInt("adsWatchedToday", 0); + //await G.prefs.setInt("adsWatchedToday", 0); } //如果没有这个key,说明是初次启动 @@ -876,29 +723,6 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)"""; G.controller = WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted); - //恢复临时开启的功能 - if (Util.shouldWatchAds(D.adsRequired["changeFFmpegCommand"]!)) { - await G.prefs.remove("defaultFFmpegCommand"); - } - if (Util.shouldWatchAds(D.adsRequired["changeHidpiOpt"]!)) { - await G.prefs.remove("defaultHidpiOpt"); - } - if (Util.shouldWatchAds(D.adsRequired["changeTermMaxLines"]!)) { - await G.prefs.setInt("termMaxLines", 4095); - } - if (Util.shouldWatchAds(D.adsRequired["closeBannerAds"]!)) { - await G.prefs.setBool("isBannerAdsClosed", false); - } - if (Util.shouldWatchAds(D.adsRequired["enableTerminalWrite"]!)) { - await G.prefs.setBool("isTerminalWriteEnabled", false); - } - if (Util.shouldWatchAds(D.adsRequired["enableTerminalCommands"]!)) { - await G.prefs.setBool("isTerminalCommandsEnabled", false); - } - if (Util.shouldWatchAds(D.adsRequired["enableVirgl"]!)) { - await G.prefs.setBool("virgl", false); - } - //设置屏幕常亮 WakelockPlus.toggle(enable: Util.getGlobal("wakelock")); } @@ -909,18 +733,6 @@ sed -i -E "s@^(VNC_RESOLUTION)=.*@\\1=${w}x${h}@" \$(command -v startvnc)"""; } } - static Future initAds() async { - UnityAds.init( - gameId: AdManager.gameId, - testMode: false, - onComplete: () { - debugPrint('Initialization Complete'); - AdManager.loadAds(); - }, - onFailed: (error, message) => debugPrint('Initialization Failed: $error $message'), - ); - } - static Future setupAudio() async { G.audioPty?.kill(); G.audioPty = Pty.start( @@ -1044,7 +856,6 @@ clear"""); static Future workflow() async { grantPermissions(); await initData(); - await initAds(); await initTerminalForCurrent(); setupAudio(); launchCurrentContainer(); diff --git a/pubspec.lock b/pubspec.lock index d0aec2c..b58d26a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -549,14 +549,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - unity_ads_plugin: - dependency: "direct main" - description: - name: unity_ads_plugin - sha256: "93dbf4069199440880f97c2c2604034a41945ae760c0b7883271ae02b75ea4d5" - url: "https://pub.dev" - source: hosted - version: "0.3.16" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 842b09d..af261c5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,7 +40,6 @@ dependencies: url_launcher: ^6.2.5 shared_preferences: ^2.2.2 intl: ^0.19.0 #日期字符串转换 - unity_ads_plugin: ^0.3.11 clipboard: ^0.1.3 ffmpeg_kit_flutter_full_gpl: ^6.0.3 wakelock_plus: ^1.1.6