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)");