From 5ead559cd9c1fe5c9fdd86c6a178875968e262d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Jan 2026 01:31:27 +0000 Subject: [PATCH 1/8] Initial plan From 733adb0fcb405d4b29d16e258b9df7d1e111dbd6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Jan 2026 01:35:25 +0000 Subject: [PATCH 2/8] Add intent-filter for OAuth callback URL handling Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com> --- app/src/main/AndroidManifest.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 565bddf..abd90df 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -45,7 +45,18 @@ + android:windowSoftInputMode="adjustResize" + android:launchMode="singleTask"> + + + + + + + + Date: Fri, 9 Jan 2026 01:44:43 +0000 Subject: [PATCH 3/8] Fix WebView User-Agent to display Continue button after 2FA Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com> --- .../github/kotlin/module/login/LoginOAuthWebFragment.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt index 8e30c37..962c846 100644 --- a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt +++ b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt @@ -68,6 +68,12 @@ class LoginOAuthFragment : BaseFragment() { settings.domStorageEnabled = true settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS settings.cacheMode = LOAD_CACHE_ELSE_NETWORK + + // Set a standard Chrome User-Agent to avoid GitHub detecting WebView + val userAgent = settings.userAgentString + if (!userAgent.contains("Chrome")) { + settings.userAgentString = userAgent.replace("wv", "").replace("; )", "; Chrome/120.0.0.0)") + } val webViewClient: WebViewClient = object : WebViewClient() { From 8cf9f5358e2824fe03cfc765189a82b09dda0668 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Jan 2026 01:45:48 +0000 Subject: [PATCH 4/8] Improve User-Agent handling to be more robust Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com> --- .../github/kotlin/module/login/LoginOAuthWebFragment.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt index 962c846..636239c 100644 --- a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt +++ b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt @@ -72,7 +72,11 @@ class LoginOAuthFragment : BaseFragment() { // Set a standard Chrome User-Agent to avoid GitHub detecting WebView val userAgent = settings.userAgentString if (!userAgent.contains("Chrome")) { - settings.userAgentString = userAgent.replace("wv", "").replace("; )", "; Chrome/120.0.0.0)") + // Build a proper Chrome User-Agent string + settings.userAgentString = "$userAgent Chrome/122.0.0.0 Mobile Safari/537.36" + } else if (userAgent.contains(" wv)")) { + // Remove WebView identifier if present + settings.userAgentString = userAgent.replace(" wv)", ")") } val webViewClient: WebViewClient = object : WebViewClient() { From 9653c895b772fafb7ecc96c3b12a17a07e58d441 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Jan 2026 01:46:40 +0000 Subject: [PATCH 5/8] Refactor User-Agent handling to be clearer and handle all cases Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com> --- .../module/login/LoginOAuthWebFragment.kt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt index 636239c..b9002d6 100644 --- a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt +++ b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt @@ -70,14 +70,19 @@ class LoginOAuthFragment : BaseFragment() { settings.cacheMode = LOAD_CACHE_ELSE_NETWORK // Set a standard Chrome User-Agent to avoid GitHub detecting WebView - val userAgent = settings.userAgentString + var userAgent = settings.userAgentString + + // Remove WebView identifier if present + if (userAgent.contains(" wv)")) { + userAgent = userAgent.replace(" wv)", ")") + } + + // Ensure Chrome is present in User-Agent if (!userAgent.contains("Chrome")) { - // Build a proper Chrome User-Agent string - settings.userAgentString = "$userAgent Chrome/122.0.0.0 Mobile Safari/537.36" - } else if (userAgent.contains(" wv)")) { - // Remove WebView identifier if present - settings.userAgentString = userAgent.replace(" wv)", ")") + userAgent = "$userAgent Chrome/122.0.0.0 Mobile Safari/537.36" } + + settings.userAgentString = userAgent val webViewClient: WebViewClient = object : WebViewClient() { From 67f9d5b831e35bdac5802ed2001df1c2ce56a564 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Jan 2026 01:56:37 +0000 Subject: [PATCH 6/8] Replace WebView with external browser for OAuth to avoid X-Requested-With header Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com> --- .../kotlin/module/StartNavigationActivity.kt | 23 +++++ .../module/login/LoginOAuthWebFragment.kt | 96 ++++++------------- 2 files changed, 54 insertions(+), 65 deletions(-) diff --git a/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt b/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt index e2f95c9..b0ab434 100644 --- a/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt +++ b/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt @@ -33,6 +33,29 @@ class StartNavigationActivity : AppCompatActivity(), HasSupportFragmentInjector //如果是调试版本,启动后台服务测试AIDL startService(Intent(this, LocalService::class.java)) } + + handleOAuthCallback(intent) + } + + override fun onNewIntent(intent: Intent?) { + super.onNewIntent(intent) + setIntent(intent) + handleOAuthCallback(intent) + } + + private fun handleOAuthCallback(intent: Intent?) { + val uri = intent?.data + if (uri != null && uri.scheme == "gsygithubapp" && uri.host == "authed") { + // OAuth callback received, navigate to OAuth fragment if not already there + val fragment = supportFragmentManager.primaryNavigationFragment + if (fragment is NavHostFragment) { + val navController = fragment.navController + // Always navigate to OAuth fragment to handle the callback + if (navController.currentDestination?.id != R.id.loginOAuthFragment) { + navController.navigate(R.id.loginOAuthFragment) + } + } + } } //实现 HasSupportFragmentInjector 的接口,表示有Fragment需要注入 diff --git a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt index b9002d6..bec6f55 100644 --- a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt +++ b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt @@ -1,13 +1,9 @@ package com.shuyu.github.kotlin.module.login -import android.graphics.Bitmap +import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.View -import android.webkit.WebResourceRequest -import android.webkit.WebSettings -import android.webkit.WebSettings.LOAD_CACHE_ELSE_NETWORK -import android.webkit.WebView -import android.webkit.WebViewClient import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders @@ -50,72 +46,42 @@ class LoginOAuthFragment : BaseFragment() { activity?.toast(R.string.LoginFailTip) } }) - initWeb() - + + // Check if we're being called back from OAuth + activity?.intent?.data?.let { uri -> + if (uri.scheme == "gsygithubapp" && uri.host == "authed") { + val code = uri.getQueryParameter("code") + if (code != null) { + binding!!.oauthWebviewLoadingBar.visibility = View.VISIBLE + loginViewModel.oauth(context!!, code) + // Clear the intent data to avoid re-processing + activity?.intent?.data = null + return + } + } + } + + // Launch OAuth in external browser instead of WebView + launchOAuthInBrowser() } override fun getLayoutId(): Int { return R.layout.fragment_login_oauth } - - private fun initWeb() { - val settings = binding!!.oauthWebview.settings - settings.javaScriptEnabled = true - settings.loadWithOverviewMode = true - settings.builtInZoomControls = false - settings.displayZoomControls = false - settings.domStorageEnabled = true - settings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS - settings.cacheMode = LOAD_CACHE_ELSE_NETWORK + private fun launchOAuthInBrowser() { + val url = "https://github.com/login/oauth/authorize?" + + "client_id=${BuildConfig.CLIENT_ID}&" + + "state=app&" + + "redirect_uri=gsygithubapp://authed" - // Set a standard Chrome User-Agent to avoid GitHub detecting WebView - var userAgent = settings.userAgentString - - // Remove WebView identifier if present - if (userAgent.contains(" wv)")) { - userAgent = userAgent.replace(" wv)", ")") - } - - // Ensure Chrome is present in User-Agent - if (!userAgent.contains("Chrome")) { - userAgent = "$userAgent Chrome/122.0.0.0 Mobile Safari/537.36" + try { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + // Add FLAG_ACTIVITY_NEW_TASK to open in external browser + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(intent) + } catch (e: Exception) { + activity?.toast(R.string.LoginFailTip) } - - settings.userAgentString = userAgent - - val webViewClient: WebViewClient = object : WebViewClient() { - - override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { - } - - override fun onPageFinished(view: WebView?, url: String?) { - binding!!.oauthWebviewLoadingBar.visibility = View.GONE - } - - override fun shouldOverrideUrlLoading( - view: WebView?, request: WebResourceRequest? - ): Boolean { - if (request != null && request.url != null && request.url.toString() - .startsWith("gsygithubapp://authed") - ) { - val code = request.url.getQueryParameter("code") - if (code != null) { - loginViewModel.oauth(context!!, code) - }; - return true - } - return false - } - } - - - binding!!.oauthWebview.webViewClient = webViewClient - - - val url = - "https://github.com/login/oauth/authorize?" + "client_id=${BuildConfig.CLIENT_ID}&" + "state=app&redirect_uri=gsygithubapp://authed"; - - binding!!.oauthWebview.loadUrl(url) } } \ No newline at end of file From a07c1b70434709a31ebbee404669de63224fc278 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Jan 2026 01:58:02 +0000 Subject: [PATCH 7/8] Fix null safety issue with context in OAuth callback Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com> --- .../shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt index bec6f55..6b67e4d 100644 --- a/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt +++ b/app/src/main/java/com/shuyu/github/kotlin/module/login/LoginOAuthWebFragment.kt @@ -53,7 +53,9 @@ class LoginOAuthFragment : BaseFragment() { val code = uri.getQueryParameter("code") if (code != null) { binding!!.oauthWebviewLoadingBar.visibility = View.VISIBLE - loginViewModel.oauth(context!!, code) + context?.let { ctx -> + loginViewModel.oauth(ctx, code) + } // Clear the intent data to avoid re-processing activity?.intent?.data = null return From f97e13d617149c783c122b2f172561fb756b04cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 9 Jan 2026 01:59:13 +0000 Subject: [PATCH 8/8] Fix null safety in onNewIntent Co-authored-by: CarGuo <10770362+CarGuo@users.noreply.github.com> --- .../com/shuyu/github/kotlin/module/StartNavigationActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt b/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt index b0ab434..48ac807 100644 --- a/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt +++ b/app/src/main/java/com/shuyu/github/kotlin/module/StartNavigationActivity.kt @@ -39,7 +39,7 @@ class StartNavigationActivity : AppCompatActivity(), HasSupportFragmentInjector override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) - setIntent(intent) + intent?.let { setIntent(it) } handleOAuthCallback(intent) }