refactor: workspace senders

This commit is contained in:
tiddlygit-test 2021-02-05 00:07:53 +08:00
parent 005f163475
commit 96c2ebc986
20 changed files with 74 additions and 125 deletions

View file

@ -15,7 +15,6 @@ import MenuItem from '@material-ui/core/MenuItem';
import FolderIcon from '@material-ui/icons/Folder';
import Autocomplete from '@material-ui/lab/Autocomplete';
import * as actions from '../../state/dialog-add-workspace/actions';
import { getWorkspaces } from '../../senders';
const CreateContainer: ComponentType<{}> = styled(Paper)`
margin-top: 5px;
`;
@ -83,7 +82,9 @@ function WikiPathForm({
}: Props) {
const [workspaces, workspacesSetter] = useState({});
useEffect(() => {
workspacesSetter(getWorkspaces());
void (async () => {
workspacesSetter(await window.service.workspace.getWorkspaces());
})();
}, []);
const hasError = wikiCreationMessage.startsWith('Error');
const { t } = useTranslation();

View file

@ -88,14 +88,13 @@ export default function AddWorkspace() {
}, [mainWikiToLink]);
const [githubWikiUrl, githubWikiUrlSetter] = useState<string>('');
useEffect(() => {
async function getWorkspaceRemoteInEffect(): Promise<void> {
void (async function getWorkspaceRemoteInEffect(): Promise<void> {
const url = await window.service.git.getWorkspacesRemote(existedFolderLocation);
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (url) {
githubWikiUrlSetter(url);
}
}
void getWorkspaceRemoteInEffect();
})();
}, [githubWikiUrl, existedFolderLocation]);
const [wikiFolderName, wikiFolderNameSetter] = useState('tiddlywiki');

View file

