From f5fb2ed37a1b16723c0711a0acfd4b97bce07ed9 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 24 Mar 2025 16:18:29 +0200 Subject: [PATCH 01/25] feat(Auth): example apple login --- src/index.html | 1 + src/routes/Intro/Intro.js | 37 +++++++++++++- src/routes/Intro/useAppleLogin.ts | 80 +++++++++++++++++++++++++++++++ src/types/global.d.ts | 22 +++++++++ 4 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 src/routes/Intro/useAppleLogin.ts diff --git a/src/index.html b/src/index.html index ba8a9e795..033f9a267 100644 --- a/src/index.html +++ b/src/index.html @@ -15,6 +15,7 @@
<%= htmlWebpackPlugin.tags.bodyTags %> + \ No newline at end of file diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js index 989e6febd..0613e1490 100644 --- a/src/routes/Intro/Intro.js +++ b/src/routes/Intro/Intro.js @@ -12,6 +12,8 @@ const { Button, Image, Checkbox } = require('stremio/components'); const CredentialsTextInput = require('./CredentialsTextInput'); const PasswordResetModal = require('./PasswordResetModal'); const useFacebookLogin = require('./useFacebookLogin'); +const { default: useAppleLogin } = require('./useAppleLogin'); + const styles = require('./styles'); const SIGNUP_FORM = 'signup'; @@ -22,6 +24,7 @@ const Intro = ({ queryParams }) => { const { t } = useTranslation(); const routeFocused = useRouteFocused(); const [startFacebookLogin, stopFacebookLogin] = useFacebookLogin(); + const [startAppleLogin, stopAppleLogin] = useAppleLogin(); const emailRef = React.useRef(null); const passwordRef = React.useRef(null); const confirmPasswordRef = React.useRef(null); @@ -106,6 +109,32 @@ const Intro = ({ queryParams }) => { stopFacebookLogin(); closeLoaderModal(); }, []); + const loginWithApple = React.useCallback(() => { + openLoaderModal(); + startAppleLogin() + .then(({ email, password }) => { + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'Authenticate', + args: { + type: 'Login', + email, + password, + apple: true + } + } + }); + }) + .catch((error) => { + closeLoaderModal(); + dispatch({ type: 'error', error: error.message }); + }); + }, []); + const cancelLoginWithApple = React.useCallback(() => { + stopAppleLogin(); + closeLoaderModal(); + }, []); const loginWithEmail = React.useCallback(() => { if (typeof state.email !== 'string' || state.email.length === 0 || !emailRef.current.validity.valid) { dispatch({ type: 'error', error: 'Invalid email' }); @@ -336,7 +365,7 @@ const Intro = ({ queryParams }) => { } { - state.error.length > 0 ? + state.error && state.error.length > 0 ?
{state.error}
: null @@ -350,6 +379,10 @@ const Intro = ({ queryParams }) => {
Continue with Facebook
+ { state.form === SIGNUP_FORM ? diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts new file mode 100644 index 000000000..695888bee --- /dev/null +++ b/src/routes/Intro/useAppleLogin.ts @@ -0,0 +1,80 @@ +import { useCallback, useRef } from 'react'; + +type AppleLoginResponse = { + email: string; + password: string; +}; + +type AppleSignInResponse = { + authorization: { + code: string; + id_token: string; + state: string; + }; + user: string; + email?: string; +}; + +const CLIENT_ID = 'com.stremio.one'; + +const useAppleLogin = (): [() => Promise, () => void] => { + const started = useRef(false); + + const start = useCallback((): Promise => { + return new Promise((resolve, reject) => { + if (typeof window.AppleID === 'undefined') { + reject(new Error('Apple Sign-In not loaded')); + return; + } + + if (started.current) { + reject(new Error('Apple login already in progress')); + return; + } + + started.current = true; + + window.AppleID.auth.init({ + clientId: CLIENT_ID, + scope: 'name email', + redirectURI: window.location.origin, + state: 'signin', + usePopup: true + }); + + window.AppleID.auth.signIn() + .then((response: AppleSignInResponse) => { + if (response.authorization) { + const userEmail = response.email || response.user; + + if (!userEmail) { + reject(new Error('No email received from Apple')); + return; + } + + resolve({ + email: userEmail as string, + password: response.authorization.id_token + }); + } else { + reject(new Error('No authorization received from Apple')); + } + }) + .catch((error: Error) => { + console.error('Error during Apple Sign-In:', error); + reject(error); + }) + .finally(() => { + started.current = false; + }); + }); + }, []); + + const stop = useCallback(() => { + started.current = false; + }, []); + + return [start, stop]; +}; + +export default useAppleLogin; diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 3849b8914..4b46cb22d 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -26,6 +26,28 @@ interface Chrome { declare global { var qt: Qt | undefined; var chrome: Chrome | undefined; + interface Window { + AppleID: { + auth: { + init: (config: { + clientId: string; + scope: string; + redirectURI: string; + state: string; + usePopup: boolean; + }) => void; + signIn: () => Promise<{ + authorization: { + code: string; + id_token: string; + state: string; + }; + user: string; + email?: string; + }>; + }; + }; + } } export {}; From 592fb17fa14b63793da74f4befcbdd357c0f1885 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 12:42:41 +0300 Subject: [PATCH 02/25] refactor(Apple login): support new endpoint --- src/routes/Intro/Intro.js | 9 +++++---- src/routes/Intro/useAppleLogin.ts | 28 ++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js index 0613e1490..d20e3ea60 100644 --- a/src/routes/Intro/Intro.js +++ b/src/routes/Intro/Intro.js @@ -112,16 +112,17 @@ const Intro = ({ queryParams }) => { const loginWithApple = React.useCallback(() => { openLoaderModal(); startAppleLogin() - .then(({ email, password }) => { + .then(({ email, token, sub, name }) => { core.transport.dispatch({ action: 'Ctx', args: { action: 'Authenticate', args: { - type: 'Login', + type: 'AuthWithApple', + token, + sub, email, - password, - apple: true + name } } }); diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 695888bee..a3ec8fa38 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -1,8 +1,10 @@ import { useCallback, useRef } from 'react'; type AppleLoginResponse = { + token: string; + sub: string; email: string; - password: string; + name: string; }; type AppleSignInResponse = { @@ -13,6 +15,10 @@ type AppleSignInResponse = { }; user: string; email?: string; + fullName?: { + firstName?: string; + lastName?: string; + }; }; const CLIENT_ID = 'com.stremio.one'; @@ -45,16 +51,26 @@ const useAppleLogin = (): [() => Promise, () => void] => { window.AppleID.auth.signIn() .then((response: AppleSignInResponse) => { if (response.authorization) { - const userEmail = response.email || response.user; + const email = response.email || ''; + const sub = response.user; + + let name = ''; + if (response.fullName) { + const firstName = response.fullName.firstName || ''; + const lastName = response.fullName.lastName || ''; + name = [firstName, lastName].filter(Boolean).join(' '); + } - if (!userEmail) { - reject(new Error('No email received from Apple')); + if (!sub) { + reject(new Error('No sub token received from Apple')); return; } resolve({ - email: userEmail as string, - password: response.authorization.id_token + token: response.authorization.id_token, + sub: sub, + email: email, + name: name }); } else { reject(new Error('No authorization received from Apple')); From a0fa5e2a924f7463cc08ab3dd7c97d52a74a501e Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 12:45:06 +0300 Subject: [PATCH 03/25] fix(chore): lint --- src/routes/Intro/useAppleLogin.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index a3ec8fa38..d600f4c13 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -45,15 +45,16 @@ const useAppleLogin = (): [() => Promise, () => void] => { scope: 'name email', redirectURI: window.location.origin, state: 'signin', - usePopup: true + usePopup: true, }); - window.AppleID.auth.signIn() + window.AppleID.auth + .signIn() .then((response: AppleSignInResponse) => { if (response.authorization) { const email = response.email || ''; const sub = response.user; - + let name = ''; if (response.fullName) { const firstName = response.fullName.firstName || ''; @@ -70,7 +71,7 @@ const useAppleLogin = (): [() => Promise, () => void] => { token: response.authorization.id_token, sub: sub, email: email, - name: name + name: name, }); } else { reject(new Error('No authorization received from Apple')); From d457db6f1e5d3a93e181a688e01706d42fd97c6c Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 12:52:56 +0300 Subject: [PATCH 04/25] refactor(useapplelogin): update redirect url --- src/routes/Intro/useAppleLogin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index d600f4c13..e6508df23 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -43,7 +43,7 @@ const useAppleLogin = (): [() => Promise, () => void] => { window.AppleID.auth.init({ clientId: CLIENT_ID, scope: 'name email', - redirectURI: window.location.origin, + redirectURI: 'https://www.stremio.com/login', state: 'signin', usePopup: true, }); From 200d3a76d8628f073a77a33e6a29139d90beb20b Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 14:20:23 +0300 Subject: [PATCH 05/25] fix(useapplelogin): use correct client id --- src/routes/Intro/useAppleLogin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index e6508df23..5ecb88c98 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -21,7 +21,7 @@ type AppleSignInResponse = { }; }; -const CLIENT_ID = 'com.stremio.one'; +const CLIENT_ID = 'com.stremio.services'; const useAppleLogin = (): [() => Promise, () => void] => { const started = useRef(false); From a1acb7423a9089d2f44ad03ce92bbddfc3b39ccc Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 20:40:05 +0300 Subject: [PATCH 06/25] fix(useapplelogin): auth response --- src/routes/Intro/useAppleLogin.ts | 9 +++++---- src/types/global.d.ts | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 5ecb88c98..b73cb4d09 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -9,11 +9,11 @@ type AppleLoginResponse = { type AppleSignInResponse = { authorization: { - code: string; id_token: string; - state: string; }; - user: string; + authorizedData: { + userId: string; + }; email?: string; fullName?: { firstName?: string; @@ -52,8 +52,9 @@ const useAppleLogin = (): [() => Promise, () => void] => { .signIn() .then((response: AppleSignInResponse) => { if (response.authorization) { + console.log('Apple Sign-In response:', response); // eslint-disable-line no-console const email = response.email || ''; - const sub = response.user; + const sub = response.authorizedData.userId; let name = ''; if (response.fullName) { diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 4b46cb22d..f1c3eeecc 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -38,9 +38,10 @@ declare global { }) => void; signIn: () => Promise<{ authorization: { - code: string; id_token: string; - state: string; + }; + authorizedData: { + userId: string; }; user: string; email?: string; From 50edda25576b0a6e8524cc37b45e35dbfb41d941 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 20:45:51 +0300 Subject: [PATCH 07/25] fix(useapplelogin): use redirect uri for testing --- src/routes/Intro/useAppleLogin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index b73cb4d09..29e385f45 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -43,7 +43,7 @@ const useAppleLogin = (): [() => Promise, () => void] => { window.AppleID.auth.init({ clientId: CLIENT_ID, scope: 'name email', - redirectURI: 'https://www.stremio.com/login', + redirectURI: 'https://stremio.github.io/stremio-web/feat/example-apple-login/', state: 'signin', usePopup: true, }); From 846445001c637c704e50b40924b817de6b9066bb Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 21:10:50 +0300 Subject: [PATCH 08/25] fix(useapplelogin): get sub id from token --- package-lock.json | 10 ++++++++ package.json | 1 + src/routes/Intro/useAppleLogin.ts | 39 ++++++++++++++----------------- src/types/global.d.ts | 5 ++-- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3592aca2b..07806b2a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "filter-invalid-dom-props": "3.0.1", "hat": "^0.0.3", "i18next": "^24.0.5", + "jwt-decode": "^4.0.0", "langs": "github:Stremio/nodejs-langs", "lodash.debounce": "4.0.8", "lodash.intersection": "4.4.0", @@ -10233,6 +10234,15 @@ "node": ">=4.0" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/package.json b/package.json index 8eebb2685..e5386fbea 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "filter-invalid-dom-props": "3.0.1", "hat": "^0.0.3", "i18next": "^24.0.5", + "jwt-decode": "^4.0.0", "langs": "github:Stremio/nodejs-langs", "lodash.debounce": "4.0.8", "lodash.intersection": "4.4.0", diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 29e385f45..c8c752fea 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -1,4 +1,5 @@ import { useCallback, useRef } from 'react'; +import jwtDecode from 'jwt-decode'; type AppleLoginResponse = { token: string; @@ -9,10 +10,9 @@ type AppleLoginResponse = { type AppleSignInResponse = { authorization: { + code?: string; id_token: string; - }; - authorizedData: { - userId: string; + state?: string; }; email?: string; fullName?: { @@ -20,7 +20,6 @@ type AppleSignInResponse = { lastName?: string; }; }; - const CLIENT_ID = 'com.stremio.services'; const useAppleLogin = (): [() => Promise, () => void] => { @@ -48,13 +47,15 @@ const useAppleLogin = (): [() => Promise, () => void] => { usePopup: true, }); - window.AppleID.auth - .signIn() - .then((response: AppleSignInResponse) => { - if (response.authorization) { - console.log('Apple Sign-In response:', response); // eslint-disable-line no-console + window.AppleID.auth.signIn().then((response: AppleSignInResponse) => { + if (response.authorization) { + console.log('Apple Sign-In response:', response); // eslint-disable-line no-console + + try { + const idToken = response.authorization.id_token; const email = response.email || ''; - const sub = response.authorizedData.userId; + const payload = jwtDecode.jwtDecode(response.authorization.id_token); + const sub = payload.sub; let name = ''; if (response.fullName) { @@ -69,22 +70,18 @@ const useAppleLogin = (): [() => Promise, () => void] => { } resolve({ - token: response.authorization.id_token, + token: idToken, sub: sub, email: email, name: name, }); - } else { - reject(new Error('No authorization received from Apple')); + } catch (error) { + reject(new Error(`Failed to parse id_token: ${error}`)); } - }) - .catch((error: Error) => { - console.error('Error during Apple Sign-In:', error); - reject(error); - }) - .finally(() => { - started.current = false; - }); + } else { + reject(new Error('No authorization received from Apple')); + } + }); }); }, []); diff --git a/src/types/global.d.ts b/src/types/global.d.ts index f1c3eeecc..82b4c55cf 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -38,10 +38,9 @@ declare global { }) => void; signIn: () => Promise<{ authorization: { + code?: string; id_token: string; - }; - authorizedData: { - userId: string; + state?: string; }; user: string; email?: string; From b86887e111a9f6177417b725106833fadae2ca77 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 21:11:41 +0300 Subject: [PATCH 09/25] chore: add testing logs --- src/routes/Intro/useAppleLogin.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index c8c752fea..6f934a1c6 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -55,6 +55,7 @@ const useAppleLogin = (): [() => Promise, () => void] => { const idToken = response.authorization.id_token; const email = response.email || ''; const payload = jwtDecode.jwtDecode(response.authorization.id_token); + console.log('Decoded id_token:', payload); // eslint-disable-line no-console const sub = payload.sub; let name = ''; From 2713c8b46d5a174995c0ed369933b0db3aaa7013 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 21:31:34 +0300 Subject: [PATCH 10/25] fix(useapplelogin): jwt errors --- src/routes/Intro/useAppleLogin.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 6f934a1c6..ec86700fc 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -1,5 +1,5 @@ import { useCallback, useRef } from 'react'; -import jwtDecode from 'jwt-decode'; +import { jwtDecode, JwtPayload } from 'jwt-decode'; type AppleLoginResponse = { token: string; @@ -20,6 +20,12 @@ type AppleSignInResponse = { lastName?: string; }; }; + +type CustomJWTPayload = JwtPayload & { + sub: string; + email?: string; +}; + const CLIENT_ID = 'com.stremio.services'; const useAppleLogin = (): [() => Promise, () => void] => { @@ -49,14 +55,14 @@ const useAppleLogin = (): [() => Promise, () => void] => { window.AppleID.auth.signIn().then((response: AppleSignInResponse) => { if (response.authorization) { - console.log('Apple Sign-In response:', response); // eslint-disable-line no-console + console.log('Apple Sign-In response:', response.authorization); // eslint-disable-line no-console try { const idToken = response.authorization.id_token; - const email = response.email || ''; - const payload = jwtDecode.jwtDecode(response.authorization.id_token); + const payload: CustomJWTPayload = jwtDecode(idToken); console.log('Decoded id_token:', payload); // eslint-disable-line no-console const sub = payload.sub; + const email = payload.email ?? response.email ?? ''; let name = ''; if (response.fullName) { From 2ce16193131be2ead5b7c7b78b80d7a83bba8a49 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 21:52:57 +0300 Subject: [PATCH 11/25] chore: remove logs & use correct core action --- src/routes/Intro/Intro.js | 2 +- src/routes/Intro/useAppleLogin.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js index d20e3ea60..136d4ccea 100644 --- a/src/routes/Intro/Intro.js +++ b/src/routes/Intro/Intro.js @@ -118,7 +118,7 @@ const Intro = ({ queryParams }) => { args: { action: 'Authenticate', args: { - type: 'AuthWithApple', + type: 'Apple', token, sub, email, diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index ec86700fc..7d5465838 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -22,7 +22,6 @@ type AppleSignInResponse = { }; type CustomJWTPayload = JwtPayload & { - sub: string; email?: string; }; @@ -55,12 +54,9 @@ const useAppleLogin = (): [() => Promise, () => void] => { window.AppleID.auth.signIn().then((response: AppleSignInResponse) => { if (response.authorization) { - console.log('Apple Sign-In response:', response.authorization); // eslint-disable-line no-console - try { const idToken = response.authorization.id_token; const payload: CustomJWTPayload = jwtDecode(idToken); - console.log('Decoded id_token:', payload); // eslint-disable-line no-console const sub = payload.sub; const email = payload.email ?? response.email ?? ''; From 5acc32411dc0869d22757e83c64584073c7cb74b Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 21:54:11 +0300 Subject: [PATCH 12/25] fix(app): apple login types --- src/types/global.d.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 82b4c55cf..e55146e9a 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -42,8 +42,11 @@ declare global { id_token: string; state?: string; }; - user: string; email?: string; + fullName?: { + firstName?: string; + lastName?: string; + }; }>; }; }; From 43c76b6a4b42af5c4aff4b001d79bf89ddd109b3 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Thu, 10 Apr 2025 22:48:56 +0300 Subject: [PATCH 13/25] refactor(Intro): adjust styles --- src/routes/Intro/Intro.js | 2 +- src/routes/Intro/styles.less | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js index 136d4ccea..01ca5eab7 100644 --- a/src/routes/Intro/Intro.js +++ b/src/routes/Intro/Intro.js @@ -381,7 +381,7 @@ const Intro = ({ queryParams }) => {
Continue with Facebook
{ diff --git a/src/routes/Intro/styles.less b/src/routes/Intro/styles.less index 935b0fad1..335ab9a5c 100644 --- a/src/routes/Intro/styles.less +++ b/src/routes/Intro/styles.less @@ -175,15 +175,27 @@ position: relative; width: 22rem; margin-left: 2rem; + display: flex; + flex-direction: column; .facebook-button { background: var(--color-facebook); + margin-bottom: 1rem; &:hover, &:focus { outline: var(--focus-outline-size) solid var(--color-facebook); background-color: transparent; } } + + .apple-button { + background: var(--color-x); + + &:hover, &:focus { + outline: var(--focus-outline-size) solid var(--color-x); + background-color: transparent; + } + } } } } From 09c1b0c45eb9494e434cd65a7897f659c7d434a7 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 13:12:08 +0300 Subject: [PATCH 14/25] chore(core-web): v0.49.3 --- package-lock.json | 44 ++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 07806b2a5..195ac30d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@babel/runtime": "7.26.0", "@sentry/browser": "8.42.0", "@stremio/stremio-colors": "5.2.0", - "@stremio/stremio-core-web": "0.49.2", + "@stremio/stremio-core-web": "0.49.3", "@stremio/stremio-icons": "5.4.1", "@stremio/stremio-video": "0.0.53", "a-color-picker": "1.2.1", @@ -79,6 +79,21 @@ "workbox-webpack-plugin": "^7.3.0" } }, + "../stremio-core/stremio-core-web": { + "name": "@stremio/stremio-core-web", + "version": "0.49.3", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.24.1" + }, + "devDependencies": { + "@babel/cli": "7.24.1", + "@babel/core": "7.24.3", + "@babel/plugin-transform-runtime": "7.24.3", + "@babel/preset-env": "7.24.3", + "babel-plugin-bundled-import-meta": "0.3.2" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -3372,31 +3387,8 @@ "integrity": "sha512-dYlPgu9W/H7c9s1zmW5tiDnRenaUa4Hg1QCyOg1lhOcgSfM/bVTi5nnqX+IfvGTTUNA0zgzh8hI3o3miwnZxTg==" }, "node_modules/@stremio/stremio-core-web": { - "version": "0.49.2", - "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.49.2.tgz", - "integrity": "sha512-IYU+pdHkq4iEfqZ9G+DFZheIE53nY8XyhI1OJLvZp68/4ntRwssXwfj9InHK2Wau20fH+oV2KD1ZWb0CsTLqPA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "7.24.1" - } - }, - "node_modules/@stremio/stremio-core-web/node_modules/@babel/runtime": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", - "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@stremio/stremio-core-web/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" + "resolved": "../stremio-core/stremio-core-web", + "link": true }, "node_modules/@stremio/stremio-icons": { "version": "5.4.1", diff --git a/package.json b/package.json index e5386fbea..b04b5aaae 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@babel/runtime": "7.26.0", "@sentry/browser": "8.42.0", "@stremio/stremio-colors": "5.2.0", - "@stremio/stremio-core-web": "0.49.2", + "@stremio/stremio-core-web": "0.49.3", "@stremio/stremio-icons": "5.4.1", "@stremio/stremio-video": "0.0.53", "a-color-picker": "1.2.1", From befcef6dd2803f6772bda5609993e5c1a7c46f2e Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 13:18:12 +0300 Subject: [PATCH 15/25] fix: update core-web --- package-lock.json | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 195ac30d5..89bc98d3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,21 +79,6 @@ "workbox-webpack-plugin": "^7.3.0" } }, - "../stremio-core/stremio-core-web": { - "name": "@stremio/stremio-core-web", - "version": "0.49.3", - "license": "MIT", - "dependencies": { - "@babel/runtime": "7.24.1" - }, - "devDependencies": { - "@babel/cli": "7.24.1", - "@babel/core": "7.24.3", - "@babel/plugin-transform-runtime": "7.24.3", - "@babel/preset-env": "7.24.3", - "babel-plugin-bundled-import-meta": "0.3.2" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -3387,8 +3372,31 @@ "integrity": "sha512-dYlPgu9W/H7c9s1zmW5tiDnRenaUa4Hg1QCyOg1lhOcgSfM/bVTi5nnqX+IfvGTTUNA0zgzh8hI3o3miwnZxTg==" }, "node_modules/@stremio/stremio-core-web": { - "resolved": "../stremio-core/stremio-core-web", - "link": true + "version": "0.49.3", + "resolved": "https://registry.npmjs.org/@stremio/stremio-core-web/-/stremio-core-web-0.49.3.tgz", + "integrity": "sha512-Ql/08LbwU99IUL6fOLy+v1Iv75boHXpunEPScKgXJALdq/OV5tZLG/IycN0O+5+50Nc/NHrI6HslnMNLTWA8JQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "7.24.1" + } + }, + "node_modules/@stremio/stremio-core-web/node_modules/@babel/runtime": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@stremio/stremio-core-web/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" }, "node_modules/@stremio/stremio-icons": { "version": "5.4.1", From 0c3b7e8d4a217f983bc8adc5b50364b96959f6b0 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 13:36:40 +0300 Subject: [PATCH 16/25] chore: add debug logs --- src/routes/Intro/useAppleLogin.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 7d5465838..5fc40e52c 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -72,6 +72,7 @@ const useAppleLogin = (): [() => Promise, () => void] => { return; } + console.log('Apple login response:', payload, idToken, sub, email, name); // eslint-disable-line no-console resolve({ token: idToken, sub: sub, From 468dc604ae2b4fcea74da1b2b9ea2630728871d7 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 14:12:05 +0300 Subject: [PATCH 17/25] Revert "chore: add debug logs" This reverts commit 0c3b7e8d4a217f983bc8adc5b50364b96959f6b0. --- src/routes/Intro/useAppleLogin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 5fc40e52c..7d5465838 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -72,7 +72,6 @@ const useAppleLogin = (): [() => Promise, () => void] => { return; } - console.log('Apple login response:', payload, idToken, sub, email, name); // eslint-disable-line no-console resolve({ token: idToken, sub: sub, From e454cecc451629d5f3d6720c2dfc5e92490faa11 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 14:38:19 +0300 Subject: [PATCH 18/25] fix(useapplelogin): remove state signin --- src/routes/Intro/useAppleLogin.ts | 1 - src/types/global.d.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 7d5465838..58c83f127 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -48,7 +48,6 @@ const useAppleLogin = (): [() => Promise, () => void] => { clientId: CLIENT_ID, scope: 'name email', redirectURI: 'https://stremio.github.io/stremio-web/feat/example-apple-login/', - state: 'signin', usePopup: true, }); diff --git a/src/types/global.d.ts b/src/types/global.d.ts index e55146e9a..5697dc574 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -33,7 +33,6 @@ declare global { clientId: string; scope: string; redirectURI: string; - state: string; usePopup: boolean; }) => void; signIn: () => Promise<{ From 52dc7722ad45a86cbafa4c3f8032ffd92191214f Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 14:53:44 +0300 Subject: [PATCH 19/25] Revert "fix(useapplelogin): remove state signin" This reverts commit e454cecc451629d5f3d6720c2dfc5e92490faa11. --- src/routes/Intro/useAppleLogin.ts | 1 + src/types/global.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 58c83f127..7d5465838 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -48,6 +48,7 @@ const useAppleLogin = (): [() => Promise, () => void] => { clientId: CLIENT_ID, scope: 'name email', redirectURI: 'https://stremio.github.io/stremio-web/feat/example-apple-login/', + state: 'signin', usePopup: true, }); diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 5697dc574..e55146e9a 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -33,6 +33,7 @@ declare global { clientId: string; scope: string; redirectURI: string; + state: string; usePopup: boolean; }) => void; signIn: () => Promise<{ From 922de40134d1dbedcd6fb73cae29495271b17ec3 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 16:12:27 +0300 Subject: [PATCH 20/25] fix(useapplelogin): add timeout for close --- src/routes/Intro/useAppleLogin.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 7d5465838..e6a39cbb9 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -52,7 +52,17 @@ const useAppleLogin = (): [() => Promise, () => void] => { usePopup: true, }); + const timeoutId = setTimeout(() => { + if (started.current) { + started.current = false; + reject(new Error('Apple login popup was closed')); + } + }, 1000); + window.AppleID.auth.signIn().then((response: AppleSignInResponse) => { + clearTimeout(timeoutId); + started.current = false; + if (response.authorization) { try { const idToken = response.authorization.id_token; @@ -84,6 +94,10 @@ const useAppleLogin = (): [() => Promise, () => void] => { } else { reject(new Error('No authorization received from Apple')); } + }).catch((error) => { + clearTimeout(timeoutId); + started.current = false; + reject(error); }); }); }, []); From 0744fdfb8db8b7ac1c618e3c3de70e20bb09f319 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 16:16:02 +0300 Subject: [PATCH 21/25] refactor(Intro): new button design --- src/routes/Intro/styles.less | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/routes/Intro/styles.less b/src/routes/Intro/styles.less index 335ab9a5c..31a09d54c 100644 --- a/src/routes/Intro/styles.less +++ b/src/routes/Intro/styles.less @@ -189,11 +189,27 @@ } .apple-button { - background: var(--color-x); + background: var(--primary-foreground-color); + + .icon { + color: var(--primary-background-color); + } + + .label { + color: var(--primary-background-color); + } &:hover, &:focus { - outline: var(--focus-outline-size) solid var(--color-x); + outline: var(--focus-outline-size) solid var(--primary-foreground-color); background-color: transparent; + + .icon { + color: var(--primary-foreground-color); + } + + .label { + color: var(--primary-foreground-color); + } } } } From 66abce42c5368e9c6caa63f9dca22d82fb76054c Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 17:20:54 +0300 Subject: [PATCH 22/25] revert(useapplelogin): timeoutid --- src/routes/Intro/useAppleLogin.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index e6a39cbb9..583dd4411 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -52,17 +52,8 @@ const useAppleLogin = (): [() => Promise, () => void] => { usePopup: true, }); - const timeoutId = setTimeout(() => { - if (started.current) { - started.current = false; - reject(new Error('Apple login popup was closed')); - } - }, 1000); window.AppleID.auth.signIn().then((response: AppleSignInResponse) => { - clearTimeout(timeoutId); - started.current = false; - if (response.authorization) { try { const idToken = response.authorization.id_token; @@ -95,8 +86,6 @@ const useAppleLogin = (): [() => Promise, () => void] => { reject(new Error('No authorization received from Apple')); } }).catch((error) => { - clearTimeout(timeoutId); - started.current = false; reject(error); }); }); From 3aac148258593903a3e3b37f77d9bd4c5a7fde52 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 17:23:09 +0300 Subject: [PATCH 23/25] Update useAppleLogin.ts --- src/routes/Intro/useAppleLogin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 583dd4411..4128ee259 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -52,7 +52,6 @@ const useAppleLogin = (): [() => Promise, () => void] => { usePopup: true, }); - window.AppleID.auth.signIn().then((response: AppleSignInResponse) => { if (response.authorization) { try { From 303dd9858b80a9196108e83bafcd3aed9d1b76ca Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 19:29:12 +0300 Subject: [PATCH 24/25] refactor(useapplelogin): handle error cases --- src/routes/Intro/Intro.js | 6 +++++- src/routes/Intro/useAppleLogin.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js index 01ca5eab7..716fe0f0d 100644 --- a/src/routes/Intro/Intro.js +++ b/src/routes/Intro/Intro.js @@ -129,7 +129,11 @@ const Intro = ({ queryParams }) => { }) .catch((error) => { closeLoaderModal(); - dispatch({ type: 'error', error: error.message }); + if (error.error === 'popup_closed_by_user') { + dispatch({ type: 'error', error: 'Apple login popup was closed.' }); + } else { + dispatch({ type: 'error', error: error.error }); + } }); }, []); const cancelLoginWithApple = React.useCallback(() => { diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 4128ee259..580ec2d86 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -1,4 +1,4 @@ -import { useCallback, useRef } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; import { jwtDecode, JwtPayload } from 'jwt-decode'; type AppleLoginResponse = { @@ -94,6 +94,10 @@ const useAppleLogin = (): [() => Promise, () => void] => { started.current = false; }, []); + useEffect(() => { + return () => stop(); + }, []); + return [start, stop]; }; From 57d16957f2cfd483f9fb6f4651153d2d0ab57230 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 14 Apr 2025 23:26:04 +0300 Subject: [PATCH 25/25] chore(useapplelogin): update redirect to prod --- src/routes/Intro/useAppleLogin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Intro/useAppleLogin.ts b/src/routes/Intro/useAppleLogin.ts index 580ec2d86..900944eb8 100644 --- a/src/routes/Intro/useAppleLogin.ts +++ b/src/routes/Intro/useAppleLogin.ts @@ -47,7 +47,7 @@ const useAppleLogin = (): [() => Promise, () => void] => { window.AppleID.auth.init({ clientId: CLIENT_ID, scope: 'name email', - redirectURI: 'https://stremio.github.io/stremio-web/feat/example-apple-login/', + redirectURI: 'https://web.stremio.com/', state: 'signin', usePopup: true, });