feat: add passkey-style online profiles for cross-device sync and show build time in About

This commit is contained in:
Jonathan Sykes
2026-07-03 05:16:05 +08:00
parent 048817bcf4
commit 94140a5433
5 changed files with 379 additions and 8 deletions

View File

@@ -53,9 +53,55 @@ export async function initDb() {
CREATE INDEX IF NOT EXISTS idx_vh_fp_time
ON video_history (fingerprint, accessed_at DESC);
CREATE TABLE IF NOT EXISTS profiles (
name TEXT PRIMARY KEY,
data TEXT NOT NULL DEFAULT '{}',
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
);
`);
}
// ---- Profiles (named cross-device sync; the name acts as the passkey) ------
// Insert a new profile. Returns false when the name is already taken.
export async function createProfile(name, dataJson) {
try {
await db.execute({
sql: `INSERT INTO profiles (name, data, created_at, updated_at)
VALUES (?, ?, unixepoch(), unixepoch())`,
args: [name, dataJson],
});
return true;
} catch (err) {
const msg = String(err && err.message || err);
if (msg.includes('UNIQUE') || msg.includes('PRIMARY KEY')) return false;
throw err;
}
}
export async function getProfile(name) {
const r = await db.execute({
sql: 'SELECT data, updated_at FROM profiles WHERE name = ?',
args: [name],
});
const row = r.rows[0];
if (!row) return null;
return { data: row.data, updatedAt: Number(row.updated_at) };
}
// Update an EXISTING profile's data blob. Returns false when it doesn't exist
// (saving must never implicitly create a profile — creation is a deliberate,
// uniqueness-checked act).
export async function saveProfile(name, dataJson) {
const r = await db.execute({
sql: 'UPDATE profiles SET data = ?, updated_at = unixepoch() WHERE name = ?',
args: [dataJson, name],
});
return (r.rowsAffected || 0) > 0;
}
// ---- Helpers ---------------------------------------------------------------
// Upsert the users row and optionally update playlists.