Files
Client/lib/widget/large_profile_picture_view.dart
T

97 lines
2.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:photo_view/photo_view.dart';
import '../api/errors/error_mapper.dart';
import 'a11y/a11y_labels.dart';
import 'app_progress_indicator.dart';
import 'placeholder_view.dart';
import 'user_avatar.dart';
/// Full-screen avatar. Loads the bytes itself instead of handing the URL to an
/// [ImageProvider]: Nextcloud and Spreed serve generated avatars as SVG, which
/// no codec can decode ("Invalid image data") — those get an [SvgPicture]
/// instead of the zoomable [PhotoView].
class LargeProfilePictureView extends StatefulWidget {
final String id;
final bool isGroup;
const LargeProfilePictureView({
required this.id,
this.isGroup = false,
super.key,
});
@override
State<LargeProfilePictureView> createState() =>
_LargeProfilePictureViewState();
}
class _LargeProfilePictureViewState extends State<LargeProfilePictureView> {
late Future<AvatarPayload?> _payload;
@override
void initState() {
super.initState();
_payload = loadAvatarPayload(
id: widget.id,
isGroup: widget.isGroup,
size: 1024,
);
}
@override
Widget build(BuildContext context) {
final label = widget.isGroup
? A11yLabels.groupPicture
: A11yLabels.profilePicture;
final background = Theme.of(context).colorScheme.surface;
return Scaffold(
appBar: AppBar(title: Text(label)),
body: Semantics(
image: true,
label: label,
child: FutureBuilder<AvatarPayload?>(
future: _payload,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const Center(child: AppProgressIndicator.large());
}
final payload = snapshot.data;
if (snapshot.hasError) {
return PlaceholderView(
icon: Icons.broken_image_outlined,
text: errorToUserMessage(snapshot.error),
);
}
// No avatar on the server — the same icon the small avatar shows.
if (payload == null) {
return PlaceholderView(
icon: widget.isGroup ? Icons.group : Icons.person,
text: 'Kein Bild hinterlegt.',
);
}
if (payload.isSvg) {
return ColoredBox(
color: background,
child: InteractiveViewer(
minScale: 0.5,
maxScale: 3,
child: SvgPicture.memory(payload.bytes, fit: BoxFit.contain),
),
);
}
return PhotoView(
minScale: 0.5,
maxScale: 3.0,
imageProvider: MemoryImage(payload.bytes),
backgroundDecoration: BoxDecoration(color: background),
);
},
),
),
);
}
}