update settings screen

This commit is contained in:
reya 2023-11-19 08:48:01 +07:00
parent c53bdb68e5
commit 7117ed05a9
9 changed files with 155 additions and 40 deletions

View File

@ -35,6 +35,7 @@
"@tanstack/react-query": "^5.8.4",
"@tauri-apps/api": "2.0.0-alpha.11",
"@tauri-apps/cli": "2.0.0-alpha.17",
"@tauri-apps/plugin-autostart": "2.0.0-alpha.3",
"@tauri-apps/plugin-clipboard-manager": "2.0.0-alpha.3",
"@tauri-apps/plugin-dialog": "2.0.0-alpha.3",
"@tauri-apps/plugin-fs": "2.0.0-alpha.3",

View File

@ -56,6 +56,9 @@ dependencies:
'@tauri-apps/cli':
specifier: 2.0.0-alpha.17
version: 2.0.0-alpha.17
'@tauri-apps/plugin-autostart':
specifier: 2.0.0-alpha.3
version: 2.0.0-alpha.3
'@tauri-apps/plugin-clipboard-manager':
specifier: 2.0.0-alpha.3
version: 2.0.0-alpha.3
@ -2145,6 +2148,12 @@ packages:
'@tauri-apps/cli-win32-x64-msvc': 2.0.0-alpha.17
dev: false
/@tauri-apps/plugin-autostart@2.0.0-alpha.3:
resolution: {integrity: sha512-FWXMun68YPs+czGj063B/R2ItK0lFAHz08GCY8Ez1v5qGfq48MqBVF6EB5AHqQ73Wyq3+RGgDTyxuRFzBnXr6A==}
dependencies:
'@tauri-apps/api': 2.0.0-alpha.11
dev: false
/@tauri-apps/plugin-clipboard-manager@2.0.0-alpha.3:
resolution: {integrity: sha512-Lo30EM8VRo9bYMeRHhZT65OUgajbxaK1A9UhD7/9VZIFoWGbzKU/jrP78mcJ77lc+RrcCcSJvkAgOaLtuOlhxw==}
dependencies:

View File

