web: fix all type errors

This commit is contained in:
Abdullah Atta
2024-02-05 11:23:28 +05:00
parent 0a973cd83a
commit 448d19e9fd
10 changed files with 60 additions and 70 deletions

View File

@@ -31,9 +31,15 @@ import { pluralize } from "@notesnook/common";
async function moveNotesToTrash(ids: string[], confirm = true) { async function moveNotesToTrash(ids: string[], confirm = true) {
if (confirm && !(await showMultiDeleteConfirmation(ids.length))) return; if (confirm && !(await showMultiDeleteConfirmation(ids.length))) return;
const lockedIds = await db.notes.locked.ids(); const vault = await db.vaults.default();
if (ids.some((id) => lockedIds.includes(id)) && !(await Vault.unlockVault())) if (vault) {
return; const lockedIds = await db.relations.from(vault, "note").get();
if (
ids.some((id) => lockedIds.findIndex((s) => s.toId === id) > -1) &&
!(await Vault.unlockVault())
)
return;
}
const items = ids.filter((id) => !db.monographs.isPublished(id)); const items = ids.filter((id) => !db.monographs.isPublished(id));

View File

@@ -288,7 +288,7 @@ const AttachmentMenuItems: (
onClick: async () => { onClick: async () => {
const isDownloading = status?.type === "download"; const isDownloading = status?.type === "download";
if (isDownloading) { if (isDownloading) {
await db.fs().cancel(attachment.hash, "download"); await db.fs().cancel(attachment.hash);
} else await saveAttachment(attachment.hash); } else await saveAttachment(attachment.hash);
} }
}, },
@@ -300,7 +300,7 @@ const AttachmentMenuItems: (
onClick: async () => { onClick: async () => {
const isDownloading = status?.type === "upload"; const isDownloading = status?.type === "upload";
if (isDownloading) { if (isDownloading) {
await db.fs().cancel(attachment.hash, "upload"); await db.fs().cancel(attachment.hash);
} else await reuploadAttachment(attachment.type, attachment.hash); } else await reuploadAttachment(attachment.type, attachment.hash);
} }
}, },

View File

