mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 23:19:40 +01:00
web: fix note editor properties
This commit is contained in:
@@ -22,7 +22,7 @@ import Database from ".";
|
||||
import { CHECK_IDS, EV, EVENTS, checkIsUserPremium } from "../common";
|
||||
import { tinyToTiptap } from "../migrations";
|
||||
import { isCipher } from "../database/crypto";
|
||||
import { EncryptedContentItem, Note } from "../types";
|
||||
import { Note } from "../types";
|
||||
import {
|
||||
isEncryptedContent,
|
||||
isUnencryptedContent
|
||||
@@ -110,6 +110,7 @@ export default class Vault {
|
||||
try {
|
||||
const content = await this.decryptContent(
|
||||
encryptedContent,
|
||||
note.id,
|
||||
oldPassword
|
||||
);
|
||||
contentItems.push({
|
||||
@@ -239,18 +240,18 @@ export default class Vault {
|
||||
}
|
||||
|
||||
async decryptContent(
|
||||
encryptedContent: EncryptedContentItem,
|
||||
encryptedContent: NoteContent<true>,
|
||||
noteId: string,
|
||||
password?: string
|
||||
) {
|
||||
if (!password) password = await this.getVaultPassword();
|
||||
|
||||
if (
|
||||
encryptedContent.noteId &&
|
||||
typeof encryptedContent.data !== "object" &&
|
||||
!isCipher(encryptedContent.data)
|
||||
) {
|
||||
await this.db.notes.add({
|
||||
id: encryptedContent.noteId,
|
||||
id: noteId,
|
||||
locked: false
|
||||
});
|
||||
return { data: encryptedContent.data, type: encryptedContent.type };
|
||||
@@ -330,7 +331,11 @@ export default class Vault {
|
||||
|
||||
const encryptedContent = await this.db.content.get(note.contentId);
|
||||
if (!encryptedContent || !isEncryptedContent(encryptedContent)) return;
|
||||
const content = await this.decryptContent(encryptedContent, password);
|
||||
const content = await this.decryptContent(
|
||||
encryptedContent,
|
||||
note.id,
|
||||
password
|
||||
);
|
||||
|
||||
if (perm) {
|
||||
await this.db.notes.add({
|
||||
|
||||
@@ -29,6 +29,7 @@ import { Attachment } from "../types";
|
||||
import Database from "../api";
|
||||
import { FilteredSelector, SQLCollection } from "../database/sql-collection";
|
||||
import { isFalse } from "../database";
|
||||
import { sql } from "kysely";
|
||||
|
||||
export class Attachments implements ICollection {
|
||||
name = "attachments";
|
||||
@@ -470,6 +471,13 @@ export class Attachments implements ICollection {
|
||||
);
|
||||
}
|
||||
|
||||
async totalSize(selector: FilteredSelector<Attachment> = this.all) {
|
||||
const result = await selector.filter
|
||||
.select((eb) => eb.fn.sum<number>(sql.raw(`size + 17`)).as("totalSize"))
|
||||
.executeTakeFirst();
|
||||
return result?.totalSize;
|
||||
}
|
||||
|
||||
private async encryptKey(key: SerializedKey) {
|
||||
const encryptionKey = await this._getEncryptionKey();
|
||||
const encryptedKey = await this.db
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import Database from "../api";
|
||||
import { isCipher } from "../database/crypto";
|
||||
import { SQLCollection } from "../database/sql-collection";
|
||||
import { FilteredSelector, SQLCollection } from "../database/sql-collection";
|
||||
import { HistorySession, isDeleted } from "../types";
|
||||
import { makeSessionContentId } from "../utils/id";
|
||||
import { ICollection } from "./collection";
|
||||
@@ -39,25 +39,31 @@ export class NoteHistory implements ICollection {
|
||||
await this.sessionContent.init();
|
||||
}
|
||||
|
||||
async get(noteId: string, order: "asc" | "desc" = "desc") {
|
||||
if (!noteId) return [];
|
||||
// async get(noteId: string, order: "asc" | "desc" = "desc") {
|
||||
// if (!noteId) return [];
|
||||
|
||||
// const indices = this.collection.indexer.indices;
|
||||
// const sessionIds = indices.filter((id) => id.startsWith(noteId));
|
||||
// if (sessionIds.length === 0) return [];
|
||||
// const history = await this.getSessions(sessionIds);
|
||||
// // const indices = this.collection.indexer.indices;
|
||||
// // const sessionIds = indices.filter((id) => id.startsWith(noteId));
|
||||
// // if (sessionIds.length === 0) return [];
|
||||
// // const history = await this.getSessions(sessionIds);
|
||||
|
||||
// return history.sort(function (a, b) {
|
||||
// return b.dateModified - a.dateModified;
|
||||
// });
|
||||
const history = await this.db
|
||||
.sql()
|
||||
.selectFrom("notehistory")
|
||||
.where("noteId", "==", noteId)
|
||||
.orderBy(`dateModified ${order}`)
|
||||
.selectAll()
|
||||
.execute();
|
||||
return history as HistorySession[];
|
||||
// // return history.sort(function (a, b) {
|
||||
// // return b.dateModified - a.dateModified;
|
||||
// // });
|
||||
// const history = await this.db
|
||||
// .sql()
|
||||
// .selectFrom("notehistory")
|
||||
// .where("noteId", "==", noteId)
|
||||
// .orderBy(`dateModified ${order}`)
|
||||
// .selectAll()
|
||||
// .execute();
|
||||
// return history as HistorySession[];
|
||||
// }
|
||||
get(noteId: string) {
|
||||
return new FilteredSelector<HistorySession>(
|
||||
"notehistory",
|
||||
this.db.sql().selectFrom("notehistory").where("noteId", "==", noteId)
|
||||
);
|
||||
}
|
||||
|
||||
async add(
|
||||
|
||||
@@ -70,7 +70,9 @@ export class SessionContent implements ICollection {
|
||||
});
|
||||
}
|
||||
|
||||
async get(sessionContentId: string) {
|
||||
async get(
|
||||
sessionContentId: string
|
||||
): Promise<NoteContent<boolean> | undefined> {
|
||||
const session = await this.collection.get(sessionContentId);
|
||||
if (!session || isDeleted(session)) return;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ const DEFAULT_GROUP_OPTIONS = (key: GroupingKey) =>
|
||||
sortBy:
|
||||
key === "trash"
|
||||
? "dateDeleted"
|
||||
: key === "tags"
|
||||
: key === "tags" || key === "reminders"
|
||||
? "dateCreated"
|
||||
: key === "reminders"
|
||||
? "dueDate"
|
||||
|
||||
@@ -345,31 +345,37 @@ export default class Backup {
|
||||
if ("sessionContentId" in item && item.type !== "session")
|
||||
(item as any).type = "notehistory";
|
||||
|
||||
await migrateItem(
|
||||
item,
|
||||
version,
|
||||
CURRENT_DATABASE_VERSION,
|
||||
item.type,
|
||||
this.db,
|
||||
"backup"
|
||||
);
|
||||
if (
|
||||
(await migrateItem(
|
||||
item,
|
||||
version,
|
||||
CURRENT_DATABASE_VERSION,
|
||||
item.type,
|
||||
this.db,
|
||||
"backup"
|
||||
)) === "skip"
|
||||
)
|
||||
continue;
|
||||
// since items in trash can have their own set of migrations,
|
||||
// we have to run the migration again to account for that.
|
||||
if (item.type === "trash" && item.itemType)
|
||||
await migrateItem(
|
||||
item as unknown as Note | Notebook,
|
||||
version,
|
||||
CURRENT_DATABASE_VERSION,
|
||||
item.itemType,
|
||||
this.db,
|
||||
"backup"
|
||||
);
|
||||
if (
|
||||
(await migrateItem(
|
||||
item as unknown as Note | Notebook,
|
||||
version,
|
||||
CURRENT_DATABASE_VERSION,
|
||||
item.itemType,
|
||||
this.db,
|
||||
"backup"
|
||||
)) === "skip"
|
||||
)
|
||||
continue;
|
||||
|
||||
const itemType =
|
||||
// colors are naively of type "tag" instead of "color" so we have to fix that.
|
||||
item.type === "tag" && COLORS.includes(item.title.toLowerCase())
|
||||
? "color"
|
||||
: "itemType" in item && item.itemType
|
||||
: item.type === "trash" && "itemType" in item && item.itemType
|
||||
? item.itemType
|
||||
: item.type;
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ export class NNMigrationProvider implements MigrationProvider {
|
||||
.addColumn("salt", "text")
|
||||
.addColumn("size", "integer")
|
||||
.addColumn("alg", "text")
|
||||
.addColumn("encryptionKey", "text")
|
||||
.addColumn("key", "text")
|
||||
.addColumn("chunkSize", "integer")
|
||||
.addColumn("hash", "text", (c) => c.unique())
|
||||
.addColumn("hashType", "text")
|
||||
|
||||
@@ -19,3 +19,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export * from "./types";
|
||||
export { VirtualizedGrouping } from "./utils/virtualized-grouping";
|
||||
export { DefaultColors } from "./collections/colors";
|
||||
|
||||
@@ -61,7 +61,7 @@ type Migration = {
|
||||
item: MigrationItemMap[P],
|
||||
db: Database,
|
||||
migrationType: MigrationType
|
||||
) => boolean | Promise<boolean> | void;
|
||||
) => "skip" | boolean | Promise<boolean | "skip"> | void;
|
||||
};
|
||||
collection?: (collection: IndexedCollection) => Promise<void> | void;
|
||||
};
|
||||
@@ -196,12 +196,22 @@ const migrations: Migration[] = [
|
||||
.items()
|
||||
.find((t) => item.title === t.title && t.id !== oldTagId))
|
||||
)
|
||||
return false;
|
||||
return "skip";
|
||||
|
||||
const colorCode = ColorToHexCode[item.title];
|
||||
if (colorCode) {
|
||||
const newColor = await db.colors.all.find((eb) =>
|
||||
eb.or([eb("title", "in", [alias, item.title])])
|
||||
);
|
||||
if (newColor) return "skip";
|
||||
|
||||
(item as unknown as Color).type = "color";
|
||||
(item as unknown as Color).colorCode = colorCode;
|
||||
} else {
|
||||
const newTag = await db.tags.all.find((eb) =>
|
||||
eb.or([eb("title", "in", [alias, item.title])])
|
||||
);
|
||||
if (newTag) return "skip";
|
||||
}
|
||||
|
||||
item.title = alias || item.title;
|
||||
@@ -305,6 +315,7 @@ const migrations: Migration[] = [
|
||||
await db.relations.add(item, { id: subNotebookId, type: "notebook" });
|
||||
}
|
||||
delete item.topics;
|
||||
delete item.totalNotes;
|
||||
return true;
|
||||
},
|
||||
shortcut: (item) => {
|
||||
@@ -409,7 +420,9 @@ export async function migrateItem<TItemType extends MigrationItemType>(
|
||||
|
||||
const itemMigrator = migration.items[type];
|
||||
if (!itemMigrator) continue;
|
||||
if (await itemMigrator(item, database, migrationType)) {
|
||||
const result = await itemMigrator(item, database, migrationType);
|
||||
if (result === "skip") return "skip";
|
||||
if (result) {
|
||||
if (item.type && item.type !== type) type = item.type as TItemType;
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export type SortOptions = {
|
||||
| "dateCreated"
|
||||
| "dateDeleted"
|
||||
| "dateEdited"
|
||||
| "dateModified"
|
||||
| "title"
|
||||
| "filename"
|
||||
| "size"
|
||||
@@ -197,6 +198,10 @@ export interface Notebook extends BaseItem<"notebook"> {
|
||||
* @deprecated only kept here for migration purposes.
|
||||
*/
|
||||
topics?: Topic[];
|
||||
/**
|
||||
* @deprecated only kept here for migration purposes.
|
||||
*/
|
||||
totalNotes?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user