annotate hg-web/src/repo-browser.tsx @ 191:a06710325c30 hg-web

[HgWeb] Fully working copy.
author MrJuneJune <me@mrjunejune.com>
date Sat, 24 Jan 2026 21:51:51 -0800
parents a2725419f988
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
1 import React, { useState, useEffect, useRef, useCallback } from 'react';
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
2 import createMarkdownModule from 'markdown_converter/markdown_to_html_wasm/markdown_to_html_bin.js';
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
3 import hljs from 'third_party/highlight/highlight.min.js';
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
4
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
5 // --- ICONS (served as static files) ---
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
6 const ICONS = {
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
7 folder: "/icons/folder.png",
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
8 file: "/icons/file.svg",
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
9 home: "/icons/home.png",
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
10 repo: "/public/epi_all_colors.svg",
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
11 close: "/icons/close.png"
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
12 };
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
14 // SVG Icons for theme toggle
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
15 const SunIcon = ({ color = "currentColor" }: { color?: string }) => (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
16 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
17 <circle cx="12" cy="12" r="5"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
18 <line x1="12" y1="1" x2="12" y2="3"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
19 <line x1="12" y1="21" x2="12" y2="23"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
20 <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
21 <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
22 <line x1="1" y1="12" x2="3" y2="12"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
23 <line x1="21" y1="12" x2="23" y2="12"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
24 <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
25 <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
26 </svg>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
27 );
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
28
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
29 const MoonIcon = ({ color = "currentColor" }: { color?: string }) => (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
30 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
31 <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
32 </svg>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
33 );
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
34
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 const API_BASE = '/api/repo';
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
37 // File extensions that should be displayed as code
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
38 const CODE_EXTENSIONS = new Set([
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
39 'js', 'jsx', 'ts', 'tsx', 'py', 'rb', 'java', 'c', 'cpp', 'h', 'hpp',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
40 'cs', 'go', 'rs', 'swift', 'kt', 'scala', 'php', 'pl', 'sh', 'bash',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
41 'zsh', 'fish', 'ps1', 'bat', 'cmd', 'html', 'htm', 'css', 'scss',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
42 'sass', 'less', 'json', 'xml', 'yaml', 'yml', 'toml', 'ini', 'cfg',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
43 'conf', 'md', 'markdown', 'txt', 'log', 'sql', 'graphql', 'vue',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
44 'svelte', 'astro', 'prisma', 'dockerfile', 'makefile', 'cmake',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
45 'gradle', 'pom', 'lock', 'gitignore', 'env', 'example', 'sample'
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
46 ]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
47
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
48 // Prefetch cache
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
49 const prefetchCache = new Map<string, Promise<any>>();
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
50
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
51 function isCodeFile(filename: string): boolean {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
52 const ext = filename.split('.').pop()?.toLowerCase() || '';
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
53 const basename = filename.toLowerCase();
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
54 return CODE_EXTENSIONS.has(ext) ||
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
55 CODE_EXTENSIONS.has(basename) ||
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
56 basename === 'dockerfile' ||
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
57 basename === 'makefile' ||
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
58 basename.startsWith('.');
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
59 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
60
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
61 function isMarkdownFile(filename: string): boolean {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
62 const ext = filename.split('.').pop()?.toLowerCase() || '';
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
63 return ext === 'md' || ext === 'markdown';
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
64 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
65
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
66 function prefetchDirectory(path: string): void {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
67 const cacheKey = `dir:${path}`;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
68 if (prefetchCache.has(cacheKey)) return;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
69
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
70 const url = path
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
71 ? `${API_BASE}/list?path=${encodeURIComponent(path)}`
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
72 : `${API_BASE}/list`;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
73
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
74 prefetchCache.set(cacheKey, fetch(url).then(r => r.json()).catch(() => null));
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
75 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
76
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
77 function prefetchFile(path: string): void {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
78 const cacheKey = `file:${path}`;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
79 if (prefetchCache.has(cacheKey)) return;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
80
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
81 prefetchCache.set(cacheKey,
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
82 fetch(`${API_BASE}/file?path=${encodeURIComponent(path)}`)
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
83 .then(r => r.ok ? r.text() : null)
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
84 .catch(() => null)
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
85 );
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
86 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
87
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
88 async function getCachedFile(path: string): Promise<string | null> {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
89 const cacheKey = `file:${path}`;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
90 if (prefetchCache.has(cacheKey)) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
91 return prefetchCache.get(cacheKey);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
92 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
93 prefetchFile(path);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
94 return prefetchCache.get(cacheKey)!;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
95 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
96
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97 /**
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
98 * Component: Styles
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
99 * Injected CSS for the polished look with dark/light mode support
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
100 */
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
101 const GlobalStyles = ({ isDark }: { isDark: boolean }) => (
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
102 <style>{`
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
103 :root {
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
104 --bg-color: ${isDark ? '#0d1117' : '#ffffff'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
105 --bg-subtle: ${isDark ? '#161b22' : '#f6f8fa'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
106 --bg-code: ${isDark ? '#1c2128' : '#f6f8fa'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
107 --border-color: ${isDark ? '#30363d' : '#d0d7de'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
108 --accent-color: ${isDark ? '#58a6ff' : '#0969da'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
109 --text-primary: ${isDark ? '#e6edf3' : '#1f2328'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
110 --text-secondary: ${isDark ? '#8b949e' : '#656d76'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
111 --hover-color: ${isDark ? '#1c2128' : '#f3f4f6'};
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
112 --radius: 6px;
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
113 --code-bg: ${isDark ? '#161b22' : '#ffffff'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
114 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
115
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
116 body {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
117 background: var(--bg-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
118 transition: background 0.2s;
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
119 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
120
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
121 .repo-container {
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
122 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
123 max-width: 980px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
124 margin: 40px auto;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
125 color: var(--text-primary);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
126 padding: 0 20px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
127 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
128
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
129 /* Header */
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
130 .header {
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
131 display: flex;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
132 align-items: center;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
133 margin-bottom: 20px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
134 gap: 15px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
135 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
136 .header-icon { width: 32px; height: 32px; opacity: 0.8; }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
137 .header h1 { margin: 0; font-size: 24px; font-weight: 600; }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
138 .description { color: var(--text-secondary); margin: 0; font-size: 14px; }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
139
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
140 /* Theme Toggle */
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
141 .theme-toggle {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
142 margin-left: auto;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
143 background: var(--bg-subtle);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
144 border: 1px solid var(--border-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
145 border-radius: var(--radius);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
146 padding: 8px 12px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
147 cursor: pointer;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
148 display: flex;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
149 align-items: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
150 gap: 6px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
151 color: var(--text-secondary);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
152 font-size: 13px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
153 transition: all 0.2s;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
154 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
155 .theme-toggle:hover {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
156 background: var(--hover-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
157 color: var(--text-primary);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
158 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
159 .theme-toggle svg {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
160 flex-shrink: 0;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
161 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
162
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
163 /* Clone Box */
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
164 .clone-box {
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
165 background: var(--bg-subtle);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
166 border: 1px solid var(--border-color);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
167 border-radius: var(--radius);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
168 padding: 12px 16px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
169 margin-bottom: 24px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
170 display: flex;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
171 justify-content: space-between;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
172 align-items: center;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
173 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
174 .clone-label { font-weight: 600; font-size: 13px; margin-right: 10px; color: var(--text-primary); }
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
175 .clone-url {
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
176 font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
177 background: var(--bg-color);
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
178 border: 1px solid var(--border-color);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
179 padding: 4px 8px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
180 border-radius: 4px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
181 font-size: 12px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
182 color: var(--text-secondary);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
183 flex-grow: 1;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
184 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
185
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
186 /* Breadcrumb */
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
187 #breadcrumb {
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
188 display: flex;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
189 align-items: center;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
190 font-size: 14px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
191 margin-bottom: 16px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
192 color: var(--text-secondary);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
193 padding: 8px 0;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
194 }
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
195 #breadcrumb a {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
196 color: var(--accent-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
197 text-decoration: none;
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
198 border-radius: 4px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
199 padding: 2px 6px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
200 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
201 #breadcrumb a:hover { background: var(--bg-subtle); text-decoration: underline; }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
202 #breadcrumb .separator { margin: 0 4px; color: var(--text-secondary); opacity: 0.5; }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
203 #breadcrumb .nav-item.active { font-weight: 600; color: var(--text-primary); padding: 2px 6px;}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
204
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
205 /* File List Table Structure */
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
206 .file-list-container {
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
207 border: 1px solid var(--border-color);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
208 border-radius: var(--radius);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
209 overflow: hidden;
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
210 background: var(--bg-color);
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
211 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
212 .file-header {
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
213 background: var(--bg-subtle);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
214 border-bottom: 1px solid var(--border-color);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
215 padding: 12px 16px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
216 font-size: 13px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
217 font-weight: 600;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
218 color: var(--text-secondary);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
219 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
220 .empty-state { padding: 40px; text-align: center; color: var(--text-secondary); }
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
221 .error-message {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
222 padding: 15px; border: 1px solid ${isDark ? '#f8514966' : '#ffdce0'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
223 background: ${isDark ? '#f8514926' : '#ffebe9'}; color: ${isDark ? '#f85149' : '#cf222e'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
224 border-radius: var(--radius); margin-bottom: 20px;
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
225 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
226
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
227 /* File Row */
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
228 .file-row {
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
229 display: flex;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
230 align-items: center;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
231 padding: 10px 16px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
232 border-bottom: 1px solid var(--border-color);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
233 transition: background 0.1s;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
234 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
235 .file-row:last-child { border-bottom: none; }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
236 .file-row:hover { background: var(--hover-color); }
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
237
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
238 .file-row .icon img {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
239 width: 20px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
240 height: 20px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
241 vertical-align: middle;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
242 margin-right: 12px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
243 filter: ${isDark ? 'invert(0.8)' : 'none'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
244 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
245 .file-row .name a {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
246 color: var(--text-primary);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
247 text-decoration: none;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
248 font-size: 14px;
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
249 }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
250 .file-row .name a:hover { color: var(--accent-color); text-decoration: underline; }
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
251
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
252 /* Readme */
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
253 #readmeSection { margin-top: 32px; border: 1px solid var(--border-color); border-radius: var(--radius); }
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
254 .readme-header {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
255 background: var(--bg-subtle);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
256 padding: 10px 16px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
257 font-size: 12px; font-weight: 600;
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
258 border-bottom: 1px solid var(--border-color);
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
259 display: flex; align-items: center; gap: 8px;
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
260 }
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
261 .readme-header img {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
262 filter: ${isDark ? 'invert(0.7)' : 'none'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
263 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
264 #readmeContent { padding: 32px; background: var(--bg-color); overflow-x: auto; color: var(--text-primary); }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
265
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
266 /* File Viewer */
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
267 .file-viewer-overlay {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
268 position: fixed;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
269 inset: 0;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
270 background: ${isDark ? 'rgba(0,0,0,0.7)' : 'rgba(0,0,0,0.5)'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
271 display: flex;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
272 justify-content: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
273 align-items: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
274 z-index: 1000;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
275 padding: 20px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
276 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
277 .file-viewer {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
278 background: var(--bg-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
279 border: 1px solid var(--border-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
280 border-radius: var(--radius);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
281 width: 100%;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
282 max-width: 900px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
283 max-height: 90vh;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
284 display: flex;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
285 flex-direction: column;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
286 box-shadow: 0 8px 32px rgba(0,0,0,0.3);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
287 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
288 .file-viewer-header {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
289 display: flex;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
290 align-items: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
291 justify-content: space-between;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
292 padding: 12px 16px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
293 background: var(--bg-subtle);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
294 border-bottom: 1px solid var(--border-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
295 border-radius: var(--radius) var(--radius) 0 0;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
296 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
297 .file-viewer-title {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
298 font-weight: 600;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
299 font-size: 14px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
300 color: var(--text-primary);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
301 display: flex;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
302 align-items: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
303 gap: 8px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
304 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
305 .file-viewer-close {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
306 background: transparent;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
307 border: none;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
308 cursor: pointer;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
309 padding: 4px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
310 border-radius: 4px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
311 display: flex;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
312 align-items: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
313 justify-content: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
314 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
315 .file-viewer-close:hover {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
316 background: var(--hover-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
317 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
318 .file-viewer-close img {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
319 width: 16px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
320 height: 16px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
321 filter: ${isDark ? 'invert(0.7)' : 'none'};
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
322 opacity: 0.7;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
323 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
324 .file-viewer-content {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
325 overflow: auto;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
326 flex: 1;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
327 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
328 .file-viewer-content pre {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
329 margin: 0;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
330 padding: 16px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
331 background: var(--code-bg);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
332 font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
333 font-size: 13px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
334 line-height: 1.5;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
335 overflow-x: auto;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
336 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
337 .file-viewer-content code {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
338 background: transparent;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
339 padding: 0;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
340 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
341 .file-viewer-loading {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
342 padding: 40px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
343 text-align: center;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
344 color: var(--text-secondary);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
345 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
346 .file-viewer-line-numbers {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
347 display: inline-block;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
348 user-select: none;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
349 text-align: right;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
350 padding-right: 16px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
351 margin-right: 16px;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
352 border-right: 1px solid var(--border-color);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
353 color: var(--text-secondary);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
354 opacity: 0.5;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
355 }
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
356 `}</style>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
357 );
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
358
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
359 /**
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
360 * Component: Breadcrumb
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
361 */
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
362 function Breadcrumb({ currentPath, onNavigate }) {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
363 if (!currentPath) {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
364 return (
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
365 <nav id="breadcrumb">
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
366 <span className="nav-item active">root</span>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
367 </nav>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
368 );
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
369 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
370
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
371 const parts = currentPath.split('/').filter(p => p);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
372 const crumbs = parts.map((part, index) => ({
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
373 name: part,
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
374 fullPath: parts.slice(0, index + 1).join('/')
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
375 }));
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
376
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
377 return (
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
378 <nav id="breadcrumb">
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
379 <a
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
380 href="/"
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
381 onClick={(e) => { e.preventDefault(); onNavigate(''); }}
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
382 title="Go to Root"
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
383 >
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
384 root
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
385 </a>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
386 {crumbs.map((crumb, index) => {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
387 const isLast = index === crumbs.length - 1;
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
388 return (
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
389 <React.Fragment key={crumb.fullPath}>
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
390 <span className="separator">/</span>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
391 {isLast ? (
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
392 <span className="nav-item active">{crumb.name}</span>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
393 ) : (
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
394 <a
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
395 href={`?path=${encodeURIComponent(crumb.fullPath)}`}
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
396 onClick={(e) => { e.preventDefault(); onNavigate(crumb.fullPath); }}
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
397 >
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
398 {crumb.name}
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
399 </a>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
400 )}
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
401 </React.Fragment>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
402 );
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
403 })}
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
404 </nav>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
405 );
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
406 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
407
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
408 /**
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
409 * Component: FileViewer
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
410 * Shows file content inline with syntax highlighting
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
411 */
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
412 function FileViewer({ filePath, onClose }: { filePath: string; onClose: () => void }) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
413 const [content, setContent] = useState<string | null>(null);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
414 const [loading, setLoading] = useState(true);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
415 const codeRef = useRef<HTMLElement>(null);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
416
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
417 const filename = filePath.split('/').pop() || filePath;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
418
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
419 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
420 setLoading(true);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
421 getCachedFile(filePath).then((text) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
422 setContent(text);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
423 setLoading(false);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
424 });
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
425 }, [filePath]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
426
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
427 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
428 if (content && codeRef.current) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
429 hljs.highlightElement(codeRef.current);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
430 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
431 }, [content]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
432
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
433 // Close on escape key
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
434 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
435 const handleKeyDown = (e: KeyboardEvent) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
436 if (e.key === 'Escape') onClose();
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
437 };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
438 window.addEventListener('keydown', handleKeyDown);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
439 return () => window.removeEventListener('keydown', handleKeyDown);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
440 }, [onClose]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
441
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
442 // Get language from file extension for highlight.js
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
443 const getLanguage = () => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
444 const ext = filename.split('.').pop()?.toLowerCase() || '';
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
445 const langMap: Record<string, string> = {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
446 js: 'javascript', jsx: 'javascript', ts: 'typescript', tsx: 'typescript',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
447 py: 'python', rb: 'ruby', rs: 'rust', go: 'go', java: 'java',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
448 c: 'c', cpp: 'cpp', h: 'c', hpp: 'cpp', cs: 'csharp',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
449 sh: 'bash', bash: 'bash', zsh: 'bash', fish: 'bash',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
450 json: 'json', yaml: 'yaml', yml: 'yaml', toml: 'toml',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
451 html: 'html', htm: 'html', css: 'css', scss: 'scss', sass: 'scss',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
452 sql: 'sql', md: 'markdown', markdown: 'markdown', xml: 'xml',
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
453 dockerfile: 'dockerfile', makefile: 'makefile'
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
454 };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
455 return langMap[ext] || 'plaintext';
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
456 };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
457
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
458 const addLineNumbers = (text: string) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
459 const lines = text.split('\n');
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
460 return lines.map((_, i) => i + 1).join('\n');
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
461 };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
462
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
463 return (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
464 <div className="file-viewer-overlay" onClick={onClose}>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
465 <div className="file-viewer" onClick={(e) => e.stopPropagation()}>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
466 <div className="file-viewer-header">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
467 <span className="file-viewer-title">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
468 <img src={ICONS.file} alt="" style={{ width: 16, height: 16 }} />
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
469 {filename}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
470 </span>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
471 <button className="file-viewer-close" onClick={onClose} title="Close (Esc)">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
472 <img src={ICONS.close} alt="Close" />
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
473 </button>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
474 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
475 <div className="file-viewer-content">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
476 {loading ? (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
477 <div className="file-viewer-loading">Loading...</div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
478 ) : content ? (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
479 <pre style={{ display: 'flex' }}>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
480 <span className="file-viewer-line-numbers">{addLineNumbers(content)}</span>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
481 <code ref={codeRef} className={`language-${getLanguage()}`}>{content}</code>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
482 </pre>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
483 ) : (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
484 <div className="file-viewer-loading">Unable to load file</div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
485 )}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
486 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
487 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
488 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
489 );
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
490 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
491
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
492 /**
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
493 * Component: MarkdownViewerModal
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
494 * Shows markdown content rendered in a modal
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
495 */
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
496 function MarkdownViewerModal({ filePath, onClose }: { filePath: string; onClose: () => void }) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
497 const [content, setContent] = useState<string | null>(null);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
498 const [loading, setLoading] = useState(true);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
499 const contentRef = useRef<HTMLDivElement>(null);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
500 const moduleRef = useRef<any>(null);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
501 const [wasmReady, setWasmReady] = useState(false);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
502
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
503 const filename = filePath.split('/').pop() || filePath;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
504
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
505 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
506 createMarkdownModule().then((Module: any) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
507 moduleRef.current = Module;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
508 setWasmReady(true);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
509 });
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
510 }, []);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
511
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
512 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
513 setLoading(true);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
514 getCachedFile(filePath).then((text) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
515 setContent(text);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
516 setLoading(false);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
517 });
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
518 }, [filePath]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
519
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
520 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
521 if (!content || !wasmReady || !contentRef.current || !moduleRef.current) return;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
522
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
523 const Module = moduleRef.current;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
524 const markdownToHtmlPtr = Module.cwrap('markdown_to_html', 'number', ['string']);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
525 const markdownFree = Module.cwrap('markdown_free', null, ['number']);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
526
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
527 const ptr = markdownToHtmlPtr(content);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
528 const html = Module.UTF8ToString(ptr);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
529 markdownFree(ptr);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
530 contentRef.current.innerHTML = html;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
531 }, [content, wasmReady]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
532
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
533 // Close on escape key
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
534 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
535 const handleKeyDown = (e: KeyboardEvent) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
536 if (e.key === 'Escape') onClose();
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
537 };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
538 window.addEventListener('keydown', handleKeyDown);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
539 return () => window.removeEventListener('keydown', handleKeyDown);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
540 }, [onClose]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
541
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
542 return (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
543 <div className="file-viewer-overlay" onClick={onClose}>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
544 <div className="file-viewer" onClick={(e) => e.stopPropagation()}>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
545 <div className="file-viewer-header">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
546 <span className="file-viewer-title">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
547 <img src={ICONS.file} alt="" style={{ width: 16, height: 16 }} />
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
548 {filename}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
549 </span>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
550 <button className="file-viewer-close" onClick={onClose} title="Close (Esc)">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
551 <img src={ICONS.close} alt="Close" />
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
552 </button>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
553 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
554 <div className="file-viewer-content">
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
555 {loading || !wasmReady ? (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
556 <div className="file-viewer-loading">Loading...</div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
557 ) : content ? (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
558 <div id="readmeContent" ref={contentRef} style={{ padding: 32 }} />
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
559 ) : (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
560 <div className="file-viewer-loading">Unable to load file</div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
561 )}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
562 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
563 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
564 </div>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
565 );
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
566 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
567
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
568 /**
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
569 * Component: FileList
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
570 */
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
571 function FileList({ directories, files, onNavigate, onOpenFile }: {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
572 directories: any[];
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
573 files: any[];
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
574 onNavigate: (path: string) => void;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
575 onOpenFile: (path: string) => void;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
576 }) {
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
577 const isEmpty = directories.length === 0 && files.length === 0;
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
578
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
579 if (isEmpty) {
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
580 return (
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
581 <div className="file-list-container">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
582 <div className="empty-state">This directory is empty.</div>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
583 </div>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
584 );
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
585 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
586
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
587 return (
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
588 <div className="file-list-container">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
589 {/* Optional header row like GitHub */}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
590 <div className="file-header">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
591 Files
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
592 </div>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
593
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
594 <div id="fileListBody">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
595 {directories.map((dir) => (
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
596 <FileRow
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
597 key={dir.abspath}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
598 item={dir}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
599 iconUrl={ICONS.folder}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
600 isDir={true}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
601 onNavigate={onNavigate}
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
602 onOpenFile={onOpenFile}
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
603 />
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
604 ))}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
605
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
606 {files.map((file) => (
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
607 <FileRow
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
608 key={file.abspath}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
609 item={file}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
610 iconUrl={ICONS.file}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
611 isDir={false}
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
612 onNavigate={onNavigate}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
613 onOpenFile={onOpenFile}
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
614 />
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
615 ))}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
616 </div>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
617 </div>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
618 );
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
619 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
620
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
621 /**
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
622 * Component: FileRow
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
623 */
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
624 function FileRow({ item, iconUrl, isDir, onNavigate, onOpenFile }: {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
625 item: { abspath: string; basename: string };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
626 iconUrl: string;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
627 isDir: boolean;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
628 onNavigate: (path: string) => void;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
629 onOpenFile: (path: string) => void;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
630 }) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
631 const handleClick = (e: React.MouseEvent) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
632 e.preventDefault();
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
633 if (isDir) {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
634 onNavigate(item.abspath);
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
635 } else if (isCodeFile(item.basename)) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
636 onOpenFile(item.abspath);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
637 } else {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
638 // For non-code files, open in new tab
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
639 window.open(`/api/repo/file?path=${encodeURIComponent(item.abspath)}`, '_blank');
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
640 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
641 };
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
642
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
643 const handleMouseEnter = () => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
644 // Prefetch on hover
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
645 if (isDir) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
646 prefetchDirectory(item.abspath);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
647 } else if (isCodeFile(item.basename)) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
648 prefetchFile(item.abspath);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
649 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
650 };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
651
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
652 const href = isDir
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
653 ? `?path=${encodeURIComponent(item.abspath)}`
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
654 : `/api/repo/file?path=${encodeURIComponent(item.abspath)}`;
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
655
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
656 return (
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
657 <div className="file-row" onMouseEnter={handleMouseEnter}>
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
658 <span className="icon">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
659 <img src={iconUrl} alt={isDir ? "Directory" : "File"} />
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
660 </span>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
661 <span className="name">
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
662 <a href={href} onClick={handleClick}>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
663 {item.basename}
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
664 </a>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
665 </span>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
666 </div>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
667 );
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
668 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
669
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
670 /**
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
671 * Component: ReadmeViewer
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
672 */
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
673 function ReadmeViewer({ content }: { content: string | null }) {
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
674 const contentRef = useRef<HTMLDivElement>(null);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
675 const moduleRef = useRef<any>(null);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
676 const [wasmReady, setWasmReady] = useState(false);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
677
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
678 useEffect(() => {
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
679 createMarkdownModule().then((Module: any) => {
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
680 moduleRef.current = Module;
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
681 setWasmReady(true);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
682 });
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
683 }, []);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
684
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
685 useEffect(() => {
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
686 if (!content || !wasmReady || !contentRef.current || !moduleRef.current) return;
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
687
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
688 const Module = moduleRef.current;
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
689 const markdownToHtmlPtr = Module.cwrap('markdown_to_html', 'number', ['string']);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
690 const markdownFree = Module.cwrap('markdown_free', null, ['number']);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
691
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
692 const ptr = markdownToHtmlPtr(content);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
693 const html = Module.UTF8ToString(ptr);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
694 markdownFree(ptr);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
695 contentRef.current.innerHTML = html;
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
696 }, [content, wasmReady]);
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
697
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
698 if (!content) return null;
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
699
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
700 return (
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
701 <div id="readmeSection">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
702 <div className="readme-header">
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
703 <img src={ICONS.file} width="16" alt="" style={{opacity:0.5}} />
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
704 README.md
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
705 </div>
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
706 <div id="readmeContent" ref={contentRef}>
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
707 {!wasmReady && 'Loading...'}
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
708 </div>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
709 </div>
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
710 );
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
711 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
712
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
713 /**
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
714 * Main Application Component
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
715 */
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
716 function RepoBrowser() {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
717 const [currentPath, setCurrentPath] = useState(getCurrentPath());
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
718 const [content, setContent] = useState<{ files: any[]; directories: any[] }>({ files: [], directories: [] });
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
719 const [readme, setReadme] = useState<string | null>(null);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
720 const [error, setError] = useState<string | null>(null);
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
721 const [loading, setLoading] = useState(false);
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
722 const [isDarkMode, setIsDarkMode] = useState(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
723 // Check localStorage or system preference
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
724 const saved = localStorage.getItem('theme');
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
725 if (saved) return saved === 'dark';
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
726 return window.matchMedia('(prefers-color-scheme: dark)').matches;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
727 });
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
728 const [viewingFile, setViewingFile] = useState<string | null>(null);
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
729
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
730 function getCurrentPath() {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
731 const params = new URLSearchParams(window.location.search);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
732 return params.get('path') || '';
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
733 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
734
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
735 // Persist theme preference
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
736 useEffect(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
737 localStorage.setItem('theme', isDarkMode ? 'dark' : 'light');
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
738 }, [isDarkMode]);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
739
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
740 useEffect(() => {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
741 const handlePopState = () => setCurrentPath(getCurrentPath());
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
742 window.addEventListener('popstate', handlePopState);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
743 return () => window.removeEventListener('popstate', handlePopState);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
744 }, []);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
745
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
746 useEffect(() => {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
747 fetchDirectory(currentPath);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
748 fetchReadme(currentPath);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
749 }, [currentPath]);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
750
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
751 const navigate = (path: string) => {
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
752 const newUrl = path ? `?path=${encodeURIComponent(path)}` : '/';
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
753 window.history.pushState({ path }, '', newUrl);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
754 setCurrentPath(path);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
755 };
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
756
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
757 const fetchDirectory = async (path: string) => {
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
758 setLoading(true);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
759 setError(null);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
760 try {
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
761 // Check prefetch cache first
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
762 const cacheKey = `dir:${path}`;
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
763 let data;
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
764 if (prefetchCache.has(cacheKey)) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
765 data = await prefetchCache.get(cacheKey);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
766 prefetchCache.delete(cacheKey); // Clear after use for fresh data next time
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
767 } else {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
768 const url = path
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
769 ? `${API_BASE}/list?path=${encodeURIComponent(path)}`
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
770 : `${API_BASE}/list`;
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
771 const response = await fetch(url);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
772 if (response.ok) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
773 data = await response.json();
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
774 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
775 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
776
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
777 if (data?.error) {
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
778 throw new Error(data.error);
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
779 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
780
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
781 setContent({
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
782 files: data?.files || [],
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
783 directories: data?.directories || []
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
784 });
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
785 } catch (err: any) {
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
786 console.error('Error loading directory:', err);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
787 setError(err.message);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
788 } finally {
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
789 setLoading(false);
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
790 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
791 };
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
792
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
793 const fetchReadme = async (path: string) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
794 setReadme(null);
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
795 const readmePath = path ? `${path}/README.md` : 'README.md';
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
796 try {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
797 const response = await fetch(`${API_BASE}/file?path=${encodeURIComponent(readmePath)}`);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
798 if (response.ok) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
799 const text = await response.text();
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
800 setReadme(text);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
801 }
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
802 } catch (err) {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
803 // Readme is optional, ignore errors
190
a2725419f988 Updated so that bun builds will with already existing js files.
MrJuneJune <me@mrjunejune.com>
parents: 188
diff changeset
804 }
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
805 };
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
806
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
807 const handleOpenFile = useCallback((path: string) => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
808 setViewingFile(path);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
809 }, []);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
810
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
811 const handleCloseFile = useCallback(() => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
812 setViewingFile(null);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
813 }, []);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
814
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
815 const toggleTheme = () => {
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
816 setIsDarkMode(prev => !prev);
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
817 };
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
818
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
819 return (
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
820 <>
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
821 <GlobalStyles isDark={isDarkMode} />
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
822 <div className="repo-container">
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
823
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
824 {/* Header */}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
825 <div className="header">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
826 <img src={ICONS.repo} alt="Repo" className="header-icon" />
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
827 <div>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
828 <h1>Zenbu Repository</h1>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
829 <p className="description">Browse and manage the mercurial codebase</p>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
830 </div>
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
831 <button className="theme-toggle" onClick={toggleTheme} title={isDarkMode ? 'Switch to light mode' : 'Switch to dark mode'}>
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
832 {isDarkMode ? <SunIcon color="#f0c674" /> : <MoonIcon color="#6e7681" />}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
833 {isDarkMode ? 'Light' : 'Dark'}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
834 </button>
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
835 </div>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
836
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
837 {/* Clone Bar */}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
838 <div className="clone-box">
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
839 <div style={{display:'flex', alignItems:'center', width:'100%'}}>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
840 <span className="clone-label">Clone HTTPS</span>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
841 <code className="clone-url">hg clone http://zenbu.babocoder.com/repo</code>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
842 </div>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
843 </div>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
844
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
845 {/* Navigation & Content */}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
846 <Breadcrumb currentPath={currentPath} onNavigate={navigate} />
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
847
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
848 {error && <div className="error-message">Error: {error}</div>}
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
849
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
850 {loading ? (
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
851 <div className="file-list-container" style={{padding: '40px', textAlign: 'center', color: 'var(--text-secondary)'}}>
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
852 Loading files...
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
853 </div>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
854 ) : (
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
855 <>
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
856 <FileList
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
857 directories={content.directories}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
858 files={content.files}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
859 onNavigate={navigate}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
860 onOpenFile={handleOpenFile}
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
861 />
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
862 <ReadmeViewer content={readme} />
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
863 </>
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
864 )}
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
865 </div>
191
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
866
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
867 {/* File Viewer Modal */}
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
868 {viewingFile && (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
869 isMarkdownFile(viewingFile) ? (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
870 <MarkdownViewerModal filePath={viewingFile} onClose={handleCloseFile} />
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
871 ) : (
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
872 <FileViewer filePath={viewingFile} onClose={handleCloseFile} />
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
873 )
a06710325c30 [HgWeb] Fully working copy.
MrJuneJune <me@mrjunejune.com>
parents: 190
diff changeset
874 )}
176
fed99fc04e12 [HgWeb] Problem with the emscript lol
MrJuneJune <me@mrjunejune.com>
parents: 175
diff changeset
875 </>
175
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
876 );
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
877 }
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
878
71ad34a8bc9a [HgWeb] Can stream hg response now. Added react page for hg web since we use json anyway.
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
879 export { RepoBrowser };