fix: sync on start not reloading wiki

fixes https://github.com/tiddly-gittly/TidGi-Desktop/issues/298
This commit is contained in:
tiddlygit-test 2022-12-18 21:26:21 +08:00
parent dc894ffdaa
commit 7e5fe1d676
6 changed files with 77 additions and 44 deletions

View file

@ -37,6 +37,7 @@ import { WindowNames } from '@services/windows/WindowProperties';
import { lazyInject } from '@services/container';
import { githubDesktopUrl } from '@/constants/urls';
import { IWorkspace } from '@services/workspaces/interface';
import { stepWithChanges } from './stepWithChanges';
@injectable()
export class Git implements IGitService {
@ -223,7 +224,7 @@ export class Git implements IGitService {
}
}
private readonly getWorkerObserver = (resolve: () => void, reject: (error: Error) => void): Observer<IGitLogMessage> => ({
private readonly getWorkerMessageObserver = (resolve: () => void, reject: (error: Error) => void): Observer<IGitLogMessage> => ({
next: (messageObject) => {
const { message, meta, level } = messageObject;
if (typeof meta === 'object' && meta !== null && 'step' in meta) {
@ -269,20 +270,35 @@ export class Git implements IGitService {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
const syncImmediately = !!isSyncedWiki && !!isMainWiki;
return await new Promise<void>((resolve, reject) => {
this.gitWorker?.initWikiGit(wikiFolderPath, syncImmediately && net.isOnline(), remoteUrl, userInfo).subscribe(this.getWorkerObserver(resolve, reject));
this.gitWorker
?.initWikiGit(wikiFolderPath, syncImmediately && net.isOnline(), remoteUrl, userInfo)
.subscribe(this.getWorkerMessageObserver(resolve, reject));
});
}
public async commitAndSync(workspace: IWorkspace, config: ICommitAndSyncConfigs): Promise<void> {
public async commitAndSync(workspace: IWorkspace, config: ICommitAndSyncConfigs): Promise<boolean> {
if (!net.isOnline()) {
return;
return false;
}
try {
return await new Promise<void>((resolve, reject) => {
this.gitWorker?.commitAndSyncWiki(workspace, config).subscribe(this.getWorkerObserver(resolve, reject));
return await new Promise<boolean>((resolve, reject) => {
const observable = this.gitWorker?.commitAndSyncWiki(workspace, config);
observable?.subscribe(this.getWorkerMessageObserver(() => {}, reject));
let hasChanges = false;
observable?.subscribe({
next: (messageObject) => {
const { meta } = messageObject;
if (typeof meta === 'object' && meta !== null && 'step' in meta && stepWithChanges.includes((meta as { step: GitStep }).step)) {
hasChanges = true;
}
},
complete: () => resolve(hasChanges),
});
return true;
});
} catch (error) {
this.createFailedDialog((error as Error).message, workspace.wikiFolderLocation);
return true;
}
}
@ -291,7 +307,7 @@ export class Git implements IGitService {
return;
}
return await new Promise<void>((resolve, reject) => {
this.gitWorker?.cloneWiki(repoFolderPath, remoteUrl, userInfo).subscribe(this.getWorkerObserver(resolve, reject));
this.gitWorker?.cloneWiki(repoFolderPath, remoteUrl, userInfo).subscribe(this.getWorkerMessageObserver(resolve, reject));
});
}
}

View file

@ -22,7 +22,11 @@ export interface IGitLogMessage {
meta: unknown;
}
export interface ICommitAndSyncConfigs { commitOnly?: boolean; remoteUrl?: string; userInfo?: IGitUserInfos }
export interface ICommitAndSyncConfigs {
commitOnly?: boolean;
remoteUrl?: string;
userInfo?: IGitUserInfos;
}
/**
* System Preferences are not stored in storage but stored in macOS Preferences.
@ -30,7 +34,10 @@ export interface ICommitAndSyncConfigs { commitOnly?: boolean; remoteUrl?: strin
*/
export interface IGitService {
clone(remoteUrl: string, repoFolderPath: string, userInfo: IGitUserInfos): Promise<void>;
commitAndSync(workspace: IWorkspace, config: ICommitAndSyncConfigs): Promise<void>;
/**
* Return true if this function's execution causes local changes. Return false if is only push or nothing changed.
*/
commitAndSync(workspace: IWorkspace, config: ICommitAndSyncConfigs): Promise<boolean>;
getModifiedFileList(wikiFolderPath: string): Promise<ModifiedFileList[]>;
/** Inspect git's remote url from folder's .git config, return undefined if there is no initialized git */
getWorkspacesRemote(wikiFolderPath?: string): Promise<string | undefined>;

View file

@ -0,0 +1,4 @@
import { GitStep } from 'git-sync-js';
// TODO: move this to git-sync-js
export const stepWithChanges = [GitStep.GitMerge, GitStep.LocalStateDivergeRebase, GitStep.LocalStateBehindSync];

View file

@ -508,9 +508,11 @@ export class Wiki implements IWikiService {
userInfo !== undefined &&
(await checkCanSyncDueToNoDraft(workspace))
) {
await this.gitService.commitAndSync(workspace, { remoteUrl: githubRepoUrl, userInfo });
await this.workspaceViewService.restartWorkspaceViewService(id);
await this.viewService.reloadViewsWebContents(id);
const hasChanges = await this.gitService.commitAndSync(workspace, { remoteUrl: githubRepoUrl, userInfo });
if (hasChanges) {
await this.workspaceViewService.restartWorkspaceViewService(id);
await this.viewService.reloadViewsWebContents(id);
}
} else if (backupOnInterval && (await checkCanSyncDueToNoDraft(workspace))) {
await this.gitService.commitAndSync(workspace, { commitOnly: true });
}
@ -563,7 +565,17 @@ export class Wiki implements IWikiService {
const userName = (workspace.userName || (await this.authService.get('userName'))) ?? '';
// if is main wiki
if (!isSubWiki) {
if (isSubWiki) {
// if is private repo wiki
// if we are creating a sub-wiki just now, restart the main wiki to load content from private wiki
if (typeof mainWikiToLink === 'string' && !this.checkWikiStartLock(mainWikiToLink)) {
const mainWorkspace = await this.workspaceService.getByWikiFolderLocation(mainWikiToLink);
if (mainWorkspace === undefined) {
throw new Error(`mainWorkspace is undefined in wikiStartup() for mainWikiPath ${mainWikiToLink}`);
}
await this.restartWiki(mainWorkspace);
}
} else {
try {
logger.debug('startWiki() calling startWiki');
await this.startWiki(wikiFolderLocation, port, userName);
@ -585,16 +597,6 @@ export class Wiki implements IWikiService {
throw error;
}
}
} else {
// if is private repo wiki
// if we are creating a sub-wiki just now, restart the main wiki to load content from private wiki
if (typeof mainWikiToLink === 'string' && !this.checkWikiStartLock(mainWikiToLink)) {
const mainWorkspace = await this.workspaceService.getByWikiFolderLocation(mainWikiToLink);
if (mainWorkspace === undefined) {
throw new Error(`mainWorkspace is undefined in wikiStartup() for mainWikiPath ${mainWikiToLink}`);
}
await this.restartWiki(mainWorkspace);
}
}
await this.startIntervalSyncIfNeeded(workspace);
}

View file

@ -111,9 +111,11 @@ export async function getWorkspaceMenuTemplate(
label: t('ContextMenu.SyncNow') + (isOnline ? '' : `(${t('ContextMenu.NoNetworkConnection')})`),
enabled: isOnline,
click: async () => {
await service.git.commitAndSync(workspace, { remoteUrl: gitUrl, userInfo });
await service.workspaceView.restartWorkspaceViewService(id);
await service.view.reloadViewsWebContents(id);
const hasChanges = await service.git.commitAndSync(workspace, { remoteUrl: gitUrl, userInfo });
if (hasChanges) {
await service.workspaceView.restartWorkspaceViewService(id);
await service.view.reloadViewsWebContents(id);
}
},
});
}

View file

@ -114,9 +114,11 @@ export class WorkspaceView implements IWorkspaceViewService {
throw new TypeError(`userInfo is undefined in initializeAllWorkspaceView when init ${wikiFolderLocation}`);
}
// sync in non-blocking way
void this.gitService.commitAndSync(workspace, { remoteUrl: githubRepoUrl, userInfo }).then(async () => {
await this.workspaceViewService.restartWorkspaceViewService(workspace.id);
await this.viewService.reloadViewsWebContents(workspace.id);
void this.gitService.commitAndSync(workspace, { remoteUrl: githubRepoUrl, userInfo }).then(async (hasChanges) => {
if (hasChanges) {
await this.workspaceViewService.restartWorkspaceViewService(workspace.id);
await this.viewService.reloadViewsWebContents(workspace.id);
}
});
}
} catch (error) {
@ -161,14 +163,14 @@ export class WorkspaceView implements IWorkspaceViewService {
// if is newly created wiki, we set the language as user preference
const currentLanguage = await this.preferenceService.get('language');
const tiddlywikiLanguageName = tiddlywikiLanguagesMap[currentLanguage];
if (tiddlywikiLanguageName !== undefined) {
logger.debug(`Setting wiki language to ${currentLanguage} (${tiddlywikiLanguageName}) on init`);
await this.wikiService.setWikiLanguage(view, workspace.id, tiddlywikiLanguageName);
} else {
if (tiddlywikiLanguageName === undefined) {
const errorMessage = `When creating new wiki, and switch to language "${currentLanguage}", there is no corresponding tiddlywiki language registered`;
logger.error(errorMessage, {
tiddlywikiLanguagesMap,
});
} else {
logger.debug(`Setting wiki language to ${currentLanguage} (${tiddlywikiLanguageName}) on init`);
await this.wikiService.setWikiLanguage(view, workspace.id, tiddlywikiLanguageName);
}
}
}
@ -178,14 +180,14 @@ export class WorkspaceView implements IWorkspaceViewService {
workspaceID: string,
view: Electron.CrossProcessExports.BrowserView | undefined = this.viewService.getView(workspaceID, WindowNames.main),
): Promise<void> {
if (view !== undefined) {
if (view === undefined) {
logger.warn(`Can't update lastUrl for workspace ${workspaceID}, view is not found`);
} else {
const currentUrl = view.webContents.getURL();
logger.debug(`Updating lastUrl for workspace ${workspaceID} to ${currentUrl}`);
await this.workspaceService.update(workspaceID, {
lastUrl: currentUrl,
});
} else {
logger.warn(`Can't update lastUrl for workspace ${workspaceID}, view is not found`);
}
}
@ -351,8 +353,10 @@ export class WorkspaceView implements IWorkspaceViewService {
}
public async restartWorkspaceViewService(id?: string): Promise<void> {
const workspaceToRestart = id !== undefined ? await this.workspaceService.get(id) : await this.workspaceService.getActiveWorkspace();
if (workspaceToRestart !== undefined) {
const workspaceToRestart = id === undefined ? await this.workspaceService.getActiveWorkspace() : await this.workspaceService.get(id);
if (workspaceToRestart === undefined) {
logger.warn(`restartWorkspaceViewService: no workspace ${id ?? 'id undefined'} to restart`);
} else {
logger.info(`Restarting workspace ${workspaceToRestart.id}`);
await this.updateLastUrl(workspaceToRestart.id);
await this.workspaceService.updateMetaData(workspaceToRestart.id, { didFailLoadErrorMessage: null, isLoading: false });
@ -364,8 +368,6 @@ export class WorkspaceView implements IWorkspaceViewService {
}
await this.viewService.reloadViewsWebContents(workspaceToRestart.id);
this.wikiService.wikiOperation(WikiChannel.generalNotification, workspaceToRestart.id, i18n.t('ContextMenu.RestartServiceComplete'));
} else {
logger.warn(`restartWorkspaceViewService: no workspace ${id ?? 'id undefined'} to restart`);
}
}
@ -443,7 +445,7 @@ export class WorkspaceView implements IWorkspaceViewService {
}
private async realignActiveWorkspaceView(id?: string): Promise<void> {
const workspaceToRealign = id !== undefined ? await this.workspaceService.get(id) : await this.workspaceService.getActiveWorkspace();
const workspaceToRealign = id === undefined ? await this.workspaceService.getActiveWorkspace() : await this.workspaceService.get(id);
logger.debug(`realignActiveWorkspaceView() activeWorkspace.id: ${workspaceToRealign?.id ?? 'undefined'}`);
const mainWindow = this.windowService.get(WindowNames.main);
const menuBarWindow = this.windowService.get(WindowNames.menuBar);
@ -455,14 +457,14 @@ export class WorkspaceView implements IWorkspaceViewService {
!!menuBarBrowserViewWebContent,
)}`,
);
if (workspaceToRealign !== undefined) {
if (workspaceToRealign === undefined) {
logger.warn('realignActiveWorkspaceView: no active workspace');
} else {
if (mainWindow === undefined && menuBarWindow === undefined) {
logger.warn('realignActiveWorkspaceView: no active window');
}
mainBrowserViewWebContent && void this.viewService.realignActiveView(mainWindow, workspaceToRealign.id);
menuBarBrowserViewWebContent && void this.viewService.realignActiveView(menuBarWindow, workspaceToRealign.id);
} else {
logger.warn('realignActiveWorkspaceView: no active workspace');
}
/* eslint-enable @typescript-eslint/strict-boolean-expressions */
}