diff --git a/src/components/dialog-notifications/index.tsx b/src/components/dialog-notifications/index.tsx index ba094e7c..4db7a403 100644 --- a/src/components/dialog-notifications/index.tsx +++ b/src/components/dialog-notifications/index.tsx @@ -18,7 +18,7 @@ import { WindowNames } from '@services/windows/WindowProperties'; import connectComponent from '../../helpers/connect-component'; -import StatedMenu from '../shared/stated-menu'; +import StatedMenu from '../github/stated-menu'; import { updateShowDateTimePicker } from '../../state/notifications/actions'; diff --git a/src/components/dialog-preferences/index.tsx b/src/components/dialog-preferences/index.tsx index a63fe526..6ae0c245 100644 --- a/src/components/dialog-preferences/index.tsx +++ b/src/components/dialog-preferences/index.tsx @@ -45,7 +45,7 @@ import { TimePicker } from '@material-ui/pickers'; import connectComponent from '../../helpers/connect-component'; import { getGithubUserInfo, setGithubUserInfo } from '@services/types'; -import StatedMenu from '../shared/stated-menu'; +import StatedMenu from '../github/stated-menu'; import hunspellLanguagesMap from '../../constants/hunspell-languages'; @@ -54,8 +54,8 @@ import translatiumLogo from '../../images/translatium-logo.svg'; import ListItemDefaultMailClient from './list-item-default-mail-client'; import ListItemDefaultBrowser from './list-item-default-browser'; -import GitTokenForm, { getGithubToken, setGithubToken } from '../shared/git-token-form'; -import type { IUserInfo } from '@services/types'; +import { GithubTokenForm, getGithubToken, setGithubToken } from '../github/git-token-form'; +import type { IAuthingUserInfo } from '@services/types'; import { WindowNames } from '@services/windows/WindowProperties'; const styles = (theme: any) => ({ @@ -361,7 +361,7 @@ const Preferences = ({ [], ); - const [userInfo, userInfoSetter] = useState(getGithubUserInfo()); + const [userInfo, userInfoSetter] = useState(getGithubUserInfo()); useEffect(() => { setGithubUserInfo(userInfo); }, [userInfo]); @@ -426,7 +426,7 @@ const Preferences = ({
- +
diff --git a/src/components/shared/git-token-form.tsx b/src/components/github/git-token-form.tsx similarity index 60% rename from src/components/shared/git-token-form.tsx rename to src/components/github/git-token-form.tsx index 4100c018..c19e27d0 100644 --- a/src/components/shared/git-token-form.tsx +++ b/src/components/github/git-token-form.tsx @@ -5,37 +5,32 @@ import { useTranslation } from 'react-i18next'; import TextField from '@material-ui/core/TextField'; import GitHubLogin from './github-login'; -import type { IUserInfo } from '@services/types'; +import type { IAuthingUserInfo, IAuthingResponse } from '@services/types'; const GitTokenInput = styled(TextField)``; -export const setGithubToken = (token: string | void) => window.service.auth.set('github-token', token); -export const getGithubToken = async () => window.service.auth.get('github-token'); +export const setGithubToken = async (token: string | undefined): Promise => await window.service.auth.set('github-token', token); +export const getGithubToken = async (): Promise => await window.service.auth.get('github-token'); -export default function GitTokenForm(props: { - accessTokenSetter: (token: string | void) => void; - userInfoSetter: (info: IUserInfo | void) => void; +export function GithubTokenForm(props: { + accessTokenSetter: (token?: string) => void; + userInfoSetter: (info?: IAuthingUserInfo) => void; accessToken: string; - children: any; -}) { + children: JSX.Element; +}): JSX.Element { const { accessToken, children } = props; const { t } = useTranslation(); return ( <> { + onSuccess={(response: IAuthingResponse) => { const accessTokenToSet = response?.userInfo?.thirdPartyIdentity?.accessToken; const authDataString = response?.userInfo?.oauth; - if (accessTokenToSet) { + if (accessTokenToSet !== undefined) { props.accessTokenSetter(accessTokenToSet); } // all data we need - if (accessTokenToSet && authDataString) { + if (accessTokenToSet !== undefined && authDataString !== undefined) { const authData = JSON.parse(authDataString); const nextUserInfo = { ...response.userInfo, @@ -44,7 +39,7 @@ export default function GitTokenForm(props: { }; delete nextUserInfo.oauth; delete nextUserInfo.thirdPartyIdentity; - props.userInfoSetter(nextUserInfo); + props.userInfoSetter(nextUserInfo as IAuthingUserInfo); } }} // eslint-disable-next-line unicorn/no-null @@ -60,7 +55,7 @@ export default function GitTokenForm(props: { onChange={(event) => { props.accessTokenSetter(event.target.value); }} - value={accessToken || ''} + value={accessToken ?? ''} /> {children} diff --git a/src/components/shared/github-login.tsx b/src/components/github/github-login.tsx similarity index 78% rename from src/components/shared/github-login.tsx rename to src/components/github/github-login.tsx index 36f57901..03d5b11e 100644 --- a/src/components/shared/github-login.tsx +++ b/src/components/github/github-login.tsx @@ -1,16 +1,14 @@ /* eslint-disable promise/no-nesting */ -import type { ComponentType } from 'react'; import React, { Component } from 'react'; import styled from 'styled-components'; import Button from '@material-ui/core/Button'; import GithubIcon from '@material-ui/icons/GitHub'; -// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module '@aut... Remove this comment to see the full error message import AuthingSSO from '@authing/sso'; import { withTranslation } from 'react-i18next'; import { APP_DOMAIN, APP_ID } from '../../constants/auth'; -const SyncToGithubButton: ComponentType<{}> = styled(Button)` +const SyncToGithubButton = styled(Button)` white-space: nowrap; width: 100%; `; @@ -34,7 +32,6 @@ class GitHubLogin extends Component { }; auth: typeof AuthingSSO; - // @ts-expect-error ts-migrate(2304) FIXME: Cannot find name 'IntervalID'. intervalHandel: IntervalID; constructor(props: Props) { @@ -50,10 +47,10 @@ class GitHubLogin extends Component { this.updateLoginState(); } - async isLogin() { + async isLogin(): boolean { const { onSuccess, onLogout } = this.props; const { session, ...rest } = await this.auth.trackSession(); - const isLogin = session !== null; + const isLogin = session !== null && session !== undefined; if (isLogin) { onSuccess(rest); } else { @@ -62,7 +59,7 @@ class GitHubLogin extends Component { return isLogin; } - updateLoginState() { + updateLoginState(): void { this.intervalHandel = setInterval(() => { // eslint-disable-next-line promise/catch-or-return, promise/always-return this.isLogin().then((isLogin) => { @@ -72,15 +69,14 @@ class GitHubLogin extends Component { }, 500); } - render() { + render(): JSX.Element { const { onRequest, onLogout, onFailure, t } = this.props; const { isLogin } = this.state; return isLogin ? ( Promise { const { code, message } = await this.auth.logout(); - window.remote.clearStorageData(); + await window.service.window.clearStorageData(); if (code === 200) { this.setState({ isLogin: false }); this.updateLoginState(); @@ -95,7 +91,6 @@ class GitHubLogin extends Component { ) : ( void; col... Remove this comment to see the full error message onClick={() => { // clear token first, otherwise github login window won't give us a chance to see the form // void this.auth.logout(); diff --git a/src/components/shared/stated-menu.tsx b/src/components/github/stated-menu.tsx similarity index 100% rename from src/components/shared/stated-menu.tsx rename to src/components/github/stated-menu.tsx diff --git a/src/helpers/use-service-value.ts b/src/helpers/use-service-value.ts index 3bb86c7c..c753b531 100644 --- a/src/helpers/use-service-value.ts +++ b/src/helpers/use-service-value.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState, useCallback, Dispatch } from 'react'; import { AsyncReturnType } from 'type-fest'; /** @@ -12,6 +12,7 @@ export function usePromiseValue( defaultValue?: AsyncReturnType, ): T | DefaultValueType { const [value, valueSetter] = useState(defaultValue as T | DefaultValueType); + // use initial value useEffect(() => { void (async () => { valueSetter(await asyncValue()); @@ -20,3 +21,24 @@ export function usePromiseValue( return value; } + +export function usePromiseValueAndSetter( + asyncValue: () => Promise, + asyncSetter: (newValue: T | DefaultValueType) => Promise, + defaultValue?: AsyncReturnType, +): [T | DefaultValueType, Dispatch] { + const cachedSetter = useCallback(asyncSetter, [asyncSetter]); + const [value, valueSetter] = useState(defaultValue as T | DefaultValueType); + // use initial value + useEffect(() => { + void (async () => { + valueSetter(await asyncValue()); + }); + }, []); + // update remote value on change + useEffect(() => { + void cachedSetter(value); + }, [value, cachedSetter]); + + return [value, valueSetter]; +} diff --git a/src/components/dialog-add-workspace/clone-wiki-done-button.tsx b/src/pages/AddWorkspace/clone-wiki-done-button.tsx similarity index 98% rename from src/components/dialog-add-workspace/clone-wiki-done-button.tsx rename to src/pages/AddWorkspace/clone-wiki-done-button.tsx index 07a8dbc7..2055ccaf 100644 --- a/src/components/dialog-add-workspace/clone-wiki-done-button.tsx +++ b/src/pages/AddWorkspace/clone-wiki-done-button.tsx @@ -12,7 +12,7 @@ import Alert from '@material-ui/lab/Alert'; import * as actions from '../../state/dialog-add-workspace/actions'; -import type { IUserInfo } from '@services/types'; +import type { IAuthingUserInfo } from '@services/types'; import useWikiCreationMessage from './use-wiki-creation-message'; @@ -29,7 +29,7 @@ interface OwnProps { wikiFolderName: string; parentFolderLocation: string; tagName: string; - userInfo: IUserInfo; + userInfo: IAuthingUserInfo; } interface DispatchProps { updateForm: (Object) => void; diff --git a/src/components/dialog-add-workspace/description-and-mode-switch.tsx b/src/pages/AddWorkspace/description-and-mode-switch.tsx similarity index 100% rename from src/components/dialog-add-workspace/description-and-mode-switch.tsx rename to src/pages/AddWorkspace/description-and-mode-switch.tsx diff --git a/src/components/dialog-add-workspace/existed-wiki-done-button.tsx b/src/pages/AddWorkspace/existed-wiki-done-button.tsx similarity index 98% rename from src/components/dialog-add-workspace/existed-wiki-done-button.tsx rename to src/pages/AddWorkspace/existed-wiki-done-button.tsx index a0054550..f4da8b0c 100644 --- a/src/components/dialog-add-workspace/existed-wiki-done-button.tsx +++ b/src/pages/AddWorkspace/existed-wiki-done-button.tsx @@ -12,7 +12,7 @@ import Alert from '@material-ui/lab/Alert'; import * as actions from '../../state/dialog-add-workspace/actions'; -import type { IUserInfo } from '@services/types'; +import type { IAuthingUserInfo } from '@services/types'; import useWikiCreationMessage from './use-wiki-creation-message'; const CloseButton = styled(Button)` @@ -27,7 +27,7 @@ interface OwnProps { githubWikiUrl: string; existedFolderLocation: string; tagName: string; - userInfo: IUserInfo; + userInfo: IAuthingUserInfo; } interface DispatchProps { updateForm: (Object) => void; diff --git a/src/components/dialog-add-workspace/existed-wiki-path-form.tsx b/src/pages/AddWorkspace/existed-wiki-path-form.tsx similarity index 100% rename from src/components/dialog-add-workspace/existed-wiki-path-form.tsx rename to src/pages/AddWorkspace/existed-wiki-path-form.tsx diff --git a/src/components/dialog-add-workspace/index.tsx b/src/pages/AddWorkspace/index.tsx similarity index 75% rename from src/components/dialog-add-workspace/index.tsx rename to src/pages/AddWorkspace/index.tsx index 58ccc85f..6aa57963 100644 --- a/src/components/dialog-add-workspace/index.tsx +++ b/src/pages/AddWorkspace/index.tsx @@ -14,11 +14,11 @@ import NewWikiPathForm from './new-wiki-path-form'; import ExistedWikiPathForm from './existed-wiki-path-form'; import ExistedWikiDoneButton from './existed-wiki-done-button'; import CloneWikiDoneButton from './clone-wiki-done-button'; -import { getGithubUserInfo, setGithubUserInfo } from '@services/types'; import type { ISubWikiPluginContent } from '@services/wiki/update-plugin-content'; -import type { IUserInfo } from '@services/types'; +import type { IAuthingUserInfo } from '@services/types'; import TabBar from './tab-bar'; -import GitTokenForm, { getGithubToken, setGithubToken } from '../shared/git-token-form'; +import { GithubTokenForm, getGithubToken, setGithubToken } from '../../components/github/git-token-form'; +import { usePromiseValue, usePromiseValueAndSetter } from '@/helpers/use-service-value'; const graphqlClient = new GraphQLClient({ url: GITHUB_GRAPHQL_API, @@ -43,24 +43,15 @@ const GithubRepoLink = styled(Typography)` } `; -const setHeaderToGraphqlClient = (token: string) => graphqlClient.setHeader('Authorization', `bearer ${token}`); -const previousToken = getGithubToken(); -previousToken && setHeaderToGraphqlClient(previousToken); - -export default function AddWorkspace() { +export default function AddWorkspace(): JSX.Element { const [currentTab, currentTabSetter] = useState('CloneOnlineWiki'); const [isCreateMainWorkspace, isCreateMainWorkspaceSetter] = useState(false); useEffect(() => { void window.service.workspace.countWorkspaces().then((workspaceCount) => isCreateMainWorkspaceSetter(workspaceCount === 0)); }, []); - const [parentFolderLocation, parentFolderLocationSetter] = useState(); - const [existedFolderLocation, existedFolderLocationSetter] = useState(); - useEffect(() => { - void (async () => { - parentFolderLocationSetter(await window.service.context.get('DESKTOP_PATH')); - existedFolderLocationSetter(await window.service.context.get('DESKTOP_PATH')); - })(); - }); + const parentFolderLocation = usePromiseValue(async () => (await window.service.context.get('DESKTOP_PATH')) as string); + const existedFolderLocation = usePromiseValue(async () => (await window.service.context.get('DESKTOP_PATH')) as string); + const [wikiPort, wikiPortSetter] = useState(5212); useEffect(() => { // only update default port on component mount @@ -68,23 +59,28 @@ export default function AddWorkspace() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + // TODO: refactor GITHUB related things out, make it can switch between vendors + const cachedGithubToken = usePromiseValue(getGithubToken); // try get token on start up, so Github GraphQL client can use it - const [accessToken, accessTokenSetter] = useState(previousToken); + const [accessToken, accessTokenSetter] = useState(); // try get token from local storage, and set to state for gql to use useEffect(() => { - if (accessToken) { - graphqlClient.setHeader('Authorization', `bearer ${accessToken}`); - setGithubToken(accessToken); - } else { + // on startup, loading the cachedGithubToken + if (accessToken === undefined && cachedGithubToken !== undefined) { + graphqlClient.setHeader('Authorization', `bearer ${cachedGithubToken}`); + accessTokenSetter(cachedGithubToken); + } else if (accessToken !== undefined && accessToken !== cachedGithubToken) { + // if user or login button changed the token, we use latest token Object.keys(graphqlClient.headers).map((key) => graphqlClient.removeHeader(key)); - setGithubToken(); + accessTokenSetter(accessToken); + void setGithubToken(accessToken); } - }, [accessToken]); + }, [cachedGithubToken, accessToken]); - const [userInfo, userInfoSetter] = useState(getGithubUserInfo()); - useEffect(() => { - setGithubUserInfo(userInfo); - }, [userInfo]); + const [userName, userNameSetter] = usePromiseValueAndSetter( + async () => await window.service.auth.get('userName'), + async (newUserName) => await window.service.auth.set('userName', newUserName), + ); const [mainWikiToLink, mainWikiToLinkSetter] = useState({ name: '', port: 0 }); const [tagName, tagNameSetter] = useState(''); @@ -95,10 +91,12 @@ export default function AddWorkspace() { const [githubWikiUrl, githubWikiUrlSetter] = useState(''); useEffect(() => { void (async function getWorkspaceRemoteInEffect(): Promise { - const url = await window.service.git.getWorkspacesRemote(existedFolderLocation); - // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions - if (url) { - githubWikiUrlSetter(url); + if (existedFolderLocation !== undefined) { + const url = await window.service.git.getWorkspacesRemote(existedFolderLocation); + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + if (url) { + githubWikiUrlSetter(url); + } } })(); }, [githubWikiUrl, existedFolderLocation]); @@ -110,26 +108,22 @@ export default function AddWorkspace() { - {/* @ts-expect-error ts-migrate(2322) FIXME: Type 'string | void' is not assignable to type 'st... Remove this comment to see the full error message */} - + {githubWikiUrl && ( - // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 1. await window.service.native.open(githubWikiUrl)} variant="subtitle2" align="center"> ({githubWikiUrl}) )} - + {currentTab === 'CreateNewWiki' && ( diff --git a/src/components/dialog-add-workspace/new-wiki-done-button.tsx b/src/pages/AddWorkspace/new-wiki-done-button.tsx similarity index 98% rename from src/components/dialog-add-workspace/new-wiki-done-button.tsx rename to src/pages/AddWorkspace/new-wiki-done-button.tsx index a58844b2..a79dbef3 100644 --- a/src/components/dialog-add-workspace/new-wiki-done-button.tsx +++ b/src/pages/AddWorkspace/new-wiki-done-button.tsx @@ -12,7 +12,7 @@ import Alert from '@material-ui/lab/Alert'; import * as actions from '../../state/dialog-add-workspace/actions'; -import type { IUserInfo } from '@services/types'; +import type { IAuthingUserInfo } from '@services/types'; import useWikiCreationMessage from './use-wiki-creation-message'; @@ -29,7 +29,7 @@ interface OwnProps { wikiFolderName: string; parentFolderLocation: string; tagName: string; - userInfo: IUserInfo; + userInfo: IAuthingUserInfo; } interface DispatchProps { updateForm: (Object) => void; diff --git a/src/components/dialog-add-workspace/new-wiki-path-form.tsx b/src/pages/AddWorkspace/new-wiki-path-form.tsx similarity index 100% rename from src/components/dialog-add-workspace/new-wiki-path-form.tsx rename to src/pages/AddWorkspace/new-wiki-path-form.tsx diff --git a/src/components/dialog-add-workspace/search-repo.tsx b/src/pages/AddWorkspace/search-repo.tsx similarity index 98% rename from src/components/dialog-add-workspace/search-repo.tsx rename to src/pages/AddWorkspace/search-repo.tsx index 79048221..c8d4bf2d 100644 --- a/src/components/dialog-add-workspace/search-repo.tsx +++ b/src/pages/AddWorkspace/search-repo.tsx @@ -16,7 +16,7 @@ import Button from '@material-ui/core/Button'; import CachedIcon from '@material-ui/icons/Cached'; import CreateNewFolderIcon from '@material-ui/icons/CreateNewFolder'; -import type { IUserInfo } from '@services/types'; +import type { IAuthingUserInfo } from '@services/types'; const RepoSearchInput = styled(TextField)``; const ReloadButton = styled(Button)` @@ -69,7 +69,7 @@ interface Props { githubWikiUrlSetter: (string) => void; // @ts-expect-error ts-migrate(7051) FIXME: Parameter has a name but no type. Did you mean 'ar... Remove this comment to see the full error message wikiFolderNameSetter: (string) => void; - userInfo: IUserInfo; + userInfo: IAuthingUserInfo; isCreateMainWorkspace: boolean; } export default function SearchRepo({ diff --git a/src/components/dialog-add-workspace/tab-bar.tsx b/src/pages/AddWorkspace/tab-bar.tsx similarity index 100% rename from src/components/dialog-add-workspace/tab-bar.tsx rename to src/pages/AddWorkspace/tab-bar.tsx diff --git a/src/components/dialog-add-workspace/use-wiki-creation-message.tsx b/src/pages/AddWorkspace/use-wiki-creation-message.tsx similarity index 100% rename from src/components/dialog-add-workspace/use-wiki-creation-message.tsx rename to src/pages/AddWorkspace/use-wiki-creation-message.tsx diff --git a/src/renderer.tsx b/src/renderer.tsx index a64b7749..f71c4074 100644 --- a/src/renderer.tsx +++ b/src/renderer.tsx @@ -22,7 +22,7 @@ import { initI18N } from './i18n'; import AppWrapper from './components/app-wrapper'; const AboutPage = React.lazy(async () => await import('./pages/About')); -const DialogAddWorkspace = React.lazy(async () => await import('./components/dialog-add-workspace')); +const DialogAddWorkspace = React.lazy(async () => await import('./pages/AddWorkspace')); const DialogAuth = React.lazy(async () => await import('./components/dialog-auth')); const DialogCustomUserAgent = React.lazy(async () => await import('./components/dialog-custom-user-agent')); const DialogDisplayMedia = React.lazy(async () => await import('./components/dialog-display-media')); diff --git a/src/services/auth/index.ts b/src/services/auth/index.ts index 7bbbbbbd..998f1b15 100644 --- a/src/services/auth/index.ts +++ b/src/services/auth/index.ts @@ -2,7 +2,7 @@ import { injectable } from 'inversify'; import getDecorators from 'inversify-inject-decorators'; import settings from 'electron-settings'; -import { IUserInfo as IAuthingUserInfo } from '@services/types'; +import { IAuthingUserInfo as IAuthingUserInfo } from '@services/types'; import { container } from '@services/container'; import type { IWindowService } from '@services/windows/interface'; import serviceIdentifier from '@services/serviceIdentifier'; diff --git a/src/services/auth/interface.ts b/src/services/auth/interface.ts index c1cdcacf..337227d9 100644 --- a/src/services/auth/interface.ts +++ b/src/services/auth/interface.ts @@ -1,11 +1,10 @@ /* eslint-disable unicorn/no-null */ import { ProxyPropertyType } from '@/helpers/electron-ipc-proxy/common'; import { AuthenticationChannel } from '@/constants/channels'; -import { IUserInfo as IAuthingUserInfo } from '@services/types'; export interface IUserInfos { userName: string; - authing: IAuthingUserInfo | undefined; + 'github-token'?: string; } /** diff --git a/src/services/constants/paths.ts b/src/services/constants/paths.ts index 025d3693..5617b16b 100644 --- a/src/services/constants/paths.ts +++ b/src/services/constants/paths.ts @@ -7,7 +7,7 @@ const isMac = process.platform === 'darwin'; const sourcePath = path.resolve(__dirname, '..', '..'); export const buildResourcePath = path.resolve(sourcePath, '..', 'build-resources'); -const REACT_PATH = 'MAIN_WINDOW_WEBPACK_ENTRY'; +const REACT_PATH = MAIN_WINDOW_WEBPACK_ENTRY; // .app/Contents/Resources/wiki/ const TIDDLYWIKI_TEMPLATE_FOLDER_PATH = isDev ? path.resolve(sourcePath, '..', 'template', 'wiki') : path.resolve(process.resourcesPath, '..', 'wiki'); const TIDDLERS_PATH = 'tiddlers'; diff --git a/src/services/git/github.ts b/src/services/git/github.ts index e84f5964..c36b0162 100644 --- a/src/services/git/github.ts +++ b/src/services/git/github.ts @@ -1,7 +1,7 @@ import { compact, trim } from 'lodash'; import { GitProcess } from 'dugite'; -import { IUserInfo } from '@services/types'; +import { IAuthingUserInfo } from '@services/types'; const getGitUrlWithCredential = (rawUrl: string, username: string, accessToken: string): string => trim(`${rawUrl}.git`.replace(/\n/g, '').replace('https://github.com/', `https://${username}:${accessToken}@github.com/`)); @@ -24,7 +24,7 @@ export async function getRemoteUrl(wikiFolderPath: string): Promise { * @param {string} githubRepoUrl * @param {{ login: string, email: string, accessToken: string }} userInfo */ -export async function credentialOn(wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo): Promise { +export async function credentialOn(wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo): Promise { const { login: username, accessToken } = userInfo; const gitUrlWithCredential = getGitUrlWithCredential(githubRepoUrl, username, accessToken); await GitProcess.exec(['remote', 'add', 'origin', gitUrlWithCredential], wikiFolderPath); diff --git a/src/services/git/index.ts b/src/services/git/index.ts index 410e49b6..b139951d 100644 --- a/src/services/git/index.ts +++ b/src/services/git/index.ts @@ -11,7 +11,7 @@ import type { IViewService } from '@services/view/interface'; 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 { IAuthingUserInfo } from '@services/types'; import { getModifiedFileList, ModifiedFileList } from './inspect'; import { IGitService } from './interface'; @@ -27,7 +27,7 @@ export class Git implements IGitService { this.debounceCommitAndSync = debounce(this.commitAndSync.bind(this), syncDebounceInterval); } - public debounceCommitAndSync: (wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo) => Promise | undefined; + public debounceCommitAndSync: (wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo) => Promise | undefined; public async getWorkspacesRemote(wikiFolderPath: string): Promise { return await github.getRemoteUrl(wikiFolderPath); @@ -69,7 +69,7 @@ export class Git implements IGitService { * @param {boolean} isMainWiki * @param {{ info: Function, notice: Function }} logger Logger instance from winston */ - public async initWikiGit(wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo, isMainWiki: boolean): Promise { + public async initWikiGit(wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo, isMainWiki: boolean): Promise { const logProgress = (message: string): unknown => logger.notice(message, { handler: 'createWikiProgress', function: 'initWikiGit' }); const logInfo = (message: string): unknown => logger.info(message, { function: 'initWikiGit' }); @@ -107,7 +107,7 @@ export class Git implements IGitService { * @param {string} githubRepoUrl * @param {{ login: string, email: string, accessToken: string }} userInfo */ - public async commitAndSync(wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo): Promise { + public async commitAndSync(wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo): Promise { /** functions to send data to main thread */ const logProgress = (message: string): unknown => logger.notice(message, { handler: 'wikiSyncProgress', function: 'commitAndSync', wikiFolderPath, githubRepoUrl }); @@ -217,7 +217,7 @@ export class Git implements IGitService { logProgress(i18n.t('Log.SynchronizationFinish')); } - public async clone(githubRepoUrl: string, repoFolderPath: string, userInfo: IUserInfo): Promise { + public async clone(githubRepoUrl: string, repoFolderPath: string, userInfo: IAuthingUserInfo): Promise { const logProgress = (message: string): unknown => logger.notice(message, { handler: 'createWikiProgress', function: 'clone' }); const logInfo = (message: string): unknown => logger.info(message, { function: 'clone' }); logProgress(i18n.t('Log.PrepareCloneOnlineWiki')); diff --git a/src/services/git/interface.ts b/src/services/git/interface.ts index 36cb9e36..67a5240a 100644 --- a/src/services/git/interface.ts +++ b/src/services/git/interface.ts @@ -1,5 +1,5 @@ import { ProxyPropertyType } from '@/helpers/electron-ipc-proxy/common'; -import { IUserInfo } from '@services/types'; +import { IAuthingUserInfo } from '@services/types'; import { GitChannel } from '@/constants/channels'; import { ModifiedFileList } from './inspect'; @@ -11,13 +11,13 @@ export interface IGitService { /** * Call commitAndSync every period of time. This cannot be used as promise, as said in https://github.com/lodash/lodash/issues/4700 */ - debounceCommitAndSync: (wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo) => Promise | undefined; + debounceCommitAndSync: (wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo) => Promise | undefined; updateGitInfoTiddler(githubRepoName: string): Promise; getModifiedFileList(wikiFolderPath: string): Promise; - initWikiGit(wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo, isMainWiki: boolean): Promise; - commitAndSync(wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo): Promise; + initWikiGit(wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo, isMainWiki: boolean): Promise; + commitAndSync(wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo): Promise; getWorkspacesRemote(wikiFolderPath: string): Promise; - clone(githubRepoUrl: string, repoFolderPath: string, userInfo: IUserInfo): Promise; + clone(githubRepoUrl: string, repoFolderPath: string, userInfo: IAuthingUserInfo): Promise; } export const GitServiceIPCDescriptor = { channel: GitChannel.name, diff --git a/src/services/types.ts b/src/services/types.ts index 6f10624e..acc711af 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -2,10 +2,23 @@ export interface IService { init?: (...parameters: never[]) => Promise; } - +export interface IAuthingResponse { + session?: null | { appId: string; type: string; userId: string }; + userInfo?: { + thirdPartyIdentity?: { + accessToken?: string; + }; + oauth?: string; + }; + urlParams?: { + code: string; // 这些参数是从 url 中获取到的,需要开发者自己存储以备使用 + id_token: string; + access_token: string; + }; +} // {"email":"linonetwo012@gmail.com","phone":"","emailVerified":false,"phoneVerified":false,"username":"lin onetwo","nickname":"","company":"ByteDance","photo":"https://avatars1.githubusercontent.com/u/3746270?v=4","browser":"","device":"","loginsCount":26,"registerMethod":"oauth:github","blocked":false,"isDeleted":false,"phoneCode":"","name":"lin onetwo","givenName":"","familyName":"","middleName":"","profile":"","preferredUsername":"","website":"","gender":"","birthdate":"","zoneinfo":"","locale":"","address":"","formatted":"","streetAddress":"","locality":"","region":"","postalCode":"","country":"","updatedAt":"2020-07-04T05:08:53.472Z","metadata":"","_operate_history":[],"sendSMSCount":0,"sendSMSLimitCount":1000,"_id":"5efdd5475b9f7bc0990d7377","unionid":"3746270","lastIP":"61.223.86.45","registerInClient":"5efdd30d48432dfae5d047da","lastLogin":"2020-07-04T05:08:53.665Z","signedUp":"2020-07-02T12:38:31.485Z","__v":0,"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImVtYWlsIjoibGlub2","tokenExpiredAt":"2020-07-19T05:08:53.000Z","__Token 验证方式说明":"https://docs.authing.cn/authing/advanced/authentication/verify-jwt-token#fa-song-token-gei-authing-fu-wu-qi-yan-zheng","login":"linonetwo","id":3746270,"node_id":"MDQ6VXNlcjM3NDYyNzA=","avatar_url":"https://avatars1.githubusercontent.com/u/3746270?v=4","gravatar_id":"","url":"https://api.github.com/users/linonetwo","html_url":"https://github.com/linonetwo","followers_url":"https://api.github.com/users/linonetwo/followers","following_url":"https://api.github.com/users/linonetwo/following{/other_user}","gists_url":"https://api.github.com/users/linonetwo/gists{/gist_id}","starred_url":"https://api.github.com/users/linonetwo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/linonetwo/subscriptions","organizations_url":"https://api.github.com/users/linonetwo/orgs","repos_url":"https://api.github.com/users/linonetwo/repos","events_url":"https://api.github.com/users/linonetwo/events{/privacy}","received_events_url":"https://api.github.com/users/linonetwo/received_events","type":"User","site_admin":false,"blog":"https://onetwo.ren","location":"Shanghaitech University","hireable":null,"bio":"Use Web technology to create dev-tool and knowledge tools for procedural content generation. Hopefully will create a knowledge-driven PCG in game cosmos one day","twitter_username":null,"public_repos":146,"public_gists":13,"followers":167,"following":120,"created_at":"2013-03-02T07:09:13Z","updated_at":"2020-07-02T12:36:46Z","accessToken":"f5610134da3c51632e43e8a2413863987e8ad16e","scope":"repo","provider":"github","expiresIn":null} -export interface IUserInfo { +export interface IAuthingUserInfo { email: string; phone: string; emailVerified: boolean; diff --git a/src/services/wiki/index.ts b/src/services/wiki/index.ts index 775d3d84..14e184e5 100644 --- a/src/services/wiki/index.ts +++ b/src/services/wiki/index.ts @@ -17,7 +17,7 @@ import type { IViewService } from '@services/view/interface'; import type { IWorkspaceService, IWorkspace } from '@services/workspaces/interface'; import type { IGitService } from '@services/git/interface'; import type { IWorkspaceViewService } from '@services/workspacesView/interface'; -import { IUserInfo } from '@services/types'; +import { IAuthingUserInfo } from '@services/types'; import { WindowNames } from '@services/windows/WindowProperties'; import { logger, wikiOutputToFile, refreshOutputFile } from '@services/libs/log'; import i18n from '@services/libs/i18n'; @@ -285,7 +285,7 @@ export class Wiki { } } - public async cloneWiki(parentFolderLocation: string, wikiFolderName: string, githubWikiUrl: string, userInfo: IUserInfo): Promise { + public async cloneWiki(parentFolderLocation: string, wikiFolderName: string, githubWikiUrl: string, userInfo: IAuthingUserInfo): Promise { this.logProgress(i18n.t('AddWorkspace.StartCloningWiki')); const newWikiPath = path.join(parentFolderLocation, wikiFolderName); if (!(await fs.pathExists(parentFolderLocation))) { @@ -307,7 +307,7 @@ export class Wiki { wikiFolderName: string, mainWikiPath: string, githubWikiUrl: string, - userInfo: IUserInfo, + userInfo: IAuthingUserInfo, tagName = '', ): Promise { this.logProgress(i18n.t('AddWorkspace.StartCloningSubWiki')); @@ -430,7 +430,7 @@ export class Wiki { // { [name: string]: Watcher } private readonly wikiWatchers: Record = {}; - public async watchWiki(wikiRepoPath: string, githubRepoUrl: string, userInfo: IUserInfo, wikiFolderPath = wikiRepoPath): Promise { + public async watchWiki(wikiRepoPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo, wikiFolderPath = wikiRepoPath): Promise { if (!fs.existsSync(wikiRepoPath)) { logger.error('Folder not exist in watchFolder()', { wikiRepoPath, wikiFolderPath, githubRepoUrl }); return; diff --git a/src/services/wiki/interface.ts b/src/services/wiki/interface.ts index 23614177..01faffca 100644 --- a/src/services/wiki/interface.ts +++ b/src/services/wiki/interface.ts @@ -1,7 +1,7 @@ import { ProxyPropertyType } from '@/helpers/electron-ipc-proxy/common'; import { WikiChannel } from '@/constants/channels'; import { IWorkspace } from '@services/workspaces/interface'; -import { IUserInfo } from '@services/types'; +import { IAuthingUserInfo } from '@services/types'; import type { ISubWikiPluginContent } from './update-plugin-content'; /** @@ -21,18 +21,18 @@ export interface IWikiService { createSubWiki(newFolderPath: string, folderName: string, mainWikiPath: string, tagName?: string, onlyLink?: boolean): Promise; removeWiki(wikiPath: string, mainWikiToUnLink?: string, onlyRemoveLink?: boolean): Promise; ensureWikiExist(wikiPath: string, shouldBeMainWiki: boolean): Promise; - cloneWiki(parentFolderLocation: string, wikiFolderName: string, githubWikiUrl: string, userInfo: IUserInfo): Promise; + cloneWiki(parentFolderLocation: string, wikiFolderName: string, githubWikiUrl: string, userInfo: IAuthingUserInfo): Promise; cloneSubWiki( parentFolderLocation: string, wikiFolderName: string, mainWikiPath: string, githubWikiUrl: string, - userInfo: IUserInfo, + userInfo: IAuthingUserInfo, tagName?: string, ): Promise; wikiStartup(workspace: IWorkspace): Promise; startNodeJSWiki(homePath: string, port: number, userName: string, workspaceID: string): Promise; - watchWiki(wikiRepoPath: string, githubRepoUrl: string, userInfo: IUserInfo, wikiFolderPath?: string): Promise; + watchWiki(wikiRepoPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo, wikiFolderPath?: string): Promise; stopWatchWiki(wikiRepoPath: string): Promise; stopWatchAllWiki(): Promise; } diff --git a/src/services/wikiGitWorkspace/index.ts b/src/services/wikiGitWorkspace/index.ts index 89718986..233d60a4 100644 --- a/src/services/wikiGitWorkspace/index.ts +++ b/src/services/wikiGitWorkspace/index.ts @@ -14,7 +14,7 @@ import { lazyInject } from '@services/container' import { logger } from '@services/libs/log'; import i18n from '@services/libs/i18n'; -import { IUserInfo } from '@services/types'; +import { IAuthingUserInfo } from '@services/types'; import { IWikiGitWorkspaceService } from './interface'; import { IMenuService } from '@services/menu/interface'; @@ -28,7 +28,7 @@ export class WikiGitWorkspace implements IWikiGitWorkspaceService { @lazyInject(serviceIdentifier.Authentication) private readonly authService!: IAuthenticationService; @lazyInject(serviceIdentifier.MenuService) private readonly menuService!: IMenuService; - public initWikiGitTransaction = async (wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo, isMainWiki: boolean): Promise => { + public initWikiGitTransaction = async (wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo, isMainWiki: boolean): Promise => { try { await this.gitService.initWikiGit(wikiFolderPath, githubRepoUrl, userInfo, isMainWiki); } catch (error) { diff --git a/src/services/wikiGitWorkspace/interface.ts b/src/services/wikiGitWorkspace/interface.ts index c2138c00..2f1bd77b 100644 --- a/src/services/wikiGitWorkspace/interface.ts +++ b/src/services/wikiGitWorkspace/interface.ts @@ -1,12 +1,12 @@ import { ProxyPropertyType } from '@/helpers/electron-ipc-proxy/common'; import { WikiGitWorkspaceChannel } from '@/constants/channels'; -import { IUserInfo } from '@services/types'; +import { IAuthingUserInfo } from '@services/types'; /** * Deal with operations that needs to create a wiki and a git repo at once in a workspace */ export interface IWikiGitWorkspaceService { - initWikiGitTransaction: (wikiFolderPath: string, githubRepoUrl: string, userInfo: IUserInfo, isMainWiki: boolean) => Promise; + initWikiGitTransaction: (wikiFolderPath: string, githubRepoUrl: string, userInfo: IAuthingUserInfo, isMainWiki: boolean) => Promise; removeWorkspace: (id: string) => Promise; } export const WikiGitWorkspaceServiceIPCDescriptor = { diff --git a/src/services/windows/index.ts b/src/services/windows/index.ts index 5fef0530..0bf80686 100644 --- a/src/services/windows/index.ts +++ b/src/services/windows/index.ts @@ -340,6 +340,11 @@ export class Window implements IWindowService { win?.getBrowserView()?.webContents?.reload(); } + public async clearStorageData(windowName: WindowNames = WindowNames.main): Promise { + const win = this.get(windowName); + await win?.getBrowserView()?.webContents?.session?.clearStorageData(); + } + private registerMenu(): void { this.menuService.insertMenu( 'window', diff --git a/src/services/windows/interface.ts b/src/services/windows/interface.ts index 3540dc48..d6aaef15 100644 --- a/src/services/windows/interface.ts +++ b/src/services/windows/interface.ts @@ -20,6 +20,7 @@ export interface IWindowService { goBack(windowName: WindowNames): void; goForward(windowName: WindowNames): void; reload(windowName: WindowNames): void; + clearStorageData(windowName?: WindowNames): Promise; findInPage(text: string, forward?: boolean | undefined, windowName?: WindowNames): void; stopFindInPage(close?: boolean | undefined, windowName?: WindowNames): void; } @@ -39,6 +40,7 @@ export const WindowServiceIPCDescriptor = { goBack: ProxyPropertyType.Function, goForward: ProxyPropertyType.Function, reload: ProxyPropertyType.Function, + clearStorageData: ProxyPropertyType.Function, findInPage: ProxyPropertyType.Function, stopFindInPage: ProxyPropertyType.Function, },