simplified code across the app and consolidated duplicated helpers

This commit is contained in:
2026-09-27 17:29:54 +02:00
parent 3e856d0b1c
commit ee1240f71a
155 changed files with 1772 additions and 2546 deletions
@@ -21,6 +21,18 @@ import 'share_password_sheet.dart';
String _two(int n) => n.toString().padLeft(2, '0');
String _isoDate(DateTime d) => '${d.year}-${_two(d.month)}-${_two(d.day)}';
/// Token of the Talk room a share points to; null for other share kinds.
String? talkRoomTokenOf(Share share) {
final token = share.shareWith;
return share.isRoom && token != null && token.isNotEmpty ? token : null;
}
/// Opens the Talk room and closes the sheet it was opened from.
void openShareInTalk(BuildContext context, String token) {
AppRoutes.openChatByToken(context, token);
if (Navigator.of(context).canPop()) Navigator.of(context).pop();
}
IconData shareIcon(Share share) {
if (share.isPublicLink) return Icons.link;
if (share.isGroup) return Icons.groups_outlined;
@@ -85,6 +97,9 @@ class _ShareOptionsBodyState extends State<_ShareOptionsBody> {
}
}
Future<void> _update(ShareUpdateParams params) =>
_mutate(() => FileSharingApi().update(_share.id, params));
List<SharePreset> _availablePresets() => [
SharePreset.readOnly,
SharePreset.edit,
@@ -93,15 +108,12 @@ class _ShareOptionsBodyState extends State<_ShareOptionsBody> {
Future<void> _setPreset(SharePreset preset) async {
final caps = context.read<NextcloudCapabilitiesCubit>();
await _mutate(
() => FileSharingApi().update(
_share.id,
ShareUpdateParams(
permissions: permissionsFor(
preset,
allowReshare: caps.canReshare,
isFolder: _share.isFolder,
),
await _update(
ShareUpdateParams(
permissions: permissionsFor(
preset,
allowReshare: caps.canReshare,
isFolder: _share.isFolder,
),
),
);
@@ -121,20 +133,11 @@ class _ShareOptionsBodyState extends State<_ShareOptionsBody> {
lastDate: lastDate,
);
if (picked == null) return;
await _mutate(
() => FileSharingApi().update(
_share.id,
ShareUpdateParams(expireDate: _isoDate(picked)),
),
);
await _update(ShareUpdateParams(expireDate: _isoDate(picked)));
}
Future<void> _clearExpiry() => _mutate(
() => FileSharingApi().update(
_share.id,
const ShareUpdateParams(expireDate: ''),
),
);
Future<void> _clearExpiry() =>
_update(const ShareUpdateParams(expireDate: ''));
Future<void> _changePassword() async {
final caps = context.read<NextcloudCapabilitiesCubit>();
@@ -144,27 +147,11 @@ class _ShareOptionsBodyState extends State<_ShareOptionsBody> {
policyHint: caps.passwordPolicyHint,
);
if (value == null || value.isEmpty || !mounted) return;
await _mutate(
() => FileSharingApi().update(
_share.id,
ShareUpdateParams(password: value),
),
);
await _update(ShareUpdateParams(password: value));
}
Future<void> _clearPassword() => _mutate(
() => FileSharingApi().update(
_share.id,
const ShareUpdateParams(password: ''),
),
);
void _openInTalk() {
final token = _share.shareWith;
if (token == null || token.isEmpty) return;
AppRoutes.openChatByToken(context, token);
if (Navigator.of(context).canPop()) Navigator.of(context).pop();
}
Future<void> _clearPassword() =>
_update(const ShareUpdateParams(password: ''));
Future<void> _confirmDelete() async {
// Use showDialog directly (not asDialog) so we get the AsyncDialogAction's
@@ -217,12 +204,12 @@ class _ShareOptionsBodyState extends State<_ShareOptionsBody> {
),
),
if (_share.isRoom && (_share.shareWith?.isNotEmpty ?? false)) ...[
if (talkRoomTokenOf(_share) case final token?) ...[
const Divider(height: 24),
ListTile(
leading: const CenteredLeading(Icon(Icons.chat_bubble_outline)),
title: const Text('Im Talk-Chat öffnen'),
onTap: _busy ? null : _openInTalk,
onTap: _busy ? null : () => openShareInTalk(context, token),
),
],
+5 -18
View File
@@ -47,19 +47,13 @@ class _ShareSheetBody extends StatefulWidget {
class _ShareSheetBodyState extends State<_ShareSheetBody> {
late final String _ocsPath = ocsPathOf(widget.file);
Future<List<Share>>? _future;
late Future<List<Share>> _future = FileSharingApi().listForPath(_ocsPath);
bool _busy = false;
/// Last resolved share list — used by the create-link gate without depending
/// on the FutureBuilder's snapshot.
List<Share>? _lastShares;
@override
void initState() {
super.initState();
_future = FileSharingApi().listForPath(_ocsPath);
}
void _reload() {
// Block body: an arrow would return the Future, which setState rejects.
setState(() {
@@ -144,26 +138,19 @@ class _ShareSheetBodyState extends State<_ShareSheetBody> {
leading: const CenteredLeading(Icon(Icons.person_add_outlined)),
title: const Text('Person oder Gruppe hinzufügen'),
enabled: !_busy,
onTap: _busy ? null : _addSharee,
onTap: _addSharee,
),
if (caps.canCreatePublicLinks && _canAddLink(caps))
ListTile(
leading: const CenteredLeading(Icon(Icons.add_link)),
title: const Text('Öffentlichen Link erstellen'),
enabled: !_busy,
onTap: _busy ? null : _createPublicLink,
onTap: _createPublicLink,
),
],
);
}
void _openInTalk(Share share) {
final token = share.shareWith;
if (token == null || token.isEmpty) return;
AppRoutes.openChatByToken(context, token);
if (Navigator.of(context).canPop()) Navigator.of(context).pop();
}
/// Whether another public link may be created — hidden once one exists on a
/// server that disallows multiple links.
bool _canAddLink(NextcloudCapabilitiesCubit caps) {
@@ -271,11 +258,11 @@ class _ShareSheetBodyState extends State<_ShareSheetBody> {
tooltip: 'Link kopieren',
onPressed: () => copyToClipboard(context, share.url!),
),
if (share.isRoom && (share.shareWith?.isNotEmpty ?? false))
if (talkRoomTokenOf(share) case final token?)
IconButton(
icon: const Icon(Icons.chat_bubble_outline),
tooltip: 'Im Talk-Chat öffnen',
onPressed: () => _openInTalk(share),
onPressed: () => openShareInTalk(context, token),
),
IconButton(
icon: const Icon(Icons.settings_outlined),