mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-29 16:30:55 +00:00
feat: add theme switcher
This commit is contained in:
parent
4dc13385a5
commit
5ca9444358
@ -2,6 +2,7 @@ import { NostrQuery } from "@lume/system";
|
|||||||
import type { Settings } from "@lume/types";
|
import type { Settings } from "@lume/types";
|
||||||
import * as Switch from "@radix-ui/react-switch";
|
import * as Switch from "@radix-ui/react-switch";
|
||||||
import { createFileRoute } from "@tanstack/react-router";
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import { requestPermission } from "@tauri-apps/plugin-notification";
|
import { requestPermission } from "@tauri-apps/plugin-notification";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useDebouncedCallback } from "use-debounce";
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
@ -61,6 +62,19 @@ function Screen() {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeTheme = (theme: string) => {
|
||||||
|
if (theme === "auto" || theme === "light" || theme === "dark") {
|
||||||
|
invoke("plugin:theme|set_theme", {
|
||||||
|
theme: theme,
|
||||||
|
}).then(() =>
|
||||||
|
setNewSettings((prev) => ({
|
||||||
|
...prev,
|
||||||
|
theme,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const updateSettings = useDebouncedCallback(() => {
|
const updateSettings = useDebouncedCallback(() => {
|
||||||
NostrQuery.setSettings(newSettings);
|
NostrQuery.setSettings(newSettings);
|
||||||
}, 200);
|
}, 200);
|
||||||
@ -173,24 +187,42 @@ function Screen() {
|
|||||||
Interface
|
Interface
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex flex-col divide-y divide-black/10 dark:divide-white/10 bg-black/5 dark:bg-white/5 rounded-xl px-3">
|
<div className="flex flex-col divide-y divide-black/10 dark:divide-white/10 bg-black/5 dark:bg-white/5 rounded-xl px-3">
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex w-full items-start justify-between gap-4 py-3">
|
||||||
<div className="flex w-full items-start justify-between gap-4 py-3">
|
<div className="flex-1">
|
||||||
<div className="flex-1">
|
<h3 className="font-semibold">Zap</h3>
|
||||||
<h3 className="font-semibold">Zap</h3>
|
<p className="text-sm text-neutral-700 dark:text-neutral-300">
|
||||||
<p className="text-sm text-neutral-700 dark:text-neutral-300">
|
Show the Zap button in each note and user's profile screen,
|
||||||
Show the Zap button in each note and user's profile screen,
|
use for send bitcoin tip to other users.
|
||||||
use for send bitcoin tip to other users.
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
<div className="w-36 flex justify-end shrink-0">
|
||||||
<div className="w-36 flex justify-end shrink-0">
|
<Switch.Root
|
||||||
<Switch.Root
|
checked={newSettings.zap}
|
||||||
checked={newSettings.zap}
|
onClick={() => toggleZap()}
|
||||||
onClick={() => toggleZap()}
|
className="relative h-7 w-12 shrink-0 cursor-default rounded-full bg-black/10 outline-none data-[state=checked]:bg-blue-500 dark:bg-white/10"
|
||||||
className="relative h-7 w-12 shrink-0 cursor-default rounded-full bg-black/10 outline-none data-[state=checked]:bg-blue-500 dark:bg-white/10"
|
>
|
||||||
>
|
<Switch.Thumb className="block size-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
|
||||||
<Switch.Thumb className="block size-6 translate-x-0.5 rounded-full bg-white transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
|
</Switch.Root>
|
||||||
</Switch.Root>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex w-full items-start justify-between gap-4 py-3">
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="font-semibold">Appearance</h3>
|
||||||
|
<p className="text-sm text-neutral-700 dark:text-neutral-300">
|
||||||
|
* Require restarting the app to take effect.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="w-36 flex justify-end shrink-0">
|
||||||
|
<select
|
||||||
|
name="theme"
|
||||||
|
className="bg-transparent shadow-none outline-none rounded-lg border-1 border-black/10 dark:border-white/10 py-1 w-24"
|
||||||
|
defaultValue={settings.theme}
|
||||||
|
onChange={(e) => changeTheme(e.target.value)}
|
||||||
|
>
|
||||||
|
<option value="auto">Auto</option>
|
||||||
|
<option value="light">Light</option>
|
||||||
|
<option value="dark">Dark</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ import { readFile, readTextFile } from "@tauri-apps/plugin-fs";
|
|||||||
import { isPermissionGranted } from "@tauri-apps/plugin-notification";
|
import { isPermissionGranted } from "@tauri-apps/plugin-notification";
|
||||||
import { open } from "@tauri-apps/plugin-dialog";
|
import { open } from "@tauri-apps/plugin-dialog";
|
||||||
import { dedupEvents } from "./dedup";
|
import { dedupEvents } from "./dedup";
|
||||||
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
|
|
||||||
enum NSTORE_KEYS {
|
enum NSTORE_KEYS {
|
||||||
settings = "lume_user_settings",
|
settings = "lume_user_settings",
|
||||||
@ -201,8 +202,11 @@ export class NostrQuery {
|
|||||||
if (query.status === "ok") {
|
if (query.status === "ok") {
|
||||||
const settings: Settings = query.data ? JSON.parse(query.data) : null;
|
const settings: Settings = query.data ? JSON.parse(query.data) : null;
|
||||||
const isGranted = await isPermissionGranted();
|
const isGranted = await isPermissionGranted();
|
||||||
|
const theme: "auto" | "light" | "dark" = await invoke(
|
||||||
|
"plugin:theme|get_theme",
|
||||||
|
);
|
||||||
|
|
||||||
return { ...settings, notification: isGranted };
|
return { ...settings, theme, notification: isGranted };
|
||||||
} else {
|
} else {
|
||||||
const initial: Settings = {
|
const initial: Settings = {
|
||||||
autoUpdate: false,
|
autoUpdate: false,
|
||||||
@ -210,6 +214,8 @@ export class NostrQuery {
|
|||||||
notification: false,
|
notification: false,
|
||||||
zap: false,
|
zap: false,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
gossip: false,
|
||||||
|
theme: "auto",
|
||||||
};
|
};
|
||||||
|
|
||||||
return initial;
|
return initial;
|
||||||
|
1
packages/types/index.d.ts
vendored
1
packages/types/index.d.ts
vendored
@ -5,6 +5,7 @@ export interface Settings {
|
|||||||
zap: boolean;
|
zap: boolean;
|
||||||
nsfw: boolean;
|
nsfw: boolean;
|
||||||
gossip: boolean;
|
gossip: boolean;
|
||||||
|
theme: "auto" | "light" | "dark";
|
||||||
[key: string]: string | number | boolean;
|
[key: string]: string | number | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
src-tauri/Cargo.lock
generated
29
src-tauri/Cargo.lock
generated
@ -2907,6 +2907,7 @@ dependencies = [
|
|||||||
"tauri-plugin-os",
|
"tauri-plugin-os",
|
||||||
"tauri-plugin-process",
|
"tauri-plugin-process",
|
||||||
"tauri-plugin-shell",
|
"tauri-plugin-shell",
|
||||||
|
"tauri-plugin-theme",
|
||||||
"tauri-plugin-updater",
|
"tauri-plugin-updater",
|
||||||
"tauri-plugin-upload",
|
"tauri-plugin-upload",
|
||||||
"tauri-plugin-window-state",
|
"tauri-plugin-window-state",
|
||||||
@ -5514,6 +5515,24 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-plugin-theme"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c23856e93f56cd8d1868e7dd8a4b529b836fd5da315cefd7702b252a850cdf5a"
|
||||||
|
dependencies = [
|
||||||
|
"cocoa",
|
||||||
|
"dirs-next",
|
||||||
|
"futures-lite 2.3.0",
|
||||||
|
"gtk",
|
||||||
|
"once_cell",
|
||||||
|
"serde",
|
||||||
|
"tauri",
|
||||||
|
"tauri-plugin",
|
||||||
|
"tintanum",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-updater"
|
name = "tauri-plugin-updater"
|
||||||
version = "2.0.0-beta.5"
|
version = "2.0.0-beta.5"
|
||||||
@ -5805,6 +5824,16 @@ dependencies = [
|
|||||||
"time-core",
|
"time-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tintanum"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7abbcf9173afc80733c20b7e27a30bc9284d6535bdbde2a70904032de63e16e8"
|
||||||
|
dependencies = [
|
||||||
|
"futures-lite 1.13.0",
|
||||||
|
"zbus 3.15.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -39,6 +39,7 @@ keyring = "2"
|
|||||||
keyring-search = "0.2.0"
|
keyring-search = "0.2.0"
|
||||||
specta = "=2.0.0-rc.12"
|
specta = "=2.0.0-rc.12"
|
||||||
tauri-specta = { version = "=2.0.0-rc.10", features = ["typescript"] }
|
tauri-specta = { version = "=2.0.0-rc.10", features = ["typescript"] }
|
||||||
|
tauri-plugin-theme = "0.4.1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
cocoa = "0.25.0"
|
cocoa = "0.25.0"
|
||||||
|
@ -56,6 +56,8 @@
|
|||||||
"dialog:allow-message",
|
"dialog:allow-message",
|
||||||
"process:allow-restart",
|
"process:allow-restart",
|
||||||
"fs:allow-read-file",
|
"fs:allow-read-file",
|
||||||
|
"theme:allow-set-theme",
|
||||||
|
"theme:allow-get-theme",
|
||||||
"shell:allow-open",
|
"shell:allow-open",
|
||||||
{
|
{
|
||||||
"identifier": "http:default",
|
"identifier": "http:default",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","local":true,"windows":["main","splash","settings","search","nwc","activity","zap-*","event-*","user-*","editor-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","os:allow-os-type","updater:default","updater:allow-check","updater:allow-download-and-install","window:allow-start-dragging","window:allow-create","window:allow-close","window:allow-set-focus","window:allow-center","window:allow-minimize","window:allow-maximize","window:allow-set-size","window:allow-set-focus","window:allow-start-dragging","decorum:allow-show-snap-overlay","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","webview:allow-create-webview-window","webview:allow-create-webview","webview:allow-set-webview-size","webview:allow-set-webview-position","webview:allow-webview-close","dialog:allow-open","dialog:allow-ask","dialog:allow-message","process:allow-restart","fs:allow-read-file","shell:allow-open",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"},{"path":"$RESOURCE/resources/*"}]}],"platforms":["linux","macOS","windows"]}}
|
{"desktop-capability":{"identifier":"desktop-capability","description":"Capability for the desktop","local":true,"windows":["main","splash","settings","search","nwc","activity","zap-*","event-*","user-*","editor-*","column-*"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","notification:allow-is-permission-granted","notification:allow-request-permission","notification:default","os:allow-locale","os:allow-platform","os:allow-os-type","updater:default","updater:allow-check","updater:allow-download-and-install","window:allow-start-dragging","window:allow-create","window:allow-close","window:allow-set-focus","window:allow-center","window:allow-minimize","window:allow-maximize","window:allow-set-size","window:allow-set-focus","window:allow-start-dragging","decorum:allow-show-snap-overlay","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","webview:allow-create-webview-window","webview:allow-create-webview","webview:allow-set-webview-size","webview:allow-set-webview-position","webview:allow-webview-close","dialog:allow-open","dialog:allow-ask","dialog:allow-message","process:allow-restart","fs:allow-read-file","theme:allow-set-theme","theme:allow-get-theme","shell:allow-open",{"identifier":"http:default","allow":[{"url":"http://**/"},{"url":"https://**/"}]},{"identifier":"fs:allow-read-text-file","allow":[{"path":"$RESOURCE/locales/*"},{"path":"$RESOURCE/resources/*"}]}],"platforms":["linux","macOS","windows"]}}
|
@ -5654,6 +5654,40 @@
|
|||||||
"shell:deny-stdin-write"
|
"shell:deny-stdin-write"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:default"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:allow-get-theme -> Enables the get_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:allow-get-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:allow-set-theme -> Enables the set_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:allow-set-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:deny-get-theme -> Denies the get_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:deny-get-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:deny-set-theme -> Denies the set_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:deny-set-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "tray:default -> Default permissions for the plugin.",
|
"description": "tray:default -> Default permissions for the plugin.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -5654,6 +5654,40 @@
|
|||||||
"shell:deny-stdin-write"
|
"shell:deny-stdin-write"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:default"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:allow-get-theme -> Enables the get_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:allow-get-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:allow-set-theme -> Enables the set_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:allow-set-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:deny-get-theme -> Denies the get_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:deny-get-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "theme:deny-set-theme -> Denies the set_theme command without any pre-configured scope.",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"theme:deny-set-theme"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "tray:default -> Default permissions for the plugin.",
|
"description": "tray:default -> Default permissions for the plugin.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -24,6 +24,7 @@ pub struct Nostr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let mut ctx = tauri::generate_context!();
|
||||||
let invoke_handler = {
|
let invoke_handler = {
|
||||||
let builder = tauri_specta::ts::builder().commands(tauri_specta::collect_commands![
|
let builder = tauri_specta::ts::builder().commands(tauri_specta::collect_commands![
|
||||||
nostr::relay::get_relays,
|
nostr::relay::get_relays,
|
||||||
@ -135,13 +136,7 @@ fn main() {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.on_window_event(|window, event| match event {
|
.plugin(tauri_plugin_theme::init(ctx.config_mut()))
|
||||||
tauri::WindowEvent::CloseRequested { api, .. } => {
|
|
||||||
window.hide().unwrap();
|
|
||||||
api.prevent_close();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
})
|
|
||||||
.plugin(tauri_plugin_decorum::init())
|
.plugin(tauri_plugin_decorum::init())
|
||||||
.plugin(tauri_plugin_clipboard_manager::init())
|
.plugin(tauri_plugin_clipboard_manager::init())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
@ -154,6 +149,6 @@ fn main() {
|
|||||||
.plugin(tauri_plugin_upload::init())
|
.plugin(tauri_plugin_upload::init())
|
||||||
.plugin(tauri_plugin_updater::Builder::new().build())
|
.plugin(tauri_plugin_updater::Builder::new().build())
|
||||||
.invoke_handler(invoke_handler)
|
.invoke_handler(invoke_handler)
|
||||||
.run(tauri::generate_context!())
|
.run(ctx)
|
||||||
.expect("error while running tauri application")
|
.expect("error while running tauri application")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user