diff --git a/package.json b/package.json
index e1145ae2..e9221f5c 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-hover-card": "^1.0.7",
"@radix-ui/react-popover": "^1.0.7",
+ "@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-toolbar": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@tanstack/react-query": "^5.8.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ad849d0a..64394c64 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -38,6 +38,9 @@ dependencies:
'@radix-ui/react-popover':
specifier: ^1.0.7
version: 1.0.7(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-switch':
+ specifier: ^1.0.3
+ version: 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-toolbar':
specifier: ^1.0.4
version: 1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0)
@@ -1438,6 +1441,33 @@ packages:
react: 18.2.0
dev: false
+ /@radix-ui/react-switch@1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.2
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.37)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.37)(react@18.2.0)
+ '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.37)(react@18.2.0)
+ '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.37)(react@18.2.0)
+ '@types/react': 18.2.37
+ '@types/react-dom': 18.2.15
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@radix-ui/react-toggle-group@1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-Uaj/M/cMyiyT9Bx6fOZO0SAG4Cls0GptBWiBmBxofmDbNVnYYoyRWj/2M/6VCi/7qcXFWnHhRUfdfZFvvkuu8A==}
peerDependencies:
@@ -1605,6 +1635,20 @@ packages:
react: 18.2.0
dev: false
+ /@radix-ui/react-use-previous@1.0.1(@types/react@18.2.37)(react@18.2.0):
+ resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.2
+ '@types/react': 18.2.37
+ react: 18.2.0
+ dev: false
+
/@radix-ui/react-use-rect@1.0.1(@types/react@18.2.37)(react@18.2.0):
resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==}
peerDependencies:
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index f6604e5d..ca452531 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -2612,7 +2612,7 @@ dependencies = [
[[package]]
name = "lume"
-version = "2.0.1"
+version = "2.1.0"
dependencies = [
"keyring",
"serde",
diff --git a/src/app/settings/about.tsx b/src/app/settings/about.tsx
index 166794bc..8bbbe597 100644
--- a/src/app/settings/about.tsx
+++ b/src/app/settings/about.tsx
@@ -1,3 +1,27 @@
+import { getVersion } from '@tauri-apps/api/app';
+import { useEffect, useState } from 'react';
+
export function AboutScreen() {
- return
;
+ const [version, setVersion] = useState('');
+
+ useEffect(() => {
+ async function loadVersion() {
+ const appVersion = await getVersion();
+ setVersion(appVersion);
+ }
+
+ loadVersion();
+ }, []);
+
+ return (
+
+
+

+
+
Lume
+
Version {version}
+
+
+
+ );
}
diff --git a/src/app/settings/advanced.tsx b/src/app/settings/advanced.tsx
index fb2d693d..8a5f8660 100644
--- a/src/app/settings/advanced.tsx
+++ b/src/app/settings/advanced.tsx
@@ -1,3 +1,26 @@
export function AdvancedSettingScreen() {
- return ;
+ return (
+
+
+
+
Event Caches
+
+
+
+
User Caches
+
+
+
+
+ );
}
diff --git a/src/app/settings/backup.tsx b/src/app/settings/backup.tsx
index b1c1c94b..c0748879 100644
--- a/src/app/settings/backup.tsx
+++ b/src/app/settings/backup.tsx
@@ -1,3 +1,37 @@
+import { useEffect, useState } from 'react';
+
+import { useStorage } from '@libs/storage/provider';
+
export function BackupSettingScreen() {
- return ;
+ const { db } = useStorage();
+ const [privkey, setPrivkey] = useState(null);
+
+ useEffect(() => {
+ async function loadPrivkey() {
+ const key = await db.secureLoad(db.account.pubkey);
+ if (key) setPrivkey(key);
+ }
+
+ loadPrivkey();
+ }, []);
+
+ return (
+
+
Private key
+
+ {!privkey ? (
+
+ You've stored private key on Lume
+
+ ) : (
+
+ )}
+
+
+ );
}
diff --git a/src/app/settings/general.tsx b/src/app/settings/general.tsx
index b6f089a9..0decafaf 100644
--- a/src/app/settings/general.tsx
+++ b/src/app/settings/general.tsx
@@ -1,3 +1,172 @@
+import * as Switch from '@radix-ui/react-switch';
+import { useEffect, useState } from 'react';
+
+import { useStorage } from '@libs/storage/provider';
+
+import { DarkIcon, LightIcon, SystemModeIcon } from '@shared/icons';
+
export function GeneralSettingScreen() {
- return ;
+ const { db } = useStorage();
+ const [settings, setSettings] = useState({
+ autolaunch: false,
+ outbox: false,
+ media: true,
+ hashtag: true,
+ notification: true,
+ appearance: 'system',
+ });
+
+ useEffect(() => {
+ async function loadSettings() {
+ 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,
+ }));
+
+ if (item.key === 'media')
+ setSettings((prev) => ({
+ ...prev,
+ media: item.value === '1' ? true : false,
+ }));
+
+ if (item.key === 'hashtag')
+ setSettings((prev) => ({
+ ...prev,
+ hashtag: item.value === '1' ? true : false,
+ }));
+
+ if (item.key === 'notification')
+ setSettings((prev) => ({
+ ...prev,
+ notification: item.value === '1' ? true : false,
+ }));
+
+ if (item.key === 'appearance')
+ setSettings((prev) => ({
+ ...prev,
+ appearance: item.value,
+ }));
+ });
+ }
+
+ loadSettings();
+ }, []);
+
+ return (
+
+
+
+
+
Startup
+
Launch Lume at Login
+
+
+
+
+
+
+
+
Gossip
+
Use Outbox model
+
+
+
+
+
+
+
+
Media
+
Automatically load media
+
+
+
+
+
+
+
+
Hashtag
+
Hide all hashtags in content
+
+
+
+
+
+
+
+
+ Notification
+
+
Automatically send notification
+
+
+
+
+
+
+
Appearance
+
+
+
+
+
+
+
+
+ );
}
diff --git a/src/libs/storage/instance.ts b/src/libs/storage/instance.ts
index 071e2555..58cef831 100644
--- a/src/libs/storage/instance.ts
+++ b/src/libs/storage/instance.ts
@@ -435,6 +435,14 @@ export class LumeStorage {
);
}
+ public async getAllSettings() {
+ const results: { key: string; value: string }[] = await this.db.select(
+ 'SELECT * FROM settings ORDER BY id DESC;'
+ );
+ if (results.length < 1) return null;
+ return results;
+ }
+
public async getSettingValue(key: string) {
const results: { key: string; value: string }[] = await this.db.select(
'SELECT * FROM settings WHERE key = $1 ORDER BY id DESC LIMIT 1;',
diff --git a/src/shared/icons/advancedSettings.tsx b/src/shared/icons/advancedSettings.tsx
new file mode 100644
index 00000000..cd804893
--- /dev/null
+++ b/src/shared/icons/advancedSettings.tsx
@@ -0,0 +1,24 @@
+import { SVGProps } from 'react';
+
+export function AdvancedSettingsIcon(
+ props: JSX.IntrinsicAttributes & SVGProps
+) {
+ return (
+
+ );
+}
diff --git a/src/shared/icons/dark.tsx b/src/shared/icons/dark.tsx
new file mode 100644
index 00000000..4bdaf2d3
--- /dev/null
+++ b/src/shared/icons/dark.tsx
@@ -0,0 +1,22 @@
+import { SVGProps } from 'react';
+
+export function DarkIcon(props: JSX.IntrinsicAttributes & SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/shared/icons/index.ts b/src/shared/icons/index.ts
index fc76dda2..2fd28a33 100644
--- a/src/shared/icons/index.ts
+++ b/src/shared/icons/index.ts
@@ -78,3 +78,9 @@ export * from './heading2';
export * from './heading3';
export * from './bold';
export * from './italic';
+export * from './user';
+export * from './advancedSettings';
+export * from './info';
+export * from './light';
+export * from './dark';
+export * from './system';
diff --git a/src/shared/icons/info.tsx b/src/shared/icons/info.tsx
new file mode 100644
index 00000000..b6a60a99
--- /dev/null
+++ b/src/shared/icons/info.tsx
@@ -0,0 +1,32 @@
+import { SVGProps } from 'react';
+
+export function InfoIcon(props: JSX.IntrinsicAttributes & SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/shared/icons/light.tsx b/src/shared/icons/light.tsx
new file mode 100644
index 00000000..119bde0f
--- /dev/null
+++ b/src/shared/icons/light.tsx
@@ -0,0 +1,22 @@
+import { SVGProps } from 'react';
+
+export function LightIcon(props: JSX.IntrinsicAttributes & SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/shared/icons/system.tsx b/src/shared/icons/system.tsx
new file mode 100644
index 00000000..3129eb8b
--- /dev/null
+++ b/src/shared/icons/system.tsx
@@ -0,0 +1,22 @@
+import { SVGProps } from 'react';
+
+export function SystemModeIcon(props: JSX.IntrinsicAttributes & SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/shared/icons/user.tsx b/src/shared/icons/user.tsx
new file mode 100644
index 00000000..7bb9eb67
--- /dev/null
+++ b/src/shared/icons/user.tsx
@@ -0,0 +1,21 @@
+import { SVGProps } from 'react';
+
+export function UserIcon(props: JSX.IntrinsicAttributes & SVGProps) {
+ return (
+
+ );
+}
diff --git a/src/shared/layouts/settings.tsx b/src/shared/layouts/settings.tsx
index 7280d4bb..f64972bb 100644
--- a/src/shared/layouts/settings.tsx
+++ b/src/shared/layouts/settings.tsx
@@ -1,10 +1,17 @@
-import { NavLink, Outlet, ScrollRestoration } from 'react-router-dom';
+import { Link, NavLink, Outlet, ScrollRestoration } from 'react-router-dom';
import { twMerge } from 'tailwind-merge';
import { WindowTitlebar } from 'tauri-controls';
import { useStorage } from '@libs/storage/provider';
-import { SecureIcon, SettingsIcon } from '@shared/icons';
+import {
+ AdvancedSettingsIcon,
+ ArrowLeftIcon,
+ InfoIcon,
+ SecureIcon,
+ SettingsIcon,
+ UserIcon,
+} from '@shared/icons';
export function SettingsLayout() {
const { db } = useStorage();
@@ -17,77 +24,88 @@ export function SettingsLayout() {
)}
-
-
- twMerge(
- 'flex w-20 shrink-0 flex-col items-center justify-center rounded-lg px-2 py-2 hover:bg-neutral-100 dark:hover:bg-neutral-900',
- isActive
- ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
- : ''
- )
- }
- >
-
- User
-
-
- 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',
- isActive
- ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
- : ''
- )
- }
- >
-
- General
-
-
- 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',
- isActive
- ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
- : ''
- )
- }
- >
-
- Backup
-
-
- 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',
- isActive
- ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
- : ''
- )
- }
- >
-
- Advanced
-
-
- 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',
- isActive
- ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
- : ''
- )
- }
- >
-
- About
-
+
+
+
+
+ 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',
+ isActive
+ ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
+ : ''
+ )
+ }
+ >
+
+ User
+
+
+ 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',
+ isActive
+ ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
+ : ''
+ )
+ }
+ >
+
+ General
+
+
+ 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',
+ isActive
+ ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
+ : ''
+ )
+ }
+ >
+
+ Backup
+
+
+ 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',
+ isActive
+ ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
+ : ''
+ )
+ }
+ >
+
+ Advanced
+
+
+ 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',
+ isActive
+ ? 'bg-neutral-100 text-blue-500 hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800'
+ : ''
+ )
+ }
+ >
+
+ About
+
+
+