about summary refs log tree commit diff stats
path: root/html/file-system
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-12-22 21:29:35 -0500
committerelioat <elioat@tilde.institute>2024-12-22 21:29:35 -0500
commit8846eb4d7a16bd905547fa7567f539aa901dd92a (patch)
tree5088ac337d72e7af3f854255af30b07ad078b29b /html/file-system
parent7391ee4f44b084abdd987a529ff94a9c813c68b5 (diff)
downloadtour-8846eb4d7a16bd905547fa7567f539aa901dd92a.tar.gz
*
Diffstat (limited to 'html/file-system')
-rw-r--r--html/file-system/index.html162
1 files changed, 158 insertions, 4 deletions
diff --git a/html/file-system/index.html b/html/file-system/index.html
index 397427f..45bfaaf 100644
--- a/html/file-system/index.html
+++ b/html/file-system/index.html
@@ -427,6 +427,81 @@
         .folder.editing input:focus {
             border-color: #0078fa;
         }
+
+        #viewControls {
+            position: absolute;
+            top: 1em;
+            right: 1em;
+        }
+
+        .view-toggle {
+            padding: 0.5em;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            background: white;
+            cursor: pointer;
+            transition: background-color 0.2s;
+        }
+
+        .view-toggle:hover {
+            background-color: #f0f0f0;
+        }
+
+        #breadcrumbs {
+            padding: 0.5em;
+            margin-bottom: 1em;
+            border-bottom: 1px solid #e0e0e0;
+            display: none; /* Hidden in tree view */
+        }
+
+        .breadcrumb-item {
+            display: inline-block;
+            cursor: pointer;
+            padding: 0.2em 0.5em;
+            border-radius: 3px;
+        }
+
+        .breadcrumb-item:hover {
+            background-color: rgba(0, 0, 0, 0.05);
+        }
+
+        .breadcrumb-separator {
+            margin: 0 0.5em;
+            color: #666;
+        }
+
+        /* Grid view styles */
+        .grid-view {
+            display: none; /* Hidden by default */
+            grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
+            gap: 1em;
+            padding: 1em;
+        }
+
+        .grid-folder {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            padding: 1em;
+            cursor: pointer;
+            border-radius: 4px;
+            text-align: center;
+        }
+
+        .grid-folder:hover {
+            background-color: rgba(0, 0, 0, 0.05);
+        }
+
+        .grid-folder-icon {
+            font-size: 2em;
+            margin-bottom: 0.5em;
+        }
+
+        .grid-folder-name {
+            font-size: 0.9em;
+            word-break: break-word;
+            max-width: 100%;
+        }
     </style>
 </head>
 <body>
@@ -443,6 +518,7 @@
 <div id="fileSystemContainer" oncontextmenu="showContextMenu(event, 'root')">
     <div class="root-folder" onclick="selectFolder('root')">~</div>
     <ul id="fileSystemTree"></ul>
+    <div class="grid-view"></div>
     <div class="empty-state" style="display: none;">
         <div class="empty-state-text">No folders yet</div>
         <div class="empty-state-hint">Right-click or use the menu to create a folder</div>
@@ -472,6 +548,14 @@
     <div class="context-menu-item delete" onclick="deleteItem()">Delete</div>
 </div>
 
+<div id="viewControls">
+    <button class="view-toggle" onclick="toggleView()" title="Toggle View">
+        <span class="tree-icon">🌳</span>/<span class="grid-icon">📱</span>
+    </button>
+</div>
+
+<div id="breadcrumbs"></div>
+
 <script>
 const initialState = () => ({
     root: { type: 'folder', children: {}, content: '' }
@@ -484,7 +568,8 @@ const state = {
     currentFolderPath: 'root',
     copiedFolderData: null,
     copiedItemPath: null,
-    draggedPath: null
+    draggedPath: null,
+    viewMode: 'tree' // 'tree' or 'grid'
 };
 
 const clone = (obj) => JSON.parse(JSON.stringify(obj));
@@ -751,9 +836,28 @@ const render = () => {
         return;
     }
 
-    const entries = Object.entries(state.fileSystem.root.children);
-    const isEmpty = entries.length === 0;
-    
+    // Show/hide breadcrumbs based on view mode
+    document.getElementById('breadcrumbs').style.display = 
+        state.viewMode === 'grid' ? 'block' : 'none';
+
+    // Update current folder content based on view mode
+    if (state.viewMode === 'tree') {
+        document.getElementById('fileSystemTree').style.display = 'block';
+        document.querySelector('.grid-view').style.display = 'none';
+        document.getElementById('fileSystemTree').innerHTML = 
+            renderFolderTree(state.fileSystem.root);
+    } else {
+        document.getElementById('fileSystemTree').style.display = 'none';
+        document.querySelector('.grid-view').style.display = 'grid';
+        const currentFolder = state.currentFolderPath === 'root' ? 
+            state.fileSystem.root : 
+            getFolder(state.currentFolderPath);
+        document.querySelector('.grid-view').innerHTML = 
+            renderGridView(currentFolder);
+    }
+
+    renderBreadcrumbs();
+
     // Update path displays
     const currentPath = state.currentFolderPath.replace('root', '') || '/';
     document.title = `Folder: ${currentPath}`;
@@ -1018,6 +1122,56 @@ const handleFolderDoubleClick = (e) => {
 
 document.addEventListener('dblclick', handleFolderDoubleClick);
 
+const toggleView = () => {
+    state.viewMode = state.viewMode === 'tree' ? 'grid' : 'tree';
+    render();
+};
+
+const navigateTo = (path, openDetails = false) => {
+    state.currentFolderPath = path;
+    
+    // Only open folder details if explicitly requested (from breadcrumbs)
+    if (openDetails) {
+        const folder = path === 'root' ? state.fileSystem.root : getFolder(path);
+        if (folder) {
+            document.getElementById('folderContent').value = folder.content || '';
+            editor.style.display = 'block';
+            setEditorSize('normal');
+        }
+    }
+    
+    render();
+};
+
+const renderBreadcrumbs = () => {
+    const parts = state.currentFolderPath.split('/');
+    const breadcrumbs = parts.map((part, index) => {
+        const path = parts.slice(0, index + 1).join('/');
+        const isLastItem = index === parts.length - 1;
+        
+        // Only pass openDetails=true for the last item in the breadcrumb
+        return `
+            <span class="breadcrumb-item" 
+                onclick="navigateTo('${path}', ${isLastItem})">${part === 'root' ? '~' : part}</span>
+            ${index < parts.length - 1 ? '<span class="breadcrumb-separator">/</span>' : ''}
+        `;
+    }).join('');
+
+    document.getElementById('breadcrumbs').innerHTML = breadcrumbs;
+};
+
+const renderGridView = (folder) => {
+    const entries = Object.entries(folder.children);
+    return entries.map(([name, item]) => `
+        <div class="grid-folder" 
+            onclick="navigateTo('${state.currentFolderPath}/${name}')"
+            oncontextmenu="showContextMenu(event, '${state.currentFolderPath}/${name}')">
+            <div class="grid-folder-icon">📁</div>
+            <div class="grid-folder-name">${name}</div>
+        </div>
+    `).join('');
+};
+
 render();
 </script>