From 53174981a901ffa53d5a8da96dee57bb12a5466c Mon Sep 17 00:00:00 2001 From: Tim Date: Thu, 3 Oct 2024 15:52:25 +0200 Subject: [PATCH] refactor(Intro): make fb login compatible with shell --- package-lock.json | 17 +++++++- package.json | 3 +- src/routes/Intro/Intro.js | 14 ++++--- src/routes/Intro/useFacebookLogin.ts | 63 ++++++++++++++++++++++++++++ src/routes/Intro/useFacebookToken.js | 51 ---------------------- 5 files changed, 88 insertions(+), 60 deletions(-) create mode 100644 src/routes/Intro/useFacebookLogin.ts delete mode 100644 src/routes/Intro/useFacebookToken.js diff --git a/package-lock.json b/package-lock.json index 6f767069b..f2404dd17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "classnames": "2.3.1", "eventemitter3": "4.0.7", "filter-invalid-dom-props": "2.1.0", - "hat": "0.0.3", + "hat": "^0.0.3", "i18next": "^22.4.3", "langs": "^2.0.0", "lodash.debounce": "4.0.8", @@ -46,6 +46,7 @@ "@babel/plugin-proposal-object-rest-spread": "7.16.0", "@babel/preset-env": "7.16.0", "@babel/preset-react": "7.16.0", + "@types/hat": "^0.0.4", "@types/react": "^18.2.9", "babel-loader": "8.2.3", "clean-webpack-plugin": "4.0.0", @@ -3181,6 +3182,13 @@ "@types/node": "*" } }, + "node_modules/@types/hat": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/hat/-/hat-0.0.4.tgz", + "integrity": "sha512-HsNPoA1/v8x1d1jztZNI/RJNv7gvFsy2QVx9TEJyZ7S2aqJEDyRPiEYjr246tujQ6Br5ouH1VWIv8tXHYKlZUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/html-minifier-terser": { "version": "6.0.0", "dev": true, @@ -6887,7 +6895,12 @@ }, "node_modules/hat": { "version": "0.0.3", - "license": "MIT/X11" + "resolved": "https://registry.npmjs.org/hat/-/hat-0.0.3.tgz", + "integrity": "sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug==", + "license": "MIT/X11", + "engines": { + "node": "*" + } }, "node_modules/he": { "version": "1.2.0", diff --git a/package.json b/package.json index 73f27d28e..725c75658 100755 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "classnames": "2.3.1", "eventemitter3": "4.0.7", "filter-invalid-dom-props": "2.1.0", - "hat": "0.0.3", + "hat": "^0.0.3", "i18next": "^22.4.3", "langs": "^2.0.0", "lodash.debounce": "4.0.8", @@ -50,6 +50,7 @@ "@babel/plugin-proposal-object-rest-spread": "7.16.0", "@babel/preset-env": "7.16.0", "@babel/preset-react": "7.16.0", + "@types/hat": "^0.0.4", "@types/react": "^18.2.9", "babel-loader": "8.2.3", "clean-webpack-plugin": "4.0.0", diff --git a/src/routes/Intro/Intro.js b/src/routes/Intro/Intro.js index cde07bc96..c1fd82d74 100644 --- a/src/routes/Intro/Intro.js +++ b/src/routes/Intro/Intro.js @@ -10,7 +10,7 @@ const { Button, Image, useBinaryState } = require('stremio/common'); const CredentialsTextInput = require('./CredentialsTextInput'); const ConsentCheckbox = require('./ConsentCheckbox'); const PasswordResetModal = require('./PasswordResetModal'); -const useFacebookToken = require('./useFacebookToken'); +const useFacebookLogin = require('./useFacebookLogin'); const styles = require('./styles'); const SIGNUP_FORM = 'signup'; @@ -19,7 +19,7 @@ const LOGIN_FORM = 'login'; const Intro = ({ queryParams }) => { const { core } = useServices(); const routeFocused = useRouteFocused(); - const getFacebookToken = useFacebookToken(); + const startFacebookLogin = useFacebookLogin(); const emailRef = React.useRef(null); const passwordRef = React.useRef(null); const confirmPasswordRef = React.useRef(null); @@ -80,15 +80,17 @@ const Intro = ({ queryParams }) => { ); const loginWithFacebook = React.useCallback(() => { openLoaderModal(); - getFacebookToken() - .then((accessToken) => { + startFacebookLogin() + .then(({ email, password }) => { core.transport.dispatch({ action: 'Ctx', args: { action: 'Authenticate', args: { - type: 'Facebook', - token: accessToken, + type: 'Login', + email, + password, + facebook: true } } }); diff --git a/src/routes/Intro/useFacebookLogin.ts b/src/routes/Intro/useFacebookLogin.ts new file mode 100644 index 000000000..a1097111b --- /dev/null +++ b/src/routes/Intro/useFacebookLogin.ts @@ -0,0 +1,63 @@ +// Copyright (C) 2017-2023 Smart code 203358507 + +import { useCallback, useEffect, useRef } from 'react'; +import hat from 'hat'; +import { usePlatform } from 'stremio/common'; + +const STREMIO_URL = 'https://www.strem.io'; +const MAX_TRIES = 10; + +const getCredentials = async (state: string) => { + try { + const response = await fetch(`${STREMIO_URL}/login-fb-get-acc/${state}`); + const { user } = await response.json(); + + return Promise.resolve({ + email: user.email, + password: user.fbLoginToken, + }); + } catch (e) { + console.error('Failed to get credentials from facebook auth', e); + return Promise.reject(e); + } +}; + +const useFacebookLogin = () => { + const platform = usePlatform(); + const timeout = useRef(null); + + const startFacebookLogin = useCallback(() => { + return new Promise((resolve, reject) => { + const state = hat(128); + let tries = 0; + + platform.openExternal(`${STREMIO_URL}/login-fb/${state}`); + + const waitForCredentials = () => { + timeout.current && clearTimeout(timeout.current); + timeout.current = setTimeout(() => { + if (tries >= MAX_TRIES) + return reject(new Error('Failed to authenticate with facebook')); + + tries++; + + getCredentials(state) + .then(resolve) + .catch(waitForCredentials); + }, 1000); + }; + + waitForCredentials(); + }); + }, []); + + useEffect(() => { + return () => { + timeout.current && clearTimeout(timeout.current); + }; + }, []); + + return startFacebookLogin; +}; + +module.exports = useFacebookLogin; diff --git a/src/routes/Intro/useFacebookToken.js b/src/routes/Intro/useFacebookToken.js deleted file mode 100644 index 8f978e248..000000000 --- a/src/routes/Intro/useFacebookToken.js +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2017-2023 Smart code 203358507 - -const React = require('react'); - -const useFacebookToken = () => { - const getToken = React.useCallback(() => { - return new Promise((resolve, reject) => { - if (typeof FB === 'undefined') { - reject(new Error('Failed to connect to Facebook')); - return; - } - - FB.getLoginStatus((resp) => { - if (resp && resp.authResponse && typeof resp.authResponse.accessToken === 'string') { - resolve(resp.authResponse.accessToken); - return; - } - - FB.login((resp) => { - if (!resp || !resp.authResponse || typeof resp.authResponse.accessToken !== 'string') { - reject(new Error('Failed to get token from Facebook')); - return; - } - - resolve(resp.authResponse.accessToken); - }); - }); - }); - }, []); - React.useEffect(() => { - window.fbAsyncInit = function() { - FB.init({ - appId: '1537119779906825', - status: true, - xfbml: false, - version: 'v2.7' - }); - }; - const sdkScriptElement = document.createElement('script'); - sdkScriptElement.src = 'https://connect.facebook.net/en_US/sdk.js'; - sdkScriptElement.async = true; - sdkScriptElement.defer = true; - document.body.appendChild(sdkScriptElement); - return () => { - document.body.removeChild(sdkScriptElement); - }; - }, []); - return getToken; -}; - -module.exports = useFacebookToken;