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_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
@@ -26,27 +27,27 @@ class MainAppBarActions extends ConsumerWidget {
if (currentRoute != '/home')
IconButton(
key: const Key('app_bar_home'),
icon: Icon(Icons.home, color: fs.parchment),
icon: Icon(LucideIcons.house, color: fs.parchment),
tooltip: 'Home',
onPressed: () => context.go('/home'),
),
if (currentRoute != '/library')
IconButton(
key: const Key('app_bar_library'),
icon: Icon(Icons.library_music, color: fs.parchment),
icon: Icon(LucideIcons.library_big, color: fs.parchment),
tooltip: 'Library',
onPressed: () => context.push('/library'),
),
if (currentRoute != '/search')
IconButton(
key: const Key('app_bar_search'),
icon: Icon(Icons.search, color: fs.parchment),
icon: Icon(LucideIcons.search, color: fs.parchment),
tooltip: 'Search',
onPressed: () => context.push('/search'),
),
PopupMenuButton<String>(
key: const Key('app_bar_overflow'),
icon: Icon(Icons.more_vert, color: fs.parchment),
icon: Icon(LucideIcons.ellipsis_vertical, color: fs.parchment),
tooltip: 'More',
onSelected: (route) => context.push(route),
itemBuilder: (_) => [
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../playlists/playlists_provider.dart';
@@ -70,7 +71,7 @@ class AddToPlaylistSheet extends ConsumerWidget {
final p = owned[i];
return ListTile(
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(
p.name,
style: TextStyle(color: fs.parchment),
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../../models/track.dart';
import '../../../theme/theme_extension.dart';
@@ -29,7 +30,7 @@ class TrackActionsButton extends StatelessWidget {
Widget build(BuildContext context) {
final fs = Theme.of(context).extension<FabledSwordTheme>()!;
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',
onPressed: () => TrackActionsSheet.show(
context,
@@ -1,5 +1,6 @@
import 'package:drift/drift.dart' as drift;
import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
@@ -73,7 +74,7 @@ class TrackActionsSheet extends ConsumerWidget {
if (!hideQueueActions) ...[
_MenuItem(
key: const Key('track_actions_play_next'),
icon: Icons.playlist_play,
icon: LucideIcons.list_video,
label: 'Play next',
onTap: () async {
Navigator.pop(context);
@@ -87,7 +88,7 @@ class TrackActionsSheet extends ConsumerWidget {
),
_MenuItem(
key: const Key('track_actions_enqueue'),
icon: Icons.queue_music,
icon: LucideIcons.list_music,
label: 'Add to queue',
onTap: () async {
Navigator.pop(context);
@@ -103,7 +104,7 @@ class TrackActionsSheet extends ConsumerWidget {
],
_MenuItem(
key: const Key('track_actions_like'),
icon: liked ? Icons.favorite : Icons.favorite_border,
icon: LucideIcons.heart,
label: liked ? 'Unlike' : 'Like',
onTap: () async {
Navigator.pop(context);
@@ -112,7 +113,7 @@ class TrackActionsSheet extends ConsumerWidget {
),
_MenuItem(
key: const Key('track_actions_add_to_playlist'),
icon: Icons.playlist_add,
icon: LucideIcons.list_plus,
label: 'Add to playlist…',
onTap: () async {
Navigator.pop(context);
@@ -136,7 +137,7 @@ class TrackActionsSheet extends ConsumerWidget {
),
_MenuItem(
key: const Key('track_actions_start_radio'),
icon: Icons.radio,
icon: LucideIcons.radio,
label: 'Start radio',
onTap: () async {
Navigator.pop(context);
@@ -154,7 +155,7 @@ class TrackActionsSheet extends ConsumerWidget {
const _Divider(),
_MenuItem(
key: const Key('track_actions_go_to_album'),
icon: Icons.album,
icon: LucideIcons.disc_3,
label: 'Go to album',
onTap: () {
Navigator.pop(context);
@@ -168,7 +169,7 @@ class TrackActionsSheet extends ConsumerWidget {
),
_MenuItem(
key: const Key('track_actions_go_to_artist'),
icon: Icons.person,
icon: LucideIcons.user,
label: 'Go to artist',
onTap: () {
Navigator.pop(context);
@@ -183,7 +184,7 @@ class TrackActionsSheet extends ConsumerWidget {
const _Divider(),
_MenuItem(
key: const Key('track_actions_hide'),
icon: hidden ? Icons.visibility : Icons.visibility_off,
icon: hidden ? LucideIcons.eye : LucideIcons.eye_off,
label: hidden ? 'Unhide' : 'Hide',
onTap: () async {
Navigator.pop(context);
@@ -2,6 +2,7 @@ import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:pub_semver/pub_semver.dart';
@@ -238,7 +239,7 @@ class VersionTooOldBanner extends ConsumerWidget {
color: fs.error.withValues(alpha: 0.15),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
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),
Expanded(
child: Text(