Skip to content

Commit a31756e

Browse files
committed
feat(ui): circuit screen v2
1 parent e6fba59 commit a31756e

File tree

12 files changed

+1248
-1487
lines changed

12 files changed

+1248
-1487
lines changed

lib/Screens/Racing/circuit.dart

Lines changed: 756 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* This file is part of BoxBox (https://github.com/BrightDV/BoxBox).
3+
*
4+
* BoxBox is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Lesser General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* BoxBox is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License
15+
* along with BoxBox. If not, see <http://www.gnu.org/licenses/>.
16+
*
17+
* Copyright (c) 2022-2025, BrightDV
18+
*/
19+
20+
import 'package:boxbox/Screens/circuit_map_screen.dart';
21+
import 'package:boxbox/helpers/buttons.dart';
22+
import 'package:boxbox/helpers/convert_ergast_and_formula_one.dart';
23+
import 'package:boxbox/helpers/loading_indicator_util.dart';
24+
import 'package:boxbox/l10n/app_localizations.dart';
25+
import 'package:flutter/material.dart';
26+
import 'package:flutter_markdown/flutter_markdown.dart';
27+
28+
class CircuitDetailsScreen extends StatelessWidget {
29+
final String trackCountry;
30+
final String trackName;
31+
final String trackImageUrl;
32+
final String trackDetailsText;
33+
final List circuitMap;
34+
const CircuitDetailsScreen(
35+
this.trackCountry,
36+
this.trackName,
37+
this.trackImageUrl,
38+
this.trackDetailsText,
39+
this.circuitMap, {
40+
super.key,
41+
});
42+
43+
@override
44+
Widget build(BuildContext context) {
45+
return Scaffold(
46+
appBar: AppBar(
47+
title: Text(trackName),
48+
backgroundColor: Theme.of(context).colorScheme.onPrimary,
49+
),
50+
body: SingleChildScrollView(
51+
child: Column(
52+
children: [
53+
SizedBox(
54+
height: MediaQuery.of(context).size.width / (16 / 9),
55+
child: TrackLayoutImage(trackImageUrl),
56+
),
57+
BoxBoxButton(
58+
AppLocalizations.of(context)!.grandPrixMap,
59+
Icon(
60+
Icons.map_outlined,
61+
),
62+
widget: CircuitMapScreen(
63+
Convert().circuitNameFromFormulaOneToErgastForCircuitPoints(
64+
trackCountry,
65+
),
66+
),
67+
isDialog: true,
68+
),
69+
for (var link in circuitMap)
70+
if (!(link['text'].contains('Buy') ||
71+
link['text'].contains('Guide') ||
72+
link['text'].contains('Results')))
73+
BoxBoxButton(
74+
link['text'],
75+
Icon(
76+
Icons.article_outlined,
77+
),
78+
route: 'article',
79+
pathParameters: {
80+
'id': link['url'].split('.').last,
81+
},
82+
extra: {'isFromLink': true},
83+
),
84+
Padding(
85+
padding: const EdgeInsets.only(
86+
top: 10,
87+
left: 10,
88+
right: 10,
89+
),
90+
child: MarkdownBody(
91+
data: trackDetailsText,
92+
selectable: true,
93+
fitContent: false,
94+
styleSheet: MarkdownStyleSheet(
95+
strong: TextStyle(
96+
fontSize: 16,
97+
fontWeight: FontWeight.w500,
98+
color: Theme.of(context).colorScheme.primary,
99+
),
100+
p: TextStyle(
101+
fontSize: 14,
102+
),
103+
pPadding: EdgeInsets.only(
104+
top: 10,
105+
bottom: 10,
106+
),
107+
a: TextStyle(
108+
color: Theme.of(context).colorScheme.primary,
109+
decoration: TextDecoration.underline,
110+
decorationColor: Theme.of(context).colorScheme.primary,
111+
fontWeight: FontWeight.normal,
112+
),
113+
textAlign: WrapAlignment.spaceBetween,
114+
),
115+
),
116+
),
117+
],
118+
),
119+
),
120+
);
121+
}
122+
}
123+
124+
class TrackLayoutImage extends StatelessWidget {
125+
final String url;
126+
const TrackLayoutImage(
127+
this.url, {
128+
Key? key,
129+
}) : super(key: key);
130+
131+
@override
132+
Widget build(BuildContext context) {
133+
return GestureDetector(
134+
onTap: () {
135+
showDialog(
136+
context: context,
137+
builder: (BuildContext context) {
138+
return AlertDialog(
139+
contentPadding: const EdgeInsets.only(
140+
top: 52,
141+
bottom: 50,
142+
),
143+
insetPadding: EdgeInsets.zero,
144+
shape: RoundedRectangleBorder(
145+
borderRadius: BorderRadius.circular(10.0),
146+
),
147+
backgroundColor: Colors.transparent,
148+
shadowColor: Colors.black,
149+
surfaceTintColor: Colors.transparent,
150+
content: Builder(
151+
builder: (context) {
152+
return SizedBox(
153+
width: double.infinity - 10,
154+
child: InteractiveViewer(
155+
minScale: 0.1,
156+
maxScale: 8,
157+
child: Stack(
158+
children: [
159+
GestureDetector(
160+
onTap: () => Navigator.pop(context),
161+
),
162+
Card(
163+
color: Colors.black,
164+
elevation: 5.0,
165+
shape: RoundedRectangleBorder(
166+
borderRadius: BorderRadius.circular(5),
167+
),
168+
clipBehavior: Clip.antiAlias,
169+
child: Image(
170+
image: NetworkImage(url),
171+
loadingBuilder: (context, child,
172+
loadingProgress) =>
173+
loadingProgress == null
174+
? child
175+
: SizedBox(
176+
height: MediaQuery.of(context)
177+
.size
178+
.width /
179+
(16 / 9),
180+
child: const LoadingIndicatorUtil(),
181+
),
182+
errorBuilder: (context, url, error) => Icon(
183+
Icons.error_outlined,
184+
size: 30,
185+
),
186+
),
187+
),
188+
Align(
189+
alignment: Alignment.topRight,
190+
child: IconButton(
191+
onPressed: () => Navigator.pop(context),
192+
icon: const Icon(
193+
Icons.close_rounded,
194+
color: Colors.white,
195+
),
196+
),
197+
),
198+
],
199+
),
200+
),
201+
);
202+
},
203+
),
204+
);
205+
},
206+
);
207+
},
208+
child: Padding(
209+
padding: const EdgeInsets.all(5),
210+
child: Stack(
211+
alignment: Alignment.bottomCenter,
212+
children: [
213+
Image.network(
214+
url,
215+
loadingBuilder: (context, child, loadingProgress) =>
216+
loadingProgress == null
217+
? child
218+
: SizedBox(
219+
height: MediaQuery.of(context).size.width / (16 / 9),
220+
child: const LoadingIndicatorUtil(),
221+
),
222+
errorBuilder: (context, url, error) => Icon(
223+
Icons.error_outlined,
224+
size: 30,
225+
),
226+
),
227+
],
228+
),
229+
),
230+
);
231+
}
232+
}

0 commit comments

Comments
 (0)