refactor(ui): Lucide migration unit 2 — Icons.* -> LucideIcons.* sweep (#60)

Mechanical sweep across 30 files: every Material Icons.* replaced with
the signed-off Lucide equivalent + a flutter_lucide import per file.
Zero Material Icons.* remain in lib/; no unused imports.

Judgment-call mappings: album->disc_3, library_music->library_big,
playlist_play->list_video, graphic_eq->audio_lines,
system_update->download, restore->archive_restore,
download_done->circle_check_big.

track_actions_sheet like menu row: collapsed `liked ? favorite :
favorite_border` to a single LucideIcons.heart (the row's Like/Unlike
text label conveys state). Icon-only LikeButton + the notification keep
the filled-vs-outline shape per the design decision.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-18 20:43:05 -04:00
parent 84f16c25f6
commit 835592f073
30 changed files with 113 additions and 83 deletions
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -34,7 +35,7 @@ class AdminLandingScreen extends ConsumerWidget {
children: [ children: [
AdminSectionCard( AdminSectionCard(
key: const Key('admin_card_requests'), key: const Key('admin_card_requests'),
icon: Icons.inbox, icon: LucideIcons.inbox,
title: 'Requests', title: 'Requests',
subtitle: 'Approve or reject Lidarr requests', subtitle: 'Approve or reject Lidarr requests',
count: c.requests, count: c.requests,
@@ -42,7 +43,7 @@ class AdminLandingScreen extends ConsumerWidget {
), ),
AdminSectionCard( AdminSectionCard(
key: const Key('admin_card_quarantine'), key: const Key('admin_card_quarantine'),
icon: Icons.warning_amber, icon: LucideIcons.triangle_alert,
title: 'Quarantine', title: 'Quarantine',
subtitle: 'Resolve scan failures', subtitle: 'Resolve scan failures',
count: c.quarantine, count: c.quarantine,
@@ -50,7 +51,7 @@ class AdminLandingScreen extends ConsumerWidget {
), ),
AdminSectionCard( AdminSectionCard(
key: const Key('admin_card_users'), key: const Key('admin_card_users'),
icon: Icons.people, icon: LucideIcons.users,
title: 'Users', title: 'Users',
subtitle: 'Manage accounts and invites', subtitle: 'Manage accounts and invites',
count: c.users, count: c.users,
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -59,7 +60,7 @@ class AdminUsersScreen extends ConsumerWidget {
trailing: TextButton.icon( trailing: TextButton.icon(
key: const Key('invite_generate_button'), key: const Key('invite_generate_button'),
onPressed: () => _showGenerateInvite(context, ref), onPressed: () => _showGenerateInvite(context, ref),
icon: Icon(Icons.add, color: fs.parchment), icon: Icon(LucideIcons.plus, color: fs.parchment),
label: Text('Generate', label: Text('Generate',
style: TextStyle(color: fs.parchment)), style: TextStyle(color: fs.parchment)),
), ),
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../models/admin_quarantine_item.dart'; import '../../models/admin_quarantine_item.dart';
import '../../theme/theme_extension.dart'; import '../../theme/theme_extension.dart';
@@ -45,7 +46,7 @@ class AdminQuarantineRow extends StatelessWidget {
), ),
trailing: PopupMenuButton<String>( trailing: PopupMenuButton<String>(
key: Key('admin_quarantine_menu_${item.trackId}'), key: Key('admin_quarantine_menu_${item.trackId}'),
icon: Icon(Icons.more_vert, color: fs.parchment), icon: Icon(LucideIcons.ellipsis_vertical, color: fs.parchment),
onSelected: (action) async { onSelected: (action) async {
switch (action) { switch (action) {
case 'resolve': case 'resolve':
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../models/admin_user.dart'; import '../../models/admin_user.dart';
import '../../theme/theme_extension.dart'; import '../../theme/theme_extension.dart';
@@ -29,7 +30,7 @@ class AdminUserRow extends StatelessWidget {
_Badge(label: 'auto-approve', color: fs.moss), _Badge(label: 'auto-approve', color: fs.moss),
], ],
), ),
trailing: Icon(Icons.chevron_right, color: fs.ash), trailing: Icon(LucideIcons.chevron_right, color: fs.ash),
onTap: onTap, onTap: onTap,
); );
} }
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import '../../models/invite.dart'; import '../../models/invite.dart';
@@ -31,7 +32,7 @@ class InviteRow extends StatelessWidget {
), ),
), ),
IconButton( IconButton(
icon: Icon(Icons.copy, color: fs.ash, size: 18), icon: Icon(LucideIcons.copy, color: fs.ash, size: 18),
tooltip: 'Copy', tooltip: 'Copy',
onPressed: () => onPressed: () =>
Clipboard.setData(ClipboardData(text: invite.token)), Clipboard.setData(ClipboardData(text: invite.token)),
@@ -63,7 +64,7 @@ class InviteRow extends StatelessWidget {
], ],
), ),
trailing: IconButton( trailing: IconButton(
icon: Icon(Icons.delete_outline, color: fs.oxblood), icon: Icon(LucideIcons.trash_2, color: fs.oxblood),
tooltip: 'Revoke', tooltip: 'Revoke',
onPressed: onRevoke, onPressed: onRevoke,
), ),
@@ -1,6 +1,7 @@
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -167,7 +168,7 @@ class _DiscoverScreenState extends ConsumerState<DiscoverScreen> {
backgroundColor: fs.obsidian, backgroundColor: fs.obsidian,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back, color: fs.parchment), icon: Icon(LucideIcons.arrow_left, color: fs.parchment),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: Text('Discover', style: TextStyle(color: fs.parchment)), title: Text('Discover', style: TextStyle(color: fs.parchment)),
@@ -193,7 +194,7 @@ class _DiscoverScreenState extends ConsumerState<DiscoverScreen> {
borderSide: BorderSide(color: fs.accent), borderSide: BorderSide(color: fs.accent),
), ),
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon(Icons.search, color: fs.ash), icon: Icon(LucideIcons.search, color: fs.ash),
onPressed: _runSearch, onPressed: _runSearch,
), ),
), ),
@@ -336,14 +337,14 @@ class _ResultTile extends StatelessWidget {
height: 56, height: 56,
color: fs.slate, color: fs.slate,
child: row.imageUrl.isEmpty child: row.imageUrl.isEmpty
? Icon(Icons.album, color: fs.ash) ? Icon(LucideIcons.disc_3, color: fs.ash)
: CachedNetworkImage( : CachedNetworkImage(
imageUrl: row.imageUrl, imageUrl: row.imageUrl,
fit: BoxFit.cover, fit: BoxFit.cover,
fadeInDuration: const Duration(milliseconds: 120), fadeInDuration: const Duration(milliseconds: 120),
fadeOutDuration: Duration.zero, fadeOutDuration: Duration.zero,
errorWidget: (_, __, ___) => errorWidget: (_, __, ___) =>
Icon(Icons.album, color: fs.ash), Icon(LucideIcons.disc_3, color: fs.ash),
), ),
), ),
), ),
@@ -419,14 +420,14 @@ class _SuggestionTile extends StatelessWidget {
height: 56, height: 56,
color: fs.slate, color: fs.slate,
child: s.imageUrl.isEmpty child: s.imageUrl.isEmpty
? Icon(Icons.person, color: fs.ash) ? Icon(LucideIcons.user, color: fs.ash)
: CachedNetworkImage( : CachedNetworkImage(
imageUrl: s.imageUrl, imageUrl: s.imageUrl,
fit: BoxFit.cover, fit: BoxFit.cover,
fadeInDuration: const Duration(milliseconds: 120), fadeInDuration: const Duration(milliseconds: 120),
fadeOutDuration: Duration.zero, fadeOutDuration: Duration.zero,
errorWidget: (_, __, ___) => errorWidget: (_, __, ___) =>
Icon(Icons.person, color: fs.ash), Icon(LucideIcons.user, color: fs.ash),
), ),
), ),
), ),
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../api/endpoints/likes.dart'; import '../api/endpoints/likes.dart';
@@ -115,7 +116,7 @@ class AlbumDetailScreen extends ConsumerWidget {
width: 48, height: 48, width: 48, height: 48,
decoration: BoxDecoration(color: fs.accent, shape: BoxShape.circle), decoration: BoxDecoration(color: fs.accent, shape: BoxShape.circle),
child: IconButton( child: IconButton(
icon: Icon(Icons.play_arrow, color: fs.parchment), icon: Icon(LucideIcons.play, color: fs.parchment),
onPressed: () => ref.read(playerActionsProvider).playTracks(r.tracks), onPressed: () => ref.read(playerActionsProvider).playTracks(r.tracks),
), ),
), ),
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -90,7 +91,7 @@ class ArtistDetailScreen extends ConsumerWidget {
width: 48, height: 48, width: 48, height: 48,
decoration: BoxDecoration(color: fs.accent, shape: BoxShape.circle), decoration: BoxDecoration(color: fs.accent, shape: BoxShape.circle),
child: IconButton( child: IconButton(
icon: Icon(Icons.play_arrow, color: fs.parchment), icon: Icon(LucideIcons.play, color: fs.parchment),
onPressed: () async { onPressed: () async {
try { try {
final tracks = final tracks =
+3 -2
View File
@@ -1,5 +1,6 @@
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -245,12 +246,12 @@ class _PlaylistsSection extends StatelessWidget {
if (offline) ...const [ if (offline) ...const [
_OfflinePoolCard( _OfflinePoolCard(
label: 'Recently played', label: 'Recently played',
icon: Icons.history, icon: LucideIcons.history,
kind: _OfflinePoolKind.recentlyPlayed, kind: _OfflinePoolKind.recentlyPlayed,
), ),
_OfflinePoolCard( _OfflinePoolCard(
label: 'Liked', label: 'Liked',
icon: Icons.favorite, icon: LucideIcons.heart,
kind: _OfflinePoolKind.liked, kind: _OfflinePoolKind.liked,
), ),
], ],
@@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:drift/drift.dart' as drift; import 'package:drift/drift.dart' as drift;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -382,7 +383,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
IconButton( IconButton(
key: const Key('shuffle_all_button'), key: const Key('shuffle_all_button'),
tooltip: 'Shuffle all', tooltip: 'Shuffle all',
icon: Icon(Icons.shuffle, color: fs.parchment), icon: Icon(LucideIcons.shuffle, color: fs.parchment),
onPressed: () async { onPressed: () async {
final messenger = ScaffoldMessenger.of(context); final messenger = ScaffoldMessenger.of(context);
final refs = await ref.read(shuffleSourceProvider).tracks(); final refs = await ref.read(shuffleSourceProvider).tracks();
@@ -866,7 +867,7 @@ class _QuarantineTile extends ConsumerWidget {
), ),
IconButton( IconButton(
tooltip: 'Unhide', tooltip: 'Unhide',
icon: Icon(Icons.restore, color: fs.ash, size: 20), icon: Icon(LucideIcons.archive_restore, color: fs.ash, size: 20),
onPressed: () async { onPressed: () async {
try { try {
await ref.read(myQuarantineProvider.notifier).unflag(row.trackId); await ref.read(myQuarantineProvider.notifier).unflag(row.trackId);
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../cache/audio_cache_manager.dart'; import '../../cache/audio_cache_manager.dart';
@@ -21,7 +22,7 @@ class CachedIndicator extends ConsumerWidget {
if (snap.data != true) return const SizedBox.shrink(); if (snap.data != true) return const SizedBox.shrink();
return Padding( return Padding(
padding: const EdgeInsets.only(left: 4), padding: const EdgeInsets.only(left: 4),
child: Icon(Icons.download_done, size: 14, color: fs.accent), child: Icon(LucideIcons.circle_check_big, size: 14, color: fs.accent),
); );
}, },
); );
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../theme/theme_extension.dart'; import '../../theme/theme_extension.dart';
@@ -85,7 +86,7 @@ class _PlayCircleButtonState extends State<PlayCircleButton> {
), ),
) )
: Icon( : Icon(
Icons.play_arrow, LucideIcons.play,
color: fs.parchment, color: fs.parchment,
size: iconSize, size: iconSize,
), ),
@@ -2,6 +2,7 @@ import 'dart:io';
import 'package:audio_service/audio_service.dart'; import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -376,13 +377,13 @@ class _TopBar extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(horizontal: 4),
child: Row(children: [ child: Row(children: [
IconButton( IconButton(
icon: Icon(Icons.expand_more, color: fs.parchment), icon: Icon(LucideIcons.chevron_down, color: fs.parchment),
tooltip: 'Close', tooltip: 'Close',
onPressed: () => Navigator.of(context).maybePop(), onPressed: () => Navigator.of(context).maybePop(),
), ),
const Spacer(), const Spacer(),
IconButton( IconButton(
icon: Icon(Icons.queue_music, color: fs.parchment), icon: Icon(LucideIcons.list_music, color: fs.parchment),
tooltip: 'Queue', tooltip: 'Queue',
onPressed: () => GoRouter.of(context).push('/queue'), onPressed: () => GoRouter.of(context).push('/queue'),
), ),
@@ -535,13 +536,13 @@ class _PrimaryControls extends StatelessWidget {
children: [ children: [
IconButton( IconButton(
iconSize: 36, iconSize: 36,
icon: Icon(Icons.skip_previous, color: fs.parchment), icon: Icon(LucideIcons.skip_back, color: fs.parchment),
onPressed: () => ref.read(audioHandlerProvider).skipToPrevious(), onPressed: () => ref.read(audioHandlerProvider).skipToPrevious(),
), ),
IconButton( IconButton(
iconSize: 72, iconSize: 72,
icon: Icon( icon: Icon(
isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled, isPlaying ? LucideIcons.circle_pause : LucideIcons.circle_play,
color: fs.accent, color: fs.accent,
), ),
onPressed: () { onPressed: () {
@@ -555,7 +556,7 @@ class _PrimaryControls extends StatelessWidget {
), ),
IconButton( IconButton(
iconSize: 36, iconSize: 36,
icon: Icon(Icons.skip_next, color: fs.parchment), icon: Icon(LucideIcons.skip_forward, color: fs.parchment),
onPressed: () => ref.read(audioHandlerProvider).skipToNext(), onPressed: () => ref.read(audioHandlerProvider).skipToNext(),
), ),
], ],
@@ -589,7 +590,7 @@ class _SecondaryControls extends StatelessWidget {
IconButton( IconButton(
tooltip: shuffleOn ? 'Shuffle on' : 'Shuffle off', tooltip: shuffleOn ? 'Shuffle on' : 'Shuffle off',
icon: Icon( icon: Icon(
Icons.shuffle, LucideIcons.shuffle,
color: shuffleOn ? fs.accent : fs.ash, color: shuffleOn ? fs.accent : fs.ash,
), ),
onPressed: actions.toggleShuffle, onPressed: actions.toggleShuffle,
@@ -602,8 +603,8 @@ class _SecondaryControls extends StatelessWidget {
}, },
icon: Icon( icon: Icon(
repeatMode == AudioServiceRepeatMode.one repeatMode == AudioServiceRepeatMode.one
? Icons.repeat_one ? LucideIcons.repeat_1
: Icons.repeat, : LucideIcons.repeat,
color: repeatMode == AudioServiceRepeatMode.none color: repeatMode == AudioServiceRepeatMode.none
? fs.ash ? fs.ash
: fs.accent, : fs.accent,
@@ -612,7 +613,7 @@ class _SecondaryControls extends StatelessWidget {
), ),
IconButton( IconButton(
tooltip: 'Queue', tooltip: 'Queue',
icon: Icon(Icons.queue_music, color: fs.ash), icon: Icon(LucideIcons.list_music, color: fs.ash),
onPressed: () => GoRouter.of(context).push('/queue'), onPressed: () => GoRouter.of(context).push('/queue'),
), ),
LikeButton(kind: LikeKind.track, id: media.id, size: 22), LikeButton(kind: LikeKind.track, id: media.id, size: 22),
+4 -3
View File
@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:audio_service/audio_service.dart'; import 'package:audio_service/audio_service.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -229,7 +230,7 @@ class _PlayControls extends StatelessWidget {
child: IconButton( child: IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 22, iconSize: 22,
icon: Icon(Icons.skip_previous, color: fs.parchment), icon: Icon(LucideIcons.skip_back, color: fs.parchment),
onPressed: () => ref.read(audioHandlerProvider).skipToPrevious(), onPressed: () => ref.read(audioHandlerProvider).skipToPrevious(),
), ),
), ),
@@ -240,7 +241,7 @@ class _PlayControls extends StatelessWidget {
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 32, iconSize: 32,
icon: Icon( icon: Icon(
isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled, isPlaying ? LucideIcons.circle_pause : LucideIcons.circle_play,
color: fs.accent, color: fs.accent,
), ),
onPressed: () { onPressed: () {
@@ -259,7 +260,7 @@ class _PlayControls extends StatelessWidget {
child: IconButton( child: IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 22, iconSize: 22,
icon: Icon(Icons.skip_next, color: fs.parchment), icon: Icon(LucideIcons.skip_forward, color: fs.parchment),
onPressed: () => ref.read(audioHandlerProvider).skipToNext(), onPressed: () => ref.read(audioHandlerProvider).skipToNext(),
), ),
), ),
+3 -2
View File
@@ -1,5 +1,6 @@
import 'package:audio_service/audio_service.dart'; import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -20,7 +21,7 @@ class QueueScreen extends ConsumerWidget {
backgroundColor: fs.obsidian, backgroundColor: fs.obsidian,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back, color: fs.parchment), icon: Icon(LucideIcons.arrow_left, color: fs.parchment),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: Text('Queue', style: TextStyle(color: fs.parchment)), title: Text('Queue', style: TextStyle(color: fs.parchment)),
@@ -84,7 +85,7 @@ class _QueueRow extends StatelessWidget {
if (isCurrent) if (isCurrent)
Padding( Padding(
padding: const EdgeInsets.only(right: 8), padding: const EdgeInsets.only(right: 8),
child: Icon(Icons.graphic_eq, color: fs.accent, size: 16), child: Icon(LucideIcons.audio_lines, color: fs.accent, size: 16),
), ),
Expanded( Expanded(
child: Column( child: Column(
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -54,7 +55,7 @@ class PlaylistDetailScreen extends ConsumerWidget {
backgroundColor: fs.obsidian, backgroundColor: fs.obsidian,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back, color: fs.parchment), icon: Icon(LucideIcons.arrow_left, color: fs.parchment),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: headerName.isEmpty title: headerName.isEmpty
@@ -268,7 +269,7 @@ class _Header extends ConsumerWidget {
OutlinedButton.icon( OutlinedButton.icon(
key: const Key('regenerate_playlist_button'), key: const Key('regenerate_playlist_button'),
onPressed: () => _regenerate(context, ref), onPressed: () => _regenerate(context, ref),
icon: const Icon(Icons.refresh, size: 16), icon: const Icon(LucideIcons.refresh_cw, size: 16),
label: const Text('Regenerate'), label: const Text('Regenerate'),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
@@ -281,7 +282,7 @@ class _Header extends ConsumerWidget {
source: p.refreshable ? p.systemVariant : null, source: p.refreshable ? p.systemVariant : null,
); );
}, },
icon: const Icon(Icons.play_arrow), icon: const Icon(LucideIcons.play),
label: const Text('Play'), label: const Text('Play'),
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
backgroundColor: fs.accent, backgroundColor: fs.accent,
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -82,11 +83,11 @@ class _PlaylistTile extends StatelessWidget {
height: 56, height: 56,
color: fs.slate, color: fs.slate,
child: playlist.coverUrl.isEmpty child: playlist.coverUrl.isEmpty
? Icon(Icons.queue_music, color: fs.ash) ? Icon(LucideIcons.list_music, color: fs.ash)
: ServerImage( : ServerImage(
url: playlist.coverUrl, url: playlist.coverUrl,
fit: BoxFit.cover, fit: BoxFit.cover,
fallback: Icon(Icons.queue_music, color: fs.ash), fallback: Icon(LucideIcons.list_music, color: fs.ash),
), ),
), ),
), ),
@@ -128,7 +129,7 @@ class _PlaylistTile extends StatelessWidget {
], ],
), ),
), ),
Icon(Icons.chevron_right, color: fs.ash), Icon(LucideIcons.chevron_right, color: fs.ash),
]), ]),
), ),
); );
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -55,12 +56,12 @@ class PlaylistCard extends ConsumerWidget {
// errorBuilder shows the queue_music icon over the // errorBuilder shows the queue_music icon over the
// slate background. // slate background.
child: playlist.coverUrl.isEmpty child: playlist.coverUrl.isEmpty
? Icon(Icons.queue_music, color: fs.ash, size: 56) ? Icon(LucideIcons.list_music, color: fs.ash, size: 56)
: ServerImage( : ServerImage(
url: playlist.coverUrl, url: playlist.coverUrl,
fit: BoxFit.cover, fit: BoxFit.cover,
fallback: fallback:
Icon(Icons.queue_music, color: fs.ash, size: 56), Icon(LucideIcons.list_music, color: fs.ash, size: 56),
), ),
), ),
), ),
@@ -80,7 +81,7 @@ class PlaylistCard extends ConsumerWidget {
top: 2, top: 2,
right: 2, right: 2,
child: PopupMenuButton<String>( child: PopupMenuButton<String>(
icon: Icon(Icons.more_vert, color: fs.parchment, size: 18), icon: Icon(LucideIcons.ellipsis_vertical, color: fs.parchment, size: 18),
tooltip: 'Playlist actions', tooltip: 'Playlist actions',
color: fs.iron, color: fs.iron,
onSelected: (_) => _refresh(context, ref), onSelected: (_) => _refresh(context, ref),
@@ -88,7 +89,7 @@ class PlaylistCard extends ConsumerWidget {
PopupMenuItem<String>( PopupMenuItem<String>(
value: 'refresh', value: 'refresh',
child: Row(children: [ child: Row(children: [
Icon(Icons.refresh, color: fs.parchment, size: 18), Icon(LucideIcons.refresh_cw, color: fs.parchment, size: 18),
const SizedBox(width: 8), const SizedBox(width: 8),
Text(_refreshLabel, Text(_refreshLabel,
style: TextStyle(color: fs.parchment)), style: TextStyle(color: fs.parchment)),
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../theme/theme_extension.dart'; import '../../theme/theme_extension.dart';
@@ -65,9 +66,9 @@ class PlaylistPlaceholderCard extends StatelessWidget {
child: CircularProgressIndicator(strokeWidth: 2, color: fs.accent), child: CircularProgressIndicator(strokeWidth: 2, color: fs.accent),
); );
case 'failed': case 'failed':
return Icon(Icons.warning_amber, color: fs.error, size: 32); return Icon(LucideIcons.triangle_alert, color: fs.error, size: 32);
default: default:
return Icon(Icons.queue_music, color: fs.ash, size: 40); return Icon(LucideIcons.list_music, color: fs.ash, size: 40);
} }
} }
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -32,7 +33,7 @@ class RequestsScreen extends ConsumerWidget {
backgroundColor: fs.obsidian, backgroundColor: fs.obsidian,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back, color: fs.parchment), icon: Icon(LucideIcons.arrow_left, color: fs.parchment),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: Text('Your requests', style: TextStyle(color: fs.parchment)), title: Text('Your requests', style: TextStyle(color: fs.parchment)),
@@ -130,9 +131,9 @@ class _RequestRow extends StatelessWidget {
Widget _kindAvatar(FabledSwordTheme fs) { Widget _kindAvatar(FabledSwordTheme fs) {
final icon = switch (request.kind) { final icon = switch (request.kind) {
'artist' => Icons.album, 'artist' => LucideIcons.disc_3,
'album' => Icons.library_music, 'album' => LucideIcons.library_big,
_ => Icons.music_note, _ => LucideIcons.music,
}; };
return CircleAvatar( return CircleAvatar(
backgroundColor: fs.iron, backgroundColor: fs.iron,
@@ -164,7 +165,7 @@ class _RequestRow extends StatelessWidget {
); );
if (ok == true) onCancel(); if (ok == true) onCancel();
}, },
icon: const Icon(Icons.close, size: 16), icon: const Icon(LucideIcons.x, size: 16),
label: const Text('Cancel'), label: const Text('Cancel'),
style: TextButton.styleFrom(foregroundColor: fs.ash), style: TextButton.styleFrom(foregroundColor: fs.ash),
); );
@@ -172,7 +173,7 @@ class _RequestRow extends StatelessWidget {
if (request.status == 'completed' && href != null) { if (request.status == 'completed' && href != null) {
return TextButton.icon( return TextButton.icon(
onPressed: () => context.push(href), onPressed: () => context.push(href),
icon: const Icon(Icons.play_arrow, size: 16), icon: const Icon(LucideIcons.play, size: 16),
label: const Text('Listen'), label: const Text('Listen'),
style: TextButton.styleFrom(foregroundColor: fs.accent), style: TextButton.styleFrom(foregroundColor: fs.accent),
); );
+3 -2
View File
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -47,7 +48,7 @@ class _SearchScreenState extends ConsumerState<SearchScreen> {
backgroundColor: fs.obsidian, backgroundColor: fs.obsidian,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back, color: fs.parchment), icon: Icon(LucideIcons.arrow_left, color: fs.parchment),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: TextField( title: TextField(
@@ -67,7 +68,7 @@ class _SearchScreenState extends ConsumerState<SearchScreen> {
actions: [ actions: [
if (_controller.text.isNotEmpty) if (_controller.text.isNotEmpty)
IconButton( IconButton(
icon: Icon(Icons.clear, color: fs.ash), icon: Icon(LucideIcons.x, color: fs.ash),
onPressed: () { onPressed: () {
_controller.clear(); _controller.clear();
ref.read(searchQueryProvider.notifier).set(''); ref.read(searchQueryProvider.notifier).set('');
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
@@ -88,7 +89,7 @@ class _AboutSectionState extends ConsumerState<AboutSection> {
padding: const EdgeInsets.fromLTRB(16, 0, 16, 4), padding: const EdgeInsets.fromLTRB(16, 0, 16, 4),
child: Row( child: Row(
children: [ children: [
Icon(Icons.info_outline, color: fs.parchment, size: 18), Icon(LucideIcons.info, color: fs.parchment, size: 18),
const SizedBox(width: 8), const SizedBox(width: 8),
Text('Installed version', Text('Installed version',
style: TextStyle(color: fs.parchment, fontSize: 14)), style: TextStyle(color: fs.parchment, fontSize: 14)),
@@ -105,7 +106,7 @@ class _AboutSectionState extends ConsumerState<AboutSection> {
padding: const EdgeInsets.fromLTRB(16, 4, 16, 4), padding: const EdgeInsets.fromLTRB(16, 4, 16, 4),
child: Row( child: Row(
children: [ children: [
Icon(Icons.cloud_outlined, color: fs.parchment, size: 18), Icon(LucideIcons.cloud, color: fs.parchment, size: 18),
const SizedBox(width: 8), const SizedBox(width: 8),
Text('Latest version', Text('Latest version',
style: TextStyle(color: fs.parchment, fontSize: 14)), style: TextStyle(color: fs.parchment, fontSize: 14)),
@@ -148,7 +149,7 @@ class _AboutSectionState extends ConsumerState<AboutSection> {
valueColor: AlwaysStoppedAnimation(fs.parchment), valueColor: AlwaysStoppedAnimation(fs.parchment),
), ),
) )
: const Icon(Icons.refresh, size: 18), : const Icon(LucideIcons.refresh_cw, size: 18),
label: Text(_checking ? 'Checking…' : 'Check for updates'), label: Text(_checking ? 'Checking…' : 'Check for updates'),
), ),
if (hasUpdate) ...[ if (hasUpdate) ...[
@@ -172,7 +173,7 @@ class _AboutSectionState extends ConsumerState<AboutSection> {
valueColor: AlwaysStoppedAnimation(fs.parchment), valueColor: AlwaysStoppedAnimation(fs.parchment),
), ),
) )
: const Icon(Icons.system_update, size: 18), : const Icon(LucideIcons.download, size: 18),
label: Text( label: Text(
_installStage == _InstallStage.downloading _installStage == _InstallStage.downloading
? 'Downloading…' ? 'Downloading…'
@@ -1,5 +1,6 @@
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -37,7 +38,7 @@ class SettingsScreen extends ConsumerWidget {
backgroundColor: fs.obsidian, backgroundColor: fs.obsidian,
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back, color: fs.parchment), icon: Icon(LucideIcons.arrow_left, color: fs.parchment),
onPressed: () => context.pop(), onPressed: () => context.pop(),
), ),
title: Text('Settings', style: TextStyle(color: fs.parchment)), title: Text('Settings', style: TextStyle(color: fs.parchment)),
@@ -107,7 +108,7 @@ class _RequestsSection extends StatelessWidget {
final fs = Theme.of(context).extension<FabledSwordTheme>()!; final fs = Theme.of(context).extension<FabledSwordTheme>()!;
return ListTile( return ListTile(
key: const Key('settings_requests_card'), key: const Key('settings_requests_card'),
leading: Icon(Icons.queue_music, color: fs.parchment), leading: Icon(LucideIcons.list_music, color: fs.parchment),
title: Text( title: Text(
'My requests', 'My requests',
style: TextStyle( style: TextStyle(
@@ -120,7 +121,7 @@ class _RequestsSection extends StatelessWidget {
"Track what you've asked Minstrel to add", "Track what you've asked Minstrel to add",
style: TextStyle(color: fs.ash), style: TextStyle(color: fs.ash),
), ),
trailing: Icon(Icons.chevron_right, color: fs.ash), trailing: Icon(LucideIcons.chevron_right, color: fs.ash),
onTap: () => context.push('/requests'), onTap: () => context.push('/requests'),
); );
} }
@@ -143,7 +144,7 @@ class _AdminSection extends ConsumerWidget {
const _Divider(), const _Divider(),
ListTile( ListTile(
key: const Key('settings_admin_card'), key: const Key('settings_admin_card'),
leading: Icon(Icons.shield, color: fs.parchment), leading: Icon(LucideIcons.shield, color: fs.parchment),
title: Text( title: Text(
'Admin', 'Admin',
style: TextStyle( style: TextStyle(
@@ -156,7 +157,7 @@ class _AdminSection extends ConsumerWidget {
'Manage requests, quarantine, and users', 'Manage requests, quarantine, and users',
style: TextStyle(color: fs.ash), style: TextStyle(color: fs.ash),
), ),
trailing: Icon(Icons.chevron_right, color: fs.ash), trailing: Icon(LucideIcons.chevron_right, color: fs.ash),
onTap: () => context.push('/admin'), onTap: () => context.push('/admin'),
), ),
], ],
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../cache/audio_cache_manager.dart'; import '../cache/audio_cache_manager.dart';
@@ -140,7 +141,7 @@ class _StorageSectionState extends ConsumerState<StorageSection> {
height: 14, height: 14,
child: CircularProgressIndicator(strokeWidth: 2), child: CircularProgressIndicator(strokeWidth: 2),
) )
: const Icon(Icons.sync, size: 16), : const Icon(LucideIcons.refresh_cw, size: 16),
label: const Text('Sync now'), label: const Text('Sync now'),
), ),
]), ]),
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -26,27 +27,27 @@ class MainAppBarActions extends ConsumerWidget {
if (currentRoute != '/home') if (currentRoute != '/home')
IconButton( IconButton(
key: const Key('app_bar_home'), key: const Key('app_bar_home'),
icon: Icon(Icons.home, color: fs.parchment), icon: Icon(LucideIcons.house, color: fs.parchment),
tooltip: 'Home', tooltip: 'Home',
onPressed: () => context.go('/home'), onPressed: () => context.go('/home'),
), ),
if (currentRoute != '/library') if (currentRoute != '/library')
IconButton( IconButton(
key: const Key('app_bar_library'), key: const Key('app_bar_library'),
icon: Icon(Icons.library_music, color: fs.parchment), icon: Icon(LucideIcons.library_big, color: fs.parchment),
tooltip: 'Library', tooltip: 'Library',
onPressed: () => context.push('/library'), onPressed: () => context.push('/library'),
), ),
if (currentRoute != '/search') if (currentRoute != '/search')
IconButton( IconButton(
key: const Key('app_bar_search'), key: const Key('app_bar_search'),
icon: Icon(Icons.search, color: fs.parchment), icon: Icon(LucideIcons.search, color: fs.parchment),
tooltip: 'Search', tooltip: 'Search',
onPressed: () => context.push('/search'), onPressed: () => context.push('/search'),
), ),
PopupMenuButton<String>( PopupMenuButton<String>(
key: const Key('app_bar_overflow'), key: const Key('app_bar_overflow'),
icon: Icon(Icons.more_vert, color: fs.parchment), icon: Icon(LucideIcons.ellipsis_vertical, color: fs.parchment),
tooltip: 'More', tooltip: 'More',
onSelected: (route) => context.push(route), onSelected: (route) => context.push(route),
itemBuilder: (_) => [ itemBuilder: (_) => [
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../playlists/playlists_provider.dart'; import '../../../playlists/playlists_provider.dart';
@@ -70,7 +71,7 @@ class AddToPlaylistSheet extends ConsumerWidget {
final p = owned[i]; final p = owned[i];
return ListTile( return ListTile(
key: Key('add_to_playlist_${p.id}'), key: Key('add_to_playlist_${p.id}'),
leading: Icon(Icons.queue_music, color: fs.parchment), leading: Icon(LucideIcons.list_music, color: fs.parchment),
title: Text( title: Text(
p.name, p.name,
style: TextStyle(color: fs.parchment), style: TextStyle(color: fs.parchment),
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../../models/track.dart'; import '../../../models/track.dart';
import '../../../theme/theme_extension.dart'; import '../../../theme/theme_extension.dart';
@@ -29,7 +30,7 @@ class TrackActionsButton extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final fs = Theme.of(context).extension<FabledSwordTheme>()!; final fs = Theme.of(context).extension<FabledSwordTheme>()!;
return IconButton( return IconButton(
icon: Icon(Icons.more_vert, color: fs.ash, size: 18), icon: Icon(LucideIcons.ellipsis_vertical, color: fs.ash, size: 18),
tooltip: 'Track actions', tooltip: 'Track actions',
onPressed: () => TrackActionsSheet.show( onPressed: () => TrackActionsSheet.show(
context, context,
@@ -1,5 +1,6 @@
import 'package:drift/drift.dart' as drift; import 'package:drift/drift.dart' as drift;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
@@ -73,7 +74,7 @@ class TrackActionsSheet extends ConsumerWidget {
if (!hideQueueActions) ...[ if (!hideQueueActions) ...[
_MenuItem( _MenuItem(
key: const Key('track_actions_play_next'), key: const Key('track_actions_play_next'),
icon: Icons.playlist_play, icon: LucideIcons.list_video,
label: 'Play next', label: 'Play next',
onTap: () async { onTap: () async {
Navigator.pop(context); Navigator.pop(context);
@@ -87,7 +88,7 @@ class TrackActionsSheet extends ConsumerWidget {
), ),
_MenuItem( _MenuItem(
key: const Key('track_actions_enqueue'), key: const Key('track_actions_enqueue'),
icon: Icons.queue_music, icon: LucideIcons.list_music,
label: 'Add to queue', label: 'Add to queue',
onTap: () async { onTap: () async {
Navigator.pop(context); Navigator.pop(context);
@@ -103,7 +104,7 @@ class TrackActionsSheet extends ConsumerWidget {
], ],
_MenuItem( _MenuItem(
key: const Key('track_actions_like'), key: const Key('track_actions_like'),
icon: liked ? Icons.favorite : Icons.favorite_border, icon: LucideIcons.heart,
label: liked ? 'Unlike' : 'Like', label: liked ? 'Unlike' : 'Like',
onTap: () async { onTap: () async {
Navigator.pop(context); Navigator.pop(context);
@@ -112,7 +113,7 @@ class TrackActionsSheet extends ConsumerWidget {
), ),
_MenuItem( _MenuItem(
key: const Key('track_actions_add_to_playlist'), key: const Key('track_actions_add_to_playlist'),
icon: Icons.playlist_add, icon: LucideIcons.list_plus,
label: 'Add to playlist…', label: 'Add to playlist…',
onTap: () async { onTap: () async {
Navigator.pop(context); Navigator.pop(context);
@@ -136,7 +137,7 @@ class TrackActionsSheet extends ConsumerWidget {
), ),
_MenuItem( _MenuItem(
key: const Key('track_actions_start_radio'), key: const Key('track_actions_start_radio'),
icon: Icons.radio, icon: LucideIcons.radio,
label: 'Start radio', label: 'Start radio',
onTap: () async { onTap: () async {
Navigator.pop(context); Navigator.pop(context);
@@ -154,7 +155,7 @@ class TrackActionsSheet extends ConsumerWidget {
const _Divider(), const _Divider(),
_MenuItem( _MenuItem(
key: const Key('track_actions_go_to_album'), key: const Key('track_actions_go_to_album'),
icon: Icons.album, icon: LucideIcons.disc_3,
label: 'Go to album', label: 'Go to album',
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -168,7 +169,7 @@ class TrackActionsSheet extends ConsumerWidget {
), ),
_MenuItem( _MenuItem(
key: const Key('track_actions_go_to_artist'), key: const Key('track_actions_go_to_artist'),
icon: Icons.person, icon: LucideIcons.user,
label: 'Go to artist', label: 'Go to artist',
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@@ -183,7 +184,7 @@ class TrackActionsSheet extends ConsumerWidget {
const _Divider(), const _Divider(),
_MenuItem( _MenuItem(
key: const Key('track_actions_hide'), key: const Key('track_actions_hide'),
icon: hidden ? Icons.visibility : Icons.visibility_off, icon: hidden ? LucideIcons.eye : LucideIcons.eye_off,
label: hidden ? 'Unhide' : 'Hide', label: hidden ? 'Unhide' : 'Hide',
onTap: () async { onTap: () async {
Navigator.pop(context); Navigator.pop(context);
@@ -2,6 +2,7 @@ import 'dart:async';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:pub_semver/pub_semver.dart'; import 'package:pub_semver/pub_semver.dart';
@@ -238,7 +239,7 @@ class VersionTooOldBanner extends ConsumerWidget {
color: fs.error.withValues(alpha: 0.15), color: fs.error.withValues(alpha: 0.15),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Row(children: [ child: Row(children: [
Icon(Icons.warning_amber_rounded, color: fs.error, size: 18), Icon(LucideIcons.triangle_alert, color: fs.error, size: 18),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: Text( child: Text(
+3 -2
View File
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../theme/theme_extension.dart'; import '../theme/theme_extension.dart';
@@ -66,7 +67,7 @@ class _UpdateBannerState extends ConsumerState<UpdateBanner> {
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Icon(Icons.system_update, color: fs.parchment, size: 16), Icon(LucideIcons.download, color: fs.parchment, size: 16),
const SizedBox(width: 8), const SizedBox(width: 8),
Expanded( Expanded(
child: Column( child: Column(
@@ -132,7 +133,7 @@ class _UpdateBannerState extends ConsumerState<UpdateBanner> {
tooltip: 'Dismiss', tooltip: 'Dismiss',
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 16, iconSize: 16,
icon: Icon(Icons.close, color: fs.ash), icon: Icon(LucideIcons.x, color: fs.ash),
onPressed: () => _onDismiss(info), onPressed: () => _onDismiss(info),
), ),
), ),