@ -15,7 +15,7 @@ import MenuItem from '@material-ui/core/MenuItem';
import FolderIcon from '@material-ui/icons/Folder';
import Autocomplete from '@material-ui/lab/Autocomplete';
import * as actions from '../../state/dialog-add-workspace/actions';
import { getWorkspaces } from '../../senders';
const CreateContainer: ComponentType<{}> = styled(Paper)`
margin-top: 5px;
`;
@ -82,7 +82,9 @@ function NewWikiPathForm({
}: Props) {
const [workspaces, workspacesSetter] = useState({});
useEffect(() => {
workspacesSetter(getWorkspaces());
void (async () => {
workspacesSetter(await window.service.workspace.getWorkspaces());
})();
}, []);
const hasError = wikiCreationMessage.startsWith('Error');
const { t } = useTranslation();

View file

@ -1142,7 +1142,7 @@ const Preferences = ({
</ListItemSecondaryAction>
</ListItem>
<Divider />
<ListItem button onClick={requestClearBrowsingData}>
<ListItem button onClick={window.service.preference.clearBrowsingDataWithConfirm}>
<ListItemText primary="Clear browsing data" secondary="Clear cookies, cache, and more" />
<ChevronRightIcon color="action" />
</ListItem>

View file

@ -51,7 +51,6 @@ export enum PreferenceChannel {
update = 'update',
getPreference = 'get-preference',
getPreferences = 'get-preferences',
requestClearBrowsingData = 'request-clear-browsing-data',
}
export enum WindowChannel {

View file

@ -52,7 +52,7 @@ const gotTheLock = app.requestSingleInstanceLock();
container.bind<Authentication>(serviceIdentifier.Authentication).to(Authentication).inSingletonScope();
container.bind<Git>(serviceIdentifier.Git).to(Git).inSingletonScope();
container.bind<MenuService>(serviceIdentifier.MenuService).to(MenuService).inSingletonScope();
container.bind<NotificationService>(serviceIdentifier.Notification).to(NotificationService).inSingletonScope();
container.bind<NotificationService>(serviceIdentifier.NotificationService).to(NotificationService).inSingletonScope();
container.bind<NativeService>(serviceIdentifier.NativeService).to(NativeService).inSingletonScope();
container.bind<Preference>(serviceIdentifier.Preference).to(Preference).inSingletonScope();
container.bind<SystemPreference>(serviceIdentifier.SystemPreference).to(SystemPreference).inSingletonScope();

View file

@ -3,7 +3,6 @@ import { enable as enableDarkMode, disable as disableDarkMode } from 'darkreader
import ContextMenuBuilder from '@services/libs/context-menu-builder';
import i18next from '@services/libs/i18n';
import './wiki-operation';
import './wiki-git-api';
import { preference } from './common/services';
const { MenuItem, shell } = remote;

View file

@ -1,28 +0,0 @@
/**
* Provide API from electron to tiddlywiki
* This file should be required by view.ts preload script to work
*/
import { contextBridge } from 'electron';
import { container } from '@services/container';
import { getModifiedFileList } from '@services/git/inspect';
import type { IGitService } from '@services/git/interface';
import type { IWorkspaceService } from '@services/workspaces/interface';
import type { IAuthenticationService } from '@services/auth/interface';
import serviceIdentifier from '@services/serviceIdentifier';
contextBridge.exposeInMainWorld('git', {
getModifiedFileList,
commitAndSync: (wikiPath: string, githubRepoUrl: string) => {
const gitService = container.get<IGitService>(serviceIdentifier.Git);
const authService = container.get<IAuthenticationService>(serviceIdentifier.Authentication);
const userInfo = authService.get('authing');
if (userInfo !== undefined) {
return gitService.commitAndSync(wikiPath, githubRepoUrl, userInfo);
}
},
getWorkspacesAsList: () => {
const workspaceService = container.get<IWorkspaceService>(serviceIdentifier.Workspace);
return workspaceService.getWorkspacesAsList();
},
});

View file

@ -12,22 +12,6 @@ export const getShouldUseDarkColors = async (): Promise<void> => {
await ipcRenderer.invoke('get-should-use-dark-colors');
};
// Workspace
export const getWorkspace = (id: string) => ipcRenderer.invokeSync('get-workspace', id);
export const getWorkspaces = () => ipcRenderer.invokeSync('get-workspaces');
export const requestClearBrowsingData = async () => await ipcRenderer.invoke('request-clear-browsing-data');
export const requestCreateWorkspace = async (
name: string,
isSubWiki: boolean,
mainWikiToLink: string,
port: number,
homeUrl: string,
gitUrl: string,
picture: string,
transparentBackground: boolean,
tagName: string,
) => await ipcRenderer.invoke('request-create-workspace', name, isSubWiki, mainWikiToLink, port, homeUrl, gitUrl, picture, transparentBackground, tagName);
export const requestHibernateWorkspace = async (id: string) => await ipcRenderer.invoke('request-hibernate-workspace', id);
export const requestOpenUrlInWorkspace = async (url: string, id: string) => await ipcRenderer.invoke('request-open-url-in-workspace', url, id);
export const requestRealignActiveWorkspace = async () => await ipcRenderer.invoke('request-realign-active-workspace');
@ -51,10 +35,6 @@ export const getIsDevelopment = () => ipcRenderer.invokeSync('get-constant', 'is
export const getBaseName = (pathString: string): string => ipcRenderer.invokeSync('get-basename', pathString);
export const getDirectoryName = (pathString: string): string => ipcRenderer.invokeSync('get-dirname', pathString);
// Workspace Meta
export const getWorkspaceMeta = (id: string) => ipcRenderer.invokeSync('get-workspace-meta', id);
export const getWorkspaceMetas = () => ipcRenderer.invokeSync('get-workspace-metas');
// Find In Page
export const requestFindInPage = async (text: string, forward: boolean) => await ipcRenderer.invoke('request-find-in-page', text, !!forward);
export const requestStopFindInPage = async (close: boolean) => await ipcRenderer.invoke('request-stop-find-in-page', !!close);

View file

@ -12,6 +12,7 @@ import type { IPreferenceService } from '@services/preferences/interface';
import { logger } from '@services/libs/log';
import i18n from '@services/libs/i18n';
import { IUserInfo } from '@services/types';
import { getModifiedFileList, ModifiedFileList } from './inspect';
import { IGitService } from './interface';
@injectable()
@ -32,6 +33,10 @@ export class Git implements IGitService {
return await github.getRemoteUrl(wikiFolderPath);
}
public async getModifiedFileList(wikiFolderPath: string): Promise<ModifiedFileList[]> {
return await getModifiedFileList(wikiFolderPath);
}
/**
*
* @param {string} githubRepoName similar to "linonetwo/wiki", string after "https://github.com/"

View file

@ -2,11 +2,16 @@ import path from 'path';
import { compact } from 'lodash';
import { GitProcess } from 'dugite';
export interface ModifiedFileList {
type: string;
fileRelativePath: string;
filePath: string;
}
/**
* Get modified files and modify type in a folder
* @param {string} wikiFolderPath location to scan git modify state
*/
async function getModifiedFileList(wikiFolderPath: string): Promise<Array<{ type: string; fileRelativePath: string; filePath: string }>> {
export async function getModifiedFileList(wikiFolderPath: string): Promise<ModifiedFileList[]> {
const { stdout } = await GitProcess.exec(['status', '--porcelain'], wikiFolderPath);
const stdoutLines = stdout.split('\n');
return compact(compact(stdoutLines).map((line) => /^\s?(\?\?|[ACMR]|[ACMR][DM])\s?(\S+)$/.exec(line))).map(([_, type, fileRelativePath]) => ({
@ -15,5 +20,3 @@ async function getModifiedFileList(wikiFolderPath: string): Promise<Array<{ type
filePath: path.join(wikiFolderPath, fileRelativePath),
}));
}
export { getModifiedFileList };

View file

@ -1,6 +1,7 @@
import { ProxyPropertyType } from '@/helpers/electron-ipc-proxy/common';
import { IUserInfo } from '@services/types';
import { GitChannel } from '@/constants/channels';
import { ModifiedFileList } from './inspect';
/**
* System Preferences are not stored in storage but stored in macOS Preferences.
@ -9,6 +10,7 @@ import { GitChannel } from '@/constants/channels';
export interface IGitService {
debounceCommitAndSync: (wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo) => Promise<void> | undefined;
updateGitInfoTiddler(githubRepoName: string): Promise<void>;
getModifiedFileList(wikiFolderPath: string): Promise<ModifiedFileList[]>;
initWikiGit(wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo, isMainWiki: boolean): Promise<void>;
commitAndSync(wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo): Promise<void>;
getWorkspacesRemote(wikiFolderPath: string): Promise<string>;
@ -19,6 +21,7 @@ export const GitServiceIPCDescriptor = {
properties: {
debounceCommitAndSync: ProxyPropertyType.Function,
updateGitInfoTiddler: ProxyPropertyType.Function,
getModifiedFileList: ProxyPropertyType.Function,
initWikiGit: ProxyPropertyType.Function,
commitAndSync: ProxyPropertyType.Function,
getWorkspacesRemote: ProxyPropertyType.Function,

View file

@ -43,7 +43,7 @@ container.bind<IContextService>(serviceIdentifier.Context).to(ContextService).in
container.bind<IGitService>(serviceIdentifier.Git).to(Git).inSingletonScope();
container.bind<IMenuService>(serviceIdentifier.MenuService).to(MenuService).inSingletonScope();
container.bind<INativeService>(serviceIdentifier.NativeService).to(NativeService).inSingletonScope();
container.bind<INotificationService>(serviceIdentifier.Notification).to(NotificationService).inSingletonScope();
container.bind<INotificationService>(serviceIdentifier.NotificationService).to(NotificationService).inSingletonScope();
container.bind<IPreferenceService>(serviceIdentifier.Preference).to(Preference).inSingletonScope();
container.bind<ISystemPreferenceService>(serviceIdentifier.SystemPreference).to(SystemPreference).inSingletonScope();
container.bind<IUpdaterService>(serviceIdentifier.Updater).to(Updater).inSingletonScope();
@ -60,7 +60,7 @@ const contextService = container.get<IContextService>(serviceIdentifier.Context)
const gitService = container.get<IGitService>(serviceIdentifier.Git);
const menuService = container.get<IMenuService>(serviceIdentifier.MenuService);
const nativeService = container.get<INativeService>(serviceIdentifier.NativeService);
const notificationService = container.get<INotificationService>(serviceIdentifier.Notification);
const notificationService = container.get<INotificationService>(serviceIdentifier.NotificationService);
const preferenceService = container.get<IPreferenceService>(serviceIdentifier.Preference);
const systemPreferenceService = container.get<ISystemPreferenceService>(serviceIdentifier.SystemPreference);
const viewService = container.get<IViewService>(serviceIdentifier.View);

View file

@ -1,6 +1,6 @@
import { injectable } from 'inversify';
import getDecorators from 'inversify-inject-decorators';
import { app, App, remote, ipcMain, dialog } from 'electron';
import { app, App, remote, dialog } from 'electron';
import path from 'path';
import semver from 'semver';
import settings from 'electron-settings';
@ -85,43 +85,13 @@ const defaultPreferences: IPreferences = {
@injectable()
export class Preference implements IPreferenceService {
@lazyInject(serviceIdentifier.Window) private readonly windowService!: IWindowService;
@lazyInject(serviceIdentifier.Notification) private readonly notificationService!: INotificationService;
@lazyInject(serviceIdentifier.WorkspaceView) private readonly workspaceViewService!: IWorkspaceViewService;
@lazyInject(serviceIdentifier.NotificationService) private readonly notificationService!: INotificationService;
cachedPreferences: IPreferences;
readonly version = '2018.2';
constructor() {
this.cachedPreferences = this.getInitPreferencesForCache();
this.init();
}
init(): void {
ipcMain.handle(PreferenceChannel.requestClearBrowsingData, () => {
const availableWindowToShowDialog = this.windowService.get(WindowNames.preferences) ?? this.windowService.get(WindowNames.main);
if (availableWindowToShowDialog !== undefined) {
dialog
.showMessageBox(availableWindowToShowDialog, {
type: 'question',
buttons: [i18n.t('Preference.ResetNow'), i18n.t('Cancel')],
message: i18n.t('Preference.ClearBrowsingDataMessage'),
cancelId: 1,
})
.then(({ response }) => {
if (response === 0) {
return this.workspaceViewService.clearBrowsingData();
}
})
.catch(console.error);
}
});
ipcMain.handle(PreferenceChannel.getPreference, (_event, name: keyof IPreferences) => {
return this.get(name);
});
ipcMain.handle(PreferenceChannel.getPreferences, (_event) => {
return this.cachedPreferences;
});
}
public async resetWithConfirm(): Promise<void> {

View file

@ -1,7 +1,8 @@
import { app, ipcMain, session } from 'electron';
import { app, ipcMain, session, dialog } from 'electron';
import { injectable, inject } from 'inversify';
import serviceIdentifier from '@services/serviceIdentifier';
import i18n from '@services/libs/i18n';
import type { IViewService } from '@services/view/interface';
import type { IWorkspaceService, IWorkspace } from '@services/workspaces/interface';
import type { IWindowService } from '@services/windows/interface';
@ -22,10 +23,6 @@ export class WorkspaceView implements IWorkspaceViewService {
}
private initIPCHandlers(): void {
ipcMain.handle('request-create-workspace', async (_event, workspaceOptions: IWorkspace) => {
await this.createWorkspaceView(workspaceOptions);
this.menuService.buildMenu();
});
ipcMain.handle('request-set-active-workspace', async (_event, id) => {
if (this.workspaceService.get(id) !== undefined) {
await this.setActiveWorkspaceView(id);
@ -169,6 +166,25 @@ export class WorkspaceView implements IWorkspaceViewService {
this.viewService.removeView(id);
}
public async clearBrowsingDataWithConfirm(): Promise<void> {
const availableWindowToShowDialog = this.windowService.get(WindowNames.preferences) ?? this.windowService.get(WindowNames.main);
if (availableWindowToShowDialog !== undefined) {
await dialog
.showMessageBox(availableWindowToShowDialog, {
type: 'question',
buttons: [i18n.t('Preference.ResetNow'), i18n.t('Cancel')],
message: i18n.t('Preference.ClearBrowsingDataMessage'),
cancelId: 1,
})
.then(({ response }) => {
if (response === 0) {
return this.clearBrowsingData();
}
})
.catch(console.error);
}
}
public async clearBrowsingData(): Promise<void> {
await session.defaultSession.clearStorageData();
const workspaces = this.workspaceService.getWorkspaces();

View file

@ -15,6 +15,7 @@ export interface IWorkspaceViewService {
setActiveWorkspaceView(id: string): Promise<void>;
removeWorkspaceView(id: string): Promise<void>;
clearBrowsingData(): Promise<void>;
clearBrowsingDataWithConfirm(): Promise<void>;
/**
* Try load url, if no id or no active workspace, then nothing will happened
* @param url url to load
@ -34,6 +35,7 @@ export const WorkspaceViewServiceIPCDescriptor = {
setActiveWorkspaceView: ProxyPropertyType.Function,
removeWorkspaceView: ProxyPropertyType.Function,
clearBrowsingData: ProxyPropertyType.Function,
clearBrowsingDataWithConfirm: ProxyPropertyType.Function,
loadURL: ProxyPropertyType.Function,
realignActiveWorkspace: ProxyPropertyType.Function,
},

View file

@ -8,7 +8,6 @@ import validate from '../../helpers/validate';
import isUrl from '../../helpers/is-url';
import hasErrors from '../../helpers/has-errors';
import { requestCreateWorkspace } from '../../senders';
import i18n from 'i18next';
export const setWikiCreationMessage = (message: string) => ({
@ -52,17 +51,19 @@ export const save = () => async (dispatch: any, getState: any) => {
const url = form.homeUrl.trim();
const homeUrl = isUrl(url) ? url : `http://${url}`;
await requestCreateWorkspace(
form.name,
form.isSubWiki,
form.mainWikiToLink,
form.port,
// FIXME: maybe use createWorkspace instead?
await window.service.workspaceView.createWorkspaceView({
name: form.name,
isSubWiki: form.isSubWiki,
mainWikiToLink: form.mainWikiToLink,
port: form.port,
homeUrl,
form.gitUrl,
form.internetIcon || form.picturePath,
Boolean(form.transparentBackground),
form.tagName,
);
gitUrl: form.gitUrl,
picturePath: form.internetIcon || form.picturePath,
transparentBackground: Boolean(form.transparentBackground),
tagName: form.tagName,
});
await window.service.menu.buildMenu();
if (!form.isSubWiki) {
dispatch(setWikiCreationMessage(i18n.t('AddWorkspace.WorkspaceUpdated')));
// and wiki will be closed after wiki server started, close logic is inside wiki-worker-manager.js

View file

@ -2,13 +2,11 @@ import { combineReducers } from 'redux';
import { DIALOG_EDIT_WORKSPACE_INIT, UPDATE_EDIT_WORKSPACE_DOWNLOADING_ICON, UPDATE_EDIT_WORKSPACE_FORM } from '../../constants/actions';
import { getWorkspaces } from '../../senders';
const form = (state = {}, action: any) => {
const form = async (state = {}, action: any) => {
switch (action.type) {
case DIALOG_EDIT_WORKSPACE_INIT: {
const editWorkspaceId = window.remote.getGlobal('editWorkspaceId');
const workspaces = getWorkspaces();
const workspaces = await window.service.workspace.getWorkspaces();
const workspaceList = Object.values(workspaces);
const workspace = workspaces[editWorkspaceId];
workspaceList.some((item, index) => {

View file

@ -1,10 +1,10 @@
import { SET_WORKSPACE_META, SET_WORKSPACE_METAS } from '../../constants/actions';
import { getWorkspaceMetas } from '../../senders';
const initialState = getWorkspaceMetas();
const workspaceMetas = (state = initialState, action: any) => {
const workspaceMetas = async (state, action: any) => {
if (state === undefined) {
state = await window.service.workspace.getAllMetaData()
}
switch (action.type) {
case SET_WORKSPACE_METAS: {
return action.workspaceMetas;

View file

@ -1,10 +1,9 @@
import { SET_WORKSPACE, SET_WORKSPACES } from '../../constants/actions';
import { getWorkspaces } from '../../senders';
const initialState = getWorkspaces();
const workspaces = (state = initialState, action: any) => {
const workspaces = async (state = initialState, action: any) => {
if (state === undefined) {
state = await window.service.workspace.getWorkspaces();
}
switch (action.type) {
case SET_WORKSPACES: {
return action.workspaces;