Files
Client/lib/view/pages/files/widgets/file_leading.dart
T

78 lines
2.7 KiB
Dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import '../../../../api/marianumcloud/webdav/queries/list_files/cacheable_file.dart';
import '../../../../model/account_data.dart';
import '../../../../model/endpoint_data.dart';
import '../data/file_type_icon.dart';
/// Leading slot for a file row: shows the Nextcloud thumbnail when the
/// server can render one (`nc:has-preview`), otherwise a typed file icon.
/// Always reserves the same square so rows stay aligned regardless of
/// whether a preview is present.
class FileLeading extends StatelessWidget {
final CacheableFile file;
/// Edge length of the rendered square. Defaults to the regular row size;
/// use a larger value (e.g. in detail sheets) where appropriate.
final double size;
const FileLeading({required this.file, this.size = 28, super.key});
@override
Widget build(BuildContext context) {
final icon = Icon(iconForFile(file), size: size);
final fileId = file.fileId;
final base = SizedBox(
width: size,
height: size,
child: (file.isDirectory || file.hasPreview != true || fileId == null)
? Center(child: icon)
: ClipRRect(
borderRadius: BorderRadius.circular(4),
child: CachedNetworkImage(
imageUrl:
'https://${EndpointData().nextcloud().full()}'
'/index.php/core/preview'
'?fileId=$fileId&x=128&y=128&a=0',
httpHeaders: AccountData().authHeaders(),
fit: BoxFit.cover,
fadeInDuration: Duration.zero,
fadeOutDuration: Duration.zero,
errorListener: (_) {},
// Icon doubles as the loading placeholder so the list doesn't
// pop a spinner per row while thumbnails stream in.
placeholder: (_, _) => Center(child: icon),
errorWidget: (_, _, _) => Center(child: icon),
),
),
);
// Badge incoming shares (shared with the user by someone else).
if (file.isSharedWithMe != true) return base;
final colors = Theme.of(context).colorScheme;
return Stack(
clipBehavior: Clip.none,
children: [
base,
Positioned(
right: -3,
bottom: -3,
child: Container(
decoration: BoxDecoration(
color: colors.errorContainer,
shape: BoxShape.circle,
),
padding: const EdgeInsets.all(1),
child: Icon(
Icons.people,
size: size * 0.45,
color: colors.onErrorContainer,
),
),
),
],
);
}
}