diff --git a/mobile/assets/fonts/README.md b/mobile/assets/fonts/README.md index 723570d71a..346e08c335 100644 --- a/mobile/assets/fonts/README.md +++ b/mobile/assets/fonts/README.md @@ -50,3 +50,16 @@ this check. PR images may be cropped afterward for readability. artifacts in the existing Flutter test lane. Restoring either original font or changing any other font data fails CI. When upgrading Inter, verify the transformation and native rendering before updating the expected digests. + +## Tabler mobile preview + +`TablerIcons.ttf` is the unmodified outline webfont from +`@tabler/icons-webfont@3.46.0`, matching buzz-app's Tabler dependency version. +Source: https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@3.46.0/dist/fonts/tabler-icons.ttf +The upstream MIT license is bundled in `TablerIcons-LICENSE.txt`. + +`lib/shared/theme/buzz_icons.dart` maps the existing mobile semantic names to +Tabler glyphs using the package's `dist/tabler-icons.css` codepoints. Native +UIKit controls retain SF Symbols. Lucide's 300/500 navigation weight variants +both map to Tabler's standard outline; selection still uses the existing color +and label treatment. diff --git a/mobile/assets/fonts/TablerIcons-LICENSE.txt b/mobile/assets/fonts/TablerIcons-LICENSE.txt new file mode 100644 index 0000000000..3e82379dab --- /dev/null +++ b/mobile/assets/fonts/TablerIcons-LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2026 Paweł Kuna + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/mobile/assets/fonts/TablerIcons.ttf b/mobile/assets/fonts/TablerIcons.ttf new file mode 100644 index 0000000000..85881c7046 Binary files /dev/null and b/mobile/assets/fonts/TablerIcons.ttf differ diff --git a/mobile/lib/features/activity/activity_page.dart b/mobile/lib/features/activity/activity_page.dart index 397ccc57fd..d38ac3e195 100644 --- a/mobile/lib/features/activity/activity_page.dart +++ b/mobile/lib/features/activity/activity_page.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/identity_names/identity_names_provider.dart'; import '../../shared/mentions/agent_identity_provider.dart'; diff --git a/mobile/lib/features/activity/activity_page/header_actions.dart b/mobile/lib/features/activity/activity_page/header_actions.dart index 0e40dd6c81..42132b56d1 100644 --- a/mobile/lib/features/activity/activity_page/header_actions.dart +++ b/mobile/lib/features/activity/activity_page/header_actions.dart @@ -89,7 +89,7 @@ class _FilterMenuButton extends StatelessWidget { width: Grid.sm, child: entry.key == filter ? Icon( - LucideIcons.check, + BuzzIcons.check, size: 16, color: context.colors.primary, ) @@ -128,7 +128,7 @@ class _FilterMenuButton extends StatelessWidget { ), const SizedBox(width: Grid.quarter), Icon( - LucideIcons.chevronDown, + BuzzIcons.chevronDown, size: 16, color: navigationPrimaryForeground(context), ), @@ -168,7 +168,7 @@ class _InboxOptionsButton extends StatelessWidget { width: Grid.xl, height: Grid.xl, ), - icon: const Icon(LucideIcons.ellipsis, size: 20), + icon: const Icon(BuzzIcons.ellipsis, size: 20), onPressed: () async { final selected = await showAnchoredPopover( context: buttonContext, @@ -185,7 +185,7 @@ class _InboxOptionsButton extends StatelessWidget { ), if (unreadOnly) Icon( - LucideIcons.check, + BuzzIcons.check, size: 16, color: context.colors.primary, ), diff --git a/mobile/lib/features/activity/activity_page/inbox_row.dart b/mobile/lib/features/activity/activity_page/inbox_row.dart index ede51c71c1..a66b2d098e 100644 --- a/mobile/lib/features/activity/activity_page/inbox_row.dart +++ b/mobile/lib/features/activity/activity_page/inbox_row.dart @@ -178,7 +178,7 @@ class _InboxRow extends HookConsumerWidget { key: ValueKey('inbox-swipe-read-${item.id}'), color: actionColor, foregroundColor: contrastForeground(actionColor), - icon: isDone ? LucideIcons.mail : LucideIcons.mailOpen, + icon: isDone ? BuzzIcons.mail : BuzzIcons.mailOpen, label: isDone ? 'Mark unread' : 'Mark as read', onTap: toggleReadState, ), @@ -386,9 +386,7 @@ class _InboxRow extends HookConsumerWidget { child: SheetActionSection( children: [ ListTile( - leading: Icon( - isDone ? LucideIcons.mail : LucideIcons.mailOpen, - ), + leading: Icon(isDone ? BuzzIcons.mail : BuzzIcons.mailOpen), title: Text(isDone ? 'Mark unread' : 'Mark as read'), onTap: () { Navigator.of(sheetContext).pop(); @@ -396,7 +394,7 @@ class _InboxRow extends HookConsumerWidget { }, ), ListTile( - leading: const Icon(LucideIcons.externalLink), + leading: const Icon(BuzzIcons.externalLink), title: const Text('Open conversation'), onTap: () { Navigator.of(sheetContext).pop(); diff --git a/mobile/lib/features/activity/activity_page/lists.dart b/mobile/lib/features/activity/activity_page/lists.dart index f867cc64ab..0097b19a37 100644 --- a/mobile/lib/features/activity/activity_page/lists.dart +++ b/mobile/lib/features/activity/activity_page/lists.dart @@ -31,7 +31,7 @@ class _RemindersList extends ConsumerWidget { } if (reminders.isEmpty) { return const _EmptySurface( - icon: LucideIcons.clock, + icon: BuzzIcons.clock, message: 'No reminders', detail: 'Reminders you set will show up here.', ); @@ -53,7 +53,7 @@ class _RemindersList extends ConsumerWidget { return ListTile( key: ValueKey('reminder-row-${reminder.id}'), leading: Icon( - due ? LucideIcons.bellRing : LucideIcons.clock, + due ? BuzzIcons.bellRing : BuzzIcons.clock, size: 20, color: due ? context.colors.primary @@ -99,7 +99,7 @@ class _DraftsList extends ConsumerWidget { final names = ref.watch(identityNameSourcesProvider); if (drafts.isEmpty) { return const _EmptySurface( - icon: LucideIcons.filePen, + icon: BuzzIcons.filePen, message: 'No drafts', detail: 'Unsent messages you start composing will show up here.', ); @@ -124,7 +124,7 @@ class _DraftsList extends ConsumerWidget { return ListTile( key: ValueKey('draft-row-${draft.key}'), leading: Icon( - LucideIcons.filePen, + BuzzIcons.filePen, size: 20, color: context.colors.onSurfaceVariant, ), @@ -133,7 +133,7 @@ class _DraftsList extends ConsumerWidget { draft.threadHeadId != null ? 'Thread in $destination' : destination, ), trailing: IconButton( - icon: const Icon(LucideIcons.trash2, size: 18), + icon: const Icon(BuzzIcons.trash2, size: 18), tooltip: 'Delete draft', onPressed: () => onDelete(draft), ), diff --git a/mobile/lib/features/activity/activity_page/status_views.dart b/mobile/lib/features/activity/activity_page/status_views.dart index ec7e969034..4e73ea6361 100644 --- a/mobile/lib/features/activity/activity_page/status_views.dart +++ b/mobile/lib/features/activity/activity_page/status_views.dart @@ -118,27 +118,24 @@ class _EmptyFilterState extends StatelessWidget { Widget build(BuildContext context) { if (unreadOnly) { return const _EmptySurface( - icon: LucideIcons.mailOpen, + icon: BuzzIcons.mailOpen, message: 'No unread messages', detail: 'Turn off the unread filter to see read messages.', ); } final (icon, message) = switch (filter) { - InboxFilter.mention => (LucideIcons.atSign, 'No mentions yet'), - InboxFilter.thread => ( - LucideIcons.messageSquare, - 'No thread replies yet', - ), + InboxFilter.mention => (BuzzIcons.atSign, 'No mentions yet'), + InboxFilter.thread => (BuzzIcons.messageSquare, 'No thread replies yet'), InboxFilter.needsAction => ( - LucideIcons.circleAlert, + BuzzIcons.circleAlert, 'Nothing needs your action', ), InboxFilter.activity => ( - LucideIcons.activity, + BuzzIcons.activity, 'No recent channel activity', ), - InboxFilter.agentActivity => (LucideIcons.bot, 'No agent updates'), - _ => (LucideIcons.bell, 'No activity yet'), + InboxFilter.agentActivity => (BuzzIcons.bot, 'No agent updates'), + _ => (BuzzIcons.bell, 'No activity yet'), }; return _EmptySurface(icon: icon, message: message); } @@ -156,7 +153,7 @@ class _ErrorView extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.triangleAlert, + BuzzIcons.triangleAlert, size: Grid.lg, color: context.colors.error, ), @@ -170,7 +167,7 @@ class _ErrorView extends StatelessWidget { const SizedBox(height: Grid.xs), FilledButton.icon( onPressed: () => unawaited(onRetry()), - icon: const Icon(LucideIcons.refreshCcw, size: 16), + icon: const Icon(BuzzIcons.refreshCcw, size: 16), label: const Text('Retry'), ), ], diff --git a/mobile/lib/features/channels/add_members_sheet.dart b/mobile/lib/features/channels/add_members_sheet.dart index 7aabf152d5..47bc804aec 100644 --- a/mobile/lib/features/channels/add_members_sheet.dart +++ b/mobile/lib/features/channels/add_members_sheet.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/app_list_card_item.dart'; @@ -155,7 +155,7 @@ class AddChannelMembersSheet extends HookConsumerWidget { onChanged: (value) => query.value = value, decoration: const InputDecoration( hintText: 'Search for people or agents', - prefixIcon: Icon(LucideIcons.search), + prefixIcon: Icon(BuzzIcons.search), ), ), if (selectedUsers.value.isNotEmpty) ...[ @@ -234,8 +234,8 @@ class AddChannelMembersSheet extends HookConsumerWidget { ), trailing: Icon( selected - ? LucideIcons.circleCheck - : LucideIcons.plus, + ? BuzzIcons.circleCheck + : BuzzIcons.plus, color: selected ? context.colors.primary : context.colors.onSurfaceVariant, diff --git a/mobile/lib/features/channels/agent_activity/agent_activity_sheet.dart b/mobile/lib/features/channels/agent_activity/agent_activity_sheet.dart index 9409dd467d..bceb6aec8e 100644 --- a/mobile/lib/features/channels/agent_activity/agent_activity_sheet.dart +++ b/mobile/lib/features/channels/agent_activity/agent_activity_sheet.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../../shared/theme/theme.dart'; import '../../../shared/widgets/buzz_loading_indicator.dart'; @@ -84,7 +84,7 @@ class AgentActivitySheet extends HookConsumerWidget { Row( children: [ Icon( - LucideIcons.bot, + BuzzIcons.bot, size: 18, color: context.colors.onSurface, ), @@ -157,7 +157,7 @@ class _EmptyState extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Icon(LucideIcons.circleX, size: 24, color: context.colors.error), + Icon(BuzzIcons.circleX, size: 24, color: context.colors.error), const SizedBox(height: Grid.xxs), Text( 'Error: ${errorMessage ?? 'Unknown error'}', diff --git a/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart b/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart index b2f515a888..68339c9180 100644 --- a/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart +++ b/mobile/lib/features/channels/agent_activity/transcript_item_widget.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gpt_markdown/gpt_markdown.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../../shared/theme/theme.dart'; import 'observer_models.dart'; @@ -116,7 +116,7 @@ class _ThoughtItemWidget extends HookWidget { Row( children: [ Icon( - LucideIcons.brain, + BuzzIcons.brain, size: 14, color: context.colors.onSurfaceVariant, ), @@ -133,8 +133,8 @@ class _ThoughtItemWidget extends HookWidget { ), Icon( expanded.value - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, + ? BuzzIcons.chevronUp + : BuzzIcons.chevronDown, size: 14, color: context.colors.onSurfaceVariant, ), @@ -214,7 +214,7 @@ class _MetadataItemWidget extends HookWidget { Row( children: [ Icon( - LucideIcons.fileText, + BuzzIcons.fileText, size: 14, color: context.colors.onSurfaceVariant, ), @@ -231,8 +231,8 @@ class _MetadataItemWidget extends HookWidget { ), Icon( expanded.value - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, + ? BuzzIcons.chevronUp + : BuzzIcons.chevronDown, size: 14, color: context.colors.onSurfaceVariant, ), @@ -310,7 +310,7 @@ class _ToolItemWidget extends HookWidget { // Header: tool name + status badge Row( children: [ - Icon(LucideIcons.wrench, size: 14, color: statusColor), + Icon(BuzzIcons.wrench, size: 14, color: statusColor), const SizedBox(width: Grid.half), Expanded( child: Text( @@ -363,8 +363,8 @@ class _ToolItemWidget extends HookWidget { const SizedBox(width: Grid.half), Icon( argsExpanded.value - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, + ? BuzzIcons.chevronUp + : BuzzIcons.chevronDown, size: 12, color: context.colors.onSurfaceVariant, ), @@ -394,8 +394,8 @@ class _ToolItemWidget extends HookWidget { const SizedBox(width: Grid.half), Icon( resultExpanded.value - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, + ? BuzzIcons.chevronUp + : BuzzIcons.chevronDown, size: 12, color: item.isError ? context.colors.error @@ -427,15 +427,15 @@ class _ToolItemWidget extends HookWidget { BuildContext context, ) { if (isError || status == ToolStatus.failed) { - return (context.colors.error, 'Error', LucideIcons.circleX); + return (context.colors.error, 'Error', BuzzIcons.circleX); } if (status == ToolStatus.completed) { - return (context.appColors.success, 'Done', LucideIcons.circleCheck); + return (context.appColors.success, 'Done', BuzzIcons.circleCheck); } if (status == ToolStatus.pending) { - return (context.colors.onSurfaceVariant, 'Pending', LucideIcons.circleDot); + return (context.colors.onSurfaceVariant, 'Pending', BuzzIcons.circleDot); } - return (context.appColors.warning, 'Running', LucideIcons.clock3); + return (context.appColors.warning, 'Running', BuzzIcons.clock3); } String _formatToolName(String toolName) { diff --git a/mobile/lib/features/channels/channel_actions_sheet.dart b/mobile/lib/features/channels/channel_actions_sheet.dart index 1405c148c6..fb687cc092 100644 --- a/mobile/lib/features/channels/channel_actions_sheet.dart +++ b/mobile/lib/features/channels/channel_actions_sheet.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/clipboard_utils.dart'; import '../../shared/identity_names/identity_names_provider.dart'; @@ -20,7 +20,7 @@ import '../../shared/widgets/buzz_loading_indicator.dart'; import '../../shared/widgets/frosted_app_bar.dart'; import '../../shared/widgets/frosted_scaffold.dart'; import '../../shared/widgets/ios_glass_navigation_button.dart'; -import '../../shared/widgets/lucide_star_icon.dart'; +import '../../shared/widgets/tabler_star_icon.dart'; import '../../shared/widgets/modal_presentation.dart'; import 'channel.dart'; import 'add_members_sheet.dart'; @@ -184,7 +184,7 @@ class ChannelActionsSheet extends HookConsumerWidget { children: [ if (!channel.isDm) ListTile( - leading: const Icon(LucideIcons.folderInput), + leading: const Icon(BuzzIcons.folderInput), title: const Text('Move to section…'), onTap: () async { final pageContext = Navigator.of( @@ -201,9 +201,7 @@ class ChannelActionsSheet extends HookConsumerWidget { }, ), ListTile( - leading: Icon( - isMuted ? LucideIcons.bell : LucideIcons.bellOff, - ), + leading: Icon(isMuted ? BuzzIcons.bell : BuzzIcons.bellOff), title: Text(isMuted ? 'Unmute channel' : 'Mute channel'), onTap: () { close(); @@ -215,7 +213,7 @@ class ChannelActionsSheet extends HookConsumerWidget { ), if (!channel.isDm) ListTile( - leading: const Icon(LucideIcons.settings), + leading: const Icon(BuzzIcons.settings), title: const Text('Manage channel'), onTap: () async { final shouldClose = @@ -248,7 +246,7 @@ class ChannelActionsSheet extends HookConsumerWidget { SheetActionSection( children: [ ListTile( - leading: const Icon(LucideIcons.copy), + leading: const Icon(BuzzIcons.copy), title: const Text('Copy channel name'), onTap: () { close(); @@ -260,7 +258,7 @@ class ChannelActionsSheet extends HookConsumerWidget { }, ), ListTile( - leading: const Icon(LucideIcons.hash), + leading: const Icon(BuzzIcons.hash), title: const Text('Copy channel ID'), onTap: () { close(); @@ -278,7 +276,7 @@ class ChannelActionsSheet extends HookConsumerWidget { children: [ if (channel.isMember && !channel.isArchived) _ActionTile( - icon: LucideIcons.logOut, + icon: BuzzIcons.logOut, label: 'Leave channel', destructive: true, onTap: () => _confirmAndRun( @@ -305,13 +303,13 @@ class ChannelActionsSheet extends HookConsumerWidget { else if (lifecycleCapabilitiesUnavailable) const ListTile( enabled: false, - leading: Icon(LucideIcons.triangleAlert), + leading: Icon(BuzzIcons.triangleAlert), title: Text('Channel actions unavailable'), ) else ...[ if (canArchive) _ActionTile( - icon: LucideIcons.archive, + icon: BuzzIcons.archive, label: 'Archive channel', onTap: () => _confirmAndRun( context, @@ -326,7 +324,7 @@ class ChannelActionsSheet extends HookConsumerWidget { ), if (canUnarchive) _ActionTile( - icon: LucideIcons.archiveRestore, + icon: BuzzIcons.archiveRestore, label: 'Unarchive channel', onTap: () => _confirmAndRun( context, @@ -341,7 +339,7 @@ class ChannelActionsSheet extends HookConsumerWidget { ), if (canDelete) _ActionTile( - icon: LucideIcons.trash2, + icon: BuzzIcons.trash2, label: 'Delete channel', destructive: true, onTap: () => _confirmAndRun( @@ -385,7 +383,11 @@ class _ChannelQuickActionsRow extends StatelessWidget { children: [ Expanded( child: _ChannelQuickAction( - icon: isStarred ? LucideIcons.starOff : LucideIcons.star, + icon: BuzzIcons.star, + iconWidget: TablerStarIcon( + color: context.colors.onSurface, + filled: isStarred, + ), label: isStarred ? 'Unstar' : 'Star', onTap: onToggleStar, ), @@ -393,7 +395,7 @@ class _ChannelQuickActionsRow extends StatelessWidget { const SizedBox(width: Grid.twelve), Expanded( child: _ChannelQuickAction( - icon: isUnread ? LucideIcons.checkCheck : LucideIcons.circleDot, + icon: isUnread ? BuzzIcons.checkCheck : BuzzIcons.circleDot, label: isUnread ? 'Mark Read' : 'Mark Unread', onTap: onToggleRead, ), @@ -405,11 +407,13 @@ class _ChannelQuickActionsRow extends StatelessWidget { class _ChannelQuickAction extends StatelessWidget { const _ChannelQuickAction({ required this.icon, + this.iconWidget, required this.label, required this.onTap, }); final IconData icon; + final Widget? iconWidget; final String label; final VoidCallback onTap; @@ -433,7 +437,8 @@ class _ChannelQuickAction extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(icon, size: 22, color: context.colors.onSurface), + iconWidget ?? + Icon(icon, size: 22, color: context.colors.onSurface), const SizedBox(height: Grid.xxs), Text( label, @@ -545,11 +550,11 @@ Future _showMoveSectionSheet( children: [ for (final section in sections) ListTile( - leading: const Icon(LucideIcons.folder), + leading: const Icon(BuzzIcons.folder), title: Text(section.name), trailing: sectionId == section.id ? Icon( - LucideIcons.check, + BuzzIcons.check, color: sheetContext.colors.primary, ) : null, @@ -561,7 +566,7 @@ Future _showMoveSectionSheet( }, ), ListTile( - leading: const Icon(LucideIcons.folderPlus), + leading: const Icon(BuzzIcons.folderPlus), title: const Text('New section…'), onTap: () async { Navigator.of(sheetContext).pop(); @@ -582,7 +587,7 @@ Future _showMoveSectionSheet( ), if (sectionId != null) ListTile( - leading: const Icon(LucideIcons.folderMinus), + leading: const Icon(BuzzIcons.folderMinus), title: const Text('Remove from section'), onTap: () { Navigator.of(sheetContext).pop(); diff --git a/mobile/lib/features/channels/channel_detail_page.dart b/mobile/lib/features/channels/channel_detail_page.dart index b2be7abea7..5b002cee29 100644 --- a/mobile/lib/features/channels/channel_detail_page.dart +++ b/mobile/lib/features/channels/channel_detail_page.dart @@ -8,7 +8,7 @@ import 'package:flutter/rendering.dart' show ScrollDirection; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import '../../shared/emoji/emoji_burst.dart'; diff --git a/mobile/lib/features/channels/channel_detail_page/app_bar.dart b/mobile/lib/features/channels/channel_detail_page/app_bar.dart index 752b43ff2d..22cbcf82fc 100644 --- a/mobile/lib/features/channels/channel_detail_page/app_bar.dart +++ b/mobile/lib/features/channels/channel_detail_page/app_bar.dart @@ -56,7 +56,7 @@ class _ConversationAppBarTitle extends StatelessWidget { children: [ if (!channel.isDm && channel.visibility == 'private') ...[ Icon( - LucideIcons.lock, + BuzzIcons.lock, size: 14, color: context.colors.onSurfaceVariant, semanticLabel: 'Private channel', diff --git a/mobile/lib/features/channels/channel_detail_page/banners.dart b/mobile/lib/features/channels/channel_detail_page/banners.dart index a88ea16538..d1fdf3f37f 100644 --- a/mobile/lib/features/channels/channel_detail_page/banners.dart +++ b/mobile/lib/features/channels/channel_detail_page/banners.dart @@ -45,7 +45,7 @@ class _HeaderEphemeralBadge extends StatelessWidget { return Tooltip( message: display.tooltipLabel, child: Icon( - LucideIcons.clockFading, + BuzzIcons.clockFading, key: const Key('chat-ephemeral-badge'), size: 16, color: context.colors.onSurfaceVariant, diff --git a/mobile/lib/features/channels/channel_detail_page/huddle_call_avatar.dart b/mobile/lib/features/channels/channel_detail_page/huddle_call_avatar.dart index eca5f97865..57575c68de 100644 --- a/mobile/lib/features/channels/channel_detail_page/huddle_call_avatar.dart +++ b/mobile/lib/features/channels/channel_detail_page/huddle_call_avatar.dart @@ -246,7 +246,7 @@ class _HuddleCallAvatar extends HookConsumerWidget { backgroundColor: context.colors.primaryContainer, fallback: Icon( - LucideIcons.userRound, + BuzzIcons.userRound, size: fallbackIconSize, color: context.colors.onPrimaryContainer, ), diff --git a/mobile/lib/features/channels/channel_detail_page/huddle_call_controls.dart b/mobile/lib/features/channels/channel_detail_page/huddle_call_controls.dart index f993a6c422..84dde64ffe 100644 --- a/mobile/lib/features/channels/channel_detail_page/huddle_call_controls.dart +++ b/mobile/lib/features/channels/channel_detail_page/huddle_call_controls.dart @@ -26,7 +26,7 @@ class _HuddleCallControls extends StatelessWidget { _HuddleRoundControl( key: const ValueKey('huddle-speaker-toggle'), tooltip: isSpeakerEnabled ? 'Use earpiece' : 'Use speaker', - icon: LucideIcons.volume2, + icon: BuzzIcons.volume2, foregroundColor: isSpeakerEnabled ? context.colors.onPrimary : context.colors.onSurface, @@ -42,7 +42,7 @@ class _HuddleCallControls extends StatelessWidget { _HuddleRoundControl( key: const ValueKey('huddle-mute-toggle'), tooltip: isMuted ? 'Unmute' : 'Mute', - icon: isMuted ? LucideIcons.micOff : LucideIcons.mic, + icon: isMuted ? BuzzIcons.micOff : BuzzIcons.mic, foregroundColor: isMuted ? context.colors.onSurface : context.colors.onPrimary, @@ -58,7 +58,7 @@ class _HuddleCallControls extends StatelessWidget { _HuddleRoundControl( key: const ValueKey('huddle-emoji-reactions'), tooltip: 'Emoji reactions', - icon: LucideIcons.smilePlus, + icon: BuzzIcons.smilePlus, foregroundColor: context.colors.onSurface, backgroundColor: context.colors.surfaceContainerHighest, dimension: 80, diff --git a/mobile/lib/features/channels/channel_detail_page/huddle_call_participants.dart b/mobile/lib/features/channels/channel_detail_page/huddle_call_participants.dart index a4d2ac02f4..30399d6b59 100644 --- a/mobile/lib/features/channels/channel_detail_page/huddle_call_participants.dart +++ b/mobile/lib/features/channels/channel_detail_page/huddle_call_participants.dart @@ -47,7 +47,7 @@ class _HuddleCallParticipants extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.triangleAlert, + BuzzIcons.triangleAlert, size: 32, color: context.colors.error, ), diff --git a/mobile/lib/features/channels/channel_detail_page/huddle_drawer.dart b/mobile/lib/features/channels/channel_detail_page/huddle_drawer.dart index 6c031c6709..5bb858f5ad 100644 --- a/mobile/lib/features/channels/channel_detail_page/huddle_drawer.dart +++ b/mobile/lib/features/channels/channel_detail_page/huddle_drawer.dart @@ -215,7 +215,7 @@ class _MobileHuddleDrawer extends ConsumerWidget { key: const ValueKey('huddle-drawer-expand'), tooltip: 'Open Huddle', showTooltip: false, - icon: LucideIcons.chevronUp, + icon: BuzzIcons.chevronUp, foregroundColor: foreground, backgroundColor: controlSurface, useHapticFeedback: true, @@ -228,7 +228,7 @@ class _MobileHuddleDrawer extends ConsumerWidget { ? 'Use earpiece' : 'Use speaker', showTooltip: false, - icon: LucideIcons.volume2, + icon: BuzzIcons.volume2, foregroundColor: session.isSpeakerEnabled ? drawerSurface : foreground, @@ -249,8 +249,8 @@ class _MobileHuddleDrawer extends ConsumerWidget { tooltip: session.isMuted ? 'Unmute' : 'Mute', showTooltip: false, icon: session.isMuted - ? LucideIcons.micOff - : LucideIcons.mic, + ? BuzzIcons.micOff + : BuzzIcons.mic, foregroundColor: session.isMuted ? foreground : drawerSurface, @@ -269,7 +269,7 @@ class _MobileHuddleDrawer extends ConsumerWidget { key: const ValueKey('huddle-drawer-leave'), tooltip: 'Leave Huddle', showTooltip: false, - icon: LucideIcons.phoneOff, + icon: BuzzIcons.phoneOff, foregroundColor: context.colors.error, backgroundColor: controlSurface, useHapticFeedback: true, diff --git a/mobile/lib/features/channels/channel_detail_page/huddle_participant_overlay.dart b/mobile/lib/features/channels/channel_detail_page/huddle_participant_overlay.dart index c9f13b158e..212e5933b2 100644 --- a/mobile/lib/features/channels/channel_detail_page/huddle_participant_overlay.dart +++ b/mobile/lib/features/channels/channel_detail_page/huddle_participant_overlay.dart @@ -214,7 +214,7 @@ class _HuddleParticipantSpotlight extends ConsumerWidget { radius: _huddleParticipantSpotlightRadius, backgroundColor: context.colors.primaryContainer, fallback: Icon( - LucideIcons.userRound, + BuzzIcons.userRound, size: 56, color: context.colors.onPrimaryContainer, ), @@ -358,7 +358,7 @@ class _HuddleParticipantRoster extends ConsumerWidget { backgroundColor: context.colors.primaryContainer, fallback: Icon( - LucideIcons.userRound, + BuzzIcons.userRound, size: 22, color: context.colors.onPrimaryContainer, ), diff --git a/mobile/lib/features/channels/channel_detail_page/huddle_sheet.dart b/mobile/lib/features/channels/channel_detail_page/huddle_sheet.dart index 6a5159bb69..201b6e0b3d 100644 --- a/mobile/lib/features/channels/channel_detail_page/huddle_sheet.dart +++ b/mobile/lib/features/channels/channel_detail_page/huddle_sheet.dart @@ -186,7 +186,7 @@ class _HuddleButton extends ConsumerWidget { color: context.colors.primary, onPressed: action.onPressed, tooltip: action.label, - icon: const Icon(LucideIcons.headphones, size: 22), + icon: const Icon(BuzzIcons.headphones, size: 22), ); } } @@ -345,11 +345,7 @@ class _HuddleJoinSurface extends ConsumerWidget { ), child: Row( children: [ - Icon( - LucideIcons.headphones, - size: 20, - color: context.colors.primary, - ), + Icon(BuzzIcons.headphones, size: 20, color: context.colors.primary), const SizedBox(width: Grid.xxs), Expanded( child: Column( @@ -646,7 +642,7 @@ class _MobileHuddleCallPage extends ConsumerWidget { final (retryTooltip, retryIcon, onRetry) = switch (true) { _ when unavailable => ( 'Start a new Huddle', - LucideIcons.headphones, + BuzzIcons.headphones, () => unawaited( _startReplacementHuddle( context: context, @@ -657,12 +653,12 @@ class _MobileHuddleCallPage extends ConsumerWidget { ), _ when needsMicrophoneSettings => ( 'Open Settings', - LucideIcons.settings, + BuzzIcons.settings, () => unawaited(sessionController.openMicrophoneSettings()), ), _ => ( 'Try again', - LucideIcons.refreshCw, + BuzzIcons.refreshCw, () => unawaited( lifecycleController.join( parentChannelId: invite.parentChannelId, @@ -833,13 +829,13 @@ class _HuddleCallHeader extends StatelessWidget { unawaited(HapticFeedback.selectionClick()); onMinimize(); }, - icon: const Icon(LucideIcons.chevronDown, size: 32), + icon: const Icon(BuzzIcons.chevronDown, size: 32), ), const Spacer(), _HuddleRoundControl( key: const ValueKey('huddle-leave'), tooltip: 'Leave Huddle', - icon: LucideIcons.phoneOff, + icon: BuzzIcons.phoneOff, foregroundColor: context.colors.error, backgroundColor: context.colors.surfaceContainerHighest, useHapticFeedback: true, diff --git a/mobile/lib/features/channels/channel_detail_page/message_bubble.dart b/mobile/lib/features/channels/channel_detail_page/message_bubble.dart index 39566cc706..41af87571e 100644 --- a/mobile/lib/features/channels/channel_detail_page/message_bubble.dart +++ b/mobile/lib/features/channels/channel_detail_page/message_bubble.dart @@ -395,8 +395,8 @@ class _UserAvatar extends StatelessWidget { } IconData channelIcon(Channel channel) { - if (channel.isDm) return LucideIcons.messagesSquare; - if (channel.isPrivate) return LucideIcons.lock; - if (channel.isForum) return LucideIcons.messageSquareText; - return LucideIcons.hash; + if (channel.isDm) return BuzzIcons.messagesSquare; + if (channel.isPrivate) return BuzzIcons.lock; + if (channel.isForum) return BuzzIcons.messageSquareText; + return BuzzIcons.hash; } diff --git a/mobile/lib/features/channels/channel_detail_page/message_list.dart b/mobile/lib/features/channels/channel_detail_page/message_list.dart index 00d386310a..1a2c3c8211 100644 --- a/mobile/lib/features/channels/channel_detail_page/message_list.dart +++ b/mobile/lib/features/channels/channel_detail_page/message_list.dart @@ -679,7 +679,7 @@ class _MessageList extends HookConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.messageSquare, + BuzzIcons.messageSquare, size: Grid.xl, color: context.colors.onSurfaceVariant, ), @@ -914,7 +914,7 @@ class _MessageList extends HookConsumerWidget { backgroundColor: context.colors.primaryContainer, foregroundColor: context.colors.onPrimaryContainer, ), - icon: const Icon(LucideIcons.chevronUp, size: 20), + icon: const Icon(BuzzIcons.chevronUp, size: 20), ), ), ) diff --git a/mobile/lib/features/channels/channel_detail_page/system_rows.dart b/mobile/lib/features/channels/channel_detail_page/system_rows.dart index be7f00081f..358d064d2e 100644 --- a/mobile/lib/features/channels/channel_detail_page/system_rows.dart +++ b/mobile/lib/features/channels/channel_detail_page/system_rows.dart @@ -560,7 +560,7 @@ Widget _systemEventAvatar( shape: BoxShape.circle, ), child: Icon( - LucideIcons.arrowLeftRight, + BuzzIcons.arrowLeftRight, size: 12, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/channel_details_page.dart b/mobile/lib/features/channels/channel_details_page.dart index 194f114b9f..5bec76d1f5 100644 --- a/mobile/lib/features/channels/channel_details_page.dart +++ b/mobile/lib/features/channels/channel_details_page.dart @@ -384,7 +384,7 @@ class ChannelDetailsPage extends HookConsumerWidget { child: BuzzActionTile( key: const ValueKey('channel-details-star-action'), icon: null, - iconWidget: LucideStarIcon( + iconWidget: TablerStarIcon( filled: isStarred, color: isStarred ? context.colors.primary @@ -398,7 +398,7 @@ class ChannelDetailsPage extends HookConsumerWidget { Expanded( child: BuzzActionTile( key: const ValueKey('channel-details-mute-action'), - icon: isMuted ? LucideIcons.bell : LucideIcons.bellOff, + icon: isMuted ? BuzzIcons.bell : BuzzIcons.bellOff, iconColor: isMuted ? context.colors.primary : null, label: isMuted ? 'Unmute' : 'Mute', onTap: toggleMute, @@ -409,7 +409,7 @@ class ChannelDetailsPage extends HookConsumerWidget { Expanded( child: BuzzActionTile( key: const ValueKey('channel-details-edit-action'), - icon: LucideIcons.pencil, + icon: BuzzIcons.pencil, label: 'Edit', isEnabled: canEdit, onTap: openManageChannel, @@ -438,7 +438,7 @@ class ChannelDetailsPage extends HookConsumerWidget { shape: BoxShape.circle, ), child: Icon( - LucideIcons.plus, + BuzzIcons.plus, color: context.colors.onSurfaceVariant, ), ), @@ -452,7 +452,7 @@ class ChannelDetailsPage extends HookConsumerWidget { ), if (membersAsync.isLoading && members.isEmpty) const AppListRow( - icon: LucideIcons.loaderCircle, + icon: BuzzIcons.loaderCircle, title: 'Loading members…', trailing: BuzzLoadingIndicator( size: 20, @@ -461,7 +461,7 @@ class ChannelDetailsPage extends HookConsumerWidget { ) else if (membersAsync.hasError && members.isEmpty) const AppListRow( - icon: LucideIcons.triangleAlert, + icon: BuzzIcons.triangleAlert, title: 'Members unavailable', ) else ...[ @@ -498,7 +498,7 @@ class ChannelDetailsPage extends HookConsumerWidget { verticalPadding: _channelDetailsSectionPadding, children: [ AppListRow( - icon: LucideIcons.folderInput, + icon: BuzzIcons.folderInput, title: 'Move to section…', trailing: const _ChannelDetailsChevron(), onTap: () async { @@ -511,7 +511,7 @@ class ChannelDetailsPage extends HookConsumerWidget { }, ), AppListRow( - icon: LucideIcons.copy, + icon: BuzzIcons.copy, title: 'Copy channel name', onTap: () { copyToClipboard( @@ -522,7 +522,7 @@ class ChannelDetailsPage extends HookConsumerWidget { }, ), AppListRow( - icon: LucideIcons.hash, + icon: BuzzIcons.hash, title: 'Copy channel ID', onTap: () { copyToClipboard( @@ -547,7 +547,7 @@ class ChannelDetailsPage extends HookConsumerWidget { children: [ if (canJoin) AppListRow( - icon: LucideIcons.logIn, + icon: BuzzIcons.logIn, title: isJoining.value ? 'Joining channel…' : 'Join channel', @@ -555,7 +555,7 @@ class ChannelDetailsPage extends HookConsumerWidget { ), if (resolvedChannel.isMember && !resolvedChannel.isArchived) AppListRow( - icon: LucideIcons.logOut, + icon: BuzzIcons.logOut, title: 'Leave channel', titleColor: context.colors.error, onTap: () => _confirmAndRun( @@ -571,7 +571,7 @@ class ChannelDetailsPage extends HookConsumerWidget { ), if (lifecycleCapabilitiesLoading) const AppListRow( - icon: LucideIcons.loaderCircle, + icon: BuzzIcons.loaderCircle, title: 'Loading channel actions…', trailing: BuzzLoadingIndicator( size: 20, @@ -580,13 +580,13 @@ class ChannelDetailsPage extends HookConsumerWidget { ) else if (lifecycleCapabilitiesUnavailable) const AppListRow( - icon: LucideIcons.triangleAlert, + icon: BuzzIcons.triangleAlert, title: 'Channel actions unavailable', ) else ...[ if (canArchive) AppListRow( - icon: LucideIcons.archive, + icon: BuzzIcons.archive, title: 'Archive channel', onTap: () => _confirmAndRun( context, @@ -601,7 +601,7 @@ class ChannelDetailsPage extends HookConsumerWidget { ), if (canUnarchive) AppListRow( - icon: LucideIcons.archiveRestore, + icon: BuzzIcons.archiveRestore, title: 'Unarchive channel', onTap: () => _confirmAndRun( context, @@ -616,7 +616,7 @@ class ChannelDetailsPage extends HookConsumerWidget { ), if (canDelete) AppListRow( - icon: LucideIcons.trash2, + icon: BuzzIcons.trash2, title: 'Delete channel', titleColor: context.colors.error, onTap: () => _confirmAndRun( @@ -788,9 +788,9 @@ String _channelMemberRoleLabel(String role) { } IconData _channelDetailsIcon(Channel channel) { - if (channel.isPrivate) return LucideIcons.lock; - if (channel.isForum) return LucideIcons.messageSquareText; - return LucideIcons.hash; + if (channel.isPrivate) return BuzzIcons.lock; + if (channel.isForum) return BuzzIcons.messageSquareText; + return BuzzIcons.hash; } class _ChannelDetailsChevron extends StatelessWidget { @@ -798,7 +798,7 @@ class _ChannelDetailsChevron extends StatelessWidget { @override Widget build(BuildContext context) => Icon( - LucideIcons.chevronRight, + BuzzIcons.chevronRight, size: 18, color: context.colors.onSurfaceVariant, ); diff --git a/mobile/lib/features/channels/channel_member_profile_actions.dart b/mobile/lib/features/channels/channel_member_profile_actions.dart index b7d170a2e0..8a95df9de8 100644 --- a/mobile/lib/features/channels/channel_member_profile_actions.dart +++ b/mobile/lib/features/channels/channel_member_profile_actions.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/app_list.dart'; @@ -144,13 +144,13 @@ class ChannelMemberProfileActions extends HookConsumerWidget { if (!member.isBot) ...[ if (member.role != 'admin') AppListRow( - icon: LucideIcons.shieldCheck, + icon: BuzzIcons.shieldCheck, title: 'Make channel admin', onTap: busy.value ? null : () => perform(role: 'admin'), ), if (member.role == 'admin' || member.role == 'guest') AppListRow( - icon: LucideIcons.user, + icon: BuzzIcons.user, title: member.role == 'guest' ? 'Make member' : 'Change to member', @@ -158,7 +158,7 @@ class ChannelMemberProfileActions extends HookConsumerWidget { ), ], AppListRow( - icon: LucideIcons.userMinus, + icon: BuzzIcons.userMinus, title: 'Remove from channel', titleColor: context.colors.error, onTap: busy.value ? null : () => perform(), diff --git a/mobile/lib/features/channels/channels_page.dart b/mobile/lib/features/channels/channels_page.dart index 58c5b6d0de..e27bfe3cd1 100644 --- a/mobile/lib/features/channels/channels_page.dart +++ b/mobile/lib/features/channels/channels_page.dart @@ -9,7 +9,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter/physics.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/auth/auth.dart'; import '../../shared/community/community_icon_provider.dart'; diff --git a/mobile/lib/features/channels/channels_page/badges.dart b/mobile/lib/features/channels/channels_page/badges.dart index e7e480e11f..15c081045e 100644 --- a/mobile/lib/features/channels/channels_page/badges.dart +++ b/mobile/lib/features/channels/channels_page/badges.dart @@ -13,7 +13,7 @@ class _EphemeralBadge extends StatelessWidget { return Tooltip( message: display.tooltipLabel, child: Icon( - LucideIcons.clockFading, + BuzzIcons.clockFading, key: Key('channel-ephemeral-${channel.id}'), size: 16, color: context.colors.onSurfaceVariant, @@ -52,11 +52,7 @@ class _ErrorView extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Icon( - LucideIcons.wifiOff, - size: Grid.xl, - color: context.colors.error, - ), + Icon(BuzzIcons.wifiOff, size: Grid.xl, color: context.colors.error), const SizedBox(height: Grid.xs), Text( 'Could not load channels', @@ -75,7 +71,7 @@ class _ErrorView extends StatelessWidget { const SizedBox(height: Grid.xs), FilledButton.icon( onPressed: onRetry, - icon: const Icon(LucideIcons.refreshCw), + icon: const Icon(BuzzIcons.refreshCw), label: const Text('Retry'), ), ], diff --git a/mobile/lib/features/channels/channels_page/body.dart b/mobile/lib/features/channels/channels_page/body.dart index 046d9acdef..4ea88c1891 100644 --- a/mobile/lib/features/channels/channels_page/body.dart +++ b/mobile/lib/features/channels/channels_page/body.dart @@ -261,7 +261,7 @@ class _SliverChannelsList extends HookConsumerWidget { if (starredStreamChannels.isNotEmpty) _ChannelSection( title: 'Starred', - icon: LucideIcons.star, + icon: BuzzIcons.star, showTopDivider: false, expanded: starredExpanded.value, onToggle: () => starredExpanded.value = !starredExpanded.value, @@ -372,7 +372,7 @@ class _SliverChannelsList extends HookConsumerWidget { ), _ChannelSection( title: 'Channels', - icon: LucideIcons.hash, + icon: BuzzIcons.hash, showTopDivider: starredStreamChannels.isNotEmpty || userSections.isNotEmpty, expanded: channelsExpanded.value, @@ -388,7 +388,7 @@ class _SliverChannelsList extends HookConsumerWidget { ), _ChannelSection( title: 'DMs', - icon: LucideIcons.messagesSquare, + icon: BuzzIcons.messagesSquare, showTopDivider: true, expanded: dmsExpanded.value, onToggle: () => dmsExpanded.value = !dmsExpanded.value, diff --git a/mobile/lib/features/channels/channels_page/channel_tile.dart b/mobile/lib/features/channels/channels_page/channel_tile.dart index 9864749be5..caa05ff9f3 100644 --- a/mobile/lib/features/channels/channels_page/channel_tile.dart +++ b/mobile/lib/features/channels/channels_page/channel_tile.dart @@ -91,7 +91,7 @@ class _ChannelTile extends ConsumerWidget { if (isMuted) ...[ const SizedBox(width: Grid.xxs), Icon( - LucideIcons.bellOff, + BuzzIcons.bellOff, size: 12, color: context.colors.onSurface.withValues(alpha: 0.4), ), diff --git a/mobile/lib/features/channels/channels_page/community.dart b/mobile/lib/features/channels/channels_page/community.dart index b2ebe1f6ab..7747170f43 100644 --- a/mobile/lib/features/channels/channels_page/community.dart +++ b/mobile/lib/features/channels/channels_page/community.dart @@ -43,16 +43,16 @@ class _CommunityMenuSheet extends StatelessWidget { children: [ if (canInvite && invitePageBuilder != null) AppListRow( - icon: LucideIcons.userPlus, + icon: BuzzIcons.userPlus, title: 'Invite', - trailing: const Icon(LucideIcons.chevronRight, size: 18), + trailing: const Icon(BuzzIcons.chevronRight, size: 18), onTap: () => openPage(invitePageBuilder!), ), if (appearancePageBuilder != null) AppListRow( - icon: LucideIcons.sunMoon, + icon: BuzzIcons.sunMoon, title: 'Appearance', - trailing: const Icon(LucideIcons.chevronRight, size: 18), + trailing: const Icon(BuzzIcons.chevronRight, size: 18), onTap: () => openPage(appearancePageBuilder!), ), ], @@ -61,9 +61,9 @@ class _CommunityMenuSheet extends StatelessWidget { children: [ AppListRow( key: const Key('community-menu-switch'), - icon: LucideIcons.arrowLeftRight, + icon: BuzzIcons.arrowLeftRight, title: 'Switch Community', - trailing: const Icon(LucideIcons.chevronRight, size: 18), + trailing: const Icon(BuzzIcons.chevronRight, size: 18), onTap: openSwitcher, ), ], diff --git a/mobile/lib/features/channels/channels_page/community_switcher.dart b/mobile/lib/features/channels/channels_page/community_switcher.dart index 97214db8a8..d642aea17e 100644 --- a/mobile/lib/features/channels/channels_page/community_switcher.dart +++ b/mobile/lib/features/channels/channels_page/community_switcher.dart @@ -279,7 +279,7 @@ class _CommunitySwitcherPage extends HookConsumerWidget { IconButton( tooltip: 'Close community switcher', onPressed: () => Navigator.of(context).pop(), - icon: const Icon(LucideIcons.x), + icon: const Icon(BuzzIcons.x), ), const Spacer(), TextButton( @@ -676,7 +676,7 @@ class _CommunityGridAdd extends StatelessWidget { height: _communityGridAvatarSize, color: context.colors.primaryContainer.withValues(alpha: 0.5), child: Icon( - LucideIcons.plus, + BuzzIcons.plus, size: 32, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/channels_page/community_switcher_action.dart b/mobile/lib/features/channels/channels_page/community_switcher_action.dart index 856f0e928b..6fbadcc510 100644 --- a/mobile/lib/features/channels/channels_page/community_switcher_action.dart +++ b/mobile/lib/features/channels/channels_page/community_switcher_action.dart @@ -76,9 +76,9 @@ class _CommunityGridAction extends HookWidget { painter: _CommunityActionGlyphPainter(t, foreground), ) : isActive && t == 0 - ? Icon(LucideIcons.check, color: foreground, size: 14) + ? Icon(BuzzIcons.check, color: foreground, size: 14) : t > 0 - ? Icon(LucideIcons.trash2, color: foreground, size: 18) + ? Icon(BuzzIcons.trash2, color: foreground, size: 18) : const SizedBox.shrink(), ), ), diff --git a/mobile/lib/features/channels/channels_page/quick_actions.dart b/mobile/lib/features/channels/channels_page/quick_actions.dart index 47b24f6c37..67f86ee65c 100644 --- a/mobile/lib/features/channels/channels_page/quick_actions.dart +++ b/mobile/lib/features/channels/channels_page/quick_actions.dart @@ -210,7 +210,7 @@ class _MorphingQuickActionsButton extends HookWidget { onTap: onToggle, child: Center( child: Icon( - LucideIcons.plus, + BuzzIcons.plus, color: defaultTargetPlatform == TargetPlatform.iOS @@ -295,21 +295,21 @@ class _QuickActionsMenu extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _QuickActionItem( - icon: LucideIcons.hash, + icon: BuzzIcons.hash, title: 'Create channel', key: const Key('quick-action-create-channel-card'), onTap: () => onSelected(_QuickAction.createChannel), ), const SizedBox(height: Grid.xxs), _QuickActionItem( - icon: LucideIcons.messagesSquare, + icon: BuzzIcons.messagesSquare, title: 'New direct message', key: const Key('quick-action-new-dm-card'), onTap: () => onSelected(_QuickAction.newDm), ), const SizedBox(height: Grid.xxs), _QuickActionItem( - icon: LucideIcons.compass, + icon: BuzzIcons.compass, title: 'Browse channels', key: const Key('quick-action-browse-channels-card'), onTap: () => onSelected(_QuickAction.browseChannels), diff --git a/mobile/lib/features/channels/channels_page/sections.dart b/mobile/lib/features/channels/channels_page/sections.dart index 6e17845d74..f0ac7d58e8 100644 --- a/mobile/lib/features/channels/channels_page/sections.dart +++ b/mobile/lib/features/channels/channels_page/sections.dart @@ -139,7 +139,7 @@ class _CustomSectionHeader extends ConsumerWidget { alignment: Alignment.centerLeft, child: icon == null || icon.isEmpty ? Icon( - LucideIcons.folder, + BuzzIcons.folder, size: _kChannelIconSize, color: sectionColor, ) @@ -179,7 +179,7 @@ class _CustomSectionHeader extends ConsumerWidget { tooltip: '${section.name} options', visualDensity: VisualDensity.compact, icon: Icon( - LucideIcons.ellipsisVertical, + BuzzIcons.ellipsisVertical, size: _kChannelIconSize, color: sectionColor, ), @@ -194,7 +194,7 @@ class _CustomSectionHeader extends ConsumerWidget { value: 'rename', padding: _sectionMenuItemPadding, child: _SectionMenuItemContent( - icon: LucideIcons.pencil, + icon: BuzzIcons.pencil, label: 'Rename section', ), ), @@ -203,7 +203,7 @@ class _CustomSectionHeader extends ConsumerWidget { enabled: !isFirst, padding: _sectionMenuItemPadding, child: const _SectionMenuItemContent( - icon: LucideIcons.arrowUp, + icon: BuzzIcons.arrowUp, label: 'Move up', ), ), @@ -212,7 +212,7 @@ class _CustomSectionHeader extends ConsumerWidget { enabled: !isLast, padding: _sectionMenuItemPadding, child: const _SectionMenuItemContent( - icon: LucideIcons.arrowDown, + icon: BuzzIcons.arrowDown, label: 'Move down', ), ), @@ -221,7 +221,7 @@ class _CustomSectionHeader extends ConsumerWidget { value: 'delete', padding: _sectionMenuItemPadding, child: _SectionMenuItemContent( - icon: LucideIcons.trash2, + icon: BuzzIcons.trash2, label: 'Delete section', color: context.colors.error, ), @@ -346,7 +346,7 @@ PopupMenuItem _sortMenuItem({ children: [ Expanded(child: Text(label)), if (selected) - const Icon(LucideIcons.check, key: ValueKey('sort-selected-check')) + const Icon(BuzzIcons.check, key: ValueKey('sort-selected-check')) else const SizedBox(width: 24), ], @@ -467,7 +467,7 @@ class _EmptyState extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.messagesSquare, + BuzzIcons.messagesSquare, size: Grid.xl, color: context.colors.onSurfaceVariant, ), @@ -559,7 +559,7 @@ class _SectionHeader extends StatelessWidget { tooltip: '$label options', visualDensity: VisualDensity.compact, icon: Icon( - LucideIcons.ellipsisVertical, + BuzzIcons.ellipsisVertical, size: _kChannelIconSize, color: sectionColor, ), @@ -612,11 +612,7 @@ class _SectionChevron extends StatelessWidget { turns: expanded ? 0 : -0.25, duration: reducedMotion ? Duration.zero : _kSectionExpandDuration, curve: _kSectionExpandCurve, - child: Icon( - LucideIcons.chevronDown, - size: _kChannelIconSize, - color: color, - ), + child: Icon(BuzzIcons.chevronDown, size: _kChannelIconSize, color: color), ); } } diff --git a/mobile/lib/features/channels/channels_page/sheets.dart b/mobile/lib/features/channels/channels_page/sheets.dart index 916f91f8ab..7015c6a0ef 100644 --- a/mobile/lib/features/channels/channels_page/sheets.dart +++ b/mobile/lib/features/channels/channels_page/sheets.dart @@ -421,7 +421,7 @@ class _CreateChannelSettingMenu extends StatelessWidget { ), const SizedBox(width: Grid.half), Icon( - LucideIcons.chevronDown, + BuzzIcons.chevronDown, size: 16, color: context.colors.onSurfaceVariant, ), @@ -769,7 +769,7 @@ class _NewDirectMessageSheet extends HookConsumerWidget { overflow: TextOverflow.ellipsis, ), trailing: Icon( - LucideIcons.plus, + BuzzIcons.plus, size: 18, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/compose_bar.dart b/mobile/lib/features/channels/compose_bar.dart index 62917a25b1..c43d4057fe 100644 --- a/mobile/lib/features/channels/compose_bar.dart +++ b/mobile/lib/features/channels/compose_bar.dart @@ -13,7 +13,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image_picker/image_picker.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; diff --git a/mobile/lib/features/channels/compose_bar/attachments.dart b/mobile/lib/features/channels/compose_bar/attachments.dart index 97bd60579b..1ba99bb0eb 100644 --- a/mobile/lib/features/channels/compose_bar/attachments.dart +++ b/mobile/lib/features/channels/compose_bar/attachments.dart @@ -503,10 +503,10 @@ class _AttachmentTrigger extends StatelessWidget { ), child: Icon( switch (surface) { - _AttachmentSurface.camera => LucideIcons.camera, - _AttachmentSurface.photos => LucideIcons.images, + _AttachmentSurface.camera => BuzzIcons.camera, + _AttachmentSurface.photos => BuzzIcons.images, _AttachmentSurface.closed || - _AttachmentSurface.menu => LucideIcons.plus, + _AttachmentSurface.menu => BuzzIcons.plus, }, key: ValueKey('attachment-trigger-${surface.name}'), size: 20, @@ -540,11 +540,11 @@ class _AttachmentMenu extends StatelessWidget { @override Widget build(BuildContext context) { final items = <(IconData, String, VoidCallback)>[ - (LucideIcons.camera, 'Camera', onCamera), - (LucideIcons.images, 'Photos', onPhotos), - (LucideIcons.video, 'Video', onVideo), - (LucideIcons.mic, 'Voice note', onVoiceNote), - (LucideIcons.file, 'Files', onFiles), + (BuzzIcons.camera, 'Camera', onCamera), + (BuzzIcons.images, 'Photos', onPhotos), + (BuzzIcons.video, 'Video', onVideo), + (BuzzIcons.mic, 'Voice note', onVoiceNote), + (BuzzIcons.file, 'Files', onFiles), ]; return SizedBox( key: const ValueKey('attachment-menu'), @@ -693,7 +693,7 @@ class _AttachmentStrip extends StatelessWidget { color: Colors.black, child: Center( child: Icon( - LucideIcons.video, + BuzzIcons.video, color: Colors.white, size: 24, ), @@ -707,7 +707,7 @@ class _AttachmentStrip extends StatelessWidget { errorBuilder: (_, _, _) => ColoredBox( color: context.colors.surface, child: Icon( - LucideIcons.image, + BuzzIcons.image, color: context.colors.onSurfaceVariant, ), ), @@ -722,7 +722,7 @@ class _AttachmentStrip extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( - LucideIcons.file, + BuzzIcons.file, color: context.colors.onSurfaceVariant, ), const SizedBox(height: Grid.quarter), @@ -765,7 +765,7 @@ class _AttachmentStrip extends StatelessWidget { tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), icon: Icon( - LucideIcons.x, + BuzzIcons.x, size: 14, color: context.colors.onSurface, ), @@ -795,7 +795,7 @@ class _MemoryAttachmentImage extends HookConsumerWidget { if (data == null || data.isEmpty) { return ColoredBox( color: context.colors.surface, - child: Icon(LucideIcons.image, color: context.colors.onSurfaceVariant), + child: Icon(BuzzIcons.image, color: context.colors.onSurfaceVariant), ); } @@ -804,7 +804,7 @@ class _MemoryAttachmentImage extends HookConsumerWidget { fit: BoxFit.cover, errorBuilder: (_, _, _) => ColoredBox( color: context.colors.surface, - child: Icon(LucideIcons.image, color: context.colors.onSurfaceVariant), + child: Icon(BuzzIcons.image, color: context.colors.onSurfaceVariant), ), ); } diff --git a/mobile/lib/features/channels/compose_bar/camera_preview.dart b/mobile/lib/features/channels/compose_bar/camera_preview.dart index 32cc992a56..12e80e53ee 100644 --- a/mobile/lib/features/channels/compose_bar/camera_preview.dart +++ b/mobile/lib/features/channels/compose_bar/camera_preview.dart @@ -216,7 +216,7 @@ class _CameraPlaceholder extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ const Icon( - LucideIcons.cameraOff, + BuzzIcons.cameraOff, color: Colors.white, size: 28, ), @@ -309,7 +309,7 @@ class _CameraCloseButton extends StatelessWidget { ), foregroundColor: Colors.white, ), - icon: Icon(LucideIcons.arrowLeft, size: emphasized ? 24 : 18), + icon: Icon(BuzzIcons.arrowLeft, size: emphasized ? 24 : 18), ), ); } diff --git a/mobile/lib/features/channels/compose_bar/formatting_toolbar.dart b/mobile/lib/features/channels/compose_bar/formatting_toolbar.dart index c6dc65a8fa..4e714a5c78 100644 --- a/mobile/lib/features/channels/compose_bar/formatting_toolbar.dart +++ b/mobile/lib/features/channels/compose_bar/formatting_toolbar.dart @@ -12,27 +12,27 @@ class _FormattingToolbar extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ _FormatButton( - icon: LucideIcons.bold, + icon: BuzzIcons.bold, tooltip: 'Bold', onTap: () => onFormat('**'), ), _FormatButton( - icon: LucideIcons.italic, + icon: BuzzIcons.italic, tooltip: 'Italic', onTap: () => onFormat('_'), ), _FormatButton( - icon: LucideIcons.strikethrough, + icon: BuzzIcons.strikethrough, tooltip: 'Strikethrough', onTap: () => onFormat('~~'), ), _FormatButton( - icon: LucideIcons.code, + icon: BuzzIcons.code, tooltip: 'Code', onTap: () => onFormat('`'), ), _FormatButton( - icon: LucideIcons.squareCode, + icon: BuzzIcons.squareCode, tooltip: 'Code block', onTap: () => onFormat('```\n', '\n```'), ), diff --git a/mobile/lib/features/channels/compose_bar/layout.dart b/mobile/lib/features/channels/compose_bar/layout.dart index aff90b9936..354a0d3ce2 100644 --- a/mobile/lib/features/channels/compose_bar/layout.dart +++ b/mobile/lib/features/channels/compose_bar/layout.dart @@ -212,19 +212,19 @@ class _ComposeBarLayout extends HookWidget { key: const ValueKey('standard-actions'), children: [ _ComposeAction( - icon: LucideIcons.atSign, + icon: BuzzIcons.atSign, onTap: onMention, ), _ComposeAction( - icon: LucideIcons.hash, + icon: BuzzIcons.hash, onTap: onChannel, ), _ComposeAction( - icon: LucideIcons.smilePlus, + icon: BuzzIcons.smilePlus, onTap: onEmoji, ), _ComposeAction( - icon: LucideIcons.aLargeSmall, + icon: BuzzIcons.aLargeSmall, onTap: onOpenFormatting, ), const Spacer(), diff --git a/mobile/lib/features/channels/compose_bar/markdown_editing_controller.dart b/mobile/lib/features/channels/compose_bar/markdown_editing_controller.dart index 2862aad1f3..715a74ad52 100644 --- a/mobile/lib/features/channels/compose_bar/markdown_editing_controller.dart +++ b/mobile/lib/features/channels/compose_bar/markdown_editing_controller.dart @@ -395,20 +395,20 @@ class _MarkdownEditingController extends TextEditingController { final link = parseBuzzDeepLink(uri) ?? parseEntityDeepLink(uri); return switch (link) { ChannelDeepLink(:final channelId) => ( - LucideIcons.hash, + BuzzIcons.hash, _resolvedChannelName(channelId), 'Channel ${_resolvedChannelName(channelId)}', ), MessageDeepLink(:final channelId, :final messageId) => ( - LucideIcons.messageSquare, + BuzzIcons.messageSquare, '${_resolvedChannelName(channelId)} · ${messageId.substring(0, 8)}', 'Message ${messageId.substring(0, 8)} in channel ${_resolvedChannelName(channelId)}', ), EntityDeepLink(:final type, :final repository, :final eventId) => ( switch (type) { - 'repo' => LucideIcons.folderGit2, - 'pr' => LucideIcons.gitPullRequest, - _ => LucideIcons.circleDot, + 'repo' => BuzzIcons.folderGit2, + 'pr' => BuzzIcons.gitPullRequest, + _ => BuzzIcons.circleDot, }, type == 'repo' ? repository @@ -591,7 +591,7 @@ class _ComposerAgentMentionChip extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon( - LucideIcons.bot, + BuzzIcons.bot, size: fontSize * 0.95, color: context.colors.primary, ), diff --git a/mobile/lib/features/channels/compose_bar/photo_gallery_picker.dart b/mobile/lib/features/channels/compose_bar/photo_gallery_picker.dart index 349aa3237a..60ddbf588f 100644 --- a/mobile/lib/features/channels/compose_bar/photo_gallery_picker.dart +++ b/mobile/lib/features/channels/compose_bar/photo_gallery_picker.dart @@ -112,7 +112,7 @@ class _RecentPhotoGalleryPicker extends HookConsumerWidget { } if (recentSnapshot.hasError) { return const _PhotoGalleryMessage( - icon: LucideIcons.images, + icon: BuzzIcons.images, title: 'Recent photos aren’t available', message: 'Use All photos to choose with the system photo picker.', ); @@ -121,7 +121,7 @@ class _RecentPhotoGalleryPicker extends HookConsumerWidget { final photos = recentSnapshot.data ?? const []; if (photos.isEmpty) { return const _PhotoGalleryMessage( - icon: LucideIcons.images, + icon: BuzzIcons.images, title: 'No recent photos', message: 'Use All photos to browse your photo library.', ); @@ -179,7 +179,7 @@ class _RecentPhotoGalleryPicker extends HookConsumerWidget { : () => _runComposerAction(onBack), tooltip: 'Back to attachment options', visualDensity: VisualDensity.compact, - icon: const Icon(LucideIcons.arrowLeft, size: 20), + icon: const Icon(BuzzIcons.arrowLeft, size: 20), ), const SizedBox(width: Grid.quarter), Expanded( @@ -245,7 +245,7 @@ class _RecentPhotoGalleryPicker extends HookConsumerWidget { color: context.colors.primary, semanticLabel: 'Opening all photos', ) - : const Icon(LucideIcons.images, size: 18), + : const Icon(BuzzIcons.images, size: 18), label: Text(actionLabel), ) : FilledButton.icon( @@ -261,7 +261,7 @@ class _RecentPhotoGalleryPicker extends HookConsumerWidget { color: Colors.white, semanticLabel: 'Preparing selected photos', ) - : const Icon(LucideIcons.plus, size: 18), + : const Icon(BuzzIcons.plus, size: 18), label: Text(actionLabel), ), ), diff --git a/mobile/lib/features/channels/compose_bar/send_button.dart b/mobile/lib/features/channels/compose_bar/send_button.dart index bbe9d2aaca..113f044e5c 100644 --- a/mobile/lib/features/channels/compose_bar/send_button.dart +++ b/mobile/lib/features/channels/compose_bar/send_button.dart @@ -35,7 +35,7 @@ class _SendButton extends StatelessWidget { semanticLabel: 'Sending message', ) : Icon( - LucideIcons.arrowUp, + BuzzIcons.arrowUp, size: 18, color: context.colors.onPrimary, ), diff --git a/mobile/lib/features/channels/compose_bar/suggestions.dart b/mobile/lib/features/channels/compose_bar/suggestions.dart index 50e4c9b97f..f057881f53 100644 --- a/mobile/lib/features/channels/compose_bar/suggestions.dart +++ b/mobile/lib/features/channels/compose_bar/suggestions.dart @@ -146,11 +146,7 @@ abstract final class _MentionSuggestionInfo { return Row( children: [ if (candidate.isAgent) ...[ - Icon( - LucideIcons.bot, - size: 12, - color: context.colors.onSurfaceVariant, - ), + Icon(BuzzIcons.bot, size: 12, color: context.colors.onSurfaceVariant), const SizedBox(width: Grid.half), Text('agent', style: style), ] else if (isAdmin) @@ -231,7 +227,7 @@ class _ChannelSuggestions extends StatelessWidget { leading: SizedBox.square( dimension: 36, child: Icon( - LucideIcons.hash, + BuzzIcons.hash, size: 20, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/emoji_picker.dart b/mobile/lib/features/channels/emoji_picker.dart index 22b3ed03e0..151377e532 100644 --- a/mobile/lib/features/channels/emoji_picker.dart +++ b/mobile/lib/features/channels/emoji_picker.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/custom_emoji/custom_emoji.dart'; import '../../shared/custom_emoji/custom_emoji_provider.dart'; @@ -281,7 +281,7 @@ List<_EmojiSection> _buildSections({ _EmojiSection( id: 'frequent', label: 'Frequently used', - icon: LucideIcons.clock, + icon: BuzzIcons.clock, itemCount: recentTiles.length, itemBuilder: (context, index) => recentTiles[index], ), @@ -308,7 +308,7 @@ List<_EmojiSection> _buildSections({ _EmojiSection( id: 'custom', label: 'Custom', - icon: LucideIcons.sparkles, + icon: BuzzIcons.sparkles, itemCount: customEmoji.length, itemBuilder: (context, index) { final entry = customEmoji[index]; diff --git a/mobile/lib/features/channels/emoji_picker/category_rail.dart b/mobile/lib/features/channels/emoji_picker/category_rail.dart index e654134ec6..f217b244bd 100644 --- a/mobile/lib/features/channels/emoji_picker/category_rail.dart +++ b/mobile/lib/features/channels/emoji_picker/category_rail.dart @@ -3,15 +3,15 @@ part of '../emoji_picker.dart'; /// Rail icon for each emoji-mart category. Ids come from the dataset, so this /// map is keyed on emoji-mart's own category ids. IconData _categoryIcon(String categoryId) => switch (categoryId) { - 'people' => LucideIcons.smile, - 'nature' => LucideIcons.leaf, - 'foods' => LucideIcons.coffee, - 'activity' => LucideIcons.volleyball, - 'places' => LucideIcons.plane, - 'objects' => LucideIcons.lightbulb, - 'symbols' => LucideIcons.heart, - 'flags' => LucideIcons.flag, - _ => LucideIcons.layoutGrid, + 'people' => BuzzIcons.smile, + 'nature' => BuzzIcons.leaf, + 'foods' => BuzzIcons.coffee, + 'activity' => BuzzIcons.volleyball, + 'places' => BuzzIcons.plane, + 'objects' => BuzzIcons.lightbulb, + 'symbols' => BuzzIcons.heart, + 'flags' => BuzzIcons.flag, + _ => BuzzIcons.layoutGrid, }; /// Height of the rail. Sized to a comfortable tap target rather than to the @@ -113,7 +113,7 @@ class _SkinToneSelector extends StatelessWidget { Expanded(child: Text(tone.label)), if (index == value) Icon( - LucideIcons.check, + BuzzIcons.check, size: 18, color: context.colors.primary, ), diff --git a/mobile/lib/features/channels/emoji_picker/emoji_grid.dart b/mobile/lib/features/channels/emoji_picker/emoji_grid.dart index eb7217be02..4e1efbffe5 100644 --- a/mobile/lib/features/channels/emoji_picker/emoji_grid.dart +++ b/mobile/lib/features/channels/emoji_picker/emoji_grid.dart @@ -221,7 +221,7 @@ class _EmojiSearchResults extends StatelessWidget { Widget build(BuildContext context) { if (entries.isEmpty && customEmoji.isEmpty) { return _EmojiEmptyState( - icon: LucideIcons.searchX, + icon: BuzzIcons.searchX, message: 'No emoji found.', ); } diff --git a/mobile/lib/features/channels/emoji_picker/search_field.dart b/mobile/lib/features/channels/emoji_picker/search_field.dart index c61dd9d2cc..50a5c64363 100644 --- a/mobile/lib/features/channels/emoji_picker/search_field.dart +++ b/mobile/lib/features/channels/emoji_picker/search_field.dart @@ -41,7 +41,7 @@ class _EmojiSearchField extends StatelessWidget { color: colors.onSurfaceVariant, ), prefixIcon: Icon( - LucideIcons.search, + BuzzIcons.search, size: 18, color: colors.onSurfaceVariant, ), @@ -57,7 +57,7 @@ class _EmojiSearchField extends StatelessWidget { key: const ValueKey('emoji-picker-search-clear'), onPressed: controller.clear, icon: Icon( - LucideIcons.x, + BuzzIcons.x, size: 16, color: colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/jump_to_latest_button.dart b/mobile/lib/features/channels/jump_to_latest_button.dart index 692d49472c..9903ab77d3 100644 --- a/mobile/lib/features/channels/jump_to_latest_button.dart +++ b/mobile/lib/features/channels/jump_to_latest_button.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import 'message_action_backdrop_state.dart'; @@ -79,7 +79,7 @@ class JumpToLatestButton extends HookWidget { border: Border.all(color: borderColor), ), child: Icon( - LucideIcons.arrowDown, + BuzzIcons.arrowDown, size: Grid.gutter, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/media_viewer_page.dart b/mobile/lib/features/channels/media_viewer_page.dart index 4d8e85d25c..7dad3358f6 100644 --- a/mobile/lib/features/channels/media_viewer_page.dart +++ b/mobile/lib/features/channels/media_viewer_page.dart @@ -9,7 +9,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:http/http.dart' as http; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:path_provider/path_provider.dart'; import 'package:video_player/video_player.dart'; @@ -554,7 +554,7 @@ class MediaImageViewerPage extends HookConsumerWidget { errorBuilder: (_, _, _) => const _MediaLoadFailure( message: 'Failed to load image', - icon: LucideIcons.imageOff, + icon: BuzzIcons.imageOff, ), ), ), diff --git a/mobile/lib/features/channels/media_viewer_page/image_controls.dart b/mobile/lib/features/channels/media_viewer_page/image_controls.dart index bbd455e8d1..571f6bbcd5 100644 --- a/mobile/lib/features/channels/media_viewer_page/image_controls.dart +++ b/mobile/lib/features/channels/media_viewer_page/image_controls.dart @@ -24,7 +24,7 @@ class _MediaViewerBottomControls extends StatelessWidget { children: [ _MediaViewerCircleButton( key: const ValueKey('message-media-image-viewer-reply-thread'), - icon: LucideIcons.messageSquareReply, + icon: BuzzIcons.messageSquareReply, tooltip: 'Reply in thread', onPressed: onReply, ), @@ -50,7 +50,7 @@ class _MediaViewerBottomControls extends StatelessWidget { const SizedBox(width: Grid.xxs), _MediaViewerCircleButton( key: const ValueKey('message-media-image-viewer-more-actions'), - icon: LucideIcons.ellipsis, + icon: BuzzIcons.ellipsis, tooltip: 'More image actions', onPressed: onMore, ), @@ -78,9 +78,9 @@ class _MediaViewerCircleButton extends StatelessWidget { return Theme( data: ThemeData.dark(), child: IosGlassNavigationButton( - icon: icon == LucideIcons.x + icon: icon == BuzzIcons.x ? IosGlassNavigationIcon.close - : icon == LucideIcons.ellipsis + : icon == BuzzIcons.ellipsis ? IosGlassNavigationIcon.more : IosGlassNavigationIcon.reply, semanticLabel: tooltip, @@ -130,7 +130,7 @@ class _MediaViewerCloseButton extends StatelessWidget { ); } return _MediaViewerCircleButton( - icon: LucideIcons.x, + icon: BuzzIcons.x, tooltip: tooltip, onPressed: onPressed, ); diff --git a/mobile/lib/features/channels/media_viewer_page/video_controls.dart b/mobile/lib/features/channels/media_viewer_page/video_controls.dart index 8dabf40898..f136c4de21 100644 --- a/mobile/lib/features/channels/media_viewer_page/video_controls.dart +++ b/mobile/lib/features/channels/media_viewer_page/video_controls.dart @@ -36,7 +36,7 @@ class _VideoViewerBottomControls extends StatelessWidget { alignment: AlignmentDirectional.centerStart, child: _MediaViewerCircleButton( key: const ValueKey('message-media-video-viewer-reply-thread'), - icon: LucideIcons.messageSquareReply, + icon: BuzzIcons.messageSquareReply, tooltip: 'Reply in thread', onPressed: onReply, ), @@ -191,7 +191,7 @@ class _VideoTransportBar extends HookConsumerWidget { }, tooltip: value.isPlaying ? 'Pause video' : 'Play video', icon: Icon( - value.isPlaying ? LucideIcons.pause : LucideIcons.play, + value.isPlaying ? BuzzIcons.pause : BuzzIcons.play, color: Colors.white, size: 20, ), @@ -228,7 +228,7 @@ class _VideoTransportBar extends HookConsumerWidget { ); }, icon: Icon( - value.volume == 0 ? LucideIcons.volumeX : LucideIcons.volume2, + value.volume == 0 ? BuzzIcons.volumeX : BuzzIcons.volume2, color: Colors.white, size: 20, ), @@ -310,7 +310,7 @@ class _VideoTransportBar extends HookConsumerWidget { key: const ValueKey( 'message-media-video-viewer-reply-thread', ), - icon: LucideIcons.messageSquareReply, + icon: BuzzIcons.messageSquareReply, tooltip: 'Reply in thread', onPressed: onReply, ), diff --git a/mobile/lib/features/channels/media_viewer_page/video_viewer.dart b/mobile/lib/features/channels/media_viewer_page/video_viewer.dart index 2b8176aee0..d3f7f41f88 100644 --- a/mobile/lib/features/channels/media_viewer_page/video_viewer.dart +++ b/mobile/lib/features/channels/media_viewer_page/video_viewer.dart @@ -341,7 +341,7 @@ class MediaVideoViewerPage extends HookConsumerWidget { if (error.value != null || snapshot.hasError) { return const _MediaLoadFailure( message: 'Failed to load video', - icon: LucideIcons.videoOff, + icon: BuzzIcons.videoOff, ); } @@ -482,7 +482,7 @@ class _VideoLoadingPoster extends StatelessWidget { return ColoredBox( color: context.colors.surfaceContainerHighest, child: Icon( - LucideIcons.video, + BuzzIcons.video, size: 40, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/members_sheet.dart b/mobile/lib/features/channels/members_sheet.dart index cb6054e206..ea16b418b6 100644 --- a/mobile/lib/features/channels/members_sheet.dart +++ b/mobile/lib/features/channels/members_sheet.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/sheet_action_section.dart'; @@ -268,7 +268,7 @@ class _MemberTile extends ConsumerWidget { ), trailing: showMenu ? IconButton( - icon: const Icon(LucideIcons.ellipsis, size: 18), + icon: const Icon(BuzzIcons.ellipsis, size: 18), onPressed: () => _showMemberActions( context, ref, @@ -311,7 +311,7 @@ class _MemberTile extends ConsumerWidget { children: [ ListTile( leading: Icon( - LucideIcons.activity, + BuzzIcons.activity, size: 18, color: context.colors.primary, ), @@ -348,7 +348,7 @@ class _MemberTile extends ConsumerWidget { children: [ ListTile( leading: Icon( - LucideIcons.userMinus, + BuzzIcons.userMinus, size: 18, color: context.colors.error, ), diff --git a/mobile/lib/features/channels/message_actions.dart b/mobile/lib/features/channels/message_actions.dart index e80903f743..883f456078 100644 --- a/mobile/lib/features/channels/message_actions.dart +++ b/mobile/lib/features/channels/message_actions.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/physics.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:path_provider/path_provider.dart'; import 'package:photo_manager/photo_manager.dart'; import 'package:share_plus/share_plus.dart'; @@ -205,7 +205,7 @@ Future showMessageActions({ children: [ // Export: take the content out of the conversation. ListTile( - leading: const Icon(LucideIcons.copy), + leading: const Icon(BuzzIcons.copy), title: const Text('Copy text'), onTap: () { Navigator.of(sheetContext).pop(); @@ -221,7 +221,7 @@ Future showMessageActions({ SheetActionSection( children: [ ListTile( - leading: const Icon(LucideIcons.pencil), + leading: const Icon(BuzzIcons.pencil), title: const Text('Edit message'), onTap: () { Navigator.of(sheetContext).pop(); @@ -235,7 +235,7 @@ Future showMessageActions({ ), ListTile( leading: Icon( - LucideIcons.trash2, + BuzzIcons.trash2, color: sheetContext.colors.error, ), title: Text( @@ -296,7 +296,7 @@ void showImageActions({ SheetActionSection( children: [ ListTile( - leading: const Icon(LucideIcons.download), + leading: const Icon(BuzzIcons.download), title: const Text('Save image'), onTap: () { Navigator.of(sheetContext).pop(); @@ -304,7 +304,7 @@ void showImageActions({ }, ), ListTile( - leading: const Icon(LucideIcons.share2), + leading: const Icon(BuzzIcons.share2), title: const Text('Share image'), onTap: () { final renderBox = @@ -325,7 +325,7 @@ void showImageActions({ }, ), ListTile( - leading: const Icon(LucideIcons.link2), + leading: const Icon(BuzzIcons.link2), title: const Text('Copy image link'), onTap: () { Navigator.of(sheetContext).pop(); @@ -343,7 +343,7 @@ void showImageActions({ children: [ ListTile( leading: Icon( - LucideIcons.trash2, + BuzzIcons.trash2, color: sheetContext.colors.error, ), title: Text( @@ -564,7 +564,7 @@ class _MarkReadUnreadTile extends ConsumerWidget { ); return ListTile( - leading: Icon(unread ? LucideIcons.mailCheck : LucideIcons.mailOpen), + leading: Icon(unread ? BuzzIcons.mailCheck : BuzzIcons.mailOpen), title: Text(unread ? 'Mark read' : 'Mark unread'), onTap: () { Navigator.of(context).pop(); @@ -605,7 +605,7 @@ class _FollowThreadTile extends ConsumerWidget { final following = follows.isFollowing(rootId); return ListTile( - leading: Icon(following ? LucideIcons.bellOff : LucideIcons.bellRing), + leading: Icon(following ? BuzzIcons.bellOff : BuzzIcons.bellRing), title: Text(following ? 'Unfollow thread' : 'Follow thread'), onTap: () { Navigator.of(context).pop(); @@ -650,7 +650,7 @@ class _FastActionsRow extends ConsumerWidget { final tiles = [ if (messages != null) _FastActionTile( - icon: LucideIcons.messageSquareReply, + icon: BuzzIcons.messageSquareReply, label: 'Reply', onTap: () { Navigator.of(context).pop(); @@ -669,7 +669,7 @@ class _FastActionsRow extends ConsumerWidget { }, ), _FastActionTile( - icon: LucideIcons.link2, + icon: BuzzIcons.link2, label: 'Copy link', onTap: () { Navigator.of(context).pop(); @@ -682,7 +682,7 @@ class _FastActionsRow extends ConsumerWidget { ), if (canRemind) _FastActionTile( - icon: LucideIcons.clock, + icon: BuzzIcons.clock, label: 'Remind me', onTap: () { final rootContext = Navigator.of( diff --git a/mobile/lib/features/channels/message_actions/message_action_popover.dart b/mobile/lib/features/channels/message_actions/message_action_popover.dart index 97ec300120..7a41f72a0c 100644 --- a/mobile/lib/features/channels/message_actions/message_action_popover.dart +++ b/mobile/lib/features/channels/message_actions/message_action_popover.dart @@ -240,7 +240,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: 'reply', title: 'Reply', - icon: LucideIcons.messageSquareReply, + icon: BuzzIcons.messageSquareReply, group: _PopoverMessageActionGroup.primary, onSelected: () { if (!context.mounted) return; @@ -264,7 +264,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: 'copyLink', title: 'Copy link', - icon: LucideIcons.link2, + icon: BuzzIcons.link2, group: _PopoverMessageActionGroup.utility, onSelected: () { if (!context.mounted) return; @@ -281,7 +281,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: 'remind', title: 'Remind me', - icon: LucideIcons.clock, + icon: BuzzIcons.clock, group: _PopoverMessageActionGroup.utility, onSelected: () { if (!context.mounted) return; @@ -314,7 +314,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: unread ? 'markRead' : 'markUnread', title: unread ? 'Mark read' : 'Mark unread', - icon: unread ? LucideIcons.mailCheck : LucideIcons.mailOpen, + icon: unread ? BuzzIcons.mailCheck : BuzzIcons.mailOpen, group: _PopoverMessageActionGroup.primary, onSelected: () { final notifier = ref.read(readStateProvider.notifier); @@ -340,7 +340,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: following ? 'unfollowThread' : 'followThread', title: following ? 'Unfollow thread' : 'Follow thread', - icon: following ? LucideIcons.bellOff : LucideIcons.bellRing, + icon: following ? BuzzIcons.bellOff : BuzzIcons.bellRing, group: _PopoverMessageActionGroup.utility, onSelected: () { final notifier = ref.read(threadFollowsProvider.notifier); @@ -356,7 +356,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: 'copyText', title: 'Copy text', - icon: LucideIcons.copy, + icon: BuzzIcons.copy, group: _PopoverMessageActionGroup.utility, onSelected: () => Clipboard.setData(ClipboardData(text: message.content)), @@ -369,7 +369,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: 'edit', title: 'Edit message', - icon: LucideIcons.pencil, + icon: BuzzIcons.pencil, group: _PopoverMessageActionGroup.primary, onSelected: () { if (!context.mounted) return; @@ -386,7 +386,7 @@ List<_PopoverMessageAction> _buildPopoverMessageActions({ _PopoverMessageAction( id: 'delete', title: 'Delete message', - icon: LucideIcons.trash2, + icon: BuzzIcons.trash2, group: _PopoverMessageActionGroup.destructive, destructive: true, onSelected: () { diff --git a/mobile/lib/features/channels/message_actions/quick_reaction_row.dart b/mobile/lib/features/channels/message_actions/quick_reaction_row.dart index 15a71c30fc..18dacae27d 100644 --- a/mobile/lib/features/channels/message_actions/quick_reaction_row.dart +++ b/mobile/lib/features/channels/message_actions/quick_reaction_row.dart @@ -116,7 +116,7 @@ class _QuickReactionRow extends ConsumerWidget { } }, child: Icon( - LucideIcons.plus, + BuzzIcons.plus, size: 24, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/message_content.dart b/mobile/lib/features/channels/message_content.dart index 1f98b757ad..f5890e31ff 100644 --- a/mobile/lib/features/channels/message_content.dart +++ b/mobile/lib/features/channels/message_content.dart @@ -8,7 +8,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:gpt_markdown/gpt_markdown.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:open_filex/open_filex.dart'; import 'package:path_provider/path_provider.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -441,7 +441,7 @@ class MessageContent extends HookConsumerWidget { final isCanonicalBuzzLabel = isBuzzLink && text == url; final buzzPresentation = switch (buzzLink) { ChannelDeepLink(:final channelId) => ( - icon: LucideIcons.hash, + icon: BuzzIcons.hash, label: _channelNameForId(resolvedChannelNames, channelId) ?? channelId.substring(0, math.min(8, channelId.length)), @@ -450,7 +450,7 @@ class MessageContent extends HookConsumerWidget { interactive: true, ), MessageDeepLink(:final channelId, :final messageId) => ( - icon: LucideIcons.messageSquare, + icon: BuzzIcons.messageSquare, label: '${_channelNameForId(resolvedChannelNames, channelId) ?? channelId.substring(0, math.min(8, channelId.length))} · ${messageId.substring(0, math.min(8, messageId.length))}', semanticLabel: @@ -459,9 +459,9 @@ class MessageContent extends HookConsumerWidget { ), EntityDeepLink(:final type, :final repository, :final eventId) => ( icon: switch (type) { - 'repo' => LucideIcons.folderGit2, - 'pr' => LucideIcons.gitPullRequest, - _ => LucideIcons.circleDot, + 'repo' => BuzzIcons.folderGit2, + 'pr' => BuzzIcons.gitPullRequest, + _ => BuzzIcons.circleDot, }, label: type == 'repo' ? repository @@ -621,7 +621,7 @@ class _MessageImagePreview extends HookConsumerWidget { ? child : const MediaLoadingPlaceholder(label: 'Loading image'), errorBuilder: (_, _, _) => _MediaPreviewFallback( - icon: LucideIcons.imageOff, + icon: BuzzIcons.imageOff, label: 'Image unavailable', ), ), @@ -803,7 +803,7 @@ class _MessageCodeBlock extends HookWidget { tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), icon: Icon( - isCopied.value ? LucideIcons.check : LucideIcons.copy, + isCopied.value ? BuzzIcons.check : BuzzIcons.copy, size: 14, color: isCopied.value ? context.colors.primary @@ -935,7 +935,7 @@ class _MentionPill extends StatelessWidget { children: [ if (isAgent) ...[ Icon( - LucideIcons.bot, + BuzzIcons.bot, size: fontSize * 0.95, color: context.colors.primary, ), diff --git a/mobile/lib/features/channels/message_content/media_carousel.dart b/mobile/lib/features/channels/message_content/media_carousel.dart index 9d9b0584a6..3436fd4ab7 100644 --- a/mobile/lib/features/channels/message_content/media_carousel.dart +++ b/mobile/lib/features/channels/message_content/media_carousel.dart @@ -169,7 +169,7 @@ class _MessageImageCarousel extends HookConsumerWidget { ), errorBuilder: (_, _, _) => const _MediaPreviewFallback( - icon: LucideIcons.imageOff, + icon: BuzzIcons.imageOff, label: 'Image unavailable', ), ), diff --git a/mobile/lib/features/channels/message_content/token_pill.dart b/mobile/lib/features/channels/message_content/token_pill.dart index 8c812d9b95..5d369d241b 100644 --- a/mobile/lib/features/channels/message_content/token_pill.dart +++ b/mobile/lib/features/channels/message_content/token_pill.dart @@ -36,7 +36,7 @@ class _ChannelLinkMd extends InlineMd { final channelName = raw.substring(1); final opensChannel = channelId != null && onChannelTap != null; final child = _TokenPill( - icon: LucideIcons.hash, + icon: BuzzIcons.hash, interactive: opensChannel, semanticLabel: opensChannel ? 'Open channel $channelName' diff --git a/mobile/lib/features/channels/message_content/video_preview.dart b/mobile/lib/features/channels/message_content/video_preview.dart index 133a0d72c4..b9fb4f33d5 100644 --- a/mobile/lib/features/channels/message_content/video_preview.dart +++ b/mobile/lib/features/channels/message_content/video_preview.dart @@ -101,7 +101,7 @@ class _MessageVideoPreview extends HookConsumerWidget { ? child : const MediaLoadingPlaceholder(label: 'Loading video'), errorBuilder: (_, _, _) => const _MediaPreviewFallback( - icon: LucideIcons.video, + icon: BuzzIcons.video, label: 'Video preview unavailable', ), ) @@ -117,7 +117,7 @@ class _MessageVideoPreview extends HookConsumerWidget { } if (frame == null) { return const _MediaPreviewFallback( - icon: LucideIcons.video, + icon: BuzzIcons.video, label: 'Video attachment', ); } @@ -143,7 +143,7 @@ class _MessageVideoPreview extends HookConsumerWidget { shape: BoxShape.circle, ), child: const Icon( - LucideIcons.play, + BuzzIcons.play, color: Colors.white, size: 24, ), diff --git a/mobile/lib/features/channels/reaction_row.dart b/mobile/lib/features/channels/reaction_row.dart index 0ba9493876..929dd5bfc0 100644 --- a/mobile/lib/features/channels/reaction_row.dart +++ b/mobile/lib/features/channels/reaction_row.dart @@ -4,7 +4,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/app_list_card_item.dart'; @@ -313,7 +313,7 @@ class _AddReactionPill extends StatelessWidget { child: Center( widthFactor: 1, child: Icon( - LucideIcons.smilePlus, + BuzzIcons.smilePlus, size: _pillGlyphSize, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/channels/thread_detail_page.dart b/mobile/lib/features/channels/thread_detail_page.dart index 59f666729c..13c5320b59 100644 --- a/mobile/lib/features/channels/thread_detail_page.dart +++ b/mobile/lib/features/channels/thread_detail_page.dart @@ -4,7 +4,7 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import '../../shared/identity_names/identity_names_provider.dart'; diff --git a/mobile/lib/features/channels/thread_detail_page/message_list.dart b/mobile/lib/features/channels/thread_detail_page/message_list.dart index 28160ee88b..ba87069fbc 100644 --- a/mobile/lib/features/channels/thread_detail_page/message_list.dart +++ b/mobile/lib/features/channels/thread_detail_page/message_list.dart @@ -173,7 +173,7 @@ class _ThreadMessageList extends StatelessWidget { onPressed: onRetryReplies, tooltip: 'Retry', icon: const Icon( - LucideIcons.refreshCcw, + BuzzIcons.refreshCcw, size: 16, ), ), diff --git a/mobile/lib/features/channels/voice_note_attachment.dart b/mobile/lib/features/channels/voice_note_attachment.dart index 01b25ef66f..c62bd35601 100644 --- a/mobile/lib/features/channels/voice_note_attachment.dart +++ b/mobile/lib/features/channels/voice_note_attachment.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/relay/relay.dart'; import '../../shared/theme/theme.dart'; @@ -180,7 +180,7 @@ class VoiceNoteAttachment extends HookConsumerWidget { ) : state.hasError && isRemote ? Icon( - LucideIcons.refreshCcw, + BuzzIcons.refreshCcw, key: const ValueKey('voice-note-retry-icon'), size: 18, color: context.colors.onSecondaryContainer, @@ -271,7 +271,7 @@ class VoiceNoteAttachment extends HookConsumerWidget { padding: EdgeInsets.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), - icon: const Icon(LucideIcons.x, size: 18), + icon: const Icon(BuzzIcons.x, size: 18), ), ), ], diff --git a/mobile/lib/features/channels/voice_note_composer_recorder.dart b/mobile/lib/features/channels/voice_note_composer_recorder.dart index 01a834c6ff..deb60e11f3 100644 --- a/mobile/lib/features/channels/voice_note_composer_recorder.dart +++ b/mobile/lib/features/channels/voice_note_composer_recorder.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/relay/app_lifecycle_provider.dart'; import '../../shared/theme/theme.dart'; @@ -139,7 +139,7 @@ class VoiceNoteComposerRecorder extends HookConsumerWidget { _RecorderButton( key: const ValueKey('voice-note-recorder-close'), tooltip: 'Discard voice note', - icon: LucideIcons.x, + icon: BuzzIcons.x, foreground: context.colors.onSurfaceVariant, background: context.colors.surface, onPressed: isStopping.value ? null : onCancel, @@ -213,7 +213,7 @@ class VoiceNoteComposerRecorder extends HookConsumerWidget { _RecorderButton( key: const ValueKey('voice-note-recorder-stop'), tooltip: 'Stop recording', - icon: LucideIcons.square, + icon: BuzzIcons.square, foreground: Colors.white, background: context.colors.error, onPressed: error.value == null && isStarted.value && !isStopping.value diff --git a/mobile/lib/features/forum/forum_post_card.dart b/mobile/lib/features/forum/forum_post_card.dart index 0e42787cfd..de452b39ce 100644 --- a/mobile/lib/features/forum/forum_post_card.dart +++ b/mobile/lib/features/forum/forum_post_card.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/mentions/agent_identity_provider.dart'; import '../../shared/theme/theme.dart'; @@ -168,7 +168,7 @@ class ForumPostCard extends HookConsumerWidget { child: IconButton( onPressed: () => _showActions(context), icon: Icon( - LucideIcons.ellipsis, + BuzzIcons.ellipsis, size: 16, color: context.colors.onSurfaceVariant, ), @@ -211,7 +211,7 @@ class ForumPostCard extends HookConsumerWidget { Row( children: [ Icon( - LucideIcons.messageSquare, + BuzzIcons.messageSquare, size: 14, color: context.colors.onSurfaceVariant, ), @@ -270,7 +270,7 @@ class ForumPostCard extends HookConsumerWidget { child: SheetActionSection( children: [ ListTile( - leading: const Icon(LucideIcons.copy), + leading: const Icon(BuzzIcons.copy), title: const Text('Copy text'), onTap: () { Navigator.of(sheetContext).pop(); @@ -280,7 +280,7 @@ class ForumPostCard extends HookConsumerWidget { if (isOwn && onDelete != null) ListTile( leading: Icon( - LucideIcons.trash2, + BuzzIcons.trash2, color: sheetContext.colors.error, ), title: Text( diff --git a/mobile/lib/features/forum/forum_posts_view.dart b/mobile/lib/features/forum/forum_posts_view.dart index 352c1bc73f..9006797344 100644 --- a/mobile/lib/features/forum/forum_posts_view.dart +++ b/mobile/lib/features/forum/forum_posts_view.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/relay/relay_closed_policy.dart'; import '../../shared/theme/theme.dart'; @@ -75,7 +75,7 @@ class ForumPostsView extends HookConsumerWidget { onPressed: () => isComposing.value = true, tooltip: 'New post', shape: const CircleBorder(), - child: const Icon(LucideIcons.plus), + child: const Icon(BuzzIcons.plus), ) : null, body: postsAsync.when( @@ -148,7 +148,7 @@ class ForumPostsView extends HookConsumerWidget { padding: const EdgeInsets.only(right: Grid.xxs), child: IconButton( onPressed: () => isComposing.value = false, - icon: const Icon(LucideIcons.x, size: 18), + icon: const Icon(BuzzIcons.x, size: 18), tooltip: 'Dismiss', visualDensity: VisualDensity.compact, ), @@ -207,7 +207,7 @@ class _EmptyState extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.messageSquareText, + BuzzIcons.messageSquareText, size: Grid.xl, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/forum/forum_thread_page.dart b/mobile/lib/features/forum/forum_thread_page.dart index ad9118a58f..b13f54e249 100644 --- a/mobile/lib/features/forum/forum_thread_page.dart +++ b/mobile/lib/features/forum/forum_thread_page.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/mentions/agent_identity_provider.dart'; import '../../shared/relay/relay_closed_policy.dart'; @@ -90,7 +90,7 @@ class ForumThreadPage extends HookConsumerWidget { onPressed: () => _showPostActions(context, ref, threadAsync.value!), tooltip: 'Post actions', - icon: const Icon(LucideIcons.ellipsis), + icon: const Icon(BuzzIcons.ellipsis), ), ], ), @@ -147,7 +147,7 @@ class ForumThreadPage extends HookConsumerWidget { child: SheetActionSection( children: [ ListTile( - leading: const Icon(LucideIcons.copy), + leading: const Icon(BuzzIcons.copy), title: const Text('Copy text'), onTap: () { Navigator.of(sheetContext).pop(); @@ -156,7 +156,7 @@ class ForumThreadPage extends HookConsumerWidget { ), ListTile( leading: Icon( - LucideIcons.trash2, + BuzzIcons.trash2, color: sheetContext.colors.error, ), title: Text( @@ -274,7 +274,7 @@ class _ThreadContent extends HookConsumerWidget { child: Row( children: [ Icon( - LucideIcons.messageSquare, + BuzzIcons.messageSquare, size: 16, color: context.colors.onSurfaceVariant, ), @@ -554,7 +554,7 @@ class _ReplyRow extends ConsumerWidget { child: IconButton( onPressed: () => _showActions(context, ref), icon: Icon( - LucideIcons.ellipsis, + BuzzIcons.ellipsis, size: 16, color: context.colors.onSurfaceVariant, ), @@ -608,7 +608,7 @@ class _ReplyRow extends ConsumerWidget { child: SheetActionSection( children: [ ListTile( - leading: const Icon(LucideIcons.copy), + leading: const Icon(BuzzIcons.copy), title: const Text('Copy text'), onTap: () { Navigator.of(sheetContext).pop(); @@ -618,7 +618,7 @@ class _ReplyRow extends ConsumerWidget { if (isOwn) ListTile( leading: Icon( - LucideIcons.trash2, + BuzzIcons.trash2, color: sheetContext.colors.error, ), title: Text( diff --git a/mobile/lib/features/home/home_page.dart b/mobile/lib/features/home/home_page.dart index 34a00f880e..c5ab27ccf9 100644 --- a/mobile/lib/features/home/home_page.dart +++ b/mobile/lib/features/home/home_page.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/concentric_sheet_surface.dart'; @@ -55,18 +55,18 @@ class HomePage extends HookConsumerWidget { static const _destinations = [ _HomeDestination( - icon: LucideIcons.house300, - selectedIcon: LucideIcons.house500, + icon: BuzzIcons.house300, + selectedIcon: BuzzIcons.house500, label: 'Home', ), _HomeDestination( - icon: LucideIcons.inbox300, - selectedIcon: LucideIcons.inbox500, + icon: BuzzIcons.inbox300, + selectedIcon: BuzzIcons.inbox500, label: 'Activity', ), _HomeDestination( - icon: LucideIcons.search300, - selectedIcon: LucideIcons.search500, + icon: BuzzIcons.search300, + selectedIcon: BuzzIcons.search500, label: 'Search', ), ]; diff --git a/mobile/lib/features/invites/invite_create_page.dart b/mobile/lib/features/invites/invite_create_page.dart index 997a3c0f68..07803c0878 100644 --- a/mobile/lib/features/invites/invite_create_page.dart +++ b/mobile/lib/features/invites/invite_create_page.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/clipboard_utils.dart'; import '../../shared/community/community_membership_provider.dart'; @@ -106,7 +106,7 @@ class _InvitePermissionError extends StatelessWidget { @override Widget build(BuildContext context) { return _InviteMessage( - icon: LucideIcons.wifiOff, + icon: BuzzIcons.wifiOff, title: 'Could not check permissions', body: 'Reconnect to this community and try again.', action: TextButton(onPressed: onRetry, child: const Text('Retry')), @@ -120,7 +120,7 @@ class _InvitePermissionDenied extends StatelessWidget { @override Widget build(BuildContext context) { return const _InviteMessage( - icon: LucideIcons.shieldAlert, + icon: BuzzIcons.shieldAlert, title: 'Invite access required', body: 'Only community owners and admins can invite people.', ); diff --git a/mobile/lib/features/invites/invite_create_page/invite_link_section.dart b/mobile/lib/features/invites/invite_create_page/invite_link_section.dart index aefa461478..6539d8571d 100644 --- a/mobile/lib/features/invites/invite_create_page/invite_link_section.dart +++ b/mobile/lib/features/invites/invite_create_page/invite_link_section.dart @@ -74,7 +74,7 @@ class _InviteLinkSection extends HookConsumerWidget { child: Builder( builder: (buttonContext) => BuzzActionTile( key: const Key('community-invite-share-link'), - icon: LucideIcons.share2, + icon: BuzzIcons.share2, label: 'Share', isEnabled: invite.value != null, onTap: () => share(buttonContext), @@ -85,7 +85,7 @@ class _InviteLinkSection extends HookConsumerWidget { Expanded( child: BuzzActionTile( key: const Key('community-invite-copy-link'), - icon: LucideIcons.copy, + icon: BuzzIcons.copy, label: 'Copy', isEnabled: invite.value != null, onTap: () => copyToClipboard( @@ -218,7 +218,7 @@ class _InviteOptionSheet extends StatelessWidget { title: option.label, trailing: option.value == value ? Icon( - LucideIcons.check, + BuzzIcons.check, size: 18, color: context.colors.primary, ) @@ -243,7 +243,7 @@ class _InviteRowChevron extends StatelessWidget { @override Widget build(BuildContext context) { return Icon( - LucideIcons.chevronRight, + BuzzIcons.chevronRight, size: 18, color: context.colors.onSurfaceVariant, ); diff --git a/mobile/lib/features/invites/invite_join_sheet.dart b/mobile/lib/features/invites/invite_join_sheet.dart index 012763e0d8..f110220de8 100644 --- a/mobile/lib/features/invites/invite_join_sheet.dart +++ b/mobile/lib/features/invites/invite_join_sheet.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/buzz_loading_indicator.dart'; @@ -70,7 +70,7 @@ class InviteJoinSheet extends ConsumerWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Icon(LucideIcons.userPlus, size: 40, color: context.colors.primary), + Icon(BuzzIcons.userPlus, size: 40, color: context.colors.primary), const SizedBox(height: Grid.sm), Text( isStarterSetupRecovery @@ -168,7 +168,7 @@ class InviteJoinSheet extends ConsumerWidget { : 'Joining community', ), ) - : const Icon(LucideIcons.check), + : const Icon(BuzzIcons.check), label: Text(primaryLabel), ), ), @@ -202,7 +202,7 @@ class _InviteJoinSuccess extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Icon( - LucideIcons.circleCheck, + BuzzIcons.circleCheck, size: 40, color: context.colors.primary, ), @@ -228,7 +228,7 @@ class _InviteJoinSuccess extends StatelessWidget { ), ); }, - icon: const Icon(LucideIcons.scanLine), + icon: const Icon(BuzzIcons.scanLine), label: const Text('Back it up now'), ), const SizedBox(height: Grid.xs), diff --git a/mobile/lib/features/pairing/pairing_page.dart b/mobile/lib/features/pairing/pairing_page.dart index ff5863eec2..88e7157ec9 100644 --- a/mobile/lib/features/pairing/pairing_page.dart +++ b/mobile/lib/features/pairing/pairing_page.dart @@ -8,7 +8,7 @@ import '../../shared/widgets/frosted_app_bar.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/security/sensitive_action_authorizer.dart'; import '../../shared/error_haptic.dart'; @@ -148,7 +148,7 @@ class PairingPage extends HookConsumerWidget { ), ) : IconButton( - icon: const Icon(LucideIcons.arrowLeft), + icon: const Icon(BuzzIcons.arrowLeft), tooltip: 'Back', onPressed: () => Navigator.of(context).pop(), ), diff --git a/mobile/lib/features/pairing/pairing_page/pairing_welcome_view.dart b/mobile/lib/features/pairing/pairing_page/pairing_welcome_view.dart index cbdb9c3c6f..c404e3582d 100644 --- a/mobile/lib/features/pairing/pairing_page/pairing_welcome_view.dart +++ b/mobile/lib/features/pairing/pairing_page/pairing_welcome_view.dart @@ -147,7 +147,7 @@ class _PairingWelcomeView extends StatelessWidget { context._onboardingMutedInk, ), prefixIcon: Icon( - LucideIcons.link, + BuzzIcons.link, color: context._onboardingInk, ), enabledBorder: context._inputBorder, @@ -208,7 +208,7 @@ class _PairingWelcomeView extends StatelessWidget { child: Row( children: [ Icon( - LucideIcons.triangleAlert, + BuzzIcons.triangleAlert, size: 16, color: context.colors.onErrorContainer, ), diff --git a/mobile/lib/features/pairing/pairing_page/sas_verification_view.dart b/mobile/lib/features/pairing/pairing_page/sas_verification_view.dart index 6eab484de7..91ae8655b9 100644 --- a/mobile/lib/features/pairing/pairing_page/sas_verification_view.dart +++ b/mobile/lib/features/pairing/pairing_page/sas_verification_view.dart @@ -118,8 +118,8 @@ class _SasVerificationView extends HookConsumerWidget { if (showProtection) ...[ Icon( biometricLabel == 'Use Face ID' - ? LucideIcons.scanFace - : LucideIcons.fingerprint, + ? BuzzIcons.scanFace + : BuzzIcons.fingerprint, size: 64, color: context._onboardingInk, ), @@ -141,11 +141,7 @@ class _SasVerificationView extends HookConsumerWidget { ), ), ] else if (codeAccepted.value) ...[ - Icon( - LucideIcons.shieldCheck, - size: 64, - color: context._onboardingInk, - ), + Icon(BuzzIcons.shieldCheck, size: 64, color: context._onboardingInk), const SizedBox(height: Grid.sm), Text('Code confirmed', style: context.textTheme.headlineSmall), ] else ...[ diff --git a/mobile/lib/features/pairing/pairing_qr_scanner.dart b/mobile/lib/features/pairing/pairing_qr_scanner.dart index bab30f6e7e..ff6c14f2f9 100644 --- a/mobile/lib/features/pairing/pairing_qr_scanner.dart +++ b/mobile/lib/features/pairing/pairing_qr_scanner.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/physics.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import '../../shared/theme/theme.dart'; diff --git a/mobile/lib/features/pairing/pairing_qr_scanner/scanner_camera.dart b/mobile/lib/features/pairing/pairing_qr_scanner/scanner_camera.dart index d02a820a05..a5f85a1f15 100644 --- a/mobile/lib/features/pairing/pairing_qr_scanner/scanner_camera.dart +++ b/mobile/lib/features/pairing/pairing_qr_scanner/scanner_camera.dart @@ -29,7 +29,7 @@ class _QrScannerCamera extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.cameraOff, + BuzzIcons.cameraOff, size: 48, color: Colors.white.withValues(alpha: 0.72), ), diff --git a/mobile/lib/features/profile/animated_avatar_capture.dart b/mobile/lib/features/profile/animated_avatar_capture.dart index 45264cf884..33e3582787 100644 --- a/mobile/lib/features/profile/animated_avatar_capture.dart +++ b/mobile/lib/features/profile/animated_avatar_capture.dart @@ -11,7 +11,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:google_mlkit_selfie_segmentation/google_mlkit_selfie_segmentation.dart'; import 'package:image/image.dart' as image; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:path_provider/path_provider.dart'; import '../../shared/emoji/emoji_avatar.dart'; @@ -609,7 +609,7 @@ class AnimatedAvatarCapture extends HookConsumerWidget { semanticLabel: 'Starting camera', ) : const Icon( - LucideIcons.cameraOff, + BuzzIcons.cameraOff, color: Colors.white, size: 32, ), diff --git a/mobile/lib/features/profile/animated_avatar_capture/review_controls.dart b/mobile/lib/features/profile/animated_avatar_capture/review_controls.dart index 2d45edd683..851d5fe468 100644 --- a/mobile/lib/features/profile/animated_avatar_capture/review_controls.dart +++ b/mobile/lib/features/profile/animated_avatar_capture/review_controls.dart @@ -54,7 +54,7 @@ class _AnimatedReviewNav extends StatelessWidget { children: [ Expanded( child: AvatarEditorOptionButton( - icon: LucideIcons.userRound, + icon: BuzzIcons.userRound, iosIcon: IosGlassNavigationIcon.person, label: 'You', selected: selected == _AnimatedReviewSection.person, @@ -64,7 +64,7 @@ class _AnimatedReviewNav extends StatelessWidget { const SizedBox(width: Grid.half), Expanded( child: AvatarEditorOptionButton( - icon: LucideIcons.palette, + icon: BuzzIcons.palette, iosIcon: IosGlassNavigationIcon.palette, label: 'Background', selected: selected == _AnimatedReviewSection.color, @@ -74,7 +74,7 @@ class _AnimatedReviewNav extends StatelessWidget { const SizedBox(width: Grid.half), Expanded( child: AvatarEditorOptionButton( - icon: LucideIcons.galleryThumbnails, + icon: BuzzIcons.galleryThumbnails, iosIcon: IosGlassNavigationIcon.frame, label: 'Frame', selected: selected == _AnimatedReviewSection.poster, @@ -86,7 +86,7 @@ class _AnimatedReviewNav extends StatelessWidget { const SizedBox(width: Grid.half), Expanded( child: AvatarEditorOptionButton( - icon: LucideIcons.camera, + icon: BuzzIcons.camera, iosIcon: IosGlassNavigationIcon.camera, label: 'Retake', selected: false, @@ -141,7 +141,7 @@ class _AnimatedFramingControl extends HookWidget { onOutlineChanged(!outline); }, icon: Icon( - outline ? LucideIcons.circle : LucideIcons.circleDashed, + outline ? BuzzIcons.circle : BuzzIcons.circleDashed, size: 24, ), constraints: const BoxConstraints.tightFor( diff --git a/mobile/lib/features/profile/image_avatar_capture.dart b/mobile/lib/features/profile/image_avatar_capture.dart index e9ffda995d..7972398f4c 100644 --- a/mobile/lib/features/profile/image_avatar_capture.dart +++ b/mobile/lib/features/profile/image_avatar_capture.dart @@ -9,7 +9,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image/image.dart' as image; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/relay/relay.dart'; import '../../shared/theme/theme.dart'; @@ -437,7 +437,7 @@ class ImageAvatarCapture extends HookConsumerWidget { ? const BuzzLoadingIndicator( semanticLabel: 'Starting camera', ) - : const Icon(LucideIcons.cameraOff, size: 32), + : const Icon(BuzzIcons.cameraOff, size: 32), ), ), ), @@ -496,8 +496,8 @@ class ImageAvatarCapture extends HookConsumerWidget { ), width: sideWidth, icon: isClosing.value - ? LucideIcons.camera - : LucideIcons.x, + ? BuzzIcons.camera + : BuzzIcons.x, iosIcon: isClosing.value ? IosGlassNavigationIcon.camera : IosGlassNavigationIcon.close, @@ -571,8 +571,8 @@ class ImageAvatarCapture extends HookConsumerWidget { ), width: sideWidth, icon: isClosing.value - ? LucideIcons.images - : LucideIcons.switchCamera, + ? BuzzIcons.images + : BuzzIcons.switchCamera, iosIcon: isClosing.value ? IosGlassNavigationIcon.photoLibrary : IosGlassNavigationIcon.rotateCamera, diff --git a/mobile/lib/features/profile/profile_avatar_editor.dart b/mobile/lib/features/profile/profile_avatar_editor.dart index b54fbee0d6..417e8e4b5a 100644 --- a/mobile/lib/features/profile/profile_avatar_editor.dart +++ b/mobile/lib/features/profile/profile_avatar_editor.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/emoji/emoji_avatar.dart'; import '../../shared/emoji/emoji_data.dart'; @@ -703,7 +703,7 @@ class _ImageMode extends StatelessWidget { Expanded( child: _ImageSourceOption( key: const ValueKey('image-source-camera'), - icon: LucideIcons.camera, + icon: BuzzIcons.camera, iosIcon: IosGlassNavigationIcon.camera, label: 'Camera', onTap: isPicking ? null : onCamera, @@ -714,7 +714,7 @@ class _ImageMode extends StatelessWidget { Expanded( child: _ImageSourceOption( key: const ValueKey('image-source-library'), - icon: LucideIcons.images, + icon: BuzzIcons.images, iosIcon: IosGlassNavigationIcon.photoLibrary, label: 'Photo Library', onTap: isPicking ? null : onLibrary, diff --git a/mobile/lib/features/profile/profile_avatar_editor/emoji_avatar_picker.dart b/mobile/lib/features/profile/profile_avatar_editor/emoji_avatar_picker.dart index 6d658935f2..9c52957a2e 100644 --- a/mobile/lib/features/profile/profile_avatar_editor/emoji_avatar_picker.dart +++ b/mobile/lib/features/profile/profile_avatar_editor/emoji_avatar_picker.dart @@ -133,7 +133,7 @@ class _EmojiMode extends HookConsumerWidget { borderSide: BorderSide.none, ), prefixIcon: const Icon( - LucideIcons.search, + BuzzIcons.search, size: 20, ), suffixIcon: searchController.text.isEmpty @@ -142,7 +142,7 @@ class _EmojiMode extends HookConsumerWidget { tooltip: 'Clear search', onPressed: searchController.clear, icon: const Icon( - LucideIcons.x, + BuzzIcons.x, size: 18, ), ), @@ -227,7 +227,7 @@ class _EmojiMode extends HookConsumerWidget { Expanded( child: AvatarEditorOptionButton( key: const ValueKey('emoji-editor-background'), - icon: LucideIcons.palette, + icon: BuzzIcons.palette, iosIcon: IosGlassNavigationIcon.palette, label: 'Background', selected: @@ -241,7 +241,7 @@ class _EmojiMode extends HookConsumerWidget { Expanded( child: AvatarEditorOptionButton( key: const ValueKey('emoji-editor-emoji'), - icon: LucideIcons.smile, + icon: BuzzIcons.smile, iosIcon: IosGlassNavigationIcon.emoji, label: 'Emoji', selected: activeSection == _EmojiEditorSection.emoji, @@ -340,7 +340,7 @@ class _AvatarSkinToneSelector extends StatelessWidget { Expanded(child: Text(tone.label)), if (index == value) Icon( - LucideIcons.check, + BuzzIcons.check, size: 18, color: context.colors.primary, ), diff --git a/mobile/lib/features/profile/profile_edit_page.dart b/mobile/lib/features/profile/profile_edit_page.dart index 7f042a2a76..0ccfdbed90 100644 --- a/mobile/lib/features/profile/profile_edit_page.dart +++ b/mobile/lib/features/profile/profile_edit_page.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/profile/user_profile.dart'; import '../../shared/relay/relay.dart'; @@ -311,7 +311,7 @@ class ProfileEditPage extends HookConsumerWidget { onPressed: isClosingAvatar.value ? null : () => unawaited(closeAvatarEditor()), - icon: const Icon(LucideIcons.arrowLeft), + icon: const Icon(BuzzIcons.arrowLeft), ) : null, actions: isEditingAvatar.value @@ -626,7 +626,7 @@ class _EditChevron extends StatelessWidget { @override Widget build(BuildContext context) => Icon( - LucideIcons.chevronRight, + BuzzIcons.chevronRight, size: 18, color: context.colors.onSurfaceVariant, ); diff --git a/mobile/lib/features/profile/profile_text_edit_sheet.dart b/mobile/lib/features/profile/profile_text_edit_sheet.dart index 939984dbf5..a0e9dce3c4 100644 --- a/mobile/lib/features/profile/profile_text_edit_sheet.dart +++ b/mobile/lib/features/profile/profile_text_edit_sheet.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/buzz_sheet_header.dart'; @@ -96,7 +96,7 @@ class ProfileTextEditSheet extends HookWidget { borderRadius: BorderRadius.circular(Radii.dialog), ), ), - icon: const Icon(LucideIcons.x, size: 22), + icon: const Icon(BuzzIcons.x, size: 22), ), ); diff --git a/mobile/lib/features/profile/set_status_sheet.dart b/mobile/lib/features/profile/set_status_sheet.dart index 15e2bd927a..dbd33aaa43 100644 --- a/mobile/lib/features/profile/set_status_sheet.dart +++ b/mobile/lib/features/profile/set_status_sheet.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:intl/intl.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/custom_emoji/custom_emoji.dart'; import '../../shared/custom_emoji/custom_emoji_provider.dart'; @@ -154,7 +154,7 @@ class _SetStatusSheet extends HookConsumerWidget { borderRadius: BorderRadius.circular(Radii.dialog), ), ), - icon: const Icon(LucideIcons.check, size: 22), + icon: const Icon(BuzzIcons.check, size: 22), ), ); @@ -197,15 +197,15 @@ class _SetStatusSheet extends HookConsumerWidget { label: 'Duration', children: [ AppListRow( - icon: LucideIcons.clock3, + icon: BuzzIcons.clock3, title: 'Duration', value: duration.value.label, - trailing: const Icon(LucideIcons.chevronDown, size: 18), + trailing: const Icon(BuzzIcons.chevronDown, size: 18), onTap: chooseDuration, ), if (duration.value == _StatusDuration.custom) AppListRow( - icon: LucideIcons.calendarClock, + icon: BuzzIcons.calendarClock, title: 'Until', value: _formatUntil(customUntil.value), onTap: pickCustomUntil, @@ -241,7 +241,7 @@ class _SetStatusSheet extends HookConsumerWidget { AppListCard( children: [ AppListRow( - icon: LucideIcons.trash2, + icon: BuzzIcons.trash2, title: 'Clear status', titleColor: context.colors.error, onTap: isSaving.value ? null : handleClear, @@ -317,7 +317,7 @@ class _StatusInput extends ConsumerWidget { tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), icon: Icon( - LucideIcons.x, + BuzzIcons.x, size: 14, color: context.colors.onSurface, ), @@ -366,7 +366,7 @@ class _StatusEmojiPreview extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { if (emoji.isEmpty) { return Icon( - LucideIcons.smilePlus, + BuzzIcons.smilePlus, size: _emojiGlyphSize, color: context.colors.onSurfaceVariant, ); @@ -406,7 +406,7 @@ Future<_StatusDuration?> _showStatusDurationSheet( AppListRow( title: option.label, trailing: option == selected - ? const Icon(LucideIcons.check, size: 18) + ? const Icon(BuzzIcons.check, size: 18) : null, onTap: () => Navigator.of(sheetContext).pop(option), ), diff --git a/mobile/lib/features/profile/settings_profile_header.dart b/mobile/lib/features/profile/settings_profile_header.dart index d452c36cec..c97b5f33b0 100644 --- a/mobile/lib/features/profile/settings_profile_header.dart +++ b/mobile/lib/features/profile/settings_profile_header.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/animated_avatar.dart'; import '../../shared/custom_emoji/custom_emoji.dart'; @@ -301,7 +301,7 @@ class _PresencePill extends StatelessWidget { ), if (option == effectivePresence) Icon( - LucideIcons.check, + BuzzIcons.check, size: 16, color: context.colors.primary, ), diff --git a/mobile/lib/features/profile/user_profile_sheet.dart b/mobile/lib/features/profile/user_profile_sheet.dart index 28e2fddd83..438f112566 100644 --- a/mobile/lib/features/profile/user_profile_sheet.dart +++ b/mobile/lib/features/profile/user_profile_sheet.dart @@ -5,7 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/misc.dart' show ProviderListenable; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/animated_avatar.dart'; import '../../shared/identity_names/identity_names.dart'; @@ -274,7 +274,7 @@ class UserProfileSheet extends HookConsumerWidget { child: BuzzActionTile( icon: isOpeningDirectMessage.value ? null - : LucideIcons.messageSquare, + : BuzzIcons.messageSquare, label: isOpeningDirectMessage.value ? 'Opening…' : 'Message', @@ -288,8 +288,8 @@ class UserProfileSheet extends HookConsumerWidget { Expanded( child: BuzzActionTile( icon: copied.value - ? LucideIcons.check - : LucideIcons.key, + ? BuzzIcons.check + : BuzzIcons.key, label: copied.value ? 'Copied' : 'Copy public key', isEnabled: npub != null, onTap: copyPublicKey, @@ -337,7 +337,7 @@ void _showProfileCopyToast(BuildContext context) { child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon(LucideIcons.check, size: 18, color: colors.onInverseSurface), + Icon(BuzzIcons.check, size: 18, color: colors.onInverseSurface), const SizedBox(width: Grid.xxs), Text('Public key copied', style: textStyle), ], diff --git a/mobile/lib/features/pulse/agent_activity_card.dart b/mobile/lib/features/pulse/agent_activity_card.dart index 6c8c4c5f30..c92905ccb7 100644 --- a/mobile/lib/features/pulse/agent_activity_card.dart +++ b/mobile/lib/features/pulse/agent_activity_card.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/identity_names/identity_names.dart'; import '../../shared/theme/theme.dart'; @@ -51,7 +51,7 @@ class AgentActivityCard extends HookConsumerWidget { imageUrl: profile?.avatarUrl, radius: 18, backgroundColor: context.colors.primaryContainer, - fallback: const Icon(LucideIcons.bot, size: 18), + fallback: const Icon(BuzzIcons.bot, size: 18), isAgent: true, ), Positioned( @@ -123,8 +123,8 @@ class AgentActivityCard extends HookConsumerWidget { if (group.notes.length > 1) Icon( expanded.value - ? LucideIcons.chevronUp - : LucideIcons.chevronDown, + ? BuzzIcons.chevronUp + : BuzzIcons.chevronDown, size: 18, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/pulse/note_card.dart b/mobile/lib/features/pulse/note_card.dart index 90d2b35fdd..8e67935d79 100644 --- a/mobile/lib/features/pulse/note_card.dart +++ b/mobile/lib/features/pulse/note_card.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; import '../../shared/clipboard_utils.dart'; @@ -131,7 +131,7 @@ class NoteCard extends HookConsumerWidget { if (isAgent) ...[ const SizedBox(width: Grid.half), Icon( - LucideIcons.bot, + BuzzIcons.bot, size: 13, color: context.colors.primary, ), @@ -195,9 +195,7 @@ class NoteCard extends HookConsumerWidget { Row( children: [ _ActionButton( - icon: effectiveUpvoted - ? Icons.favorite - : LucideIcons.heart, + icon: effectiveUpvoted ? Icons.favorite : BuzzIcons.heart, label: effectiveCount > 0 ? '$effectiveCount' : null, color: effectiveUpvoted ? Colors.redAccent : null, onTap: () async { @@ -218,7 +216,7 @@ class NoteCard extends HookConsumerWidget { }, ), _ActionButton( - icon: LucideIcons.messageCircle, + icon: BuzzIcons.messageCircle, onTap: () => Navigator.of(context).push( MaterialPageRoute( builder: (_) => @@ -227,7 +225,7 @@ class NoteCard extends HookConsumerWidget { ), ), _ActionButton( - icon: LucideIcons.share, + icon: BuzzIcons.share, onTap: () async { await copyToClipboard( context, @@ -237,7 +235,7 @@ class NoteCard extends HookConsumerWidget { }, ), _ActionButton( - icon: LucideIcons.mail, + icon: BuzzIcons.mail, onTap: () async { final channel = await ref .read(channelActionsProvider) diff --git a/mobile/lib/features/pulse/pulse_page.dart b/mobile/lib/features/pulse/pulse_page.dart index 070f6c8f9a..d9e8ef4c7f 100644 --- a/mobile/lib/features/pulse/pulse_page.dart +++ b/mobile/lib/features/pulse/pulse_page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/identity_names/identity_names_provider.dart'; import '../../shared/relay/relay.dart'; @@ -69,7 +69,7 @@ class PulsePage extends HookConsumerWidget { ), tooltip: 'New note', shape: const CircleBorder(), - child: const Icon(LucideIcons.plus), + child: const Icon(BuzzIcons.plus), ), body: Column( children: [ @@ -81,27 +81,27 @@ class PulsePage extends HookConsumerWidget { FilterChipItem( id: PulseTab.everyone, label: 'Everyone', - icon: LucideIcons.radio, + icon: BuzzIcons.radio, ), FilterChipItem( id: PulseTab.following, label: 'Following', - icon: LucideIcons.users, + icon: BuzzIcons.users, ), FilterChipItem( id: PulseTab.liked, label: 'Liked', - icon: LucideIcons.heart, + icon: BuzzIcons.heart, ), FilterChipItem( id: PulseTab.agents, label: 'Agents', - icon: LucideIcons.bot, + icon: BuzzIcons.bot, ), FilterChipItem( id: PulseTab.mine, label: 'Mine', - icon: LucideIcons.user, + icon: BuzzIcons.user, ), ], ), @@ -165,7 +165,7 @@ class _PulseBody extends ConsumerWidget { loading: () => const _TimelineSkeleton(), error: (_, _) => _MessageListShell( child: _EmptyState( - icon: LucideIcons.circleAlert, + icon: BuzzIcons.circleAlert, message: 'Could not load Pulse. Pull to try again.', ), ), @@ -270,7 +270,7 @@ class _EmptyState extends StatelessWidget { final IconData icon; final String message; - const _EmptyState({this.icon = LucideIcons.radio, required this.message}); + const _EmptyState({this.icon = BuzzIcons.radio, required this.message}); @override Widget build(BuildContext context) { diff --git a/mobile/lib/features/search/search_page.dart b/mobile/lib/features/search/search_page.dart index 427a11f87c..f5adadee6c 100644 --- a/mobile/lib/features/search/search_page.dart +++ b/mobile/lib/features/search/search_page.dart @@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/identity_names/identity_names_provider.dart'; import '../../shared/mentions/agent_identity_provider.dart'; import '../../shared/mentions/mention_tags.dart'; @@ -522,7 +522,7 @@ class _SearchBody extends ConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.search, + BuzzIcons.search, size: 64, color: context.colors.onSurfaceVariant, ), @@ -678,7 +678,7 @@ class _RecentSearches extends StatelessWidget { child: Row( children: [ Icon( - LucideIcons.clock, + BuzzIcons.clock, size: 18, color: context.colors.onSurfaceVariant, ), @@ -692,7 +692,7 @@ class _RecentSearches extends StatelessWidget { ), ), Icon( - LucideIcons.chevronRight, + BuzzIcons.chevronRight, size: 16, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/settings/accent_picker_page.dart b/mobile/lib/features/settings/accent_picker_page.dart index 1cf5d851d5..c15e83aa4a 100644 --- a/mobile/lib/features/settings/accent_picker_page.dart +++ b/mobile/lib/features/settings/accent_picker_page.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/frosted_app_bar.dart'; @@ -74,7 +74,7 @@ class _AccentRow extends StatelessWidget { ), title: Text(label), trailing: selected - ? Icon(LucideIcons.check, size: 18, color: context.colors.primary) + ? Icon(BuzzIcons.check, size: 18, color: context.colors.primary) : null, onTap: onTap, ); diff --git a/mobile/lib/features/settings/settings_page.dart b/mobile/lib/features/settings/settings_page.dart index 7583a6b8be..0f780b8a86 100644 --- a/mobile/lib/features/settings/settings_page.dart +++ b/mobile/lib/features/settings/settings_page.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; import 'package:package_info_plus/package_info_plus.dart'; @@ -104,7 +104,7 @@ class SettingsPage extends HookConsumerWidget { Navigator.of(context).pop(); }, color: navigationPrimaryForeground(context), - icon: const Icon(LucideIcons.x), + icon: const Icon(BuzzIcons.x), ), ), bottomHeight: Grid.xxs, @@ -173,7 +173,7 @@ class _RowChevron extends StatelessWidget { @override Widget build(BuildContext context) { return Icon( - LucideIcons.chevronRight, + BuzzIcons.chevronRight, size: 18, color: context.colors.onSurfaceVariant, ); diff --git a/mobile/lib/features/settings/settings_page/connection_section.dart b/mobile/lib/features/settings/settings_page/connection_section.dart index 29d6b00cdd..b45860012d 100644 --- a/mobile/lib/features/settings/settings_page/connection_section.dart +++ b/mobile/lib/features/settings/settings_page/connection_section.dart @@ -112,7 +112,7 @@ class _IdentityRow extends StatelessWidget { child: AppListRow( title: 'Copy public key (npub)', trailing: Icon( - LucideIcons.copy, + BuzzIcons.copy, size: 18, color: context.colors.onSurfaceVariant, ), diff --git a/mobile/lib/features/settings/settings_page/notifications_section.dart b/mobile/lib/features/settings/settings_page/notifications_section.dart index 64f05ede3a..8383b90403 100644 --- a/mobile/lib/features/settings/settings_page/notifications_section.dart +++ b/mobile/lib/features/settings/settings_page/notifications_section.dart @@ -57,7 +57,7 @@ class _NotificationsSection extends ConsumerWidget { children: [ AppListRow( key: const ValueKey('push-notifications-enabled'), - icon: LucideIcons.bell, + icon: BuzzIcons.bell, title: 'Push notifications', subtitle: subtitle, subtitleStyle: showSettingsRecovery @@ -89,7 +89,7 @@ class _NotificationsSection extends ConsumerWidget { if (showSettingsRecovery) AppListRow( key: const ValueKey('push-notifications-open-settings'), - icon: LucideIcons.settings, + icon: BuzzIcons.settings, title: 'Open iOS Notification Settings', onTap: () => unawaited( ref.read(buzzPushNotificationSettingsOpenerProvider)(), diff --git a/mobile/lib/features/settings/theme_option_sheets.dart b/mobile/lib/features/settings/theme_option_sheets.dart index da96c3b877..8de22df5af 100644 --- a/mobile/lib/features/settings/theme_option_sheets.dart +++ b/mobile/lib/features/settings/theme_option_sheets.dart @@ -3,15 +3,15 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/theme/theme.dart'; import '../../shared/widgets/modal_presentation.dart'; const appearanceModeOptions = <({ThemeMode mode, String label, IconData icon})>[ - (mode: ThemeMode.light, label: 'Light', icon: LucideIcons.sun), - (mode: ThemeMode.dark, label: 'Dark', icon: LucideIcons.moon), - (mode: ThemeMode.system, label: 'System', icon: LucideIcons.sunMoon), + (mode: ThemeMode.light, label: 'Light', icon: BuzzIcons.sun), + (mode: ThemeMode.dark, label: 'Dark', icon: BuzzIcons.moon), + (mode: ThemeMode.system, label: 'System', icon: BuzzIcons.sunMoon), ]; String appearanceModeLabel(ThemeMode mode) => diff --git a/mobile/lib/features/settings/theme_picker_page.dart b/mobile/lib/features/settings/theme_picker_page.dart index de229b7e5e..edeab2d30c 100644 --- a/mobile/lib/features/settings/theme_picker_page.dart +++ b/mobile/lib/features/settings/theme_picker_page.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../shared/community/community_icon_provider.dart'; import '../../shared/community/community_provider.dart'; diff --git a/mobile/lib/features/settings/theme_picker_page/theme_preview_sheet.dart b/mobile/lib/features/settings/theme_picker_page/theme_preview_sheet.dart index 4e0808939d..cb0d5f3ec9 100644 --- a/mobile/lib/features/settings/theme_picker_page/theme_preview_sheet.dart +++ b/mobile/lib/features/settings/theme_picker_page/theme_preview_sheet.dart @@ -437,7 +437,7 @@ class _ThemePreviewCloseButton extends StatelessWidget { borderRadius: BorderRadius.circular(Radii.dialog), ), ), - icon: const Icon(LucideIcons.x, size: 22), + icon: const Icon(BuzzIcons.x, size: 22), ), ); } @@ -558,9 +558,9 @@ class _AppearanceCycleAction extends StatelessWidget { final VoidCallback onTap; IconData get _icon => switch (mode) { - ThemeMode.light => LucideIcons.sun, - ThemeMode.dark => LucideIcons.moon, - ThemeMode.system => LucideIcons.sunMoon, + ThemeMode.light => BuzzIcons.sun, + ThemeMode.dark => BuzzIcons.moon, + ThemeMode.system => BuzzIcons.sunMoon, }; IosGlassNavigationIcon get _iosIcon => switch (mode) { diff --git a/mobile/lib/shared/reminders/remind_me_later_sheet.dart b/mobile/lib/shared/reminders/remind_me_later_sheet.dart index 2af11c27ef..0afcabf20d 100644 --- a/mobile/lib/shared/reminders/remind_me_later_sheet.dart +++ b/mobile/lib/shared/reminders/remind_me_later_sheet.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../theme/theme.dart'; import '../widgets/sheet_action_section.dart'; @@ -61,7 +61,7 @@ void showRemindMeLaterSheet({ children: [ for (final preset in reminderTimePresets) ListTile( - leading: const Icon(LucideIcons.clock), + leading: const Icon(BuzzIcons.clock), title: Text(preset.label), onTap: () { Navigator.of(sheetContext).pop(); @@ -73,7 +73,7 @@ void showRemindMeLaterSheet({ SheetActionSection( children: [ ListTile( - leading: const Icon(LucideIcons.calendarClock), + leading: const Icon(BuzzIcons.calendarClock), title: const Text('Pick a date & time'), onTap: () async { final navigator = Navigator.of(sheetContext); diff --git a/mobile/lib/shared/theme/buzz_icons.dart b/mobile/lib/shared/theme/buzz_icons.dart new file mode 100644 index 0000000000..ed22c9b5f3 --- /dev/null +++ b/mobile/lib/shared/theme/buzz_icons.dart @@ -0,0 +1,412 @@ +import 'package:flutter/widgets.dart'; + +/// Tabler 3.46.0 icons for the mobile icon preview. +/// +/// Semantic names preserve existing call sites; artwork matches buzz-app. +/// Native iOS controls continue to use their platform symbols. +abstract final class BuzzIcons { + /// Tabler `text-size`. + static const aLargeSmall = IconData(0xf2b1, fontFamily: 'BuzzTabler'); + + /// Tabler `activity`. + static const activity = IconData(0xed23, fontFamily: 'BuzzTabler'); + + /// Tabler `archive`. + static const archive = IconData(0xea0b, fontFamily: 'BuzzTabler'); + + /// Tabler `restore`. + static const archiveRestore = IconData(0xfafd, fontFamily: 'BuzzTabler'); + + /// Tabler `arrow-down`. + static const arrowDown = IconData(0xea16, fontFamily: 'BuzzTabler'); + + /// Tabler `arrow-left`. + static const arrowLeft = IconData(0xea19, fontFamily: 'BuzzTabler'); + + /// Tabler `arrows-exchange`. + static const arrowLeftRight = IconData(0xf1f4, fontFamily: 'BuzzTabler'); + + /// Tabler `arrow-up`. + static const arrowUp = IconData(0xea25, fontFamily: 'BuzzTabler'); + + /// Tabler `arrows-sort`. + static const arrowUpDown = IconData(0xeb5a, fontFamily: 'BuzzTabler'); + + /// Tabler `at`. + static const atSign = IconData(0xea2b, fontFamily: 'BuzzTabler'); + + /// Tabler `bell`. + static const bell = IconData(0xea35, fontFamily: 'BuzzTabler'); + + /// Tabler `bell-off`. + static const bellOff = IconData(0xece9, fontFamily: 'BuzzTabler'); + + /// Tabler `bell-ringing`. + static const bellRing = IconData(0xed07, fontFamily: 'BuzzTabler'); + + /// Tabler `bold`. + static const bold = IconData(0xeb7b, fontFamily: 'BuzzTabler'); + + /// Tabler `robot`. + static const bot = IconData(0xf00b, fontFamily: 'BuzzTabler'); + + /// Tabler `brain`. + static const brain = IconData(0xf59f, fontFamily: 'BuzzTabler'); + + /// Tabler `calendar-time`. + static const calendarClock = IconData(0xee21, fontFamily: 'BuzzTabler'); + + /// Tabler `camera`. + static const camera = IconData(0xea54, fontFamily: 'BuzzTabler'); + + /// Tabler `camera-off`. + static const cameraOff = IconData(0xecee, fontFamily: 'BuzzTabler'); + + /// Tabler `check`. + static const check = IconData(0xea5e, fontFamily: 'BuzzTabler'); + + /// Tabler `checks`. + static const checkCheck = IconData(0xebaa, fontFamily: 'BuzzTabler'); + + /// Tabler `chevron-down`. + static const chevronDown = IconData(0xea5f, fontFamily: 'BuzzTabler'); + + /// Tabler `chevron-left`. + static const chevronLeft = IconData(0xea60, fontFamily: 'BuzzTabler'); + + /// Tabler `chevron-right`. + static const chevronRight = IconData(0xea61, fontFamily: 'BuzzTabler'); + + /// Tabler `chevron-up`. + static const chevronUp = IconData(0xea62, fontFamily: 'BuzzTabler'); + + /// Tabler `circle`. + static const circle = IconData(0xea6b, fontFamily: 'BuzzTabler'); + + /// Tabler `alert-circle`. + static const circleAlert = IconData(0xea05, fontFamily: 'BuzzTabler'); + + /// Tabler `circle-check`. + static const circleCheck = IconData(0xea67, fontFamily: 'BuzzTabler'); + + /// Tabler `circle-dashed`. + static const circleDashed = IconData(0xed27, fontFamily: 'BuzzTabler'); + + /// Tabler `circle-dot`. + static const circleDot = IconData(0xefb1, fontFamily: 'BuzzTabler'); + + /// Tabler `circle-x`. + static const circleX = IconData(0xea6a, fontFamily: 'BuzzTabler'); + + /// Tabler `clock`. + static const clock = IconData(0xea70, fontFamily: 'BuzzTabler'); + + /// Tabler `clock-hour-3`. + static const clock3 = IconData(0xf318, fontFamily: 'BuzzTabler'); + + /// Tabler `hourglass`: a channel with a limited lifetime. + static const clockFading = IconData(0xef93, fontFamily: 'BuzzTabler'); + + /// Tabler `code`. + static const code = IconData(0xea77, fontFamily: 'BuzzTabler'); + + /// Tabler `coffee`. + static const coffee = IconData(0xef0e, fontFamily: 'BuzzTabler'); + + /// Tabler `compass`. + static const compass = IconData(0xea79, fontFamily: 'BuzzTabler'); + + /// Tabler `copy`. + static const copy = IconData(0xea7a, fontFamily: 'BuzzTabler'); + + /// Tabler `download`. + static const download = IconData(0xea96, fontFamily: 'BuzzTabler'); + + /// Tabler `dots`. + static const ellipsis = IconData(0xea95, fontFamily: 'BuzzTabler'); + + /// Tabler `dots-vertical`. + static const ellipsisVertical = IconData(0xea94, fontFamily: 'BuzzTabler'); + + /// Tabler `external-link`. + static const externalLink = IconData(0xea99, fontFamily: 'BuzzTabler'); + + /// Tabler `file`. + static const file = IconData(0xeaa4, fontFamily: 'BuzzTabler'); + + /// Tabler `file-pencil`. + static const filePen = IconData(0xf039, fontFamily: 'BuzzTabler'); + + /// Tabler `file-text`. + static const fileText = IconData(0xeaa2, fontFamily: 'BuzzTabler'); + + /// Tabler `fingerprint`. + static const fingerprint = IconData(0xebd1, fontFamily: 'BuzzTabler'); + + /// Tabler `flag`. + static const flag = IconData(0xeaa6, fontFamily: 'BuzzTabler'); + + /// Tabler `folder`. + static const folder = IconData(0xeaad, fontFamily: 'BuzzTabler'); + + /// Tabler `folder-code`. + static const folderGit2 = IconData(0xf90f, fontFamily: 'BuzzTabler'); + + /// Tabler `folder-symlink`. + static const folderInput = IconData(0xf91b, fontFamily: 'BuzzTabler'); + + /// Tabler `folder-minus`. + static const folderMinus = IconData(0xeaaa, fontFamily: 'BuzzTabler'); + + /// Tabler `folder-plus`. + static const folderPlus = IconData(0xeaab, fontFamily: 'BuzzTabler'); + + /// Tabler `carousel-horizontal`. + static const galleryThumbnails = IconData(0xf659, fontFamily: 'BuzzTabler'); + + /// Tabler `git-pull-request`. + static const gitPullRequest = IconData(0xeab6, fontFamily: 'BuzzTabler'); + + /// Tabler `hash`. + static const hash = IconData(0xeabc, fontFamily: 'BuzzTabler'); + + /// Tabler `headphones-off`. + static const headphoneOff = IconData(0xed1d, fontFamily: 'BuzzTabler'); + + /// Tabler `headphones`. + static const headphones = IconData(0xeabd, fontFamily: 'BuzzTabler'); + + /// Tabler `heart`. + static const heart = IconData(0xeabe, fontFamily: 'BuzzTabler'); + + /// Tabler `home`. + static const house300 = IconData(0xeac1, fontFamily: 'BuzzTabler'); + + /// Tabler `home`. + static const house500 = IconData(0xeac1, fontFamily: 'BuzzTabler'); + + /// Tabler `photo`. + static const image = IconData(0xeb0a, fontFamily: 'BuzzTabler'); + + /// Tabler `photo-off`. + static const imageOff = IconData(0xecf6, fontFamily: 'BuzzTabler'); + + /// Tabler `library-photo`. + static const images = IconData(0xfd4a, fontFamily: 'BuzzTabler'); + + /// Tabler `inbox`. + static const inbox300 = IconData(0xeac4, fontFamily: 'BuzzTabler'); + + /// Tabler `inbox`. + static const inbox500 = IconData(0xeac4, fontFamily: 'BuzzTabler'); + + /// Tabler `italic`. + static const italic = IconData(0xeb93, fontFamily: 'BuzzTabler'); + + /// Tabler `key`. + static const key = IconData(0xeac7, fontFamily: 'BuzzTabler'); + + /// Tabler `layout-grid`. + static const layoutGrid = IconData(0xedba, fontFamily: 'BuzzTabler'); + + /// Tabler `leaf`. + static const leaf = IconData(0xed4f, fontFamily: 'BuzzTabler'); + + /// Tabler `bulb`. + static const lightbulb = IconData(0xea51, fontFamily: 'BuzzTabler'); + + /// Tabler `link`. + static const link = IconData(0xeade, fontFamily: 'BuzzTabler'); + + /// Tabler `link`. + static const link2 = IconData(0xeade, fontFamily: 'BuzzTabler'); + + /// Tabler `loader-2`. + static const loaderCircle = IconData(0xf226, fontFamily: 'BuzzTabler'); + + /// Tabler `lock`. + static const lock = IconData(0xeae2, fontFamily: 'BuzzTabler'); + + /// Tabler `login`. + static const logIn = IconData(0xeba7, fontFamily: 'BuzzTabler'); + + /// Tabler `logout`. + static const logOut = IconData(0xeba8, fontFamily: 'BuzzTabler'); + + /// Tabler `mail`. + static const mail = IconData(0xeae5, fontFamily: 'BuzzTabler'); + + /// Tabler `mail-check`. + static const mailCheck = IconData(0xf939, fontFamily: 'BuzzTabler'); + + /// Tabler `mail-opened`. + static const mailOpen = IconData(0xeae4, fontFamily: 'BuzzTabler'); + + /// Tabler `message-circle`. + static const messageCircle = IconData(0xeaed, fontFamily: 'BuzzTabler'); + + /// Tabler `message`. + static const messageSquare = IconData(0xeaef, fontFamily: 'BuzzTabler'); + + /// Tabler `message-reply`. + static const messageSquareReply = IconData(0xfd4d, fontFamily: 'BuzzTabler'); + + /// Tabler `message-2`. + static const messageSquareText = IconData(0xeaec, fontFamily: 'BuzzTabler'); + + /// Tabler `messages`. + static const messagesSquare = IconData(0xeb6c, fontFamily: 'BuzzTabler'); + + /// Tabler `microphone`. + static const mic = IconData(0xeaf0, fontFamily: 'BuzzTabler'); + + /// Tabler `microphone-off`. + static const micOff = IconData(0xed16, fontFamily: 'BuzzTabler'); + + /// Tabler `moon`. + static const moon = IconData(0xeaf8, fontFamily: 'BuzzTabler'); + + /// Tabler `palette`. + static const palette = IconData(0xeb01, fontFamily: 'BuzzTabler'); + + /// Tabler `player-pause`. + static const pause = IconData(0xed45, fontFamily: 'BuzzTabler'); + + /// Tabler `pencil`. + static const pencil = IconData(0xeb04, fontFamily: 'BuzzTabler'); + + /// Tabler `phone-off`. + static const phoneOff = IconData(0xecf5, fontFamily: 'BuzzTabler'); + + /// Tabler `plane`. + static const plane = IconData(0xeb6f, fontFamily: 'BuzzTabler'); + + /// Tabler `player-play`. + static const play = IconData(0xed46, fontFamily: 'BuzzTabler'); + + /// Tabler `plus`. + static const plus = IconData(0xeb0b, fontFamily: 'BuzzTabler'); + + /// Tabler `radio`. + static const radio = IconData(0xef2d, fontFamily: 'BuzzTabler'); + + /// Tabler `rotate`. + static const refreshCcw = IconData(0xeb16, fontFamily: 'BuzzTabler'); + + /// Tabler `rotate-clockwise`. + static const refreshCw = IconData(0xeb15, fontFamily: 'BuzzTabler'); + + /// Tabler `face-id`. + static const scanFace = IconData(0xea9b, fontFamily: 'BuzzTabler'); + + /// Tabler `scan`. + static const scanLine = IconData(0xebc8, fontFamily: 'BuzzTabler'); + + /// Tabler `search`. + static const search = IconData(0xeb1c, fontFamily: 'BuzzTabler'); + + /// Tabler `search`. + static const search300 = IconData(0xeb1c, fontFamily: 'BuzzTabler'); + + /// Tabler `search`. + static const search500 = IconData(0xeb1c, fontFamily: 'BuzzTabler'); + + /// Tabler `search-off`. + static const searchX = IconData(0xf19c, fontFamily: 'BuzzTabler'); + + /// Tabler `settings`. + static const settings = IconData(0xeb20, fontFamily: 'BuzzTabler'); + + /// Tabler `share`. + static const share = IconData(0xeb21, fontFamily: 'BuzzTabler'); + + /// Tabler `share`. + static const share2 = IconData(0xeb21, fontFamily: 'BuzzTabler'); + + /// Tabler `shield`. + static const shield = IconData(0xeb24, fontFamily: 'BuzzTabler'); + + /// Tabler `shield-exclamation`. + static const shieldAlert = IconData(0xf9c6, fontFamily: 'BuzzTabler'); + + /// Tabler `shield-check`. + static const shieldCheck = IconData(0xeb22, fontFamily: 'BuzzTabler'); + + /// Tabler `mood-smile`. + static const smile = IconData(0xeaf7, fontFamily: 'BuzzTabler'); + + /// Tabler `mood-plus`. + static const smilePlus = IconData(0xf7b9, fontFamily: 'BuzzTabler'); + + /// Tabler `sparkles`. + static const sparkles = IconData(0xf6d7, fontFamily: 'BuzzTabler'); + + /// Tabler `square`. + static const square = IconData(0xeb2c, fontFamily: 'BuzzTabler'); + + /// Tabler `code-dots`. + static const squareCode = IconData(0xf61a, fontFamily: 'BuzzTabler'); + + /// Tabler `star`. + static const star = IconData(0xeb2e, fontFamily: 'BuzzTabler'); + + /// Tabler `star-off`. + static const starOff = IconData(0xed62, fontFamily: 'BuzzTabler'); + + /// Tabler `strikethrough`. + static const strikethrough = IconData(0xeb9e, fontFamily: 'BuzzTabler'); + + /// Tabler `sun`. + static const sun = IconData(0xeb30, fontFamily: 'BuzzTabler'); + + /// Tabler `sun-moon`. + static const sunMoon = IconData(0xf4a3, fontFamily: 'BuzzTabler'); + + /// Tabler `camera-rotate`. + static const switchCamera = IconData(0xee22, fontFamily: 'BuzzTabler'); + + /// Tabler `trash`. + static const trash2 = IconData(0xeb41, fontFamily: 'BuzzTabler'); + + /// Tabler `alert-triangle`. + static const triangleAlert = IconData(0xea06, fontFamily: 'BuzzTabler'); + + /// Tabler `user`. + static const user = IconData(0xeb4d, fontFamily: 'BuzzTabler'); + + /// Tabler `user-minus`. + static const userMinus = IconData(0xeb4a, fontFamily: 'BuzzTabler'); + + /// Tabler `user-plus`. + static const userPlus = IconData(0xeb4b, fontFamily: 'BuzzTabler'); + + /// Tabler `user`. + static const userRound = IconData(0xeb4d, fontFamily: 'BuzzTabler'); + + /// Tabler `users`. + static const users = IconData(0xebf2, fontFamily: 'BuzzTabler'); + + /// Tabler `video`. + static const video = IconData(0xed22, fontFamily: 'BuzzTabler'); + + /// Tabler `video-off`. + static const videoOff = IconData(0xed20, fontFamily: 'BuzzTabler'); + + /// Tabler `ball-volleyball`. + static const volleyball = IconData(0xec2b, fontFamily: 'BuzzTabler'); + + /// Tabler `volume`. + static const volume2 = IconData(0xeb51, fontFamily: 'BuzzTabler'); + + /// Tabler `volume-off`. + static const volumeX = IconData(0xf1c3, fontFamily: 'BuzzTabler'); + + /// Tabler `wifi-off`. + static const wifiOff = IconData(0xecfa, fontFamily: 'BuzzTabler'); + + /// Tabler `tool`. + static const wrench = IconData(0xeb40, fontFamily: 'BuzzTabler'); + + /// Tabler `x`. + static const x = IconData(0xeb55, fontFamily: 'BuzzTabler'); +} diff --git a/mobile/lib/shared/widgets/buzz_search_field.dart b/mobile/lib/shared/widgets/buzz_search_field.dart index d6e5530a17..f0c0b31c73 100644 --- a/mobile/lib/shared/widgets/buzz_search_field.dart +++ b/mobile/lib/shared/widgets/buzz_search_field.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../theme/theme.dart'; @@ -158,7 +158,7 @@ class BuzzSearchField extends StatelessWidget { ? _searchCompactIconSize / _searchIdleIconSize : 1, child: Icon( - LucideIcons.search, + BuzzIcons.search, key: const Key('search-moving-icon'), size: _searchIdleIconSize, color: iconColor, diff --git a/mobile/lib/shared/widgets/buzz_sheet_header.dart b/mobile/lib/shared/widgets/buzz_sheet_header.dart index 22814b5ae6..e51f6973cd 100644 --- a/mobile/lib/shared/widgets/buzz_sheet_header.dart +++ b/mobile/lib/shared/widgets/buzz_sheet_header.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../theme/theme.dart'; import 'buzz_navigation_metrics.dart'; @@ -107,7 +107,7 @@ class _SheetCloseButton extends StatelessWidget { borderRadius: BorderRadius.circular(Radii.dialog), ), ), - icon: const Icon(LucideIcons.x, size: 22), + icon: const Icon(BuzzIcons.x, size: 22), ), ); } diff --git a/mobile/lib/shared/widgets/frosted_app_bar.dart b/mobile/lib/shared/widgets/frosted_app_bar.dart index 3dc04eed5d..6932adf046 100644 --- a/mobile/lib/shared/widgets/frosted_app_bar.dart +++ b/mobile/lib/shared/widgets/frosted_app_bar.dart @@ -2,7 +2,7 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../theme/theme.dart'; import 'buzz_navigation_metrics.dart'; @@ -368,7 +368,7 @@ class FrostedAppBar extends StatelessWidget { child: IconButton( onPressed: () => Navigator.of(context).pop(), color: effectiveIconColor, - icon: const Icon(LucideIcons.chevronLeft), + icon: const Icon(BuzzIcons.chevronLeft), tooltip: 'Back', ), ) @@ -625,11 +625,11 @@ IosNavigationAction? _nativeAction(Widget? widget) { } if (widget is IconButton) { final icon = widget.icon is Icon ? (widget.icon as Icon).icon : null; - final symbol = icon == LucideIcons.x + final symbol = icon == BuzzIcons.x ? 'xmark' - : icon == LucideIcons.chevronLeft || icon == LucideIcons.arrowLeft + : icon == BuzzIcons.chevronLeft || icon == BuzzIcons.arrowLeft ? 'chevron.backward' - : icon == LucideIcons.users + : icon == BuzzIcons.users ? 'person.2' : 'ellipsis'; return IosNavigationAction( diff --git a/mobile/lib/shared/widgets/load_error_view.dart b/mobile/lib/shared/widgets/load_error_view.dart index 50952e3cb8..806b880c1a 100644 --- a/mobile/lib/shared/widgets/load_error_view.dart +++ b/mobile/lib/shared/widgets/load_error_view.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../theme/theme.dart'; @@ -22,7 +22,7 @@ class LoadErrorView extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Icon( - LucideIcons.triangleAlert, + BuzzIcons.triangleAlert, size: Grid.lg, color: context.colors.error, ), @@ -37,7 +37,7 @@ class LoadErrorView extends StatelessWidget { FilledButton.icon( key: const ValueKey('load-error-retry'), onPressed: onRetry, - icon: const Icon(LucideIcons.refreshCcw, size: 16), + icon: const Icon(BuzzIcons.refreshCcw, size: 16), label: const Text('Retry'), ), ], diff --git a/mobile/lib/shared/widgets/lucide_star_icon.dart b/mobile/lib/shared/widgets/lucide_star_icon.dart deleted file mode 100644 index 5d6bf3b20d..0000000000 --- a/mobile/lib/shared/widgets/lucide_star_icon.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'dart:math' as math; - -import 'package:flutter/material.dart'; - -/// A Lucide-shaped star that can fill without changing its geometry. -class LucideStarIcon extends StatelessWidget { - /// Creates a Lucide star using [color], optionally filled. - const LucideStarIcon({ - super.key, - required this.color, - this.filled = false, - this.size = 22, - }); - - /// Color of the star's stroke or fill. - final Color color; - - /// Whether to paint the star filled instead of outlined. - final bool filled; - - /// Width and height of the square icon canvas. - final double size; - - @override - Widget build(BuildContext context) => CustomPaint( - size: Size.square(size), - painter: _LucideStarPainter(color: color, filled: filled), - ); -} - -class _LucideStarPainter extends CustomPainter { - const _LucideStarPainter({required this.color, required this.filled}); - - final Color color; - final bool filled; - - @override - void paint(Canvas canvas, Size size) { - final scale = math.min(size.width, size.height) / 24; - final path = Path() - ..moveTo(12 * scale, 2 * scale) - ..lineTo(15.09 * scale, 8.26 * scale) - ..lineTo(22 * scale, 9.27 * scale) - ..lineTo(17 * scale, 14.14 * scale) - ..lineTo(18.18 * scale, 21.02 * scale) - ..lineTo(12 * scale, 17.77 * scale) - ..lineTo(5.82 * scale, 21.02 * scale) - ..lineTo(7 * scale, 14.14 * scale) - ..lineTo(2 * scale, 9.27 * scale) - ..lineTo(8.91 * scale, 8.26 * scale) - ..close(); - - canvas.drawPath( - path, - Paint() - ..color = color - ..style = filled ? PaintingStyle.fill : PaintingStyle.stroke - ..strokeWidth = 2 * scale - ..strokeCap = StrokeCap.round - ..strokeJoin = StrokeJoin.round, - ); - } - - @override - bool shouldRepaint(_LucideStarPainter oldDelegate) => - color != oldDelegate.color || filled != oldDelegate.filled; -} diff --git a/mobile/lib/shared/widgets/tabler_star_icon.dart b/mobile/lib/shared/widgets/tabler_star_icon.dart new file mode 100644 index 0000000000..f33f787de1 --- /dev/null +++ b/mobile/lib/shared/widgets/tabler_star_icon.dart @@ -0,0 +1,69 @@ +import 'dart:math' as math; + +import 'package:flutter/material.dart'; + +/// A Tabler-shaped star that can fill without changing its geometry. +class TablerStarIcon extends StatelessWidget { + /// Creates a Tabler star using [color], optionally filled. + const TablerStarIcon({ + super.key, + required this.color, + this.filled = false, + this.size = 22, + }); + + /// Color of the star's stroke or fill. + final Color color; + + /// Whether to paint the star filled instead of outlined. + final bool filled; + + /// Width and height of the square icon canvas. + final double size; + + @override + Widget build(BuildContext context) => CustomPaint( + size: Size.square(size), + painter: _TablerStarPainter(color: color, filled: filled), + ); +} + +class _TablerStarPainter extends CustomPainter { + const _TablerStarPainter({required this.color, required this.filled}); + + final Color color; + final bool filled; + + @override + void paint(Canvas canvas, Size size) { + final scale = math.min(size.width, size.height) / 24; + // Tabler 3.46.0 outline/star.svg, shared by both Star action surfaces. + final path = Path() + ..moveTo(12 * scale, 17.75 * scale) + ..relativeLineTo(-6.172 * scale, 3.245 * scale) + ..relativeLineTo(1.179 * scale, -6.873 * scale) + ..relativeLineTo(-5 * scale, -4.867 * scale) + ..relativeLineTo(6.9 * scale, -1 * scale) + ..relativeLineTo(3.086 * scale, -6.253 * scale) + ..relativeLineTo(3.086 * scale, 6.253 * scale) + ..relativeLineTo(6.9 * scale, 1 * scale) + ..relativeLineTo(-5 * scale, 4.867 * scale) + ..relativeLineTo(1.179 * scale, 6.873 * scale) + ..relativeLineTo(-6.158 * scale, -3.245 * scale) + ..close(); + + canvas.drawPath( + path, + Paint() + ..color = color + ..style = filled ? PaintingStyle.fill : PaintingStyle.stroke + ..strokeWidth = 2 * scale + ..strokeCap = StrokeCap.round + ..strokeJoin = StrokeJoin.round, + ); + } + + @override + bool shouldRepaint(_TablerStarPainter oldDelegate) => + color != oldDelegate.color || filled != oldDelegate.filled; +} diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 023e9666fa..613684a9bf 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -904,14 +904,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - lucide_icons_flutter: - dependency: "direct main" - description: - name: lucide_icons_flutter - sha256: f9fd5d49b93bf14b89e0ff4818658a74ab16899bdaf7aa745358ee1a34f54eed - url: "https://pub.dev" - source: hosted - version: "3.1.14+1" matcher: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 92ddca8fb5..2e09552ae8 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -16,7 +16,6 @@ dependencies: characters: ^1.4.0 hooks_riverpod: ^3.0.3 flutter_hooks: ^0.21.3 - lucide_icons_flutter: ^3.1.0 http: ^1.4.0 flutter_secure_storage: ^10.0.0 flutter_svg: ^2.2.4 @@ -76,6 +75,9 @@ flutter: # desktop uses. Do not hand-edit. - assets/emoji/emoji-data.json fonts: + - family: BuzzTabler + fonts: + - asset: assets/fonts/TablerIcons.ttf - family: Inter fonts: - asset: assets/fonts/InterVariable.ttf diff --git a/mobile/test/features/activity/activity_page_test.dart b/mobile/test/features/activity/activity_page_test.dart index 910300b741..7995192167 100644 --- a/mobile/test/features/activity/activity_page_test.dart +++ b/mobile/test/features/activity/activity_page_test.dart @@ -26,7 +26,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/misc.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() { @@ -966,7 +966,7 @@ void main() { final action = find.byKey(const ValueKey('inbox-swipe-read-m1')); expect(action, findsOneWidget); expect( - find.descendant(of: action, matching: find.byIcon(LucideIcons.mail)), + find.descendant(of: action, matching: find.byIcon(BuzzIcons.mail)), findsOneWidget, ); expect(find.text('Mark unread'), findsNothing); diff --git a/mobile/test/features/channels/channel_detail_page_test.dart b/mobile/test/features/channels/channel_detail_page_test.dart index 91de39ee5b..692e518eef 100644 --- a/mobile/test/features/channels/channel_detail_page_test.dart +++ b/mobile/test/features/channels/channel_detail_page_test.dart @@ -21,7 +21,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:http/http.dart' as http; import 'package:http/testing.dart' as http_testing; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; import 'package:pointycastle/digests/sha256.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; @@ -70,7 +70,7 @@ import 'package:buzz/shared/widgets/frosted_app_bar.dart'; import 'package:buzz/shared/widgets/frosted_scaffold.dart'; import 'package:buzz/shared/widgets/flapping_bee.dart'; import 'package:buzz/shared/widgets/keyboard_dismiss_on_drag.dart'; -import 'package:buzz/shared/widgets/lucide_star_icon.dart'; +import 'package:buzz/shared/widgets/tabler_star_icon.dart'; import 'package:buzz/shared/widgets/skeleton.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -2267,7 +2267,7 @@ void main() { expect( find.descendant( of: aliceRow, - matching: find.byIcon(LucideIcons.chevronRight), + matching: find.byIcon(BuzzIcons.chevronRight), ), findsOneWidget, ); @@ -2449,16 +2449,16 @@ void main() { const ValueKey('channel-details-mute-action'), ); expect(find.text('Star'), findsOneWidget); - var star = tester.widget(find.byType(LucideStarIcon)); + var star = tester.widget(find.byType(TablerStarIcon)); expect(star.filled, isFalse); expect(find.text('Mute'), findsOneWidget); - expect(find.byIcon(LucideIcons.bellOff), findsOneWidget); + expect(find.byIcon(BuzzIcons.bellOff), findsOneWidget); await tester.tap(starAction); await tester.pump(); expect(find.text('Unstar'), findsOneWidget); - star = tester.widget(find.byType(LucideStarIcon)); + star = tester.widget(find.byType(TablerStarIcon)); expect(star.filled, isTrue); expect(star.color, AppTheme.light().colorScheme.primary); @@ -2466,7 +2466,7 @@ void main() { await tester.pump(); expect(find.text('Unmute'), findsOneWidget); - final activeBell = tester.widget(find.byIcon(LucideIcons.bell)); + final activeBell = tester.widget(find.byIcon(BuzzIcons.bell)); expect(activeBell.color, AppTheme.light().colorScheme.primary); await tester.tap(starAction); @@ -2475,9 +2475,9 @@ void main() { expect(find.text('Star'), findsOneWidget); expect(find.text('Mute'), findsOneWidget); - star = tester.widget(find.byType(LucideStarIcon)); + star = tester.widget(find.byType(TablerStarIcon)); expect(star.filled, isFalse); - expect(find.byIcon(LucideIcons.bellOff), findsOneWidget); + expect(find.byIcon(BuzzIcons.bellOff), findsOneWidget); }, ); @@ -2599,10 +2599,7 @@ void main() { findsNothing, ); expect( - find.descendant( - of: seeAllRow, - matching: find.byIcon(LucideIcons.users), - ), + find.descendant(of: seeAllRow, matching: find.byIcon(BuzzIcons.users)), findsNothing, ); final firstMemberRow = previews.first; @@ -3943,7 +3940,7 @@ void main() { ), findsOneWidget, ); - expect(find.byIcon(LucideIcons.chevronRight), findsNothing); + expect(find.byIcon(BuzzIcons.chevronRight), findsNothing); final replyAvatars = find.byType(SmallAvatar); expect(replyAvatars, findsNWidgets(2)); for (final avatar in replyAvatars.evaluate()) { @@ -4119,7 +4116,7 @@ void main() { expect( find.descendant( of: unreadButton, - matching: find.byIcon(LucideIcons.chevronUp), + matching: find.byIcon(BuzzIcons.chevronUp), ), findsOneWidget, ); @@ -4147,7 +4144,7 @@ void main() { findsOneWidget, ); expect(find.text('Latest'), findsNothing); - expect(find.byIcon(LucideIcons.arrowDown), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowDown), findsOneWidget); expect(find.byTooltip('Jump to latest message'), findsOneWidget); }); @@ -5038,7 +5035,7 @@ void main() { ), ); expect(find.text('Latest'), findsNothing); - expect(find.byIcon(LucideIcons.arrowDown), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowDown), findsOneWidget); for (final container in tester.widgetList( find.descendant( of: find.byKey(const ValueKey('channel-jump-to-latest')), @@ -6010,7 +6007,7 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('huddle-retry')), - matching: find.byIcon(LucideIcons.refreshCw), + matching: find.byIcon(BuzzIcons.refreshCw), ), findsNothing, ); @@ -6070,7 +6067,7 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('huddle-retry')), - matching: find.byIcon(LucideIcons.settings), + matching: find.byIcon(BuzzIcons.settings), ), findsOneWidget, ); @@ -6124,11 +6121,11 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('channel-huddle-button')), - matching: find.byIcon(LucideIcons.headphones), + matching: find.byIcon(BuzzIcons.headphones), ), findsOneWidget, ); - expect(find.byIcon(LucideIcons.headphoneOff), findsNothing); + expect(find.byIcon(BuzzIcons.headphoneOff), findsNothing); }); testWidgets('failed admission cannot publish Huddle leave lifecycle', ( @@ -6817,7 +6814,7 @@ void main() { tester.getSize(find.byType(CircleAvatar).first), const Size.square(104), ); - expect(find.byIcon(LucideIcons.userRound), findsNWidgets(3)); + expect(find.byIcon(BuzzIcons.userRound), findsNWidgets(3)); await tester.tap( find.byKey(const ValueKey('huddle-participant-avatar-desktop')), ); @@ -6987,17 +6984,17 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('huddle-speaker-toggle')), - matching: find.byIcon(LucideIcons.volume2), + matching: find.byIcon(BuzzIcons.volume2), ), findsOneWidget, ); final speakerIcon = find.descendant( of: find.byKey(const ValueKey('huddle-speaker-toggle')), - matching: find.byIcon(LucideIcons.volume2), + matching: find.byIcon(BuzzIcons.volume2), ); final leaveIcon = find.descendant( of: find.byKey(const ValueKey('huddle-leave')), - matching: find.byIcon(LucideIcons.phoneOff), + matching: find.byIcon(BuzzIcons.phoneOff), ); expect(tester.widget(speakerIcon).size, 28); expect(tester.widget(leaveIcon).size, 28); @@ -7030,7 +7027,7 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('huddle-speaker-toggle')), - matching: find.byIcon(LucideIcons.volume2), + matching: find.byIcon(BuzzIcons.volume2), ), findsOneWidget, ); @@ -7064,7 +7061,7 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('huddle-mute-toggle')), - matching: find.byIcon(LucideIcons.mic), + matching: find.byIcon(BuzzIcons.mic), ), findsOneWidget, ); @@ -7073,7 +7070,7 @@ void main() { .widget( find.descendant( of: find.byKey(const ValueKey('huddle-mute-toggle')), - matching: find.byIcon(LucideIcons.mic), + matching: find.byIcon(BuzzIcons.mic), ), ) .size, @@ -7086,7 +7083,7 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('huddle-mute-toggle')), - matching: find.byIcon(LucideIcons.micOff), + matching: find.byIcon(BuzzIcons.micOff), ), findsOneWidget, ); @@ -7107,7 +7104,7 @@ void main() { final emojiIcon = find.descendant( of: find.byKey(const ValueKey('huddle-emoji-reactions')), - matching: find.byIcon(LucideIcons.smilePlus), + matching: find.byIcon(BuzzIcons.smilePlus), ); expect(emojiIcon, findsOneWidget); expect(tester.widget(emojiIcon).size, 28); @@ -7179,14 +7176,14 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('huddle-drawer-expand')), - matching: find.byIcon(LucideIcons.chevronUp), + matching: find.byIcon(BuzzIcons.chevronUp), ), findsOneWidget, ); expect( find.descendant( of: find.byKey(const ValueKey('huddle-drawer-mute-toggle')), - matching: find.byIcon(LucideIcons.micOff), + matching: find.byIcon(BuzzIcons.micOff), ), findsOneWidget, ); @@ -9613,7 +9610,7 @@ void main() { // Only the text message should render, unknown system event is skipped. expect(findRichText('Hello'), findsOneWidget); // No system message row rendered for unknown type. - expect(find.byIcon(LucideIcons.arrowLeftRight), findsNothing); + expect(find.byIcon(BuzzIcons.arrowLeftRight), findsNothing); }); }); @@ -9867,13 +9864,13 @@ void main() { await tester.pumpAndSettle(); expect(find.byType(TextField), findsNothing); - expect(find.byIcon(LucideIcons.arrowUp).hitTestable(), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowUp).hitTestable(), findsOneWidget); await tester.tap(find.text('Message #general')); await tester.pumpAndSettle(); expect(find.byType(TextField), findsOneWidget); - expect(find.byIcon(LucideIcons.arrowUp).hitTestable(), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowUp).hitTestable(), findsOneWidget); }); testWidgets('shows hint text', (tester) async { @@ -10802,7 +10799,7 @@ void main() { await tester.pumpAndSettle(); expect(find.text('secret'), findsOneWidget); - expect(find.byIcon(LucideIcons.lock), findsOneWidget); + expect(find.byIcon(BuzzIcons.lock), findsOneWidget); }); }); @@ -15058,7 +15055,7 @@ void main() { expect( find.descendant( of: find.byKey(const ValueKey('thread-jump-to-latest')), - matching: find.byIcon(LucideIcons.arrowDown), + matching: find.byIcon(BuzzIcons.arrowDown), ), findsOneWidget, ); diff --git a/mobile/test/features/channels/channels_page_test.dart b/mobile/test/features/channels/channels_page_test.dart index ec884e6301..1a543e3fd1 100644 --- a/mobile/test/features/channels/channels_page_test.dart +++ b/mobile/test/features/channels/channels_page_test.dart @@ -20,7 +20,7 @@ import 'package:hooks_riverpod/misc.dart'; import 'package:buzz/features/channels/channel_stars/channel_stars_provider.dart'; import 'package:buzz/features/channels/channel_mutes/channel_mutes_provider.dart'; import 'package:buzz/features/channels/channel_sort/channel_sort_provider.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:buzz/features/channels/channel.dart'; import 'package:buzz/features/channels/channel_management_provider.dart'; import 'package:buzz/features/channels/channel_sections/channel_sections_provider.dart'; @@ -57,8 +57,7 @@ void main() { if (Platform.environment.containsKey('COMMUNITY_SCREENSHOTS')) { for (final font in { 'Inter': 'assets/fonts/InterVariable.ttf', - 'packages/lucide_icons_flutter/Lucide': - 'packages/lucide_icons_flutter/assets/lucide.ttf', + 'BuzzTabler': 'assets/fonts/TablerIcons.ttf', }.entries) { await (FontLoader( font.key, @@ -290,8 +289,8 @@ void main() { expect(find.text('Community'), findsOneWidget); expect(find.byTooltip('Create or start conversation'), findsOneWidget); expect(find.byTooltip('Channels options'), findsOneWidget); - expect(find.byIcon(LucideIcons.ellipsisVertical), findsWidgets); - expect(find.byIcon(LucideIcons.arrowUpDown), findsNothing); + expect(find.byIcon(BuzzIcons.ellipsisVertical), findsWidgets); + expect(find.byIcon(BuzzIcons.arrowUpDown), findsNothing); expect(find.byTooltip('DMs options'), findsOneWidget); // DM identity display: the unnamed counterpart tile renders its @@ -775,10 +774,10 @@ void main() { ); } for (final icon in [ - LucideIcons.pencil, - LucideIcons.arrowUp, - LucideIcons.arrowDown, - LucideIcons.trash2, + BuzzIcons.pencil, + BuzzIcons.arrowUp, + BuzzIcons.arrowDown, + BuzzIcons.trash2, ]) { expect( find.descendant(of: popover, matching: find.byIcon(icon)), @@ -814,7 +813,7 @@ void main() { final error = Theme.of(tester.element(popover)).colorScheme.error; final deleteText = tester.widget(find.text('Delete section')); final deleteIcon = tester.widget( - find.descendant(of: popover, matching: find.byIcon(LucideIcons.trash2)), + find.descendant(of: popover, matching: find.byIcon(BuzzIcons.trash2)), ); expect(deleteText.style?.color, error); expect(deleteIcon.color, error); @@ -1482,12 +1481,12 @@ void main() { expect( find.descendant( of: options, - matching: find.byIcon(LucideIcons.ellipsisVertical), + matching: find.byIcon(BuzzIcons.ellipsisVertical), ), findsNothing, ); expect(find.text('Edit'), findsOneWidget); - expect(find.byIcon(LucideIcons.trash2), findsNothing); + expect(find.byIcon(BuzzIcons.trash2), findsNothing); expect( tester.getSize(find.byKey(const Key('community-switcher-avatar-alpha'))), const Size.square(88), @@ -1526,14 +1525,14 @@ void main() { expect( find.descendant( of: activeSelection, - matching: find.byIcon(LucideIcons.check), + matching: find.byIcon(BuzzIcons.check), ), findsOneWidget, ); expect( find.descendant( of: inactiveSelection, - matching: find.byIcon(LucideIcons.check), + matching: find.byIcon(BuzzIcons.check), ), findsNothing, ); @@ -1548,7 +1547,7 @@ void main() { await tester.pumpAndSettle(); expect(find.text('Done'), findsOneWidget); - expect(find.byIcon(LucideIcons.trash2), findsNWidgets(2)); + expect(find.byIcon(BuzzIcons.trash2), findsNWidgets(2)); expect(activeSelection, findsNothing); expect(inactiveSelection, findsNothing); @@ -1698,7 +1697,7 @@ void main() { .transform .storage[0]; expect(opacity(), 0); - expect(find.byIcon(LucideIcons.check), findsOneWidget); + expect(find.byIcon(BuzzIcons.check), findsOneWidget); await tester.tap(find.text('Edit')); await tester.pump(); await tester.pump(const Duration(milliseconds: 100)); @@ -1714,14 +1713,14 @@ void main() { await tester.pumpAndSettle(); expect(tester.getCenter(badge), center); expect(opacity(), 0); - expect(find.byIcon(LucideIcons.check), findsOneWidget); - expect(find.byIcon(LucideIcons.trash2), findsNothing); + expect(find.byIcon(BuzzIcons.check), findsOneWidget); + expect(find.byIcon(BuzzIcons.trash2), findsNothing); await tester.tap(find.text('Edit')); await tester.pumpAndSettle(); expect(tester.getCenter(badge), center); expect(opacity(), 1); expect(scale(), 1); - expect(find.byIcon(LucideIcons.trash2), findsNWidgets(2)); + expect(find.byIcon(BuzzIcons.trash2), findsNWidgets(2)); expect(tester.takeException(), isNull); }, ); @@ -1761,7 +1760,7 @@ void main() { await tester.tap(find.text('Edit')); await tester.pump(); - expect(find.byIcon(LucideIcons.trash2), findsOneWidget); + expect(find.byIcon(BuzzIcons.trash2), findsOneWidget); expect( tester.getSize(find.byKey(const Key('community-switcher-badge-alpha'))), const Size.square(36), @@ -2079,7 +2078,7 @@ void main() { expect( find.descendant( of: find.byKey(Key('community-switcher-selection-$id')), - matching: find.byIcon(LucideIcons.check), + matching: find.byIcon(BuzzIcons.check), ), id == 'alpha' ? findsOneWidget : findsNothing, ); @@ -3093,7 +3092,7 @@ void main() { 16, ); expect( - find.descendant(of: aliceChip, matching: find.byIcon(LucideIcons.x)), + find.descendant(of: aliceChip, matching: find.byIcon(BuzzIcons.x)), findsNothing, ); expect(find.bySemanticsLabel('Remove Alice'), findsOneWidget); diff --git a/mobile/test/features/channels/compose_bar_test.dart b/mobile/test/features/channels/compose_bar_test.dart index 94b4c8739d..38c896be48 100644 --- a/mobile/test/features/channels/compose_bar_test.dart +++ b/mobile/test/features/channels/compose_bar_test.dart @@ -11,7 +11,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:http/http.dart' as http; import 'package:http/testing.dart' as http_testing; import 'package:image_picker/image_picker.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; import 'package:buzz/features/channels/channel.dart'; import 'package:buzz/features/channels/channel_management_provider.dart'; @@ -707,7 +707,7 @@ void main() { expect(find.byType(TextField), findsNothing); expect(find.byTooltip('Add attachment').hitTestable(), findsOneWidget); - expect(find.byIcon(LucideIcons.arrowUp).hitTestable(), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowUp).hitTestable(), findsOneWidget); expect(find.byKey(const ValueKey('composer-footer-gradient')), findsOne); final composerBackdrop = find.descendant( of: find.byKey(const ValueKey('composer-footer-gradient')), @@ -762,10 +762,10 @@ void main() { BorderRadius.circular(Radii.dialog), ); expect(find.byType(TextField), findsOneWidget); - expect(find.byIcon(LucideIcons.atSign), findsOneWidget); - expect(find.byIcon(LucideIcons.hash), findsOneWidget); - expect(find.byIcon(LucideIcons.smilePlus), findsOneWidget); - expect(find.byIcon(LucideIcons.aLargeSmall), findsOneWidget); + expect(find.byIcon(BuzzIcons.atSign), findsOneWidget); + expect(find.byIcon(BuzzIcons.hash), findsOneWidget); + expect(find.byIcon(BuzzIcons.smilePlus), findsOneWidget); + expect(find.byIcon(BuzzIcons.aLargeSmall), findsOneWidget); }); testWidgets('notifies focus intent before attaching the focused field', ( @@ -1133,7 +1133,7 @@ void main() { final sendButton = find .ancestor( - of: find.byIcon(LucideIcons.arrowUp), + of: find.byIcon(BuzzIcons.arrowUp), matching: find.byType(IconButton), ) .hitTestable(); @@ -1160,7 +1160,7 @@ void main() { await _expandComposer(tester); await tester.enterText(find.byType(TextField), 'hello'); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); for (var i = 0; i < 20; i++) { await tester.pump(const Duration(milliseconds: 20)); if (tester @@ -1197,7 +1197,7 @@ void main() { await _expandComposer(tester); await tester.enterText(find.byType(TextField), 'retry me'); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); for (var i = 0; i < 20; i++) { await tester.pump(const Duration(milliseconds: 20)); if (tester @@ -1236,7 +1236,7 @@ void main() { await _expandComposer(tester); await tester.enterText(find.byType(TextField), 'first draft'); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); for (var i = 0; i < 20; i++) { await tester.pump(const Duration(milliseconds: 20)); if (tester @@ -1466,9 +1466,9 @@ void main() { offset: 6, ); - await tester.tap(find.byIcon(LucideIcons.smilePlus)); + await tester.tap(find.byIcon(BuzzIcons.smilePlus)); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.sparkles)); + await tester.tap(find.byIcon(BuzzIcons.sparkles)); await tester.pump(); await tester.tap(find.byTooltip(':meow:')); await tester.pumpAndSettle(); @@ -1599,14 +1599,14 @@ void main() { await _expandComposer(tester); hapticCalls.clear(); - await tester.tap(find.byIcon(LucideIcons.atSign)); + await tester.tap(find.byIcon(BuzzIcons.atSign)); tester.widget(find.byType(TextField)).controller!.clear(); await tester.pump(); - await tester.tap(find.byIcon(LucideIcons.hash)); + await tester.tap(find.byIcon(BuzzIcons.hash)); await tester.pump(); - await tester.tap(find.byIcon(LucideIcons.aLargeSmall)); + await tester.tap(find.byIcon(BuzzIcons.aLargeSmall)); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.bold)); + await tester.tap(find.byIcon(BuzzIcons.bold)); await tester.pump(); await tester.tap(find.byTooltip('Close formatting')); await tester.pumpAndSettle(); @@ -1638,7 +1638,7 @@ void main() { ), ); await _expandComposer(tester); - await tester.tap(find.byIcon(LucideIcons.hash)); + await tester.tap(find.byIcon(BuzzIcons.hash)); await tester.pumpAndSettle(); final surface = find.byKey(const ValueKey('channel-suggestions-popover')); @@ -1704,7 +1704,7 @@ void main() { ); await _expandComposer(tester); - await tester.tap(find.byIcon(LucideIcons.atSign)); + await tester.tap(find.byIcon(BuzzIcons.atSign)); await tester.pump(); expect(pendingMembers.isCompleted, isFalse); @@ -2643,7 +2643,7 @@ void main() { expect(find.byTooltip('Remove attachment'), findsOneWidget); await _expandComposer(tester); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pump(); await tester.pumpAndSettle(); @@ -2714,7 +2714,7 @@ void main() { expect(find.byTooltip('Remove attachment'), findsNWidgets(2)); await _expandComposer(tester); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect( @@ -3203,7 +3203,7 @@ void main() { ); await _expandComposer(tester); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pump(); expect( @@ -3336,7 +3336,7 @@ void main() { await tester.tap(find.text('Helper Bot')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), 'hello @Helper Bot'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await _inviteOutside(tester); await tester.pumpAndSettle(); @@ -3469,7 +3469,7 @@ void main() { await tester.tap(find.text('Helper Bot')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), 'hello @Helper Bot'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await _inviteOutside(tester); await tester.pump(); @@ -3697,10 +3697,10 @@ void main() { ); await _expandComposer(tester); - await tester.tap(find.byIcon(LucideIcons.aLargeSmall)); + await tester.tap(find.byIcon(BuzzIcons.aLargeSmall)); await tester.pumpAndSettle(); - final boldFinder = find.byIcon(LucideIcons.bold); + final boldFinder = find.byIcon(BuzzIcons.bold); final boldIcon = tester.widget(boldFinder); final colors = tester.element(boldFinder).colors; expect(boldIcon.color, colors.primary); @@ -3784,7 +3784,7 @@ void main() { findsOneWidget, ); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(uploadedBytes, _pngBytes); @@ -4215,7 +4215,7 @@ void main() { await tester.pumpAndSettle(); await _expandComposer(tester); await tester.enterText(find.byType(TextField), 'Keep this draft'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(find.textContaining('upload failed'), findsOneWidget); @@ -4260,7 +4260,7 @@ void main() { await _openSystemPhotoPicker(tester); await tester.pumpAndSettle(); await _expandComposer(tester); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect( @@ -4369,13 +4369,13 @@ void main() { await tester.pumpAndSettle(); await tester.tap(find.text('Helper Bot')); await tester.pumpAndSettle(); - expect(find.byIcon(LucideIcons.bot), findsOneWidget); + expect(find.byIcon(BuzzIcons.bot), findsOneWidget); expect( find.byKey(const ValueKey('composer-agent-mention-chip')), findsOneWidget, ); await tester.enterText(find.byType(TextField), 'hello @Helper Bot'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await _inviteOutside(tester); await tester.pumpAndSettle(); @@ -4444,7 +4444,7 @@ void main() { await tester.tap(find.text('Helper Bot')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), 'hello @Helper Bot'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await _inviteOutside(tester); await tester.pump(); @@ -4554,7 +4554,7 @@ void main() { await tester.tap(find.text('Mary Jane')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), 'hello @Mary Jane'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); } @@ -4824,7 +4824,7 @@ void main() { await tester.tap(find.text('Helper Bot')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), 'hello @Helper Bot'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pump(); expect(didSend, isFalse); @@ -4900,7 +4900,7 @@ void main() { await tester.tap(find.text('Helper Bot')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), 'hello @Helper Bot'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await _inviteOutside(tester); await tester.pumpAndSettle(); @@ -4989,11 +4989,11 @@ void main() { await tester.tap(find.text('Video')); await tester.pumpAndSettle(); - expect(find.byIcon(LucideIcons.video), findsOneWidget); + expect(find.byIcon(BuzzIcons.video), findsOneWidget); final sendButton = find .ancestor( - of: find.byIcon(LucideIcons.arrowUp), + of: find.byIcon(BuzzIcons.arrowUp), matching: find.byType(IconButton), ) .hitTestable(); @@ -5064,7 +5064,7 @@ void main() { ); expect(find.byKey(const ValueKey('voice-note-waveform')), findsOneWidget); expect(find.byType(TextField), findsNothing); - expect(find.byIcon(LucideIcons.arrowUp), findsNothing); + expect(find.byIcon(BuzzIcons.arrowUp), findsNothing); expect(find.byTooltip('Add attachment'), findsNothing); final recordingWidth = tester @@ -5215,7 +5215,7 @@ void main() { ); final sendButton = find .ancestor( - of: find.byIcon(LucideIcons.arrowUp), + of: find.byIcon(BuzzIcons.arrowUp), matching: find.byType(IconButton), ) .hitTestable(); @@ -5529,7 +5529,7 @@ void main() { await tester.pumpAndSettle(); final sendButton = find .ancestor( - of: find.byIcon(LucideIcons.arrowUp), + of: find.byIcon(BuzzIcons.arrowUp), matching: find.byType(IconButton), ) .hitTestable(); @@ -5963,7 +5963,7 @@ Future _selectAndSendAgentMention(WidgetTester tester) async { await tester.tap(find.text('Helper Bot')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField), 'hello @Helper Bot'); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); } diff --git a/mobile/test/features/channels/compose_bar_test/durable_mention_tests.dart b/mobile/test/features/channels/compose_bar_test/durable_mention_tests.dart index 4c33ddb4fa..eebeb5cc86 100644 --- a/mobile/test/features/channels/compose_bar_test/durable_mention_tests.dart +++ b/mobile/test/features/channels/compose_bar_test/durable_mention_tests.dart @@ -73,7 +73,7 @@ void durableMentionTests() { tester.widget(find.byType(TextField)).controller!.text, draft, ); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(sent, [first, second]); expect( @@ -89,7 +89,7 @@ void durableMentionTests() { await tester.pumpAndSettle(); await tester.tap(find.text(draft.trim())); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(sent, [first, second]); }, @@ -183,7 +183,7 @@ void durableMentionTests() { await mount(); await tester.tap(find.text('@Helper Bot')); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(events.where((e) => e['kind'] == 9000), isEmpty); if (fallback == 'human') { diff --git a/mobile/test/features/channels/compose_bar_test/exact_mention_tests.dart b/mobile/test/features/channels/compose_bar_test/exact_mention_tests.dart index bb248403a0..a16a820e46 100644 --- a/mobile/test/features/channels/compose_bar_test/exact_mention_tests.dart +++ b/mobile/test/features/channels/compose_bar_test/exact_mention_tests.dart @@ -195,7 +195,7 @@ void exactMentionTests() { } } } - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); if (scenario == 'non-member human') { expect( @@ -276,14 +276,14 @@ void exactMentionTests() { expect(controller.text, '@Scout '); await pick(tester, '@Scout @', last: true); expect(controller.text, '@Scout @Scout ($second) '); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(sent, [first, second]); await pick(tester, '@'); await pick(tester, '@Scout @', last: true); await tester.enterText(find.byType(TextField), '@Scout ($second) '); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(sent, [second]); }, @@ -298,7 +298,7 @@ void exactMentionTests() { ], (_, keys, {mediaTags = const []}) async => sent = keys); await tester.enterText(find.byType(TextField), '@Scout ($second)'); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(sent, isEmpty); }); @@ -316,7 +316,7 @@ void exactMentionTests() { }); await tester.enterText(find.byType(TextField), '@Scout hello'); await tester.pumpAndSettle(); - await tester.tap(find.byIcon(LucideIcons.arrowUp)); + await tester.tap(find.byIcon(BuzzIcons.arrowUp)); await tester.pumpAndSettle(); expect(sent, isFalse); expect( diff --git a/mobile/test/features/channels/jump_to_latest_button_test.dart b/mobile/test/features/channels/jump_to_latest_button_test.dart index af476d527e..0c4481d048 100644 --- a/mobile/test/features/channels/jump_to_latest_button_test.dart +++ b/mobile/test/features/channels/jump_to_latest_button_test.dart @@ -6,7 +6,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; void main() { test( @@ -90,7 +90,7 @@ void main() { await tester.pump(); expect(find.byType(UiKitView), findsNothing); expect(find.byType(BackdropFilter), findsOneWidget); - expect(find.byIcon(LucideIcons.arrowDown), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowDown), findsOneWidget); } finally { messageActionBackdropActive.value = false; tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( @@ -120,7 +120,7 @@ void main() { expect(find.byType(UiKitView), findsNothing); expect(find.byType(BackdropFilter), findsOneWidget); - expect(find.byIcon(LucideIcons.arrowDown), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowDown), findsOneWidget); expect( tester.getSize(find.byType(JumpToLatestButton)), const Size.square(Grid.xl), diff --git a/mobile/test/features/channels/message_content_stability_test.dart b/mobile/test/features/channels/message_content_stability_test.dart index 3499cc18ca..b301d90b41 100644 --- a/mobile/test/features/channels/message_content_stability_test.dart +++ b/mobile/test/features/channels/message_content_stability_test.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:gpt_markdown/gpt_markdown.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; class _Fixture { final revision = ValueNotifier(0); @@ -197,7 +197,7 @@ void main() { fixture.agents.add('alice-key'); await fixture.refresh(tester); expect(_components(tester), isNot(same(before))); - expect(find.byIcon(LucideIcons.bot), findsOneWidget); + expect(find.byIcon(BuzzIcons.bot), findsOneWidget); before = _components(tester); fixture.mentionHandler = false; fixture.tappedId = null; @@ -210,7 +210,7 @@ void main() { await fixture.refresh(tester); await tester.tap(find.text('ALICE')); expect(fixture.tappedId, 'second-key'); - expect(find.byIcon(LucideIcons.bot), findsNothing); + expect(find.byIcon(BuzzIcons.bot), findsNothing); }, ); diff --git a/mobile/test/features/channels/message_content_test.dart b/mobile/test/features/channels/message_content_test.dart index 2283403692..4cba2278ef 100644 --- a/mobile/test/features/channels/message_content_test.dart +++ b/mobile/test/features/channels/message_content_test.dart @@ -18,7 +18,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/misc.dart'; import 'package:http/http.dart' as http; import 'package:just_audio/just_audio.dart' as audio; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; import 'package:buzz/features/channels/channel.dart'; import 'package:buzz/features/channels/channels_provider.dart'; @@ -2403,7 +2403,7 @@ Photos ), findsOneWidget, ); - expect(find.byIcon(LucideIcons.play), findsOneWidget); + expect(find.byIcon(BuzzIcons.play), findsOneWidget); }); testWidgets('derives a first frame for a posterless video event', ( @@ -2731,11 +2731,11 @@ Photos expect(find.text('engineering'), findsOneWidget); expect(find.text('buzz'), findsOneWidget); expect(find.text('buzz · cdcdcdcd'), findsNWidgets(2)); - expect(find.byIcon(LucideIcons.messageSquare), findsOneWidget); - expect(find.byIcon(LucideIcons.hash), findsOneWidget); - expect(find.byIcon(LucideIcons.folderGit2), findsOneWidget); - expect(find.byIcon(LucideIcons.gitPullRequest), findsOneWidget); - expect(find.byIcon(LucideIcons.circleDot), findsOneWidget); + expect(find.byIcon(BuzzIcons.messageSquare), findsOneWidget); + expect(find.byIcon(BuzzIcons.hash), findsOneWidget); + expect(find.byIcon(BuzzIcons.folderGit2), findsOneWidget); + expect(find.byIcon(BuzzIcons.gitPullRequest), findsOneWidget); + expect(find.byIcon(BuzzIcons.circleDot), findsOneWidget); expect( find.bySemanticsLabel( 'Open message cdcdcdcd in channel engineering', @@ -2813,7 +2813,7 @@ Photos ), ); - expect(find.byIcon(LucideIcons.bot), findsOneWidget); + expect(find.byIcon(BuzzIcons.bot), findsOneWidget); expect(find.text('@'), findsNothing); expect(find.text('Helper Bot'), findsOneWidget); }); @@ -2831,7 +2831,7 @@ Photos ), ); - expect(find.byIcon(LucideIcons.bot), findsOneWidget); + expect(find.byIcon(BuzzIcons.bot), findsOneWidget); expect(find.text('Helper Bot'), findsOneWidget); expect(_allRichText(tester), isNot(contains('Bot Bot'))); }); @@ -2944,7 +2944,7 @@ Photos ), ); - expect(find.byIcon(LucideIcons.hash), findsOneWidget); + expect(find.byIcon(BuzzIcons.hash), findsOneWidget); expect(find.text('general'), findsOneWidget); expect(find.text('#general'), findsNothing); }); @@ -3014,7 +3014,7 @@ Photos ), ); - expect(find.byIcon(LucideIcons.hash), findsOneWidget); + expect(find.byIcon(BuzzIcons.hash), findsOneWidget); expect(find.text('unknown'), findsOneWidget); expect(find.text('#unknown'), findsNothing); }); diff --git a/mobile/test/features/home/home_page_test.dart b/mobile/test/features/home/home_page_test.dart index 8251beb740..9b8cc9f78b 100644 --- a/mobile/test/features/home/home_page_test.dart +++ b/mobile/test/features/home/home_page_test.dart @@ -1,10 +1,11 @@ import 'package:buzz/features/home/home_page.dart'; +import 'package:buzz/features/search/search_page.dart'; import 'package:buzz/features/channels/channels_page.dart'; import 'package:buzz/features/profile/profile_avatar.dart'; import 'package:buzz/shared/theme/theme.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -74,11 +75,11 @@ void main() { expect(tester.getSize(bar), const Size(218, 56)); expect(created.where((params) => params['usesGlass'] == true), isNotEmpty); expect( - find.descendant(of: bar, matching: find.byIcon(LucideIcons.house500)), + find.descendant(of: bar, matching: find.byIcon(BuzzIcons.house500)), findsOneWidget, ); expect( - find.descendant(of: bar, matching: find.byIcon(LucideIcons.inbox300)), + find.descendant(of: bar, matching: find.byIcon(BuzzIcons.inbox300)), findsOneWidget, ); expect(find.bySemanticsLabel('Activity, unread'), findsOneWidget); @@ -97,7 +98,7 @@ void main() { .widget( find.descendant( of: launcherGlass, - matching: find.byIcon(LucideIcons.plus), + matching: find.byIcon(BuzzIcons.plus), ), ) .color, @@ -108,10 +109,7 @@ void main() { greaterThanOrEqualTo(2), ); expect( - find.descendant( - of: launcherGlass, - matching: find.byIcon(LucideIcons.plus), - ), + find.descendant(of: launcherGlass, matching: find.byIcon(BuzzIcons.plus)), findsOneWidget, ); await tester.tap(find.byTooltip('Create or start conversation')); @@ -129,17 +127,33 @@ void main() { await tester.pump(const Duration(milliseconds: 250)); await tester.pump(); expect( - find.descendant(of: bar, matching: find.byIcon(LucideIcons.inbox500)), + find.descendant(of: bar, matching: find.byIcon(BuzzIcons.inbox500)), findsOneWidget, ); expect(find.bySemanticsLabel('Activity, unread'), findsNothing); + final semantics = tester.ensureSemantics(); + expect(find.byType(SearchPage), findsNothing); + expect( + tester + .getSemantics(find.bySemanticsLabel('Search')) + .flagsCollection + .isSelected + .toString(), + 'Tristate.isFalse', + ); await tester.tap(find.byTooltip('Search')); await tester.pump(const Duration(milliseconds: 250)); await tester.pump(); + expect(find.byType(SearchPage), findsOneWidget); expect( - find.descendant(of: bar, matching: find.byIcon(LucideIcons.search500)), - findsOneWidget, + tester + .getSemantics(find.bySemanticsLabel('Search')) + .flagsCollection + .isSelected + .toString(), + 'Tristate.isTrue', ); + semantics.dispose(); await tester.pumpWidget(const SizedBox.shrink()); await tester.pump(); debugDefaultTargetPlatformOverride = null; diff --git a/mobile/test/features/invites/invite_create_page_test.dart b/mobile/test/features/invites/invite_create_page_test.dart index 5e6970151c..b3784cc87d 100644 --- a/mobile/test/features/invites/invite_create_page_test.dart +++ b/mobile/test/features/invites/invite_create_page_test.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; void main() { @@ -134,8 +134,8 @@ void main() { .dx, ), ); - expect(tester.widget(find.byIcon(LucideIcons.share2)).size, 22); - expect(tester.widget(find.byIcon(LucideIcons.copy)).size, 22); + expect(tester.widget(find.byIcon(BuzzIcons.share2)).size, 22); + expect(tester.widget(find.byIcon(BuzzIcons.copy)).size, 22); final settingsDivider = find.descendant( of: find.byKey(const Key('community-invite-link-settings')), matching: find.byType(Divider), @@ -171,7 +171,7 @@ void main() { findsNothing, ); expect(find.text('Role'), findsOneWidget); - expect(find.byIcon(LucideIcons.shield), findsNothing); + expect(find.byIcon(BuzzIcons.shield), findsNothing); final personDivider = find.descendant( of: find.byKey(const Key('community-invite-person-card')), matching: find.byType(Divider), @@ -378,7 +378,7 @@ void main() { ); await tester.pumpAndSettle(); expect(find.text('Limit number of uses'), findsNWidgets(2)); - expect(find.byIcon(LucideIcons.check), findsOneWidget); + expect(find.byIcon(BuzzIcons.check), findsOneWidget); await tester.tap(find.byKey(const Key('community-invite-option-5-uses'))); await tester.pumpAndSettle(); @@ -390,7 +390,7 @@ void main() { await tester.tap(find.byKey(const Key('community-invite-expiry-setting'))); await tester.pumpAndSettle(); expect(find.text('Expires after'), findsNWidgets(2)); - expect(find.byIcon(LucideIcons.check), findsOneWidget); + expect(find.byIcon(BuzzIcons.check), findsOneWidget); await tester.tap(find.byKey(const Key('community-invite-option-7-days'))); await tester.pumpAndSettle(); diff --git a/mobile/test/features/pairing/pairing_page_test.dart b/mobile/test/features/pairing/pairing_page_test.dart index 0ab42cf150..c575cde5f5 100644 --- a/mobile/test/features/pairing/pairing_page_test.dart +++ b/mobile/test/features/pairing/pairing_page_test.dart @@ -7,7 +7,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:local_auth/local_auth.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:buzz/features/pairing/pairing_page.dart'; import 'package:buzz/features/pairing/pairing_page/onboarding_wordmark.dart'; import 'package:buzz/features/pairing/pairing_provider.dart'; @@ -307,7 +307,7 @@ void main() { expect(find.byType(AppBar), findsNothing); expect(find.text('Add Community'), findsNothing); - expect(find.byIcon(LucideIcons.arrowLeft), findsNothing); + expect(find.byIcon(BuzzIcons.arrowLeft), findsNothing); expect(find.byKey(const Key('pairing-pop-scope')), findsOneWidget); await tester.tap(find.widgetWithText(TextButton, 'Cancel')); @@ -328,7 +328,7 @@ void main() { expect(appBar.surfaceTintColor, Colors.transparent); expect(appBar.elevation, 0); expect(appBar.scrolledUnderElevation, 0); - expect(find.byIcon(LucideIcons.arrowLeft), findsOneWidget); + expect(find.byIcon(BuzzIcons.arrowLeft), findsOneWidget); }); testWidgets('uses the native navigation bar on iOS', (tester) async { @@ -635,7 +635,7 @@ void main() { ), ); - expect(find.byIcon(LucideIcons.shieldCheck), findsNothing); + expect(find.byIcon(BuzzIcons.shieldCheck), findsNothing); expect(find.text('Enter pairing code'), findsOneWidget); expect( find.text( diff --git a/mobile/test/features/profile/set_status_sheet_test.dart b/mobile/test/features/profile/set_status_sheet_test.dart index 5ae424dfb0..aa87e73df9 100644 --- a/mobile/test/features/profile/set_status_sheet_test.dart +++ b/mobile/test/features/profile/set_status_sheet_test.dart @@ -6,7 +6,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../helpers/widget_helpers.dart'; @@ -98,7 +98,7 @@ void main() { await tester.pump(); expect(find.text('\u{1F3AF}'), findsNothing); - expect(find.byIcon(LucideIcons.smilePlus), findsOneWidget); + expect(find.byIcon(BuzzIcons.smilePlus), findsOneWidget); expect( tester.widget(find.byType(TextField)).controller?.text, 'Focusing', diff --git a/mobile/test/features/search/search_page_test.dart b/mobile/test/features/search/search_page_test.dart index 6d71d8e909..525363b54a 100644 --- a/mobile/test/features/search/search_page_test.dart +++ b/mobile/test/features/search/search_page_test.dart @@ -15,7 +15,7 @@ import 'package:buzz/shared/widgets/frosted_app_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import '../../helpers/widget_helpers.dart'; @@ -1085,7 +1085,7 @@ void main() { ); expect(content.mentionNames, {agentPubkey: 'Helper Bot'}); expect(content.agentMentionPubkeys, contains(agentPubkey)); - expect(find.byIcon(LucideIcons.bot), findsOneWidget); + expect(find.byIcon(BuzzIcons.bot), findsOneWidget); }); testWidgets('does not label an unjoined channel as having zero members', ( diff --git a/mobile/test/features/settings/connection_section_test.dart b/mobile/test/features/settings/connection_section_test.dart index cfc6926bb3..b94bcfc465 100644 --- a/mobile/test/features/settings/connection_section_test.dart +++ b/mobile/test/features/settings/connection_section_test.dart @@ -9,7 +9,7 @@ import 'package:buzz/shared/widgets/app_list_card.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:lucide_icons_flutter/lucide_icons.dart'; +import 'package:buzz/shared/theme/buzz_icons.dart'; import 'package:nostr/nostr.dart' as nostr; import 'package:shared_preferences/shared_preferences.dart'; @@ -119,10 +119,8 @@ void main() { ), findsOneWidget, ); - final copy = tester.getRect(find.byIcon(LucideIcons.copy)); - final chevron = tester.getRect( - find.byIcon(LucideIcons.chevronRight).first, - ); + final copy = tester.getRect(find.byIcon(BuzzIcons.copy)); + final chevron = tester.getRect(find.byIcon(BuzzIcons.chevronRight).first); expect(copy.center.dx, closeTo(chevron.center.dx, 0.5)); await tester.tap(find.text('Copy public key (npub)')); diff --git a/mobile/test/features/settings/settings_page_test.dart b/mobile/test/features/settings/settings_page_test.dart index 64fec33ef3..99db70f625 100644 --- a/mobile/test/features/settings/settings_page_test.dart +++ b/mobile/test/features/settings/settings_page_test.dart @@ -295,8 +295,7 @@ void main() { await tester.runAsync(() async { for (final font in { 'Inter': 'assets/fonts/InterVariable.ttf', - 'packages/lucide_icons_flutter/Lucide': - 'packages/lucide_icons_flutter/assets/lucide.ttf', + 'BuzzTabler': 'assets/fonts/TablerIcons.ttf', }.entries) { await (FontLoader( font.key, diff --git a/mobile/test/shared/theme/buzz_icons_test.dart b/mobile/test/shared/theme/buzz_icons_test.dart new file mode 100644 index 0000000000..c88bc91f68 --- /dev/null +++ b/mobile/test/shared/theme/buzz_icons_test.dart @@ -0,0 +1,15 @@ +import 'package:buzz/shared/theme/buzz_icons.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('Unarchive uses restoration instead of crossed-out archiving', () { + expect(BuzzIcons.archiveRestore.codePoint, 0xfafd); + expect(BuzzIcons.archiveRestore, isNot(BuzzIcons.archive)); + expect(BuzzIcons.archiveRestore.codePoint, isNot(0xf0ad)); + }); + + test('temporary channels use an hourglass distinct from running status', () { + expect(BuzzIcons.clockFading.codePoint, 0xef93); + expect(BuzzIcons.clockFading, isNot(BuzzIcons.clock3)); + }); +} diff --git a/mobile/test/shared/theme/tabler_icon_render_test.dart b/mobile/test/shared/theme/tabler_icon_render_test.dart new file mode 100644 index 0000000000..ffb50cc3ef --- /dev/null +++ b/mobile/test/shared/theme/tabler_icon_render_test.dart @@ -0,0 +1,101 @@ +import 'dart:io'; +import 'dart:ui' as ui; + +import 'package:buzz/shared/theme/buzz_icons.dart'; +import 'package:buzz/shared/theme/theme.dart'; +import 'package:buzz/shared/widgets/tabler_star_icon.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + for (final dark in [false, true]) { + testWidgets('Tabler action artwork in ${dark ? 'dark' : 'light'}', ( + tester, + ) async { + await tester.runAsync(() async { + await (FontLoader( + 'Inter', + )..addFont(rootBundle.load('assets/fonts/InterVariable.ttf'))).load(); + await (FontLoader( + 'BuzzTabler', + )..addFont(rootBundle.load('assets/fonts/TablerIcons.ttf'))).load(); + }); + final theme = dark ? AppTheme.dark() : AppTheme.light(); + final color = theme.colorScheme.onSurface; + final key = GlobalKey(); + await tester.pumpWidget( + MaterialApp( + theme: theme.copyWith( + listTileTheme: ListTileThemeData( + titleTextStyle: TextStyle( + fontFamily: 'Inter', + fontSize: 16, + color: color, + ), + ), + ), + home: Center( + child: RepaintBoundary( + key: key, + child: Material( + child: SizedBox( + width: 320, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const ListTile( + leading: Icon(BuzzIcons.archive), + title: Text('Archive'), + ), + const ListTile( + leading: Icon(BuzzIcons.archiveRestore), + title: Text('Unarchive'), + ), + const ListTile( + leading: Icon(BuzzIcons.clock3), + title: Text('Running'), + ), + const ListTile( + leading: Icon(BuzzIcons.clockFading), + title: Text('Temporary channel'), + ), + ListTile( + leading: TablerStarIcon(color: color), + title: const Text('Star'), + ), + ListTile( + leading: TablerStarIcon( + color: theme.colorScheme.primary, + filled: true, + ), + title: const Text('Unstar'), + ), + ], + ), + ), + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + expect(tester.takeException(), isNull); + final directory = Platform.environment['TABLER_SCREENSHOTS']; + if (directory != null) { + await tester.runAsync(() async { + final boundary = + key.currentContext!.findRenderObject()! as RenderRepaintBoundary; + final image = await boundary.toImage(pixelRatio: 2); + final bytes = await image.toByteData(format: ui.ImageByteFormat.png); + await Directory(directory).create(recursive: true); + await File( + '$directory/${dark ? 'dark' : 'light'}.png', + ).writeAsBytes(bytes!.buffer.asUint8List()); + image.dispose(); + }); + } + }); + } +}