app menu window
This commit is contained in:
132
src/app.css
132
src/app.css
@@ -2,75 +2,77 @@
|
||||
@plugin "daisyui";
|
||||
|
||||
@plugin "daisyui/theme" {
|
||||
name: "proper";
|
||||
default: true;
|
||||
prefersdark: false;
|
||||
color-scheme: "light";
|
||||
--color-base-100: oklch(96% 0.001 286.375);
|
||||
--color-base-200: oklch(92% 0.004 286.32);
|
||||
--color-base-300: oklch(87% 0.006 286.286);
|
||||
--color-base-content: oklch(44% 0.017 285.786);
|
||||
--color-primary: oklch(71% 0.143 215.221);
|
||||
--color-primary-content: oklch(98% 0.019 200.873);
|
||||
--color-secondary: oklch(67% 0.182 276.935);
|
||||
--color-secondary-content: oklch(93% 0.034 272.788);
|
||||
--color-accent: oklch(93% 0.032 255.585);
|
||||
--color-accent-content: oklch(38% 0.063 188.416);
|
||||
--color-neutral: oklch(96% 0.001 286.375);
|
||||
--color-neutral-content: oklch(0% 0 0);
|
||||
--color-info: oklch(58% 0.158 241.966);
|
||||
--color-info-content: oklch(100% 0 0);
|
||||
--color-success: oklch(76% 0.233 130.85);
|
||||
--color-success-content: oklch(98% 0.031 120.757);
|
||||
--color-warning: oklch(66% 0.179 58.318);
|
||||
--color-warning-content: oklch(100% 0 0);
|
||||
--color-error: oklch(70% 0.191 22.216);
|
||||
--color-error-content: oklch(100% 0 0);
|
||||
--radius-selector: 0.5rem;
|
||||
--radius-field: 0.5rem;
|
||||
--radius-box: 0.5rem;
|
||||
--size-selector: 0.25rem;
|
||||
--size-field: 0.25rem;
|
||||
--border: 1px;
|
||||
--depth: 1;
|
||||
--noise: 1;
|
||||
name: "proper";
|
||||
default: true;
|
||||
prefersdark: false;
|
||||
color-scheme: "light";
|
||||
--color-base-50: oklch(96% 0.001 286.375);
|
||||
--color-base-100: oklch(96% 0.001 286.375);
|
||||
--color-base-200: oklch(92% 0.004 286.32);
|
||||
--color-base-300: oklch(87% 0.006 286.286);
|
||||
--color-base-content: oklch(44% 0.017 285.786);
|
||||
--color-primary: oklch(71% 0.143 215.221);
|
||||
--color-primary-content: oklch(98% 0.019 200.873);
|
||||
--color-secondary: oklch(67% 0.182 276.935);
|
||||
--color-secondary-content: oklch(93% 0.034 272.788);
|
||||
--color-accent: oklch(93% 0.032 255.585);
|
||||
--color-accent-content: oklch(38% 0.063 188.416);
|
||||
--color-neutral: oklch(96% 0.001 286.375);
|
||||
--color-neutral-content: oklch(0% 0 0);
|
||||
--color-info: oklch(58% 0.158 241.966);
|
||||
--color-info-content: oklch(100% 0 0);
|
||||
--color-success: oklch(76% 0.233 130.85);
|
||||
--color-success-content: oklch(98% 0.031 120.757);
|
||||
--color-warning: oklch(66% 0.179 58.318);
|
||||
--color-warning-content: oklch(100% 0 0);
|
||||
--color-error: oklch(70% 0.191 22.216);
|
||||
--color-error-content: oklch(100% 0 0);
|
||||
--radius-selector: 0.25rem;
|
||||
--radius-field: 0.25rem;
|
||||
--radius-box: 0.25rem;
|
||||
--size-selector: 0.1875rem;
|
||||
--size-field: 0.1875rem;
|
||||
--border: 1px;
|
||||
--depth: 1;
|
||||
--noise: 1;
|
||||
}
|
||||
|
||||
@plugin "daisyui/theme" {
|
||||
name: "properdark";
|
||||
default: false;
|
||||
prefersdark: true;
|
||||
color-scheme: "dark";
|
||||
--color-base-100: oklch(26% 0 0);
|
||||
--color-base-200: oklch(37% 0 0);
|
||||
--color-base-300: oklch(43% 0 0);
|
||||
--color-base-content: oklch(100% 0 0);
|
||||
--color-primary: oklch(86% 0.127 207.078);
|
||||
--color-primary-content: oklch(39% 0.07 227.392);
|
||||
--color-secondary: oklch(87% 0.065 274.039);
|
||||
--color-secondary-content: oklch(35% 0.144 278.697);
|
||||
--color-accent: oklch(36.2% 0.076 265.6);
|
||||
--color-accent-content: oklch(97% 0.014 254.604);
|
||||
--color-neutral: oklch(37% 0.01 67.558);
|
||||
--color-neutral-content: oklch(100% 0 0);
|
||||
--color-info: oklch(64.4% 0.12 237.3);
|
||||
--color-info-content: oklch(100% 0 0);
|
||||
--color-success: oklch(76% 0.233 130.85);
|
||||
--color-success-content: oklch(0% 0 0);
|
||||
--color-warning: oklch(87% 0.169 91.605);
|
||||
--color-warning-content: oklch(0% 0 0);
|
||||
--color-error: oklch(63% 0.237 25.331);
|
||||
--color-error-content: oklch(100% 0 0);
|
||||
--radius-selector: 0.5rem;
|
||||
--radius-field: 0.5rem;
|
||||
--radius-box: 0.5rem;
|
||||
--size-selector: 0.25rem;
|
||||
--size-field: 0.25rem;
|
||||
--border: 1px;
|
||||
--depth: 1;
|
||||
--noise: 1;
|
||||
name: "properdark";
|
||||
default: false;
|
||||
prefersdark: true;
|
||||
color-scheme: "dark";
|
||||
--color-base-50: oklch(14% 0 0);
|
||||
--color-base-100: oklch(26% 0 0);
|
||||
--color-base-200: oklch(37% 0 0);
|
||||
--color-base-300: oklch(43% 0 0);
|
||||
--color-base-content: oklch(100% 0 0);
|
||||
--color-primary: oklch(86% 0.127 207.078);
|
||||
--color-primary-content: oklch(39% 0.07 227.392);
|
||||
--color-secondary: oklch(87% 0.065 274.039);
|
||||
--color-secondary-content: oklch(35% 0.144 278.697);
|
||||
--color-accent: oklch(36.2% 0.076 265.6);
|
||||
--color-accent-content: oklch(97% 0.014 254.604);
|
||||
--color-neutral: oklch(37% 0.01 67.558);
|
||||
--color-neutral-content: oklch(100% 0 0);
|
||||
--color-info: oklch(64.4% 0.12 237.3);
|
||||
--color-info-content: oklch(100% 0 0);
|
||||
--color-success: oklch(76% 0.233 130.85);
|
||||
--color-success-content: oklch(0% 0 0);
|
||||
--color-warning: oklch(87% 0.169 91.605);
|
||||
--color-warning-content: oklch(0% 0 0);
|
||||
--color-error: oklch(63% 0.237 25.331);
|
||||
--color-error-content: oklch(100% 0 0);
|
||||
--radius-selector: 0.25rem;
|
||||
--radius-field: 0.25rem;
|
||||
--radius-box: 0.25rem;
|
||||
--size-selector: 0.1875rem;
|
||||
--size-field: 0.1875rem;
|
||||
--border: 1px;
|
||||
--depth: 1;
|
||||
--noise: 1;
|
||||
}
|
||||
|
||||
:root {
|
||||
background-color: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
40
src/events/app-data.ts
Normal file
40
src/events/app-data.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { writable } from "svelte/store";
|
||||
import { type AppData } from "../types/bindings/AppData";
|
||||
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
export let appData = writable<AppData | null>(null);
|
||||
|
||||
let unlisten: UnlistenFn | null = null;
|
||||
let isListening = false;
|
||||
|
||||
export async function initAppDataListener() {
|
||||
try {
|
||||
if (isListening) return;
|
||||
appData.set(await invoke("get_app_data"));
|
||||
unlisten = await listen<AppData>("app-data-refreshed", (event) => {
|
||||
console.log("app-data-refreshed", event.payload);
|
||||
appData.set(event.payload);
|
||||
});
|
||||
|
||||
isListening = true;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function stopAppDataListener() {
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
unlisten = null;
|
||||
isListening = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle HMR (Hot Module Replacement) cleanup
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.dispose(() => {
|
||||
stopAppDataListener();
|
||||
});
|
||||
}
|
||||
@@ -2,14 +2,16 @@
|
||||
import { browser } from "$app/environment";
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import { initCursorTracking, stopCursorTracking } from "../events/cursor";
|
||||
import { initAppDataListener } from "../events/app-data";
|
||||
|
||||
let { children } = $props();
|
||||
if (browser) {
|
||||
onMount(async () => {
|
||||
try {
|
||||
await initCursorTracking();
|
||||
await initAppDataListener();
|
||||
} catch (err) {
|
||||
console.error("[Scene] Failed to initialize cursor tracking:", err);
|
||||
console.error("[Scene] Failed to initialize event listeners:", err);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
46
src/routes/app-menu/+page.svelte
Normal file
46
src/routes/app-menu/+page.svelte
Normal file
@@ -0,0 +1,46 @@
|
||||
<script lang="ts">
|
||||
import Friends from "./tabs/friends.svelte";
|
||||
import Preferences from "./tabs/preferences.svelte";
|
||||
import YourDolls from "./tabs/your-dolls.svelte";
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="p-2 h-full absolute inset-0 bg-base-100 border-base-200/50 border border-t-0 rounded-b-xl"
|
||||
>
|
||||
<div class="flex flex-col gap-2 h-full">
|
||||
<div class="size-full">
|
||||
<div class="tabs tabs-lift h-full">
|
||||
<input
|
||||
type="radio"
|
||||
name="app_menu_tabs"
|
||||
class="tab"
|
||||
aria-label="Your Dolls"
|
||||
checked
|
||||
/>
|
||||
<div class="tab-content bg-base-100 border-base-300 p-4">
|
||||
<YourDolls />
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
name="app_menu_tabs"
|
||||
class="tab"
|
||||
aria-label="Friends"
|
||||
/>
|
||||
<div class="tab-content bg-base-100 border-base-300 p-4">
|
||||
<Friends />
|
||||
</div>
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
name="app_menu_tabs"
|
||||
class="tab"
|
||||
aria-label="Preferences"
|
||||
/>
|
||||
<div class="tab-content bg-base-100 border-base-300 p-4">
|
||||
<Preferences />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
7
src/routes/app-menu/tabs/friends.svelte
Normal file
7
src/routes/app-menu/tabs/friends.svelte
Normal file
@@ -0,0 +1,7 @@
|
||||
<script>
|
||||
import { appData } from "../../../events/app-data";
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<p>{$appData?.user?.name}'s friends</p>
|
||||
</div>
|
||||
21
src/routes/app-menu/tabs/preferences.svelte
Normal file
21
src/routes/app-menu/tabs/preferences.svelte
Normal file
@@ -0,0 +1,21 @@
|
||||
<script>
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { appData } from "../../../events/app-data";
|
||||
</script>
|
||||
|
||||
<div class="size-full flex flex-col justify-between">
|
||||
<div>
|
||||
<p>{$appData?.user?.name}'s preferences</p>
|
||||
</div>
|
||||
<div class="w-full flex flex-row justify-between">
|
||||
<div></div>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-error btn-sm btn-soft"
|
||||
onclick={async () => {
|
||||
await invoke("quit_app");
|
||||
}}>Quit Friendolls</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
7
src/routes/app-menu/tabs/your-dolls.svelte
Normal file
7
src/routes/app-menu/tabs/your-dolls.svelte
Normal file
@@ -0,0 +1,7 @@
|
||||
<script>
|
||||
import { appData } from "../../../events/app-data";
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<p>{$appData?.user?.name}</p>
|
||||
</div>
|
||||
@@ -1,35 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { cursorPositionOnScreen } from "../../events/cursor";
|
||||
</script>
|
||||
|
||||
<div class="p-4">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div>
|
||||
<p class="text-xl font-semibold">Preferences</p>
|
||||
<p class="text-sm opacity-50">Settings and configuration</p>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-200 p-4">
|
||||
<h3 class="font-semibold mb-2">Cursor Position (Multi-Window Test)</h3>
|
||||
<div class="flex flex-col gap-1">
|
||||
<span class="font-mono text-sm">
|
||||
Raw: ({$cursorPositionOnScreen.raw.x}, {$cursorPositionOnScreen.raw
|
||||
.y})
|
||||
</span>
|
||||
<span class="font-mono text-sm">
|
||||
Mapped: ({$cursorPositionOnScreen.mapped.x}, {$cursorPositionOnScreen
|
||||
.mapped.y})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="btn"
|
||||
onclick={() => {
|
||||
invoke("get_app_data").then((data) => {
|
||||
console.log("data", data);
|
||||
});
|
||||
}}>Fetch app data</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user