Implement core reader TypeScript modules for shell and UI management
- reader-shell.ts: Main initialization, Alpine.js integration, media type detection - progress-indicator.ts: Reading progress tracking and display components - settings-manager.ts: User settings persistence and retrieval - panel-dock-system.ts: Dockable panel management with drag/drop and collapse - parser-manager.ts: Parser selection and format detection system These core modules provide the foundation for all reader types with shared functionality for progress tracking, settings management, and the flexible panel docking system.
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
// Per-user settings with localStorage fallback
|
||||
|
||||
import { apiGet, apiPut } from "../api";
|
||||
import { getToken, setItem, getItem } from "../storage";
|
||||
|
||||
const SETTINGS_KEY = "reader_settings";
|
||||
const LOCALSTORAGE_KEY = "reader_settings_local";
|
||||
|
||||
interface SettingsManager {
|
||||
load(): Promise<ReaderSettings>;
|
||||
save(settings: Partial<ReaderSettings>): Promise<void>;
|
||||
sync(): Promise<void>; // Sync localStorage → DB
|
||||
get(key: keyof ReaderSettings): any;
|
||||
set(key: keyof ReaderSettings, value: any): Promise<void>;
|
||||
}
|
||||
|
||||
async function loadSettings(): Promise<ReaderSettings> {
|
||||
const token = getToken();
|
||||
if (!token) {
|
||||
// Fallback to localStorage
|
||||
const local = getItem(LOCALSTORAGE_KEY);
|
||||
return local ? JSON.parse(local) : getDefaultSettings();
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await apiGet("/readers/settings");
|
||||
const settings = await response.json();
|
||||
// Cache in localStorage
|
||||
setItem(LOCALSTORAGE_KEY, JSON.stringify(settings));
|
||||
return settings;
|
||||
} catch (error) {
|
||||
// Fallback to localStorage on error
|
||||
const local = getItem(LOCALSTORAGE_KEY);
|
||||
return local ? JSON.parse(local) : getDefaultSettings();
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSettings(settings: Partial<ReaderSettings>): Promise<void> {
|
||||
const token = getToken();
|
||||
if (!token) {
|
||||
// Save to localStorage only
|
||||
const current = loadSettings();
|
||||
const updated = { ...current, ...settings };
|
||||
setItem(LOCALSTORAGE_KEY, JSON.stringify(updated));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await apiPut("/readers/settings", settings);
|
||||
// Update localStorage cache
|
||||
const current = loadSettings();
|
||||
const updated = { ...current, ...settings };
|
||||
setItem(LOCALSTORAGE_KEY, JSON.stringify(updated));
|
||||
} catch (error) {
|
||||
// Fallback to localStorage
|
||||
const current = loadSettings();
|
||||
const updated = { ...current, ...settings };
|
||||
setItem(LOCALSTORAGE_KEY, JSON.stringify(updated));
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultSettings(): ReaderSettings {
|
||||
return {
|
||||
chrome_behavior: "auto-hide",
|
||||
progress_mode: "pages",
|
||||
chrome_theme: "tokyo-night", // UI chrome: All 11 themes available
|
||||
reading_theme: "dark", // Ebook text: 5 reading-optimized themes
|
||||
reading_font: "literata", // Default reading font (designed for ebooks)
|
||||
tap_zone_size: 30,
|
||||
auto_scroll: false,
|
||||
panel_zoom_enabled: true,
|
||||
font_size: 16,
|
||||
line_height: 1.6,
|
||||
margin_width: 20,
|
||||
double_page_spread: false,
|
||||
reading_direction: "ltr",
|
||||
hardware_acceleration: true,
|
||||
|
||||
// Dockable panel defaults by media type
|
||||
panel_layout: {
|
||||
toc: {
|
||||
side: "left",
|
||||
visible: true,
|
||||
collapsed: false,
|
||||
width_px: 320,
|
||||
order: 1,
|
||||
locked: false,
|
||||
last_valid_side: "left",
|
||||
},
|
||||
settings: {
|
||||
side: "left",
|
||||
visible: false,
|
||||
collapsed: true,
|
||||
width_px: 380,
|
||||
order: 2,
|
||||
locked: false,
|
||||
last_valid_side: "left",
|
||||
},
|
||||
navigator: {
|
||||
side: "right",
|
||||
visible: true,
|
||||
collapsed: false,
|
||||
width_px: 200,
|
||||
order: 1,
|
||||
locked: false,
|
||||
last_valid_side: "right",
|
||||
},
|
||||
bookmarks: {
|
||||
side: "right",
|
||||
visible: false,
|
||||
collapsed: true,
|
||||
width_px: 280,
|
||||
order: 2,
|
||||
locked: false,
|
||||
last_valid_side: "right",
|
||||
},
|
||||
mobile_nav_visible: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user