Show real photos for people instead of scene art
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
This commit is contained in:
@@ -27,6 +27,7 @@ import '../../designs/Component.dart';
|
||||
import '../../designs/FloatingNav.dart';
|
||||
import '../../designs/GlassSurface.dart';
|
||||
import '../../designs/MemberAvatar.dart';
|
||||
import '../../designs/Portrait.dart';
|
||||
import '../../designs/ProgressRing.dart';
|
||||
import '../../designs/Responsive.dart';
|
||||
import '../../designs/Shell.dart';
|
||||
@@ -35,6 +36,7 @@ import '../../designs/input/InputFields.dart';
|
||||
import '../../designs/scene/SceneArt.dart';
|
||||
import '../../designs/text/Text.dart';
|
||||
import '../../utils/Colors.dart';
|
||||
import '../../utils/PhotoPicker.dart';
|
||||
import '../../utils/CommonUtils.dart';
|
||||
import '../../utils/StandingEngine.dart';
|
||||
import '../../utils/Thresholds.dart';
|
||||
@@ -247,6 +249,13 @@ class HomeState extends State<Home> implements ConnectHome {
|
||||
}
|
||||
}
|
||||
|
||||
void _onChangePhoto() async {
|
||||
final String? pic = await PhotoPicker.pickPortrait();
|
||||
if (pic != null) {
|
||||
_model?.savePhoto(pic);
|
||||
}
|
||||
}
|
||||
|
||||
void _onOpenSettings() {
|
||||
GroundedNavigation()
|
||||
.navigateToPage(NavigatorType.justOpen, const Settings(), context);
|
||||
@@ -1194,28 +1203,11 @@ class HomeState extends State<Home> implements ConnectHome {
|
||||
// ── Header helpers ────────────────────────────────────────────────────────
|
||||
|
||||
/// A portrait cut from the painted landscape, with the initial on it.
|
||||
/// Your photo. Tapping it picks a new one.
|
||||
Widget _avatar(double size) {
|
||||
final String initial =
|
||||
_user.name.isEmpty ? "G" : _user.name.substring(0, 1).toUpperCase();
|
||||
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: colorWhite, width: 2),
|
||||
),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
SceneArt(palette: sceneWorkout, seed: sceneSeed(_user.name)),
|
||||
Center(
|
||||
child:
|
||||
text(initial, size * 0.4, TextType.Medium, color: colorWhite),
|
||||
),
|
||||
],
|
||||
),
|
||||
return GestureDetector(
|
||||
onTap: _onChangePhoto,
|
||||
child: portrait(_user.pic, _user.name, size),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1705,7 +1697,10 @@ class HomeState extends State<Home> implements ConnectHome {
|
||||
children: [
|
||||
avatarStack(
|
||||
group.members.map((member) => member.name).toList(),
|
||||
26),
|
||||
26,
|
||||
photos: group.members
|
||||
.map((member) => member.photo)
|
||||
.toList()),
|
||||
const Spacer(),
|
||||
Icon(CupertinoIcons.chat_bubble_2_fill,
|
||||
size: 16, color: colorInkSoft),
|
||||
|
||||
Reference in New Issue
Block a user