Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 42 additions & 17 deletions src/components/AppController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import React, {
} from "react";

import useLogFileStore from "../stores/logFileStore";
import {handleErrorWithNotification} from "../stores/notificationStore";
import useQueryStore from "../stores/queryStore";
import useUiStore from "../stores/uiStore";
import useViewStore from "../stores/viewStore";
import {TAB_NAME} from "../typings/tab";
import {HASH_PARAM_NAMES} from "../typings/url";
import {
HASH_PARAM_NAMES,
UrlHashParams,
} from "../typings/url";
import {
CURSOR_CODE,
CursorType,
Expand Down Expand Up @@ -39,6 +43,32 @@ const handleHashChange = () => {
}
};

/**
* Returns the initial load file cursor based on the URL hash parameters.
*
* @param hashParams
* @return
*/
const getInitialCursor = (hashParams: UrlHashParams) => {
let cursor: CursorType = {code: CURSOR_CODE.LAST_EVENT, args: null};

if (URL_HASH_PARAMS_DEFAULT.timestamp !== hashParams.timestamp) {
cursor = {
code: CURSOR_CODE.TIMESTAMP,
args: {timestamp: hashParams.timestamp},
};
} else if (URL_HASH_PARAMS_DEFAULT.logEventNum !== hashParams.logEventNum) {
const {setLogEventNum} = useViewStore.getState();
setLogEventNum(hashParams.logEventNum);
cursor = {
code: CURSOR_CODE.EVENT_NUM,
args: {eventNum: hashParams.logEventNum},
};
}

return cursor;
};

interface AppControllerProps {
children: React.ReactNode;
}
Expand Down Expand Up @@ -75,23 +105,18 @@ const AppController = ({children}: AppControllerProps) => {

const searchParams = getWindowUrlSearchParams();
if (URL_SEARCH_PARAMS_DEFAULT.filePath !== searchParams.filePath) {
let cursor: CursorType = {code: CURSOR_CODE.LAST_EVENT, args: null};

if (URL_HASH_PARAMS_DEFAULT.timestamp !== hashParams.timestamp) {
cursor = {
code: CURSOR_CODE.TIMESTAMP,
args: {timestamp: hashParams.timestamp},
};
} else if (URL_HASH_PARAMS_DEFAULT.logEventNum !== hashParams.logEventNum) {
const {setLogEventNum} = useViewStore.getState();
setLogEventNum(hashParams.logEventNum);
cursor = {
code: CURSOR_CODE.EVENT_NUM,
args: {eventNum: hashParams.logEventNum},
};
}
const {loadFile} = useLogFileStore.getState();
loadFile(searchParams.filePath, cursor);
(async () => {
await loadFile(searchParams.filePath);
const {loadPageByCursor} = useViewStore.getState();
await loadPageByCursor(getInitialCursor(hashParams));
if (updateQueryHashParams()) {
const {setActiveTabName} = useUiStore.getState();
setActiveTabName(TAB_NAME.SEARCH);
const {startQuery} = useQueryStore.getState();
startQuery();
}
})().catch(handleErrorWithNotification);
}

return () => {
Expand Down
10 changes: 8 additions & 2 deletions src/components/DropFileContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import React, {
} from "react";

import useLogFileStore from "../../stores/logFileStore";
import {handleErrorWithNotification} from "../../stores/notificationStore";
import useUiStore from "../../stores/uiStore";
import useViewStore from "../../stores/viewStore";
import {UI_ELEMENT} from "../../typings/states";
import {CURSOR_CODE} from "../../typings/worker";
import {isDisabled} from "../../utils/states";
Expand Down Expand Up @@ -66,8 +68,12 @@ const DropFileContainer = ({children}: DropFileContextProviderProps) => {

return;
}
const {loadFile} = useLogFileStore.getState();
loadFile(file, {code: CURSOR_CODE.LAST_EVENT, args: null});
(async () => {
const {loadFile} = useLogFileStore.getState();
await loadFile(file);
const {loadPageByCursor} = useViewStore.getState();
await loadPageByCursor({code: CURSOR_CODE.LAST_EVENT, args: null});
})().catch(handleErrorWithNotification);
}, [disabled]);

