Skip to content

Commit 373b12b

Browse files
committed
wip
Signed-off-by: Adam Setch <[email protected]>
1 parent 4955efc commit 373b12b

File tree

5 files changed

+133
-106
lines changed

5 files changed

+133
-106
lines changed

src/main/main.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ const mb = menubar({
3737
const menuBuilder = new MenuBuilder(mb);
3838
const contextMenu = menuBuilder.buildMenu();
3939

40-
/**
41-
* Electron Auto Updater only supports macOS and Windows
42-
* https://github.com/electron/update-electron-app
43-
*/
40+
// Register your app as the handler for a custom protocol
41+
app.setAsDefaultProtocolClient('gitify');
42+
4443
if (isMacOS() || isWindows()) {
44+
/**
45+
* Electron Auto Updater only supports macOS and Windows
46+
* https://github.com/electron/update-electron-app
47+
*/
4548
const updater = new Updater(mb, menuBuilder);
4649
updater.initialize();
4750
}
@@ -186,3 +189,15 @@ app.whenReady().then(async () => {
186189
app.setLoginItemSettings(settings);
187190
});
188191
});
192+
193+
app.on('open-url', (event, url) => {
194+
event.preventDefault();
195+
const code = new URL(url).searchParams.get('code'); // Extract the authorization code
196+
console.log('Authorization Code:', code);
197+
198+
if (code) {
199+
// Exchange the code for an access token
200+
mb.window.webContents.send(namespacedEvent('auth-code'), code);
201+
// exchangeCodeForToken(code);
202+
}
203+
});

