diff --git a/package.json b/package.json index ae2d9fb..18bdf03 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@tauri-apps/plugin-fs": "~2", "@tauri-apps/plugin-http": "~2", "@tauri-apps/plugin-opener": "^2", + "@tauri-apps/plugin-os": "~2", "@tauri-apps/plugin-store": "~2", "@tauri-apps/plugin-upload": "~2", "@tauri-apps/plugin-websocket": "~2", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 59da5d0..b9b59dd 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1028,6 +1028,7 @@ dependencies = [ "tauri-plugin-fs", "tauri-plugin-http", "tauri-plugin-opener", + "tauri-plugin-os", "tauri-plugin-store", "tauri-plugin-upload", "tauri-plugin-websocket", @@ -1263,6 +1264,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix", + "windows-link 0.2.1", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -2315,6 +2326,16 @@ dependencies = [ "objc2-foundation", ] +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2", + "objc2-foundation", +] + [[package]] name = "objc2-core-text" version = "0.3.2" @@ -2419,8 +2440,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.10.0", + "block2", "objc2", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", "objc2-foundation", ] @@ -2474,6 +2514,22 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_info" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" +dependencies = [ + "android_system_properties", + "log", + "nix", + "objc2", + "objc2-foundation", + "objc2-ui-kit", + "serde", + "windows-sys 0.61.2", +] + [[package]] name = "pango" version = "0.18.3" @@ -3782,6 +3838,15 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + [[package]] name = "system-configuration" version = "0.6.1" @@ -4091,6 +4156,24 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-os" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f08346c8deb39e96f86973da0e2d76cbb933d7ac9b750f6dc4daf955a6f997" +dependencies = [ + "gethostname", + "log", + "os_info", + "serde", + "serde_json", + "serialize-to-javascript", + "sys-locale", + "tauri", + "tauri-plugin", + "thiserror 2.0.17", +] + [[package]] name = "tauri-plugin-store" version = "2.4.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index da263e6..1720d65 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -28,4 +28,5 @@ tauri-plugin-websocket = "2" tauri-plugin-upload = "2" tauri-plugin-dialog = "2" tauri-plugin-fs = "2" +tauri-plugin-os = "2" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 89710eb..628361f 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -7,6 +7,12 @@ ], "permissions": [ "core:default", + "core:window:allow-maximize", + "core:window:allow-minimize", + "core:window:allow-close", + "core:window:allow-toggle-maximize", + "core:window:allow-start-dragging", + "core:window:allow-set-fullscreen", "opener:default", "store:default", { @@ -47,7 +53,7 @@ "allow": [ "*" ] - } + }, + "os:default" ] -} - +} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 5a3f2b6..a46662f 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -7,6 +7,7 @@ fn greet(name: &str) -> String { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_upload::init()) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8141a53..f6f46f4 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -15,7 +15,7 @@ "title": "frangipane", "width": 800, "height": 600, - "decorations": true, + "decorations": false, "resizable": true, "fullscreen": false, "center": true, diff --git a/src/App.vue b/src/App.vue index 1a5cd7e..1cb61cf 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,16 +1,35 @@ diff --git a/src/base.css b/src/base.css index 042e927..c699847 100644 --- a/src/base.css +++ b/src/base.css @@ -16,6 +16,7 @@ body, overflow-y: hidden; } +/* This is overwritten by the theme configuration */ :root { --bg: #0f1116; --panel: #171922; @@ -23,6 +24,7 @@ body, --text: #e6e6eb; --muted: #9aa0aa; --accent: #f27aa3; + --accent-rgb: 242, 122, 163; --accent-hover: #ff91b3; --accent-second: #96CDFB; --border: #2a2f3b; @@ -30,6 +32,10 @@ body, --radius: 8px; } +* { + transition: background-color 0.2s ease, border-color 0.2s ease; +} + body { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; @@ -59,7 +65,8 @@ input:focus, textarea:focus { button, .button { font-size: 1rem; background: var(--accent); - color: #0b0d12; + color: var(--bg); + /* color: var(--btn-text); */ border: none; border-radius: var(--radius); padding: 0.6rem 1rem; @@ -74,6 +81,19 @@ button:hover, .button:hover { background: var(--accent-hover); } +.secondary { + background: transparent; + color: var(--text); + border: 1px solid var(--border); + padding: 8px 16px; + border-radius: var(--radius); + cursor: pointer; +} + +.secondary:hover { + background: var(--panel-hover); +} + input[type="checkbox"] { appearance: none; -webkit-appearance: none; diff --git a/src/components/ChatWindow.vue b/src/components/ChatWindow.vue index d78c8fe..8cbac44 100644 --- a/src/components/ChatWindow.vue +++ b/src/components/ChatWindow.vue @@ -347,7 +347,7 @@ async function onSend(content: string) { border-radius: var(--radius); border: none; background: transparent; - color: white; + color: var(--text); cursor: pointer; font-size: 1.6rem; @@ -386,7 +386,7 @@ async function onSend(content: string) { } .retry-btn:hover { - background: rgba(255, 255, 255, 0.05); + background: var(--panel-hover); } .no-room { diff --git a/src/components/ConfirmModal.vue b/src/components/ConfirmModal.vue index 6d7bc1d..8ec6947 100644 --- a/src/components/ConfirmModal.vue +++ b/src/components/ConfirmModal.vue @@ -76,15 +76,6 @@ const emit = defineEmits(['yes', 'no']); color: var(--text); } -.secondary { - cursor: pointer; - padding: 8px 16px; - border-radius: var(--radius); - background: transparent; - color: var(--text); - border: 1px solid var(--border); -} - .btn-danger { border-color: var(--error); color: var(--error); diff --git a/src/components/CreateRoomModal.vue b/src/components/CreateRoomModal.vue index 4f79115..245d8c0 100644 --- a/src/components/CreateRoomModal.vue +++ b/src/components/CreateRoomModal.vue @@ -92,14 +92,4 @@ async function submit() { justify-content: flex-end; gap: 0.5rem; } - -.secondary { - background: transparent; - color: var(--text); - border: 1px solid var(--border); -} - -.secondary:hover { - background: rgba(255, 255, 255, 0.05); -} diff --git a/src/components/InvitePeopleModal.vue b/src/components/InvitePeopleModal.vue index 6ba2da2..fc1f5bd 100644 --- a/src/components/InvitePeopleModal.vue +++ b/src/components/InvitePeopleModal.vue @@ -120,14 +120,4 @@ async function submit() { justify-content: flex-end; gap: 0.5rem; } - -.secondary { - background: transparent; - color: var(--text); - border: 1px solid var(--border); -} - -.secondary:hover { - background: rgba(255, 255, 255, 0.05); -} diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue index fe66ae5..f829d1c 100644 --- a/src/components/Navbar.vue +++ b/src/components/Navbar.vue @@ -76,7 +76,7 @@ onMounted(() => { top: 4px; right: 4px; background-color: var(--accent); - color: black; + color: var(--bg); font-size: 0.65rem; font-weight: bold; min-width: 18px; @@ -92,7 +92,7 @@ onMounted(() => { @media (hover: hover) { .nav-item:hover { - background: rgba(255, 255, 255, 0.04); + background: var(--panel-hover); } .nav-item:not(.router-link-active):hover i { diff --git a/src/components/RoomDetailsModal.vue b/src/components/RoomDetailsModal.vue index 82db27b..5525eff 100644 --- a/src/components/RoomDetailsModal.vue +++ b/src/components/RoomDetailsModal.vue @@ -205,15 +205,6 @@ const handleAvatarError = (event: Event) => { gap: 0.5rem; } -.secondary { - background: transparent; - color: var(--text); - border: 1px solid var(--border); - padding: 8px 16px; - border-radius: var(--radius); - cursor: pointer; -} - .member-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); diff --git a/src/components/RoomList.vue b/src/components/RoomList.vue index 09d9250..83e5b4f 100644 --- a/src/components/RoomList.vue +++ b/src/components/RoomList.vue @@ -138,7 +138,7 @@ onMounted(async () => { } .retry-btn:hover { - background: rgba(255, 255, 255, 0.05); + background: var(--panel-hover); } .room-content-wrapper { @@ -150,7 +150,7 @@ onMounted(async () => { .unread-badge { background-color: var(--accent); - color: black; + color: var(--bg); font-size: 0.75rem; font-weight: bold; min-width: 20px; @@ -193,7 +193,7 @@ onMounted(async () => { } .room-item:hover { - background: rgba(255, 255, 255, 0.05); + background: var(--panel-hover); color: var(--text); } @@ -236,6 +236,6 @@ onMounted(async () => { } .create-btn:hover { - background: rgba(255, 255, 255, 0.05); + background: var(--panel-hover); } diff --git a/src/components/UpdateAccountModal.vue b/src/components/UpdateAccountModal.vue index e55667c..3769acf 100644 --- a/src/components/UpdateAccountModal.vue +++ b/src/components/UpdateAccountModal.vue @@ -112,7 +112,6 @@ async function submit() { display: flex; flex-direction: column; gap: 1.2rem; - box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); } .subtitle { @@ -154,10 +153,4 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } - -.secondary { - background: transparent; - color: var(--text); - border: 1px solid var(--border); -} diff --git a/src/components/UploadAvatarModal.vue b/src/components/UploadAvatarModal.vue index 17a2840..50f1a34 100644 --- a/src/components/UploadAvatarModal.vue +++ b/src/components/UploadAvatarModal.vue @@ -202,7 +202,7 @@ async function handleUpload() { text-align: center; cursor: pointer; transition: all 0.2s ease; - background: rgba(255, 255, 255, 0.02); + background: var(--panel-accent); min-height: 180px; display: flex; align-items: center; @@ -221,7 +221,7 @@ async function handleUpload() { .drop-zone:hover { border-color: var(--accent); - background: rgba(255, 255, 255, 0.05); + background: var(--panel-hover); } .drop-content i { @@ -299,10 +299,4 @@ async function handleUpload() { justify-content: flex-end; gap: 0.5rem; } - -.secondary { - background: transparent; - color: var(--text); - border: 1px solid var(--border); -} diff --git a/src/components/VersionWarningModal.vue b/src/components/VersionWarningModal.vue index 8f9527b..c9f02c3 100644 --- a/src/components/VersionWarningModal.vue +++ b/src/components/VersionWarningModal.vue @@ -49,10 +49,4 @@ const emit = defineEmits(['close']); justify-content: flex-end; gap: 0.5rem; } - -.secondary { - background: transparent; - color: var(--text); - border: 1px solid var(--border); -} diff --git a/src/locales/en.ftl b/src/locales/en.ftl index 159529f..f922dc1 100644 --- a/src/locales/en.ftl +++ b/src/locales/en.ftl @@ -79,6 +79,7 @@ settings-loading = Loading settings... settings-title = Settings settings-account = Account settings-language = Language +settings-appearance = Appearance settings-label-username = Username: settings-label-email = Email: settings-update-btn = Update diff --git a/src/locales/fr.ftl b/src/locales/fr.ftl index bcbc253..3a46467 100644 --- a/src/locales/fr.ftl +++ b/src/locales/fr.ftl @@ -79,6 +79,7 @@ settings-loading = Chargement des paramètres... settings-title = Paramètres settings-account = Compte settings-language = Langue +settings-appearance = Apparence settings-label-username = Nom d'utilisateur : settings-label-email = Email : settings-update-btn = Modifier diff --git a/src/main.ts b/src/main.ts index 7749ca1..dfdaece 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,7 @@ import { createApp } from 'vue' import router from './router.ts' import App from './App.vue' -import { validateToken } from './store.ts' +import { validateToken, initTheme } from './store.ts' import { fluent, setLanguage } from './i18n' import './base.css' @@ -17,6 +17,8 @@ async function init() { const savedLocale = await getLocalePreference(); const osLocale = navigator.language; + await initTheme(); + if (savedLocale) { setLanguage(savedLocale); } else { diff --git a/src/pages/ChatPage.vue b/src/pages/ChatPage.vue index df1ac65..52f7239 100644 --- a/src/pages/ChatPage.vue +++ b/src/pages/ChatPage.vue @@ -43,7 +43,7 @@ const handleRoomAction = async () => { await roomListRef.value.refreshRooms(); } - router.push('/rooms/none'); + router.push('/rooms/none'); }; const handleNotification = (roomUuid: string) => { @@ -152,7 +152,7 @@ const handleNotification = (roomUuid: string) => { .sidebar-overlay { position: absolute; inset: 0; - background: rgba(0, 0, 0, 0.3); + /* background: rgba(0, 0, 0, 0.3); */ z-index: 15; } diff --git a/src/pages/NotificationsPage.vue b/src/pages/NotificationsPage.vue index d892fd6..063a462 100644 --- a/src/pages/NotificationsPage.vue +++ b/src/pages/NotificationsPage.vue @@ -182,7 +182,7 @@ async function declineRoom(senderUuid: string, roomUuid: string) { } .decline-btn:hover { - background-color: rgba(255, 255, 255, 0.05); + background-color: var(--panel-hover); } @media (max-width: 720px) { diff --git a/src/pages/SettingsPage.vue b/src/pages/SettingsPage.vue index 8ae2f01..8378155 100644 --- a/src/pages/SettingsPage.vue +++ b/src/pages/SettingsPage.vue @@ -38,6 +38,14 @@ +

{{ $t('settings-appearance') || 'Appearance' }}

+
+ +
+