return (
Expand Down
10 changes: 8 additions & 2 deletions src/components/MenuBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import {
import FolderOpenIcon from "@mui/icons-material/FolderOpen";

import useLogFileStore from "../../stores/logFileStore";
import {handleErrorWithNotification} from "../../stores/notificationStore";
import useUiStore from "../../stores/uiStore";
import useViewStore from "../../stores/viewStore";
import {UI_ELEMENT} from "../../typings/states";
import {CURSOR_CODE} from "../../typings/worker";
import {openFile} from "../../utils/file";
Expand All @@ -34,8 +36,12 @@ const MenuBar = () => {

const handleOpenFile = useCallback(() => {
openFile((file) => {
const {loadFile} = useLogFileStore.getState();
loadFile(file, {code: CURSOR_CODE.LAST_EVENT, args: null});
(async () => {
const {loadFile} = useLogFileStore.getState();
await loadFile(file);
const {loadPageByCursor} = useViewStore.getState();
await loadPageByCursor({code: CURSOR_CODE.LAST_EVENT, args: null});
})().catch(handleErrorWithNotification);
});
}, []);

Expand Down
6 changes: 1 addition & 5 deletions src/components/StatusBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ import AutoFixOffIcon from "@mui/icons-material/AutoFixOff";
import useLogFileStore from "../../stores/logFileStore";
import useUiStore from "../../stores/uiStore";
import useViewStore from "../../stores/viewStore";
import {
UI_ELEMENT,
UI_STATE,
} from "../../typings/states";
import {UI_ELEMENT} from "../../typings/states";
import {HASH_PARAM_NAMES} from "../../typings/url";
import {ACTION_NAME} from "../../utils/actions";
import {isDisabled} from "../../utils/states";
Expand Down Expand Up @@ -58,7 +55,6 @@ const StatusBar = () => {
updateWindowUrlHashParams({
[HASH_PARAM_NAMES.IS_PRETTIFIED]: false === isPrettified,
});
useUiStore.getState().setUiState(UI_STATE.FAST_LOADING);
updateViewHashParams();
break;
default:
Expand Down
74 changes: 24 additions & 50 deletions src/stores/logFileStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@ import {
import {UI_STATE} from "../typings/states";
import {TAB_NAME} from "../typings/tab";
import {SEARCH_PARAM_NAMES} from "../typings/url";
import {
CursorType,
FileSrcType,
} from "../typings/worker";
import {FileSrcType} from "../typings/worker";
import {getConfig} from "../utils/config";
import {updateWindowUrlSearchParams} from "../utils/url";
import {updateQueryHashParams} from "../utils/url/urlHash";
import useLogExportStore, {LOG_EXPORT_STORE_DEFAULT} from "./logExportStore";
import useLogFileManagerProxyStore from "./logFileManagerProxyStore";
import useNotificationStore, {handleErrorWithNotification} from "./notificationStore";
import useNotificationStore from "./notificationStore";
import useQueryStore from "./queryStore";
import useUiStore from "./uiStore";
import useViewStore from "./viewStore";
Expand All @@ -41,7 +37,7 @@ interface LogFileValues {
}

interface LogFileActions {
loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void;
loadFile: (fileSrc: FileSrcType) => Promise<void>;
}

type LogFileState = LogFileValues & LogFileActions;
Expand Down Expand Up @@ -110,10 +106,9 @@ const handleQueryResults = (progress: number, results: QueryResults) => {
};


// eslint-disable-next-line max-lines-per-function
const useLogFileStore = create<LogFileState>((set) => ({
...LOG_FILE_STORE_DEFAULT,
loadFile: (fileSrc: FileSrcType, cursor: CursorType) => {
loadFile: async (fileSrc: FileSrcType) => {
const {setUiState} = useUiStore.getState();
setUiState(UI_STATE.FILE_LOADING);

Expand All @@ -139,48 +134,27 @@ const useLogFileStore = create<LogFileState>((set) => ({
pageNum: VIEW_PAGE_DEFAULT.pageNum,
});

set({fileSrc});
if ("string" !== typeof fileSrc) {
updateWindowUrlSearchParams({[SEARCH_PARAM_NAMES.FILE_PATH]: null});
const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
const decoderOptions = getConfig(CONFIG_KEY.DECODER_OPTIONS);
const fileInfo = await logFileManagerProxy.loadFile(
{
decoderOptions: decoderOptions,
fileSrc: fileSrc,
pageSize: getConfig(CONFIG_KEY.PAGE_SIZE),
},
Comlink.proxy(handleExportChunk),
Comlink.proxy(handleQueryResults)
);

set(fileInfo);

const {isPrettified} = useViewStore.getState();
await logFileManagerProxy.setIsPrettified(isPrettified);

if (0 === decoderOptions.formatString.length && fileInfo.fileTypeInfo.isStructured) {
const {postPopUp} = useNotificationStore.getState();
postPopUp(FORMAT_POP_UP_MESSAGE);
}

(async () => {
const {logFileManagerProxy} = useLogFileManagerProxyStore.getState();
const decoderOptions = getConfig(CONFIG_KEY.DECODER_OPTIONS);
const fileInfo = await logFileManagerProxy.loadFile(
{
decoderOptions: decoderOptions,
fileSrc: fileSrc,
pageSize: getConfig(CONFIG_KEY.PAGE_SIZE),
},
Comlink.proxy(handleExportChunk),
Comlink.proxy(handleQueryResults)
);

set(fileInfo);

const {isPrettified} = useViewStore.getState();
await logFileManagerProxy.setIsPrettified(isPrettified);

const pageData = await logFileManagerProxy.loadPage(cursor);
updatePageData(pageData);
setUiState(UI_STATE.READY);

if (updateQueryHashParams()) {
const {setActiveTabName} = useUiStore.getState();
setActiveTabName(TAB_NAME.SEARCH);
const {startQuery} = useQueryStore.getState();
startQuery();
}

if (0 === decoderOptions.formatString.length && fileInfo.fileTypeInfo.isStructured) {
const {postPopUp} = useNotificationStore.getState();
postPopUp(FORMAT_POP_UP_MESSAGE);
}
})().catch((e: unknown) => {
handleErrorWithNotification(e);
setUiState(UI_STATE.UNOPENED);
});
},
}));

Expand Down
48 changes: 28 additions & 20 deletions src/stores/viewStore/createViewPageSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,6 @@ const createViewPageSlice: StateCreator<
ViewState, [], [], ViewPageSlice
> = (set, get) => ({
...VIEW_PAGE_DEFAULT,
updatePageData: (pageData: PageData) => {
set({
beginLineNumToLogEventNum: pageData.beginLineNumToLogEventNum,
logData: pageData.logs,
logEventNum: pageData.logEventNum,
numPages: pageData.numPages,
pageNum: pageData.pageNum,
});
updateWindowUrlHashParams({logEventNum: pageData.logEventNum});
},
loadPageByAction: (navAction: NavigationAction) => {
if (navAction.code === ACTION_NAME.RELOAD) {
const {fileSrc, loadFile} = useLogFileStore.getState();
Expand All @@ -113,37 +103,55 @@ const createViewPageSlice: StateCreator<
)}, logEventNum=${logEventNum} when reloading.`
);
}
loadFile(fileSrc, {
code: CURSOR_CODE.EVENT_NUM,
args: {eventNum: logEventNum},
});
(async () => {
await loadFile(fileSrc);
const {loadPageByCursor} = get();
await loadPageByCursor({
code: CURSOR_CODE.EVENT_NUM,
args: {eventNum: logEventNum},
});
})().catch(handleErrorWithNotification);

return;
}

const {uiState, setUiState} = useUiStore.getState();
const {uiState} = useUiStore.getState();
if (UI_STATE.READY !== uiState) {
console.warn("Skipping navigation: page load in progress.");

return;
}
setUiState(UI_STATE.FAST_LOADING);

const {numPages, pageNum} = get();
const {numPages, pageNum, loadPageByCursor} = get();
const cursor = getPageNumCursor(navAction, pageNum, numPages);
if (null === cursor) {
console.error(`Error with nav action ${navAction.code}.`);

return;
}
loadPageByCursor(cursor).catch(handleErrorWithNotification);
},
loadPageByCursor: async (cursor: CursorType) => {
const {setUiState} = useUiStore.getState();
setUiState(UI_STATE.FAST_LOADING);

(async () => {
try {
const {logFileManagerProxy} = useLogFileManagerStore.getState();
const pageData = await logFileManagerProxy.loadPage(cursor);
const {updatePageData} = get();
updatePageData(pageData);
} finally {
setUiState(UI_STATE.READY);
})().catch(handleErrorWithNotification);
}
Comment on lines +137 to +144
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably should remove this try - finally

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is actually coderabbitai's suggestion:
if the current loadPage fails, the uiState will remain in FAST_LOADING state, which not what we want, right?

Copy link
Contributor

@hoophalab hoophalab Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense. Even though I feel there might be better solutions than try-finally, let's merge this for now.

},
updatePageData: (pageData: PageData) => {
set({
beginLineNumToLogEventNum: pageData.beginLineNumToLogEventNum,
logData: pageData.logs,
logEventNum: pageData.logEventNum,
numPages: pageData.numPages,
pageNum: pageData.pageNum,
});
updateWindowUrlHashParams({logEventNum: pageData.logEventNum});
},
});

Expand Down
2 changes: 2 additions & 0 deletions src/stores/viewStore/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {LogLevelFilter} from "../../typings/logs";
import {
BeginLineNumToLogEventNumMap,
CursorType,
PageData,
} from "../../typings/worker";
import {NavigationAction} from "../../utils/actions";
Expand All @@ -14,6 +15,7 @@ interface ViewPageValues {
}

interface ViewPageActions {
loadPageByCursor: (cursor: CursorType) => Promise<void>;
loadPageByAction: (navAction: NavigationAction) => void;
updatePageData: (pageData: PageData) => void;
}
Expand Down
Loading
Loading