fix(office): PDF am Telefon nur bei OnlyOffice, Collabora behält den Editor
Die Regel galt für beide Anbieter – das war falsch. Marcs Kritik betraf nur OnlyOffice: Es baut auf dem Telefon dieselbe Oberfläche auf wie am PC. Collabora bringt für kleine Schirme eine eigene Ansicht mit, die taugt; dort wäre der Umweg über ein PDF ein Rückschritt. Der Anbieter steht jetzt in der öffentlichen Konfiguration (office_provider), und die Oberfläche entscheidet daran. Der Endpunkt selbst kann weiterhin beides. Nachgeholt: Der ganze Weg ist jetzt auch mit Collabora gemessen, nicht nur mit OnlyOffice – gegen die Dev-Instanz, die damit läuft. erster Abruf 0,347 s, zweiter 0,009 s, eine Datei auf der Platte (OnlyOffice zum Vergleich: 1,05 s – es muss die Datei erst abholen) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
065372359b
commit
6c53651568
6 files changed
+57
-17
No files matched your search
@@ -654,18 +654,30 @@ Abbild.
|
|||||||
> über `{"payload": …}`) kommt das Ergebnis. Der Schlüssel gehört also
|
> über `{"payload": …}`) kommt das Ergebnis. Der Schlüssel gehört also
|
||||||
> gesetzt – sonst läuft die API offen.
|
> gesetzt – sonst läuft die API offen.
|
||||||
|
|
||||||
### Am Telefon: ansehen statt bearbeiten
|
### Am Telefon: bei OnlyOffice ansehen statt bearbeiten
|
||||||
|
|
||||||
Tippt man auf ein Office-Dokument, öffnet sich am **Finger** nicht der Editor,
|
Tippt man mit dem **Finger** auf ein Office-Dokument, hängt es vom Anbieter ab,
|
||||||
sondern das Dokument als PDF im eigenen Betrachter. „Edit" in der Kopfzeile
|
was aufgeht:
|
||||||
führt trotzdem hinein. Mit **Maus** ändert sich nichts.
|
|
||||||
|
|
||||||
Der Grund ist keine Geschmacksfrage: Der Web-Editor ist eine vollständige
|
| Anbieter | am Telefon |
|
||||||
Textverarbeitung, und zwischen Menüband, Formatleisten und
|
|---|---|
|
||||||
|
| **Collabora** | der Editor – seine eigene Handy-Ansicht taugt |
|
||||||
|
| **OnlyOffice / Euro-Office** | das Dokument als PDF; „Edit" führt trotzdem hinein |
|
||||||
|
|
||||||
|
Mit **Maus** ändert sich nichts: Dort geht immer der Editor auf, auch in einem
|
||||||
|
schmalen Fenster. Ein schmales Fenster auf dem Schreibtisch ist immer noch
|
||||||
|
eine Tastatur.
|
||||||
|
|
||||||
|
Der Unterschied ist keine Geschmacksfrage. OnlyOffice baut auf dem Telefon
|
||||||
|
dieselbe Oberfläche auf wie am PC – zwischen Menüband, Formatleisten und
|
||||||
Eigenschaftenbereich bleibt auf 400 Pixeln vom Dokument ein Rechteck übrig.
|
Eigenschaftenbereich bleibt auf 400 Pixeln vom Dokument ein Rechteck übrig.
|
||||||
Das gilt für Collabora wie für OnlyOffice – beide ausprobiert, dasselbe Bild.
|
Collabora hat für kleine Schirme eine eigene Ansicht und braucht den Umweg
|
||||||
Unterwegs ist der Anlass fast immer *nachsehen*, und dafür ist ein PDF das
|
nicht.
|
||||||
bessere Werkzeug.
|
|
||||||
|
Der Endpunkt selbst gilt für beide: `GET /api/v1/files/{id}/preview.pdf`
|
||||||
|
wandelt bei Collabora über `/cool/convert-to/pdf` (gemessen 0,35 s) und bei
|
||||||
|
OnlyOffice über `/ConvertService.ashx` (1,05 s). Nur *wann* er benutzt wird,
|
||||||
|
entscheidet der Anbieter.
|
||||||
|
|
||||||
Gewandelt wird von **demselben** Server, der auch bearbeitet: Wer OnlyOffice
|
Gewandelt wird von **demselben** Server, der auch bearbeitet: Wer OnlyOffice
|
||||||
wegen der Treue zu MS-Office-Formaten nimmt, soll unterwegs nicht ein
|
wegen der Treue zu MS-Office-Formaten nimmt, soll unterwegs nicht ein
|
||||||
|
|||||||
@@ -396,6 +396,16 @@ func main() {
|
|||||||
// Damit die Oberflaeche den Menuepunkt „Edit in Office" gar nicht
|
// Damit die Oberflaeche den Menuepunkt „Edit in Office" gar nicht
|
||||||
// erst anbietet, wenn es keinen Office-Server gibt.
|
// erst anbietet, wenn es keinen Office-Server gibt.
|
||||||
"office_enabled": officeHandler.Enabled(),
|
"office_enabled": officeHandler.Enabled(),
|
||||||
|
// Welcher Anbieter – die Oberflaeche entscheidet daran, ob ein
|
||||||
|
// Dokument am Telefon im Editor oder als PDF aufgeht. Collabora
|
||||||
|
// hat eine brauchbare Handy-Ansicht, OnlyOffice baut dort die
|
||||||
|
// PC-Oberflaeche auf. Ohne Office-Server ein leerer Wert.
|
||||||
|
"office_provider": func() string {
|
||||||
|
if officeHandler.Enabled() {
|
||||||
|
return cfg.OfficeProvider
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}(),
|
||||||
// Damit der Verlaufs-Dialog dieselbe Zahl nennt, die der Server
|
// Damit der Verlaufs-Dialog dieselbe Zahl nennt, die der Server
|
||||||
// anwendet. Vorher stand sie zweimal im Quelltext, mit einem
|
// anwendet. Vorher stand sie zweimal im Quelltext, mit einem
|
||||||
// Kommentar „muss zusammenpassen" – das ist keine Zusicherung.
|
// Kommentar „muss zusammenpassen" – das ist keine Zusicherung.
|
||||||
|
|||||||
@@ -273,7 +273,8 @@ Geplante Ideen (noch nicht umgesetzt):
|
|||||||
- Glasmorphismus-Theme (transluzente Sidebar/Cards mit Blur-Effekt)
|
- Glasmorphismus-Theme (transluzente Sidebar/Cards mit Blur-Effekt)
|
||||||
- Logo und App-Symbol bereits in Phase 4.5/D umgesetzt
|
- Logo und App-Symbol bereits in Phase 4.5/D umgesetzt
|
||||||
|
|
||||||
- ✅ **Office-Dokumente am Telefon als PDF ansehen** (`internal/office/convert.go` + `preview.go`, Migration 000020, 31.08.2026, Wunsch von Marc). Am Finger öffnet ein `.docx` nicht mehr den Editor, sondern das gewandelte PDF im eigenen Betrachter; „Edit" daneben führt trotzdem hinein. Am Schreibtisch bleibt alles wie es war.
|
- ✅ **Office-Dokumente am Telefon als PDF ansehen** (`internal/office/convert.go` + `preview.go`, Migration 000020, 31.08.2026, Wunsch von Marc). Am Finger öffnet ein `.docx` **bei OnlyOffice** nicht mehr den Editor, sondern das gewandelte PDF im eigenen Betrachter; „Edit" daneben führt trotzdem hinein. Am Schreibtisch bleibt alles wie es war.
|
||||||
|
- **Bei Collabora bleibt der Editor.** Zuerst galt die Regel für beide Anbieter – falsch, und Marc hat es sofort gesehen: Seine Kritik betraf nur OnlyOffice. Collabora bringt für kleine Schirme eine eigene Ansicht mit, die taugt; dort wäre der Umweg über ein PDF ein Rückschritt. Der Anbieter steht deshalb in der öffentlichen Konfiguration (`office_provider`), und die Oberfläche entscheidet daran. Der Endpunkt selbst kann beides und ist mit beiden gemessen (Collabora 0,35 s, OnlyOffice 1,05 s).
|
||||||
- **Warum überhaupt:** Der Web-Editor ist eine vollständige Textverarbeitung. Menüband, Formatleisten und Eigenschaftenbereich sind nicht Beiwerk, sondern das Produkt – auf 400 Pixeln bleibt für das Dokument ein Rechteck. Marc hat Collabora **und** OnlyOffice ausprobiert, mit demselben Ergebnis; das ist der Grund, aus dem hier kein besserer Bedienmodus gesucht wurde, sondern ein anderes Werkzeug. Nextcloud löst es in seiner App genauso: ansehen statt bearbeiten.
|
- **Warum überhaupt:** Der Web-Editor ist eine vollständige Textverarbeitung. Menüband, Formatleisten und Eigenschaftenbereich sind nicht Beiwerk, sondern das Produkt – auf 400 Pixeln bleibt für das Dokument ein Rechteck. Marc hat Collabora **und** OnlyOffice ausprobiert, mit demselben Ergebnis; das ist der Grund, aus dem hier kein besserer Bedienmodus gesucht wurde, sondern ein anderes Werkzeug. Nextcloud löst es in seiner App genauso: ansehen statt bearbeiten.
|
||||||
- **Gewandelt wird von dem Server, der auch bearbeitet.** Wer OnlyOffice wegen der Treue zu MS-Office-Formaten nimmt, aber Collabora das PDF rechnen ließe, sähe unterwegs ein LibreOffice-Layout desselben Dokuments – zwei Geräte, zwei Umbrüche, ausgerechnet bei Unterlagen. Beide Wege sind deshalb gebaut: Collabora nimmt die Bytes (`/cool/convert-to/pdf`), OnlyOffice eine Adresse, holt die Datei selbst und antwortet mit einer Adresse (`/ConvertService.ashx`, HS256-signiert).
|
- **Gewandelt wird von dem Server, der auch bearbeitet.** Wer OnlyOffice wegen der Treue zu MS-Office-Formaten nimmt, aber Collabora das PDF rechnen ließe, sähe unterwegs ein LibreOffice-Layout desselben Dokuments – zwei Geräte, zwei Umbrüche, ausgerechnet bei Unterlagen. Beide Wege sind deshalb gebaut: Collabora nimmt die Bytes (`/cool/convert-to/pdf`), OnlyOffice eine Adresse, holt die Datei selbst und antwortet mit einer Adresse (`/ConvertService.ashx`, HS256-signiert).
|
||||||
- **Je Datei gibt es genau ein PDF, und das ist keine Frage des Aufräumens, sondern des Schlüssels:** `previews/<id>.pdf` trägt die Fassung **nicht** im Namen. Eine neue Fassung überschreibt, statt danebenzulegen. Ob das Abgelegte noch passt, sagt `files.preview_version`. Gemessen: Nach dem erneuten Hochladen stand die Datei auf Fassung 2, `preview_version` auf 2, und im Ordner lag weiterhin genau eine Datei.
|
- **Je Datei gibt es genau ein PDF, und das ist keine Frage des Aufräumens, sondern des Schlüssels:** `previews/<id>.pdf` trägt die Fassung **nicht** im Namen. Eine neue Fassung überschreibt, statt danebenzulegen. Ob das Abgelegte noch passt, sagt `files.preview_version`. Gemessen: Nach dem erneuten Hochladen stand die Datei auf Fassung 2, `preview_version` auf 2, und im Ordner lag weiterhin genau eine Datei.
|
||||||
|
|||||||
@@ -225,6 +225,8 @@ export interface PublicConfig {
|
|||||||
/** Gibt es einen Office-Server? Sonst bietet das Menue das Bearbeiten gar
|
/** Gibt es einen Office-Server? Sonst bietet das Menue das Bearbeiten gar
|
||||||
* nicht erst an – ein Punkt, der immer scheitert, ist schlimmer als keiner. */
|
* nicht erst an – ein Punkt, der immer scheitert, ist schlimmer als keiner. */
|
||||||
office_enabled?: boolean
|
office_enabled?: boolean
|
||||||
|
/** 'collabora' | 'onlyoffice' | '' – entscheidet über die Handy-Ansicht. */
|
||||||
|
office_provider?: string
|
||||||
/** Wie viele frühere Fassungen der Server aufhebt (MAX_VERSIONS_KEPT). */
|
/** Wie viele frühere Fassungen der Server aufhebt (MAX_VERSIONS_KEPT). */
|
||||||
max_versions_kept?: number
|
max_versions_kept?: number
|
||||||
/** Beschriftung des SSO-Knopfes (OIDC_BUTTON_LABEL). Leer, wenn OIDC aus ist. */
|
/** Beschriftung des SSO-Knopfes (OIDC_BUTTON_LABEL). Leer, wenn OIDC aus ist. */
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ interface AppSettingsValue {
|
|||||||
globalColors: { primary?: string; accent?: string }
|
globalColors: { primary?: string; accent?: string }
|
||||||
/** Gibt es einen Office-Server? Steuert nur, ob der Menuepunkt erscheint. */
|
/** Gibt es einen Office-Server? Steuert nur, ob der Menuepunkt erscheint. */
|
||||||
officeEnabled: boolean
|
officeEnabled: boolean
|
||||||
|
/**
|
||||||
|
* Welcher Anbieter – 'collabora', 'onlyoffice' oder leer.
|
||||||
|
*
|
||||||
|
* Die Oberfläche braucht das, weil sich die beiden am Telefon verschieden
|
||||||
|
* verhalten: Collabora hat eine eigene Handy-Ansicht, die taugt; OnlyOffice
|
||||||
|
* baut dort dieselbe Oberfläche auf wie am PC.
|
||||||
|
*/
|
||||||
|
officeProvider: string
|
||||||
/** Wie viele frühere Fassungen der Server aufhebt. Kommt vom Server, damit
|
/** Wie viele frühere Fassungen der Server aufhebt. Kommt vom Server, damit
|
||||||
* der Dialog nicht eine andere Zahl nennt als die, die angewendet wird. */
|
* der Dialog nicht eine andere Zahl nennt als die, die angewendet wird. */
|
||||||
maxVersionsKept: number
|
maxVersionsKept: number
|
||||||
@@ -34,6 +42,7 @@ interface AppSettingsValue {
|
|||||||
const Ctx = createContext<AppSettingsValue>({
|
const Ctx = createContext<AppSettingsValue>({
|
||||||
cloudName: 'Aether',
|
cloudName: 'Aether',
|
||||||
officeEnabled: false,
|
officeEnabled: false,
|
||||||
|
officeProvider: '',
|
||||||
maxVersionsKept: 5,
|
maxVersionsKept: 5,
|
||||||
logoUrl: '',
|
logoUrl: '',
|
||||||
faviconUrl: '',
|
faviconUrl: '',
|
||||||
@@ -89,6 +98,7 @@ export function AppSettingsProvider({ children }: { children: ReactNode }) {
|
|||||||
const [appIconUrl, setAppIconUrl] = useState('')
|
const [appIconUrl, setAppIconUrl] = useState('')
|
||||||
const [globalColors, setGlobalColors] = useState<{ primary?: string; accent?: string }>({})
|
const [globalColors, setGlobalColors] = useState<{ primary?: string; accent?: string }>({})
|
||||||
const [officeEnabled, setOfficeEnabled] = useState(false)
|
const [officeEnabled, setOfficeEnabled] = useState(false)
|
||||||
|
const [officeProvider, setOfficeProvider] = useState('')
|
||||||
const [maxVersionsKept, setMaxVersionsKept] = useState(5)
|
const [maxVersionsKept, setMaxVersionsKept] = useState(5)
|
||||||
|
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
@@ -101,6 +111,7 @@ export function AppSettingsProvider({ children }: { children: ReactNode }) {
|
|||||||
applyFavicon(cfg.favicon_url ?? '', cfg.apple_touch_icon_url ?? '')
|
applyFavicon(cfg.favicon_url ?? '', cfg.apple_touch_icon_url ?? '')
|
||||||
setGlobalColors({ primary: cfg.primary_color, accent: cfg.accent_color })
|
setGlobalColors({ primary: cfg.primary_color, accent: cfg.accent_color })
|
||||||
setOfficeEnabled(!!cfg.office_enabled)
|
setOfficeEnabled(!!cfg.office_enabled)
|
||||||
|
setOfficeProvider(cfg.office_provider ?? '')
|
||||||
if (typeof cfg.max_versions_kept === 'number' && cfg.max_versions_kept > 0) {
|
if (typeof cfg.max_versions_kept === 'number' && cfg.max_versions_kept > 0) {
|
||||||
setMaxVersionsKept(cfg.max_versions_kept)
|
setMaxVersionsKept(cfg.max_versions_kept)
|
||||||
}
|
}
|
||||||
@@ -116,7 +127,7 @@ export function AppSettingsProvider({ children }: { children: ReactNode }) {
|
|||||||
useEffect(() => { void refresh() }, [refresh])
|
useEffect(() => { void refresh() }, [refresh])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Ctx.Provider value={{ cloudName, logoUrl, faviconUrl, appIconUrl, globalColors, officeEnabled, maxVersionsKept, refresh }}>{children}</Ctx.Provider>
|
<Ctx.Provider value={{ cloudName, logoUrl, faviconUrl, appIconUrl, globalColors, officeEnabled, officeProvider, maxVersionsKept, refresh }}>{children}</Ctx.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ export default function FileBrowser({
|
|||||||
const [officePreview, setOfficePreview] = useState<FileItem | null>(null)
|
const [officePreview, setOfficePreview] = useState<FileItem | null>(null)
|
||||||
/** Datei, die gerade im Office-Server bearbeitet wird. */
|
/** Datei, die gerade im Office-Server bearbeitet wird. */
|
||||||
const [editing, setEditing] = useState<FileItem | null>(null)
|
const [editing, setEditing] = useState<FileItem | null>(null)
|
||||||
const { officeEnabled } = useAppSettings()
|
const { officeEnabled, officeProvider } = useAppSettings()
|
||||||
/** Finger oder Maus? Entscheidet, ob ein Office-Dokument als PDF oder im
|
/** Finger oder Maus? Entscheidet, ob ein Office-Dokument als PDF oder im
|
||||||
* Editor aufgeht. */
|
* Editor aufgeht. */
|
||||||
const touchDevice = useCoarsePointer()
|
const touchDevice = useCoarsePointer()
|
||||||
@@ -316,15 +316,19 @@ export default function FileBrowser({
|
|||||||
*/
|
*/
|
||||||
function openFile(file: FileItem) {
|
function openFile(file: FileItem) {
|
||||||
if (officeEnabled && isOfficeFile(file.name)) {
|
if (officeEnabled && isOfficeFile(file.name)) {
|
||||||
// Am Telefon zuerst ansehen, nicht bearbeiten. Der Editor ist dort eine
|
// **Nur bei OnlyOffice** öffnet ein Dokument am Telefon als PDF.
|
||||||
// vollständige Textverarbeitung; zwischen Menüband, Formatleisten und
|
//
|
||||||
// Eigenschaftenbereich bleibt vom Dokument ein Rechteck. Gilt für
|
// Der Unterschied ist gemessen, nicht vermutet: Collabora bringt eine
|
||||||
// Collabora wie für OnlyOffice – beide ausprobiert, dasselbe Bild.
|
// eigene Handy-Ansicht mit, die taugt – dort ist der Editor der
|
||||||
|
// richtige Weg. OnlyOffice baut auf dem Telefon dieselbe Oberfläche
|
||||||
|
// auf wie am PC; zwischen Menüband, Formatleisten und
|
||||||
|
// Eigenschaftenbereich bleibt vom Dokument ein Rechteck übrig, und
|
||||||
|
// genau das war der Anlass für die PDF-Ansicht.
|
||||||
//
|
//
|
||||||
// Die Entscheidung fällt am **Zeigegerät**, nicht an der Fensterbreite:
|
// Die Entscheidung fällt am **Zeigegerät**, nicht an der Fensterbreite:
|
||||||
// Ein schmales Fenster auf dem Schreibtisch ist immer noch eine Maus
|
// Ein schmales Fenster auf dem Schreibtisch ist immer noch eine Maus
|
||||||
// und eine Tastatur, und dort will man bearbeiten.
|
// und eine Tastatur, und dort will man bearbeiten.
|
||||||
if (touchDevice) setOfficePreview(file)
|
if (touchDevice && officeProvider === 'onlyoffice') setOfficePreview(file)
|
||||||
else setEditing(file)
|
else setEditing(file)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user