feat: merge visibility+appearance flyout, slim history, nav stays open

- Eye icon now opens a combined vis-display flyout (visibility toggles
  + appearance settings in one panel, with divider)
- History flyout reduced to undo+redo only; Refresh moved back to
  standalone rail icon
- Navigation flyout stays open when clicking prev/next day/week
  (removed setFlyoutSection(null) from all nav button handlers,
  both desktop and mobile)
- Mobile rail mirrors desktop flyout structure (vis-display, history,
  nav, refresh standalone)

v1.110.7
This commit is contained in:
mARTin-B78 2026-05-11 14:43:16 +02:00
parent 75bb3301f9
commit cf504846da
3 changed files with 26 additions and 36 deletions

View File

@ -1,6 +1,6 @@
{
"name": "my-weekly-todo-list",
"version": "1.110.6",
"version": "1.110.7",
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
"main": "index.js",
"scripts": {

View File

@ -1452,6 +1452,7 @@ h3 {
box-sizing: border-box;
padding-top: 4px;
padding-bottom: 4px;
min-height: 38px;
}
.task-list-slot.drop-target {

View File

@ -5927,13 +5927,13 @@ export default function WeeklyView() {
<button onClick={() => { const nv = !profile.showNextTask; setShowNextTask(nv); saveSetting("showNextTask", nv); }} style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Ziel" : "Goal"}>{profile.showNextTask ? <Play size={15} /> : <Target size={15} />}</button>
<button onClick={() => setShowFocusMode(true)} style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Fokus" : "Focus"}><Zap size={15} /></button>
{railSep}
{/* Visibility flyout */}
<button style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Sichtbarkeit" : "Visibility"} onMouseEnter={(e) => openFlyout("visibility", e)} onMouseLeave={closeFlyoutDelayed}><Eye size={15} /></button>
{/* Appearance flyout */}
<button style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Darstellung" : "Appearance"} onMouseEnter={(e) => openFlyout("display", e)} onMouseLeave={closeFlyoutDelayed}>{darkMode ? <Moon size={15} /> : <Sun size={15} />}</button>
{/* Visibility + Appearance merged flyout */}
<button style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Darstellung" : "Display"} onMouseEnter={(e) => openFlyout("vis-display", e)} onMouseLeave={closeFlyoutDelayed}><Eye size={15} /></button>
{railSep}
{/* History & Utilities flyout */}
{/* History flyout (undo / redo) */}
<button style={{ ...railIconBtnStyle, opacity: undoCount === 0 && redoCount === 0 ? 0.5 : 1 }} title={profile.language === "de" ? "Verlauf" : "History"} onMouseEnter={(e) => openFlyout("history", e)} onMouseLeave={closeFlyoutDelayed}><Undo2 size={15} /></button>
{/* Refresh */}
<button onClick={() => { fetchCalendarEvents(true); fetchTasks(); }} style={{ ...railIconBtnStyle }} title="Refresh"><RefreshCcw size={15} /></button>
<div style={{ flex: 1 }} />
{railSep}
{/* Settings (cogwheel) + User menu at bottom */}
@ -5976,11 +5976,11 @@ export default function WeeklyView() {
<>
<div style={flyoutLabelStyle}>{profile.language === "de" ? "Navigation" : "Navigation"}</div>
<div style={{ display: "flex", gap: "4px" }}>
<button onClick={() => { goToPrevWeek(); setFlyoutSection(null); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorherige Woche" : "Prev Week"}><ChevronsLeft size={14} /></button>
<button onClick={() => { goToPrevDay(); setFlyoutSection(null); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorheriger Tag" : "Prev Day"}><ChevronLeft size={14} /></button>
<button onClick={() => { goToToday(); setFlyoutSection(null); }} style={{ flex: 2, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#374151" : "var(--ink)", color: "#fff", fontSize: "0.55rem", fontWeight: 800, letterSpacing: "0.05em" }} title="Today">{profile.language === "de" ? "HEUTE" : "TODAY"}</button>
<button onClick={() => { goToNextDay(); setFlyoutSection(null); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächster Tag" : "Next Day"}><ChevronRight size={14} /></button>
<button onClick={() => { goToNextWeek(); setFlyoutSection(null); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächste Woche" : "Next Week"}><ChevronsRight size={14} /></button>
<button onClick={goToPrevWeek} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorherige Woche" : "Prev Week"}><ChevronsLeft size={14} /></button>
<button onClick={goToPrevDay} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorheriger Tag" : "Prev Day"}><ChevronLeft size={14} /></button>
<button onClick={goToToday} style={{ flex: 2, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#374151" : "var(--ink)", color: "#fff", fontSize: "0.55rem", fontWeight: 800, letterSpacing: "0.05em" }} title="Today">{profile.language === "de" ? "HEUTE" : "TODAY"}</button>
<button onClick={goToNextDay} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächster Tag" : "Next Day"}><ChevronRight size={14} /></button>
<button onClick={goToNextWeek} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächste Woche" : "Next Week"}><ChevronsRight size={14} /></button>
</div>
</>
)}
@ -5990,8 +5990,6 @@ export default function WeeklyView() {
<div style={{ display: "flex", gap: "4px" }}>
<button onClick={handleUndo} disabled={undoCount === 0} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: undoCount === 0 ? "default" : "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center", opacity: undoCount === 0 ? 0.3 : 1 }} title="Undo"><Undo2 size={14} /></button>
<button onClick={handleRedo} disabled={redoCount === 0} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: redoCount === 0 ? "default" : "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center", opacity: redoCount === 0 ? 0.3 : 1 }} title="Redo"><Redo2 size={14} /></button>
<button onClick={() => { fetchCalendarEvents(true); fetchTasks(); setFlyoutSection(null); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title="Refresh"><RefreshCcw size={14} /></button>
<button onClick={() => { setShowWeekPrintModal(true); setFlyoutSection(null); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Drucken" : "Print"}><Printer size={14} /></button>
</div>
</>
)}
@ -6014,14 +6012,11 @@ export default function WeeklyView() {
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}><span style={{ fontSize: "0.75rem", color: darkMode ? "#9ca3af" : "#6b7280" }}>:15/:30/:45</span><button onClick={() => { saveViewSetting("showSubHourSlots", !effectiveShowSubHourSlots, true); }} style={{ background: "none", border: "none", cursor: "pointer", color: darkMode ? "#9ca3af" : "#6b7280" }}>{effectiveShowSubHourSlots ? <Eye size={15} /> : <EyeOff size={15} />}</button></div>
</>
)}
{flyoutSection === "visibility" && (
{flyoutSection === "vis-display" && (
<>
<div style={flyoutLabelStyle}>{profile.language === "de" ? "Sichtbarkeit" : "Visibility"}</div>
{[{ label: profile.language === "de" ? "Irgendwann" : "Someday", value: effectiveShowSomeday, toggle: () => saveViewSetting("showSomeday", !effectiveShowSomeday, true) }, { label: profile.language === "de" ? "Ganztägig" : "All-day", value: effectiveShowAllDay, toggle: () => saveViewSetting("showAllDayEvents", !effectiveShowAllDay, true) }, { label: profile.language === "de" ? "Checkboxen" : "Checkboxes", value: effectiveShowTaskCheckboxes, toggle: () => saveViewSetting("showTaskCheckboxes", !effectiveShowTaskCheckboxes, true) }, { label: profile.language === "de" ? "Projekt-Icons" : "Project Icons", value: effectiveShowProjectIcons, toggle: () => saveViewSetting("showProjectIcons", !effectiveShowProjectIcons, true) }, { label: profile.language === "de" ? "Prioritäts-Icons" : "Priority Icons", value: effectiveShowPriorityIcons, toggle: () => saveViewSetting("showPriorityIcons", !effectiveShowPriorityIcons, true) }, ...((profile.weatherEnabled || profile.weatherLat || profile.weatherLon) ? [{ label: profile.language === "de" ? "Wetter" : "Weather", value: effectiveWeatherEnabled, toggle: () => { const v = !effectiveWeatherEnabled; setProfile((p: any) => ({ ...p, weatherEnabled: v })); saveViewSetting("weatherEnabled", v, true); } }] : []) ].map(({ label, value, toggle }) => (<div key={label} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: "16px" }}><span style={{ fontSize: "0.8rem", color: darkMode ? "#d1d5db" : "#333", whiteSpace: "nowrap" }}>{label}</span><button onClick={toggle} style={{ background: "none", border: "none", cursor: "pointer", color: darkMode ? "#9ca3af" : "#6b7280", flexShrink: 0 }}>{value ? <Eye size={15} /> : <EyeOff size={15} />}</button></div>))}
</>
)}
{flyoutSection === "display" && (
<>
<div style={{ borderTop: "1px solid var(--line)", margin: "6px 0" }} />
<div style={flyoutLabelStyle}>{profile.language === "de" ? "Darstellung" : "Appearance"}</div>
<div><div style={{ fontSize: "0.7rem", color: darkMode ? "#9ca3af" : "#6b7280", marginBottom: "4px" }}>{profile.language === "de" ? "Textgröße" : "Text size"}</div><div style={{ display: "flex", gap: "4px" }}>{(["S", "M", "L"] as const).map((size) => (<button key={size} onClick={() => { setFontSize(size); saveSetting("fontSize", size); }} style={{ flex: 1, padding: "4px 0", fontSize: "0.8rem", borderRadius: "6px", border: "none", cursor: "pointer", fontWeight: profile.fontSize === size ? 700 : 400, background: profile.fontSize === size ? (darkMode ? "#374151" : "#333") : (darkMode ? "#1f2937" : "#e5e7eb"), color: profile.fontSize === size ? "#fff" : (darkMode ? "#9ca3af" : "#6b7280") }}>{size}</button>))}</div></div>
<div><div style={{ fontSize: "0.7rem", color: darkMode ? "#9ca3af" : "#6b7280", marginBottom: "4px" }}>{profile.language === "de" ? "Starten mit" : "Start on"}</div><div style={{ display: "flex", gap: "4px" }}><button onClick={() => { setProfile({ ...profile, startDayOffset: 0 }); saveSetting("startDayOffset", 0); const d = new Date(); d.setHours(0, 0, 0, 0); setCurrentWeekStart(d); }} style={{ flex: 1, padding: "4px 0", fontSize: "0.75rem", borderRadius: "6px", border: "none", cursor: "pointer", fontWeight: (profile.startDayOffset || 0) === 0 ? 700 : 400, background: (profile.startDayOffset || 0) === 0 ? (darkMode ? "#374151" : "#333") : (darkMode ? "#1f2937" : "#e5e7eb"), color: (profile.startDayOffset || 0) === 0 ? "#fff" : (darkMode ? "#9ca3af" : "#6b7280") }}>{profile.language === "de" ? "Heute" : "Today"}</button><button onClick={() => { setProfile({ ...profile, startDayOffset: -1 }); saveSetting("startDayOffset", -1); const d = new Date(); d.setHours(0, 0, 0, 0); d.setDate(d.getDate() - 1); setCurrentWeekStart(d); }} style={{ flex: 1, padding: "4px 0", fontSize: "0.75rem", borderRadius: "6px", border: "none", cursor: "pointer", fontWeight: profile.startDayOffset === -1 ? 700 : 400, background: profile.startDayOffset === -1 ? (darkMode ? "#374151" : "#333") : (darkMode ? "#1f2937" : "#e5e7eb"), color: profile.startDayOffset === -1 ? "#fff" : (darkMode ? "#9ca3af" : "#6b7280") }}>{profile.language === "de" ? "Gestern" : "Yesterday"}</button></div></div>
@ -6170,13 +6165,13 @@ export default function WeeklyView() {
<button className="mobile-rail-btn" onClick={() => { const nv = !profile.showNextTask; setShowNextTask(nv); saveSetting("showNextTask", nv); }} style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Ziel" : "Goal"}>{profile.showNextTask ? <Play size={15} /> : <Target size={15} />}</button>
<button className="mobile-rail-btn" onClick={() => { setShowFocusMode(true); setShowMobileRail(false); setFlyoutSection(null); }} style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Fokus" : "Focus"}><Zap size={15} /></button>
{railSep}
{/* Visibility flyout */}
<button className="mobile-rail-btn" style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Sichtbarkeit" : "Visibility"} onClick={(e) => { const rect = (e.currentTarget as HTMLElement).getBoundingClientRect(); setFlyoutY(rect.top); setFlyoutSection(flyoutSection === "visibility" ? null : "visibility"); }}><Eye size={15} /></button>
{/* Appearance flyout */}
<button className="mobile-rail-btn" style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Darstellung" : "Appearance"} onClick={(e) => { const rect = (e.currentTarget as HTMLElement).getBoundingClientRect(); setFlyoutY(rect.top); setFlyoutSection(flyoutSection === "display" ? null : "display"); }}>{darkMode ? <Moon size={15} /> : <Sun size={15} />}</button>
{/* Visibility + Appearance merged flyout */}
<button className="mobile-rail-btn" style={{ ...railIconBtnStyle }} title={profile.language === "de" ? "Darstellung" : "Display"} onClick={(e) => { const rect = (e.currentTarget as HTMLElement).getBoundingClientRect(); setFlyoutY(rect.top); setFlyoutSection(flyoutSection === "vis-display" ? null : "vis-display"); }}><Eye size={15} /></button>
{railSep}
{/* History & Utilities flyout */}
{/* History flyout (undo / redo) */}
<button className="mobile-rail-btn" style={{ ...railIconBtnStyle, opacity: undoCount === 0 && redoCount === 0 ? 0.5 : 1 }} title={profile.language === "de" ? "Verlauf" : "History"} onClick={(e) => { const rect = (e.currentTarget as HTMLElement).getBoundingClientRect(); setFlyoutY(rect.top); setFlyoutSection(flyoutSection === "history" ? null : "history"); }}><Undo2 size={15} /></button>
{/* Refresh */}
<button className="mobile-rail-btn" onClick={() => { fetchCalendarEvents(true); fetchTasks(); setShowMobileRail(false); setFlyoutSection(null); }} style={{ ...railIconBtnStyle }} title="Refresh"><RefreshCcw size={15} /></button>
<button className="mobile-rail-btn" onClick={() => setDarkMode(!darkMode)} style={{ ...railIconBtnStyle }} title={darkMode ? "Light Mode" : "Dark Mode"}>{darkMode ? <Sun size={15} /> : <Moon size={15} />}</button>
<div style={{ flex: 1 }} />
{railSep}
@ -6194,11 +6189,11 @@ export default function WeeklyView() {
<>
<div style={flyoutLabelStyle}>{profile.language === "de" ? "Navigation" : "Navigation"}</div>
<div style={{ display: "flex", gap: "4px" }}>
<button onClick={() => { goToPrevWeek(); setFlyoutSection(null); setShowMobileRail(false); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorherige Woche" : "Prev Week"}><ChevronsLeft size={14} /></button>
<button onClick={() => { goToPrevDay(); setFlyoutSection(null); setShowMobileRail(false); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorheriger Tag" : "Prev Day"}><ChevronLeft size={14} /></button>
<button onClick={() => { goToToday(); setFlyoutSection(null); setShowMobileRail(false); }} style={{ flex: 2, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#374151" : "var(--ink)", color: "#fff", fontSize: "0.55rem", fontWeight: 800, letterSpacing: "0.05em" }} title="Today">{profile.language === "de" ? "HEUTE" : "TODAY"}</button>
<button onClick={() => { goToNextDay(); setFlyoutSection(null); setShowMobileRail(false); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächster Tag" : "Next Day"}><ChevronRight size={14} /></button>
<button onClick={() => { goToNextWeek(); setFlyoutSection(null); setShowMobileRail(false); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächste Woche" : "Next Week"}><ChevronsRight size={14} /></button>
<button onClick={goToPrevWeek} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorherige Woche" : "Prev Week"}><ChevronsLeft size={14} /></button>
<button onClick={goToPrevDay} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Vorheriger Tag" : "Prev Day"}><ChevronLeft size={14} /></button>
<button onClick={goToToday} style={{ flex: 2, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#374151" : "var(--ink)", color: "#fff", fontSize: "0.55rem", fontWeight: 800, letterSpacing: "0.05em" }} title="Today">{profile.language === "de" ? "HEUTE" : "TODAY"}</button>
<button onClick={goToNextDay} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächster Tag" : "Next Day"}><ChevronRight size={14} /></button>
<button onClick={goToNextWeek} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Nächste Woche" : "Next Week"}><ChevronsRight size={14} /></button>
</div>
</>
)}
@ -6208,8 +6203,6 @@ export default function WeeklyView() {
<div style={{ display: "flex", gap: "4px" }}>
<button onClick={handleUndo} disabled={undoCount === 0} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: undoCount === 0 ? "default" : "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center", opacity: undoCount === 0 ? 0.3 : 1 }} title="Undo"><Undo2 size={14} /></button>
<button onClick={handleRedo} disabled={redoCount === 0} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: redoCount === 0 ? "default" : "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center", opacity: redoCount === 0 ? 0.3 : 1 }} title="Redo"><Redo2 size={14} /></button>
<button onClick={() => { fetchCalendarEvents(true); fetchTasks(); setFlyoutSection(null); setShowMobileRail(false); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title="Refresh"><RefreshCcw size={14} /></button>
<button onClick={() => { setShowWeekPrintModal(true); setFlyoutSection(null); setShowMobileRail(false); }} style={{ flex: 1, padding: "6px 0", borderRadius: "6px", border: "none", cursor: "pointer", background: darkMode ? "#1f2937" : "#e5e7eb", color: darkMode ? "#9ca3af" : "var(--ink-3)", display: "flex", alignItems: "center", justifyContent: "center" }} title={profile.language === "de" ? "Drucken" : "Print"}><Printer size={14} /></button>
</div>
</>
)}
@ -6232,17 +6225,13 @@ export default function WeeklyView() {
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}><span style={{ fontSize: "0.75rem", color: darkMode ? "#9ca3af" : "#6b7280" }}>:15/:30/:45</span><button onClick={() => { saveViewSetting("showSubHourSlots", !effectiveShowSubHourSlots, true); }} style={{ background: "none", border: "none", cursor: "pointer", color: darkMode ? "#9ca3af" : "#6b7280" }}>{effectiveShowSubHourSlots ? <Eye size={15} /> : <EyeOff size={15} />}</button></div>
</>
)}
{flyoutSection === "visibility" && (
{flyoutSection === "vis-display" && (
<>
<div style={flyoutLabelStyle}>{profile.language === "de" ? "Sichtbarkeit" : "Visibility"}</div>
{[{ label: profile.language === "de" ? "Irgendwann" : "Someday", value: effectiveShowSomeday, toggle: () => saveViewSetting("showSomeday", !effectiveShowSomeday, true) }, { label: profile.language === "de" ? "Ganztägig" : "All-day", value: effectiveShowAllDay, toggle: () => saveViewSetting("showAllDayEvents", !effectiveShowAllDay, true) }, { label: profile.language === "de" ? "Checkboxen" : "Checkboxes", value: effectiveShowTaskCheckboxes, toggle: () => saveViewSetting("showTaskCheckboxes", !effectiveShowTaskCheckboxes, true) }, { label: profile.language === "de" ? "Projekt-Icons" : "Project Icons", value: effectiveShowProjectIcons, toggle: () => saveViewSetting("showProjectIcons", !effectiveShowProjectIcons, true) }, { label: profile.language === "de" ? "Prioritäts-Icons" : "Priority Icons", value: effectiveShowPriorityIcons, toggle: () => saveViewSetting("showPriorityIcons", !effectiveShowPriorityIcons, true) }, ...((profile.weatherEnabled || profile.weatherLat || profile.weatherLon) ? [{ label: profile.language === "de" ? "Wetter" : "Weather", value: effectiveWeatherEnabled, toggle: () => { const v = !effectiveWeatherEnabled; setProfile((p: any) => ({ ...p, weatherEnabled: v })); saveViewSetting("weatherEnabled", v, true); } }] : []) ].map(({ label, value, toggle }) => (<div key={label} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: "16px" }}><span style={{ fontSize: "0.8rem", color: darkMode ? "#d1d5db" : "#333", whiteSpace: "nowrap" }}>{label}</span><button onClick={toggle} style={{ background: "none", border: "none", cursor: "pointer", color: darkMode ? "#9ca3af" : "#6b7280", flexShrink: 0 }}>{value ? <Eye size={15} /> : <EyeOff size={15} />}</button></div>))}
</>
)}
{flyoutSection === "display" && (
<>
<div style={{ borderTop: "1px solid var(--line)", margin: "6px 0" }} />
<div style={flyoutLabelStyle}>{profile.language === "de" ? "Darstellung" : "Appearance"}</div>
<div><div style={{ fontSize: "0.7rem", color: darkMode ? "#9ca3af" : "#6b7280", marginBottom: "4px" }}>{profile.language === "de" ? "Textgröße" : "Text size"}</div><div style={{ display: "flex", gap: "4px" }}>{(["S", "M", "L"] as const).map((size) => (<button key={size} onClick={() => { setFontSize(size); saveSetting("fontSize", size); }} style={{ flex: 1, padding: "4px 0", fontSize: "0.8rem", borderRadius: "6px", border: "none", cursor: "pointer", fontWeight: profile.fontSize === size ? 700 : 400, background: profile.fontSize === size ? (darkMode ? "#374151" : "#333") : (darkMode ? "#1f2937" : "#e5e7eb"), color: profile.fontSize === size ? "#fff" : (darkMode ? "#9ca3af" : "#6b7280") }}>{size}</button>))}</div></div>
<div><div style={{ fontSize: "0.7rem", color: darkMode ? "#9ca3af" : "#6b7280", marginBottom: "4px" }}>{profile.language === "de" ? "Starten mit" : "Start on"}</div><div style={{ display: "flex", gap: "4px" }}><button onClick={() => { setProfile({ ...profile, startDayOffset: 0 }); saveSetting("startDayOffset", 0); const d = new Date(); d.setHours(0, 0, 0, 0); setCurrentWeekStart(d); }} style={{ flex: 1, padding: "4px 0", fontSize: "0.75rem", borderRadius: "6px", border: "none", cursor: "pointer", fontWeight: (profile.startDayOffset || 0) === 0 ? 700 : 400, background: (profile.startDayOffset || 0) === 0 ? (darkMode ? "#374151" : "#333") : (darkMode ? "#1f2937" : "#e5e7eb"), color: (profile.startDayOffset || 0) === 0 ? "#fff" : (darkMode ? "#9ca3af" : "#6b7280") }}>{profile.language === "de" ? "Heute" : "Today"}</button><button onClick={() => { setProfile({ ...profile, startDayOffset: -1 }); saveSetting("startDayOffset", -1); const d = new Date(); d.setHours(0, 0, 0, 0); d.setDate(d.getDate() - 1); setCurrentWeekStart(d); }} style={{ flex: 1, padding: "4px 0", fontSize: "0.75rem", borderRadius: "6px", border: "none", cursor: "pointer", fontWeight: profile.startDayOffset === -1 ? 700 : 400, background: profile.startDayOffset === -1 ? (darkMode ? "#374151" : "#333") : (darkMode ? "#1f2937" : "#e5e7eb"), color: profile.startDayOffset === -1 ? "#fff" : (darkMode ? "#9ca3af" : "#6b7280") }}>{profile.language === "de" ? "Gestern" : "Yesterday"}</button></div></div>
<div><div style={{ fontSize: "0.7rem", color: darkMode ? "#9ca3af" : "#6b7280", marginBottom: "4px" }}>{profile.language === "de" ? "Anzeige" : "Display"}</div><div style={{ display: "flex", gap: "4px" }}><button onClick={() => setDarkMode(false)} style={{ flex: 1, padding: "4px 0", fontSize: "0.75rem", borderRadius: "6px", border: "none", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: "4px", fontWeight: !darkMode ? 700 : 400, background: !darkMode ? "#333" : (darkMode ? "#1f2937" : "#e5e7eb"), color: !darkMode ? "#fff" : (darkMode ? "#9ca3af" : "#6b7280") }}><Sun size={12} /> {profile.language === "de" ? "Hell" : "Light"}</button><button onClick={() => setDarkMode(true)} style={{ flex: 1, padding: "4px 0", fontSize: "0.75rem", borderRadius: "6px", border: "none", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", gap: "4px", fontWeight: darkMode ? 700 : 400, background: darkMode ? "#374151" : "#e5e7eb", color: darkMode ? "#fff" : "#6b7280" }}><Moon size={12} /> {profile.language === "de" ? "Dunkel" : "Dark"}</button></div></div>
</>
)}