@@ -61,7 +61,6 @@ import {
MaybeDeletedItem, MaybeDeletedItem,
isDeleted isDeleted
} from "@notesnook/core/dist/types"; } from "@notesnook/core/dist/types";
import { isEncryptedContent } from "@notesnook/core/dist/collections/content";
import { PreviewSession } from "./types"; import { PreviewSession } from "./types";
const PDFPreview = React.lazy(() => import("../pdf-preview")); const PDFPreview = React.lazy(() => import("../pdf-preview"));
@@ -89,7 +88,7 @@ export default function EditorManager({
noteId, noteId,
nonce nonce
}: { }: {
noteId?: string; noteId?: string | number;
nonce?: string; nonce?: string;
}) { }) {
const isNewSession = !!nonce && !noteId; const isNewSession = !!nonce && !noteId;
@@ -136,7 +135,7 @@ export default function EditorManager({
if (id && isContent && editorInstance.current) { if (id && isContent && editorInstance.current) {
let content: string | null = null; let content: string | null = null;
if (locked && isEncryptedContent(item)) { if (locked && item.locked) {
const result = await db.vault const result = await db.vault
.decryptContent(item, item.noteId) .decryptContent(item, item.noteId)
.catch(() => undefined); .catch(() => undefined);
@@ -181,7 +180,7 @@ export default function EditorManager({
}, [isNewSession, nonce]); }, [isNewSession, nonce]);
useEffect(() => { useEffect(() => {
if (!isOldSession) return; if (!isOldSession || typeof noteId === "number") return;
openSession(noteId); openSession(noteId);
}, [noteId]); }, [noteId]);
@@ -210,7 +209,9 @@ export default function EditorManager({
{previewSession.current && noteId && ( {previewSession.current && noteId && (
<PreviewModeNotice <PreviewModeNotice
{...previewSession.current} {...previewSession.current}
onDiscard={() => openSession(noteId)} onDiscard={() =>
typeof noteId === "string" && openSession(noteId)
}
/> />
)} )}
<Editor <Editor
@@ -330,7 +331,7 @@ type EditorOptions = {
onRequestFocus?: () => void; onRequestFocus?: () => void;
}; };
type EditorProps = { type EditorProps = {
id: string | number; id?: string | number;
content: () => string | undefined; content: () => string | undefined;
nonce?: number; nonce?: number;
options?: EditorOptions; options?: EditorOptions;
@@ -393,7 +394,7 @@ export function Editor(props: EditorProps) {
const dataurl = await downloadAttachment( const dataurl = await downloadAttachment(
hash, hash,
"base64", "base64",
id.toString() id?.toString()
); );
if (!dataurl) if (!dataurl)
return showToast("error", "This image cannot be previewed."); return showToast("error", "This image cannot be previewed.");
@@ -411,7 +412,7 @@ export function Editor(props: EditorProps) {
); );
} else if (attachment && onPreviewDocument) { } else if (attachment && onPreviewDocument) {
onPreviewDocument({ hash }); onPreviewDocument({ hash });
const blob = await downloadAttachment(hash, "blob", id.toString()); const blob = await downloadAttachment(hash, "blob", id?.toString());
if (!blob) return; if (!blob) return;
onPreviewDocument({ url: URL.createObjectURL(blob), hash }); onPreviewDocument({ url: URL.createObjectURL(blob), hash });
} }
@@ -427,7 +428,7 @@ export function Editor(props: EditorProps) {
return downloadAttachment( return downloadAttachment(
attachment.hash, attachment.hash,
attachment.type === "web-clip" ? "text" : "base64", attachment.type === "web-clip" ? "text" : "base64",
id.toString() id?.toString()
); );
}} }}
onAttachFile={async (file) => { onAttachFile={async (file) => {

View File

@@ -190,8 +190,8 @@ async function addAttachment(
metadata: { metadata: {
hash, hash,
hashType, hashType,
filename: exists?.metadata.filename || file.name, filename: exists?.filename || file.name,
type: exists?.metadata.type || file.type type: exists?.type || file.type
}, },
key key
}); });

View File

@@ -25,21 +25,20 @@ import { VirtualizedList, VirtualizedListProps } from "../virtualized-list";
type FilteredListProps<T> = { type FilteredListProps<T> = {
placeholders: { filter: string; empty: string }; placeholders: { filter: string; empty: string };
filter: (query: string) => Promise<T[]>; filter: (query: string) => Promise<void>;
onCreateNewItem: (title: string) => Promise<void>; onCreateNewItem: (title: string) => Promise<void>;
} & VirtualizedListProps<T, unknown>; } & VirtualizedListProps<T, unknown>;
export function FilteredList<T>(props: FilteredListProps<T>) { export function FilteredList<T>(props: FilteredListProps<T>) {
const { items, filter, onCreateNewItem, placeholders, ...listProps } = props; const { items, filter, onCreateNewItem, placeholders, ...listProps } = props;
const [filteredItems, setFilteredItems] = useState<T[]>([]);
const [query, setQuery] = useState<string>(); const [query, setQuery] = useState<string>();
const noItemsFound = filteredItems.length <= 0 && query && query.length > 0; const noItemsFound = items.length <= 0 && query && query.length > 0;
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
const _filter = useCallback( const _filter = useCallback(
async (query = "") => { async (query = "") => {
setFilteredItems(query ? await filter(query) : []); await filter(query);
setQuery(query); setQuery(query);
}, },
[filter] [filter]
@@ -61,7 +60,7 @@ export function FilteredList<T>(props: FilteredListProps<T>) {
data-test-id={"filter-input"} data-test-id={"filter-input"}
autoFocus autoFocus
placeholder={ placeholder={
filteredItems.length <= 0 ? placeholders.empty : placeholders.filter items.length <= 0 ? placeholders.empty : placeholders.filter
} }
onChange={(e) => _filter((e.target as HTMLInputElement).value)} onChange={(e) => _filter((e.target as HTMLInputElement).value)}
onKeyUp={async (e) => { onKeyUp={async (e) => {
@@ -70,7 +69,7 @@ export function FilteredList<T>(props: FilteredListProps<T>) {
} }
}} }}
action={ action={
filteredItems.length <= 0 && !!query items.length <= 0 && !!query
? { ? {
icon: Plus, icon: Plus,
onClick: async () => await _createNewItem(query) onClick: async () => await _createNewItem(query)
@@ -95,7 +94,7 @@ export function FilteredList<T>(props: FilteredListProps<T>) {
<Plus size={16} color="accent" /> <Plus size={16} color="accent" />
</Button> </Button>
) : ( ) : (
<VirtualizedList {...listProps} items={query ? filteredItems : items} /> <VirtualizedList {...listProps} items={items} />
)} )}
</> </>
); );

View File

@@ -69,7 +69,6 @@ export function SessionItem(props: SessionItemProps) {
try { try {
const decryptedContent = await db.vault.decryptContent( const decryptedContent = await db.vault.decryptContent(
content, content,
noteId,
password password
); );
onOpenPreviewSession({ onOpenPreviewSession({

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { useEffect } from "react"; import { useEffect, useState } from "react";
import { Flex, Text } from "@theme-ui/components"; import { Flex, Text } from "@theme-ui/components";
import { import {
CheckCircleOutline, CheckCircleOutline,
@@ -34,6 +34,7 @@ import { FilteredList } from "../components/filtered-list";
import { ItemReference, Tag } from "@notesnook/core/dist/types"; import { ItemReference, Tag } from "@notesnook/core/dist/types";
import { ResolvedItem } from "../components/list-container/resolved-item"; import { ResolvedItem } from "../components/list-container/resolved-item";
import { create } from "zustand"; import { create } from "zustand";
import { VirtualizedGrouping } from "@notesnook/core";
type SelectedReference = { type SelectedReference = {
id: string; id: string;
@@ -58,14 +59,18 @@ export type AddTagsDialogProps = {
function AddTagsDialog(props: AddTagsDialogProps) { function AddTagsDialog(props: AddTagsDialogProps) {
const { onClose, noteIds } = props; const { onClose, noteIds } = props;
const tags = useStore((store) => store.tags); const [tags, setTags] = useState<VirtualizedGrouping<Tag> | undefined>(
() => useStore.getState().tags
);
useEffect(() => { useEffect(() => {
(async function () { (async function () {
if (!tags) { if (!tags) {
await useStore.getState().refresh(); await useStore.getState().refresh();
setTags(useStore.getState().tags);
return; return;
} }
const selected: SelectedReference[] = []; const selected: SelectedReference[] = [];
const selectedTags = await db.relations const selectedTags = await db.relations
.to({ type: "note", ids: noteIds }, "tag") .to({ type: "note", ids: noteIds }, "tag")
@@ -76,7 +81,7 @@ function AddTagsDialog(props: AddTagsDialogProps) {
}); });
useSelectionStore.getState().setSelected(selected); useSelectionStore.getState().setSelected(selected);
})(); })();
}, [tags, noteIds]); }, []);
return ( return (
<Dialog <Dialog
@@ -119,7 +124,13 @@ function AddTagsDialog(props: AddTagsDialogProps) {
empty: "Add a new tag", empty: "Add a new tag",
filter: "Search or add a new tag" filter: "Search or add a new tag"
}} }}
filter={(query) => db.lookup.tags(query).ids()} filter={async (query) => {
setTags(
query
? await db.lookup.tags(query).sorted()
: useStore.getState().tags
);
}}
onCreateNewItem={async (title) => { onCreateNewItem={async (title) => {
const tagId = await db.tags.add({ title }); const tagId = await db.tags.add({ title });
if (!tagId) return; if (!tagId) return;
@@ -202,7 +213,3 @@ function SelectedCheck({ id, size = 20 }: { id: string; size?: number }) {
<CircleEmpty size={size} sx={{ mr: 1, opacity: 0.4 }} /> <CircleEmpty size={size} sx={{ mr: 1, opacity: 0.4 }} />
); );
} }
function tagHasNotes(tagId: string, noteIds: string[]) {
return db.relations.from({ type: "tag", id: tagId }, "note").has(...noteIds);
}

View File

@@ -135,7 +135,7 @@ class EditorStore extends BaseStore<EditorStore> {
openSession = async (noteId: string, force = false) => { openSession = async (noteId: string, force = false) => {
const session = this.get().session; const session = this.get().session;
if (session.id) await db.fs().cancel(session.id, "download"); if (session.id) await db.fs().cancel(session.id);
if (session.id === noteId && !force) return; if (session.id === noteId && !force) return;
if (session.state === SESSION_STATES.unlocked) { if (session.state === SESSION_STATES.unlocked) {
@@ -285,7 +285,7 @@ class EditorStore extends BaseStore<EditorStore> {
newSession = async (nonce?: string) => { newSession = async (nonce?: string) => {
const context = noteStore.get().context; const context = noteStore.get().context;
const session = this.get().session; const session = this.get().session;
if (session.id) await db.fs().cancel(session.id, "download"); if (session.id) await db.fs().cancel(session.id);
this.set((state) => { this.set((state) => {
state.session = { state.session = {
@@ -302,7 +302,7 @@ class EditorStore extends BaseStore<EditorStore> {
clearSession = async (shouldNavigate = true) => { clearSession = async (shouldNavigate = true) => {
const session = this.get().session; const session = this.get().session;
if (session.id) await db.fs().cancel(session.id, "download"); if (session.id) await db.fs().cancel(session.id);
this.set((state) => { this.set((state) => {
state.session = { state.session = {

View File

@@ -36,7 +36,7 @@ export class AttachmentStream extends ReadableStream<ZipFile> {
const counters: Record<string, number> = {}; const counters: Record<string, number> = {};
if (signal) if (signal)
signal.onabort = async () => { signal.onabort = async () => {
await db.fs().cancel(GROUP_ID, "download"); await db.fs().cancel(GROUP_ID);
}; };
super({ super({

View File

@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { db } from "../../common/db";
import { exportNote } from "../../common/export"; import { exportNote } from "../../common/export";
import { makeUniqueFilename } from "./utils"; import { makeUniqueFilename } from "./utils";
import { ZipFile } from "./zip-stream"; import { ZipFile } from "./zip-stream";
@@ -44,41 +45,18 @@ export class ExportStream extends TransformStream<Note, ZipFile> {
const { filename, content } = result; const { filename, content } = result;
const notebooks = [ const notebooks = await db.relations
...( .to({ id: note.id, type: "note" }, "notebook")
db.relations .get();
?.to({ id: note.id, type: "note" }, "notebook")
.resolved() || []
).map((n) => ({ title: n.title, topics: [] })),
...(note.notebooks || []).map(
(ref: { id: string; topics: string[] }) => {
const notebook = db.notebooks?.notebook(ref.id);
const topics: any[] = notebook?.topics.all || [];
return { const filePaths: string[] = [];
title: notebook?.title, for (const { fromId: notebookId } of notebooks) {
topics: ref.topics const crumbs = (await db.notebooks.breadcrumbs(notebookId)).map(
.map((topicId: string) => (n) => n.title
topics.find((topic) => topic.id === topicId) );
) filePaths.push([...crumbs, filename].join("/"));
.filter(Boolean) }
}; if (filePaths.length <= 0) filePaths.push(filename);
}
)
];
const filePaths: Array<string> =
notebooks.length > 0
? notebooks
.map((notebook) => {
if (notebook.topics.length > 0)
return notebook.topics.map((topic: { title: string }) =>
[notebook.title, topic.title, filename].join("/")
);
return [notebook.title, filename].join("/");
})
.flat()
: [filename];
filePaths.forEach((filePath) => { filePaths.forEach((filePath) => {
controller.enqueue({ controller.enqueue({