diff --git a/ota/expo-manifest.json b/ota/expo-manifest.json deleted file mode 100644 index e4e96fd..0000000 --- a/ota/expo-manifest.json +++ /dev/null @@ -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" - } -} \ No newline at end of file diff --git a/packages/client-android/android/app/src/main/assets/index.html b/packages/client-android/android/app/src/main/assets/index.html new file mode 100644 index 0000000..33db4d8 --- /dev/null +++ b/packages/client-android/android/app/src/main/assets/index.html @@ -0,0 +1,47 @@ + + + +

Yuzu GCA

+
version v0.1.0-dav-android-8
+ + +
+ diff --git a/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt b/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt index 6f9fecd..191e716 100644 --- a/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt +++ b/packages/client-android/android/app/src/main/java/dev/yuzu/gca/MainActivity.kt @@ -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 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 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") } - - 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 | 点击[检查更新]开始") + setContentView(wv) + appendLog("WebView 热更新模式启动") } - 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) { diff --git a/packages/client-android/index.js b/packages/client-android/index.js new file mode 100644 index 0000000..9f552f6 --- /dev/null +++ b/packages/client-android/index.js @@ -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; });