Compare commits
2 Commits
93b272ecb5
...
ae5257b2b3
Author | SHA1 | Date | |
---|---|---|---|
|
ae5257b2b3 | ||
|
c3f9529feb |
6
package-lock.json
generated
6
package-lock.json
generated
@ -3541,9 +3541,9 @@
|
||||
}
|
||||
},
|
||||
"idb": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz",
|
||||
"integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw=="
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/idb/-/idb-4.0.3.tgz",
|
||||
"integrity": "sha512-moRlNNe0Gsvp4jAwz5cJ7scjyNTVA/cESKGCobULaljfaKZ970y8NDNCseHdMY+YxNXH58Z1V+7tTyf0GZyKqw=="
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.1.13",
|
||||
|
@ -18,7 +18,7 @@
|
||||
"@hibas123/utils": "^2.1.0",
|
||||
"aes-js": "^3.1.2",
|
||||
"feather-icons": "^4.22.1",
|
||||
"idb": "3.0.2",
|
||||
"idb": "^4.0.3",
|
||||
"js-sha256": "^0.9.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"secure-file-wrapper": "git+https://git.stamm.me/OpenServer/OSSecureFileWrapper.git",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { h } from "preact";
|
||||
import { Page } from "../../../page";
|
||||
import Theme from "../../../theme";
|
||||
import Theme, { ThemeStates } from "../../../theme";
|
||||
import Navigation from "../../../navigation";
|
||||
import ArrowLeft from "feather-icons/dist/icons/arrow-left.svg";
|
||||
|
||||
@ -10,6 +10,7 @@ export default class SettingsPage extends Page<{ state: any }, { vault: string }
|
||||
}
|
||||
|
||||
render() {
|
||||
let active = Theme.active();
|
||||
return <div>
|
||||
<header class="header">
|
||||
<a class="header-icon-button" onClick={() => history.back()}><ArrowLeft height={undefined} width={undefined} /></a>
|
||||
@ -17,7 +18,18 @@ export default class SettingsPage extends Page<{ state: any }, { vault: string }
|
||||
<span></span>
|
||||
</header>
|
||||
<div class="container">
|
||||
<button class="btn" onClick={() => Theme.toggle()}>Toggle Dark Mode</button>
|
||||
<div className="input-group">
|
||||
<label>Select Theme: </label>
|
||||
<select class="inp" onChange={(ev) => Theme.change(Number((ev.target as HTMLSelectElement).value))}>
|
||||
{Object.keys(ThemeStates)
|
||||
.filter(e => Number.isNaN(Number(e)))
|
||||
.map(e => <option selected={ThemeStates[e] === active} value={ThemeStates[e]}>{e.charAt(0).toUpperCase() + e.slice(1).toLowerCase()}</option>)}
|
||||
{/* <option value={ThemeStates.AUTO}>Auto</option>
|
||||
<option value={ThemeStates.LIGHT}>Light</option>
|
||||
<option value={ThemeStates.DARK}>Dark</option> */}
|
||||
</select>
|
||||
</div>
|
||||
{/* <button class="btn" onClick={() => Theme.toggle()}>Toggle Dark Mode</button> */}
|
||||
<button class="btn" onClick={() => window.navigator.serviceWorker.controller.postMessage("clear_cache")}>Clear cache</button>
|
||||
</div>
|
||||
</div >;
|
||||
|
@ -3,7 +3,7 @@
|
||||
padding: 0.5rem;
|
||||
margin-top: 0 !important;
|
||||
align-items: flex-end;
|
||||
justify-content: end;
|
||||
justify-content: start;
|
||||
|
||||
>span {
|
||||
font-size: 1.5rem;
|
||||
|
@ -1,14 +1,12 @@
|
||||
import { Lock } from "@hibas123/utils";
|
||||
|
||||
import { DB, openDb, Transaction } from "idb";
|
||||
import { openDB, IDBPDatabase, IDBPTransaction, } from "idb";
|
||||
|
||||
export default class IDB {
|
||||
initLock = new Lock();
|
||||
db: DB;
|
||||
db: IDBPDatabase;
|
||||
constructor(database: string, private stores: string[]) {
|
||||
let lock = this.initLock.getLock();
|
||||
lock.then(async l => {
|
||||
|
||||
this.initLock.getLock().then(async l => {
|
||||
let v = localStorage.getItem(database + "_version");
|
||||
let version = 0;
|
||||
if (v) version = Number(v)
|
||||
@ -21,12 +19,15 @@ export default class IDB {
|
||||
localStorage.setItem(database + "_version", version.toString());
|
||||
localStorage.setItem(database + "_stores", stores.join(","));
|
||||
|
||||
this.db = await openDb(database, version, db => {
|
||||
console.log("IndexedDB need update")
|
||||
stores.forEach(store => {
|
||||
if (!db.objectStoreNames.contains(store))
|
||||
db.createObjectStore(store);
|
||||
})
|
||||
this.db = await openDB(database, version, {
|
||||
upgrade: (db) => {
|
||||
console.log("IndexedDB need update")
|
||||
const check = name => (<any>db.objectStoreNames as DOMStringList).contains ? (<any>db.objectStoreNames as DOMStringList).contains(name) : db.objectStoreNames.find(e => e === name);
|
||||
stores.forEach(store => {
|
||||
if (!check(store))
|
||||
db.createObjectStore(store);
|
||||
})
|
||||
},
|
||||
})
|
||||
console.log("Got DATABASE", this.db)
|
||||
l.release();
|
||||
@ -48,42 +49,42 @@ export default class IDB {
|
||||
return {
|
||||
name: name,
|
||||
transaction: () => {
|
||||
return this.db.transaction(name, "readwrite")
|
||||
return <any>this.db.transaction(name, "readwrite") as IDBPTransaction<unknown, string[]>;
|
||||
},
|
||||
get: async (key: string, transaction?: Transaction): Promise<T> => {
|
||||
get: async (key: string, transaction?: IDBPTransaction<unknown, string[]>): Promise<T> => {
|
||||
(await this.initLock.getLock()).release()
|
||||
return (transaction || this.db.transaction(name))
|
||||
.objectStore(name).get(key);
|
||||
},
|
||||
|
||||
getAll: async (transaction?: Transaction): Promise<T[]> => {
|
||||
getAll: async (transaction?: IDBPTransaction<unknown, string[]>): Promise<T[]> => {
|
||||
(await this.initLock.getLock()).release()
|
||||
return (transaction || this.db.transaction(name))
|
||||
.objectStore(name).getAll();
|
||||
},
|
||||
|
||||
set: async (key: string, val: T, transaction?: Transaction) => {
|
||||
set: async (key: string, val: T, transaction?: IDBPTransaction<unknown, string[]>) => {
|
||||
(await this.initLock.getLock()).release()
|
||||
const tx = (transaction || this.db.transaction(name, "readwrite"));
|
||||
tx.objectStore(name).put(val, key);
|
||||
return tx.complete;
|
||||
return tx.done;
|
||||
},
|
||||
|
||||
delete: async (key: string, transaction?: Transaction) => {
|
||||
delete: async (key: string, transaction?: IDBPTransaction<unknown, string[]>) => {
|
||||
(await this.initLock.getLock()).release()
|
||||
const tx = (transaction || this.db.transaction(name, "readwrite"));
|
||||
tx.objectStore(name).delete(key);
|
||||
return tx.complete;
|
||||
return tx.done;
|
||||
},
|
||||
|
||||
clear: async (transaction?: Transaction) => {
|
||||
clear: async (transaction?: IDBPTransaction<unknown, string[]>) => {
|
||||
(await this.initLock.getLock()).release()
|
||||
const tx = (transaction || this.db.transaction(name, "readwrite"));
|
||||
tx.objectStore(name).clear();
|
||||
return tx.complete;
|
||||
return tx.done;
|
||||
},
|
||||
|
||||
keys: async (transaction?: Transaction): Promise<string[]> => {
|
||||
keys: async (transaction?: IDBPTransaction<unknown, string[]>): Promise<string[]> => {
|
||||
(await this.initLock.getLock()).release()
|
||||
const tx = (transaction || this.db.transaction(name));
|
||||
const keys: string[] = [];
|
||||
@ -91,13 +92,15 @@ export default class IDB {
|
||||
|
||||
// This would be store.getAllKeys(), but it isn't supported by Edge or Safari.
|
||||
// openKeyCursor isn't supported by Safari, so we fall back
|
||||
(store.iterateKeyCursor || store.iterateCursor).call(store, (cursor: any) => {
|
||||
if (!cursor) return;
|
||||
keys.push(cursor.key);
|
||||
cursor.continue();
|
||||
});
|
||||
store.getAllKeys()
|
||||
|
||||
return tx.complete.then(() => keys);
|
||||
// (store.iterateKeyCursor || store.iterateCursor).call(store, (cursor: any) => {
|
||||
// if (!cursor) return;
|
||||
// keys.push(cursor.key);
|
||||
// cursor.continue();
|
||||
// });
|
||||
|
||||
return tx.done.then(() => keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,17 +99,25 @@ console.log("Dark mode:", Theme.active);
|
||||
let err = await Notes.getToken(code)
|
||||
if (err) {
|
||||
Notifications.sendError("Login failed: " + err)
|
||||
Notes.login()
|
||||
return Notes.login()
|
||||
} else {
|
||||
window.history.replaceState(null, document.title, "/" + window.location.hash);
|
||||
}
|
||||
} else {
|
||||
Notes.login()
|
||||
return Notes.login()
|
||||
}
|
||||
}
|
||||
|
||||
await Notes.start();
|
||||
|
||||
if (window.navigator.storage && navigator.storage.persist) {
|
||||
navigator.storage.persisted()
|
||||
.then(has => has ? true : navigator.storage.persist())
|
||||
.then(is => {
|
||||
console.log("Persistant Storage:", is);
|
||||
})
|
||||
}
|
||||
|
||||
Navigation.default = VaultsPage as typeof Page;
|
||||
Navigation.addPage("/vault", VaultPage as typeof Page)
|
||||
Navigation.addPage("/demo", DemoPage as typeof Page)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import SecureFile, { IFile } from "@hibas123/secure-file-wrapper";
|
||||
import { Lock, Observable } from "@hibas123/utils";
|
||||
import * as aesjs from "aes-js";
|
||||
import { Transaction } from "idb";
|
||||
import { IDBPTransaction } from "idb";
|
||||
import { sha256 } from "js-sha256";
|
||||
import * as uuidv4 from "uuid/v4";
|
||||
import * as config from "../config.json";
|
||||
@ -480,7 +480,7 @@ class NotesProvider {
|
||||
return Decoder.decode(this._decrypt(msg, this.generalEncryption))
|
||||
}
|
||||
|
||||
async addop(note_id: string, type: OpLogType, values: { value: Uint8Array, preview: Uint8Array }, date: Date, transaction?: Transaction) {
|
||||
async addop(note_id: string, type: OpLogType, values: { value: Uint8Array, preview: Uint8Array }, date: Date, transaction?: IDBPTransaction<unknown, string[]>) {
|
||||
let tx = transaction || this.oplogDB.transaction();
|
||||
let oplog = await this.oplogDB.get(note_id, tx);
|
||||
if (!oplog) oplog = { logs: [], id: note_id };
|
||||
|
51
src/theme.ts
51
src/theme.ts
@ -1,27 +1,52 @@
|
||||
const light = require("!!raw-loader!@hibas123/theme/out/light.css").default;
|
||||
const dark = require("!!raw-loader!@hibas123/theme/out/dark.css").default;
|
||||
|
||||
let isDark = localStorage.getItem("theme") === "dark";
|
||||
export enum ThemeStates {
|
||||
AUTO,
|
||||
LIGHT,
|
||||
DARK
|
||||
}
|
||||
|
||||
let themeConfig: ThemeStates = Number(localStorage.getItem("theme"));
|
||||
if (Number.isNaN(themeConfig))
|
||||
themeConfig = ThemeStates.AUTO;
|
||||
|
||||
let isDark = false;
|
||||
let mediaIsDark = false;
|
||||
|
||||
if (window.matchMedia) {
|
||||
const mediaq = matchMedia("(prefers-color-scheme: dark)");
|
||||
mediaIsDark = mediaq.matches;
|
||||
mediaq.onchange = ev => {
|
||||
mediaIsDark = ev.matches;
|
||||
apply();
|
||||
}
|
||||
console.log(mediaq);
|
||||
}
|
||||
|
||||
|
||||
let styleElm: HTMLStyleElement;
|
||||
|
||||
function apply() {
|
||||
if (styleElm) styleElm.remove();
|
||||
styleElm = document.createElement("style");
|
||||
document.head.appendChild(styleElm);
|
||||
styleElm.innerHTML = isDark ? dark : light;
|
||||
function apply(force?: boolean) {
|
||||
let shouldDark = themeConfig === ThemeStates.AUTO ? mediaIsDark : themeConfig === ThemeStates.DARK;
|
||||
if (force || shouldDark !== isDark) {
|
||||
if (styleElm) styleElm.remove();
|
||||
styleElm = document.createElement("style");
|
||||
document.head.appendChild(styleElm);
|
||||
styleElm.innerHTML = shouldDark ? dark : light;
|
||||
isDark = shouldDark;
|
||||
}
|
||||
}
|
||||
apply();
|
||||
apply(true);
|
||||
|
||||
function toggle() {
|
||||
isDark = !isDark;
|
||||
localStorage.setItem("theme", isDark ? "dark" : "light");
|
||||
|
||||
function change(state: ThemeStates) {
|
||||
themeConfig = state;
|
||||
localStorage.setItem("theme", String(themeConfig));
|
||||
apply();
|
||||
}
|
||||
|
||||
export default {
|
||||
active: () => isDark,
|
||||
toggle: () => toggle()
|
||||
active: () => themeConfig,
|
||||
change: (state: ThemeStates) => change(state)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user