fix: mobile sync icon no longer shifts date; selected day tracks last clicked column
- Mobile header: removed spinner/error from inside the date button, placed as a fixed-width (24px) sibling slot after the button — date text position is now stable regardless of sync state - Selected day: added selectedDay state tracking the last day column the user clicked; passed to getSelectedDay() so "Selektierter Tag" in the header reflects the actual cursor position, not just visibleDays[0] - getSelectedDay() priority: explicit selection → today if visible → first visible day - Navigating to a new week resets selectedDay so the header stays accurate v1.81.1
This commit is contained in:
parent
e800d87235
commit
5bcf281502
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "my-weekly-todo-list",
|
"name": "my-weekly-todo-list",
|
||||||
"version": "1.81.0",
|
"version": "1.81.1",
|
||||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -415,8 +415,10 @@ function formatCustomHeader(format: string, days: Date[], language: string, t: a
|
|||||||
return format.replace(regex, (match) => tokens[match] || match);
|
return format.replace(regex, (match) => tokens[match] || match);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the "selected" day for current_day header: today if visible, otherwise first visible day
|
// Get the "selected" day for current_day header.
|
||||||
function getSelectedDay(days: Date[]): Date {
|
// Priority: explicit selection → today if visible → first visible day
|
||||||
|
function getSelectedDay(days: Date[], explicitSelection?: Date | null): Date {
|
||||||
|
if (explicitSelection) return explicitSelection;
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
return days.some(d =>
|
return days.some(d =>
|
||||||
d.getDate() === today.getDate() &&
|
d.getDate() === today.getDate() &&
|
||||||
@ -792,6 +794,9 @@ export default function WeeklyView() {
|
|||||||
const [isMobile, setIsMobile] = useState(false);
|
const [isMobile, setIsMobile] = useState(false);
|
||||||
const [isPortrait, setIsPortrait] = useState(false);
|
const [isPortrait, setIsPortrait] = useState(false);
|
||||||
|
|
||||||
|
// Tracks the last day column the user interacted with (for "selected day" header display)
|
||||||
|
const [selectedDay, setSelectedDay] = useState<Date | null>(null);
|
||||||
|
|
||||||
const [showMobileFabSheet, setShowMobileFabSheet] = useState(false);
|
const [showMobileFabSheet, setShowMobileFabSheet] = useState(false);
|
||||||
const [showMobileFabMenu, setShowMobileFabMenu] = useState(false);
|
const [showMobileFabMenu, setShowMobileFabMenu] = useState(false);
|
||||||
const [mobileStickyDay, setMobileStickyDay] = useState<string | null>(null);
|
const [mobileStickyDay, setMobileStickyDay] = useState<string | null>(null);
|
||||||
@ -3429,6 +3434,7 @@ export default function WeeklyView() {
|
|||||||
}
|
}
|
||||||
setCurrentWeekStart(newDate);
|
setCurrentWeekStart(newDate);
|
||||||
setSlideDirection(direction === "left" ? "next" : "prev");
|
setSlideDirection(direction === "left" ? "next" : "prev");
|
||||||
|
setSelectedDay(null); // reset so header shows the new week's today/first day
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToPrevWeek = () =>
|
const goToPrevWeek = () =>
|
||||||
@ -5601,17 +5607,13 @@ export default function WeeklyView() {
|
|||||||
<PanelLeftOpen size={22} />
|
<PanelLeftOpen size={22} />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Center: Date display (tap to jump to date) */}
|
{/* Center: Date display (tap to jump to date) + fixed-width sync slot */}
|
||||||
<button className="mobile-header-date" onClick={() => setShowDatePicker(true)} style={{
|
<button className="mobile-header-date" onClick={() => setShowDatePicker(true)} style={{
|
||||||
fontFamily: profile.cwFontFamily || "Inter",
|
fontFamily: profile.cwFontFamily || "Inter",
|
||||||
fontSize: scaleRem(profile.cwFontSize || "0.9rem"),
|
fontSize: scaleRem(profile.cwFontSize || "0.9rem"),
|
||||||
fontWeight: Number(profile.cwFontWeight || "700"),
|
fontWeight: Number(profile.cwFontWeight || "700"),
|
||||||
color: adjustColorForDarkMode(profile.cwColor || (darkMode ? "#e5e7eb" : "#333333"), darkMode),
|
color: adjustColorForDarkMode(profile.cwColor || (darkMode ? "#e5e7eb" : "#333333"), darkMode),
|
||||||
}}>
|
}}>
|
||||||
{(isLoading || isSyncing || syncStatus === "syncing") && (
|
|
||||||
<div className="weekly-spinner" title="Syncing..." style={{ width: 14, height: 14 }}></div>
|
|
||||||
)}
|
|
||||||
{syncError && <AlertCircle size={14} className="text-red-500" />}
|
|
||||||
<span>
|
<span>
|
||||||
{(() => {
|
{(() => {
|
||||||
const visibleDays = getVisibleDays();
|
const visibleDays = getVisibleDays();
|
||||||
@ -5621,7 +5623,7 @@ export default function WeeklyView() {
|
|||||||
if (mobileDisplay === "none") return "";
|
if (mobileDisplay === "none") return "";
|
||||||
if (mobileDisplay === "current_day") {
|
if (mobileDisplay === "current_day") {
|
||||||
const fmt = profile.headerCurrentDayFormat || "DDD, DD. MMMM YYYY";
|
const fmt = profile.headerCurrentDayFormat || "DDD, DD. MMMM YYYY";
|
||||||
return formatCustomHeader(fmt, visibleDays, profile.language, t, getSelectedDay(visibleDays));
|
return formatCustomHeader(fmt, visibleDays, profile.language, t, getSelectedDay(visibleDays, selectedDay));
|
||||||
}
|
}
|
||||||
if (mobileDisplay === "date") return new Date().toLocaleDateString(profile.language, { day: '2-digit', month: '2-digit', year: 'numeric' });
|
if (mobileDisplay === "date") return new Date().toLocaleDateString(profile.language, { day: '2-digit', month: '2-digit', year: 'numeric' });
|
||||||
if (mobileDisplay === "month_year") return getCWReferenceDate(visibleDays).toLocaleDateString(profile.language, { month: 'long', year: 'numeric' });
|
if (mobileDisplay === "month_year") return getCWReferenceDate(visibleDays).toLocaleDateString(profile.language, { month: 'long', year: 'numeric' });
|
||||||
@ -5633,6 +5635,15 @@ export default function WeeklyView() {
|
|||||||
<ChevronDown size={12} style={{ opacity: 0.5 }} />
|
<ChevronDown size={12} style={{ opacity: 0.5 }} />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Sync status indicator — fixed width so date never shifts */}
|
||||||
|
<div style={{ width: 24, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
|
||||||
|
{syncError
|
||||||
|
? <AlertCircle size={14} className="text-red-500" title={syncError} />
|
||||||
|
: (isLoading || isSyncing || syncStatus === "syncing")
|
||||||
|
? <div className="weekly-spinner" title="Syncing..." style={{ width: 14, height: 14 }}></div>
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Right: Settings menu */}
|
{/* Right: Settings menu */}
|
||||||
<button className="mobile-header-btn" onClick={() => setShowSettings(true)} title="Settings" style={{ color: darkMode ? "#e5e7eb" : "#6b7280" }}>
|
<button className="mobile-header-btn" onClick={() => setShowSettings(true)} title="Settings" style={{ color: darkMode ? "#e5e7eb" : "#6b7280" }}>
|
||||||
<Menu size={22} />
|
<Menu size={22} />
|
||||||
@ -5767,7 +5778,7 @@ export default function WeeklyView() {
|
|||||||
if (effectiveDisplay === "none") return "";
|
if (effectiveDisplay === "none") return "";
|
||||||
if (effectiveDisplay === "current_day") {
|
if (effectiveDisplay === "current_day") {
|
||||||
const fmt = profile.headerCurrentDayFormat || "DDD, DD. MMMM YYYY";
|
const fmt = profile.headerCurrentDayFormat || "DDD, DD. MMMM YYYY";
|
||||||
return formatCustomHeader(fmt, visibleDays, profile.language, t, getSelectedDay(visibleDays));
|
return formatCustomHeader(fmt, visibleDays, profile.language, t, getSelectedDay(visibleDays, selectedDay));
|
||||||
}
|
}
|
||||||
if (effectiveDisplay === "month") return getCWReferenceDate(visibleDays).toLocaleDateString(profile.language, { month: "long" });
|
if (effectiveDisplay === "month") return getCWReferenceDate(visibleDays).toLocaleDateString(profile.language, { month: "long" });
|
||||||
if (effectiveDisplay === "month_year") return getCWReferenceDate(visibleDays).toLocaleDateString(profile.language, { month: "long", year: "numeric" });
|
if (effectiveDisplay === "month_year") return getCWReferenceDate(visibleDays).toLocaleDateString(profile.language, { month: "long", year: "numeric" });
|
||||||
@ -6653,6 +6664,7 @@ export default function WeeklyView() {
|
|||||||
key={date.toISOString()}
|
key={date.toISOString()}
|
||||||
className={`weekly-day-column ${date.getDay() === 6 ? "is-sat" : ""} ${date.getDay() === 0 ? "is-sun" : ""} ${isToday ? "is-today" : ""} ${isPast ? "is-past" : ""}`}
|
className={`weekly-day-column ${date.getDay() === 6 ? "is-sat" : ""} ${date.getDay() === 0 ? "is-sun" : ""} ${isToday ? "is-today" : ""} ${isPast ? "is-past" : ""}`}
|
||||||
data-date={`${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`}
|
data-date={`${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`}
|
||||||
|
onClick={() => setSelectedDay(date)}
|
||||||
>
|
>
|
||||||
{/* Day Header */}
|
{/* Day Header */}
|
||||||
<header className="weekly-day-header" ref={colIndex === 0 ? dayHeaderRef : undefined}>
|
<header className="weekly-day-header" ref={colIndex === 0 ? dayHeaderRef : undefined}>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user