@ -137,10 +137,6 @@ fn main() {
)
.build(),
)
.plugin(tauri_plugin_autostart::init(
MacosLauncher::LaunchAgent,
Some(vec!["--flag1", "--flag2"]),
))
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
@ -151,6 +147,10 @@ fn main() {
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_upload::init())
.plugin(tauri_plugin_window_state::Builder::default().build())
.plugin(tauri_plugin_autostart::init(
MacosLauncher::LaunchAgent,
Some(vec![]),
))
.invoke_handler(tauri::generate_handler![
opengraph,
secure_save,

View File

@ -1,5 +1,6 @@
import { getVersion } from '@tauri-apps/api/app';
import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
export function AboutScreen() {
const [version, setVersion] = useState('');
@ -22,6 +23,20 @@ export function AboutScreen() {
<p className="text-neutral-700 dark:text-neutral-300">Version {version}</p>
</div>
</div>
<div className="mx-auto mt-4 flex w-full max-w-xs flex-col gap-2">
<Link
to="https://lume.nu"
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
>
Website
</Link>
<Link
to="https://github.com/luminous-devs/lume/issues"
className="inline-flex h-9 w-full items-center justify-center rounded-lg bg-neutral-100 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
>
Report a issue
</Link>
</div>
</div>
);
}

View File

@ -1,21 +1,24 @@
import { useStorage } from '@libs/storage/provider';
export function AdvancedSettingScreen() {
const { db } = useStorage();
const clearCache = async () => {
await db.clearCache();
};
return (
<div className="mx-auto w-full max-w-lg">
<div className="flex flex-col gap-6">
<div className="flex w-full items-center justify-between">
<div className="w-24 shrink-0 text-end text-sm font-semibold">Event Caches</div>
<div className="flex items-center gap-8">
<div className="w-24 shrink-0 text-end text-sm font-semibold">Caches</div>
<div className="text-sm">Use for boost up NDK</div>
</div>
<button
type="button"
className="h-9 w-max rounded-lg bg-blue-500 px-2.5 text-white hover:bg-blue-600"
>
Clear
</button>
</div>
<div className="flex w-full items-center justify-between">
<div className="w-24 shrink-0 text-end text-sm font-semibold">User Caches</div>
<button
type="button"
className="h-9 w-max rounded-lg bg-blue-500 px-2.5 text-white hover:bg-blue-600"
onClick={() => clearCache()}
className="h-8 w-max rounded-lg bg-blue-500 px-3 text-sm font-medium text-white hover:bg-blue-600"
>
Clear
</button>

View File

@ -1,10 +1,19 @@
import { nip19 } from 'nostr-tools';
import { useEffect, useState } from 'react';
import { useStorage } from '@libs/storage/provider';
import { EyeOffIcon } from '@shared/icons';
export function BackupSettingScreen() {
const { db } = useStorage();
const [privkey, setPrivkey] = useState(null);
const [showPassword, setShowPassword] = useState(false);
const removePrivkey = async () => {
await db.secureRemove(db.account.pubkey);
};
useEffect(() => {
async function loadPrivkey() {
@ -24,12 +33,30 @@ export function BackupSettingScreen() {
You&apos;ve stored private key on Lume
</div>
) : (
<textarea
readOnly
className="relative h-36 w-full resize-none rounded-lg bg-neutral-200 px-3 py-1 text-neutral-900 !outline-none placeholder:text-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:placeholder:text-neutral-400"
>
{privkey}
</textarea>
<>
<div className="relative">
<input
readOnly
type={showPassword ? 'text' : 'password'}
value={nip19.nsecEncode(privkey)}
className="relative h-11 w-full resize-none rounded-lg bg-neutral-200 py-1 pl-3 pr-11 text-neutral-900 !outline-none placeholder:text-neutral-600 dark:bg-neutral-800 dark:text-neutral-100 dark:placeholder:text-neutral-400"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-1.5 top-1/2 inline-flex h-8 w-8 -translate-y-1/2 transform items-center justify-center rounded-lg bg-neutral-50 dark:bg-neutral-950"
>
<EyeOffIcon className="h-4 w-4" />
</button>
</div>
<button
type="button"
onClick={() => removePrivkey()}
className="mt-2 inline-flex h-9 w-full items-center justify-center gap-2 rounded-lg bg-red-200 px-6 font-medium text-red-500 hover:bg-red-500 hover:text-white focus:outline-none dark:hover:text-white"
>
Remove private key
</button>
</>
)}
</div>
</div>

View File

@ -1,6 +1,8 @@
import * as Switch from '@radix-ui/react-switch';
import { invoke } from '@tauri-apps/api/primitives';
import { getCurrent } from '@tauri-apps/api/window';
import { disable, enable, isEnabled } from '@tauri-apps/plugin-autostart';
import { isPermissionGranted, requestPermission } from '@tauri-apps/plugin-notification';
import { useEffect, useState } from 'react';
import { twMerge } from 'tailwind-merge';
@ -20,51 +22,86 @@ export function GeneralSettingScreen() {
});
const changeTheme = async (theme: 'light' | 'dark' | 'auto') => {
await invoke('plugin:theme|set_theme', {
theme,
});
await db.createSetting('appearance', theme);
await invoke('plugin:theme|set_theme', { theme });
// update state
setSettings((prev) => ({ ...prev, appearance: theme }));
};
const toggleAutolaunch = async () => {
if (!settings.autolaunch) {
await enable();
// update state
setSettings((prev) => ({ ...prev, autolaunch: true }));
} else {
await disable();
// update state
setSettings((prev) => ({ ...prev, autolaunch: false }));
}
};
const toggleOutbox = async () => {
await db.createSetting('outbox', String(+!settings.outbox));
// update state
setSettings((prev) => ({ ...prev, outbox: !settings.outbox }));
};
const toggleMedia = async () => {
await db.createSetting('media', String(+!settings.media));
// update state
setSettings((prev) => ({ ...prev, media: !settings.media }));
};
const toggleHashtag = async () => {
await db.createSetting('hashtag', String(+!settings.hashtag));
// update state
setSettings((prev) => ({ ...prev, hashtag: !settings.hashtag }));
};
const toggleNofitication = async () => {
if (settings.notification) return;
await requestPermission();
// update state
setSettings((prev) => ({ ...prev, notification: !settings.notification }));
};
useEffect(() => {
async function loadSettings() {
const theme = await getCurrent().theme();
setSettings((prev) => ({ ...prev, appearance: theme }));
const autostart = await isEnabled();
setSettings((prev) => ({ ...prev, autolaunch: autostart }));
const permissionGranted = await isPermissionGranted();
setSettings((prev) => ({ ...prev, notification: permissionGranted }));
const data = await db.getAllSettings();
if (!data) return;
data.forEach((item) => {
if (item.key === 'autolaunch')
setSettings((prev) => ({
...prev,
autolaunch: item.value === '1' ? true : false,
}));
if (item.key === 'outbox')
setSettings((prev) => ({
...prev,
outbox: item.value === '1' ? true : false,
outbox: !!parseInt(item.value),
}));
if (item.key === 'media')
setSettings((prev) => ({
...prev,
media: item.value === '1' ? true : false,
media: !!parseInt(item.value),
}));
if (item.key === 'hashtag')
setSettings((prev) => ({
...prev,
hashtag: item.value === '1' ? true : false,
hashtag: !!parseInt(item.value),
}));
if (item.key === 'notification')
setSettings((prev) => ({
...prev,
notification: item.value === '1' ? true : false,
notification: !!parseInt(item.value),
}));
});
}
@ -82,6 +119,7 @@ export function GeneralSettingScreen() {
</div>
<Switch.Root
checked={settings.autolaunch}
onClick={() => toggleAutolaunch()}
className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800"
>
<Switch.Thumb className="block h-6 w-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
@ -94,6 +132,7 @@ export function GeneralSettingScreen() {
</div>
<Switch.Root
checked={settings.outbox}
onClick={() => toggleOutbox()}
className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800"
>
<Switch.Thumb className="block h-6 w-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
@ -106,6 +145,7 @@ export function GeneralSettingScreen() {
</div>
<Switch.Root
checked={settings.media}
onClick={() => toggleMedia()}
className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800"
>
<Switch.Thumb className="block h-6 w-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
@ -118,6 +158,7 @@ export function GeneralSettingScreen() {
</div>
<Switch.Root
checked={settings.hashtag}
onClick={() => toggleHashtag()}
className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800"
>
<Switch.Thumb className="block h-6 w-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
@ -132,6 +173,8 @@ export function GeneralSettingScreen() {
</div>
<Switch.Root
checked={settings.notification}
disabled={settings.notification}
onClick={() => toggleNofitication()}
className="relative h-7 w-12 cursor-default rounded-full bg-neutral-200 outline-none data-[state=checked]:bg-blue-500 dark:bg-neutral-800"
>
<Switch.Thumb className="block h-6 w-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />

View File

@ -429,10 +429,20 @@ export class LumeStorage {
}
public async createSetting(key: string, value: string) {
return await this.db.execute(
'INSERT OR IGNORE INTO settings (key, value) VALUES ($1, $2);',
[key, value]
);
const currentSetting = await this.getSettingValue(key);
if (!currentSetting)
return await this.db.execute(
'INSERT OR IGNORE INTO settings (key, value) VALUES ($1, $2);',
[key, value]
);
const currentValue = !!parseInt(currentSetting);
return await this.db.execute('UPDATE settings SET value = $1 WHERE key = $2;', [
+!currentValue,
key,
]);
}
public async getAllSettings() {
@ -452,6 +462,12 @@ export class LumeStorage {
return results[0].value;
}
public async clearCache() {
await this.db.execute('DELETE FROM ndk_events;');
await this.db.execute('DELETE FROM ndk_eventtags;');
await this.db.execute('DELETE FROM ndk_users;');
}
public async accountLogout() {
// update current account status
await this.db.execute("UPDATE accounts SET is_active = '0' WHERE id = $1;", [

View File

@ -35,7 +35,8 @@ export function SettingsLayout() {
</div>
<div className="flex items-center gap-0.5">
<NavLink
to="/settings/"
to="/settings"
end
className={({ isActive }) =>
twMerge(
'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 text-neutral-700 hover:bg-neutral-100 dark:text-neutral-300 dark:hover:bg-neutral-900',