feat: auto open clone repo tab after login, by update windowMeta after reload

This commit is contained in:
linonetwo 2023-12-29 19:09:07 +08:00
parent e55097618f
commit 4724020772
17 changed files with 69 additions and 40 deletions

View file

@ -33,8 +33,6 @@ export function useGetGithubUserInfoOnLoad(): void {
useEffect(() => {
void window.service.auth.get(`${SupportedStorageServices.github}-token`).then(async (githubToken) => {
try {
// DEBUG: console githubToken
console.log(`githubToken`, githubToken);
if (githubToken) {
// get user name and email using github api
const response = await fetch('https://api.github.com/user', {
@ -44,8 +42,6 @@ export function useGetGithubUserInfoOnLoad(): void {
},
});
const userInfo = await (response.json() as Promise<{ email: string; login: string; name: string }>);
// DEBUG: console userInfo
console.log(`userInfo`, userInfo);
await window.service.auth.set(`${SupportedStorageServices.github}-userName`, userInfo.login);
await window.service.auth.set('userName', userInfo.name);
await window.service.auth.set(`${SupportedStorageServices.github}-email`, userInfo.email);

View file

@ -86,16 +86,16 @@ export enum WikiChannel {
name = 'WikiChannel',
openTiddler = 'wiki-open-tiddler',
printTiddler = 'print-tiddler',
/**
* Render wiki text to html
*/
renderWikiText = 'render-wiki-text',
runFilter = 'wiki-run-filter',
sendActionMessage = 'wiki-send-action-message',
setState = 'wiki-set-state',
setTiddlerText = 'wiki-set-tiddler-text',
/** show message inside tiddlywiki to show git sync progress */
syncProgress = 'wiki-sync-progress',
/**
* Render wiki text to html
*/
renderWikiText = 'render-wiki-text',
}
export enum WikiGitWorkspaceChannel {
name = 'WikiGitWorkspaceChannel',
@ -145,6 +145,7 @@ export enum MetaDataChannel {
browserViewMetaData = 'browserViewMetaData',
getViewMetaData = 'getViewMetaData',
name = 'MetaDataChannel',
pushViewMetaData = 'pushViewMetaData',
}
export type Channels =

View file

@ -1,7 +1,6 @@
import os from 'os';
import path from 'path';
import { isMac } from '../helpers/system';
import { GITHUB_LOGIN_REDIRECT_PATH, GITHUB_OAUTH_APP_CLIENT_ID } from './auth';
import { isDevelopmentOrTest } from './environment';
import { developmentWikiFolderName, localizationFolderName } from './fileNames';

View file

@ -0,0 +1,6 @@
export enum CreateWorkspaceTabs {
CloneOnlineWiki = 'CloneOnlineWiki',
CreateNewWiki = 'CreateNewWiki',
OpenLocalWiki = 'OpenLocalWiki',
OpenLocalWikiFromHtml = 'OpenLocalWikiFromHtml',
}

View file

@ -20,18 +20,13 @@ import { IErrorInWhichComponent, useWikiWorkspaceForm } from './useForm';
import { TokenForm } from '@/components/TokenForm';
import { usePromiseValue } from '@/helpers/useServiceValue';
import { IPossibleWindowMeta, WindowMeta, WindowNames } from '@services/windows/WindowProperties';
import { CreateWorkspaceTabs } from './constants';
import { LocationPickerContainer, LocationPickerInput } from './FormComponents';
import { GitRepoUrlForm } from './GitRepoUrlForm';
import { ImportHtmlWikiDoneButton } from './ImportHtmlWikiDoneButton';
import { ImportHtmlWikiForm } from './ImportHtmlWikiForm';
enum CreateWorkspaceTabs {
CloneOnlineWiki = 'CloneOnlineWiki',
CreateNewWiki = 'CreateNewWiki',
OpenLocalWiki = 'OpenLocalWiki',
OpenLocalWikiFromHtml = 'OpenLocalWikiFromHtml',
}
export const Paper = styled(PaperRaw)`
border-color: ${({ theme }) => theme.palette.divider};
background: ${({ theme }) => theme.palette.background.paper};
@ -78,7 +73,9 @@ const AdvancedSettingsAccordionSummary = styled(AccordionSummary)`
export function AddWorkspace(): JSX.Element {
const { t } = useTranslation();
const [currentTab, currentTabSetter] = useState<CreateWorkspaceTabs>(CreateWorkspaceTabs.CreateNewWiki);
const [currentTab, currentTabSetter] = useState<CreateWorkspaceTabs>(
(window.meta() as IPossibleWindowMeta<WindowMeta[WindowNames.addWorkspace]>)?.addWorkspaceTab ?? CreateWorkspaceTabs.CreateNewWiki,
);
const isCreateSyncedWorkspace = currentTab === CreateWorkspaceTabs.CloneOnlineWiki;
const [isCreateMainWorkspace, isCreateMainWorkspaceSetter] = useState(true);
const form = useWikiWorkspaceForm();

View file

@ -136,7 +136,7 @@ const getValidIconPath = (iconPath?: string | null): string => {
return defaultIcon;
};
const workspaceID = (window.meta as WindowMeta[WindowNames.editWorkspace]).workspaceID as string;
const workspaceID = (window.meta() as WindowMeta[WindowNames.editWorkspace]).workspaceID as string;
export default function EditWorkspace(): JSX.Element {
const { t } = useTranslation();

View file

@ -145,7 +145,7 @@ export default function Notifications(): JSX.Element {
<ListItemText
primary={pauseNotificationsInfo.reason === 'scheduled' ? 'Adjust schedule...' : 'Pause notifications by schedule...'}
onClick={async () => {
await window.service.window.open(WindowNames.preferences, { gotoTab: PreferenceSections.notifications });
await window.service.window.open(WindowNames.preferences, { preferenceGotoTab: PreferenceSections.notifications });
void window.remote.closeCurrentWindow();
}}
/>
@ -179,7 +179,7 @@ export default function Notifications(): JSX.Element {
<ListItemText
primary='Pause notifications by schedule...'
onClick={async () => {
await window.service.window.open(WindowNames.preferences, { gotoTab: PreferenceSections.notifications });
await window.service.window.open(WindowNames.preferences, { preferenceGotoTab: PreferenceSections.notifications });
void window.remote.closeCurrentWindow();
}}
/>

View file

@ -41,7 +41,7 @@ export default function Preferences(): JSX.Element {
// handle open preference from other window, and goto some tab
useEffect(() => {
const scrollTo = (window.meta as IPossibleWindowMeta<WindowMeta[WindowNames.preferences]>).gotoTab;
const scrollTo = (window.meta() as IPossibleWindowMeta<WindowMeta[WindowNames.preferences]>).preferenceGotoTab;
if (scrollTo === undefined) return;
sections[scrollTo].ref?.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, [sections]);

View file

@ -86,7 +86,7 @@ export function ViewLoadErrorMessages(props: IViewLoadErrorMessagesProps): JSX.E
const { t } = useTranslation();
const requestReload = useCallback(async (): Promise<void> => {
await window.service.workspace.updateMetaData(props.activeWorkspace.id, { didFailLoadErrorMessage: null, isLoading: false });
await window.service.window.reload(window.meta.windowName);
await window.service.window.reload(window.meta().windowName);
await window.service.view.removeAllViewOfWorkspace(props.activeWorkspace.id);
await window.service.wiki.stopWiki(props.activeWorkspace.id);
await window.service.workspaceView.initializeWorkspaceView(props.activeWorkspace);

View file

@ -14,7 +14,7 @@ const SpellcheckLanguages = lazy(() => import('./SpellcheckLanguages'));
export function Pages(): JSX.Element {
const [, setLocation] = useLocation();
useEffect(() => {
setLocation(`/${window.meta.windowName}`);
setLocation(`/${window.meta().windowName}`);
}, [setLocation]);
return (
<Switch>

View file

@ -1,8 +1,10 @@
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
// on production build, if we try to redirect to http://localhost:3012 , we will reach chrome-error://chromewebdata/ , but we can easily get back
// this happens when we are redirected by OAuth login
import { CreateWorkspaceTabs } from '@/pages/AddWorkspace/constants';
import { PreferenceSections } from '@services/preferences/interface';
import { SupportedStorageServices } from '@services/types';
import { WindowNames } from '@services/windows/WindowProperties';
import { WindowMeta, WindowNames } from '@services/windows/WindowProperties';
import { windowName } from './browserViewMetaData';
import { context, window as windowService } from './services';
@ -62,6 +64,13 @@ async function refresh(): Promise<void> {
const { access_token: token } = await (response.json() as Promise<{ access_token: string }>);
await window.service.auth.set(`${SupportedStorageServices.github}-token`, token);
}
await windowService.updateWindowMeta(
windowName,
{
addWorkspaceTab: CreateWorkspaceTabs.CloneOnlineWiki,
preferenceGotoTab: PreferenceSections.sync,
} satisfies WindowMeta[WindowNames.addWorkspace] & WindowMeta[WindowNames.preferences],
);
await windowService.loadURL(windowName, MAIN_WINDOW_WEBPACK_ENTRY);
} else if (window.location.href === CHROME_ERROR_PATH) {
await windowService.loadURL(windowName, MAIN_WINDOW_WEBPACK_ENTRY);

View file

@ -1,5 +1,5 @@
import { MetaDataChannel } from '@/constants/channels';
import { WindowMeta, WindowNames } from '@services/windows/WindowProperties';
import { IPossibleWindowMeta, WindowMeta, WindowNames } from '@services/windows/WindowProperties';
import { contextBridge, ipcRenderer } from 'electron';
const metaDataArguments = process.argv
@ -16,8 +16,14 @@ try {
);
}
export const browserViewMetaData = { windowName, ...extraMeta };
contextBridge.exposeInMainWorld('meta', browserViewMetaData);
export let browserViewMetaData = { windowName, ...extraMeta };
contextBridge.exposeInMainWorld('meta', () => browserViewMetaData);
ipcRenderer.on(MetaDataChannel.getViewMetaData, (event, payload?: { ipcToken: string }) => {
ipcRenderer.send(`${MetaDataChannel.getViewMetaData}-${payload?.ipcToken ?? ''}`, browserViewMetaData);
});
/**
* Receive update or windowMeta from server service.
*/
ipcRenderer.on(MetaDataChannel.pushViewMetaData, (event, payload?: IPossibleWindowMeta) => {
browserViewMetaData = { ...browserViewMetaData, ...payload };
});

View file

@ -19,7 +19,7 @@ import { fixAlertConfirm } from './fixer/fixAlertConfirm';
declare global {
interface Window {
meta: IPossibleWindowMeta;
meta: () => IPossibleWindowMeta;
observables: IServicesWithOnlyObservables<typeof service>;
service: IServicesWithoutObservables<typeof service>;
}

View file

@ -13,7 +13,7 @@ function getInfoTiddlerFields(updateInfoTiddlersCallback: (infos: Array<{ text:
// Basics
if (!$tw.browser || typeof window === 'undefined') return infoTiddlerFields;
const isInTidGi = typeof document !== 'undefined' && document?.location?.protocol?.startsWith('tidgi');
const workspaceID = (window.meta as WindowMeta[WindowNames.view] | undefined)?.workspaceID;
const workspaceID = (window.meta() as WindowMeta[WindowNames.view] | undefined)?.workspaceID;
infoTiddlerFields.push({ title: '$:/info/tidgi', text: mapBoolean(isInTidGi) });
if (isInTidGi && workspaceID) {
infoTiddlerFields.push({ title: '$:/info/tidgi/workspaceID', text: workspaceID });

View file

@ -40,7 +40,7 @@ class TidGiIPCSyncAdaptor {
this.isLoggedIn = false;
this.isReadOnly = false;
this.logoutIsAvailable = true;
this.workspaceID = (window.meta as WindowMeta[WindowNames.view]).workspaceID!;
this.workspaceID = (window.meta() as WindowMeta[WindowNames.view]).workspaceID!;
if (window.observables?.wiki?.getWikiChangeObserver$ !== undefined) {
// if install-electron-ipc-cat is faster than us, just subscribe to the observable. Otherwise we normally will wait for it to call us here.
this.setupSSE();
@ -336,7 +336,7 @@ class TidGiIPCSyncAdaptor {
if ($tw.browser && typeof window !== 'undefined') {
const isInTidGi = typeof document !== 'undefined' && document?.location?.protocol?.startsWith('tidgi');
const servicesExposed = Boolean(window.service?.wiki);
const hasWorkspaceIDinMeta = Boolean((window.meta as WindowMeta[WindowNames.view] | undefined)?.workspaceID);
const hasWorkspaceIDinMeta = Boolean((window.meta() as WindowMeta[WindowNames.view] | undefined)?.workspaceID);
if (isInTidGi && servicesExposed && hasWorkspaceIDinMeta) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
exports.adaptorClass = TidGiIPCSyncAdaptor;

View file

@ -1,3 +1,4 @@
import type { CreateWorkspaceTabs } from '@/pages/AddWorkspace/constants';
import type { PreferenceSections } from '@services/preferences/interface';
export enum WindowNames {
@ -84,7 +85,7 @@ export const windowDimension: Record<WindowNames, { height?: number; width?: num
};
export interface IPreferenceWindowMeta {
gotoTab?: PreferenceSections;
preferenceGotoTab?: PreferenceSections;
preventClosingWindow?: boolean;
}
@ -94,8 +95,8 @@ export interface IPreferenceWindowMeta {
*/
export interface WindowMeta {
[WindowNames.about]: undefined;
[WindowNames.addWorkspace]: undefined;
[WindowNames.any]: { uri: string };
[WindowNames.addWorkspace]: { addWorkspaceTab?: CreateWorkspaceTabs };
[WindowNames.any]: { uri?: string };
[WindowNames.auth]: undefined;
[WindowNames.editWorkspace]: { workspaceID?: string };
[WindowNames.main]: { forceClose?: boolean };

View file

@ -211,7 +211,7 @@ export class Window implements IWindowService {
config?: IWindowOpenConfig<N>,
): Promise<BrowserWindow> {
const newWindow = new BrowserWindow(windowConfig);
const newWindowURL = windowMeta !== undefined && 'uri' in windowMeta ? windowMeta.uri : MAIN_WINDOW_WEBPACK_ENTRY;
const newWindowURL = (windowMeta !== undefined && 'uri' in windowMeta ? windowMeta.uri : undefined) ?? MAIN_WINDOW_WEBPACK_ENTRY;
if (config?.multiple !== true) {
this.windows[windowName] = newWindow;
}
@ -303,13 +303,13 @@ export class Window implements IWindowService {
newWindow.on('enter-full-screen', async () => {
const mainWindow = this.get(windowName);
if (mainWindow === undefined) return;
mainWindow?.webContents.send('is-fullscreen-updated', true);
mainWindow?.webContents?.send?.('is-fullscreen-updated', true);
await this.workspaceViewService.realignActiveWorkspace();
});
newWindow.on('leave-full-screen', async () => {
const mainWindow = this.get(windowName);
if (mainWindow === undefined) return;
mainWindow?.webContents.send('is-fullscreen-updated', false);
mainWindow?.webContents?.send?.('is-fullscreen-updated', false);
await this.workspaceViewService.realignActiveWorkspace();
});
}
@ -323,13 +323,21 @@ export class Window implements IWindowService {
}
public async updateWindowMeta<N extends WindowNames>(windowName: N, meta: WindowMeta[N]): Promise<void> {
this.windowMeta[windowName] = { ...this.windowMeta[windowName], ...meta };
const newMeta = { ...this.windowMeta[windowName], ...meta };
this.windowMeta[windowName] = newMeta;
}
public async getWindowMeta<N extends WindowNames>(windowName: N): Promise<WindowMeta[N] | undefined> {
return this.windowMeta[windowName] as WindowMeta[N];
}
/**
* When using `loadURL`, window meta will be clear. And we can only append meta to a new window. So we need to push meta to window after `loadURL`.
*/
private async pushWindowMetaToWindow<N extends WindowNames>(win: BrowserWindow, meta: WindowMeta[N]): Promise<void> {
win?.webContents?.send?.(MetaDataChannel.pushViewMetaData, meta);
}
/**
* BroadCast message to all opened windows, so we can sync state to redux and make them take effect immediately
* @param channel ipc channel to send
@ -375,12 +383,18 @@ export class Window implements IWindowService {
public async reload(windowName: WindowNames = WindowNames.main): Promise<void> {
const win = this.get(windowName);
win?.getBrowserView()?.webContents?.reload();
if (win !== undefined) {
win.getBrowserView()?.webContents?.reload?.();
await this.pushWindowMetaToWindow(win, this.windowMeta[windowName]);
}
}
async loadURL(windowName: WindowNames, newUrl: string): Promise<void> {
const win = this.get(windowName);
await win?.loadURL(newUrl);
if (win !== undefined) {
await win.loadURL(newUrl);
await this.pushWindowMetaToWindow(win, this.windowMeta[windowName]);
}
}
public async clearStorageData(windowName: WindowNames = WindowNames.main): Promise<void> {