From 6f05b7d19f8d3f1ed5b4dc83d31f341d267956d8 Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 28 Aug 2025 17:24:30 +0200 Subject: [PATCH 1/6] reduce button --- .../top-bar/src/components/gitLogin.tsx | 153 +++++------------- .../top-bar/src/lib/remix-ui-topbar.tsx | 2 - 2 files changed, 38 insertions(+), 117 deletions(-) diff --git a/libs/remix-ui/top-bar/src/components/gitLogin.tsx b/libs/remix-ui/top-bar/src/components/gitLogin.tsx index 2f13c6b9f67..18f9e136a4b 100644 --- a/libs/remix-ui/top-bar/src/components/gitLogin.tsx +++ b/libs/remix-ui/top-bar/src/components/gitLogin.tsx @@ -1,141 +1,59 @@ /* eslint-disable @nrwl/nx/enforce-module-boundaries */ -import React, { useEffect, useRef, useState, useCallback } from 'react' -import axios from 'axios' +import React, { useContext, useState, useCallback, useEffect } from 'react' import { Button, ButtonGroup, Dropdown } from 'react-bootstrap' import { CustomTopbarMenu } from '@remix-ui/helper' import { publishToGist } from 'libs/remix-ui/workspace/src/lib/actions' +import { AppContext } from '@remix-ui/app' +import { gitUIPanels } from 'libs/remix-ui/git/src/types' const _paq = window._paq || [] -interface GitHubUser { - login: string; - avatar_url?: string; - html_url?: string; - isConnected: boolean; -} - interface GitHubLoginProps { - onLoginSuccess: (user: GitHubUser, token: string) => void - onLoginError: (error: string) => void - clientIdEndpoint?: string - tokenExchangeEndpoint?: string cloneGitRepository: () => void logOutOfGithub: () => void } export const GitHubLogin: React.FC = ({ - onLoginSuccess, - onLoginError, cloneGitRepository, - logOutOfGithub, - clientIdEndpoint = 'https://github-login-proxy.api.remix.live/client', - tokenExchangeEndpoint = 'https://github-login-proxy.api.remix.live/login/oauth/access_token' + logOutOfGithub }) => { - const [isLoading, setIsLoading] = useState(false); - const [popupError, setPopupError] = useState(false); - const popupRef = useRef(null); - - // Get GitHub OAuth client ID based on hostname - const getClientId = async (): Promise => { - try { - const host = window.location.hostname; - const response = await axios.get(`${clientIdEndpoint}/${host}`, { - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - } - }); - return response.data.client_id; - } catch (error) { - throw new Error('Failed to fetch GitHub client ID'); - } - }; + const appContext = useContext(AppContext) + const [isLoading, setIsLoading] = useState(false) - // Handle popup-based OAuth login - const openPopupLogin = useCallback(async () => { - setIsLoading(true); - setPopupError(false); - - try { - const clientId = await getClientId(); - const redirectUri = `${window.location.origin}/?source=github` - const scope = 'repo gist user:email read:user'; - - const url = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&response_type=code`; - - const popup = window.open(url, '_blank', 'width=600,height=700'); - if (!popup) { - throw new Error('Popup blocked or failed to open'); - } - popupRef.current = popup; + // Get the GitHub user state from app context + const gitHubUser = appContext?.appState?.gitHubUser + const isConnected = gitHubUser?.isConnected - // Listen for messages from the popup - const messageListener = async (event: MessageEvent) => { - if (event.origin !== window.location.origin) return; + // Simple login handler that delegates to the dgit plugin + const handleLogin = useCallback(async () => { + if (isLoading) return - if (event.data.type === 'GITHUB_AUTH_SUCCESS') { - const token = event.data.token; - await handleLoginSuccess(token); - window.removeEventListener('message', messageListener); - popup?.close(); - } else if (event.data.type === 'GITHUB_AUTH_FAILURE') { - setPopupError(true); - setIsLoading(false); - onLoginError(event.data.error); - window.removeEventListener('message', messageListener); - popup?.close(); - } - }; + setIsLoading(true) - window.addEventListener('message', messageListener); - } catch (error) { - setIsLoading(false); - setPopupError(true); - onLoginError(error instanceof Error ? error.message : 'Login failed'); - } - }, [onLoginSuccess, onLoginError, clientIdEndpoint]); - - // Handle successful login - const handleLoginSuccess = async (token: string) => { try { - // Load GitHub user data - const userData = await loadGitHubUser(token); + // Check if dgit plugin is active and activate if needed + const isActive = await appContext.appManager.call('manager', 'isActive', 'dgit') + if (!isActive) { + await appContext.appManager.call('manager', 'activatePlugin', 'dgit') + } - // Save token to localStorage - localStorage.setItem('github_token', token); + // Open the GitHub panel in the git plugin and let it handle the login + await appContext.appManager.call('menuicons', 'select', 'dgit') + await appContext.appManager.call('dgit', 'open', gitUIPanels.GITHUB) - setIsLoading(false); - onLoginSuccess(userData, token); } catch (error) { - setIsLoading(false); - onLoginError('Failed to load user data'); + console.error('Failed to open GitHub login:', error) + } finally { + setIsLoading(false) } - }; - - // Load GitHub user data from token - const loadGitHubUser = async (token: string): Promise => { - const response = await axios.get('https://api.github.com/user', { - headers: { - 'Authorization': `token ${token}`, - 'Accept': 'application/vnd.github.v3+json' - } - }); - - return { - login: response.data.login, - avatar_url: response.data.avatar_url, - html_url: response.data.html_url, - isConnected: true - }; - }; + }, [appContext, isLoading]) - // Check if user is already logged in + // Monitor GitHub user state changes to stop loading when connection is established useEffect(() => { - const token = localStorage.getItem('github_token'); - if (token) { - handleLoginSuccess(token); + if (isConnected && isLoading) { + setIsLoading(false) } - }, []); + }, [isConnected, isLoading]) return ( = ({ fontSize: '0.8rem', padding: '0.35rem 0.5rem', }} - onClick={openPopupLogin} - disabled={isLoading} + onClick={isConnected ? undefined : handleLogin} + disabled={isLoading || isConnected} > {isLoading ? ( <> - Connecting... + Opening... + ) : isConnected ? ( +
+ + {gitHubUser.login} +
) : (
@@ -170,7 +93,7 @@ export const GitHubLogin: React.FC = ({ variant="outline-secondary" className="btn-topbar btn-sm" data-id="github-dropdown-toggle" - // disabled={true} + disabled={!isConnected} > ) : ( From b2cc97db53335c8159430c05bf67403eeaac942f Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Thu, 28 Aug 2025 17:45:07 +0200 Subject: [PATCH 2/6] asbtract away --- .../git/src/components/github/devicecode.tsx | 137 ++++------------ libs/remix-ui/git/src/lib/gitLoginActions.ts | 151 ++++++++++++++++++ libs/remix-ui/git/src/lib/gitactions.ts | 3 + libs/remix-ui/git/src/lib/listeners.ts | 17 ++ 4 files changed, 204 insertions(+), 104 deletions(-) create mode 100644 libs/remix-ui/git/src/lib/gitLoginActions.ts diff --git a/libs/remix-ui/git/src/components/github/devicecode.tsx b/libs/remix-ui/git/src/components/github/devicecode.tsx index aa55417204b..9b785d518aa 100644 --- a/libs/remix-ui/git/src/components/github/devicecode.tsx +++ b/libs/remix-ui/git/src/components/github/devicecode.tsx @@ -7,8 +7,7 @@ import { sendToMatomo } from "../../lib/pluginActions"; import { gitMatomoEventTypes } from "../../types"; import { endpointUrls } from "@remix-endpoints-helper"; import isElectron from "is-electron"; -import { set } from "lodash"; -import { use } from "chai"; +import { startGitHubLogin, getDeviceCodeFromGitHub, connectWithDeviceCode } from "../../lib/gitLoginActions"; export const GetDeviceCode = () => { const context = React.useContext(gitPluginContext) @@ -21,119 +20,49 @@ export const GetDeviceCode = () => { const popupRef = useRef(null) - // Dynamically select the GitHub OAuth client ID based on the hostname - const getClientId = async () => { - const host = isElectron() ? 'desktop' : window.location.hostname - // fetch it with axios from `${endpointUrls.gitHubLoginProxy}/client-id?host=${host}` - try { - const response = await axios.get(`${endpointUrls.gitHubLoginProxy}/client/${host}`, { - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - } - }) - return response.data.client_id - } - catch (error) { - throw new Error('Failed to fetch GitHub client ID') - } - - } - const openPopupLogin = useCallback(async () => { - - if (isElectron()) { - setDesktopIsLoading(true) - pluginActions.loginWithGitHub() - return - } - - const clientId = await getClientId() - const redirectUri = `${window.location.origin}/?source=github` - const scope = 'repo gist user:email read:user' - - const url = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&response_type=code` - - const popup = window.open(url, '_blank', 'width=600,height=700') - if (!popup) { - console.warn('Popup blocked or failed to open, falling back to device code flow.') - await getDeviceCodeFromGitHub() - return - } - popupRef.current = popup - - const messageListener = async (event: MessageEvent) => { - if (event.origin !== window.location.origin) return - - if (event.data.type === 'GITHUB_AUTH_SUCCESS') { - const token = event.data.token - await pluginActions.saveToken(token) - await actions.loadGitHubUserFromToken() + try { + if (isElectron()) { + setDesktopIsLoading(true) + } + + await startGitHubLogin() + + if (!isElectron()) { setAuthorized(true) - await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS) - window.removeEventListener('message', messageListener) - popup?.close() - } else if (event.data.type === 'GITHUB_AUTH_FAILURE') { + } + } catch (error) { + console.error('GitHub login failed:', error) + if (isElectron()) { + setDesktopIsLoading(false) + } else { setPopupError(true) - window.removeEventListener('message', messageListener) - popup?.close() + // Fallback to device code flow + await handleGetDeviceCode() } } + }, []) - window.addEventListener('message', messageListener) - }, [actions, pluginActions]) - - const getDeviceCodeFromGitHub = async () => { + const handleGetDeviceCode = async () => { setDesktopIsLoading(false) setPopupError(false) - await sendToMatomo(gitMatomoEventTypes.GETGITHUBDEVICECODE) setAuthorized(false) - // Send a POST request - const response = await axios({ - method: 'post', - url: `${endpointUrls.github}/login/device/code`, - data: { - client_id: '2795b4e41e7197d6ea11', - scope: 'repo gist user:email read:user' - }, - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - }); - - // convert response to json - const githubrespone = await response.data; - - setGitHubResponse(githubrespone) + + try { + const githubResponse = await getDeviceCodeFromGitHub() + setGitHubResponse(githubResponse) + } catch (error) { + console.error('Failed to get device code:', error) + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBFAIL) + } } const connectApp = async () => { - await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUB) - // poll https://github.com/login/oauth/access_token - const accestokenresponse = await axios({ - method: 'post', - url: `${endpointUrls.github}/login/oauth/access_token`, - data: { - client_id: '2795b4e41e7197d6ea11', - device_code: gitHubResponse.device_code, - grant_type: 'urn:ietf:params:oauth:grant-type:device_code' - }, - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - }); - - // convert response to json - const response = await accestokenresponse.data; - - if (response.access_token) { + try { + await connectWithDeviceCode(gitHubResponse.device_code) setAuthorized(true) - await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS) - await pluginActions.saveToken(response.access_token) - await actions.loadGitHubUserFromToken() - } else { + } catch (error) { + console.error('Failed to connect with device code:', error) await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBFAIL) } } @@ -162,7 +91,7 @@ export const GetDeviceCode = () => { {popupError && !gitHubResponse && !authorized && (
GitHub login failed. You can continue using another method. -
@@ -171,7 +100,7 @@ export const GetDeviceCode = () => {
In case of issues, you can try another method. -
diff --git a/libs/remix-ui/git/src/lib/gitLoginActions.ts b/libs/remix-ui/git/src/lib/gitLoginActions.ts new file mode 100644 index 00000000000..821d4087722 --- /dev/null +++ b/libs/remix-ui/git/src/lib/gitLoginActions.ts @@ -0,0 +1,151 @@ +import axios from "axios"; +import { endpointUrls } from "@remix-endpoints-helper"; +import isElectron from "is-electron"; +import { saveToken } from "./pluginActions"; +import { loadGitHubUserFromToken } from "./gitactions"; +import { sendToMatomo } from "./pluginActions"; +import { gitMatomoEventTypes } from "../types"; + +// Reference to the plugin - this will be set from listeners.ts +let plugin: any = null; + +export const setLoginPlugin = (pluginInstance: any) => { + plugin = pluginInstance; +}; + +// Get the GitHub OAuth client ID based on the platform +const getClientId = async () => { + const host = isElectron() ? 'desktop' : window.location.hostname; + try { + const response = await axios.get(`${endpointUrls.gitHubLoginProxy}/client/${host}`, { + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + } + }); + return response.data.client_id; + } catch (error) { + throw new Error('Failed to fetch GitHub client ID'); + } +}; + +// Start GitHub login process based on platform +export const startGitHubLogin = async (): Promise => { + if (!plugin) { + throw new Error('Plugin not initialized for GitHub login'); + } + + try { + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUB); + + if (isElectron()) { + // For desktop/electron, use the githubAuthHandler plugin + await plugin.call('githubAuthHandler', 'login'); + } else { + // For web, open popup login + await startWebPopupLogin(); + } + } catch (error) { + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBFAIL); + throw error; + } +}; + +// Web popup login implementation +const startWebPopupLogin = async (): Promise => { + const clientId = await getClientId(); + const redirectUri = `${window.location.origin}/?source=github`; + const scope = 'repo gist user:email read:user'; + + const url = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&response_type=code`; + + const popup = window.open(url, '_blank', 'width=600,height=700'); + if (!popup) { + console.warn('Popup blocked or failed to open, falling back to device code flow.'); + throw new Error('Popup blocked - please allow popups for this site or use device code flow'); + } + + return new Promise((resolve, reject) => { + const messageListener = async (event: MessageEvent) => { + if (event.origin !== window.location.origin) return; + + if (event.data.type === 'GITHUB_AUTH_SUCCESS') { + const token = event.data.token; + try { + await saveToken(token); + await loadGitHubUserFromToken(); + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS); + window.removeEventListener('message', messageListener); + popup?.close(); + resolve(); + } catch (error) { + window.removeEventListener('message', messageListener); + popup?.close(); + reject(error); + } + } else if (event.data.type === 'GITHUB_AUTH_FAILURE') { + window.removeEventListener('message', messageListener); + popup?.close(); + reject(new Error('GitHub authentication failed')); + } + }; + + window.addEventListener('message', messageListener); + + // Check if popup was closed without authentication + const checkClosed = setInterval(() => { + if (popup?.closed) { + clearInterval(checkClosed); + window.removeEventListener('message', messageListener); + reject(new Error('Authentication popup was closed')); + } + }, 1000); + }); +}; + +// Device code flow fallback (can be called from components if needed) +export const getDeviceCodeFromGitHub = async (): Promise => { + await sendToMatomo(gitMatomoEventTypes.GETGITHUBDEVICECODE); + + const response = await axios({ + method: 'post', + url: `${endpointUrls.github}/login/device/code`, + data: { + client_id: '2795b4e41e7197d6ea11', + scope: 'repo gist user:email read:user' + }, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + }); + + return response.data; +}; + +// Connect using device code +export const connectWithDeviceCode = async (deviceCode: string): Promise => { + const response = await axios({ + method: 'post', + url: `${endpointUrls.github}/login/oauth/access_token`, + data: { + client_id: '2795b4e41e7197d6ea11', + device_code: deviceCode, + grant_type: 'urn:ietf:params:oauth:grant-type:device_code' + }, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + }); + + const data = response.data; + + if (data.access_token) { + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS); + await saveToken(data.access_token); + await loadGitHubUserFromToken(); + } else { + throw new Error('Failed to get access token from device code'); + } +}; diff --git a/libs/remix-ui/git/src/lib/gitactions.ts b/libs/remix-ui/git/src/lib/gitactions.ts index 425c86a3b5f..e9c21dab5a3 100644 --- a/libs/remix-ui/git/src/lib/gitactions.ts +++ b/libs/remix-ui/git/src/lib/gitactions.ts @@ -912,3 +912,6 @@ export const clearGitLog = async () => { export const setStorage = async (storage: storage) => { dispatch(setStoragePayload(storage)) } + +// Re-export the login function for external use +export { startGitHubLogin } from './gitLoginActions' diff --git a/libs/remix-ui/git/src/lib/listeners.ts b/libs/remix-ui/git/src/lib/listeners.ts index 028bf7d1fb3..a6087160f29 100644 --- a/libs/remix-ui/git/src/lib/listeners.ts +++ b/libs/remix-ui/git/src/lib/listeners.ts @@ -9,6 +9,7 @@ import { CustomRemixApi } from "@remix-api"; import { saveToken, sendToMatomo, statusChanged } from "./pluginActions"; import { appPlatformTypes } from "@remix-ui/app"; import { AppAction } from "@remix-ui/app"; +import { setLoginPlugin, startGitHubLogin } from "./gitLoginActions"; let plugin: Plugin, gitDispatch: React.Dispatch, loaderDispatch: React.Dispatch, loadFileQueue: AsyncDebouncedQueue let callBackEnabled: boolean = false @@ -43,6 +44,9 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { loadFileQueue.enqueue(async () => { @@ -207,6 +211,19 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { + try { + await startGitHubLogin() + } catch (error) { + console.error('Failed to start GitHub login from dgit plugin:', error) + // Optionally show error to user + gitDispatch(setLog({ + message: `GitHub login failed: ${error.message}`, + type: "error" + })) + } + }) + plugin.on('githubAuthHandler', 'onLogin', async (data: { token: string }) => { await saveToken(data.token) await loadGitHubUserFromToken() From 8d2de7cf1062e9f827edf831b4988953c4884c0f Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 2 Sep 2025 13:15:17 +0200 Subject: [PATCH 3/6] use context --- apps/remix-ide/src/app/plugins/git.tsx | 6 ++++- .../app/src/lib/remix-app/context/context.tsx | 1 + .../app/src/lib/remix-app/remix-app.tsx | 22 ++++++++++++++++++- .../top-bar/src/components/gitLogin.tsx | 16 +++----------- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/apps/remix-ide/src/app/plugins/git.tsx b/apps/remix-ide/src/app/plugins/git.tsx index 42c655c7cfc..6e2cd72aea1 100644 --- a/apps/remix-ide/src/app/plugins/git.tsx +++ b/apps/remix-ide/src/app/plugins/git.tsx @@ -8,7 +8,7 @@ const profile = { name: 'dgit', displayName: 'Git', description: 'Git plugin for Remix', - methods: ['open', 'init'], + methods: ['open', 'init', 'startLogin'], events: [''], version: packageJson.version, maintainedBy: 'Remix', @@ -41,4 +41,8 @@ export class GitPlugin extends ViewPlugin { return
} + async startLogin(){ + this.emit('startLogin') + } + } diff --git a/libs/remix-ui/app/src/lib/remix-app/context/context.tsx b/libs/remix-ui/app/src/lib/remix-app/context/context.tsx index 48aa1b391e1..a93afd9c55b 100644 --- a/libs/remix-ui/app/src/lib/remix-app/context/context.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/context/context.tsx @@ -11,6 +11,7 @@ export type appProviderContextType = { modal: any appState: AppState appStateDispatch: React.Dispatch + loginWithGitHub: () => Promise } export enum appPlatformTypes { diff --git a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx index c936272b5c3..90f02829e30 100644 --- a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx @@ -199,7 +199,27 @@ const RemixApp = (props: IRemixAppUi) => { showEnter: props.app.showEnter, modal: props.app.notification, appState: appState, - appStateDispatch: appStateDispatch + appStateDispatch: appStateDispatch, + loginWithGitHub: async () => { + try { + // Activate dgit plugin if not active + const isActive = await props.app.appManager.call('manager', 'isActive', 'dgit') + if (!isActive) { + await props.app.appManager.call('manager', 'activatePlugin', 'dgit') + } + + // Emit the startLogin event to trigger the abstracted login logic + await props.app.appManager.call('dgit', 'startLogin') + } catch (error) { + console.error('Failed to trigger GitHub login:', error) + // Optionally show a user-friendly error + props.app.notification.alert({ + id: 'github-login-error', + title: 'Login Error', + message: 'Failed to start GitHub login. Please try again.' + }) + } + } } const handleUserChosenType = async (type) => { diff --git a/libs/remix-ui/top-bar/src/components/gitLogin.tsx b/libs/remix-ui/top-bar/src/components/gitLogin.tsx index 18f9e136a4b..ab1b7728623 100644 --- a/libs/remix-ui/top-bar/src/components/gitLogin.tsx +++ b/libs/remix-ui/top-bar/src/components/gitLogin.tsx @@ -4,7 +4,6 @@ import { Button, ButtonGroup, Dropdown } from 'react-bootstrap' import { CustomTopbarMenu } from '@remix-ui/helper' import { publishToGist } from 'libs/remix-ui/workspace/src/lib/actions' import { AppContext } from '@remix-ui/app' -import { gitUIPanels } from 'libs/remix-ui/git/src/types' const _paq = window._paq || [] @@ -24,25 +23,16 @@ export const GitHubLogin: React.FC = ({ const gitHubUser = appContext?.appState?.gitHubUser const isConnected = gitHubUser?.isConnected - // Simple login handler that delegates to the dgit plugin + // Simple login handler that delegates to the app context const handleLogin = useCallback(async () => { if (isLoading) return setIsLoading(true) try { - // Check if dgit plugin is active and activate if needed - const isActive = await appContext.appManager.call('manager', 'isActive', 'dgit') - if (!isActive) { - await appContext.appManager.call('manager', 'activatePlugin', 'dgit') - } - - // Open the GitHub panel in the git plugin and let it handle the login - await appContext.appManager.call('menuicons', 'select', 'dgit') - await appContext.appManager.call('dgit', 'open', gitUIPanels.GITHUB) - + await appContext.loginWithGitHub() } catch (error) { - console.error('Failed to open GitHub login:', error) + console.error('Failed to start GitHub login:', error) } finally { setIsLoading(false) } From 9b193775ac53ff47fe830afc7933c9b2e76131ed Mon Sep 17 00:00:00 2001 From: bunsenstraat Date: Tue, 2 Sep 2025 14:56:47 +0200 Subject: [PATCH 4/6] refactor --- apps/remix-ide/src/app/plugins/git.tsx | 10 +- .../app/src/lib/remix-app/context/context.tsx | 1 - .../app/src/lib/remix-app/remix-app.tsx | 22 +---- .../git/src/components/github/devicecode.tsx | 22 ++--- libs/remix-ui/git/src/lib/gitLoginActions.ts | 16 +++- libs/remix-ui/git/src/lib/listeners.ts | 18 +++- .../top-bar/src/components/gitLogin.tsx | 94 +++++++++---------- .../src/components/githubLoginSuccess.tsx | 83 ---------------- .../top-bar/src/lib/remix-ui-topbar.tsx | 60 ++++++------ 9 files changed, 119 insertions(+), 207 deletions(-) delete mode 100644 libs/remix-ui/top-bar/src/components/githubLoginSuccess.tsx diff --git a/apps/remix-ide/src/app/plugins/git.tsx b/apps/remix-ide/src/app/plugins/git.tsx index 6e2cd72aea1..3dac3ff2e30 100644 --- a/apps/remix-ide/src/app/plugins/git.tsx +++ b/apps/remix-ide/src/app/plugins/git.tsx @@ -8,7 +8,7 @@ const profile = { name: 'dgit', displayName: 'Git', description: 'Git plugin for Remix', - methods: ['open', 'init', 'startLogin'], + methods: ['open', 'init', 'login', 'logOut'], events: [''], version: packageJson.version, maintainedBy: 'Remix', @@ -41,8 +41,12 @@ export class GitPlugin extends ViewPlugin { return
} - async startLogin(){ - this.emit('startLogin') + async login(){ + this.emit('login') + } + + async logOut(){ + this.emit('disconnect') } } diff --git a/libs/remix-ui/app/src/lib/remix-app/context/context.tsx b/libs/remix-ui/app/src/lib/remix-app/context/context.tsx index a93afd9c55b..48aa1b391e1 100644 --- a/libs/remix-ui/app/src/lib/remix-app/context/context.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/context/context.tsx @@ -11,7 +11,6 @@ export type appProviderContextType = { modal: any appState: AppState appStateDispatch: React.Dispatch - loginWithGitHub: () => Promise } export enum appPlatformTypes { diff --git a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx index 90f02829e30..c936272b5c3 100644 --- a/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx +++ b/libs/remix-ui/app/src/lib/remix-app/remix-app.tsx @@ -199,27 +199,7 @@ const RemixApp = (props: IRemixAppUi) => { showEnter: props.app.showEnter, modal: props.app.notification, appState: appState, - appStateDispatch: appStateDispatch, - loginWithGitHub: async () => { - try { - // Activate dgit plugin if not active - const isActive = await props.app.appManager.call('manager', 'isActive', 'dgit') - if (!isActive) { - await props.app.appManager.call('manager', 'activatePlugin', 'dgit') - } - - // Emit the startLogin event to trigger the abstracted login logic - await props.app.appManager.call('dgit', 'startLogin') - } catch (error) { - console.error('Failed to trigger GitHub login:', error) - // Optionally show a user-friendly error - props.app.notification.alert({ - id: 'github-login-error', - title: 'Login Error', - message: 'Failed to start GitHub login. Please try again.' - }) - } - } + appStateDispatch: appStateDispatch } const handleUserChosenType = async (type) => { diff --git a/libs/remix-ui/git/src/components/github/devicecode.tsx b/libs/remix-ui/git/src/components/github/devicecode.tsx index 9b785d518aa..d5b33784d00 100644 --- a/libs/remix-ui/git/src/components/github/devicecode.tsx +++ b/libs/remix-ui/git/src/components/github/devicecode.tsx @@ -7,7 +7,7 @@ import { sendToMatomo } from "../../lib/pluginActions"; import { gitMatomoEventTypes } from "../../types"; import { endpointUrls } from "@remix-endpoints-helper"; import isElectron from "is-electron"; -import { startGitHubLogin, getDeviceCodeFromGitHub, connectWithDeviceCode } from "../../lib/gitLoginActions"; +import { startGitHubLogin, getDeviceCodeFromGitHub, connectWithDeviceCode, disconnectFromGitHub } from "../../lib/gitLoginActions"; export const GetDeviceCode = () => { const context = React.useContext(gitPluginContext) @@ -25,9 +25,7 @@ export const GetDeviceCode = () => { if (isElectron()) { setDesktopIsLoading(true) } - await startGitHubLogin() - if (!isElectron()) { setAuthorized(true) } @@ -47,7 +45,7 @@ export const GetDeviceCode = () => { setDesktopIsLoading(false) setPopupError(false) setAuthorized(false) - + try { const githubResponse = await getDeviceCodeFromGitHub() setGitHubResponse(githubResponse) @@ -73,12 +71,14 @@ export const GetDeviceCode = () => { } },[context.gitHubUser]) - const disconnect = async () => { - await sendToMatomo(gitMatomoEventTypes.DISCONNECTFROMGITHUB) - setAuthorized(false) - setGitHubResponse(null) - await pluginActions.saveToken(null) - await actions.loadGitHubUserFromToken() + const handleDisconnect = async () => { + try { + await disconnectFromGitHub() + setAuthorized(false) + setGitHubResponse(null) + } catch (error) { + console.error('Failed to disconnect from GitHub:', error) + } } return ( @@ -131,7 +131,7 @@ export const GetDeviceCode = () => { (context.gitHubUser && context.gitHubUser.isConnected) ?
: null } diff --git a/libs/remix-ui/git/src/lib/gitLoginActions.ts b/libs/remix-ui/git/src/lib/gitLoginActions.ts index 821d4087722..20a9c177045 100644 --- a/libs/remix-ui/git/src/lib/gitLoginActions.ts +++ b/libs/remix-ui/git/src/lib/gitLoginActions.ts @@ -91,7 +91,7 @@ const startWebPopupLogin = async (): Promise => { }; window.addEventListener('message', messageListener); - + // Check if popup was closed without authentication const checkClosed = setInterval(() => { if (popup?.closed) { @@ -106,7 +106,7 @@ const startWebPopupLogin = async (): Promise => { // Device code flow fallback (can be called from components if needed) export const getDeviceCodeFromGitHub = async (): Promise => { await sendToMatomo(gitMatomoEventTypes.GETGITHUBDEVICECODE); - + const response = await axios({ method: 'post', url: `${endpointUrls.github}/login/device/code`, @@ -149,3 +149,15 @@ export const connectWithDeviceCode = async (deviceCode: string): Promise = throw new Error('Failed to get access token from device code'); } }; + +// Disconnect from GitHub +export const disconnectFromGitHub = async (): Promise => { + try { + await sendToMatomo(gitMatomoEventTypes.DISCONNECTFROMGITHUB); + await saveToken(null); + await loadGitHubUserFromToken(); + } catch (error) { + console.error('Failed to disconnect from GitHub:', error); + throw error; + } +}; diff --git a/libs/remix-ui/git/src/lib/listeners.ts b/libs/remix-ui/git/src/lib/listeners.ts index a6087160f29..b640d7b45ba 100644 --- a/libs/remix-ui/git/src/lib/listeners.ts +++ b/libs/remix-ui/git/src/lib/listeners.ts @@ -9,7 +9,7 @@ import { CustomRemixApi } from "@remix-api"; import { saveToken, sendToMatomo, statusChanged } from "./pluginActions"; import { appPlatformTypes } from "@remix-ui/app"; import { AppAction } from "@remix-ui/app"; -import { setLoginPlugin, startGitHubLogin } from "./gitLoginActions"; +import { setLoginPlugin, startGitHubLogin, disconnectFromGitHub } from "./gitLoginActions"; let plugin: Plugin, gitDispatch: React.Dispatch, loaderDispatch: React.Dispatch, loadFileQueue: AsyncDebouncedQueue let callBackEnabled: boolean = false @@ -44,7 +44,6 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { + plugin.on('dgit' as any, 'login', async () => { try { await startGitHubLogin() } catch (error) { @@ -224,6 +223,19 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch { + try { + await disconnectFromGitHub() + } catch (error) { + console.error('Failed to disconnect from GitHub from dgit plugin:', error) + // Optionally show error to user + gitDispatch(setLog({ + message: `GitHub disconnect failed: ${error.message}`, + type: "error" + })) + } + }) + plugin.on('githubAuthHandler', 'onLogin', async (data: { token: string }) => { await saveToken(data.token) await loadGitHubUserFromToken() diff --git a/libs/remix-ui/top-bar/src/components/gitLogin.tsx b/libs/remix-ui/top-bar/src/components/gitLogin.tsx index ab1b7728623..9503e9a1375 100644 --- a/libs/remix-ui/top-bar/src/components/gitLogin.tsx +++ b/libs/remix-ui/top-bar/src/components/gitLogin.tsx @@ -1,8 +1,7 @@ /* eslint-disable @nrwl/nx/enforce-module-boundaries */ -import React, { useContext, useState, useCallback, useEffect } from 'react' +import React, { useContext, useCallback } from 'react' import { Button, ButtonGroup, Dropdown } from 'react-bootstrap' import { CustomTopbarMenu } from '@remix-ui/helper' -import { publishToGist } from 'libs/remix-ui/workspace/src/lib/actions' import { AppContext } from '@remix-ui/app' const _paq = window._paq || [] @@ -10,40 +9,30 @@ const _paq = window._paq || [] interface GitHubLoginProps { cloneGitRepository: () => void logOutOfGithub: () => void + loginWithGitHub: () => Promise + publishToGist: () => void } export const GitHubLogin: React.FC = ({ cloneGitRepository, - logOutOfGithub + logOutOfGithub, + publishToGist, + loginWithGitHub }) => { const appContext = useContext(AppContext) - const [isLoading, setIsLoading] = useState(false) // Get the GitHub user state from app context const gitHubUser = appContext?.appState?.gitHubUser const isConnected = gitHubUser?.isConnected - // Simple login handler that delegates to the app context + // Simple login handler that delegates to the prop function const handleLogin = useCallback(async () => { - if (isLoading) return - - setIsLoading(true) - try { - await appContext.loginWithGitHub() + await loginWithGitHub() } catch (error) { console.error('Failed to start GitHub login:', error) - } finally { - setIsLoading(false) - } - }, [appContext, isLoading]) - - // Monitor GitHub user state changes to stop loading when connection is established - useEffect(() => { - if (isConnected && isLoading) { - setIsLoading(false) } - }, [isConnected, isLoading]) + }, [loginWithGitHub]) return ( = ({ > - - - - - - Clone - - { - await publishToGist() - _paq.push(['trackEvent', 'topbar', 'GIT', 'publishToGist']) - }} - > - - Publish to Gist - - - { - handleLogout() - _paq.push(['trackEvent', 'topbar', 'GIT', 'logout']) - }} - className="text-danger" - > - - Disconnect - - - - ) -} diff --git a/libs/remix-ui/top-bar/src/lib/remix-ui-topbar.tsx b/libs/remix-ui/top-bar/src/lib/remix-ui-topbar.tsx index 45ab780d483..4d8dbaa9bc3 100644 --- a/libs/remix-ui/top-bar/src/lib/remix-ui-topbar.tsx +++ b/libs/remix-ui/top-bar/src/lib/remix-ui-topbar.tsx @@ -1,9 +1,9 @@ /* eslint-disable @nrwl/nx/enforce-module-boundaries */ -import React, { MutableRefObject, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react' +import React, { useContext, useEffect, useMemo, useRef, useState } from 'react' import BasicLogo from '../components/BasicLogo' import '../css/topbar.css' -import { Button, ButtonGroup, Dropdown } from 'react-bootstrap' -import { CustomMenu, CustomToggle, CustomTopbarMenu } from 'libs/remix-ui/helper/src/lib/components/custom-dropdown' +import { Button, Dropdown } from 'react-bootstrap' +import { CustomToggle, CustomTopbarMenu } from 'libs/remix-ui/helper/src/lib/components/custom-dropdown' import { WorkspaceMetadata } from 'libs/remix-ui/workspace/src/lib/types' import { appPlatformTypes, platformContext } from 'libs/remix-ui/app/src/lib/remix-app/context/context' import { FormattedMessage, useIntl } from 'react-intl' @@ -11,16 +11,13 @@ import { TopbarContext } from '../context/topbarContext' import { WorkspacesDropdown } from '../components/WorkspaceDropdown' import { useOnClickOutside } from 'libs/remix-ui/remix-ai-assistant/src/components/onClickOutsideHook' import { cloneRepository, deleteWorkspace, fetchWorkspaceDirectory, deleteAllWorkspaces as deleteAllWorkspacesAction, handleDownloadFiles, handleDownloadWorkspace, handleExpandPath, publishToGist, renameWorkspace, restoreBackupZip, switchToWorkspace } from 'libs/remix-ui/workspace/src/lib/actions' -import { gitUIPanels } from 'libs/remix-ui/git/src/types' -import { loginWithGitHub, setPlugin } from 'libs/remix-ui/git/src/lib/pluginActions' import { GitHubUser } from 'libs/remix-api/src/lib/types/git' import { GitHubCallback } from '../topbarUtils/gitOauthHandler' import { GitHubLogin } from '../components/gitLogin' -import GithubLoginSuccess from '../components/githubLoginSuccess' const _paq = window._paq || [] -export function RemixUiTopbar () { +export function RemixUiTopbar() { const intl = useIntl() const [showDropdown, setShowDropdown] = useState(false) const platform = useContext(platformContext) @@ -145,7 +142,7 @@ export function RemixUiTopbar () { intl.formatMessage({ id: 'filePanel.workspace.rename' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), - () => {}, + () => { }, intl.formatMessage({ id: 'filePanel.cancel' }) ) console.error(e) @@ -160,7 +157,7 @@ export function RemixUiTopbar () { intl.formatMessage({ id: 'filePanel.workspace.download' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), - () => {}, + () => { }, intl.formatMessage({ id: 'filePanel.cancel' }) ) console.error(e) @@ -174,7 +171,7 @@ export function RemixUiTopbar () { intl.formatMessage({ id: 'filePanel.workspace.delete' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), - () => {}, + () => { }, intl.formatMessage({ id: 'filePanel.cancel' }) ) console.error(e) @@ -214,7 +211,7 @@ export function RemixUiTopbar () { intl.formatMessage({ id: 'filePanel.workspace.deleteAll' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), - () => {}, + () => { }, intl.formatMessage({ id: 'filePanel.cancel' }) ) console.error(e) @@ -252,9 +249,14 @@ export function RemixUiTopbar () { ) } + const loginWithGitHub = async () => { + global.plugin.call('dgit', 'login') + _paq.push(['trackEvent', 'Workspace', 'GIT', 'login']) + } + const logOutOfGithub = async () => { - await global.plugin.call('menuicons', 'select', 'dgit'); - await global.plugin.call('dgit', 'open', gitUIPanels.GITHUB) + global.plugin.call('dgit', 'logOut') + _paq.push(['trackEvent', 'Workspace', 'GIT', 'logout']) } @@ -267,8 +269,8 @@ export function RemixUiTopbar () { global.modal( intl.formatMessage({ id: 'filePanel.workspace.clone' }), intl.formatMessage({ id: 'filePanel.workspace.cloneMessage' }), - intl.formatMessage({ id: (platform !== appPlatformTypes.desktop)? 'filePanel.ok':'filePanel.selectFolder' }), - () => {}, + intl.formatMessage({ id: (platform !== appPlatformTypes.desktop) ? 'filePanel.ok' : 'filePanel.selectFolder' }), + () => { }, intl.formatMessage({ id: 'filePanel.cancel' }) ) } @@ -278,7 +280,7 @@ export function RemixUiTopbar () { global.modal( intl.formatMessage({ id: 'filePanel.workspace.clone' }), cloneModalMessage(), - intl.formatMessage({ id: (platform !== appPlatformTypes.desktop)? 'filePanel.ok':'filePanel.selectFolder' }), + intl.formatMessage({ id: (platform !== appPlatformTypes.desktop) ? 'filePanel.ok' : 'filePanel.selectFolder' }), handleTypingUrl, intl.formatMessage({ id: 'filePanel.cancel' }) ) @@ -335,7 +337,7 @@ export function RemixUiTopbar () { const checkIfLightTheme = (themeName: string) => themeName.includes('dark') || themeName.includes('black') || themeName.includes('hackerOwl') ? false : true - const IsGitRepoDropDownMenuItem = (props: { isGitRepo: boolean, mName: string}) => { + const IsGitRepoDropDownMenuItem = (props: { isGitRepo: boolean, mName: string }) => { return ( <> {props.isGitRepo ? ( @@ -368,7 +370,7 @@ export function RemixUiTopbar () { intl.formatMessage({ id: 'filePanel.workspace.switch' }), e.message, intl.formatMessage({ id: 'filePanel.ok' }), - () => {}, + () => { }, intl.formatMessage({ id: 'filePanel.cancel' }) ) console.error(e) @@ -379,7 +381,7 @@ export function RemixUiTopbar () { return ( <> - { global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => ( + {global.fs.browser.workspaces.map(({ name, isGitRepo }, index) => (
<> - {user ? ( - - ) : ( - - )} + Date: Thu, 4 Sep 2025 12:28:20 +0200 Subject: [PATCH 5/6] fix events styling --- .../git/src/components/github/devicecode.tsx | 3 +- libs/remix-ui/git/src/components/gitui.tsx | 4 +- libs/remix-ui/git/src/lib/gitLoginActions.ts | 85 +++++++++++-------- libs/remix-ui/git/src/types/index.ts | 8 ++ .../top-bar/src/components/gitLogin.tsx | 8 +- libs/remix-ui/top-bar/src/css/topbar.css | 5 ++ .../top-bar/src/lib/remix-ui-topbar.tsx | 4 +- 7 files changed, 72 insertions(+), 45 deletions(-) diff --git a/libs/remix-ui/git/src/components/github/devicecode.tsx b/libs/remix-ui/git/src/components/github/devicecode.tsx index d5b33784d00..3af50fb94b1 100644 --- a/libs/remix-ui/git/src/components/github/devicecode.tsx +++ b/libs/remix-ui/git/src/components/github/devicecode.tsx @@ -9,7 +9,7 @@ import { endpointUrls } from "@remix-endpoints-helper"; import isElectron from "is-electron"; import { startGitHubLogin, getDeviceCodeFromGitHub, connectWithDeviceCode, disconnectFromGitHub } from "../../lib/gitLoginActions"; -export const GetDeviceCode = () => { +export const ConnectToGitHub = () => { const context = React.useContext(gitPluginContext) const actions = React.useContext(gitActionsContext) const pluginActions = React.useContext(pluginActionsContext) @@ -21,6 +21,7 @@ export const GetDeviceCode = () => { const popupRef = useRef(null) const openPopupLogin = useCallback(async () => { + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBBUTTON) try { if (isElectron()) { setDesktopIsLoading(true) diff --git a/libs/remix-ui/git/src/components/gitui.tsx b/libs/remix-ui/git/src/components/gitui.tsx index 84d5b8585a1..c4410f33313 100644 --- a/libs/remix-ui/git/src/components/gitui.tsx +++ b/libs/remix-ui/git/src/components/gitui.tsx @@ -21,7 +21,7 @@ import { RemotesNavigation } from './navigation/remotes' import { Remotes } from './panels/remotes' import { GitHubNavigation } from './navigation/github' import { loaderReducer } from '../state/loaderReducer' -import { GetDeviceCode } from './github/devicecode' +import { ConnectToGitHub } from './github/devicecode' import { LogNavigation } from './navigation/log' import LogViewer from './panels/log' import { SourceControlBase } from './buttons/sourceControlBase' @@ -241,7 +241,7 @@ export const GitUI = (props: IGitUi) => {
- +
diff --git a/libs/remix-ui/git/src/lib/gitLoginActions.ts b/libs/remix-ui/git/src/lib/gitLoginActions.ts index 20a9c177045..8118116b679 100644 --- a/libs/remix-ui/git/src/lib/gitLoginActions.ts +++ b/libs/remix-ui/git/src/lib/gitLoginActions.ts @@ -58,9 +58,10 @@ const startWebPopupLogin = async (): Promise => { const scope = 'repo gist user:email read:user'; const url = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&response_type=code`; - + await sendToMatomo(gitMatomoEventTypes.OPENLOGINMODAL) const popup = window.open(url, '_blank', 'width=600,height=700'); if (!popup) { + await sendToMatomo(gitMatomoEventTypes.LOGINMODALFAIL); console.warn('Popup blocked or failed to open, falling back to device code flow.'); throw new Error('Popup blocked - please allow popups for this site or use device code flow'); } @@ -84,6 +85,7 @@ const startWebPopupLogin = async (): Promise => { reject(error); } } else if (event.data.type === 'GITHUB_AUTH_FAILURE') { + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBFAIL); window.removeEventListener('message', messageListener); popup?.close(); reject(new Error('GitHub authentication failed')); @@ -106,47 +108,62 @@ const startWebPopupLogin = async (): Promise => { // Device code flow fallback (can be called from components if needed) export const getDeviceCodeFromGitHub = async (): Promise => { await sendToMatomo(gitMatomoEventTypes.GETGITHUBDEVICECODE); + try { + const response = await axios({ + method: 'post', + url: `${endpointUrls.github}/login/device/code`, + data: { + client_id: '2795b4e41e7197d6ea11', + scope: 'repo gist user:email read:user' + }, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + }); + await sendToMatomo(gitMatomoEventTypes.GET_GITHUB_DEVICECODE_SUCCESS); + return response.data; - const response = await axios({ - method: 'post', - url: `${endpointUrls.github}/login/device/code`, - data: { - client_id: '2795b4e41e7197d6ea11', - scope: 'repo gist user:email read:user' - }, - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - }); + } catch (error) { + await sendToMatomo(gitMatomoEventTypes.GET_GITHUB_DEVICECODE_FAIL); + throw new Error('Failed to get device code from GitHub'); + + } - return response.data; }; // Connect using device code export const connectWithDeviceCode = async (deviceCode: string): Promise => { - const response = await axios({ - method: 'post', - url: `${endpointUrls.github}/login/oauth/access_token`, - data: { - client_id: '2795b4e41e7197d6ea11', - device_code: deviceCode, - grant_type: 'urn:ietf:params:oauth:grant-type:device_code' - }, - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - }); + await sendToMatomo(gitMatomoEventTypes.DEVICECODEAUTH); + try { + const response = await axios({ + method: 'post', + url: `${endpointUrls.github}/login/oauth/access_token`, + data: { + client_id: '2795b4e41e7197d6ea11', + device_code: deviceCode, + grant_type: 'urn:ietf:params:oauth:grant-type:device_code' + }, + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json' + }, + }); - const data = response.data; + const data = response.data; - if (data.access_token) { - await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS); - await saveToken(data.access_token); - await loadGitHubUserFromToken(); - } else { - throw new Error('Failed to get access token from device code'); + if (data.access_token) { + await sendToMatomo(gitMatomoEventTypes.CONNECTTOGITHUBSUCCESS); + await sendToMatomo(gitMatomoEventTypes.DEVICE_CODE_AUTH_SUCCESS); + await saveToken(data.access_token); + await loadGitHubUserFromToken(); + } else { + await sendToMatomo(gitMatomoEventTypes.DEVICE_CODE_AUTH_FAIL); + throw new Error('Failed to get access token from device code'); + } + } catch (error) { + await sendToMatomo(gitMatomoEventTypes.DEVICE_CODE_AUTH_FAIL); + throw new Error('Failed to connect with device code'); } }; diff --git a/libs/remix-ui/git/src/types/index.ts b/libs/remix-ui/git/src/types/index.ts index f87ee222f82..5b6e1e9283c 100644 --- a/libs/remix-ui/git/src/types/index.ts +++ b/libs/remix-ui/git/src/types/index.ts @@ -158,13 +158,21 @@ export enum gitMatomoEventTypes { BRANCH = 'BRANCH', CREATEBRANCH = 'CREATEBRANCH', GETGITHUBDEVICECODE = 'GET_GITHUB_DEVICECODE', + GET_GITHUB_DEVICECODE_SUCCESS = 'GET_GITHUB_DEVICECODE_SUCCESS', + GET_GITHUB_DEVICECODE_FAIL = 'GET_GITHUB_DEVICECODE_FAIL', + DEVICECODEAUTH = 'DEVICE_CODE_AUTH', + DEVICE_CODE_AUTH_SUCCESS = 'DEVICE_CODE_AUTH_SUCCESS', + DEVICE_CODE_AUTH_FAIL = 'DEVICE_CODE_AUTH_FAIL', CONNECTTOGITHUB = 'CONNECT_TO_GITHUB', + CONNECTTOGITHUBBUTTON = 'CONNECT_TO_GITHUB_BUTTON', DISCONNECTFROMGITHUB = 'DISCONNECT_FROM_GITHUB', SAVEMANUALGITHUBCREDENTIALS = 'SAVE_MANUAL_GITHUB_CREDENTIALS', LOADREPOSITORIESFROMGITHUB = 'LOAD_REPOSITORIES_FROM_GITHUB', COPYGITHUBDEVICECODE = 'COPY_GITHUB_DEVICE_CODE', CONNECTTOGITHUBSUCCESS = 'CONNECT_TO_GITHUB_SUCCESS', CONNECTTOGITHUBFAIL = 'CONNECT_TO_GITHUB_FAIL', + OPENLOGINMODAL = 'OPEN_LOGIN_MODAL', + LOGINMODALFAIL = 'LOGIN_MODAL_FAIL', OPENPANEL = 'OPEN_PANEL', ADDMANUALREMOTE = 'ADD_MANUAL_REMOTE', SETDEFAULTREMOTE = 'SET_DEFAULT_REMOTE', diff --git a/libs/remix-ui/top-bar/src/components/gitLogin.tsx b/libs/remix-ui/top-bar/src/components/gitLogin.tsx index 9503e9a1375..a1ce59245a8 100644 --- a/libs/remix-ui/top-bar/src/components/gitLogin.tsx +++ b/libs/remix-ui/top-bar/src/components/gitLogin.tsx @@ -40,13 +40,9 @@ export const GitHubLogin: React.FC = ({ align="end" >