diff --git a/src/constants/urls.ts b/src/constants/urls.ts index 039ec1b4..ab833875 100644 --- a/src/constants/urls.ts +++ b/src/constants/urls.ts @@ -8,3 +8,5 @@ export const githubDesktopUrl = 'https://desktop.github.com/'; * This is currently unused, because it always entering /#safe:safe , very annoying. And even entered, the url can still not containing this. So I decided not support enter/quit safe mode now. */ export const safeModeHash = '#:safe'; +export const getDefaultHTTPServerIP = (port: number) => `http://${defaultServerIP}:${port}`; +export const getDefaultTidGiUrl = (workspaceID: string) => `tidgi://${workspaceID}`; diff --git a/src/pages/EditWorkspace/index.tsx b/src/pages/EditWorkspace/index.tsx index c89f4fa1..6ca47356 100644 --- a/src/pages/EditWorkspace/index.tsx +++ b/src/pages/EditWorkspace/index.tsx @@ -20,7 +20,6 @@ import { List, ListItem, ListItemText } from '@/components/ListItem'; import { useRestartSnackbar } from '@/components/RestartSnackbar'; import { TokenForm } from '@/components/TokenForm'; import { wikiPictureExtensions } from '@/constants/fileNames'; -import { useActualIp } from '@services/native/hooks'; import { SupportedStorageServices } from '@services/types'; import { isEqual } from 'lodash'; import { SyncedWikiDescription } from '../AddWorkspace/Description'; @@ -173,7 +172,6 @@ export default function EditWorkspace(): JSX.Element { const fallbackUserName = usePromiseValue(async () => (await window.service.auth.get('userName')) as string, ''); const rememberLastPageVisited = usePromiseValue(async () => await window.service.preference.get('rememberLastPageVisited')); - const actualIP = useActualIp(homeUrl, workspaceID); if (workspaceID === undefined) { return Error {workspaceID ?? '-'} not exists; } @@ -230,17 +228,17 @@ export default function EditWorkspace(): JSX.Element { id='outlined-full-width' label={t('EditWorkspace.LastVisitState')} helperText={t('Preference.RememberLastVisitState')} - placeholder={actualIP} + placeholder={homeUrl} value={lastUrl} onChange={(event) => { workspaceSetter({ ...workspace, - lastUrl: (event.target.value || actualIP) ?? '', + lastUrl: (event.target.value || homeUrl) ?? '', }); }} /> )} - + )} {isSubWiki && ( diff --git a/src/pages/EditWorkspace/server.tsx b/src/pages/EditWorkspace/server.tsx index 21367143..f4cbf5ec 100644 --- a/src/pages/EditWorkspace/server.tsx +++ b/src/pages/EditWorkspace/server.tsx @@ -23,8 +23,9 @@ import { DEFAULT_USER_NAME, getTidGiAuthHeaderWithToken } from '@/constants/auth import { WikiChannel } from '@/constants/channels'; import { rootTiddlers } from '@/constants/defaultTiddlerNames'; import { tlsCertExtensions, tlsKeyExtensions } from '@/constants/fileNames'; -import { defaultServerIP } from '@/constants/urls'; +import { defaultServerIP, getDefaultHTTPServerIP } from '@/constants/urls'; import { usePromiseValue } from '@/helpers/useServiceValue'; +import { useActualIp } from '@services/native/hooks'; import { IWorkspace } from '@services/workspaces/interface'; const AServerOptionsAccordion = styled(Accordion)` @@ -48,13 +49,12 @@ const AuthTokenTextAndButtonContainer = styled.div` `; export interface IServerOptionsProps { - actualIP: string | undefined; workspace: IWorkspace; workspaceSetter: (newValue: IWorkspace, requestSaveAndRestart?: boolean | undefined) => void; } export function ServerOptions(props: IServerOptionsProps) { const { t } = useTranslation(); - const { workspace, actualIP, workspaceSetter } = props; + const { workspace, workspaceSetter } = props; const { https = { enabled: false }, port, @@ -67,6 +67,7 @@ export function ServerOptions(props: IServerOptionsProps) { userName, id, } = (workspace ?? {}) as unknown as IWorkspace; + const actualIP = useActualIp(getDefaultHTTPServerIP(port), id); // some feature need a username to work, so if userName is empty, assign a fallbackUserName DEFAULT_USER_NAME // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const fallbackUserName = usePromiseValue(async () => (await window.service.auth.get('userName')) as string, ''); diff --git a/src/services/view/index.ts b/src/services/view/index.ts index c56a7f03..16ebcde3 100644 --- a/src/services/view/index.ts +++ b/src/services/view/index.ts @@ -12,6 +12,7 @@ import type { IWorkspaceService } from '@services/workspaces/interface'; import type { IWorkspaceViewService } from '@services/workspacesView/interface'; import { MetaDataChannel, ViewChannel, WindowChannel } from '@/constants/channels'; +import { getDefaultTidGiUrl } from '@/constants/urls'; import { isMac, isWin } from '@/helpers/system'; import { IAuthenticationService } from '@services/auth/interface'; import { lazyInject } from '@services/container'; @@ -319,26 +320,21 @@ export class View implements IViewService { workspace, sharedWebPreferences, loadInitialUrlWithCatch: async () => { - // await this.loadUrlForView(workspace, view, windowName); + await this.loadUrlForView(workspace, view, windowName); }, }); - await setupIpcServerRoutesHandlers(view, workspace.id); - // await this.loadUrlForView(workspace, view, windowName); + setupIpcServerRoutesHandlers(view, workspace.id); + await this.loadUrlForView(workspace, view, windowName); } public async loadUrlForView(workspace: IWorkspace, view: BrowserView, windowName: WindowNames): Promise { const { rememberLastPageVisited } = await this.preferenceService.getPreferences(); // fix some case that local ip can't be load - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const urlToReplace = rememberLastPageVisited ? workspace.lastUrl ?? workspace.homeUrl : workspace.homeUrl; - const replacedUrl = await this.nativeService.getLocalHostUrlWithActualInfo(urlToReplace, workspace.id); - logger.debug(`Load initialUrl: ${replacedUrl} for windowName ${windowName} for workspace ${workspace.name}`, { - urlToReplace, - replacedUrl, - }); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing, @typescript-eslint/strict-boolean-expressions + const urlToLoad = (rememberLastPageVisited ? workspace.lastUrl ?? workspace.homeUrl : workspace.homeUrl) || getDefaultTidGiUrl(workspace.id); try { logger.debug( - `loadInitialUrlWithCatch(): view.webContents: ${String(view.webContents)} ${replacedUrl} for windowName ${windowName} for workspace ${workspace.name}`, + `loadUrlForView(): view.webContents: ${String(view.webContents)} urlToLoad: ${urlToLoad} for windowName ${windowName} for workspace ${workspace.name}`, { stack: new Error('stack').stack?.replace('Error:', '') }, ); if (await this.workspaceService.workspaceDidFailLoad(workspace.id)) { @@ -350,14 +346,16 @@ export class View implements IViewService { didFailLoadErrorMessage: null, isLoading: true, }); - await view.webContents.loadURL(replacedUrl); - logger.debug('loadInitialUrlWithCatch() await loadURL() done'); + // DEBUG devTool + // view.webContents.openDevTools({ mode: 'detach' }); + await view.webContents.loadURL(urlToLoad); + logger.debug('loadUrlForView() await loadURL() done'); const unregisterContextMenu = await this.menuService.initContextMenuForWindowWebContents(view.webContents); view.webContents.on('destroyed', () => { unregisterContextMenu(); }); } catch (error) { - logger.warn(new ViewLoadUrlError(replacedUrl, `${(error as Error).message} ${(error as Error).stack ?? ''}`)); + logger.warn(new ViewLoadUrlError(urlToLoad, `${(error as Error).message} ${(error as Error).stack ?? ''}`)); } } diff --git a/src/services/view/setupIpcServerRoutesHandlers.ts b/src/services/view/setupIpcServerRoutesHandlers.ts index 8a3c6d33..49feacc5 100644 --- a/src/services/view/setupIpcServerRoutesHandlers.ts +++ b/src/services/view/setupIpcServerRoutesHandlers.ts @@ -8,15 +8,14 @@ import { IWikiService } from '@services/wiki/interface'; import { IWorkspaceService } from '@services/workspaces/interface'; import type { ITiddlerFields } from 'tiddlywiki'; -export async function setupIpcServerRoutesHandlers(view: BrowserView, workspaceID: string) { - const urlBase = `tidgi://${workspaceID}`; +export function setupIpcServerRoutesHandlers(view: BrowserView, workspaceID: string) { const workspaceService = container.get(serviceIdentifier.Workspace); const authService = container.get(serviceIdentifier.Authentication); const wikiService = container.get(serviceIdentifier.Wiki); const methods = [ { method: 'GET', - path: /^\/$/, + path: /^\/?$/, name: 'getIndex', handler: async (_request: GlobalRequest, _parameters: RegExpMatchArray | null) => await wikiService.callWikiIpcServerRoute(workspaceID, 'getIndex', (await workspaceService.get(workspaceID))?.rootTiddler ?? '$:/core/save/lazy-images'), @@ -83,16 +82,20 @@ export async function setupIpcServerRoutesHandlers(view: BrowserView, workspaceI async function handlerCallback(request: GlobalRequest): Promise { const parsedUrl = new URL(request.url); // Iterate through methods to find matching routes + // DEBUG: console parsedUrl + console.log(`parsedUrl`, parsedUrl); try { for (const route of methods) { + // DEBUG: console parsedUrl.pathname + console.log(`parsedUrl.pathname`, parsedUrl.pathname, request.method === route.method, route.name, route.path.test(parsedUrl.pathname)); if (request.method === route.method && route.path.test(parsedUrl.pathname)) { // Get the parameters in the URL path const parameters = parsedUrl.pathname.match(route.path); - logger.debug(`loadHTMLStringForView: ${route.name}`, { parsedUrl, parameters }); + logger.debug(`setupIpcServerRoutesHandlers.handlerCallback: ${route.name}`, { parsedUrl, parameters }); // Call the handler of the route to process the request and return the result const responseData = await route.handler(request, parameters); if (responseData === undefined) { - const statusText = `loadHTMLStringForView: responseData is undefined ${request.url}`; + const statusText = `setupIpcServerRoutesHandlers.handlerCallback: responseData is undefined ${request.url}`; logger.warn(statusText); return new Response(undefined, { status: 404, statusText }); } @@ -102,7 +105,7 @@ export async function setupIpcServerRoutesHandlers(view: BrowserView, workspaceI } catch (error) { return new Response(undefined, { status: 500, statusText: `${(error as Error).message} ${(error as Error).stack ?? ''}` }); } - const statusText = `loadHTMLStringForView: tidgi protocol is not handled ${request.url}`; + const statusText = `setupIpcServerRoutesHandlers.handlerCallback: tidgi protocol is not handled ${request.url}`; logger.warn(statusText); return new Response(undefined, { status: 404, statusText }); } @@ -111,13 +114,9 @@ export async function setupIpcServerRoutesHandlers(view: BrowserView, workspaceI view.webContents.session.protocol.handle(`tidgi`, handlerCallback); const handled = view.webContents.session.protocol.isProtocolHandled(`tidgi`); if (!handled) { - logger.warn(`loadHTMLStringForView: tidgi protocol is not handled`); + logger.warn(`setupIpcServerRoutesHandlers.handlerCallback: tidgi protocol is not handled`); } - logger.info(`view.webContents.loadURL(${urlBase}/)`); - // DEBUG devTool - // view.webContents.openDevTools({ mode: 'detach' }); - await view.webContents.loadURL(`${urlBase}/`); } catch (error) { - logger.error(`loadHTMLStringForView: ${(error as Error).message}`); + logger.error(`setupIpcServerRoutesHandlers.handlerCallback: ${(error as Error).message}`); } } diff --git a/src/services/wiki/plugin/ipcSyncAdaptor/fix-location-info.ts b/src/services/wiki/plugin/ipcSyncAdaptor/fix-location-info.ts index a9abd5d2..348673ef 100644 --- a/src/services/wiki/plugin/ipcSyncAdaptor/fix-location-info.ts +++ b/src/services/wiki/plugin/ipcSyncAdaptor/fix-location-info.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/strict-boolean-expressions */ +import { getDefaultHTTPServerIP } from '@/constants/urls'; import type { WindowMeta, WindowNames } from '@services/windows/WindowProperties'; function getInfoTiddlerFields(updateInfoTiddlersCallback: (infos: Array<{ text: string; title: string }>) => void) { @@ -20,7 +21,7 @@ function getInfoTiddlerFields(updateInfoTiddlersCallback: (infos: Array<{ text: const setLocationProperty = function(name: string, value: string) { asyncInfoTiddlerFields.push({ title: '$:/info/url/' + name, text: value }); }; - const localHostUrl = await window.service.native.getLocalHostUrlWithActualInfo(workspace.homeUrl, workspaceID); + const localHostUrl = await window.service.native.getLocalHostUrlWithActualInfo(getDefaultHTTPServerIP(workspace.port), workspaceID); const urlObject = new URL(localHostUrl); setLocationProperty('full', (localHostUrl).split('#')[0]); setLocationProperty('host', urlObject.host); diff --git a/src/services/workspaces/index.ts b/src/services/workspaces/index.ts index 0f0980e5..8a76f79d 100644 --- a/src/services/workspaces/index.ts +++ b/src/services/workspaces/index.ts @@ -13,8 +13,9 @@ import path from 'path'; import { BehaviorSubject, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { defaultServerIP } from '@/constants/urls'; +import { getDefaultTidGiUrl } from '@/constants/urls'; import { fixSettingFileWhenError } from '@/helpers/configSetting'; +import { IAuthenticationService } from '@services/auth/interface'; import { lazyInject } from '@services/container'; import { i18n } from '@services/libs/i18n'; import { logger } from '@services/libs/log'; @@ -29,7 +30,6 @@ import { WindowNames } from '@services/windows/WindowProperties'; import type { IWorkspaceViewService } from '@services/workspacesView/interface'; import type { INewWorkspaceConfig, IWorkspace, IWorkspaceMetaData, IWorkspaceService, IWorkspaceWithMetadata } from './interface'; import { workspaceSorter } from './utils'; -import { IAuthenticationService } from '@services/auth/interface'; // eslint-disable-next-line @typescript-eslint/no-unsafe-argument const debouncedSetSettingFile = debounce(async (workspaces: Record) => { @@ -291,8 +291,11 @@ export class Workspace implements IWorkspaceService { fixingValues.tagName = workspaceToSanitize.tagName.replaceAll('\n', ''); } // before 0.8.0, tidgi was loading http content, so lastUrl will be http protocol, but later we switch to tidgi:// protocol, so old value can't be used. - if (workspaceToSanitize.lastUrl?.startsWith('tidgi')) { - fixingValues.lastUrl = ''; + if (!workspaceToSanitize.lastUrl?.startsWith('tidgi')) { + fixingValues.lastUrl = null; + } + if (!workspaceToSanitize.homeUrl?.startsWith('tidgi')) { + fixingValues.homeUrl = getDefaultTidGiUrl(workspaceToSanitize.id); } if (workspaceToSanitize.tokenAuth && !workspaceToSanitize.authToken) { fixingValues.authToken = this.authService.generateOneTimeAdminAuthTokenForWorkspaceSync(workspaceToSanitize.id); @@ -475,7 +478,7 @@ export class Workspace implements IWorkspaceService { disableNotifications: false, hibernated: false, hibernateWhenUnused: false, - homeUrl: `http://${defaultServerIP}:${newWorkspaceConfig.port}`, + homeUrl: getDefaultTidGiUrl(newID), id: newID, lastUrl: null, lastNodeJSArgv: [],