src/renderer/context/App.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { useNotifications } from '../hooks/useNotifications';
1616
import {
1717
type Account,
1818
type AccountNotifications,
19+
type AuthCode,
1920
type AuthState,
2021
type GitifyError,
2122
GroupBy,
@@ -108,7 +109,7 @@ export const defaultSettings: SettingsState = {
108109
interface AppContextState {
109110
auth: AuthState;
110111
isLoggedIn: boolean;
111-
loginWithGitHubApp: () => void;
112+
loginWithGitHubApp: (authCode: AuthCode) => void;
112113
loginWithOAuthApp: (data: LoginOAuthAppOptions) => void;
113114
loginWithPersonalAccessToken: (data: LoginPersonalAccessTokenOptions) => void;
114115
logoutFromAccount: (account: Account) => void;
@@ -231,14 +232,17 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
231232
return hasAccounts(auth);
232233
}, [auth]);
233234

234-
const loginWithGitHubApp = useCallback(async () => {
235-
const { authCode } = await authGitHub();
236-
const { token } = await getToken(authCode);
237-
const hostname = Constants.DEFAULT_AUTH_OPTIONS.hostname;
238-
const updatedAuth = await addAccount(auth, 'GitHub App', token, hostname);
239-
setAuth(updatedAuth);
240-
saveState({ auth: updatedAuth, settings });
241-
}, [auth, settings]);
235+
const loginWithGitHubApp = useCallback(
236+
async (authCode: AuthCode) => {
237+
// const { authCode } = await authGitHub();
238+
const { token } = await getToken(authCode);
239+
const hostname = Constants.DEFAULT_AUTH_OPTIONS.hostname;
240+
const updatedAuth = await addAccount(auth, 'GitHub App', token, hostname);
241+
setAuth(updatedAuth);
242+
saveState({ auth: updatedAuth, settings });
243+
},
244+
[auth, settings],
245+
);
242246

243247
const loginWithOAuthApp = useCallback(
244248
async (data: LoginOAuthAppOptions) => {

src/renderer/routes/Accounts.tsx

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@ import {
2222
Text,
2323
} from '@primer/react';
2424

25-
import { logError } from '../../shared/logger';
2625
import { AvatarWithFallback } from '../components/avatars/AvatarWithFallback';
2726
import { Contents } from '../components/layout/Contents';
2827
import { Page } from '../components/layout/Page';
2928
import { Footer } from '../components/primitives/Footer';
3029
import { Header } from '../components/primitives/Header';
3130
import { AppContext } from '../context/App';
32-
import { type Account, Size } from '../types';
31+
import { type Account, type Link, Size } from '../types';
3332
import {
3433
formatRequiredScopes,
3534
getAccountUUID,
3635
refreshAccount,
3736
} from '../utils/auth/utils';
38-
import { updateTrayIcon, updateTrayTitle } from '../utils/comms';
37+
import {
38+
openExternalLink,
39+
updateTrayIcon,
40+
updateTrayTitle,
41+
} from '../utils/comms';
3942
import { getAuthMethodIcon, getPlatformIcon } from '../utils/icons';
4043
import {
4144
openAccountProfile,
@@ -45,8 +48,7 @@ import {
4548
import { saveState } from '../utils/storage';
4649

4750
export const AccountsRoute: FC = () => {
48-
const { auth, settings, loginWithGitHubApp, logoutFromAccount } =
49-
useContext(AppContext);
51+
const { auth, settings, logoutFromAccount } = useContext(AppContext);
5052
const navigate = useNavigate();
5153

5254
const logoutAccount = useCallback(
@@ -65,14 +67,6 @@ export const AccountsRoute: FC = () => {
6567
navigate('/accounts', { replace: true });
6668
}, []);
6769

68-
const loginWithGitHub = useCallback(async () => {
69-
try {
70-
await loginWithGitHubApp();
71-
} catch (err) {
72-
logError('loginWithGitHub', 'failed to login with GitHub', err);
73-
}
74-
}, []);
75-
7670
const loginWithPersonalAccessToken = useCallback(() => {
7771
return navigate('/login-personal-access-token', { replace: true });
7872
}, []);
@@ -237,7 +231,7 @@ export const AccountsRoute: FC = () => {
237231
<ActionMenu.Overlay width="medium">
238232
<ActionList>
239233
<ActionList.Item
240-
onSelect={() => loginWithGitHub()}
234+
onSelect={() => openExternalLink('https://github.com' as Link)}
241235
data-testid="account-add-github"
242236
>
243237
<ActionList.LeadingVisual>

src/renderer/routes/Login.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { KeyIcon, MarkGithubIcon, PersonIcon } from '@primer/octicons-react';
22
import { Button, Heading, Stack, Text } from '@primer/react';
3-
import { type FC, useCallback, useContext, useEffect } from 'react';
3+
import { type FC, useContext, useEffect } from 'react';
44
import { useNavigate } from 'react-router-dom';
55

6-
import { logError } from '../../shared/logger';
6+
import { ipcRenderer } from 'electron';
7+
import { namespacedEvent } from '../../shared/events';
78
import { LogoIcon } from '../components/icons/LogoIcon';
89
import { Centered } from '../components/layout/Centered';
910
import { AppContext } from '../context/App';
10-
import { Size } from '../types';
11-
import { showWindow } from '../utils/comms';
11+
import { type AuthCode, type Link, Size } from '../types';
12+
import { openExternalLink, showWindow } from '../utils/comms';
1213

1314
export const LoginRoute: FC = () => {
1415
const navigate = useNavigate();
@@ -21,14 +22,21 @@ export const LoginRoute: FC = () => {
2122
}
2223
}, [isLoggedIn]);
2324

24-
const loginUser = useCallback(() => {
25-
try {
26-
loginWithGitHubApp();
27-
} catch (err) {
28-
logError('loginWithGitHubApp', 'failed to login with GitHub', err);
29-
}
25+
useEffect(() => {
26+
ipcRenderer.on(namespacedEvent('auth-code'), (_, authCode: AuthCode) => {
27+
console.log('RENDER AUTH CODE', authCode);
28+
loginWithGitHubApp(authCode);
29+
});
3030
}, [loginWithGitHubApp]);
3131

32+
// const loginUser = useCallback(() => {
33+
// try {
34+
// loginWithGitHubApp();
35+
// } catch (err) {
36+
// logError('loginWithGitHubApp', 'failed to login with GitHub', err);
37+
// }
38+
// }, [loginWithGitHubApp]);
39+
3240
return (
3341
<Centered fullHeight={true}>
3442
<Stack direction="vertical" align="center">
@@ -45,7 +53,7 @@ export const LoginRoute: FC = () => {
4553
<Button
4654
leadingVisual={MarkGithubIcon}
4755
variant="primary"
48-
onClick={() => loginUser()}
56+
onClick={() => openExternalLink('https://github.com' as Link)}
4957
data-testid="login-github"
5058
>
5159
GitHub

src/renderer/utils/auth/utils.ts

Lines changed: 74 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -17,79 +17,85 @@ import type {
1717
import type { UserDetails } from '../../typesGitHub';
1818
import { getAuthenticatedUser } from '../api/client';
1919
import { apiRequest } from '../api/request';
20+
import { openExternalLink } from '../comms';
2021
import { Constants } from '../constants';
2122
import { getPlatformFromHostname } from '../helpers';
2223
import type { AuthMethod, AuthResponse, AuthTokenResponse } from './types';
2324

2425
// TODO - Refactor our OAuth2 flow to use system browser and local app gitify://callback - see #485 #561 #654
25-
export function authGitHub(
26-
authOptions = Constants.DEFAULT_AUTH_OPTIONS,
27-
): Promise<AuthResponse> {
28-
return new Promise((resolve, reject) => {
29-
// Build the OAuth consent page URL
30-
const authWindow = new BrowserWindow({
31-
width: 548,
32-
height: 736,
33-
show: true,
34-
});
35-
36-
const authUrl = new URL(`https://${authOptions.hostname}`);
37-
authUrl.pathname = '/login/oauth/authorize';
38-
authUrl.searchParams.append('client_id', authOptions.clientId);
39-
authUrl.searchParams.append('scope', Constants.AUTH_SCOPE.toString());
40-
41-
const session = authWindow.webContents.session;
42-
session.clearStorageData();
43-
44-
authWindow.loadURL(authUrl.toString());
45-
46-
const handleCallback = (url: Link) => {
47-
const raw_code = /code=([^&]*)/.exec(url) || null;
48-
const authCode =
49-
raw_code && raw_code.length > 1 ? (raw_code[1] as AuthCode) : null;
50-
const error = /\?error=(.+)$/.exec(url);
51-
if (authCode || error) {
52-
// Close the browser if code found or error
53-
authWindow.destroy();
54-
}
55-
// If there is a code, proceed to get token from github
56-
if (authCode) {
57-
resolve({ authCode, authOptions });
58-
} else if (error) {
59-
reject(
60-
"Oops! Something went wrong and we couldn't " +
61-
'log you in using GitHub. Please try again.',
62-
);
63-
}
64-
};
65-
66-
// If "Done" button is pressed, hide "Loading"
67-
authWindow.on('close', () => {
68-
authWindow.destroy();
69-
});
70-
71-
authWindow.webContents.on(
72-
'did-fail-load',
73-
(_event, _errorCode, _errorDescription, validatedURL) => {
74-
if (validatedURL.includes(authOptions.hostname)) {
75-
authWindow.destroy();
76-
reject(
77-
`Invalid Hostname. Could not load https://${authOptions.hostname}/.`,
78-
);
79-
}
80-
},
81-
);
82-
83-
authWindow.webContents.on('will-redirect', (event, url) => {
84-
event.preventDefault();
85-
handleCallback(url as Link);
86-
});
87-
88-
authWindow.webContents.on('will-navigate', (event, url) => {
89-
event.preventDefault();
90-
handleCallback(url as Link);
91-
});
92-
});
26+
export function authGitHub(authOptions = Constants.DEFAULT_AUTH_OPTIONS) {
27+
const authUrl = new URL(`https://${authOptions.hostname}`);
28+
authUrl.pathname = '/login/oauth/authorize';
29+
authUrl.searchParams.append('client_id', authOptions.clientId);
30+
authUrl.searchParams.append('scope', Constants.AUTH_SCOPE.toString());
31+
32+
openExternalLink(authUrl.toString() as Link);
33+
34+
// return new Promise((resolve, reject) => {
35+
// // Build the OAuth consent page URL
36+
// const authWindow = new BrowserWindow({
37+
// width: 548,
38+
// height: 736,
39+
// show: true,
40+
// });
41+
42+
// const authUrl = new URL(`https://${authOptions.hostname}`);
43+
// authUrl.pathname = '/login/oauth/authorize';
44+
// authUrl.searchParams.append('client_id', authOptions.clientId);
45+
// authUrl.searchParams.append('scope', Constants.AUTH_SCOPE.toString());
46+
47+
// const session = authWindow.webContents.session;
48+
// session.clearStorageData();
49+
50+
// authWindow.loadURL(authUrl.toString());
51+
52+
// const handleCallback = (url: Link) => {
53+
// const raw_code = /code=([^&]*)/.exec(url) || null;
54+
// const authCode =
55+
// raw_code && raw_code.length > 1 ? (raw_code[1] as AuthCode) : null;
56+
// const error = /\?error=(.+)$/.exec(url);
57+
// if (authCode || error) {
58+
// // Close the browser if code found or error
59+
// authWindow.destroy();
60+
// }
61+
// // If there is a code, proceed to get token from github
62+
// if (authCode) {
63+
// resolve({ authCode, authOptions });
64+
// } else if (error) {
65+
// reject(
66+
// "Oops! Something went wrong and we couldn't " +
67+
// 'log you in using GitHub. Please try again.',
68+
// );
69+
// }
70+
// };
71+
72+
// // If "Done" button is pressed, hide "Loading"
73+
// authWindow.on('close', () => {
74+
// authWindow.destroy();
75+
// });
76+
77+
// authWindow.webContents.on(
78+
// 'did-fail-load',
79+
// (_event, _errorCode, _errorDescription, validatedURL) => {
80+
// if (validatedURL.includes(authOptions.hostname)) {
81+
// authWindow.destroy();
82+
// reject(
83+
// `Invalid Hostname. Could not load https://${authOptions.hostname}/.`,
84+
// );
85+
// }
86+
// },
87+
// );
88+
89+
// authWindow.webContents.on('will-redirect', (event, url) => {
90+
// event.preventDefault();
91+
// handleCallback(url as Link);
92+
// });
93+
94+
// authWindow.webContents.on('will-navigate', (event, url) => {
95+
// event.preventDefault();
96+
// handleCallback(url as Link);
97+
// });
98+
// });
9399
}
94100

95101
export async function getUserData(

0 commit comments

Comments
 (0)