-
- setTheme(v ? 'light' : getStoredDarkBase())}
- aria-label={isLight ? 'Switch to dark theme' : 'Switch to light theme'}
- className="data-[state=checked]:bg-emerald-400 data-[state=unchecked]:bg-zinc-600"
- />
-
-
- )
-}
export function AppHeader() {
return (
@@ -194,10 +167,10 @@ export function AppHeader() {
- {/* what's new + theme switch + BPM readout + beat indicator -- always visible */}
+ {/* what's new + BPM readout + beat indicator -- always visible
+ (v7.15.2: the theme tick switch moved to the Settings tab) */}
-
diff --git a/src/components/ava/settings-tab.tsx b/src/components/ava/settings-tab.tsx
index 0795417..d0dd96e 100755
--- a/src/components/ava/settings-tab.tsx
+++ b/src/components/ava/settings-tab.tsx
@@ -1,8 +1,9 @@
-// OVE — Settings tab (v6.5): appearance controls — base theme + highlight
-// color pickers. Everything is per-visitor (localStorage only, nothing on
-// the server) and applies instantly. The Native tab that previously lived
-// in this slot is parked (see control-panel.tsx) and returns unchanged
-// when the project nears completion.
+// OVE — Settings tab (v6.5): appearance controls — light/dark flip (v7.15.2,
+// moved here from the header), base theme + highlight color pickers.
+// Everything is per-visitor (localStorage only, nothing on the server) and
+// applies instantly. The Native tab that previously lived in this slot is
+// parked (see control-panel.tsx) and returns unchanged when the project
+// nears completion.
//
// v7.7: the Music Services log in / "log out of all" section is PARKED
// (MUSIC_SERVICES_UI below). Stream-a-Link already plays for everyone
@@ -14,10 +15,11 @@
'use client'
import { useSyncExternalStore, useState, useEffect } from 'react'
-import { Check, LogIn, LogOut, Music4, Palette, RotateCcw } from 'lucide-react'
+import { Check, LogIn, LogOut, Moon, Music4, Palette, RotateCcw, Sun } from 'lucide-react'
import { useTheme } from 'next-themes'
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
+import { Switch } from '@/components/ui/switch'
import { ServiceLoginDialog } from '@/components/ava/service-login-dialog'
import { SERVICES, type ServiceId } from '@/lib/music-services'
import {
@@ -31,6 +33,7 @@ import {
DEFAULT_BASE,
THEME_BASES,
applyAccent,
+ getStoredDarkBase,
isAccentId,
storeDarkBase,
type AccentId,
@@ -89,6 +92,14 @@ export function SettingsTab() {
if (id === 'outline' && accent !== 'blue') applyAccent('blue')
}
+ /** v7.15.2 — the header tick switch's flip, verbatim: checking = the white
+ * theme; unchecking returns to the visitor's stored dark base (kept fresh
+ * by pickBase below). The mount guard lives in `isLight`, so the SSR
+ * render shows the unchecked position without a hydration mismatch. */
+ function flipLight(v: boolean) {
+ setTheme(v ? 'light' : getStoredDarkBase())
+ }
+
function pickAccent(id: AccentId) {
applyAccent(id)
}
@@ -157,6 +168,38 @@ export function SettingsTab() {
+ {/* v7.15.2 — the light/dark tick switch, moved from the header. First
+ control in Appearance: the quick flip. The base cards below remain
+ the full palette choice; this row only toggles between the white
+ theme and whichever dark base the visitor picked (default outline). */}
+
+
+ Quick flip between the white theme and the dark side — flipping back to dark returns
+ to the base picked below (or the last one used).
+
+
+
+
+
+
+
+
+
+
Base theme
diff --git a/src/lib/release-notes.ts b/src/lib/release-notes.ts
index 7e2219b..17089ad 100755
--- a/src/lib/release-notes.ts
+++ b/src/lib/release-notes.ts
@@ -39,6 +39,20 @@ export interface ReleaseNote {
}
export const RELEASE_NOTES: ReleaseNote[] = [
+ {
+ version: '7.15.2',
+ name: 'Facebook page + theme switch in Settings',
+ changes: [
+ {
+ kind: 'added',
+ text: "OVE has a Facebook page now -- the footer carries the link (the Facebook icon beside the version stamp), so that is where news and showcase clips will land.",
+ },
+ {
+ kind: 'improved',
+ text: 'The light/dark tick switch moved from the header to the Settings tab, as the first row of the Appearance section -- every look-and-feel control now lives in one place. It flips exactly as before: back to dark it returns to the base picked below it, and both choices persist.',
+ },
+ ],
+ },
{
version: '7.15.1',
name: 'Silence holds the beat grid',
diff --git a/src/lib/version.ts b/src/lib/version.ts
index 90e544f..956e253 100755
--- a/src/lib/version.ts
+++ b/src/lib/version.ts
@@ -12,6 +12,22 @@
// warns in the console when the two drift apart.
//
// History:
+// 7.15.2 — Facebook page + theme switch relocation (user request): the
+// project now has its own Facebook page, and the footer's
+// right-hand group carries the link (facebook.com/openvisengine)
+// beside the version stamp -- an icon-only button (lucide
+// Facebook glyph) that opens in a new tab, same hover/focus
+// treatment as the portfolio link. The light/dark tick switch
+// (v6.3) moved out of the header into the Settings tab's
+// Appearance section, as a "Light / dark mode" row ABOVE the
+// base-theme cards -- the header is one control lighter and all
+// appearance controls now live in one place. Mechanics are
+// identical: checking = the white theme, unchecking returns to
+// the visitor's stored dark base (kept fresh by the base cards),
+// both choices persist per visitor, and the mount guard keeps
+// the SSR render mismatch-free. The row states the current side
+// ("Light theme" / "Dark theme") and explains the return-to-base
+// behavior in its caption.
// 7.15.1 — the silence hold (user request): "if silence is detected,
// it needs to place an immediate override and hold on the beat
// detection / prediction ... if silence is no longer detected,
@@ -532,4 +548,4 @@
export const APP_NAME = 'Open Visualization Engine'
export const APP_SHORT = 'OVE'
-export const APP_VERSION = '7.15.1'
+export const APP_VERSION = '7.15.2'
diff --git a/worklog.md b/worklog.md
index 22e8b23..e9e54fd 100755
--- a/worklog.md
+++ b/worklog.md
@@ -2500,3 +2500,33 @@ BROWSER E2E (agent-browser, ALL PASS; probe track = generated 13 s WAV, 8 s of 1
Stage Summary:
- v7.15.1 shipped: silence places an immediate HOLD on beat detection + prediction (level < 0.006 for 300 ms; sticky until 0.015) -- nothing fires, learning/confidence/beatphase freeze; decisive audio releases instantly and the grid resumes from the phase the audio went quiet (pause/resume keeps perfect time); taps override; waveform/band data never gated; scripts get silent; the indicator shows HOLD. Headless 26/26 + browser E2E green; pushed to zai-dev.
+
+---
+Task ID: 45
+Agent: main (Z.ai Code)
+Task: v7.15.2 (user request): "So I created a facebook page just for this project that I would like to add to the footer, it is 'https://www.facebook.com/openvisengine/'. Also the light/dark theme switch needs to be moved to the 'Settings' tab." Delivered on the zai-dev staging branch (remote: gitzcreations/openvisengine).
+
+Approach:
+- The Facebook link belongs with the PROJECT identity, not the maker credit block (that corner is the site creator's) -- so it went into the footer's right-hand group beside the version stamp: icon-only (lucide Facebook glyph, size-3.5 in a size-6 hit area), target=_blank + rel=noopener noreferrer, aria-label + title for a11y, same hover/focus treatment as the portfolio link (zinc-500 -> emerald-300, focus-visible ring).
+- The theme tick switch (v6.3 header resident) is a stateless control whose logic (flip to light / flip back to the STORED dark base) lives entirely in setTheme + getStoredDarkBase() -- so moving it is pure relocation. New home: the Settings tab's Appearance section, as a "Light / dark mode" row ABOVE the base-theme cards (the quick flip first, the full palette choice below), in a bordered card that states the current side ("Light theme" / "Dark theme") and explains the return-to-base behavior in its caption. Mechanics are byte-identical: checked = 'light', unchecked = getStoredDarkBase(); the existing mounted/isLight guard keeps the SSR render mismatch-free.
+- pickBase() already refreshes the stored dark base on every dark card pick, so the switch's return target always tracks the visitor's latest dark choice -- verified with a purple -> light -> dark round trip.
+
+Work Log:
+- footer-bar.tsx: Facebook icon link in the right group (v7.15.2 comment block; Facebook import from lucide-react).
+- header.tsx: ThemeToggle component + its now-unused imports removed (useSyncExternalStore, Moon/Sun, useTheme, Switch, getStoredDarkBase); file header + right-group comments updated (v7.15.2 note pointing at settings-tab.tsx); the header right group is now What's New! + BPM readout + beat indicator.
+- settings-tab.tsx: "Light / dark mode" section (first in Appearance) with the Moon/Sun tick switch; flipLight() = the header toggle's onCheckedChange verbatim; Moon, Sun, Switch, getStoredDarkBase imports; file header comment updated.
+- version.ts: APP_VERSION 7.15.2 + history entry. release-notes.ts: 7.15.2 "Facebook page + theme switch in Settings" (1 added + 1 improved, first-person voice, no em dashes).
+
+BROWSER E2E (agent-browser, ALL PASS):
+- Fresh load: title "OVE -- Open Visualization Engine (v7.15.2)"; footer shows "version 7.15.2".
+- Footer link: present in