feat: add sidebar apps management feature

- Implemented sidebar apps functionality including adding, editing, and deleting apps.
- Created a modal for managing sidebar apps with forms for inputting app details.
- Added icon picker component for selecting app icons.
- Introduced inline app view for displaying apps within the sidebar.
- Updated translations for new sidebar apps feature in Dutch and Portuguese.
- Enhanced settings store to manage sidebar apps state.
- Added hooks for managing sidebar apps state and modal visibility.
This commit is contained in:
Linus Rath
2026-03-17 23:02:26 +01:00
parent 3186198fad
commit 6fe4a98b02
20 changed files with 1545 additions and 41 deletions
+48
View File
@@ -38,6 +38,14 @@ export interface KeywordDefinition {
color: string; // Key from KEYWORD_PALETTE
}
export interface SidebarApp {
id: string;
name: string;
url: string;
icon: string; // Lucide icon name (e.g. 'Globe', 'Rss')
openMode: 'tab' | 'inline'; // Open in new tab or embed inline
}
// Available color palette for keywords
export const KEYWORD_PALETTE: Record<string, { dot: string; bg: string }> = {
red: { dot: 'bg-red-500', bg: 'bg-red-50 dark:bg-red-950/30' },
@@ -113,6 +121,11 @@ interface SettingsState {
// Keywords (labels/tags)
emailKeywords: KeywordDefinition[];
// Sidebar Apps
sidebarApps: SidebarApp[];
keepAppsLoaded: boolean;
// Advanced
debugMode: boolean;
settingsSyncDisabled: boolean;
@@ -142,6 +155,12 @@ interface SettingsState {
reorderKeywords: (keywords: KeywordDefinition[]) => void;
getKeywordById: (id: string) => KeywordDefinition | undefined;
// Sidebar Apps
addSidebarApp: (app: SidebarApp) => void;
updateSidebarApp: (id: string, updates: Partial<Omit<SidebarApp, 'id'>>) => void;
removeSidebarApp: (id: string) => void;
reorderSidebarApps: (apps: SidebarApp[]) => void;
// Settings sync
enableSync: (username: string, serverUrl: string) => void;
disableSync: () => void;
@@ -197,6 +216,10 @@ const DEFAULT_SETTINGS = {
// Keywords
emailKeywords: DEFAULT_KEYWORDS,
// Sidebar Apps
sidebarApps: [] as SidebarApp[],
keepAppsLoaded: false,
// Advanced
debugMode: false,
settingsSyncDisabled: false,
@@ -261,6 +284,8 @@ export const useSettingsStore = create<SettingsState>()(
senderFavicons: state.senderFavicons,
folderIcons: state.folderIcons,
emailKeywords: state.emailKeywords,
sidebarApps: state.sidebarApps,
keepAppsLoaded: state.keepAppsLoaded,
debugMode: state.debugMode,
settingsSyncDisabled: state.settingsSyncDisabled,
// Cross-store settings
@@ -364,6 +389,29 @@ export const useSettingsStore = create<SettingsState>()(
return get().emailKeywords.find(k => k.id === id);
},
// Sidebar Apps methods
addSidebarApp: (app: SidebarApp) => {
const current = get().sidebarApps;
if (current.some(a => a.id === app.id)) return;
set({ sidebarApps: [...current, app] });
},
updateSidebarApp: (id: string, updates: Partial<Omit<SidebarApp, 'id'>>) => {
set({
sidebarApps: get().sidebarApps.map(a =>
a.id === id ? { ...a, ...updates } : a
),
});
},
removeSidebarApp: (id: string) => {
set({ sidebarApps: get().sidebarApps.filter(a => a.id !== id) });
},
reorderSidebarApps: (apps: SidebarApp[]) => {
set({ sidebarApps: apps });
},
// Settings sync methods
enableSync: (username: string, serverUrl: string) => {
syncUsername = username;