|
|
|
|
@ -1,5 +1,7 @@
@@ -1,5 +1,7 @@
|
|
|
|
|
<script lang="ts"> |
|
|
|
|
import { onMount } from 'svelte'; |
|
|
|
|
import { goto } from '$app/navigation'; |
|
|
|
|
import { shouldIncludeClientTag, setIncludeClientTag } from '../../services/client-tag-preference.js'; |
|
|
|
|
|
|
|
|
|
type TextSize = 'small' | 'medium' | 'large'; |
|
|
|
|
type LineSpacing = 'tight' | 'normal' | 'loose'; |
|
|
|
|
@ -8,11 +10,16 @@
@@ -8,11 +10,16 @@
|
|
|
|
|
let textSize = $state<TextSize>('medium'); |
|
|
|
|
let lineSpacing = $state<LineSpacing>('normal'); |
|
|
|
|
let contentWidth = $state<ContentWidth>('medium'); |
|
|
|
|
let isDark = $state(false); |
|
|
|
|
let expiringEvents = $state(false); |
|
|
|
|
let mediaUploadServer = $state('https://nostr.build'); |
|
|
|
|
let includeClientTag = $state(true); |
|
|
|
|
let showPreferences = $state(false); |
|
|
|
|
|
|
|
|
|
onMount(() => { |
|
|
|
|
loadPreferences(); |
|
|
|
|
applyPreferences(); |
|
|
|
|
loadTheme(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
function loadPreferences() { |
|
|
|
|
@ -21,10 +28,39 @@
@@ -21,10 +28,39 @@
|
|
|
|
|
const savedTextSize = localStorage.getItem('aitherboard_textSize') as TextSize | null; |
|
|
|
|
const savedLineSpacing = localStorage.getItem('aitherboard_lineSpacing') as LineSpacing | null; |
|
|
|
|
const savedContentWidth = localStorage.getItem('aitherboard_contentWidth') as ContentWidth | null; |
|
|
|
|
const savedExpiringEvents = localStorage.getItem('aitherboard_expiringEvents'); |
|
|
|
|
const savedMediaUploadServer = localStorage.getItem('aitherboard_mediaUploadServer'); |
|
|
|
|
|
|
|
|
|
if (savedTextSize) textSize = savedTextSize; |
|
|
|
|
if (savedLineSpacing) lineSpacing = savedLineSpacing; |
|
|
|
|
if (savedContentWidth) contentWidth = savedContentWidth; |
|
|
|
|
if (savedExpiringEvents === 'true') expiringEvents = true; |
|
|
|
|
if (savedMediaUploadServer) mediaUploadServer = savedMediaUploadServer; |
|
|
|
|
includeClientTag = shouldIncludeClientTag(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function loadTheme() { |
|
|
|
|
if (typeof window === 'undefined') return; |
|
|
|
|
const stored = localStorage.getItem('theme'); |
|
|
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; |
|
|
|
|
isDark = stored === 'dark' || (!stored && prefersDark); |
|
|
|
|
updateTheme(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function toggleTheme() { |
|
|
|
|
isDark = !isDark; |
|
|
|
|
updateTheme(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function updateTheme() { |
|
|
|
|
if (typeof document === 'undefined') return; |
|
|
|
|
if (isDark) { |
|
|
|
|
document.documentElement.classList.add('dark'); |
|
|
|
|
localStorage.setItem('theme', 'dark'); |
|
|
|
|
} else { |
|
|
|
|
document.documentElement.classList.remove('dark'); |
|
|
|
|
localStorage.setItem('theme', 'light'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function savePreferences() { |
|
|
|
|
@ -33,6 +69,9 @@
@@ -33,6 +69,9 @@
|
|
|
|
|
localStorage.setItem('aitherboard_textSize', textSize); |
|
|
|
|
localStorage.setItem('aitherboard_lineSpacing', lineSpacing); |
|
|
|
|
localStorage.setItem('aitherboard_contentWidth', contentWidth); |
|
|
|
|
localStorage.setItem('aitherboard_expiringEvents', expiringEvents ? 'true' : 'false'); |
|
|
|
|
localStorage.setItem('aitherboard_mediaUploadServer', mediaUploadServer); |
|
|
|
|
setIncludeClientTag(includeClientTag); |
|
|
|
|
|
|
|
|
|
applyPreferences(); |
|
|
|
|
} |
|
|
|
|
@ -42,7 +81,7 @@
@@ -42,7 +81,7 @@
|
|
|
|
|
|
|
|
|
|
const root = document.documentElement; |
|
|
|
|
|
|
|
|
|
// Text size - set both CSS variable and data attribute |
|
|
|
|
// Text size |
|
|
|
|
const textSizes = { |
|
|
|
|
small: '14px', |
|
|
|
|
medium: '16px', |
|
|
|
|
@ -51,7 +90,7 @@
@@ -51,7 +90,7 @@
|
|
|
|
|
root.style.setProperty('--text-size', textSizes[textSize]); |
|
|
|
|
root.setAttribute('data-text-size', textSize); |
|
|
|
|
|
|
|
|
|
// Line spacing - set both CSS variable and data attribute |
|
|
|
|
// Line spacing |
|
|
|
|
const lineSpacings = { |
|
|
|
|
tight: '1.4', |
|
|
|
|
normal: '1.6', |
|
|
|
|
@ -60,7 +99,7 @@
@@ -60,7 +99,7 @@
|
|
|
|
|
root.style.setProperty('--line-height', lineSpacings[lineSpacing]); |
|
|
|
|
root.setAttribute('data-line-spacing', lineSpacing); |
|
|
|
|
|
|
|
|
|
// Content width - set CSS variable and data attribute |
|
|
|
|
// Content width |
|
|
|
|
const contentWidths = { |
|
|
|
|
narrow: '600px', |
|
|
|
|
medium: '800px', |
|
|
|
|
@ -70,14 +109,37 @@
@@ -70,14 +109,37 @@
|
|
|
|
|
root.setAttribute('data-content-width', contentWidth); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleMediaUploadServerChange(e: Event) { |
|
|
|
|
const target = e.target as HTMLInputElement; |
|
|
|
|
mediaUploadServer = target.value; |
|
|
|
|
savePreferences(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleManageCache() { |
|
|
|
|
showPreferences = false; |
|
|
|
|
goto('/cache'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$effect(() => { |
|
|
|
|
savePreferences(); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
$effect(() => { |
|
|
|
|
if (showPreferences) { |
|
|
|
|
const handleEscape = (e: KeyboardEvent) => { |
|
|
|
|
if (e.key === 'Escape') { |
|
|
|
|
showPreferences = false; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
document.addEventListener('keydown', handleEscape); |
|
|
|
|
return () => document.removeEventListener('keydown', handleEscape); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
<button |
|
|
|
|
onclick={() => (showPreferences = !showPreferences)} |
|
|
|
|
class="px-3 py-1 rounded border border-fog-border dark:border-fog-dark-border bg-fog-post dark:bg-fog-dark-post text-fog-text dark:text-fog-dark-text hover:bg-fog-highlight dark:hover:bg-fog-dark-highlight transition-colors" |
|
|
|
|
class="preferences-button" |
|
|
|
|
title="User Preferences" |
|
|
|
|
aria-label="User Preferences" |
|
|
|
|
> |
|
|
|
|
@ -85,113 +147,182 @@
@@ -85,113 +147,182 @@
|
|
|
|
|
</button> |
|
|
|
|
|
|
|
|
|
{#if showPreferences} |
|
|
|
|
<!-- Backdrop --> |
|
|
|
|
<div |
|
|
|
|
class="preferences-modal" |
|
|
|
|
onclick={(e) => e.target === e.currentTarget && (showPreferences = false)} |
|
|
|
|
onkeydown={(e) => { |
|
|
|
|
if (e.key === 'Escape') { |
|
|
|
|
e.preventDefault(); |
|
|
|
|
showPreferences = false; |
|
|
|
|
} |
|
|
|
|
}} |
|
|
|
|
role="dialog" |
|
|
|
|
aria-modal="true" |
|
|
|
|
aria-labelledby="preferences-title" |
|
|
|
|
tabindex="-1" |
|
|
|
|
> |
|
|
|
|
<div class="preferences-content"> |
|
|
|
|
<div class="preferences-header"> |
|
|
|
|
<h2 id="preferences-title">User Preferences</h2> |
|
|
|
|
<button onclick={() => (showPreferences = false)} class="close-button" aria-label="Close preferences">×</button> |
|
|
|
|
class="preferences-backdrop" |
|
|
|
|
onclick={() => (showPreferences = false)} |
|
|
|
|
role="presentation" |
|
|
|
|
></div> |
|
|
|
|
|
|
|
|
|
<!-- Panel --> |
|
|
|
|
<div class="preferences-panel" role="dialog" aria-modal="true" aria-labelledby="preferences-title"> |
|
|
|
|
<div class="preferences-header"> |
|
|
|
|
<h2 id="preferences-title">Preferences</h2> |
|
|
|
|
<button onclick={() => (showPreferences = false)} class="close-button" aria-label="Close preferences">×</button> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="preferences-body"> |
|
|
|
|
<!-- Theme Toggle --> |
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Theme</legend> |
|
|
|
|
<div class="preference-options" role="group" aria-label="Theme"> |
|
|
|
|
<button |
|
|
|
|
onclick={toggleTheme} |
|
|
|
|
class="preference-option theme-toggle" |
|
|
|
|
aria-pressed={isDark} |
|
|
|
|
> |
|
|
|
|
<span class="emoji emoji-grayscale">{#if isDark}☀️{:else}🌙{/if}</span> |
|
|
|
|
<span>{isDark ? 'Light' : 'Dark'} Mode</span> |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<!-- Text Size --> |
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Text Size</legend> |
|
|
|
|
<div class="preference-options" role="group" aria-label="Text Size"> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (textSize = 'small')} |
|
|
|
|
class="preference-option {textSize === 'small' ? 'active' : ''}" |
|
|
|
|
aria-pressed={textSize === 'small'} |
|
|
|
|
> |
|
|
|
|
Small |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (textSize = 'medium')} |
|
|
|
|
class="preference-option {textSize === 'medium' ? 'active' : ''}" |
|
|
|
|
aria-pressed={textSize === 'medium'} |
|
|
|
|
> |
|
|
|
|
Medium |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (textSize = 'large')} |
|
|
|
|
class="preference-option {textSize === 'large' ? 'active' : ''}" |
|
|
|
|
aria-pressed={textSize === 'large'} |
|
|
|
|
> |
|
|
|
|
Large |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<!-- Line Spacing --> |
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Line Spacing</legend> |
|
|
|
|
<div class="preference-options" role="group" aria-label="Line Spacing"> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (lineSpacing = 'tight')} |
|
|
|
|
class="preference-option {lineSpacing === 'tight' ? 'active' : ''}" |
|
|
|
|
aria-pressed={lineSpacing === 'tight'} |
|
|
|
|
> |
|
|
|
|
Tight |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (lineSpacing = 'normal')} |
|
|
|
|
class="preference-option {lineSpacing === 'normal' ? 'active' : ''}" |
|
|
|
|
aria-pressed={lineSpacing === 'normal'} |
|
|
|
|
> |
|
|
|
|
Normal |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (lineSpacing = 'loose')} |
|
|
|
|
class="preference-option {lineSpacing === 'loose' ? 'active' : ''}" |
|
|
|
|
aria-pressed={lineSpacing === 'loose'} |
|
|
|
|
> |
|
|
|
|
Loose |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<!-- Expiring Events --> |
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Event Expiration</legend> |
|
|
|
|
<label class="checkbox-label"> |
|
|
|
|
<input |
|
|
|
|
type="checkbox" |
|
|
|
|
bind:checked={expiringEvents} |
|
|
|
|
class="checkbox-input" |
|
|
|
|
/> |
|
|
|
|
<span>Create expiring events (6 months: kinds 7, 1, 30315)</span> |
|
|
|
|
</label> |
|
|
|
|
<p class="preference-help">Adds a 6-month expiration timestamp to created events of the specified kinds.</p> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<!-- Include Client Tag --> |
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Client Tag</legend> |
|
|
|
|
<label class="checkbox-label"> |
|
|
|
|
<input |
|
|
|
|
type="checkbox" |
|
|
|
|
bind:checked={includeClientTag} |
|
|
|
|
class="checkbox-input" |
|
|
|
|
/> |
|
|
|
|
<span>Include client tag</span> |
|
|
|
|
</label> |
|
|
|
|
<p class="preference-help">Include NIP-89 client tag in published events to identify the client used.</p> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<!-- Media Upload Server --> |
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Media Upload Server</legend> |
|
|
|
|
<input |
|
|
|
|
type="text" |
|
|
|
|
bind:value={mediaUploadServer} |
|
|
|
|
oninput={handleMediaUploadServerChange} |
|
|
|
|
placeholder="https://nostr.build" |
|
|
|
|
class="text-input" |
|
|
|
|
/> |
|
|
|
|
<p class="preference-help">Preferred server for uploading media files (NIP-96).</p> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<!-- Manage Cache Button --> |
|
|
|
|
<div class="preference-group"> |
|
|
|
|
<button |
|
|
|
|
onclick={handleManageCache} |
|
|
|
|
class="manage-cache-button" |
|
|
|
|
> |
|
|
|
|
Manage Cache |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div class="preferences-body"> |
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Text Size</legend> |
|
|
|
|
<div class="preference-options" role="group" aria-label="Text Size"> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (textSize = 'small')} |
|
|
|
|
class="preference-option {textSize === 'small' ? 'active' : ''}" |
|
|
|
|
aria-pressed={textSize === 'small'} |
|
|
|
|
> |
|
|
|
|
Small |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (textSize = 'medium')} |
|
|
|
|
class="preference-option {textSize === 'medium' ? 'active' : ''}" |
|
|
|
|
aria-pressed={textSize === 'medium'} |
|
|
|
|
> |
|
|
|
|
Medium |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (textSize = 'large')} |
|
|
|
|
class="preference-option {textSize === 'large' ? 'active' : ''}" |
|
|
|
|
aria-pressed={textSize === 'large'} |
|
|
|
|
> |
|
|
|
|
Large |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Line Spacing</legend> |
|
|
|
|
<div class="preference-options" role="group" aria-label="Line Spacing"> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (lineSpacing = 'tight')} |
|
|
|
|
class="preference-option {lineSpacing === 'tight' ? 'active' : ''}" |
|
|
|
|
aria-pressed={lineSpacing === 'tight'} |
|
|
|
|
> |
|
|
|
|
Tight |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (lineSpacing = 'normal')} |
|
|
|
|
class="preference-option {lineSpacing === 'normal' ? 'active' : ''}" |
|
|
|
|
aria-pressed={lineSpacing === 'normal'} |
|
|
|
|
> |
|
|
|
|
Normal |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (lineSpacing = 'loose')} |
|
|
|
|
class="preference-option {lineSpacing === 'loose' ? 'active' : ''}" |
|
|
|
|
aria-pressed={lineSpacing === 'loose'} |
|
|
|
|
> |
|
|
|
|
Loose |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</fieldset> |
|
|
|
|
|
|
|
|
|
<fieldset class="preference-group"> |
|
|
|
|
<legend class="preference-label">Content Width</legend> |
|
|
|
|
<div class="preference-options" role="group" aria-label="Content Width"> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (contentWidth = 'narrow')} |
|
|
|
|
class="preference-option {contentWidth === 'narrow' ? 'active' : ''}" |
|
|
|
|
aria-pressed={contentWidth === 'narrow'} |
|
|
|
|
> |
|
|
|
|
Narrow |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (contentWidth = 'medium')} |
|
|
|
|
class="preference-option {contentWidth === 'medium' ? 'active' : ''}" |
|
|
|
|
aria-pressed={contentWidth === 'medium'} |
|
|
|
|
> |
|
|
|
|
Medium |
|
|
|
|
</button> |
|
|
|
|
<button |
|
|
|
|
onclick={() => (contentWidth = 'wide')} |
|
|
|
|
class="preference-option {contentWidth === 'wide' ? 'active' : ''}" |
|
|
|
|
aria-pressed={contentWidth === 'wide'} |
|
|
|
|
> |
|
|
|
|
Wide |
|
|
|
|
</button> |
|
|
|
|
</div> |
|
|
|
|
</fieldset> |
|
|
|
|
<!-- About Section --> |
|
|
|
|
<div class="preferences-footer"> |
|
|
|
|
<div class="about-section"> |
|
|
|
|
<h3 class="about-title">About</h3> |
|
|
|
|
<p class="about-text"> |
|
|
|
|
Aitherboard is a decentralized discussion board built on Nostr. |
|
|
|
|
Brought to you by <a href="/profile/fd208ee8c8f283780a9552896e4823cc9dc6bfd442063889577106940fd927c1" class="about-link">Silberengel</a>. |
|
|
|
|
</p> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
{/if} |
|
|
|
|
|
|
|
|
|
<style> |
|
|
|
|
.preferences-button { |
|
|
|
|
padding: 0.5rem 0.75rem; |
|
|
|
|
border-radius: 0.25rem; |
|
|
|
|
border: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
background: var(--fog-post, #ffffff); |
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
cursor: pointer; |
|
|
|
|
transition: all 0.2s; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preferences-button { |
|
|
|
|
border-color: var(--fog-dark-border, #374151); |
|
|
|
|
background: var(--fog-dark-post, #1f2937); |
|
|
|
|
color: var(--fog-dark-text, #f9fafb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preferences-button:hover { |
|
|
|
|
background: var(--fog-highlight, #f3f4f6); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preferences-button:hover { |
|
|
|
|
background: var(--fog-dark-highlight, #374151); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.emoji { |
|
|
|
|
font-size: 1rem; |
|
|
|
|
line-height: 1; |
|
|
|
|
@ -199,11 +330,7 @@
@@ -199,11 +330,7 @@
|
|
|
|
|
filter: grayscale(100%); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
button:hover .emoji { |
|
|
|
|
filter: grayscale(80%); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preferences-modal { |
|
|
|
|
.preferences-backdrop { |
|
|
|
|
position: fixed; |
|
|
|
|
top: 0; |
|
|
|
|
left: 0; |
|
|
|
|
@ -211,26 +338,48 @@
@@ -211,26 +338,48 @@
|
|
|
|
|
bottom: 0; |
|
|
|
|
background: rgba(0, 0, 0, 0.5); |
|
|
|
|
backdrop-filter: blur(4px); |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
|
justify-content: center; |
|
|
|
|
z-index: 1000; |
|
|
|
|
z-index: 999; |
|
|
|
|
animation: fadeIn 0.2s ease-out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preferences-content { |
|
|
|
|
.preferences-panel { |
|
|
|
|
position: fixed; |
|
|
|
|
top: 0; |
|
|
|
|
left: 0; |
|
|
|
|
width: 320px; |
|
|
|
|
height: 100vh; |
|
|
|
|
background: var(--fog-post, #ffffff); |
|
|
|
|
border: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
border-radius: 8px; |
|
|
|
|
max-width: 500px; |
|
|
|
|
width: 90%; |
|
|
|
|
max-height: 80vh; |
|
|
|
|
overflow: auto; |
|
|
|
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); |
|
|
|
|
border-right: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1); |
|
|
|
|
z-index: 1000; |
|
|
|
|
display: flex; |
|
|
|
|
flex-direction: column; |
|
|
|
|
animation: slideIn 0.3s ease-out; |
|
|
|
|
overflow: hidden; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preferences-content { |
|
|
|
|
:global(.dark) .preferences-panel { |
|
|
|
|
background: var(--fog-dark-post, #1f2937); |
|
|
|
|
border-color: var(--fog-dark-border, #374151); |
|
|
|
|
border-right-color: var(--fog-dark-border, #374151); |
|
|
|
|
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.3); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@keyframes slideIn { |
|
|
|
|
from { |
|
|
|
|
transform: translateX(-100%); |
|
|
|
|
} |
|
|
|
|
to { |
|
|
|
|
transform: translateX(0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@keyframes fadeIn { |
|
|
|
|
from { |
|
|
|
|
opacity: 0; |
|
|
|
|
} |
|
|
|
|
to { |
|
|
|
|
opacity: 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preferences-header { |
|
|
|
|
@ -239,12 +388,24 @@
@@ -239,12 +388,24 @@
|
|
|
|
|
align-items: center; |
|
|
|
|
padding: 1rem; |
|
|
|
|
border-bottom: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
flex-shrink: 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preferences-header { |
|
|
|
|
border-bottom-color: var(--fog-dark-border, #374151); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preferences-header h2 { |
|
|
|
|
margin: 0; |
|
|
|
|
font-size: 1.25rem; |
|
|
|
|
font-weight: 600; |
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preferences-header h2 { |
|
|
|
|
color: var(--fog-dark-text, #f9fafb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.close-button { |
|
|
|
|
background: none; |
|
|
|
|
border: none; |
|
|
|
|
@ -253,10 +414,30 @@
@@ -253,10 +414,30 @@
|
|
|
|
|
padding: 0; |
|
|
|
|
width: 2rem; |
|
|
|
|
height: 2rem; |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
|
justify-content: center; |
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
border-radius: 0.25rem; |
|
|
|
|
transition: background 0.2s; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .close-button { |
|
|
|
|
color: var(--fog-dark-text, #f9fafb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.close-button:hover { |
|
|
|
|
background: var(--fog-highlight, #f3f4f6); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .close-button:hover { |
|
|
|
|
background: var(--fog-dark-highlight, #374151); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preferences-body { |
|
|
|
|
padding: 1rem; |
|
|
|
|
overflow-y: auto; |
|
|
|
|
flex: 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preference-group { |
|
|
|
|
@ -271,6 +452,7 @@
@@ -271,6 +452,7 @@
|
|
|
|
|
margin-bottom: 0.5rem; |
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
padding: 0; |
|
|
|
|
font-size: 0.875rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preference-label { |
|
|
|
|
@ -282,22 +464,6 @@
@@ -282,22 +464,6 @@
|
|
|
|
|
flex-wrap: wrap; |
|
|
|
|
gap: 0.5rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) { |
|
|
|
|
.preferences-content { |
|
|
|
|
width: 95%; |
|
|
|
|
max-height: 90vh; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preference-options { |
|
|
|
|
gap: 0.375rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preference-option { |
|
|
|
|
padding: 0.5rem 0.75rem; |
|
|
|
|
font-size: 0.875rem; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preference-option { |
|
|
|
|
padding: 0.5rem 1rem; |
|
|
|
|
@ -307,6 +473,13 @@
@@ -307,6 +473,13 @@
|
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
cursor: pointer; |
|
|
|
|
transition: all 0.2s; |
|
|
|
|
font-size: 0.875rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preference-option.theme-toggle { |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
|
gap: 0.5rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preference-option { |
|
|
|
|
@ -326,13 +499,136 @@
@@ -326,13 +499,136 @@
|
|
|
|
|
|
|
|
|
|
.preference-option.active { |
|
|
|
|
background: var(--fog-accent, #64748b); |
|
|
|
|
color: var(--fog-text, #475569); |
|
|
|
|
color: white; |
|
|
|
|
border-color: var(--fog-accent, #64748b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preference-option.active { |
|
|
|
|
background: var(--fog-dark-accent, #64748b); |
|
|
|
|
color: var(--fog-dark-text, #cbd5e1); |
|
|
|
|
border-color: var(--fog-dark-accent, #64748b); |
|
|
|
|
background: var(--fog-dark-accent, #94a3b8); |
|
|
|
|
color: var(--fog-dark-text, #1f2937); |
|
|
|
|
border-color: var(--fog-dark-accent, #94a3b8); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.checkbox-label { |
|
|
|
|
display: flex; |
|
|
|
|
align-items: center; |
|
|
|
|
gap: 0.5rem; |
|
|
|
|
cursor: pointer; |
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
font-size: 0.875rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .checkbox-label { |
|
|
|
|
color: var(--fog-dark-text, #f9fafb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.checkbox-input { |
|
|
|
|
width: 1rem; |
|
|
|
|
height: 1rem; |
|
|
|
|
cursor: pointer; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preference-help { |
|
|
|
|
margin: 0.5rem 0 0 0; |
|
|
|
|
font-size: 0.75rem; |
|
|
|
|
color: var(--fog-text-light, #6b7280); |
|
|
|
|
font-style: italic; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preference-help { |
|
|
|
|
color: var(--fog-dark-text-light, #9ca3af); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.text-input { |
|
|
|
|
width: 100%; |
|
|
|
|
padding: 0.5rem; |
|
|
|
|
border: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
border-radius: 0.25rem; |
|
|
|
|
background: var(--fog-post, #ffffff); |
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
font-size: 0.875rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .text-input { |
|
|
|
|
border-color: var(--fog-dark-border, #374151); |
|
|
|
|
background: var(--fog-dark-post, #1f2937); |
|
|
|
|
color: var(--fog-dark-text, #f9fafb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.manage-cache-button { |
|
|
|
|
width: 100%; |
|
|
|
|
padding: 0.75rem; |
|
|
|
|
border: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
border-radius: 0.25rem; |
|
|
|
|
background: var(--fog-accent, #64748b); |
|
|
|
|
color: white; |
|
|
|
|
cursor: pointer; |
|
|
|
|
font-size: 0.875rem; |
|
|
|
|
font-weight: 500; |
|
|
|
|
transition: opacity 0.2s; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .manage-cache-button { |
|
|
|
|
border-color: var(--fog-dark-border, #374151); |
|
|
|
|
background: var(--fog-dark-accent, #94a3b8); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.manage-cache-button:hover { |
|
|
|
|
opacity: 0.9; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.preferences-footer { |
|
|
|
|
padding: 1rem; |
|
|
|
|
border-top: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
flex-shrink: 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .preferences-footer { |
|
|
|
|
border-top-color: var(--fog-dark-border, #374151); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.about-section { |
|
|
|
|
font-size: 0.75rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.about-title { |
|
|
|
|
margin: 0 0 0.5rem 0; |
|
|
|
|
font-size: 0.875rem; |
|
|
|
|
font-weight: 600; |
|
|
|
|
color: var(--fog-text, #1f2937); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .about-title { |
|
|
|
|
color: var(--fog-dark-text, #f9fafb); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.about-text { |
|
|
|
|
margin: 0; |
|
|
|
|
color: var(--fog-text-light, #6b7280); |
|
|
|
|
line-height: 1.5; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .about-text { |
|
|
|
|
color: var(--fog-dark-text-light, #9ca3af); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.about-link { |
|
|
|
|
color: var(--fog-accent, #64748b); |
|
|
|
|
text-decoration: underline; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .about-link { |
|
|
|
|
color: var(--fog-dark-accent, #94a3b8); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.about-link:hover { |
|
|
|
|
opacity: 0.8; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) { |
|
|
|
|
.preferences-panel { |
|
|
|
|
width: 100%; |
|
|
|
|
max-width: 320px; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
</style> |
|
|
|
|
|