feat: add mobile font scale setting
New setting in Settings > Styling that scales all fonts on mobile devices (75% / 85% / 100% / 115% / 130%). Applies to day names, dates, tasks, events, and the mobile header date. Also scales the CW/date display in the mobile header via scaleRem(). New DB field: mobileFontScale (Float, default 1.0) v1.38.0
This commit is contained in:
parent
2ad55fe1bd
commit
43169c0bfc
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "my-weekly-todo-list",
|
"name": "my-weekly-todo-list",
|
||||||
"version": "1.37.4",
|
"version": "1.38.0",
|
||||||
"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": {
|
||||||
|
|||||||
@ -100,6 +100,7 @@ model User {
|
|||||||
weekdayFormat String? @default("long")
|
weekdayFormat String? @default("long")
|
||||||
weekdayCase String? @default("capitalize")
|
weekdayCase String? @default("capitalize")
|
||||||
customWeekdayNames String? @default("")
|
customWeekdayNames String? @default("")
|
||||||
|
mobileFontScale Float @default(1.0)
|
||||||
startDayOffset Int @default(-1)
|
startDayOffset Int @default(-1)
|
||||||
quoteSourceUrls String[] @default([])
|
quoteSourceUrls String[] @default([])
|
||||||
quoteLanguages String[] @default(["en", "de"])
|
quoteLanguages String[] @default(["en", "de"])
|
||||||
|
|||||||
@ -96,6 +96,7 @@ export async function GET(request: NextRequest) {
|
|||||||
lightTheme: true,
|
lightTheme: true,
|
||||||
darkTheme: true,
|
darkTheme: true,
|
||||||
notificationsEnabled: true,
|
notificationsEnabled: true,
|
||||||
|
mobileFontScale: true,
|
||||||
createdAt: true
|
createdAt: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -138,7 +139,7 @@ export async function PATCH(request: NextRequest) {
|
|||||||
yearFontFamily, yearFontSize, yearFontWeight, yearColor,
|
yearFontFamily, yearFontSize, yearFontWeight, yearColor,
|
||||||
showTaskCheckboxes, dayHeaderGap,
|
showTaskCheckboxes, dayHeaderGap,
|
||||||
showCompletedTasks, showLines, startDayOffset, weekdayFormat, weekdayCase, customWeekdayNames, quoteSourceUrls, quoteLanguages,
|
showCompletedTasks, showLines, startDayOffset, weekdayFormat, weekdayCase, customWeekdayNames, quoteSourceUrls, quoteLanguages,
|
||||||
kanbanStages, lightTheme, darkTheme, notificationsEnabled
|
kanbanStages, lightTheme, darkTheme, notificationsEnabled, mobileFontScale
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
const updateData: any = {
|
const updateData: any = {
|
||||||
@ -223,6 +224,7 @@ export async function PATCH(request: NextRequest) {
|
|||||||
...(lightTheme !== undefined && { lightTheme }),
|
...(lightTheme !== undefined && { lightTheme }),
|
||||||
...(darkTheme !== undefined && { darkTheme }),
|
...(darkTheme !== undefined && { darkTheme }),
|
||||||
...(notificationsEnabled !== undefined && { notificationsEnabled }),
|
...(notificationsEnabled !== undefined && { notificationsEnabled }),
|
||||||
|
...(mobileFontScale !== undefined && { mobileFontScale: parseFloat(mobileFontScale) || 1.0 }),
|
||||||
};
|
};
|
||||||
if (password && password.trim() !== "") {
|
if (password && password.trim() !== "") {
|
||||||
updateData.passwordHash = await bcrypt.hash(password, 10);
|
updateData.passwordHash = await bcrypt.hash(password, 10);
|
||||||
@ -316,6 +318,7 @@ export async function PATCH(request: NextRequest) {
|
|||||||
lightTheme: true,
|
lightTheme: true,
|
||||||
darkTheme: true,
|
darkTheme: true,
|
||||||
notificationsEnabled: true,
|
notificationsEnabled: true,
|
||||||
|
mobileFontScale: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -4980,10 +4980,11 @@ export default function WeeklyView() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const fontSizeScale = fontSize === "S" ? 0.85 : fontSize === "L" ? 1.15 : 1;
|
const fontSizeScale = fontSize === "S" ? 0.85 : fontSize === "L" ? 1.15 : 1;
|
||||||
|
const mobileScale = isMobile ? (profile.mobileFontScale || 1.0) : 1.0;
|
||||||
const fontVal = (v: string | undefined) => v && v !== "__custom__" ? v : "";
|
const fontVal = (v: string | undefined) => v && v !== "__custom__" ? v : "";
|
||||||
const scaleRem = (base: string) => {
|
const scaleRem = (base: string) => {
|
||||||
const num = parseFloat(base);
|
const num = parseFloat(base);
|
||||||
return `${(num * fontSizeScale).toFixed(3)}rem`;
|
return `${(num * fontSizeScale * mobileScale).toFixed(3)}rem`;
|
||||||
};
|
};
|
||||||
const activeTheme = (darkMode ? profile.darkTheme : profile.lightTheme) as Record<string, string> | null;
|
const activeTheme = (darkMode ? profile.darkTheme : profile.lightTheme) as Record<string, string> | null;
|
||||||
|
|
||||||
@ -5548,7 +5549,7 @@ export default function WeeklyView() {
|
|||||||
{/* Center: Date display (tap to jump to date) */}
|
{/* Center: Date display (tap to jump to date) */}
|
||||||
<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: 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),
|
||||||
}}>
|
}}>
|
||||||
@ -11914,6 +11915,55 @@ function SettingsSidebar({
|
|||||||
<div
|
<div
|
||||||
style={{ display: "flex", flexDirection: "column", gap: "24px" }}
|
style={{ display: "flex", flexDirection: "column", gap: "24px" }}
|
||||||
>
|
>
|
||||||
|
{/* Mobile Font Scale */}
|
||||||
|
<div style={{
|
||||||
|
background: "var(--weekly-settings-item-bg)",
|
||||||
|
padding: "12px",
|
||||||
|
borderRadius: "8px",
|
||||||
|
}}>
|
||||||
|
<label style={{
|
||||||
|
display: "block", fontSize: "0.85rem", fontWeight: 600,
|
||||||
|
marginBottom: "8px", color: "var(--weekly-settings-label)",
|
||||||
|
}}>
|
||||||
|
{(profile.language || "en") === "de" ? "Mobile Schriftgröße" : "Mobile Font Scale"}
|
||||||
|
</label>
|
||||||
|
<div style={{ display: "flex", gap: "6px" }}>
|
||||||
|
{[
|
||||||
|
{ label: "75%", value: 0.75 },
|
||||||
|
{ label: "85%", value: 0.85 },
|
||||||
|
{ label: "100%", value: 1.0 },
|
||||||
|
{ label: "115%", value: 1.15 },
|
||||||
|
{ label: "130%", value: 1.3 },
|
||||||
|
].map(opt => (
|
||||||
|
<button
|
||||||
|
key={opt.value}
|
||||||
|
onClick={() => {
|
||||||
|
setProfile({ ...profile, mobileFontScale: opt.value });
|
||||||
|
saveSetting("mobileFontScale", opt.value);
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
flex: 1, padding: "6px 4px", borderRadius: "6px",
|
||||||
|
border: (profile.mobileFontScale || 1.0) === opt.value
|
||||||
|
? "2px solid var(--weekly-teal, #0ea5e9)"
|
||||||
|
: "1px solid var(--weekly-border, #ddd)",
|
||||||
|
background: (profile.mobileFontScale || 1.0) === opt.value
|
||||||
|
? "var(--weekly-teal, #0ea5e9)" : "transparent",
|
||||||
|
color: (profile.mobileFontScale || 1.0) === opt.value
|
||||||
|
? "white" : "var(--weekly-text)",
|
||||||
|
fontSize: "0.8rem", fontWeight: 600, cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{opt.label}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<span style={{ fontSize: "0.7rem", color: "var(--weekly-text-light)", marginTop: "4px", display: "block" }}>
|
||||||
|
{(profile.language || "en") === "de"
|
||||||
|
? "Skaliert alle Schriften auf Mobilgeräten (< 768px)"
|
||||||
|
: "Scales all fonts on mobile devices (< 768px)"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Typography Settings */}
|
{/* Typography Settings */}
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user