@@ -6,6 +6,37 @@ import 'package:iris/models/file.dart';
66import 'package:iris/models/storages/storage.dart' ;
77import 'package:iris/store/use_storage_store.dart' ;
88
9+ class _CoverImage extends StatelessWidget {
10+ final FileItem cover;
11+ final String ? auth;
12+ final BoxFit fit;
13+
14+ const _CoverImage ({
15+ required this .cover,
16+ required this .auth,
17+ required this .fit,
18+ });
19+
20+ @override
21+ Widget build (BuildContext context) {
22+ final isLocal = cover.storageId == localStorageId;
23+ if (isLocal) {
24+ return Image .file (
25+ File (cover.uri),
26+ fit: fit,
27+ gaplessPlayback: true ,
28+ );
29+ } else {
30+ return Image .network (
31+ cover.uri,
32+ headers: auth != null ? {'authorization' : auth! } : null ,
33+ fit: fit,
34+ gaplessPlayback: true ,
35+ );
36+ }
37+ }
38+ }
39+
940class Audio extends HookWidget {
1041 const Audio ({
1142 super .key,
@@ -22,60 +53,145 @@ class Audio extends HookWidget {
2253 : useStorageStore ().findById (cover! .storageId),
2354 [cover? .storageId]);
2455 final auth = useMemoized (() => storage? .getAuth (), [storage]);
56+
2557 return IgnorePointer (
2658 child: Stack (
59+ fit: StackFit .expand,
2760 children: [
28- SizedBox (
29- width: MediaQuery .of (context).size.width,
30- height: MediaQuery .of (context).size.height,
31- child: cover != null
32- ? cover? .storageId == localStorageId
33- ? Image .file (
34- File (cover! .uri),
35- fit: BoxFit .cover,
36- )
37- : Image .network (
38- cover! .uri,
39- headers: auth != null ? {'authorization' : auth} : null ,
40- fit: BoxFit .cover,
41- )
42- : null ,
43- ),
61+ if (cover != null )
62+ _CoverImage (cover: cover! , auth: auth, fit: BoxFit .cover),
4463 BackdropFilter (
45- filter: ImageFilter .blur (sigmaX: 16.0 , sigmaY: 16.0 ),
46- child: Container (color: Colors .transparent),
64+ filter: ImageFilter .blur (sigmaX: 24.0 , sigmaY: 24.0 ),
65+ child: DecoratedBox (
66+ decoration: BoxDecoration (
67+ gradient: LinearGradient (
68+ begin: Alignment .topCenter,
69+ end: Alignment .bottomCenter,
70+ colors: [
71+ Theme .of (context)
72+ .colorScheme
73+ .surface
74+ .withValues (alpha: 0.6 ),
75+ Theme .of (context)
76+ .colorScheme
77+ .surface
78+ .withValues (alpha: 0.2 ),
79+ ],
80+ ),
81+ ),
82+ ),
4783 ),
48- Positioned (
49- left: 0 ,
50- top: 0 ,
51- right: MediaQuery .of (context).size.width > 800
52- ? MediaQuery .of (context).size.width / 2
53- : 0 ,
54- bottom: 0 ,
55- child: Center (
56- child: SizedBox (
57- height: MediaQuery .of (context).size.height / 2 ,
58- child: ClipRRect (
59- borderRadius: BorderRadius .circular (8 ),
60- child: cover != null
61- ? cover! .storageId == localStorageId
62- ? Image .file (
63- File (cover! .uri),
64- fit: BoxFit .contain,
65- )
66- : Image .network (
67- cover! .uri,
68- headers:
69- auth != null ? {'authorization' : auth} : null ,
70- fit: BoxFit .contain,
71- )
72- : null ,
84+ LayoutBuilder (
85+ builder: (context, constraints) {
86+ const double wideLayoutThreshold = 600 ;
87+ final isWideScreen = constraints.maxWidth >= wideLayoutThreshold;
88+
89+ if (isWideScreen) {
90+ return _buildWideLayout (context, constraints, cover, auth);
91+ } else {
92+ return _buildNarrowLayout (context, constraints, cover, auth);
93+ }
94+ },
95+ ),
96+ ],
97+ ),
98+ );
99+ }
100+
101+ Widget _buildNarrowLayout (BuildContext context, BoxConstraints constraints,
102+ FileItem ? cover, String ? auth) {
103+ return Align (
104+ alignment: const Alignment (0.0 , - 0.2 ),
105+ child: Padding (
106+ padding: const EdgeInsets .symmetric (horizontal: 48.0 , vertical: 24.0 ),
107+ child: ConstrainedBox (
108+ constraints: const BoxConstraints (
109+ maxWidth: 400.0 ,
110+ maxHeight: 400.0 ,
111+ ),
112+ child: AspectRatio (
113+ aspectRatio: 1.0 ,
114+ child: _buildCoverCard (
115+ cover: cover,
116+ auth: auth,
117+ shadowColor: Theme .of (context)
118+ .colorScheme
119+ .onSurface
120+ .withValues (alpha: 0.15 ),
121+ ),
122+ ),
123+ ),
124+ ),
125+ );
126+ }
127+
128+ Widget _buildWideLayout (BuildContext context, BoxConstraints constraints,
129+ FileItem ? cover, String ? auth) {
130+ return Row (
131+ children: [
132+ Expanded (
133+ flex: 5 ,
134+ child: Align (
135+ alignment: const Alignment (0.0 , - 0.2 ),
136+ child: Padding (
137+ padding: const EdgeInsets .fromLTRB (48 , 24 , 24 , 24 ),
138+ child: ConstrainedBox (
139+ constraints: const BoxConstraints (
140+ maxWidth: 400.0 ,
141+ maxHeight: 400.0 ,
142+ ),
143+ child: AspectRatio (
144+ aspectRatio: 1.0 ,
145+ child: _buildCoverCard (
146+ cover: cover,
147+ auth: auth,
148+ shadowColor: Theme .of (context)
149+ .colorScheme
150+ .onSurface
151+ .withValues (alpha: 0.15 ),
152+ ),
73153 ),
74154 ),
75155 ),
76156 ),
157+ ),
158+ Expanded (
159+ flex: 5 ,
160+ child: Container (
161+ padding:
162+ const EdgeInsets .symmetric (horizontal: 48.0 , vertical: 24.0 ),
163+ ),
164+ ),
165+ ],
166+ );
167+ }
168+
169+ Widget _buildCoverCard (
170+ {required FileItem ? cover,
171+ required String ? auth,
172+ required Color shadowColor}) {
173+ return Container (
174+ decoration: BoxDecoration (
175+ borderRadius: BorderRadius .circular (16 ),
176+ boxShadow: [
177+ BoxShadow (
178+ color: shadowColor,
179+ blurRadius: 32 ,
180+ spreadRadius: 2 ,
181+ offset: const Offset (0 , 8 ),
182+ ),
77183 ],
78184 ),
185+ child: ClipRRect (
186+ borderRadius: BorderRadius .circular (16 ),
187+ child: cover != null
188+ ? _CoverImage (
189+ cover: cover,
190+ auth: auth,
191+ fit: BoxFit .cover,
192+ )
193+ : Container (),
194+ ),
79195 );
80196 }
81197}
0 commit comments