cleanup: 删除 feat/expo-ota 分支,回滚到 main
- 删除远程 feat/expo-ota 分支 - 删除 Gitea Releases #5~#10 + Tags v5~v10 - 清除 Expo 产物(npmrc, package-lock, expo-manifest) - 保留 index.js + index.html(H5热更新) - MainActivity 改为 WebView + Android Bridge 模式 - 构建验证通过(33 tasks, 54s)
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"id": "ca582f57-9d65-4831-9d8a-1df3939264c7",
|
||||
"assets": [
|
||||
|
||||
],
|
||||
"createdAt": "2026-07-20T15:48:27.579Z",
|
||||
"metadata": {
|
||||
|
||||
},
|
||||
"runtimeVersion": "0.1.0",
|
||||
"launchAsset": {
|
||||
"contentType": "application/javascript",
|
||||
"key": "bundle",
|
||||
"url": "https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/v0.1.0-dav-android-10/index.android.bundle"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width">
|
||||
<style>
|
||||
body{font-family:monospace;background:#0f172a;color:#e2e8f0;padding:16px;margin:0}
|
||||
h1{font-size:18px;color:#38bdf8}
|
||||
.btn{display:block;width:100%;padding:14px;margin:8px 0;border:none;border-radius:8px;
|
||||
font-size:16px;cursor:pointer}
|
||||
.btn-check{background:#1e40af;color:#fff}
|
||||
.btn-download{background:#15803d;color:#fff}
|
||||
.log{background:#1e293b;padding:12px;border-radius:8px;margin-top:12px;
|
||||
max-height:300px;overflow-y:auto;font-size:12px;white-space:pre-wrap}
|
||||
.info{color:#94a3b8;font-size:12px;margin:4px 0}
|
||||
</style></head><body>
|
||||
<h1>Yuzu GCA</h1>
|
||||
<div class="info">version <span id="ver">v0.1.0-dav-android-8</span></div>
|
||||
<button class="btn btn-check" onclick="checkUpdate()">检查更新</button>
|
||||
<button class="btn btn-download" onclick="applyUpdate()" id="btnApply" disabled>下载更新</button>
|
||||
<div class="log" id="log"></div>
|
||||
<script>
|
||||
var dlUrl='',dlVer='';
|
||||
function log(m){document.getElementById('log').innerText+=m+'\n'}
|
||||
function checkUpdate(){
|
||||
log('正在检查...');
|
||||
fetch('https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/raw/branch/main/ota/version.txt')
|
||||
.then(r=>{if(!r.ok)throw Error('网络错误');return r.text()})
|
||||
.then(t=>{t=t.trim();log('远程: '+t);
|
||||
var local=document.getElementById('ver').innerText;
|
||||
if(t!==local){dlVer=t;dlUrl='https://git.childish-ghost.com/LukeMackin/Yuzu-GCA/releases/download/'+t+'/index.android.bundle';
|
||||
log('有新版本!');document.getElementById('btnApply').disabled=false}
|
||||
else log('已是最新')})
|
||||
.catch(e=>log('失败: '+e.message))
|
||||
}
|
||||
function applyUpdate(){
|
||||
log('下载中...');
|
||||
fetch(dlUrl).then(r=>{if(!r.ok)throw Error('下载失败');return r.text()})
|
||||
.then(t=>{localStorage.setItem('bundle',t);localStorage.setItem('ver',dlVer);
|
||||
log('下载完成,重启生效');location.reload()})
|
||||
.catch(e=>log('失败: '+e.message))
|
||||
}
|
||||
window.onload=function(){
|
||||
var b=localStorage.getItem('bundle'),v=localStorage.getItem('ver');
|
||||
if(b&&v){
|
||||
document.getElementById('ver').innerText=v;
|
||||
document.write(b);document.close()
|
||||
}
|
||||
}
|
||||
</script></body></html>
|
||||
@@ -7,6 +7,8 @@ import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ScrollView
|
||||
@@ -29,87 +31,30 @@ class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val scroll = ScrollView(this)
|
||||
val layout = LinearLayout(this).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setPadding(24, 24, 24, 24)
|
||||
val wv = WebView(this).apply {
|
||||
settings.javaScriptEnabled = true
|
||||
settings.domStorageEnabled = true
|
||||
settings.allowFileAccess = true
|
||||
webViewClient = object : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
||||
if (url.startsWith("http")) { view.loadUrl(url); return true }
|
||||
return false
|
||||
}
|
||||
}
|
||||
addJavascriptInterface(AndroidBridge(this@MainActivity), "Android")
|
||||
loadUrl("file:///android_asset/index.html")
|
||||
}
|
||||
setContentView(wv)
|
||||
appendLog("WebView 热更新模式启动")
|
||||
}
|
||||
|
||||
val title = TextView(this).apply {
|
||||
text = "Yuzu GCA"
|
||||
textSize = 20f
|
||||
setPadding(0, 0, 0, 4)
|
||||
}
|
||||
layout.addView(title)
|
||||
|
||||
val versionInfo = TextView(this).apply {
|
||||
text = "v0.1.0-dav-android-8-debug"
|
||||
textSize = 12f
|
||||
setTextColor(Color.GRAY)
|
||||
setPadding(0, 0, 0, 12)
|
||||
}
|
||||
layout.addView(versionInfo)
|
||||
|
||||
val channelLabel = TextView(this).apply {
|
||||
text = "选择更新渠道:"
|
||||
textSize = 13f
|
||||
setPadding(0, 8, 0, 4)
|
||||
}
|
||||
layout.addView(channelLabel)
|
||||
|
||||
// 渠道按钮行
|
||||
val channelRow = LinearLayout(this).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
setPadding(0, 0, 0, 12)
|
||||
}
|
||||
|
||||
fun makeChannelBtn(label: String, channel: String): Button {
|
||||
return Button(this).apply {
|
||||
text = label
|
||||
textSize = 12f
|
||||
setOnClickListener {
|
||||
selectedChannel = channel
|
||||
highlightChannel(channelRow, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val btnStable = makeChannelBtn("Stable", "stable")
|
||||
val btnBeta = makeChannelBtn("Beta", "beta")
|
||||
val btnNightly = makeChannelBtn("Nightly", "nightly")
|
||||
|
||||
channelRow.addView(btnStable)
|
||||
channelRow.addView(btnBeta)
|
||||
channelRow.addView(btnNightly)
|
||||
layout.addView(channelRow)
|
||||
highlightChannel(channelRow, btnStable)
|
||||
|
||||
logView = TextView(this).apply {
|
||||
textSize = 12f
|
||||
setTextColor(Color.LTGRAY)
|
||||
}
|
||||
layout.addView(logView)
|
||||
|
||||
val btn = Button(this).apply {
|
||||
text = "检查更新"
|
||||
setOnClickListener {
|
||||
val ch = selectedChannel
|
||||
CoroutineScope(Dispatchers.IO).launch { doOtaTest(ch) }
|
||||
}
|
||||
}
|
||||
layout.addView(btn)
|
||||
|
||||
scroll.addView(layout)
|
||||
setContentView(scroll)
|
||||
|
||||
appendLog("渠道: stable | 点击[检查更新]开始")
|
||||
}
|
||||
|
||||
private fun highlightChannel(row: LinearLayout, active: Button) {
|
||||
for (i in 0 until row.childCount) {
|
||||
val b = row.getChildAt(i) as Button
|
||||
b.isSelected = (b == active)
|
||||
inner class AndroidBridge(private val ctx: MainActivity) {
|
||||
@android.webkit.JavascriptInterface
|
||||
fun checkUpdate(channel: String) {
|
||||
CoroutineScope(Dispatchers.IO).launch { doOtaTest(channel) }
|
||||
}
|
||||
@android.webkit.JavascriptInterface
|
||||
fun log(msg: String) { appendLog(msg) }
|
||||
}
|
||||
|
||||
private fun appendLog(msg: String) {
|
||||
|
||||
43
packages/client-android/index.js
Normal file
43
packages/client-android/index.js
Normal file
@@ -0,0 +1,43 @@
|
||||
var React = require("react");
|
||||
var View = require("react-native").View;
|
||||
var Text = require("react-native").Text;
|
||||
var AppRegistry = require("react-native").AppRegistry;
|
||||
var Updates = require("expo-updates");
|
||||
|
||||
function App() {
|
||||
var [msg, setMsg] = React.useState("checking...");
|
||||
|
||||
React.useEffect(function() {
|
||||
async function check() {
|
||||
try {
|
||||
var rv = Updates.runtimeVersion || "empty";
|
||||
var ch = Updates.channel || "default";
|
||||
var id = Updates.updateId || "none";
|
||||
var emb = Updates.isEmbeddedLaunch ? "embedded" : "not-embedded";
|
||||
var info = "rv=" + rv + " ch=" + ch + " id=" + id + " emb=" + emb;
|
||||
|
||||
var result = await Updates.checkForUpdateAsync();
|
||||
if (result.isAvailable) {
|
||||
info += "\nUPDATE AVAILABLE! downloading...";
|
||||
await Updates.fetchUpdateAsync();
|
||||
info += "\ndownloaded. Restart app.";
|
||||
await Updates.reloadAsync();
|
||||
} else {
|
||||
info += "\nno update available";
|
||||
}
|
||||
setMsg(info);
|
||||
} catch(e) {
|
||||
setMsg("Error: " + e.message);
|
||||
}
|
||||
}
|
||||
check();
|
||||
}, []);
|
||||
|
||||
return React.createElement(View, {style: {flex:1,backgroundColor:"#0f172a",alignItems:"center",justifyContent:"center"}},
|
||||
React.createElement(Text, {style: {fontSize:28,fontWeight:"800",color:"#e2e8f0"}}, "Yuzu GCA"),
|
||||
React.createElement(Text, {style: {fontSize:14,color:"#64748b",marginTop:8}}, "v0.1.0-dav-android-10"),
|
||||
React.createElement(Text, {style: {fontSize:10,color:"#3b82f6",marginTop:8,textAlign:"center"}}, msg)
|
||||
);
|
||||
}
|
||||
|
||||
AppRegistry.registerComponent("main", function() { return App; });
|
||||
Reference in New Issue
Block a user