11import 'package:flutter/material.dart' ;
2+ import 'package:lrc/lrc.dart' ;
23import 'package:watch_it/watch_it.dart' ;
34
5+ import '../../common/data/audio.dart' ;
46import '../../common/view/ui_constants.dart' ;
57import '../../extensions/build_context_x.dart' ;
68import '../../extensions/taget_platform_x.dart' ;
79import '../../local_audio/view/local_cover.dart' ;
10+ import '../../settings/settings_model.dart' ;
811import '../player_model.dart' ;
912import 'audio_visualizer.dart' ;
1013import 'player_fall_back_image.dart' ;
@@ -33,6 +36,9 @@ class FullHeightPlayerImage extends StatelessWidget with WatchItMixin {
3336 final showAudioVisualizer = watchPropertyValue (
3437 (PlayerModel m) => m.showAudioVisualizer && this .showAudioVisualizer,
3538 );
39+ final showPlayerLyrics = watchPropertyValue (
40+ (SettingsModel m) => m.showPlayerLyrics,
41+ );
3642
3743 final size = context.isPortrait
3844 ? fullHeightPlayerImageSize
@@ -74,6 +80,10 @@ class FullHeightPlayerImage extends StatelessWidget with WatchItMixin {
7480 return AudioVisualizer (height: height ?? 200 );
7581 }
7682
83+ if (showPlayerLyrics && audio != null ) {
84+ return PlayerLyrics (audio: audio, size: size);
85+ }
86+
7787 return SizedBox (
7888 height: theHeight,
7989 width: theWidth,
@@ -87,3 +97,63 @@ class FullHeightPlayerImage extends StatelessWidget with WatchItMixin {
8797 );
8898 }
8999}
100+
101+ class PlayerLyrics extends StatefulWidget with WatchItStatefulWidgetMixin {
102+ const PlayerLyrics ({super .key, required this .audio, required this .size});
103+
104+ final Audio audio;
105+ final double size;
106+
107+ @override
108+ State <PlayerLyrics > createState () => _PlayerLyricsState ();
109+ }
110+
111+ class _PlayerLyricsState extends State <PlayerLyrics > {
112+ List <LrcLine >? lrc;
113+ String ? lyrcisString;
114+
115+ @override
116+ void initState () {
117+ super .initState ();
118+
119+ if (widget.audio.lyrics != null ) {
120+ if (widget.audio.lyrics! .isValidLrc) {
121+ lrc = Lrc .parse (widget.audio.lyrics! ).lyrics;
122+ } else {
123+ lyrcisString = widget.audio.lyrics;
124+ }
125+ }
126+ }
127+
128+ @override
129+ Widget build (BuildContext context) {
130+ if (lyrcisString != null ) {
131+ return Text (lyrcisString! );
132+ }
133+
134+ if (lrc == null || lrc! .isEmpty) {
135+ return const Text ('no lyrcis found' );
136+ }
137+
138+ final position = watchPropertyValue ((PlayerModel m) => m.position);
139+ final color = watchPropertyValue (
140+ (PlayerModel m) => m.color ?? context.colorScheme.primary,
141+ );
142+
143+ return SizedBox (
144+ height: widget.size,
145+ width: widget.size,
146+ child: ListView .builder (
147+ itemCount: lrc! .length,
148+ itemBuilder: (context, index) {
149+ final line = lrc! .elementAt (index);
150+ return ListTile (
151+ selectedColor: color,
152+ selected: line.timestamp.inSeconds == position? .inSeconds,
153+ title: Text (line.lyrics),
154+ );
155+ },
156+ ),
157+ );
158+ }
159+ }
0 commit comments