Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ class _RowAvatar extends StatelessWidget {
final initial =
profile?.initial ?? (pubkey.isNotEmpty ? pubkey[0].toUpperCase() : '?');
return AvatarImage(
pubkey: pubkey,
imageUrl: profile?.avatarUrl,
radius: activityAvatarSize / 2,
backgroundColor: context.colors.primaryContainer,
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/channels/add_members_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class AddChannelMembersSheet extends HookConsumerWidget {
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: AvatarImage(
pubkey: user.pubkey,
imageUrl: user.avatarUrl,
radius: 20,
backgroundColor:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ class _HuddleCallAvatar extends HookConsumerWidget {
),
)
: AvatarImage(
pubkey: pubkey,
key: ValueKey('huddle-avatar-image-$pubkey'),
imageUrl: profile?.avatarUrl,
radius: avatarRadius,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ class _HuddleParticipantSpotlight extends ConsumerWidget {
),
),
child: AvatarImage(
pubkey: pubkey,
imageUrl: profile?.avatarUrl,
radius: _huddleParticipantSpotlightRadius,
backgroundColor: context.colors.primaryContainer,
Expand Down Expand Up @@ -346,6 +347,7 @@ class _HuddleParticipantRoster extends ConsumerWidget {
child: Row(
children: [
AvatarImage(
pubkey: pubkey,
imageUrl: profile?.avatarUrl,
radius: 22,
backgroundColor:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ class _UserAvatar extends StatelessWidget {
final avatarUrl = profile?.avatarUrl;

return AvatarImage(
pubkey: pubkey,
imageUrl: avatarUrl,
radius: size / 2,
backgroundColor: context.colors.primaryContainer,
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/channels/channel_details_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ class _ChannelMemberPreviewRow extends StatelessWidget {

return AppListRowRaw(
leading: AvatarImage(
pubkey: member.pubkey,
imageUrl: avatarUrl,
radius: 20,
backgroundColor: context.colors.primaryContainer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class _DmAvatar extends ConsumerWidget {
clipBehavior: Clip.none,
children: [
AvatarImage(
pubkey: otherPubkey,
imageUrl: avatarUrl,
radius: _kDmAvatarSize / 2,
backgroundColor: context.colors.primaryContainer,
Expand Down
2 changes: 2 additions & 0 deletions mobile/lib/features/channels/channels_page/sheets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ class _NewDirectMessageSheet extends HookConsumerWidget {
horizontal: Grid.half,
),
leading: AvatarImage(
pubkey: user.pubkey,
imageUrl: user.avatarUrl,
radius: 20,
backgroundColor: context.colors.primaryContainer,
Expand Down Expand Up @@ -838,6 +839,7 @@ class _SelectedDmRecipientChip extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
AvatarImage(
pubkey: user.pubkey,
imageUrl: user.avatarUrl,
radius: 16,
backgroundColor: context.colors.primaryContainer,
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/channels/compose_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import '../../shared/huddle/huddle_session.dart';
import '../../shared/relay/relay.dart';
import '../../shared/theme/theme.dart';
import '../../shared/widgets/avatar_image.dart';
import '../../shared/widgets/agent_provenance.dart';
import '../../shared/widgets/anchored_popover_menu.dart';
import '../../shared/widgets/buzz_loading_indicator.dart';
import '../../shared/widgets/concentric_sheet_surface.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,13 @@ class ComposeBar extends HookConsumerWidget {
'\u0000',
);
useEffect(() {
controller.setMentionPubkeys({
for (final entry in mentionMap.value.entries)
entry.key.toLowerCase(): entry.value.pubkey,
});
controller.setAgentMentionNames(agentMentionLabels);
return null;
}, [controller, agentMentionLabelsKey]);
}, [controller, agentMentionLabelsKey, mentionMap.value]);
useEffect(
() {
final memberList = channelMembersForAutocomplete(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class _MarkdownRule {
}

class _MarkdownEditingController extends TextEditingController {
Map<String, String> _mentionPubkeys = const {};
final Set<String> _agentMentionNames = <String>{};
TextSpan? _cachedTextSpan;
String? _cachedText;
Expand All @@ -24,6 +25,13 @@ class _MarkdownEditingController extends TextEditingController {
Color? _cachedSurface;
Map<String, String> _channelNames = const {};

void setMentionPubkeys(Map<String, String> keys) {
if (mapEquals(keys, _mentionPubkeys)) return;
_mentionPubkeys = keys;
_cachedTextSpan = null;
notifyListeners();
}

void setChannelNames(Map<String, String> names) {
if (mapEquals(_channelNames, names)) return;
_channelNames = Map.unmodifiable(names);
Expand Down Expand Up @@ -296,7 +304,11 @@ class _MarkdownEditingController extends TextEditingController {
WidgetSpan(
alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic,
child: _ComposerAgentMentionChip(label: label, textStyle: style),
child: _ComposerAgentMentionChip(
label: label,
textStyle: style,
pubkey: _mentionPubkeys[label.toLowerCase()],
),
),
);
// The visual chip replaces the `@` placeholder. Keep the label as
Expand Down Expand Up @@ -547,26 +559,31 @@ class _ComposerBuzzLinkChip extends StatelessWidget {
}
}

class _ComposerAgentMentionChip extends StatelessWidget {
class _ComposerAgentMentionChip extends ConsumerWidget {
final String? pubkey;
final String label;
final TextStyle textStyle;

const _ComposerAgentMentionChip({
this.pubkey,
required this.label,
required this.textStyle,
});

@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
final style = textStyle.copyWith(
color: context.colors.primary,
fontWeight: FontWeight.w500,
height: 1,
);
final fontSize = style.fontSize ?? 16;

final notManaged =
pubkey != null && ref.watch(agentNotManagedHereProvider(pubkey!));
return Semantics(
label: 'Agent mention: $label',
label:
'Agent mention: $label${notManaged ? ', Not managed on this device' : ''}',
excludeSemantics: true,
child: Container(
key: const ValueKey('composer-agent-mention-chip'),
Expand Down Expand Up @@ -597,6 +614,7 @@ class _ComposerAgentMentionChip extends StatelessWidget {
),
const SizedBox(width: Grid.quarter),
Text(label, style: style),
AgentProvenance(pubkey: pubkey),
],
),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class _MentionSuggestions extends StatelessWidget {
dense: true,
visualDensity: VisualDensity.compact,
leading: AvatarImage(
pubkey: candidate.pubkey,
imageUrl: avatarUrl,
radius: 18,
backgroundColor: context.colors.primaryContainer,
Expand Down
4 changes: 4 additions & 0 deletions mobile/lib/features/channels/members_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ class _MemberTile extends ConsumerWidget {
return ListTile(
contentPadding: EdgeInsets.zero,
leading: _MemberAvatar(
pubkey: member.pubkey,
avatarUrl: profile?.avatarUrl,
initial: initial,
isAgent: member.isBot || profile?.isAgent == true,
Expand Down Expand Up @@ -446,11 +447,13 @@ class _RoleSelector extends StatelessWidget {
}

class _MemberAvatar extends StatelessWidget {
final String pubkey;
final String? avatarUrl;
final String initial;
final bool isAgent;

const _MemberAvatar({
required this.pubkey,
required this.avatarUrl,
required this.initial,
required this.isAgent,
Expand All @@ -459,6 +462,7 @@ class _MemberAvatar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AvatarImage(
pubkey: pubkey,
imageUrl: avatarUrl,
radius: 20,
fallback: Text(initial),
Expand Down
5 changes: 5 additions & 0 deletions mobile/lib/features/channels/message_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:video_player/video_player.dart';
import '../../shared/clipboard_utils.dart';
import '../../shared/mentions/mention_bindings.dart';
import '../../shared/mentions/mention_tags.dart';
import '../../shared/widgets/agent_provenance.dart';
import '../../shared/deeplink/deep_link.dart';
import '../../shared/deeplink/pending_deep_link_provider.dart';
import '../../shared/relay/relay.dart';
Expand Down Expand Up @@ -878,6 +879,7 @@ class _MentionMd extends InlineMd {
final pill = _MentionPill(
label: visibleLabel,
semanticsLabel: fullLabel,
pubkey: pubkey,
isAgent: isAgent,
textStyle: config.style,
);
Expand All @@ -893,12 +895,14 @@ class _MentionMd extends InlineMd {
}

class _MentionPill extends StatelessWidget {
final String? pubkey;
final String label;
final String? semanticsLabel;
final bool isAgent;
final TextStyle? textStyle;

const _MentionPill({
this.pubkey,
required this.label,
this.semanticsLabel,
required this.isAgent,
Expand Down Expand Up @@ -950,6 +954,7 @@ class _MentionPill extends StatelessWidget {
Flexible(
child: Text(label, style: style, semanticsLabel: semanticsLabel),
),
AgentProvenance(pubkey: pubkey),
],
),
);
Expand Down
4 changes: 4 additions & 0 deletions mobile/lib/features/channels/reaction_row.dart
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ class _ReactorTile extends StatelessWidget {

return ListTile(
leading: _ReactorAvatar(
pubkey: pubkey,
avatarUrl: profile?.avatarUrl,
initial:
profile?.initial ??
Expand Down Expand Up @@ -486,11 +487,13 @@ class _ReactorTile extends StatelessWidget {
}

class _ReactorAvatar extends StatelessWidget {
final String pubkey;
final String? avatarUrl;
final String initial;
final bool isAgent;

const _ReactorAvatar({
required this.pubkey,
required this.avatarUrl,
required this.initial,
required this.isAgent,
Expand All @@ -499,6 +502,7 @@ class _ReactorAvatar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AvatarImage(
pubkey: pubkey,
imageUrl: avatarUrl,
radius: 20,
fallback: Text(initial),
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/channels/small_avatar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class SmallAvatar extends StatelessWidget {
border: Border.all(color: context.colors.surface, width: 1.5),
),
child: AvatarImage(
pubkey: pubkey,
imageUrl: avatarUrl,
radius: (size - 2) / 2,
backgroundColor: context.colors.primaryContainer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class _Avatar extends StatelessWidget {
final avatarUrl = profile?.avatarUrl;

return AvatarImage(
pubkey: pubkey,
imageUrl: avatarUrl,
radius: messageAvatarSize / 2,
backgroundColor: context.colors.primaryContainer,
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/forum/forum_post_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ class _PostAvatar extends StatelessWidget {
final avatarUrl = profile?.avatarUrl;

return AvatarImage(
pubkey: pubkey,
imageUrl: avatarUrl,
radius: 14,
backgroundColor: context.colors.primaryContainer,
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/forum/forum_thread_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ class _Avatar extends StatelessWidget {
final avatarUrl = profile?.avatarUrl;

return AvatarImage(
pubkey: pubkey,
imageUrl: avatarUrl,
radius: radius,
backgroundColor: context.colors.primaryContainer,
Expand Down
28 changes: 22 additions & 6 deletions mobile/lib/features/profile/user_profile_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import '../../shared/relay/relay.dart';
import '../../shared/theme/theme.dart';
import '../../shared/utils/string_utils.dart';
import '../../shared/widgets/avatar_image.dart';
import '../../shared/widgets/agent_provenance.dart';
import '../../shared/widgets/buzz_action_tile.dart';
import '../../shared/widgets/modal_presentation.dart';
import '../../shared/widgets/progressive_animated_avatar.dart';
Expand Down Expand Up @@ -172,6 +173,7 @@ class UserProfileSheet extends HookConsumerWidget {
child: FractionallySizedBox(
widthFactor: 0.5,
child: _ProfileAvatar(
pubkey: pubkey,
avatarUrl: avatarUrl,
initial: initial,
isAgent: profile?.isAgent == true,
Expand Down Expand Up @@ -400,11 +402,13 @@ class _ProfilePresenceChip extends StatelessWidget {
}

class _ProfileAvatar extends HookWidget {
final String pubkey;
final String? avatarUrl;
final String initial;
final bool isAgent;

const _ProfileAvatar({
required this.pubkey,
required this.avatarUrl,
required this.initial,
required this.isAgent,
Expand Down Expand Up @@ -440,12 +444,24 @@ class _ProfileAvatar extends HookWidget {
imageUrl: animatedAvatar?.posterUrl ?? avatarUrl,
fallback: _AvatarFallback(initial: initial),
);
if (!isAgent) return ClipOval(child: avatar);
return ClipRRect(
borderRadius: BorderRadius.circular(
constraints.biggest.shortestSide * 0.3,
),
child: avatar,
final shaped = !isAgent
? ClipOval(child: avatar)
: ClipRRect(
borderRadius: BorderRadius.circular(
constraints.biggest.shortestSide * 0.3,
),
child: avatar,
);
return Stack(
fit: StackFit.expand,
children: [
shaped,
Positioned(
right: 0,
top: 0,
child: AgentProvenance(pubkey: pubkey, size: 24),
),
],
);
},
),
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/pulse/agent_activity_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class AgentActivityCard extends HookConsumerWidget {
Stack(
children: [
AvatarImage(
pubkey: group.pubkey,
imageUrl: profile?.avatarUrl,
radius: 18,
backgroundColor: context.colors.primaryContainer,
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/features/pulse/note_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class NoteCard extends HookConsumerWidget {
GestureDetector(
onTap: () => showUserProfileSheet(context, note.pubkey),
child: AvatarImage(
pubkey: note.pubkey,
imageUrl: profile?.avatarUrl,
radius: 18,
backgroundColor: context.colors.primaryContainer,
Expand Down
Loading
Loading