diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index ee13d618..42d19ae9 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -57,7 +57,7 @@ jobs: frontend/src-tauri/gen/android/.gradle frontend/src-tauri/gen/android/build frontend/src-tauri/gen/android/app/build - key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties') }} + key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties', 'frontend/src-tauri/tauri.conf.json', 'frontend/src-tauri/capabilities/**') }} restore-keys: | ${{ runner.os }}-gradle- @@ -141,6 +141,13 @@ jobs: echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV + - name: Clean Gradle build cache + run: | + # Clear Gradle build cache to ensure fresh builds when capabilities change + rm -rf ~/.gradle/caches/build-cache-* + rm -rf frontend/src-tauri/gen/android/.gradle/build-cache + rm -rf frontend/src-tauri/gen/android/app/build + - name: Build Tauri Android App (Signed Release) working-directory: ./frontend run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af981788..1d40f577 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -181,7 +181,7 @@ jobs: frontend/src-tauri/gen/android/.gradle frontend/src-tauri/gen/android/build frontend/src-tauri/gen/android/app/build - key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties') }} + key: ${{ runner.os }}-gradle-${{ hashFiles('frontend/src-tauri/gen/android/**/*.gradle*', 'frontend/src-tauri/gen/android/gradle-wrapper.properties', 'frontend/src-tauri/tauri.conf.json', 'frontend/src-tauri/capabilities/**') }} restore-keys: | ${{ runner.os }}-gradle- @@ -265,6 +265,13 @@ jobs: echo "SCCACHE_DIR=$HOME/.cache/sccache" >> $GITHUB_ENV echo "SCCACHE_CACHE_SIZE=2G" >> $GITHUB_ENV + - name: Clean Gradle build cache + run: | + # Clear Gradle build cache to ensure fresh builds when capabilities change + rm -rf ~/.gradle/caches/build-cache-* + rm -rf frontend/src-tauri/gen/android/.gradle/build-cache + rm -rf frontend/src-tauri/gen/android/app/build + - name: Build Tauri Android App (Signed Release) working-directory: ./frontend run: | diff --git a/frontend/bun.lock b/frontend/bun.lock index 5e73ef45..34fd0d3b 100644 --- a/frontend/bun.lock +++ b/frontend/bun.lock @@ -23,7 +23,7 @@ "@tauri-apps/plugin-deep-link": "^2.4.5", "@tauri-apps/plugin-dialog": "^2.4.2", "@tauri-apps/plugin-fs": "^2.4.4", - "@tauri-apps/plugin-opener": "^2.5.2", + "@tauri-apps/plugin-opener": "2.2.6", "@tauri-apps/plugin-os": "^2.3.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", @@ -441,7 +441,7 @@ "@tauri-apps/plugin-fs": ["@tauri-apps/plugin-fs@2.4.4", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-MTorXxIRmOnOPT1jZ3w96vjSuScER38ryXY88vl5F0uiKdnvTKKTtaEjTEo8uPbl4e3gnUtfsDVwC7h77GQLvQ=="], - "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew=="], + "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.2.6", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-bSdkuP71ZQRepPOn8BOEdBKYJQvl6+jb160QtJX/i2H9BF6ZySY/kYljh76N2Ne5fJMQRge7rlKoStYQY5Jq1w=="], "@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A=="], diff --git a/frontend/package.json b/frontend/package.json index da5113cf..05f27a50 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -36,7 +36,7 @@ "@tauri-apps/plugin-deep-link": "^2.4.5", "@tauri-apps/plugin-dialog": "^2.4.2", "@tauri-apps/plugin-fs": "^2.4.4", - "@tauri-apps/plugin-opener": "^2.5.2", + "@tauri-apps/plugin-opener": "2.2.6", "@tauri-apps/plugin-os": "^2.3.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/frontend/src-tauri/Cargo.lock b/frontend/src-tauri/Cargo.lock index 3620d256..359177d6 100644 --- a/frontend/src-tauri/Cargo.lock +++ b/frontend/src-tauri/Cargo.lock @@ -5084,7 +5084,7 @@ dependencies = [ "tao-macros", "unicode-segmentation", "url", - "windows", + "windows 0.61.3", "windows-core 0.61.2", "windows-version", "x11-dl", @@ -5172,7 +5172,7 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows", + "windows 0.61.3", ] [[package]] @@ -5340,9 +5340,9 @@ dependencies = [ [[package]] name = "tauri-plugin-opener" -version = "2.5.2" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c26b72571d25dee25667940027114e60f569fc3974f8cefbe50c2cbc5fd65e3b" +checksum = "2fdc6cb608e04b7d2b6d1f21e9444ad49245f6d03465ba53323d692d1ceb1a30" dependencies = [ "dunce", "glob", @@ -5356,7 +5356,7 @@ dependencies = [ "tauri-plugin", "thiserror 2.0.17", "url", - "windows", + "windows 0.60.0", "zbus", ] @@ -5460,7 +5460,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.61.3", ] [[package]] @@ -5486,7 +5486,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows", + "windows 0.61.3", "wry", ] @@ -6449,9 +6449,9 @@ checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows", + "windows 0.61.3", "windows-core 0.61.2", - "windows-implement", + "windows-implement 0.60.2", "windows-interface", ] @@ -6473,7 +6473,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" dependencies = [ "thiserror 2.0.17", - "windows", + "windows 0.61.3", "windows-core 0.61.2", ] @@ -6529,17 +6529,39 @@ dependencies = [ "windows-version", ] +[[package]] +name = "windows" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf874e74c7a99773e62b1c671427abf01a425e77c3d3fb9fb1e4883ea934529" +dependencies = [ + "windows-collections 0.1.1", + "windows-core 0.60.1", + "windows-future 0.1.1", + "windows-link 0.1.3", + "windows-numerics 0.1.1", +] + [[package]] name = "windows" version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-collections", + "windows-collections 0.2.0", "windows-core 0.61.2", - "windows-future", + "windows-future 0.2.1", "windows-link 0.1.3", - "windows-numerics", + "windows-numerics 0.2.0", +] + +[[package]] +name = "windows-collections" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5467f79cc1ba3f52ebb2ed41dbb459b8e7db636cc3429458d9a852e15bc24dec" +dependencies = [ + "windows-core 0.60.1", ] [[package]] @@ -6551,13 +6573,26 @@ dependencies = [ "windows-core 0.61.2", ] +[[package]] +name = "windows-core" +version = "0.60.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247" +dependencies = [ + "windows-implement 0.59.0", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.3.1", +] + [[package]] name = "windows-core" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement", + "windows-implement 0.60.2", "windows-interface", "windows-link 0.1.3", "windows-result 0.3.4", @@ -6570,13 +6605,23 @@ version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "windows-implement", + "windows-implement 0.60.2", "windows-interface", "windows-link 0.2.1", "windows-result 0.4.1", "windows-strings 0.5.1", ] +[[package]] +name = "windows-future" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a787db4595e7eb80239b74ce8babfb1363d8e343ab072f2ffe901400c03349f0" +dependencies = [ + "windows-core 0.60.1", + "windows-link 0.1.3", +] + [[package]] name = "windows-future" version = "0.2.1" @@ -6588,6 +6633,17 @@ dependencies = [ "windows-threading", ] +[[package]] +name = "windows-implement" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "windows-implement" version = "0.60.2" @@ -6622,6 +6678,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005dea54e2f6499f2cee279b8f703b3cf3b5734a2d8d21867c8f44003182eeed" +dependencies = [ + "windows-core 0.60.1", + "windows-link 0.1.3", +] + [[package]] name = "windows-numerics" version = "0.2.0" @@ -6661,6 +6727,15 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-strings" version = "0.4.2" @@ -7007,7 +7082,7 @@ dependencies = [ "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows", + "windows 0.61.3", "windows-core 0.61.2", "windows-version", "x11-dl", diff --git a/frontend/src-tauri/Cargo.toml b/frontend/src-tauri/Cargo.toml index 4ce2baa1..f5cdd483 100644 --- a/frontend/src-tauri/Cargo.toml +++ b/frontend/src-tauri/Cargo.toml @@ -28,7 +28,7 @@ tauri-plugin-dialog = "2.4.2" tauri-plugin = "2.1.1" tauri-plugin-deep-link = "2.4.5" tauri-plugin-single-instance = { version = "2.3.6", features = ["deep-link"] } -tauri-plugin-opener = "2.5.2" +tauri-plugin-opener = "2.2.6" tauri-plugin-os = "2.3.2" tauri-plugin-sign-in-with-apple = "1.0.2" tokio = { version = "1.0", features = ["net", "sync", "rt-multi-thread", "macros", "time"] } diff --git a/frontend/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/frontend/src-tauri/gen/android/app/src/main/AndroidManifest.xml index 034fe065..2add4bb5 100644 --- a/frontend/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/frontend/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -8,6 +8,18 @@ + + + + + + + + + + + + { + setError(null); + const platform = isIOSPlatform ? "iOS" : "Android/Desktop"; + setError(`[DEBUG] GitHub click detected. Tauri=${isTauriEnv}, Platform=${platform}`); + try { console.log("[OAuth] Using", isTauriEnv ? "Tauri" : "web", "flow"); if (isTauriEnv) { - // For Tauri (desktop or mobile), redirect to the web app's desktop-auth route let desktopAuthUrl = "https://trymaple.ai/desktop-auth?provider=github"; - // If there's a selected plan, add it to the URL if (selected_plan) { desktopAuthUrl += `&selected_plan=${encodeURIComponent(selected_plan)}`; } - // If there's a redemption code, add it to the URL if (code) { desktopAuthUrl += `&code=${encodeURIComponent(code)}`; } - // Use the opener plugin by directly invoking the command - // This works for both desktop and mobile (iOS/Android) console.log("[OAuth] Opening URL in external browser:", desktopAuthUrl); - invoke("plugin:opener|open_url", { url: desktopAuthUrl }).catch((error: Error) => { - console.error("[OAuth] Failed to open external browser:", error); - setError("Failed to open authentication page in browser"); - }); + setError(`[DEBUG] Attempting to open: ${desktopAuthUrl}`); + + try { + const result = await invoke("plugin:opener|open_url", { url: desktopAuthUrl }); + console.log("[OAuth] invoke result:", result); + setError(`[DEBUG] invoke succeeded, result: ${JSON.stringify(result)}`); + } catch (invokeError) { + const errMsg = + invokeError instanceof Error ? invokeError.message : JSON.stringify(invokeError); + console.error("[OAuth] invoke failed:", invokeError); + setError(`[ERROR] invoke failed: ${errMsg}`); + + // Try fallback with plugin import + try { + setError(`[DEBUG] Trying fallback with plugin import...`); + const { openUrl } = await import("@tauri-apps/plugin-opener"); + await openUrl(desktopAuthUrl); + setError(`[DEBUG] Fallback openUrl succeeded`); + } catch (fallbackError) { + const fbErrMsg = + fallbackError instanceof Error + ? fallbackError.message + : JSON.stringify(fallbackError); + console.error("[OAuth] Fallback also failed:", fallbackError); + setError(`[ERROR] Both methods failed. invoke: ${errMsg} | fallback: ${fbErrMsg}`); + } + } } else { - // Web flow remains unchanged const { auth_url } = await os.initiateGitHubAuth(""); if (selected_plan) { sessionStorage.setItem("selected_plan", selected_plan); @@ -142,38 +163,59 @@ function LoginPage() { window.location.href = auth_url; } } catch (error) { + const errMsg = error instanceof Error ? error.message : JSON.stringify(error); console.error("Failed to initiate GitHub login:", error); - setError("Failed to initiate GitHub login. Please try again."); + setError(`[ERROR] Outer catch: ${errMsg}`); } }; const handleGoogleLogin = async () => { + setError(null); + const platform = isIOSPlatform ? "iOS" : "Android/Desktop"; + setError(`[DEBUG] Google click detected. Tauri=${isTauriEnv}, Platform=${platform}`); + try { console.log("[OAuth] Using", isTauriEnv ? "Tauri" : "web", "flow"); if (isTauriEnv) { - // For Tauri (desktop or mobile), redirect to the web app's desktop-auth route let desktopAuthUrl = "https://trymaple.ai/desktop-auth?provider=google"; - // If there's a selected plan, add it to the URL if (selected_plan) { desktopAuthUrl += `&selected_plan=${encodeURIComponent(selected_plan)}`; } - // If there's a redemption code, add it to the URL if (code) { desktopAuthUrl += `&code=${encodeURIComponent(code)}`; } - // Use the opener plugin by directly invoking the command - // This works for both desktop and mobile (iOS/Android) console.log("[OAuth] Opening URL in external browser:", desktopAuthUrl); - invoke("plugin:opener|open_url", { url: desktopAuthUrl }).catch((error: Error) => { - console.error("[OAuth] Failed to open external browser:", error); - setError("Failed to open authentication page in browser"); - }); + setError(`[DEBUG] Attempting to open: ${desktopAuthUrl}`); + + try { + const result = await invoke("plugin:opener|open_url", { url: desktopAuthUrl }); + console.log("[OAuth] invoke result:", result); + setError(`[DEBUG] invoke succeeded, result: ${JSON.stringify(result)}`); + } catch (invokeError) { + const errMsg = + invokeError instanceof Error ? invokeError.message : JSON.stringify(invokeError); + console.error("[OAuth] invoke failed:", invokeError); + setError(`[ERROR] invoke failed: ${errMsg}`); + + try { + setError(`[DEBUG] Trying fallback with plugin import...`); + const { openUrl } = await import("@tauri-apps/plugin-opener"); + await openUrl(desktopAuthUrl); + setError(`[DEBUG] Fallback openUrl succeeded`); + } catch (fallbackError) { + const fbErrMsg = + fallbackError instanceof Error + ? fallbackError.message + : JSON.stringify(fallbackError); + console.error("[OAuth] Fallback also failed:", fallbackError); + setError(`[ERROR] Both methods failed. invoke: ${errMsg} | fallback: ${fbErrMsg}`); + } + } } else { - // Web flow remains unchanged const { auth_url } = await os.initiateGoogleAuth(""); if (selected_plan) { sessionStorage.setItem("selected_plan", selected_plan); @@ -184,8 +226,9 @@ function LoginPage() { window.location.href = auth_url; } } catch (error) { + const errMsg = error instanceof Error ? error.message : JSON.stringify(error); console.error("Failed to initiate Google login:", error); - setError("Failed to initiate Google login. Please try again."); + setError(`[ERROR] Outer catch: ${errMsg}`); } }; @@ -317,25 +360,47 @@ function LoginPage() { setError(errorMessage); } } else if (isTauriEnv) { - // For Tauri desktop and Android, redirect to the web app's desktop-auth route + setError( + `[DEBUG] Apple click (non-iOS Tauri). Platform=${isIOSPlatform ? "iOS" : "Android/Desktop"}` + ); + let desktopAuthUrl = "https://trymaple.ai/desktop-auth?provider=apple"; - // If there's a selected plan, add it to the URL if (selected_plan) { desktopAuthUrl += `&selected_plan=${encodeURIComponent(selected_plan)}`; } - // If there's a redemption code, add it to the URL if (code) { desktopAuthUrl += `&code=${encodeURIComponent(code)}`; } - // Use the opener plugin by directly invoking the command console.log("[OAuth] Opening URL in external browser:", desktopAuthUrl); - invoke("plugin:opener|open_url", { url: desktopAuthUrl }).catch((error: Error) => { - console.error("[OAuth] Failed to open external browser:", error); - setError("Failed to open authentication page in browser"); - }); + setError(`[DEBUG] Attempting to open: ${desktopAuthUrl}`); + + try { + const result = await invoke("plugin:opener|open_url", { url: desktopAuthUrl }); + console.log("[OAuth] invoke result:", result); + setError(`[DEBUG] invoke succeeded, result: ${JSON.stringify(result)}`); + } catch (invokeError) { + const errMsg = + invokeError instanceof Error ? invokeError.message : JSON.stringify(invokeError); + console.error("[OAuth] invoke failed:", invokeError); + setError(`[ERROR] invoke failed: ${errMsg}`); + + try { + setError(`[DEBUG] Trying fallback with plugin import...`); + const { openUrl } = await import("@tauri-apps/plugin-opener"); + await openUrl(desktopAuthUrl); + setError(`[DEBUG] Fallback openUrl succeeded`); + } catch (fallbackError) { + const fbErrMsg = + fallbackError instanceof Error + ? fallbackError.message + : JSON.stringify(fallbackError); + console.error("[OAuth] Fallback also failed:", fallbackError); + setError(`[ERROR] Both methods failed. invoke: ${errMsg} | fallback: ${fbErrMsg}`); + } + } } else { // Web flow - use AppleAuthProvider component which will initiate the flow console.log("[OAuth] Using web flow for Apple Sign In (Web only)");