Merge pull request #12 from gamosoft/features/mobile
added real mobile-friendly support
This commit is contained in:
commit
c184b41a5b
|
|
@ -81,6 +81,9 @@ function noteApp() {
|
||||||
sidebarWidth: CONFIG.DEFAULT_SIDEBAR_WIDTH,
|
sidebarWidth: CONFIG.DEFAULT_SIDEBAR_WIDTH,
|
||||||
isResizing: false,
|
isResizing: false,
|
||||||
|
|
||||||
|
// Mobile sidebar state
|
||||||
|
mobileSidebarOpen: false,
|
||||||
|
|
||||||
// Split view resize state
|
// Split view resize state
|
||||||
editorWidth: 50, // percentage
|
editorWidth: 50, // percentage
|
||||||
isResizingSplit: false,
|
isResizingSplit: false,
|
||||||
|
|
@ -129,6 +132,9 @@ function noteApp() {
|
||||||
this.refreshDOMCache();
|
this.refreshDOMCache();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Setup mobile view mode handler
|
||||||
|
this.setupMobileViewMode();
|
||||||
|
|
||||||
// Watch view mode changes and auto-save
|
// Watch view mode changes and auto-save
|
||||||
this.$watch('viewMode', (newValue) => {
|
this.$watch('viewMode', (newValue) => {
|
||||||
this.saveViewMode();
|
this.saveViewMode();
|
||||||
|
|
@ -832,6 +838,9 @@ function noteApp() {
|
||||||
// Load a specific note
|
// Load a specific note
|
||||||
async loadNote(notePath, updateHistory = true, searchQuery = '') {
|
async loadNote(notePath, updateHistory = true, searchQuery = '') {
|
||||||
try {
|
try {
|
||||||
|
// Close mobile sidebar when a note is selected
|
||||||
|
this.mobileSidebarOpen = false;
|
||||||
|
|
||||||
const response = await fetch(`/api/notes/${notePath}`);
|
const response = await fetch(`/api/notes/${notePath}`);
|
||||||
|
|
||||||
// Check if note exists
|
// Check if note exists
|
||||||
|
|
@ -2081,6 +2090,33 @@ function noteApp() {
|
||||||
document.addEventListener('mouseup', stopResize);
|
document.addEventListener('mouseup', stopResize);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Setup mobile view mode handler (auto-switch from split to edit on mobile)
|
||||||
|
setupMobileViewMode() {
|
||||||
|
const MOBILE_BREAKPOINT = 768; // Match CSS breakpoint
|
||||||
|
let previousWidth = window.innerWidth;
|
||||||
|
|
||||||
|
const handleResize = () => {
|
||||||
|
const currentWidth = window.innerWidth;
|
||||||
|
const wasMobile = previousWidth <= MOBILE_BREAKPOINT;
|
||||||
|
const isMobile = currentWidth <= MOBILE_BREAKPOINT;
|
||||||
|
|
||||||
|
// If switching from desktop to mobile and in split mode
|
||||||
|
if (!wasMobile && isMobile && this.viewMode === 'split') {
|
||||||
|
this.viewMode = 'edit';
|
||||||
|
}
|
||||||
|
|
||||||
|
previousWidth = currentWidth;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for window resize
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
|
||||||
|
// Check initial state
|
||||||
|
if (window.innerWidth <= MOBILE_BREAKPOINT && this.viewMode === 'split') {
|
||||||
|
this.viewMode = 'edit';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Load editor width from localStorage
|
// Load editor width from localStorage
|
||||||
loadEditorWidth() {
|
loadEditorWidth() {
|
||||||
const saved = localStorage.getItem('editorWidth');
|
const saved = localStorage.getItem('editorWidth');
|
||||||
|
|
|
||||||
|
|
@ -568,15 +568,119 @@
|
||||||
.markdown-preview pre code.language-ps .hljs-operator {
|
.markdown-preview pre code.language-ps .hljs-operator {
|
||||||
color: #f472b6 !important; /* Pink for operators */
|
color: #f472b6 !important; /* Pink for operators */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mobile Responsive Styles */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
/* Hide sidebar by default on mobile */
|
||||||
|
.mobile-sidebar {
|
||||||
|
position: fixed;
|
||||||
|
left: -100%;
|
||||||
|
top: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 80% !important;
|
||||||
|
max-width: 300px !important;
|
||||||
|
z-index: 1000;
|
||||||
|
transition: left 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show sidebar when open */
|
||||||
|
.mobile-sidebar-open {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile overlay */
|
||||||
|
.mobile-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 999;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-overlay-visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hamburger button */
|
||||||
|
.mobile-menu-button {
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide desktop resize handle on mobile */
|
||||||
|
.sidebar-resize-handle,
|
||||||
|
.resize-handle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make editor take full width on mobile */
|
||||||
|
.mobile-editor {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack view modes vertically on mobile */
|
||||||
|
.mobile-view-toggle {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smaller buttons on mobile */
|
||||||
|
.mobile-toolbar button {
|
||||||
|
padding: 0.5rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smaller text input on mobile */
|
||||||
|
.mobile-toolbar input {
|
||||||
|
min-width: 100px !important;
|
||||||
|
max-width: 200px !important;
|
||||||
|
font-size: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide split view on mobile (not enough space) */
|
||||||
|
.mobile-hide-split {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make toolbar wrap on very small screens */
|
||||||
|
.mobile-toolbar {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Larger touch targets */
|
||||||
|
.note-item,
|
||||||
|
.folder-item {
|
||||||
|
padding: 0.75rem !important;
|
||||||
|
min-height: 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide mobile menu button on desktop */
|
||||||
|
@media (min-width: 769px) {
|
||||||
|
.mobile-menu-button {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body x-data="noteApp()" x-init="init()" style="background-color: var(--bg-primary);">
|
<body x-data="noteApp()" x-init="init()" style="background-color: var(--bg-primary);">
|
||||||
|
|
||||||
|
<!-- Mobile Overlay -->
|
||||||
|
<div
|
||||||
|
@click="mobileSidebarOpen = false"
|
||||||
|
:class="{'mobile-overlay': true, 'mobile-overlay-visible': mobileSidebarOpen}"
|
||||||
|
x-show="mobileSidebarOpen"
|
||||||
|
></div>
|
||||||
|
|
||||||
<!-- Main Container -->
|
<!-- Main Container -->
|
||||||
<div class="flex h-screen overflow-hidden">
|
<div class="flex h-screen overflow-hidden">
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div class="flex flex-col" :style="'width: ' + sidebarWidth + 'px; background-color: var(--bg-secondary); border-right: 1px solid var(--border-primary); min-width: 200px; max-width: 600px;'">
|
<div
|
||||||
|
class="flex flex-col mobile-sidebar"
|
||||||
|
:class="{'mobile-sidebar-open': mobileSidebarOpen}"
|
||||||
|
:style="'width: ' + sidebarWidth + 'px; background-color: var(--bg-secondary); border-right: 1px solid var(--border-primary); min-width: 200px; max-width: 600px;'"
|
||||||
|
>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="p-4 border-b" style="border-color: var(--border-primary);">
|
<div class="p-4 border-b" style="border-color: var(--border-primary);">
|
||||||
<div class="flex items-center gap-2 mb-3">
|
<div class="flex items-center gap-2 mb-3">
|
||||||
|
|
@ -839,14 +943,27 @@
|
||||||
<!-- Editor Area -->
|
<!-- Editor Area -->
|
||||||
<div class="flex-1 flex flex-col overflow-hidden" style="background-color: var(--bg-primary);">
|
<div class="flex-1 flex flex-col overflow-hidden" style="background-color: var(--bg-primary);">
|
||||||
<!-- Toolbar -->
|
<!-- Toolbar -->
|
||||||
<div class="px-4 py-3 flex items-center justify-between" style="background-color: var(--bg-secondary); border-bottom: 1px solid var(--border-primary);">
|
<div class="px-4 py-3 flex items-center justify-between mobile-toolbar" style="background-color: var(--bg-secondary); border-bottom: 1px solid var(--border-primary);">
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
|
<!-- Mobile Menu Button -->
|
||||||
|
<button
|
||||||
|
@click="mobileSidebarOpen = !mobileSidebarOpen"
|
||||||
|
class="mobile-menu-button p-2 rounded-lg"
|
||||||
|
style="color: var(--text-primary); display: none;"
|
||||||
|
onmouseover="this.style.backgroundColor='var(--bg-hover)'"
|
||||||
|
onmouseout="this.style.backgroundColor='transparent'"
|
||||||
|
title="Toggle sidebar"
|
||||||
|
>
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
x-model="currentNoteName"
|
x-model="currentNoteName"
|
||||||
@blur="renameNote()"
|
@blur="renameNote()"
|
||||||
class="text-xl font-semibold border-none focus:outline-none focus:ring-2 rounded px-3 py-1.5"
|
class="text-xl font-semibold border-none focus:outline-none focus:ring-2 rounded px-3 py-1.5"
|
||||||
style="background-color: var(--bg-primary); color: var(--text-primary); border: 1px solid var(--border-primary); min-width: 300px;"
|
style="background-color: var(--bg-primary); color: var(--text-primary); border: 1px solid var(--border-primary); min-width: 150px; max-width: 300px;"
|
||||||
>
|
>
|
||||||
<!-- Undo Button -->
|
<!-- Undo Button -->
|
||||||
<button
|
<button
|
||||||
|
|
@ -900,21 +1017,21 @@
|
||||||
<div class="flex rounded-lg p-1" style="background-color: var(--bg-tertiary);">
|
<div class="flex rounded-lg p-1" style="background-color: var(--bg-tertiary);">
|
||||||
<button
|
<button
|
||||||
@click="viewMode = 'edit'"
|
@click="viewMode = 'edit'"
|
||||||
class="px-3 py-1 text-sm rounded transition"
|
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||||
:style="viewMode === 'edit' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
:style="viewMode === 'edit' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="viewMode = 'split'"
|
@click="viewMode = 'split'"
|
||||||
class="px-3 py-1 text-sm rounded transition"
|
class="mobile-hide-split px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||||
:style="viewMode === 'split' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
:style="viewMode === 'split' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||||
>
|
>
|
||||||
Split
|
Split
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="viewMode = 'preview'"
|
@click="viewMode = 'preview'"
|
||||||
class="px-3 py-1 text-sm rounded transition"
|
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||||
:style="viewMode === 'preview' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
:style="viewMode === 'preview' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||||
>
|
>
|
||||||
Preview
|
Preview
|
||||||
|
|
@ -925,11 +1042,12 @@
|
||||||
<button
|
<button
|
||||||
x-show="currentNote"
|
x-show="currentNote"
|
||||||
@click="exportToHTML()"
|
@click="exportToHTML()"
|
||||||
class="px-3 py-1.5 text-sm rounded transition hover:opacity-80"
|
class="px-2 md:px-3 py-1 md:py-1.5 text-xs md:text-sm rounded transition hover:opacity-80"
|
||||||
style="background-color: var(--accent-secondary); color: var(--text-primary);"
|
style="background-color: var(--accent-secondary); color: var(--text-primary);"
|
||||||
title="Export as HTML"
|
title="Export as HTML"
|
||||||
>
|
>
|
||||||
📄 Export HTML
|
<span class="hidden md:inline">📄 Export HTML</span>
|
||||||
|
<span class="md:hidden">📄</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue