Skip to content

Commit ae584b7

Browse files
committed
Add AboutPage and integrate navigation from SettingsPage
1 parent 8cef09c commit ae584b7

File tree

2 files changed

+289
-1
lines changed

2 files changed

+289
-1
lines changed
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:url_launcher/url_launcher.dart';
3+
4+
class AboutPage extends StatelessWidget {
5+
const AboutPage({super.key});
6+
7+
@override
8+
Widget build(BuildContext context) {
9+
return Scaffold(
10+
backgroundColor: const Color(0xFF121212),
11+
body: SingleChildScrollView(
12+
padding: const EdgeInsets.all(32.0),
13+
child: Center(
14+
child: ConstrainedBox(
15+
constraints: const BoxConstraints(maxWidth: 800),
16+
child: Column(
17+
crossAxisAlignment: CrossAxisAlignment.center,
18+
children: [
19+
const SizedBox(height: 32),
20+
21+
// App Icon
22+
Container(
23+
width: 120,
24+
height: 120,
25+
decoration: BoxDecoration(
26+
borderRadius: BorderRadius.circular(20),
27+
gradient: LinearGradient(
28+
begin: Alignment.topLeft,
29+
end: Alignment.bottomRight,
30+
colors: [
31+
Colors.purple.shade700,
32+
Colors.blue.shade700,
33+
],
34+
),
35+
),
36+
child: const Icon(
37+
Icons.music_note,
38+
size: 64,
39+
color: Colors.white,
40+
),
41+
),
42+
43+
const SizedBox(height: 24),
44+
45+
// App Name
46+
const Text(
47+
'Obscurify',
48+
style: TextStyle(
49+
color: Colors.white,
50+
fontSize: 48,
51+
fontWeight: FontWeight.bold,
52+
),
53+
),
54+
55+
const SizedBox(height: 8),
56+
57+
// Version
58+
const Text(
59+
'Version 1.0.0',
60+
style: TextStyle(
61+
color: Colors.grey,
62+
fontSize: 16,
63+
),
64+
),
65+
66+
const SizedBox(height: 24),
67+
68+
// Tagline
69+
const Text(
70+
'Your music. Your way. Everywhere.',
71+
style: TextStyle(
72+
color: Colors.white70,
73+
fontSize: 20,
74+
fontStyle: FontStyle.italic,
75+
),
76+
textAlign: TextAlign.center,
77+
),
78+
79+
const SizedBox(height: 32),
80+
81+
// Description
82+
const Text(
83+
'The Spotify experience you love, powered by your own Plex music library.',
84+
style: TextStyle(
85+
color: Colors.white,
86+
fontSize: 18,
87+
height: 1.5,
88+
),
89+
textAlign: TextAlign.center,
90+
),
91+
92+
const SizedBox(height: 48),
93+
94+
// Features Section
95+
_buildSection(
96+
'What You Get',
97+
[
98+
_buildFeature(Icons.library_music, 'Your Library, Beautiful',
99+
'Browse your collection by artists, albums, or tracks with stunning visuals.'),
100+
_buildFeature(Icons.search, 'Search That Just Works',
101+
'Find any track, album, or artist instantly.'),
102+
_buildFeature(Icons.play_circle_outline, 'Seamless Playback',
103+
'High-quality streaming with support for FLAC, MP3, AAC, and more.'),
104+
_buildFeature(Icons.playlist_play, 'Playlists & Collections',
105+
'Create and manage playlists for every mood.'),
106+
_buildFeature(Icons.dark_mode, 'Dark Mode Always',
107+
'Easy on your eyes, day or night.'),
108+
],
109+
),
110+
111+
const SizedBox(height: 48),
112+
113+
// Tech Section
114+
_buildSection(
115+
'Built With',
116+
[
117+
const Padding(
118+
padding: EdgeInsets.symmetric(vertical: 8.0),
119+
child: Text(
120+
'• Flutter - Cross-platform framework\n'
121+
'• Plex Media Server API\n'
122+
'• SQLite for local caching\n'
123+
'• Media Kit for audio playback',
124+
style: TextStyle(
125+
color: Colors.white70,
126+
fontSize: 16,
127+
height: 1.8,
128+
),
129+
),
130+
),
131+
],
132+
),
133+
134+
const SizedBox(height: 48),
135+
136+
// License Section
137+
_buildSection(
138+
'License',
139+
[
140+
const Padding(
141+
padding: EdgeInsets.symmetric(vertical: 8.0),
142+
child: Text(
143+
'Apache License 2.0\n\n'
144+
'Obscurify is open source and free to use. '
145+
'Contributions are welcome!',
146+
style: TextStyle(
147+
color: Colors.white70,
148+
fontSize: 16,
149+
height: 1.8,
150+
),
151+
textAlign: TextAlign.center,
152+
),
153+
),
154+
],
155+
),
156+
157+
const SizedBox(height: 48),
158+
159+
// Links
160+
Row(
161+
mainAxisAlignment: MainAxisAlignment.center,
162+
children: [
163+
_buildLinkButton(
164+
'GitHub',
165+
Icons.code,
166+
'https://github.com/j-convey/Obscurify',
167+
),
168+
const SizedBox(width: 16),
169+
_buildLinkButton(
170+
'Sponsor',
171+
Icons.favorite,
172+
'https://github.com/sponsors/j-convey',
173+
color: Colors.pink,
174+
),
175+
],
176+
),
177+
178+
const SizedBox(height: 48),
179+
180+
// Footer
181+
const Text(
182+
'Made with ❤️ for music collectors everywhere.',
183+
style: TextStyle(
184+
color: Colors.grey,
185+
fontSize: 14,
186+
fontStyle: FontStyle.italic,
187+
),
188+
textAlign: TextAlign.center,
189+
),
190+
191+
const SizedBox(height: 32),
192+
],
193+
),
194+
),
195+
),
196+
),
197+
);
198+
}
199+
200+
Widget _buildSection(String title, List<Widget> children) {
201+
return Column(
202+
crossAxisAlignment: CrossAxisAlignment.start,
203+
children: [
204+
Center(
205+
child: Text(
206+
title,
207+
style: const TextStyle(
208+
color: Colors.white,
209+
fontSize: 24,
210+
fontWeight: FontWeight.bold,
211+
),
212+
),
213+
),
214+
const SizedBox(height: 24),
215+
...children,
216+
],
217+
);
218+
}
219+
220+
Widget _buildFeature(IconData icon, String title, String description) {
221+
return Padding(
222+
padding: const EdgeInsets.symmetric(vertical: 12.0),
223+
child: Row(
224+
crossAxisAlignment: CrossAxisAlignment.start,
225+
children: [
226+
Container(
227+
width: 48,
228+
height: 48,
229+
decoration: BoxDecoration(
230+
color: Colors.white.withOpacity(0.1),
231+
borderRadius: BorderRadius.circular(12),
232+
),
233+
child: Icon(icon, color: Colors.blue, size: 24),
234+
),
235+
const SizedBox(width: 16),
236+
Expanded(
237+
child: Column(
238+
crossAxisAlignment: CrossAxisAlignment.start,
239+
children: [
240+
Text(
241+
title,
242+
style: const TextStyle(
243+
color: Colors.white,
244+
fontSize: 18,
245+
fontWeight: FontWeight.bold,
246+
),
247+
),
248+
const SizedBox(height: 4),
249+
Text(
250+
description,
251+
style: const TextStyle(
252+
color: Colors.white70,
253+
fontSize: 14,
254+
height: 1.5,
255+
),
256+
),
257+
],
258+
),
259+
),
260+
],
261+
),
262+
);
263+
}
264+
265+
Widget _buildLinkButton(String label, IconData icon, String url, {Color? color}) {
266+
return ElevatedButton.icon(
267+
onPressed: () => _launchUrl(url),
268+
icon: Icon(icon),
269+
label: Text(label),
270+
style: ElevatedButton.styleFrom(
271+
backgroundColor: color ?? Colors.blue,
272+
foregroundColor: Colors.white,
273+
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
274+
shape: RoundedRectangleBorder(
275+
borderRadius: BorderRadius.circular(8),
276+
),
277+
),
278+
);
279+
}
280+
281+
Future<void> _launchUrl(String urlString) async {
282+
final url = Uri.parse(urlString);
283+
if (await canLaunchUrl(url)) {
284+
await launchUrl(url, mode: LaunchMode.externalApplication);
285+
}
286+
}
287+
}

lib/desktop/features/settings/settings_page.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:obscurify/core/services/audio_player_service.dart';
33
import 'server/server_settings_page.dart';
4+
import 'about_page.dart';
45

56
class SettingsPage extends StatelessWidget {
67
final void Function(Widget) onNavigate;
@@ -41,7 +42,7 @@ class SettingsPage extends StatelessWidget {
4142
const Text('App information', style: TextStyle(color: Colors.grey)),
4243
trailing: const Icon(Icons.chevron_right, color: Colors.white),
4344
onTap: () {
44-
// TODO: Implement About page
45+
onNavigate(const AboutPage());
4546
},
4647
),
4748
],

0 commit comments

Comments
 (0)