mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-29 10:09:26 +02:00
global: add demo data seed
This commit is contained in:
1815
apps/mobile/app/common/seed-demo.ts
Normal file
1815
apps/mobile/app/common/seed-demo.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -448,7 +448,7 @@ export const ReferencesList = ({ item, close }: ReferencesListProps) => {
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={{ height: "100%" }}>
|
||||
<View style={{ height: "50%" }}>
|
||||
<SheetProvider context="local" />
|
||||
|
||||
<View
|
||||
|
||||
@@ -1848,6 +1848,126 @@ export const settingsGroups: SettingSection[] = [
|
||||
}
|
||||
},
|
||||
description: getVersion()
|
||||
},
|
||||
// TEMPORARY — demo data seeder for the App Store / Play Store screenshots.
|
||||
// Delete this section and app/common/seed-demo.ts once they are captured.
|
||||
{
|
||||
id: "seed-demo-account",
|
||||
name: "Seed demo account",
|
||||
icon: "database-plus",
|
||||
description:
|
||||
"Fills this account with the persona, notebooks, 44 notes, tags, colours, reminders and vault note used for the store screenshots. Run once, on an empty account.",
|
||||
hidden: () => !__DEV__,
|
||||
modifer: async () => {
|
||||
presentDialog({
|
||||
title: "Seed demo account",
|
||||
paragraph:
|
||||
"This adds 44 notes and creates a vault. Only run it on a fresh, empty account — it does not clean up after itself.",
|
||||
positiveText: "Seed",
|
||||
negativeText: strings.cancel(),
|
||||
positivePress: async () => {
|
||||
setTimeout(async () => {
|
||||
startProgress({
|
||||
title: "Seeding demo account",
|
||||
paragraph: "Please wait, this takes about a minute."
|
||||
});
|
||||
try {
|
||||
const { seedDemoAccount } = await import(
|
||||
"../../common/seed-demo"
|
||||
);
|
||||
const result = await seedDemoAccount((message) => {
|
||||
DatabaseLogger.info(`[seed] ${message}`);
|
||||
startProgress({
|
||||
title: "Seeding demo account",
|
||||
paragraph: message
|
||||
});
|
||||
});
|
||||
await refreshAllStores();
|
||||
endProgress();
|
||||
ToastManager.show({
|
||||
heading: `Created ${result.notes} notes`,
|
||||
message: "Vault password: demo-vault-2026",
|
||||
type: "success",
|
||||
context: "global"
|
||||
});
|
||||
} catch (e) {
|
||||
endProgress();
|
||||
DatabaseLogger.error(e);
|
||||
ToastManager.error(
|
||||
e as Error,
|
||||
"Failed to seed demo account",
|
||||
"global"
|
||||
);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clear-demo-data",
|
||||
type: "danger",
|
||||
name: "Delete all items",
|
||||
icon: "database-remove",
|
||||
description:
|
||||
"Permanently deletes every note, notebook, tag, colour, reminder and the vault, then empties the trash. The account itself is kept. Cannot be undone.",
|
||||
hidden: () => !__DEV__,
|
||||
modifer: async () => {
|
||||
presentDialog({
|
||||
title: "Delete all items",
|
||||
paragraph:
|
||||
"This permanently deletes everything in this account — not just the demo data — and empties the trash. It cannot be undone. Type DELETE to confirm.",
|
||||
input: true,
|
||||
inputPlaceholder: "DELETE",
|
||||
positiveText: strings.delete(),
|
||||
negativeText: strings.cancel(),
|
||||
positiveType: "errorShade",
|
||||
positivePress: async (value) => {
|
||||
if (value?.trim() !== "DELETE") {
|
||||
ToastManager.error(
|
||||
new Error("Type DELETE to confirm"),
|
||||
undefined,
|
||||
"local"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
setTimeout(async () => {
|
||||
startProgress({
|
||||
title: "Deleting all items",
|
||||
paragraph: "Please wait."
|
||||
});
|
||||
try {
|
||||
const { clearAllData } = await import(
|
||||
"../../common/seed-demo"
|
||||
);
|
||||
const counts = await clearAllData((message) => {
|
||||
DatabaseLogger.info(`[seed] ${message}`);
|
||||
startProgress({
|
||||
title: "Deleting all items",
|
||||
paragraph: message
|
||||
});
|
||||
});
|
||||
await refreshAllStores();
|
||||
endProgress();
|
||||
ToastManager.show({
|
||||
heading: `Deleted ${counts.notes} notes`,
|
||||
message: `${counts.notebooks} notebooks, ${counts.tags} tags, ${counts.reminders} reminders`,
|
||||
type: "success",
|
||||
context: "global"
|
||||
});
|
||||
} catch (e) {
|
||||
endProgress();
|
||||
DatabaseLogger.error(e);
|
||||
ToastManager.error(
|
||||
e as Error,
|
||||
"Failed to delete all items",
|
||||
"global"
|
||||
);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
10
apps/mobile/package-lock.json
generated
10
apps/mobile/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.4.5",
|
||||
"version": "3.4.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "3.4.5",
|
||||
"version": "3.4.7",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
@@ -191,6 +191,7 @@
|
||||
"version": "2.1.3",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@notesnook/common": "^2.1.3",
|
||||
"@notesnook/core": "file:../core",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"dayjs": "1.11.13",
|
||||
@@ -333,7 +334,10 @@
|
||||
"papaparse": "^5.5.3",
|
||||
"prism-themes": "^1.9.0",
|
||||
"prosemirror-codemark": "^0.4.2",
|
||||
"prosemirror-view": "1.34.2",
|
||||
"prosemirror-model": "1.25.11",
|
||||
"prosemirror-state": "1.4.4",
|
||||
"prosemirror-transform": "1.12.0",
|
||||
"prosemirror-view": "1.42.2",
|
||||
"re-resizable": "^6.9.18",
|
||||
"react-colorful": "^5.6.1",
|
||||
"redent": "^4.0.0",
|
||||
|
||||
1814
apps/web/src/common/seed-demo.ts
Normal file
1814
apps/web/src/common/seed-demo.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,13 @@ import { strings } from "@notesnook/intl";
|
||||
import { desktop } from "../../common/desktop-bridge";
|
||||
import { TaskManager } from "../../common/task-manager";
|
||||
import { useStore as useSettingStore } from "../../stores/setting-store";
|
||||
// TEMPORARY — used only by the demo data group at the bottom of this file.
|
||||
import { ConfirmDialog } from "../confirm";
|
||||
import { useStore as useAppStore } from "../../stores/app-store";
|
||||
import { useStore as useNoteStore } from "../../stores/note-store";
|
||||
import { useStore as useNotebookStore } from "../../stores/notebook-store";
|
||||
import { useStore as useTagStore } from "../../stores/tag-store";
|
||||
import { useStore as useReminderStore } from "../../stores/reminder-store";
|
||||
|
||||
export const AboutSettings: SettingsGroup[] = [
|
||||
{
|
||||
@@ -419,9 +426,118 @@ export const SupportSettings: SettingsGroup[] = [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
// TEMPORARY — demo data seeder for producing App Store / Play Store
|
||||
// screenshots. Delete this group and src/common/seed-demo.ts once the store
|
||||
// assets are captured.
|
||||
{
|
||||
key: "demo-data",
|
||||
section: "about",
|
||||
header: "Demo data",
|
||||
isHidden: () => !import.meta.env.DEV,
|
||||
settings: [
|
||||
{
|
||||
key: "seed-demo-account",
|
||||
title: "Seed demo account",
|
||||
description:
|
||||
"Fills this account with the persona, notebooks, notes, tags, colours, reminders and vault notes the marketing site shows. Run once, on an empty account. Open the notes with pictures afterwards so the images download and become attachments.",
|
||||
components: [
|
||||
{
|
||||
type: "button",
|
||||
action: async () => {
|
||||
const { seedDemoAccount } = await import("../../common/seed-demo");
|
||||
await TaskManager.startTask({
|
||||
type: "modal",
|
||||
title: "Seeding demo account",
|
||||
subtitle: "This takes about a minute. Do not close the app.",
|
||||
action: async (report) => {
|
||||
await seedDemoAccount((message) => {
|
||||
console.log("[seed]", message);
|
||||
report({ text: message });
|
||||
});
|
||||
}
|
||||
});
|
||||
await refreshAfterBulkChange();
|
||||
showToast("success", "Demo data created. Sync, then capture.");
|
||||
},
|
||||
title: "Seed",
|
||||
variant: "secondary"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "clear-demo-data",
|
||||
title: "Delete all items",
|
||||
description:
|
||||
"Permanently deletes every note, notebook, tag, colour, reminder and the vault, then empties the trash. The account itself is kept. Cannot be undone.",
|
||||
components: [
|
||||
{
|
||||
type: "button",
|
||||
action: async () => {
|
||||
// Typed confirmation, not a yes/no: this deletes everything in
|
||||
// the account, including anything that was not seeded.
|
||||
const result = await ConfirmDialog.show({
|
||||
title: "Delete all items",
|
||||
message:
|
||||
"This permanently deletes everything in this account — not just the demo data — and empties the trash. It cannot be undone.",
|
||||
inputs: {
|
||||
confirmation: {
|
||||
title: 'Type DELETE to confirm',
|
||||
required: true
|
||||
}
|
||||
},
|
||||
positiveButtonText: strings.delete(),
|
||||
negativeButtonText: strings.cancel()
|
||||
});
|
||||
if (!result) return;
|
||||
if (result.inputs?.confirmation?.trim() !== "DELETE") {
|
||||
showToast("error", "Type DELETE to confirm.");
|
||||
return;
|
||||
}
|
||||
|
||||
const { clearAllData } = await import("../../common/seed-demo");
|
||||
let counts: Awaited<ReturnType<typeof clearAllData>> | undefined;
|
||||
await TaskManager.startTask({
|
||||
type: "modal",
|
||||
title: "Deleting all items",
|
||||
subtitle: "Please wait.",
|
||||
action: async (report) => {
|
||||
counts = await clearAllData((message) => {
|
||||
console.log("[seed]", message);
|
||||
report({ text: message });
|
||||
});
|
||||
}
|
||||
});
|
||||
await refreshAfterBulkChange();
|
||||
showToast(
|
||||
"success",
|
||||
counts
|
||||
? `Deleted ${counts.notes} notes, ${counts.notebooks} notebooks, ${counts.tags} tags, ${counts.reminders} reminders.`
|
||||
: "Account cleared."
|
||||
);
|
||||
},
|
||||
title: "Delete",
|
||||
variant: "error"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* Both demo actions rewrite the whole database underneath the UI. The stores
|
||||
* read from a cache that does not know that happened, so without this the app
|
||||
* keeps rendering the previous account until a reload.
|
||||
*/
|
||||
async function refreshAfterBulkChange() {
|
||||
await useAppStore.getState().refreshNavItems();
|
||||
await useNoteStore.getState().refresh();
|
||||
await useNotebookStore.getState().refresh();
|
||||
await useTagStore.getState().refresh();
|
||||
await useReminderStore.getState().refresh();
|
||||
}
|
||||
|
||||
async function switchReleaseTrack(track: string) {
|
||||
const registration = await navigator.serviceWorker.getRegistration();
|
||||
if (!registration) return;
|
||||
|
||||
@@ -44,7 +44,7 @@ if (theme) {
|
||||
if (stylesheet) stylesheet.innerHTML = css;
|
||||
} else stylesheet?.remove();
|
||||
|
||||
const locale = import.meta.env.DEV
|
||||
const locale = !import.meta.env.DEV
|
||||
? import("@notesnook/intl/locales/$pseudo-LOCALE.json")
|
||||
: import("@notesnook/intl/locales/$en.json");
|
||||
locale.then(({ default: locale }) => {
|
||||
|
||||
6
packages/editor-mobile/package-lock.json
generated
6
packages/editor-mobile/package-lock.json
generated
@@ -40,6 +40,7 @@
|
||||
"version": "2.1.3",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@notesnook/common": "^2.1.3",
|
||||
"@notesnook/core": "file:../core",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"dayjs": "1.11.13",
|
||||
@@ -106,7 +107,10 @@
|
||||
"papaparse": "^5.5.3",
|
||||
"prism-themes": "^1.9.0",
|
||||
"prosemirror-codemark": "^0.4.2",
|
||||
"prosemirror-view": "1.34.2",
|
||||
"prosemirror-model": "1.25.11",
|
||||
"prosemirror-state": "1.4.4",
|
||||
"prosemirror-transform": "1.12.0",
|
||||
"prosemirror-view": "1.42.2",
|
||||
"re-resizable": "^6.9.18",
|
||||
"react-colorful": "^5.6.1",
|
||||
"redent": "^4.0.0",
|
||||
|
||||
Reference in New Issue
Block a user