diff --git a/README.md b/README.md index 7313f03..5850bc9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Ditchcord +# Zep -Ditchcord is a self-hosted, privacy-oriented chat application built with **Svelte 5** and **SpacetimeDB**. Designed as a modern, lightweight alternative to commercial platforms, it prioritizes performance, low-latency communication, and high feature density without the bloat. +Zep is a self-hosted, privacy-oriented chat application built with **Svelte 5** and **SpacetimeDB**. Designed as a modern, lightweight alternative to commercial platforms, it prioritizes performance, low-latency communication, and high feature density without the bloat. ## πŸš€ Features -Ditchcord offers a rich, Discord-inspired user experience backed by a highly scalable, WebAssembly-powered database architecture. +Zep offers a rich, Discord-inspired user experience backed by a highly scalable, WebAssembly-powered database architecture. * **Multi-Server & Channel Support:** Organize your communities with dedicated Text, Voice, and Threaded channels. * **Blazing Fast Pagination:** Uses a sophisticated hybrid "Recent Activity Cache" to load channels instantly, with on-demand expansion for deep history scrollback. @@ -15,7 +15,7 @@ Ditchcord offers a rich, Discord-inspired user experience backed by a highly sca ## πŸ—ΊοΈ Roadmap -We are actively developing Ditchcord. Here is what's coming next: +We are actively developing Zep. Here is what's coming next: * [ ] **Direct Messaging:** Private, 1-on-1 conversations outside of server contexts. * [ ] **Mentions & Notifications:** Robust `@user` and `@role` tagging with RLS-protected notification delivery. @@ -32,7 +32,7 @@ We are actively developing Ditchcord. Here is what's coming next: * **Desktop:** Tauri (Planned/Configured) ### Architecture Highlights -Ditchcord leverages **SpacetimeDB's client-side cache model** to eliminate traditional REST API bottlenecks. +Zep leverages **SpacetimeDB's client-side cache model** to eliminate traditional REST API bottlenecks. * **Zero-Latency Switching:** The client subscribes to a lightweight `recent_message` table for all joined servers on startup. This populates the UI instantly when switching channels. * **Surgical Subscriptions:** The heavy `message` history table is only subscribed to on-demand when a user explicitly requests older messages, saving bandwidth and memory. * **WASM Reducers:** All database mutations (sending messages, updating profiles) are handled by deterministic TypeScript reducers compiled to WebAssembly and executed transactionally on the server. @@ -56,7 +56,7 @@ Ditchcord leverages **SpacetimeDB's client-side cache model** to eliminate tradi ``` 3. Publish the module to your SpacetimeDB instance (e.g., `maincloud` or a local instance). *Note: The first publish creates the database.* ```bash - spacetime publish --server maincloud ditchcord + spacetime publish --server maincloud zep ``` 4. Generate the TypeScript bindings for the frontend: ```bash @@ -76,7 +76,7 @@ Ditchcord leverages **SpacetimeDB's client-side cache model** to eliminate tradi 3. Configure your environment variables (create a `.env.local` file if necessary) to point to your published SpacetimeDB instance: ```env VITE_SPACETIMEDB_HOST=wss://maincloud.spacetimedb.com - VITE_SPACETIMEDB_DB_NAME=ditchcord + VITE_SPACETIMEDB_DB_NAME=zep ``` 4. Run the development server: ```bash diff --git a/index.html b/index.html index 00285f2..4f803da 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Ditchcord + Zep
diff --git a/package.json b/package.json index c49b736..371a757 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "ditchcord", + "name": "zep", "private": true, "version": "0.0.1", "type": "module", diff --git a/public/vite.svg b/public/vite.svg index e7b8dfb..7a1777e 100644 --- a/public/vite.svg +++ b/public/vite.svg @@ -1 +1,15 @@ - \ No newline at end of file + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spacetimedb/package.json b/spacetimedb/package.json index fea99e4..76ae248 100644 --- a/spacetimedb/package.json +++ b/spacetimedb/package.json @@ -1,5 +1,5 @@ { - "name": "ditchcord", + "name": "zep", "license": "ISC", "type": "module", "scripts": { diff --git a/spacetimedb/src/index.ts b/spacetimedb/src/index.ts index 93af439..ba4e4df 100644 --- a/spacetimedb/src/index.ts +++ b/spacetimedb/src/index.ts @@ -1225,7 +1225,7 @@ export const init = spacetimedb.init((ctx) => { if (!hasServers) { const s = ctx.db.server.insert({ id: 0n, - name: "Ditchcord", + name: "Zep", owner: undefined, }); ctx.db.channel.insert({ diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b79314e..16d7a1c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -713,18 +713,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "ditchcord" -version = "0.1.0" -dependencies = [ - "log", - "serde", - "serde_json", - "tauri", - "tauri-build", - "tauri-plugin-log", -] - [[package]] name = "dlopen2" version = "0.8.2" @@ -5193,6 +5181,18 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zep" +version = "0.1.0" +dependencies = [ + "log", + "serde", + "serde_json", + "tauri", + "tauri-build", + "tauri-plugin-log", +] + [[package]] name = "zerocopy" version = "0.8.48" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 09305fc..8d64d88 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "ditchcord" +name = "zep" version = "0.1.0" -description = "ditchcord - self-hosted communication" +description = "zep - self-hosted communication" authors = ["Adam Lamers"] license = "" repository = "" @@ -11,7 +11,7 @@ rust-version = "1.77.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] -name = "ditchcord_lib" +name = "zep_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d07f8ca..444686e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -2,5 +2,5 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { - ditchcord_lib::run(); + zep_lib::run(); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7eb2fe7..1b28d97 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,8 +1,8 @@ { "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", - "productName": "ditchcord", + "productName": "zep", "version": "0.1.0", - "identifier": "com.ditchcord.chat", + "identifier": "com.zep.chat", "build": { "frontendDist": "../dist", "devUrl": "http://localhost:5173", @@ -12,7 +12,7 @@ "app": { "windows": [ { - "title": "Ditchcord", + "title": "Zep", "width": 800, "height": 600, "resizable": true, diff --git a/src/App.css b/src/App.css index 5a37615..d71fbf7 100644 --- a/src/App.css +++ b/src/App.css @@ -1,4 +1,114 @@ :root { + --server-sidebar-width: 72px; + --channel-sidebar-width: 240px; + --font-primary: + "gg sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + --font-display: + "gg sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + --font-code: + source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; + --status-positive: var(--status-positive); + --status-danger: var(--status-danger); + --status-warning: var(--status-warning); +} + +/* Premium Midnight Purple (Amethyst) */ +.theme-amethyst, :root { + --background-primary: #161126; + --background-secondary: #0f0a1a; + --background-tertiary: #0a0714; + --background-accent: #241b3d; + --header-primary: #f3eeff; + --text-normal: #e0d1f0; + --text-muted: #9a8cbb; + --interactive-normal: #b3a5d1; + --interactive-hover: #ffffff; + --brand: #9d4edd; + --brand-hover: #7b2cbf; + --background-modifier-hover: rgba(157, 78, 221, 0.15); + --background-modifier-active: rgba(157, 78, 221, 0.3); + --background-modifier-selected: rgba(157, 78, 221, 0.3); + --background-floating: #0a0714; +} + +/* Slate Cyan (Cyber) */ +.theme-cyan { + --background-primary: #121826; + --background-secondary: #0c111a; + --background-tertiary: #080c13; + --background-accent: #1f2937; + --header-primary: #f8fafc; + --text-normal: #cbd5e1; + --text-muted: #64748b; + --interactive-normal: #94a3b8; + --interactive-hover: #f1f5f9; + --brand: #00d2ff; + --brand-hover: #00a8cc; + --background-modifier-hover: rgba(0, 210, 255, 0.15); + --background-modifier-active: rgba(0, 210, 255, 0.3); + --background-modifier-selected: rgba(0, 210, 255, 0.3); + --background-floating: #080c13; +} + +/* Deep Sea Green (Emerald) */ +.theme-emerald { + --background-primary: #061a14; + --background-secondary: #04120e; + --background-tertiary: #020a08; + --background-accent: #0d2e24; + --header-primary: #e6fffa; + --text-normal: #b2f5ea; + --text-muted: #4e9a84; + --interactive-normal: #81e6d9; + --interactive-hover: #ffffff; + --brand: #10b981; + --brand-hover: #059669; + --background-modifier-hover: rgba(16, 185, 129, 0.15); + --background-modifier-active: rgba(16, 185, 129, 0.3); + --background-modifier-selected: rgba(16, 185, 129, 0.3); + --background-floating: #020a08; +} + +/* Crimson Rose (Rose) */ +.theme-rose { + --background-primary: #1a0a0f; + --background-secondary: #12060a; + --background-tertiary: #0a0305; + --background-accent: #2e0d16; + --header-primary: #fff5f7; + --text-normal: #fed7e2; + --text-muted: #9b4e64; + --interactive-normal: #fbb6ce; + --interactive-hover: #ffffff; + --brand: #f43f5e; + --brand-hover: #e11d48; + --background-modifier-hover: rgba(244, 63, 94, 0.15); + --background-modifier-active: rgba(244, 63, 94, 0.3); + --background-modifier-selected: rgba(244, 63, 94, 0.3); + --background-floating: #0a0305; +} + +/* Amber Gold (Amber) */ +.theme-amber { + --background-primary: #1a1405; + --background-secondary: #120e03; + --background-tertiary: #0a0802; + --background-accent: #2e240d; + --header-primary: #fffaf0; + --text-normal: #fef3c7; + --text-muted: #9a7b4e; + --interactive-normal: #fcd34d; + --interactive-hover: #ffffff; + --brand: #f59e0b; + --brand-hover: #d97706; + --background-modifier-hover: rgba(245, 158, 11, 0.15); + --background-modifier-active: rgba(245, 158, 11, 0.3); + --background-modifier-selected: rgba(245, 158, 11, 0.3); + --background-floating: #0a0802; +} + +/* Generic Dark (Standard) */ +.theme-dark { --background-primary: #313338; --background-secondary: #2b2d31; --background-tertiary: #1e1f22; @@ -10,23 +120,32 @@ --interactive-hover: #dbdee1; --brand: #5865f2; --brand-hover: #4752c4; - --server-sidebar-width: 72px; - --channel-sidebar-width: 240px; --background-modifier-hover: rgba(78, 80, 88, 0.3); --background-modifier-active: rgba(78, 80, 88, 0.6); --background-modifier-selected: rgba(78, 80, 88, 0.6); --background-floating: #1e1f22; - --status-positive: #23a559; - --status-danger: #f23f43; - --status-warning: #f0b232; - --font-primary: - "gg sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - --font-display: - "gg sans", "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; - --font-code: - source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } +/* Generic Light (Standard) */ +.theme-light { + --background-primary: #ffffff; + --background-secondary: #f2f3f5; + --background-tertiary: #e3e5e8; + --background-accent: #ebedef; + --header-primary: #060607; + --text-normal: #313338; + --text-muted: #5c6067; + --interactive-normal: #4e5058; + --interactive-hover: #060607; + --brand: #5865f2; + --brand-hover: #4752c4; + --background-modifier-hover: rgba(78, 80, 88, 0.1); + --background-modifier-active: rgba(78, 80, 88, 0.2); + --background-modifier-selected: rgba(78, 80, 88, 0.2); + --background-floating: #ffffff; +} + + body { margin: 0; font-family: var(--font-primary); @@ -173,7 +292,7 @@ body { } .server-dropdown-item.danger:hover { - background-color: #f23f43; + background-color: var(--status-danger); } .server-dropdown-item.muted { @@ -249,13 +368,14 @@ body { /* User Info Bar */ .user-info-bar { - background-color: #232428; + background-color: var(--background-tertiary); padding: 0 8px; display: flex; align-items: center; justify-content: space-between; height: 52px; flex-shrink: 0; + border-top: 1px solid rgba(255, 255, 255, 0.05); } .user-info-main { @@ -290,7 +410,7 @@ body { } .avatar.talking { - border: 2px solid #23a559; + border: 2px solid var(--status-positive); box-shadow: 0 0 0 2px rgba(35, 165, 89, 0.15); } @@ -365,7 +485,7 @@ body { } .avatar.talking { - border: 2px solid #23a559; + border: 2px solid var(--status-positive); box-shadow: 0 0 0 2px rgba(35, 165, 89, 0.15); } @@ -448,7 +568,7 @@ body { } .icon-btn.danger.active { - color: #f23f43; + color: var(--status-danger); } /* Main Content Area */ @@ -903,7 +1023,7 @@ body { } .video-tile.talking { - border-color: #23a559; + border-color: var(--status-positive); } .video-tile video { @@ -1107,7 +1227,7 @@ body { } .sharing-badge { - background-color: #f23f43; + background-color: var(--status-danger); color: white; font-size: 0.6rem; padding: 1px 4px; @@ -1152,18 +1272,18 @@ body { } .status-dot.green { - background-color: #23a559; + background-color: var(--status-positive); } .status-dot.yellow { - background-color: #f0b232; + background-color: var(--status-warning); } .status-dot.red { - background-color: #f23f43; + background-color: var(--status-danger); } .status-dot.grey { - background-color: #80848e; + background-color: var(--text-muted); } /* Connection Popover */ @@ -1212,13 +1332,13 @@ body { } .popover-status.green { - color: #23a559; + color: var(--status-positive); } .popover-status.yellow { - color: #f0b232; + color: var(--status-warning); } .popover-status.red { - color: #f23f43; + color: var(--status-danger); } .popover-info { @@ -1379,7 +1499,7 @@ body { } .btn-danger { - background-color: #f23f43; + background-color: var(--status-danger); color: white; border: none; padding: 8px 16px; @@ -1393,7 +1513,7 @@ body { } .btn-danger:hover { - background-color: #d83c3e; + background-color: var(--status-danger); } .btn-danger.small { @@ -1463,7 +1583,7 @@ body { } .login-error { - color: #fa777a; + color: var(--status-danger); background-color: rgba(250, 119, 122, 0.1); border: 1px solid rgba(250, 119, 122, 0.2); padding: 8px; @@ -1475,12 +1595,12 @@ body { /* Voice Connected Bar */ .voice-status-bar { - background-color: #232428; + background-color: var(--background-tertiary); padding: 8px; display: flex; justify-content: space-between; align-items: center; - border-top: 1px solid rgba(255, 255, 255, 0.1); + border-top: 1px solid rgba(255, 255, 255, 0.05); } .voice-info { @@ -1489,7 +1609,7 @@ body { } .voice-connected-text { - color: #23a559; + color: var(--status-positive); font-size: 0.8rem; font-weight: bold; } @@ -1500,7 +1620,7 @@ body { } .screen-share-btn { - background-color: #3f4147; + background-color: var(--background-accent); color: white; border: none; padding: 4px 12px; @@ -1512,15 +1632,15 @@ body { } .screen-share-btn:hover { - background-color: #4f5157; + background-color: var(--background-modifier-hover); } .screen-share-btn.active { - background-color: #f23f43; + background-color: var(--status-danger); } .screen-share-btn.active:hover { - background-color: #d83c3e; + opacity: 0.9; } .screen-share-controls { @@ -1564,11 +1684,12 @@ body { .context-menu { position: fixed; z-index: 3000; - background: #18191c; + background: var(--background-floating); border-radius: 4px; padding: 8px; min-width: 180px; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.24); + border: 1px solid rgba(255, 255, 255, 0.05); } .context-menu-header { @@ -1599,7 +1720,7 @@ body { } .context-menu-item:hover { - background: var(--primary); + background: var(--brand); color: white; } diff --git a/src/App.svelte b/src/App.svelte index 18bba29..8c0a120 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -2,15 +2,22 @@ import { AuthGate } from "./auth"; import { ChatContainer } from "./chat"; import { connectionState } from "./connection.svelte"; + import { themeService } from "./chat/services/theme.svelte"; import "./App.css"; let showServerSettings = $state(false); + // Apply theme class to body globally + $effect(() => { + const theme = themeService.theme; + document.body.className = `theme-${theme}`; + }); + function handleReconnect() { console.log("App: Reconnection requested. Reloading page..."); // If we are showing settings, we should keep showing them after reload if (showServerSettings) { - localStorage.setItem("ditchcord_changing_server", "true"); + localStorage.setItem("zep_changing_server", "true"); } window.location.reload(); } @@ -19,9 +26,9 @@ console.log("App: Setting showServerSettings to", val); showServerSettings = val; if (val) { - localStorage.setItem("ditchcord_changing_server", "true"); + localStorage.setItem("zep_changing_server", "true"); } else { - localStorage.removeItem("ditchcord_changing_server"); + localStorage.removeItem("zep_changing_server"); } } diff --git a/src/auth/AuthGate.svelte b/src/auth/AuthGate.svelte index 5935c57..b812a4f 100644 --- a/src/auth/AuthGate.svelte +++ b/src/auth/AuthGate.svelte @@ -29,7 +29,7 @@ isMaincloud = stdbHost === MAINCLOUD_URI || stdbHost === ""; if (isMaincloud) stdbHost = MAINCLOUD_URI; - const isChanging = localStorage.getItem("ditchcord_changing_server") === "true"; + const isChanging = localStorage.getItem("zep_changing_server") === "true"; if (isChanging) { isSettingsExpanded = true; userWantsToConnect = false; @@ -95,7 +95,7 @@ -

Ditchcord

+

Zep

Decentralized. Private. Fast.

@@ -183,7 +183,7 @@ id="stdb-db" type="text" bind:value={stdbDbName} - placeholder="ditchcord" + placeholder="zep" style="background-color: var(--background-tertiary); color: var(--text-normal); border: 1px solid var(--background-modifier-accent); border-radius: 4px; padding: 10px;" /> diff --git a/src/chat/components/ProfileModal.svelte b/src/chat/components/ProfileModal.svelte index b0b817e..5785be7 100644 --- a/src/chat/components/ProfileModal.svelte +++ b/src/chat/components/ProfileModal.svelte @@ -147,7 +147,7 @@ } .status-dot.green { background-color: var(--status-positive); } - .status-dot.grey { background-color: #80848e; } + .status-dot.grey { background-color: var(--text-muted); } .profile-info { display: flex; diff --git a/src/chat/components/ServerList.svelte b/src/chat/components/ServerList.svelte index 8a931b2..9135d92 100644 --- a/src/chat/components/ServerList.svelte +++ b/src/chat/components/ServerList.svelte @@ -29,7 +29,7 @@ + {/each} + + + +

Custom Emojis

Personalize your experience by uploading unique emojis. They'll be automatically optimized for the best performance.

@@ -120,6 +163,95 @@ line-height: 1.4; } + .theme-selection-container { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 16px; + margin-top: 16px; + } + + .theme-card { + background-color: var(--background-secondary); + border: 2px solid transparent; + border-radius: 8px; + padding: 12px; + cursor: pointer; + display: flex; + flex-direction: column; + gap: 12px; + transition: all 0.2s; + position: relative; + text-align: left; + } + + .theme-card:hover { + background-color: var(--background-modifier-hover); + border-color: var(--background-modifier-accent); + } + + .theme-card.active { + border-color: var(--theme-accent); + background-color: var(--background-modifier-selected); + } + + .theme-preview { + height: 60px; + background-color: var(--theme-bg); + border-radius: 4px; + display: flex; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.05); + } + + .theme-preview-sidebar { + width: 20px; + height: 100%; + background-color: rgba(0, 0, 0, 0.2); + border-right: 1px solid rgba(255, 255, 255, 0.05); + } + + .theme-preview-content { + flex: 1; + padding: 6px; + display: flex; + flex-direction: column; + gap: 4px; + } + + .theme-preview-header { + height: 6px; + width: 60%; + background-color: var(--theme-accent); + border-radius: 2px; + margin-bottom: 4px; + opacity: 0.8; + } + + .theme-preview-msg { + height: 4px; + width: 90%; + background-color: rgba(255, 255, 255, 0.1); + border-radius: 2px; + } + + .theme-preview-msg.short { + width: 50%; + } + + .theme-name { + font-size: 0.85rem; + font-weight: 600; + color: var(--text-normal); + } + + .theme-active-check { + position: absolute; + top: 8px; + right: 8px; + color: var(--theme-accent); + font-size: 1.1rem; + } + .emoji-management-container { background-color: var(--background-secondary); padding: 16px; diff --git a/src/chat/services/chat.svelte.ts b/src/chat/services/chat.svelte.ts index 74a71fd..c60c93f 100644 --- a/src/chat/services/chat.svelte.ts +++ b/src/chat/services/chat.svelte.ts @@ -5,7 +5,7 @@ import * as Types from "../../module_bindings/types"; import { getUsername, formatTime } from "../utils"; import { DatabaseService } from "./database.svelte"; import { NavigationService } from "./navigation.svelte"; -import { UIService } from "./ui.svelte"; +import { ThemeService, themeService } from "./theme.svelte"; import { AuthContextService } from "./auth-context.svelte"; import { MessagingService } from "./messaging.svelte"; import { VoiceService } from "./voice.svelte"; @@ -15,7 +15,7 @@ import { ServerManagementService } from "./server-management.svelte"; export class ChatService { #db: DatabaseService; #nav: NavigationService; - #ui: UIService; + #ui: ThemeService = themeService; #auth: AuthContextService; #msg: MessagingService; #voice: VoiceService; @@ -30,7 +30,7 @@ export class ChatService { this.identity = initialIdentity; this.#db = new DatabaseService(); - this.#ui = new UIService(); + // this.#ui = new ThemeService(); // Removed to use shared themeService this.#nav = new NavigationService(this.#db, () => this.identity); this.#auth = new AuthContextService(this.#db, () => this.identity); this.#msg = new MessagingService(this.#db, this.#nav, () => this.identity); diff --git a/src/chat/services/messaging.svelte.ts b/src/chat/services/messaging.svelte.ts index 493fe48..df8368b 100644 --- a/src/chat/services/messaging.svelte.ts +++ b/src/chat/services/messaging.svelte.ts @@ -95,7 +95,7 @@ export class MessagingService { } else { queries.push("SELECT * FROM custom_emoji"); queries.push("SELECT * FROM system_configuration"); - queries.push("SELECT * FROM server WHERE name = 'Ditchcord'"); + queries.push("SELECT * FROM server WHERE name = 'Zep'"); } let userQuery = "SELECT * FROM user WHERE online = true"; diff --git a/src/chat/services/ui.svelte.ts b/src/chat/services/theme.svelte.ts similarity index 72% rename from src/chat/services/ui.svelte.ts rename to src/chat/services/theme.svelte.ts index 820312f..9d1db58 100644 --- a/src/chat/services/ui.svelte.ts +++ b/src/chat/services/theme.svelte.ts @@ -1,6 +1,6 @@ import { SvelteMap } from "svelte/reactivity"; -export class UIService { +export class ThemeService { showCreateServerModal = $state(false); newServerName = $state(""); showCreateChannelModal = $state(false); @@ -16,6 +16,16 @@ export class UIService { viewingProfileUser = $state(null); userContextMenu = $state<{ x: number, y: number, user: any } | null>(null); + // Theme management + theme = $state(localStorage.getItem("zep_theme") || "dark"); + + setTheme(newTheme: string) { + this.theme = newTheme; + localStorage.setItem("zep_theme", newTheme); + } + // Track collapsed state of embeds by key: `${messageId}-${index}` embedCollapsedStates = new SvelteMap(); } + +export const themeService = new ThemeService(); diff --git a/src/config.ts b/src/config.ts index 24271be..67c22fd 100644 --- a/src/config.ts +++ b/src/config.ts @@ -41,7 +41,7 @@ export const getStdbHost = () => getEnv("VITE_SPACETIMEDB_HOST", "wss://maincloud.spacetimedb.com"); export const getStdbDbName = () => localStorage.getItem(DB_NAME_KEY) || - getEnv("VITE_SPACETIMEDB_DB_NAME", "ditchcord"); + getEnv("VITE_SPACETIMEDB_DB_NAME", "zep"); let _connection: DbConnection | null = null; export const getConnection = () => _connection; diff --git a/src/index.css b/src/index.css index 984f1b4..519ef7e 100644 --- a/src/index.css +++ b/src/index.css @@ -9,17 +9,17 @@ /* ----- Color Variables ----- */ :root { - --theme-color: #3dc373; - --theme-color-contrast: #08180e; - --textbox-color: #edfef4; + --theme-color: #9d4edd; + --theme-color-contrast: #ffffff; + --textbox-color: #241b3d; color-scheme: light dark; } @media (prefers-color-scheme: dark) { :root { - --theme-color: #4cf490; - --theme-color-contrast: #132219; - --textbox-color: #0f311d; + --theme-color: #9d4edd; + --theme-color-contrast: #ffffff; + --textbox-color: #0a0714; } } diff --git a/src/main.ts b/src/main.ts index afbe366..7cb06f5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,7 +4,7 @@ import "@fortawesome/fontawesome-free/css/all.min.css"; import "./index.css"; import App from "./App.svelte"; -console.log("Ditchcord: Starting app..."); +console.log("Zep: Starting app..."); const app = mount(App, { target: document.getElementById("root")!, diff --git a/wrangler.jsonc b/wrangler.jsonc index 71e1dc5..3d88e07 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -1,6 +1,6 @@ { "$schema": "node_modules/wrangler/config-schema.json", - "name": "ditchcord", + "name": "zep", "compatibility_date": "2026-04-04", "observability": { "enabled": true,