Your avatar is your photo, picked from the device by tapping it on Home or from a new Profile photo row in Settings, shrunk to 256 px and kept on the phone (there is no upload endpoint yet). Group members show the photo the server sends in a new `photo` field, everywhere avatars appear. Without a photo, an initial on a neutral disc. Mock mode bundles free Unsplash portraits for the sample people. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhQh614DMeYoQEH9SoMRUw
55 lines
1.8 KiB
Dart
55 lines
1.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../about/internal/application/TextType.dart';
|
|
import '../utils/Colors.dart';
|
|
import 'Portrait.dart';
|
|
import 'text/Text.dart';
|
|
|
|
/// A member's round photo, or their initial when they have none.
|
|
Widget memberAvatar(String name, double size,
|
|
{String photo = "", Color? border}) {
|
|
return portrait(photo, name, size, border: border);
|
|
}
|
|
|
|
/// Several portraits overlapping, with "+N" once there are more than fit.
|
|
/// [photos] lines up with [names]; missing entries fall back to initials.
|
|
Widget avatarStack(List<String> names, double size,
|
|
{List<String> photos = const <String>[], int max = 4, Color? border}) {
|
|
final List<String> shown = names.take(max).toList();
|
|
final int extra = names.length - shown.length;
|
|
final double step = size * 0.68;
|
|
final int slots = shown.length + (extra > 0 ? 1 : 0);
|
|
|
|
return SizedBox(
|
|
width: slots == 0 ? 0 : size + step * (slots - 1),
|
|
height: size,
|
|
child: Stack(
|
|
children: [
|
|
for (int index = 0; index < shown.length; index++)
|
|
Positioned(
|
|
left: step * index,
|
|
child: memberAvatar(shown[index], size,
|
|
photo: index < photos.length ? photos[index] : "",
|
|
border: border),
|
|
),
|
|
if (extra > 0)
|
|
Positioned(
|
|
left: step * shown.length,
|
|
child: Container(
|
|
width: size,
|
|
height: size,
|
|
alignment: Alignment.center,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: colorNight,
|
|
border: Border.all(color: border ?? colorWhite, width: 2),
|
|
),
|
|
child: text("+$extra", size * 0.34, TextType.Medium,
|
|
color: colorWhite),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|