feat(aether): initial commit – self-hosted Cloud, Phasen 1–7

Go-Backend (chi, pgx, golang-migrate) + React/TS-Frontend als PWA.
Enthalten: Auth inkl. OIDC, Dateien mit Versionen und Papierkorb,
Freigaben (Links + intern), WebDAV, Gruppenordner, Admin/Theming,
Volltextsuche mit OCR, eigener PDF-Betrachter und WOPI-Office
(Collabora/OnlyOffice).

Nicht im Repo: deploy/.env (Sitzungsschlüssel, DB- und Admin-Passwort)
sowie alle Daten- und Build-Verzeichnisse – siehe .gitignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 5 committed 2026-08-24 09:25:36 +02:00
commit 31a027c93a
225 files changed
+38042

No files matched your search

+87
View File
@@ -0,0 +1,87 @@
import type { FolderItem } from '../api/client'
interface Props {
path: FolderItem[]
onNavigate: (folderId: string | undefined) => void
}
/**
* Der Pfad in der Kopfleiste.
*
* Schriftgröße und -stärke sind dieselben wie bei den Titeln der anderen
* Ansichten („Trash", „Shared links"): 15 px, 600 für den aktuellen Ort. Bis
* zum 23.08.2026 lief das über Tailwind-Klassen (`text-sm`, `font-medium`) und
* war damit 14 px bei Stärke 500 – nebeneinander sieht man den Unterschied
* sofort, auch ohne ihn benennen zu können.
*
* Auch das Symbol war kleiner (15 statt 18). Es ist jetzt Zeichen für Zeichen
* dasselbe wie in der Seitenleiste.
*/
const rootLabel = 'Home'
export default function Breadcrumb({ path, onNavigate }: Props) {
const atRoot = path.length === 0
const segment = (active: boolean) => ({
flexShrink: 0,
display: 'flex',
alignItems: 'center',
// 10 wie in PageHeader zwischen Symbol und Titel – bei 7 stand „Home"
// drei Pixel weiter links als „Trash". Gemessen: 265 statt 268.
gap: 10,
padding: '2px 6px',
borderRadius: 6,
border: 'none',
background: 'none',
cursor: 'pointer',
// Gleiche Schrift wie die Seitentitel – sonst wirkt die Dateiansicht wie
// eine andere Anwendung.
fontSize: 15,
fontWeight: 600,
lineHeight: 1.3,
color: active ? 'var(--color-text)' : 'var(--color-text-muted)',
})
return (
<nav style={{
display: 'flex', alignItems: 'center', gap: 2,
minWidth: 0, overflowX: 'auto',
// Der Wurzel-Knopf hat innen 6 px Rand, damit sein Hover-Feld nicht am
// Text klebt. Ohne diesen Ausgleich begänne das Haus-Symbol 6 px weiter
// rechts als das Symbol in Papierkorb und Co. – beim Umschalten sieht man
// genau diesen Sprung. Gemessen: 246 statt 240.
marginLeft: -6,
}}>
<button onClick={() => onNavigate(undefined)} style={segment(atRoot)} title={rootLabel}>
{/* Das Symbol bleibt gedämpft, auch wenn der Titel hell ist – genau so
steht es im Papierkorb und bei den Freigabe-Links. Vorher erbte es
die Textfarbe und leuchtete auf der Startebene heller als dort. */}
<span style={{ display: 'flex', color: 'var(--color-text-muted)' }}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M3 10.5L12 3l9 7.5" />
<path d="M5.5 9.5V20a1 1 0 001 1h11a1 1 0 001-1V9.5" />
</svg>
</span>
{rootLabel}
</button>
{path.map((folder, i) => (
<span key={folder.id} style={{ display: 'flex', alignItems: 'center', gap: 2, minWidth: 0 }}>
<span style={{ color: 'var(--color-text-muted)', fontSize: 15, opacity: 0.6 }}>/</span>
<button
onClick={() => onNavigate(folder.id)}
style={{
...segment(i === path.length - 1),
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
display: 'block', maxWidth: 220,
}}
title={folder.name}
>
{folder.name}
</button>
</span>
))}
</nav>
)
}