mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 03:20:46 +02:00
# Description of Changes When I added Prettier formatting in #6052, my aim was to use just the default settings in Prettier. Turns out, Prettier looks _really hard_ for any config files if it's not explicitly given one, which means that if a developer has some sort of Prettier config file lying around on their system, Prettier might find it and use it. Also, Prettier changes its defaults based on stuff in `.editorconfig` without any good way of disabling that behaviour explicitly in its config file. To solve both of these issues, I've introduced a `.prettierrc` file which sets Prettier's defaults explicitly, and then reformatted all our code _again_ in Prettier's actual default settings. This should achieve the aim of #6052 and remove the possibility for it breaking on different dev computers.
211 lines
6.3 KiB
TypeScript
211 lines
6.3 KiB
TypeScript
import type { StepType } from "@reactour/tour";
|
|
import type { TFunction } from "i18next";
|
|
|
|
async function waitForElement(
|
|
selector: string,
|
|
timeoutMs = 7000,
|
|
intervalMs = 100,
|
|
): Promise<void> {
|
|
if (typeof document === "undefined") return;
|
|
const start = Date.now();
|
|
// Immediate hit
|
|
if (document.querySelector(selector)) return;
|
|
|
|
return new Promise((resolve) => {
|
|
const check = () => {
|
|
if (document.querySelector(selector) || Date.now() - start >= timeoutMs) {
|
|
resolve();
|
|
return;
|
|
}
|
|
setTimeout(check, intervalMs);
|
|
};
|
|
check();
|
|
});
|
|
}
|
|
|
|
async function waitForHighlightable(
|
|
selector: string,
|
|
timeoutMs = 7000,
|
|
intervalMs = 500,
|
|
): Promise<void> {
|
|
if (typeof document === "undefined") return;
|
|
const start = Date.now();
|
|
|
|
return new Promise((resolve) => {
|
|
const check = () => {
|
|
const el = document.querySelector<HTMLElement>(selector);
|
|
const isVisible = !!el && el.getClientRects().length > 0;
|
|
if (isVisible || Date.now() - start >= timeoutMs) {
|
|
// Nudge Reactour to recalc positions in case layout shifted
|
|
window.dispatchEvent(new Event("resize"));
|
|
requestAnimationFrame(() => window.dispatchEvent(new Event("resize")));
|
|
resolve();
|
|
return;
|
|
}
|
|
setTimeout(check, intervalMs);
|
|
};
|
|
check();
|
|
});
|
|
}
|
|
|
|
export enum WhatsNewTourStep {
|
|
QUICK_ACCESS,
|
|
LEFT_PANEL,
|
|
FILE_UPLOAD,
|
|
RIGHT_RAIL,
|
|
TOP_BAR,
|
|
PAGE_EDITOR_VIEW,
|
|
ACTIVE_FILES_VIEW,
|
|
WRAP_UP,
|
|
}
|
|
|
|
interface WhatsNewStepActions {
|
|
saveWorkbenchState: () => void;
|
|
closeFilesModal: () => void;
|
|
backToAllTools: () => void;
|
|
openFilesModal: () => void;
|
|
loadSampleFile: () => Promise<void> | void;
|
|
switchToViewer: () => void;
|
|
switchToPageEditor: () => void;
|
|
switchToActiveFiles: () => void;
|
|
selectFirstFile: () => void;
|
|
}
|
|
|
|
interface CreateWhatsNewStepsConfigArgs {
|
|
t: TFunction;
|
|
actions: WhatsNewStepActions;
|
|
}
|
|
|
|
export function createWhatsNewStepsConfig({
|
|
t,
|
|
actions,
|
|
}: CreateWhatsNewStepsConfigArgs): Record<WhatsNewTourStep, StepType> {
|
|
const {
|
|
saveWorkbenchState,
|
|
closeFilesModal,
|
|
backToAllTools,
|
|
openFilesModal,
|
|
loadSampleFile,
|
|
switchToViewer,
|
|
switchToPageEditor,
|
|
switchToActiveFiles,
|
|
selectFirstFile,
|
|
} = actions;
|
|
|
|
return {
|
|
[WhatsNewTourStep.QUICK_ACCESS]: {
|
|
selector: '[data-tour="quick-access-bar"]',
|
|
content: t(
|
|
"onboarding.whatsNew.quickAccess",
|
|
"Start at the <strong>Quick Access</strong> rail to jump between Reader, Automate, your files, and all the tours.",
|
|
),
|
|
position: "right",
|
|
padding: 10,
|
|
action: () => {
|
|
saveWorkbenchState();
|
|
closeFilesModal();
|
|
backToAllTools();
|
|
},
|
|
},
|
|
[WhatsNewTourStep.LEFT_PANEL]: {
|
|
selector: '[data-tour="tool-panel"]',
|
|
content: t(
|
|
"onboarding.whatsNew.leftPanel",
|
|
"The left <strong>Tools</strong> panel lists everything you can do. Browse categories or search to find a tool quickly.",
|
|
),
|
|
position: "center",
|
|
padding: 0,
|
|
},
|
|
[WhatsNewTourStep.FILE_UPLOAD]: {
|
|
selector: '[data-tour="files-button"]',
|
|
content: t(
|
|
"onboarding.whatsNew.fileUpload",
|
|
"Use the <strong>Files</strong> button to upload or pick a recent PDF. We will load a sample so you can see the workspace.",
|
|
),
|
|
position: "right",
|
|
padding: 10,
|
|
action: async () => {
|
|
openFilesModal();
|
|
await waitForElement('[data-tour="file-sources"]', 5000, 100);
|
|
},
|
|
actionAfter: async () => {
|
|
await Promise.resolve(loadSampleFile());
|
|
closeFilesModal();
|
|
switchToViewer();
|
|
// wait for file render and top controls to mount
|
|
await waitForElement('[data-tour="view-switcher"]', 7000, 100);
|
|
await waitForHighlightable('[data-tour="view-switcher"]', 7000, 500);
|
|
},
|
|
},
|
|
[WhatsNewTourStep.RIGHT_RAIL]: {
|
|
selector: '[data-tour="right-rail-controls"]',
|
|
highlightedSelectors: [
|
|
'[data-tour="right-rail-controls"]',
|
|
'[data-tour="right-rail-settings"]',
|
|
],
|
|
content: t(
|
|
"onboarding.whatsNew.rightRail",
|
|
"The <strong>Right Rail</strong> holds quick actions to select files, change theme or language, and download results.",
|
|
),
|
|
position: "left",
|
|
padding: 10,
|
|
action: async () => {
|
|
await waitForElement('[data-tour="right-rail-controls"]', 7000, 100);
|
|
selectFirstFile();
|
|
},
|
|
},
|
|
[WhatsNewTourStep.TOP_BAR]: {
|
|
selector: '[data-tour="view-switcher"]',
|
|
content: t(
|
|
"onboarding.whatsNew.topBar",
|
|
"The top bar lets you swap between <strong>Viewer</strong>, <strong>Page Editor</strong>, and <strong>Active Files</strong>.",
|
|
),
|
|
position: "bottom",
|
|
padding: 8,
|
|
// Ensure the switcher has mounted before this step renders
|
|
action: async () => {
|
|
switchToViewer();
|
|
await waitForElement('[data-tour="view-switcher"]', 7000, 100);
|
|
await waitForHighlightable('[data-tour="view-switcher"]', 7000, 500);
|
|
},
|
|
},
|
|
[WhatsNewTourStep.PAGE_EDITOR_VIEW]: {
|
|
selector: '[data-tour="view-switcher"]',
|
|
content: t(
|
|
"onboarding.whatsNew.pageEditorView",
|
|
"Switch to the Page Editor to reorder, rotate, or delete pages.",
|
|
),
|
|
position: "bottom",
|
|
padding: 8,
|
|
action: async () => {
|
|
switchToPageEditor();
|
|
await waitForElement('[data-tour="view-switcher"]', 7000, 100);
|
|
await waitForHighlightable('[data-tour="view-switcher"]', 7000, 500);
|
|
},
|
|
},
|
|
[WhatsNewTourStep.ACTIVE_FILES_VIEW]: {
|
|
selector: '[data-tour="view-switcher"]',
|
|
content: t(
|
|
"onboarding.whatsNew.activeFilesView",
|
|
"Use Active Files to see everything you have open and pick what to work on.",
|
|
),
|
|
position: "bottom",
|
|
padding: 8,
|
|
action: async () => {
|
|
switchToActiveFiles();
|
|
await waitForElement('[data-tour="view-switcher"]', 7000, 100);
|
|
await waitForHighlightable('[data-tour="view-switcher"]', 7000, 500);
|
|
},
|
|
},
|
|
[WhatsNewTourStep.WRAP_UP]: {
|
|
selector: '[data-tour="help-button"]',
|
|
content: t(
|
|
"onboarding.whatsNew.wrapUp",
|
|
"That is what is new in V2. Open the <strong>Tours</strong> menu anytime to replay this, the Tools tour, or the Admin tour.",
|
|
),
|
|
position: "right",
|
|
padding: 10,
|
|
},
|
|
};
|
|
}
|