Merge branch 'master' into beta

This commit is contained in:
Abdullah Atta
2026-06-23 08:34:57 +05:00
7 changed files with 134 additions and 47 deletions

View File

@@ -66,12 +66,17 @@ import {
VAULT_ERRORS
} from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import { useUserStore } from "../../../stores/use-user-store";
import { AppFontSize } from "../../../utils/size";
import { Pressable } from "../../ui/pressable";
import AppIcon from "../../ui/AppIcon";
export const VaultDialog: React.FC = () => {
const { colors } = useThemeColors();
// UI State
const [visible, setVisible] = useState(false);
const isUserLoggedIn = useUserStore((state) => !!state.user);
const [loading, setLoading] = useState(false);
const [deleteAll, setDeleteAll] = useState(false);
const [biometricUnlock, setBiometricUnlock] = useState(false);
@@ -196,9 +201,12 @@ export const VaultDialog: React.FC = () => {
}
eSendEvent("vaultUpdated");
setLoading(false);
setTimeout(() => {
close();
}, 100);
close();
ToastManager.show({
message: strings.vaultDeleted(),
type: "success",
context: "global"
});
} else {
setLoading(false);
formRef.current.setError("password", strings.passwordIncorrect());
@@ -489,6 +497,13 @@ export const VaultDialog: React.FC = () => {
const { password, newPassword } = formRef.current.getValues();
if (requestType === VaultRequestType.DeleteVault && !isUserLoggedIn) {
setLoading(true);
await deleteVault();
setLoading(false);
return;
}
if (requestType === VaultRequestType.CreateVault) {
createVault();
} else if (requestType === VaultRequestType.ChangePassword) {
@@ -629,16 +644,22 @@ export const VaultDialog: React.FC = () => {
// Auto-unlock with fingerprint if applicable
const canAutoUnlock =
fingerprint &&
available &&
data.requestType !== VaultRequestType.EnableFingerprint &&
data.requestType !== VaultRequestType.RevokeFingerprint &&
data.requestType !== VaultRequestType.ChangePassword &&
data.requestType !== VaultRequestType.ClearVault &&
data.requestType !== VaultRequestType.DeleteVault &&
data.requestType !== VaultRequestType.CustomAction &&
data.requestType !== VaultRequestType.PermanentUnlock;
data.requestType !== VaultRequestType.PermanentUnlock &&
data.requestType !== VaultRequestType.CreateVault;
if (canAutoUnlock) {
await onPressFingerprintAuth(data.title, data.description);
if (canAutoUnlock && available) {
try {
await onPressFingerprintAuth(data.title, data.description);
} catch (e) {
setVisible(true);
}
} else {
setVisible(true);
}
@@ -700,7 +721,6 @@ export const VaultDialog: React.FC = () => {
icon="shield"
padding={12}
/>
<Seperator half />
<View
style={{
@@ -709,8 +729,7 @@ export const VaultDialog: React.FC = () => {
>
{(isChangePassword ||
isClearVault ||
!isCreateVault ||
isDeleteVault ||
(isDeleteVault && isUserLoggedIn) ||
isCustomAction) &&
!isRevokeFingerprint ? (
<>
@@ -772,20 +791,32 @@ export const VaultDialog: React.FC = () => {
) : null}
{isDeleteVault && (
<Button
<Pressable
onPress={() => setDeleteAll(!deleteAll)}
icon={
deleteAll
? "check-circle-outline"
: "checkbox-blank-circle-outline"
}
style={{
marginTop: DefaultAppStyles.GAP_VERTICAL
paddingVertical: 0,
flexDirection: "row",
gap: DefaultAppStyles.GAP_SMALL,
marginTop: isUserLoggedIn
? DefaultAppStyles.GAP_VERTICAL_SMALL
: 0,
justifyContent: "flex-start"
}}
width="100%"
title={strings.deleteAllNotes()}
type="errorShade"
/>
>
<AppIcon
name={
deleteAll
? "check-circle-outline"
: "checkbox-blank-circle-outline"
}
color={colors.error.accent}
size={AppFontSize.md}
/>
<Paragraph color={colors.error.accent} size={AppFontSize.sm}>
{strings.deleteAllNotes()}
</Paragraph>
</Pressable>
)}
{isChangePassword ? (

View File

@@ -384,10 +384,14 @@ function MonographLockscreen({
}) {
const [error, setError] = useState<string>();
const [loading, setLoading] = useState<boolean>();
const password = useRef<string>();
const password = useRef<string>("");
const unlock = useCallback(async () => {
if (!password.current) return;
if (!password.current) {
setError("Password is required.");
return;
}
setError(undefined);
setLoading(true);
try {
@@ -467,7 +471,9 @@ function MonographLockscreen({
}}
autoFocus={true}
autofillBackgroundColor="background-secondary"
onChange={(event) => (password.current = event.target.value)}
onChange={(event) => {
password.current = event.target.value;
}}
onKeyUp={(e) => (e.key === "Enter" ? unlock() : null)}
type="password"
placeholder="Enter password to continue"
@@ -477,6 +483,7 @@ function MonographLockscreen({
title="Unlock"
sx={{ borderRadius: 100, px: 50, mt: 1 }}
onClick={() => unlock()}
disabled={loading}
>
Unlock
</Button>

View File

@@ -23,6 +23,7 @@ import { showToast } from "../utils/toast";
import { VAULT_ERRORS } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useStore as useAppStore } from "../stores/app-store";
import { useStore as useUserStore } from "../stores/user-store";
class Vault {
static async createVault() {
@@ -63,29 +64,47 @@ class Vault {
static async deleteVault() {
if (!(await db.vault.exists())) return false;
const result = await showPasswordDialog({
title: strings.deleteVault(),
subtitle: strings.deleteVaultDesc(),
inputs: {
password: {
label: strings.accountPassword(),
autoComplete: "current-password"
}
},
checks: {
deleteAllLockedNotes: {
text: strings.deleteAllNotes(),
default: false
}
},
validate: ({ password }) => {
return db.user.verifyPassword(password);
}
});
const result = await (useUserStore.getState().isLoggedIn
? showPasswordDialog({
title: strings.deleteVault(),
subtitle: strings.deleteVaultDesc(),
inputs: {
password: {
label: strings.accountPassword(),
autoComplete: "current-password"
}
},
checks: {
deleteAllLockedNotes: {
text: strings.deleteAllNotes(),
default: false
}
},
validate: ({ password }) => {
return db.user.verifyPassword(password);
}
})
: showPasswordDialog({
title: strings.deleteVault(),
subtitle: strings.deleteVaultDesc(),
inputs: {},
checks: {
deleteAllLockedNotes: {
text: strings.deleteAllNotes(),
default: false
}
},
validate: () => {
return Promise.resolve(true);
}
}));
if (result) {
await db.vault.delete(result.deleteAllLockedNotes);
return true;
}
return false;
}

View File

@@ -38,6 +38,7 @@ export class NNMigrationProvider implements MigrationProvider {
async up(db) {
await db.schema
.createTable("kv")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.addColumn("key", "text", (c) => c.primaryKey().unique().notNull())
.addColumn("value", "text")
@@ -46,6 +47,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("notes")
.ifNotExists()
// .modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.$call(addTrashColumns)
@@ -68,6 +70,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("content")
.ifNotExists()
// .modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("noteId", "text")
@@ -88,6 +91,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("notehistory")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("noteId", "text")
@@ -98,6 +102,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("sessioncontent")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("data", "text")
@@ -109,6 +114,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("notebooks")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.$call(addTrashColumns)
@@ -120,6 +126,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("tags")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("title", "text", COLLATE_NOCASE)
@@ -127,6 +134,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("colors")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("title", "text", COLLATE_NOCASE)
@@ -135,6 +143,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("vaults")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("title", "text", COLLATE_NOCASE)
@@ -143,6 +152,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("relations")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("fromType", "text")
@@ -153,6 +163,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("shortcuts")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("sortIndex", "integer")
@@ -162,6 +173,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("reminders")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("title", "text", COLLATE_NOCASE)
@@ -178,6 +190,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("attachments")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("iv", "text")
@@ -197,6 +210,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createTable("settings")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.$call(addBaseColumns)
.addColumn("key", "text", (c) => c.unique())
@@ -205,12 +219,14 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createIndex("notehistory_noteid")
.ifNotExists()
.on("notehistory")
.column("noteId")
.execute();
await db.schema
.createIndex("relation_from_general")
.ifNotExists()
.on("relations")
.columns(["fromType", "toType", "fromId"])
.where("toType", "!=", "note")
@@ -219,6 +235,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createIndex("relation_to_general")
.ifNotExists()
.on("relations")
.columns(["fromType", "toType", "toId"])
.where("fromType", "!=", "note")
@@ -227,6 +244,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createIndex("relation_from_note_notebook")
.ifNotExists()
.on("relations")
.columns(["fromType", "toType", "fromId", "toId"])
.where((eb) =>
@@ -239,6 +257,7 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createIndex("relation_to_note_notebook")
.ifNotExists()
.on("relations")
.columns(["fromType", "toType", "toId", "fromId"])
.where((eb) =>
@@ -251,36 +270,42 @@ export class NNMigrationProvider implements MigrationProvider {
await db.schema
.createIndex("note_type")
.ifNotExists()
.on("notes")
.columns(["type"])
.execute();
await db.schema
.createIndex("note_deleted")
.ifNotExists()
.on("notes")
.columns(["deleted"])
.execute();
await db.schema
.createIndex("note_date_deleted")
.ifNotExists()
.on("notes")
.columns(["dateDeleted"])
.execute();
await db.schema
.createIndex("notebook_type")
.ifNotExists()
.on("notebooks")
.columns(["type"])
.execute();
await db.schema
.createIndex("attachment_hash")
.ifNotExists()
.on("attachments")
.column("hash")
.execute();
await db.schema
.createIndex("content_noteId")
.ifNotExists()
.on("content")
.columns(["noteId"])
.execute();
@@ -316,6 +341,7 @@ export class NNMigrationProvider implements MigrationProvider {
async up(db) {
await db.schema
.createTable("config")
.ifNotExists()
.modifyEnd(sql`without rowid`)
.addColumn("name", "text", (c) => c.primaryKey().unique().notNull())
.addColumn("value", "text")
@@ -397,6 +423,7 @@ export class NNMigrationProvider implements MigrationProvider {
async up(db) {
await db.schema
.createTable("monographs")
.ifNotExists()
.$call(addBaseColumns)
.addColumn("datePublished", "integer")
.addColumn("title", "text", COLLATE_NOCASE)
@@ -413,6 +440,7 @@ export class NNMigrationProvider implements MigrationProvider {
.execute();
await db.schema
.createIndex("note_expiry_date")
.ifNotExists()
.on("notes")
.expression(sql`expiryDate ->> '$.value'`)
.execute();
@@ -514,7 +542,9 @@ function createFTS5Table(
sql.join(_options.map((o) => sql.raw(o)))
]);
return sql`CREATE VIRTUAL TABLE ${sql.raw(name)} USING fts5(${args})`;
return sql`CREATE VIRTUAL TABLE IF NOT EXISTS ${sql.raw(
name
)} USING fts5(${args})`;
}
async function runFTSTablesMigrations(db: Kysely<any>) {

View File

@@ -2310,8 +2310,8 @@ msgid "Delete mode"
msgstr "Delete mode"
#: src/strings.ts:562
msgid "Delete notes in this vault"
msgstr "Delete notes in this vault"
msgid "Delete notes in this vault permanently"
msgstr "Delete notes in this vault permanently"
#: src/strings.ts:569
msgid "Delete permanently"

View File

@@ -2299,7 +2299,7 @@ msgid "Delete mode"
msgstr ""
#: src/strings.ts:562
msgid "Delete notes in this vault"
msgid "Delete notes in this vault permanently"
msgstr ""
#: src/strings.ts:569

View File

@@ -559,7 +559,7 @@ $day$: Current day (eg. Monday)`,
couldNotUnlock: () => t`Could not unlock`,
unlockNoteDesc: () =>
t`Your note will be unencrypted and removed from the vault.`,
deleteAllNotes: () => t`Delete notes in this vault`,
deleteAllNotes: () => t`Delete notes in this vault permanently`,
getStarted: () => t`Get started`,
saveACopy: () => t`Save a copy`,
discard: () => t`Discard`,