feat(nextcloud-files): Teilen in Modul-Changelog, Anleitungen und Changelog

- Modul-Changelog: unveroeffentlichter Eintrag 1.0.0 um drei Teilen-Punkte erweitert (Version bleibt 1.0.0)
- CHANGELOG.md: Dateien, Teilen und Dateien, Uebersicht der Freigaben
- Anleitungen Anwender, Administration, Betrieb, Entwicklung beschreiben das Teilen
- Live-Test e2e-shares.sh: Abschnitt version
- Teilen-Dialog: Linkformular scrollt beim Oeffnen in den sichtbaren Bereich
- Mit mir geteilt: offene Freigaben zeigen kein irrefuehrendes Eigene Berechtigung

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-09 11:46:18 +02:00
parent c3adf851b8
commit 0585fd17c4
11 changed files with 129 additions and 5 deletions
@@ -1,7 +1,7 @@
'use client';
import { useLocale, useTranslations } from 'next-intl';
import { useId, useRef, useState } from 'react';
import { useEffect, useId, useRef, useState } from 'react';
import { copyText } from '@/components/nextcloud-files/clipboard';
import {
accessOptions,
@@ -75,6 +75,7 @@ export function LinkShareForm({
const [showPassword, setShowPassword] = useState(false);
const [passwordCopied, setPasswordCopied] = useState(false);
const passwordInput = useRef<HTMLInputElement>(null);
const formRef = useRef<HTMLFormElement>(null);
const passwordFieldVisible = editing ? editPassword === 'change' : createPasswordOn;
// --- Ablauf ---
@@ -127,11 +128,18 @@ export function LinkShareForm({
setPasswordCopied(ok);
};
// Das Formular steht unter den Personen im scrollbaren Dialog: beim Öffnen ganz in den
// sichtbaren Bereich holen, damit „Link erstellen“ und „Abbrechen“ nicht verborgen bleiben.
useEffect(() => {
formRef.current?.scrollIntoView?.({ block: 'nearest' });
}, []);
const passwordLabel = required ? t('passwordRequiredLabel') : t('passwordLabel');
const expiryLabel = rule.required ? t('expiryRequiredLabel') : t('expiryLabel');
return (
<form
ref={formRef}
onSubmit={submit}
aria-label={editing ? t('titleEdit') : t('titleCreate')}
className="mt-3 space-y-4 rounded border border-border bg-well/40 p-3"
@@ -283,6 +283,8 @@ describe('SharesView — Mit mir geteilt', () => {
name: 'Ben-Briefkasten',
target: '/Ben-Briefkasten',
pending: true,
permissions: 0,
access: 'custom',
});
mockReceived.mockResolvedValue({
shares: [incoming()],
@@ -292,6 +294,8 @@ describe('SharesView — Mit mir geteilt', () => {
});
mount('withMe');
expect(await screen.findByText('Noch nicht angenommen')).toBeTruthy();
// die Nextcloud meldet offene Freigaben ohne Berechtigung: kein irreführendes "Eigene Berechtigung"
expect(screen.queryByText(/Eigene Berechtigung/)).toBeNull();
// keine "Öffnen"-Aktion fuer eine offene Freigabe
expect(screen.queryByRole('button', { name: '„Ben-Briefkasten“ öffnen' })).toBeNull();
@@ -200,7 +200,9 @@ export function SharesView({
<p className="truncate text-xs text-muted-foreground">
{[
share.ownerName ? t('from', { name: share.ownerName }) : null,
accessText(share),
// Eine noch offene Freigabe meldet die Nextcloud ohne Berechtigung (gemessen: 0);
// „Eigene Berechtigung“ wäre dort irreführend, also steht nichts.
isPending ? null : accessText(share),
share.expiration
? tShare('people.expires', { date: dateText(share.expiration, locale) })
: null,