refactor(auth): authenticate user in main window (#8032)

This commit is contained in:
forehalo
2024-09-03 09:03:46 +00:00
parent e33aa35f7e
commit 52c9da67f0
31 changed files with 561 additions and 509 deletions

View File

@@ -3,12 +3,13 @@ import path from 'node:path';
import type { App } from 'electron';
import { buildType, isDev } from './config';
import { mainWindowOrigin } from './constants';
import { logger } from './logger';
import { uiSubjects } from './ui';
import {
getMainWindow,
openUrlInHiddenWindow,
openUrlInMainWindow,
showMainWindow,
} from './windows-manager';
let protocol = buildType === 'stable' ? 'affine' : `affine-${buildType}`;
@@ -58,31 +59,39 @@ export function setupDeepLink(app: App) {
}
async function handleAffineUrl(url: string) {
await showMainWindow();
logger.info('open affine url', url);
const urlObj = new URL(url);
logger.info('handle affine schema action', urlObj.hostname);
if (urlObj.hostname === 'bring-to-front') {
const mainWindow = await getMainWindow();
if (mainWindow) {
mainWindow.show();
if (urlObj.hostname === 'authentication') {
const method = urlObj.searchParams.get('method');
const payload = JSON.parse(urlObj.searchParams.get('payload') ?? 'false');
if (
!method ||
(method !== 'magic-link' && method !== 'oauth') ||
!payload
) {
logger.error('Invalid authentication url', url);
return;
}
uiSubjects.authenticationRequest$.next({
method,
payload,
});
} else {
await openUrl(urlObj);
}
}
async function openUrl(urlObj: URL) {
const params = urlObj.searchParams;
const openInHiddenWindow = params.get('hidden');
params.delete('hidden');
const url = mainWindowOrigin + urlObj.pathname + '?' + params.toString();
if (!openInHiddenWindow) {
await openUrlInHiddenWindow(url);
} else {
// TODO(@pengx17): somehow the page won't load the url passed, help needed
await openUrlInMainWindow(url);
const hiddenWindow = urlObj.searchParams.get('hidden')
? await openUrlInHiddenWindow(urlObj)
: await openUrlInMainWindow(urlObj);
const main = await getMainWindow();
if (main && hiddenWindow) {
// when hidden window closed, the main window will be hidden somehow
hiddenWindow.on('close', () => {
main.show();
});
}
}
}

View File

@@ -1,5 +1,6 @@
import type { MainEventRegister } from '../type';
import {
type AuthenticationRequest,
onActiveTabChanged,
onTabAction,
onTabShellViewActiveChange,
@@ -35,4 +36,10 @@ export const uiEvents = {
onTabsStatusChange,
onActiveTabChanged,
onTabShellViewActiveChange,
onAuthenticationRequest: (fn: (state: AuthenticationRequest) => void) => {
const sub = uiSubjects.authenticationRequest$.subscribe(fn);
return () => {
sub.unsubscribe();
};
},
} satisfies Record<string, MainEventRegister>;

View File

@@ -1,7 +1,10 @@
import { Subject } from 'rxjs';
import type { AuthenticationRequest } from '../windows-manager';
export const uiSubjects = {
onMaximized$: new Subject<boolean>(),
onFullScreen$: new Subject<boolean>(),
onToggleRightSidebar$: new Subject<string>(),
authenticationRequest$: new Subject<AuthenticationRequest>(),
};

View File

@@ -0,0 +1,4 @@
export interface AuthenticationRequest {
method: 'magic-link' | 'oauth';
payload: Record<string, any>;
}

View File

@@ -1,3 +1,4 @@
export * from './authentication';
export * from './launcher';
export * from './main-window';
export * from './onboarding';

View File

@@ -6,6 +6,7 @@ import { BehaviorSubject } from 'rxjs';
import { isLinux, isMacOS, isWindows } from '../../shared/utils';
import { buildType } from '../config';
import { mainWindowOrigin } from '../constants';
import { ensureHelperProcess } from '../helper-process';
import { logger } from '../logger';
import { uiSubjects } from '../ui/subject';
@@ -227,33 +228,60 @@ export async function showMainWindow() {
window.focus();
}
const getWindowAdditionalArguments = async () => {
const { getExposedMeta } = await import('../exposed');
const mainExposedMeta = getExposedMeta();
return [
`--main-exposed-meta=` + JSON.stringify(mainExposedMeta),
`--window-name=hidden-window`,
];
};
function transformToAppUrl(url: URL) {
const params = url.searchParams;
return mainWindowOrigin + url.pathname + '?' + params.toString();
}
/**
* Open a URL in a hidden window.
*/
export async function openUrlInHiddenWindow(url: string) {
export async function openUrlInHiddenWindow(urlObj: URL) {
const url = transformToAppUrl(urlObj);
const win = new BrowserWindow({
width: 1200,
height: 600,
webPreferences: {
preload: join(__dirname, './preload.js'),
additionalArguments: await getWindowAdditionalArguments(),
},
show: environment.isDebug,
});
if (environment.isDebug) {
win.webContents.openDevTools();
}
win.on('close', e => {
e.preventDefault();
if (!win.isDestroyed()) {
if (win && !win.isDestroyed()) {
win.destroy();
}
});
logger.info('loading page at', url);
await win.loadURL(url);
win.loadURL(url).catch(e => {
logger.error('failed to load url', e);
});
return win;
}
export async function openUrlInMainWindow(url: string) {
// TODO(@pengx17): somehow the page won't load the url passed, help needed
export async function openUrlInMainWindow(urlObj: URL) {
const url = transformToAppUrl(urlObj);
logger.info('loading page at', url);
const mainWindow = await getMainWindow();
if (mainWindow) {
mainWindow.show();
await mainWindow.loadURL(url);
}
return null;
}