Improve mobile/iOS support and simplify theme handling

- Add iOS/mobile meta tags for better web app experience
- Enhance Editor.razor.css for mobile responsiveness and touch
- Simplify theme logic: only light/dark, no "auto" mode
- Remove localStorage and system theme detection from theme.js
- Apply themes via CSS variables for better compatibility
- Update ThemeToggle to match new theme logic and improve UX
This commit is contained in:
Michal Vrba
2026-01-31 12:58:15 +01:00
parent e5edc372fe
commit 5a06a307fb
4 changed files with 90 additions and 56 deletions
+5 -1
View File
@@ -3,7 +3,11 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Notemark" />
<meta name="mobile-web-app-capable" content="yes" />
<base href="/" /> <base href="/" />
<ResourcePreloader /> <ResourcePreloader />
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" /> <link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
+48 -10
View File
@@ -1,5 +1,4 @@
/* Notemark Editor Styles */ /* Notemark Editor Styles */
.editor-container { .editor-container {
height: 100vh; height: 100vh;
display: flex; display: flex;
@@ -458,37 +457,76 @@
background-color: white; background-color: white;
} }
/* Mobile Responsive */ /* Mobile Responsive - Place at end to override desktop styles */
@media (max-width: 768px) { @media screen and (max-width: 768px) {
.editor-layout.split-view { .editor-layout.split-view {
flex-direction: column; flex-direction: column !important;
} }
.split-view .editor-pane { .split-view .editor-pane {
border-right: none; border-right: none;
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
flex: 1;
}
.preview-pane {
flex: 1;
}
.splitter {
display: none;
} }
.top-bar { .top-bar {
padding: 0.5rem; padding: 0.5rem;
height: auto;
min-height: 50px;
flex-wrap: wrap;
gap: 0.5rem;
}
.top-bar-left,
.top-bar-center,
.top-bar-right {
gap: 0.5rem;
} }
.btn-toggle, .btn-toggle,
.btn-share, .btn-share,
.btn-save, .btn-save,
.btn-new { .btn-new {
font-size: 0.75rem; font-size: 14px;
padding: 0.375rem 0.75rem; padding: 8px 12px;
min-height: 44px;
white-space: nowrap;
} }
.btn-save { .btn-save {
padding: 0.375rem; min-width: 44px;
min-width: 2rem; padding: 8px;
font-size: 0.875rem; }
.markdown-editor {
font-size: 16px; /* Prevent iOS zoom */
padding: 1rem;
-webkit-overflow-scrolling: touch;
} }
.markdown-editor,
.preview-content { .preview-content {
padding: 1rem; padding: 1rem;
-webkit-overflow-scrolling: touch;
}
/* Share dropdown mobile adjustments */
.share-dropdown {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90vw;
max-width: 320px;
z-index: 1000;
} }
} }
+12 -28
View File
@@ -5,39 +5,35 @@
</button> </button>
@code { @code {
private string currentTheme = "auto"; private string currentTheme = "light";
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
try try
{ {
await JSRuntime.InvokeVoidAsync("notemarkTheme.init");
currentTheme = await JSRuntime.InvokeAsync<string>("notemarkTheme.getCurrentTheme"); currentTheme = await JSRuntime.InvokeAsync<string>("notemarkTheme.getCurrentTheme");
} }
catch catch (Exception ex)
{ {
// Fallback if JS not ready System.Diagnostics.Debug.WriteLine($"Theme init error: {ex.Message}");
currentTheme = "auto"; currentTheme = "light";
} }
} }
private async Task ToggleTheme() private async Task ToggleTheme()
{ {
// Cycle through: auto -> light -> dark -> auto // Simple toggle: light <-> dark
currentTheme = currentTheme switch currentTheme = currentTheme == "light" ? "dark" : "light";
{
"auto" => "light",
"light" => "dark",
"dark" => "auto",
_ => "auto"
};
try try
{ {
await JSRuntime.InvokeVoidAsync("notemarkTheme.setTheme", currentTheme); await JSRuntime.InvokeVoidAsync("notemarkTheme.setTheme", currentTheme);
System.Diagnostics.Debug.WriteLine($"Theme switched to: {currentTheme}");
} }
catch catch (Exception ex)
{ {
// JS not ready, silently fail System.Diagnostics.Debug.WriteLine($"Theme toggle error: {ex.Message}");
} }
StateHasChanged(); StateHasChanged();
@@ -45,23 +41,11 @@
private string GetThemeIcon() private string GetThemeIcon()
{ {
return currentTheme switch return currentTheme == "dark" ? "🌙" : "☀️";
{
"light" => "☀️",
"dark" => "🌙",
"auto" => "🔄",
_ => "🔄"
};
} }
private string GetThemeTooltip() private string GetThemeTooltip()
{ {
return currentTheme switch return currentTheme == "dark" ? "Switch to light mode" : "Switch to dark mode";
{
"light" => "Switch to dark mode",
"dark" => "Switch to auto mode",
"auto" => "Switch to light mode",
_ => "Toggle theme"
};
} }
} }
+24 -16
View File
@@ -1,35 +1,43 @@
// Ultra-simple theme for iOS testing
window.notemarkTheme = { window.notemarkTheme = {
currentTheme: 'light',
init: function() { init: function() {
// Get saved theme or default to 'auto' console.log('Simple theme init');
const savedTheme = localStorage.getItem('notemark-theme') || 'auto'; this.applyTheme(this.currentTheme);
this.applyTheme(savedTheme); return this.currentTheme;
return savedTheme;
}, },
setTheme: function(theme) { setTheme: function(theme) {
localStorage.setItem('notemark-theme', theme); console.log('Setting theme:', theme);
this.currentTheme = theme;
this.applyTheme(theme); this.applyTheme(theme);
}, },
applyTheme: function(theme) { applyTheme: function(theme) {
console.log('Applying theme:', theme);
const root = document.documentElement; const root = document.documentElement;
if (theme === 'light') { if (theme === 'dark') {
root.setAttribute('data-theme', 'light'); root.style.setProperty('--bg', '#1a1a1a');
} else if (theme === 'dark') { root.style.setProperty('--surface', '#2d2d2d');
root.setAttribute('data-theme', 'dark'); root.style.setProperty('--primary-text', '#ffffff');
root.style.setProperty('--secondary-text', '#cccccc');
root.style.setProperty('--border', '#404040');
root.style.setProperty('--accent', '#007acc');
} else { } else {
// For 'auto', remove data-theme to let CSS @media handle it root.style.setProperty('--bg', '#ffffff');
root.removeAttribute('data-theme'); root.style.setProperty('--surface', '#f8f9fa');
root.style.setProperty('--primary-text', '#333333');
root.style.setProperty('--secondary-text', '#666666');
root.style.setProperty('--border', '#e9ecef');
root.style.setProperty('--accent', '#007acc');
} }
}, console.log('Theme applied successfully');
getSystemTheme: function() {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}, },
getCurrentTheme: function() { getCurrentTheme: function() {
return localStorage.getItem('notemark-theme') || 'auto'; return this.currentTheme;
} }
}; };