@@ -32,7 +32,7 @@ StyledRect {
3232 anchors .margins : Appearance .padding .large
3333 spacing: Appearance .spacing .normal
3434
35- // Header: icon, backend name , refresh, toggle
35+ // Header: icon, backend selector , refresh, toggle
3636 RowLayout {
3737 Layout .fillWidth : true
3838 spacing: Appearance .padding .small
@@ -44,12 +44,49 @@ StyledRect {
4444 font .pointSize : Appearance .spacing .large
4545 }
4646
47- StyledText {
47+ Rectangle {
48+ Layout .preferredHeight : 24
49+ Layout .preferredWidth : 80
50+ radius: Appearance .rounding .small
51+ color: Qt .rgba (Colours .palette .m3primary .r , Colours .palette .m3primary .g , Colours .palette .m3primary .b , 0.15 )
52+
53+ StyledText {
54+ anchors .centerIn : parent
55+ text: LyricsService .preferredBackend
56+ font .pointSize : Appearance .font .size .small
57+ color: Colours .palette .m3primary
58+ }
59+
60+ MouseArea {
61+ anchors .fill : parent
62+ cursorShape: Qt .PointingHandCursor
63+ onClicked: {
64+ const backends = [" Auto" , " Local" , " NetEase" ];
65+ const currentIndex = backends .indexOf (LyricsService .preferredBackend );
66+ const nextIndex = (currentIndex + 1 ) % backends .length ;
67+ LyricsService .preferredBackend = backends[nextIndex];
68+ LyricsService .loadLyrics ();
69+ }
70+ }
71+ }
72+
73+ Rectangle {
74+ Layout .preferredHeight : 24
75+ Layout .preferredWidth : 60
76+ radius: Appearance .rounding .small
77+ visible: LyricsService .preferredBackend === " Auto"
78+ color: LyricsService .backend === " Local" ? Qt .rgba (Colours .palette .m3tertiary .r , Colours .palette .m3tertiary .g , Colours .palette .m3tertiary .b , 0.15 ) : Qt .rgba (Colours .palette .m3secondary .r , Colours .palette .m3secondary .g , Colours .palette .m3secondary .b , 0.15 )
79+
80+ StyledText {
81+ anchors .centerIn : parent
82+ text: LyricsService .backend
83+ font .pointSize : Appearance .font .size .small
84+ color: LyricsService .backend === " Local" ? Colours .palette .m3tertiary : Colours .palette .m3secondary
85+ }
86+ }
87+
88+ Item {
4889 Layout .fillWidth : true
49- text: LyricsService .backend
50- font .pointSize : Appearance .font .size .normal
51- color: Colours .palette .m3secondary
52- elide: Text .ElideRight
5390 }
5491
5592 IconButton {
@@ -66,117 +103,141 @@ StyledRect {
66103
67104 StyledText {
68105 Layout .fillWidth : true
69- text: " Fetched Candidates:"
106+ text: LyricsService . preferredBackend === " Local " ? " Loaded File: " : " Fetched Candidates:"
70107 color: Colours .palette .m3outline
71108 font .pointSize : Appearance .font .size .small
72109 elide: Text .ElideRight
110+ visible: LyricsService .preferredBackend === " Local" ? LyricsService .loadedLocalFile .length > 0 : LyricsService .candidatesModel .count > 0
73111 }
74112
75- // Candidates list
76- ListView {
77- id: candidatesView
78-
113+ // Local file info (shown in Local mode)
114+ Rectangle {
79115 Layout .fillWidth : true
80- Layout .fillHeight : true
116+ Layout .preferredHeight : 48
117+ visible: LyricsService .preferredBackend === " Local" && LyricsService .loadedLocalFile .length > 0
118+ radius: Appearance .rounding .small
119+ color: Qt .rgba (Colours .palette .m3tertiary .r , Colours .palette .m3tertiary .g , Colours .palette .m3tertiary .b , 0.1 )
120+
121+ ColumnLayout {
122+ anchors .fill : parent
123+ anchors .margins : Appearance .padding .small
124+ spacing: 0
81125
82- visible: LyricsService .candidatesModel .count > 0
83- model: LyricsService .candidatesModel
84- clip: true
85- spacing: Appearance .spacing .small
86-
87- opacity: visible ? 1 : 0
88- // Behavior on opacity {
89- // NumberAnimation { duration: Appearance.anim.durations.normal }
90- // }
91-
92- delegate: Item {
93- id: delegateRoot
94-
95- required property real id
96- required property string title
97- required property string artist
98- property bool hovered: false
99- property bool pressed: false
100-
101- width: ListView .view .width * 0.98
102- height: 70
103- anchors .horizontalCenter : parent? .horizontalCenter
104- scale: hovered ? 1.02 : 1.0
105-
106- Behavior on scale {
107- NumberAnimation {
108- duration: Appearance .anim .durations .small
109- easing .type : Easing .OutCubic
126+ StyledText {
127+ Layout .fillWidth : true
128+ text: {
129+ const path = LyricsService .loadedLocalFile ;
130+ const parts = path .split (' /' );
131+ return parts[parts .length - 1 ];
110132 }
133+ font .pointSize : Appearance .font .size .small
134+ color: Colours .palette .m3tertiary
135+ elide: Text .ElideMiddle
111136 }
112137
113- Rectangle {
114- id: background
138+ StyledText {
139+ Layout .fillWidth : true
140+ text: {
141+ const path = LyricsService .loadedLocalFile ;
142+ const parts = path .split (' /' );
143+ if (parts .length > 2 ) {
144+ return parts .slice (- 3 , - 1 ).join (' /' );
145+ }
146+ return " " ;
147+ }
148+ font .pointSize : Appearance .font .size .small
149+ color: Colours .palette .m3outline
150+ elide: Text .ElideMiddle
151+ }
152+ }
153+ }
115154
116- anchors .fill : parent
117- radius: Appearance .rounding .small
155+ // Candidates list
156+ Loader {
157+ Layout .fillWidth : true
158+ Layout .fillHeight : true
118159
119- color : delegateRoot . pressed ? Qt . rgba ( Colours . palette . m3primary . r , Colours . palette . m3primary . g , Colours . palette . m3primary . b , 0.25 ) : delegateRoot . hovered ? Qt . rgba ( Colours . palette . m3primary . r , Colours . palette . m3primary . g , Colours . palette . m3primary . b , 0.06 ) : Qt . rgba ( Colours . palette . m3primary . r , Colours . palette . m3primary . g , Colours . palette . m3primary . b , 0.03 )
160+ active : LyricsService . preferredBackend !== " Local "
120161
121- border . width : delegateRoot . hovered ? 1 : 0
122- border . color : Colours . palette . m3primary
162+ sourceComponent : ListView {
163+ id : candidatesView
123164
124- Behavior on color {
125- ColorAnimation {
126- duration: Appearance .anim .durations .small
127- }
128- }
129- Behavior on border .width {
165+ model: LyricsService .candidatesModel
166+ clip: true
167+ spacing: Appearance .spacing .small
168+ visible: LyricsService .candidatesModel .count > 0
169+ opacity: visible ? 1 : 0
170+
171+ delegate: Item {
172+ id: delegateRoot
173+
174+ required property real id
175+ required property string title
176+ required property string artist
177+
178+ property bool hovered: false
179+ property bool pressed: false
180+
181+ width: ListView .view .width * 0.98
182+ height: 70
183+
184+ anchors .horizontalCenter : parent? .horizontalCenter
185+ scale: hovered ? 1.02 : 1.0
186+
187+ Behavior on scale {
130188 NumberAnimation {
131189 duration: Appearance .anim .durations .small
190+ easing .type : Easing .OutCubic
132191 }
133192 }
134- }
135193
136- MouseArea {
137- anchors .fill : parent
138- hoverEnabled: true
139- cursorShape: Qt .PointingHandCursor
194+ Rectangle {
195+ id: background
140196
141- onEntered: delegateRoot .hovered = true
142- onExited: delegateRoot .hovered = false
143- onPressed: delegateRoot .pressed = true
144- onReleased: delegateRoot .pressed = false
145- onClicked: LyricsService .selectCandidate (delegateRoot .id )
146- }
197+ anchors .fill : parent
198+ radius: Appearance .rounding .small
147199
148- Row {
149- anchors .fill : parent
150- anchors .margins : Appearance .padding .normal
151- spacing: Appearance .spacing .small
200+ color: delegateRoot .pressed ? Qt .rgba (Colours .palette .m3primary .r , Colours .palette .m3primary .g , Colours .palette .m3primary .b , 0.25 ) : delegateRoot .hovered ? Qt .rgba (Colours .palette .m3primary .r , Colours .palette .m3primary .g , Colours .palette .m3primary .b , 0.06 ) : Qt .rgba (Colours .palette .m3primary .r , Colours .palette .m3primary .g , Colours .palette .m3primary .b , 0.03 )
152201
153- // Active indicator bar
154- Rectangle {
155- width: 4
156- height: parent .height * 0.6
157- radius: 2
158- anchors .verticalCenter : parent .verticalCenter
159- color: LyricsService .currentSongId === delegateRoot .id ? Colours .palette .m3primary : " transparent"
202+ border .width : delegateRoot .hovered ? 1 : 0
203+ border .color : Colours .palette .m3primary
160204
161205 Behavior on color {
162206 ColorAnimation {
163207 duration: Appearance .anim .durations .small
164208 }
165209 }
210+ Behavior on border .width {
211+ NumberAnimation {
212+ duration: Appearance .anim .durations .small
213+ }
214+ }
166215 }
167216
168- Column {
169- anchors .verticalCenter : parent . verticalCenter
170- width : parent . width - 30
171- spacing : 4
217+ MouseArea {
218+ anchors .fill : parent
219+ hoverEnabled : true
220+ cursorShape : Qt . PointingHandCursor
172221
173- Text {
174- text: delegateRoot .title
175- font .pointSize : Appearance .font .size .normal
176- font .bold : true
177- color: delegateRoot .hovered ? Colours .palette .m3primary : Colours .palette .m3onSurface
178- width: parent .width
179- elide: Text .ElideRight
222+ onEntered: delegateRoot .hovered = true
223+ onExited: delegateRoot .hovered = false
224+ onPressed: delegateRoot .pressed = true
225+ onReleased: delegateRoot .pressed = false
226+ onClicked: LyricsService .selectCandidate (delegateRoot .id )
227+ }
228+
229+ Row {
230+ anchors .fill : parent
231+ anchors .margins : Appearance .padding .normal
232+ spacing: Appearance .spacing .small
233+
234+ // Active indicator bar
235+ Rectangle {
236+ width: 4
237+ height: parent .height * 0.6
238+ radius: 2
239+ anchors .verticalCenter : parent .verticalCenter
240+ color: LyricsService .currentSongId === delegateRoot .id ? Colours .palette .m3primary : " transparent"
180241
181242 Behavior on color {
182243 ColorAnimation {
@@ -185,11 +246,32 @@ StyledRect {
185246 }
186247 }
187248
188- Text {
189- text: delegateRoot .artist
190- font .pointSize : Appearance .font .size .small
191- color: Colours .palette .m3onSurfaceVariant
192- elide: Text .ElideRight
249+ Column {
250+ anchors .verticalCenter : parent .verticalCenter
251+ width: parent .width - 30
252+ spacing: 4
253+
254+ Text {
255+ text: delegateRoot .title
256+ font .pointSize : Appearance .font .size .normal
257+ font .bold : true
258+ color: delegateRoot .hovered ? Colours .palette .m3primary : Colours .palette .m3onSurface
259+ width: parent .width
260+ elide: Text .ElideRight
261+
262+ Behavior on color {
263+ ColorAnimation {
264+ duration: Appearance .anim .durations .small
265+ }
266+ }
267+ }
268+
269+ Text {
270+ text: delegateRoot .artist
271+ font .pointSize : Appearance .font .size .small
272+ color: Colours .palette .m3onSurfaceVariant
273+ elide: Text .ElideRight
274+ }
193275 }
194276 }
195277 }
@@ -198,7 +280,7 @@ StyledRect {
198280
199281 Item {
200282 Layout .fillHeight : true
201- visible: LyricsService .candidatesModel .count == 0
283+ visible: LyricsService .candidatesModel .count == 0 && LyricsService . preferredBackend !== " Local "
202284 }
203285
204286 // Manual search
0 commit comments