spotube/lib/components/Settings/Settings.dart
2022-08-03 12:44:20 +06:00

387 lines
16 KiB
Dart

import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/components/Settings/About.dart';
import 'package:spotube/components/Settings/ColorSchemePickerDialog.dart';
import 'package:spotube/components/Shared/PageWindowTitleBar.dart';
import 'package:spotube/models/SpotifyMarkets.dart';
import 'package:spotube/models/SpotubeTrack.dart';
import 'package:spotube/provider/Auth.dart';
import 'package:spotube/provider/Playback.dart';
import 'package:spotube/provider/UserPreferences.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:collection/collection.dart';
class Settings extends HookConsumerWidget {
const Settings({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ref) {
final UserPreferences preferences = ref.watch(userPreferencesProvider);
final Auth auth = ref.watch(authProvider);
final pickColorScheme = useCallback((ColorSchemeType schemeType) {
return () => showDialog(
context: context,
builder: (context) {
return ColorSchemePickerDialog(
schemeType: schemeType,
);
});
}, []);
final pickDownloadLocation = useCallback(() async {
final dirStr = await FilePicker.platform.getDirectoryPath(
dialogTitle: "Download Location",
);
if (dirStr == null) return;
preferences.setDownloadLocation(dirStr);
}, [preferences.downloadLocation]);
var ytSearchFormatController = useTextEditingController(
text: preferences.ytSearchFormat,
);
return SafeArea(
child: Scaffold(
appBar: PageWindowTitleBar(
leading: const BackButton(),
center: Text(
"Settings",
style: Theme.of(context).textTheme.headline5,
),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Container(
constraints: const BoxConstraints(maxWidth: 1366),
child: ListView(
children: [
ListTile(
title: const Text("Theme"),
horizontalTitleGap: 10,
trailing: DropdownButton<ThemeMode>(
value: preferences.themeMode,
items: const [
DropdownMenuItem(
child: Text(
"Dark",
),
value: ThemeMode.dark,
),
DropdownMenuItem(
child: Text(
"Light",
),
value: ThemeMode.light,
),
DropdownMenuItem(
child: Text("System"),
value: ThemeMode.system,
),
],
onChanged: (value) {
if (value != null) {
preferences.setThemeMode(value);
}
},
),
),
ListTile(
title: const Text("Accent Color Scheme"),
horizontalTitleGap: 10,
contentPadding: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 5,
),
trailing: ColorTile(
color: preferences.accentColorScheme,
onPressed: pickColorScheme(ColorSchemeType.accent),
isActive: true,
),
onTap: pickColorScheme(ColorSchemeType.accent),
),
ListTile(
title: const Text("Background Color Scheme"),
horizontalTitleGap: 10,
contentPadding: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 5,
),
trailing: ColorTile(
color: preferences.backgroundColorScheme,
onPressed: pickColorScheme(ColorSchemeType.background),
isActive: true,
),
onTap: pickColorScheme(ColorSchemeType.background),
),
Padding(
padding: const EdgeInsets.all(15),
child: Wrap(
alignment: WrapAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Market Place",
style: Theme.of(context).textTheme.bodyText1,
),
Text(
"Recommendation Country",
style: Theme.of(context).textTheme.caption,
),
],
),
const SizedBox(height: 10),
DropdownButton(
value: preferences.recommendationMarket,
items: spotifyMarkets
.map(
(country) => (DropdownMenuItem(
child: Text(country.last),
value: country.first,
)),
)
.toList(),
onChanged: (value) {
if (value == null) return;
preferences.setRecommendationMarket(
value as String,
);
},
),
],
),
),
ListTile(
title: const Text("Download Location"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
preferences.downloadLocation,
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(width: 5),
ElevatedButton(
child: const Icon(Icons.folder_rounded),
onPressed: pickDownloadLocation,
),
],
),
onTap: pickDownloadLocation,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 15.0,
vertical: 5,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 2,
child: Text(
"Format of the YouTube Search term (Case sensitive)",
style: Theme.of(context).textTheme.bodyText2,
),
),
Expanded(
flex: 1,
child: TextField(
controller: ytSearchFormatController,
decoration: InputDecoration(
isDense: true,
suffix: ElevatedButton(
child: const Icon(Icons.save_rounded),
onPressed: () {
preferences.setYtSearchFormat(
ytSearchFormatController.value.text,
);
},
),
),
onSubmitted: (value) {
preferences.setYtSearchFormat(value);
},
),
),
],
),
),
ListTile(
title: const Text(
"Skip non-music segments (SponsorBlock)",
),
horizontalTitleGap: 10,
trailing: Switch.adaptive(
activeColor: Theme.of(context).primaryColor,
value: preferences.skipSponsorSegments,
onChanged: (state) {
preferences.setSkipSponsorSegments(state);
},
),
),
ListTile(
title: const Text("Download lyrics along with the Track"),
horizontalTitleGap: 10,
trailing: Switch.adaptive(
activeColor: Theme.of(context).primaryColor,
value: preferences.saveTrackLyrics,
onChanged: (state) {
preferences.setSaveTrackLyrics(state);
},
),
),
if (auth.isAnonymous)
ListTile(
title: const Text("Login with your Spotify account"),
horizontalTitleGap: 10,
trailing: ElevatedButton(
child: Text("Connect with Spotify".toUpperCase()),
onPressed: () {
GoRouter.of(context).push("/login");
},
style: ButtonStyle(
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0),
),
),
),
),
),
ListTile(
title: const Text("Check for Update"),
horizontalTitleGap: 10,
trailing: Switch.adaptive(
activeColor: Theme.of(context).primaryColor,
value: preferences.checkUpdate,
onChanged: (checked) =>
preferences.setCheckUpdate(checked),
),
),
ListTile(
title: const Text("Track Match Algorithm"),
horizontalTitleGap: 10,
trailing: DropdownButton<SpotubeTrackMatchAlgorithm>(
value: preferences.trackMatchAlgorithm,
items: const [
DropdownMenuItem(
child: Text(
"Popular from Author",
),
value: SpotubeTrackMatchAlgorithm.authenticPopular,
),
DropdownMenuItem(
child: Text(
"Accurately Popular",
),
value: SpotubeTrackMatchAlgorithm.popular,
),
DropdownMenuItem(
child: Text("YouTube's choice is my choice"),
value: SpotubeTrackMatchAlgorithm.youtube,
),
],
onChanged: (value) {
if (value != null) {
preferences.setTrackMatchAlgorithm(value);
}
},
),
),
ListTile(
title: const Text("Audio Quality"),
horizontalTitleGap: 10,
trailing: DropdownButton<AudioQuality>(
value: preferences.audioQuality,
items: const [
DropdownMenuItem(
child: Text(
"High",
),
value: AudioQuality.high,
),
DropdownMenuItem(
child: Text("Low"),
value: AudioQuality.low,
),
],
onChanged: (value) {
if (value != null) {
preferences.setAudioQuality(value);
}
},
),
),
if (auth.isLoggedIn)
Builder(builder: (context) {
Auth auth = ref.watch(authProvider);
return ListTile(
title: const Text("Log out of this account"),
horizontalTitleGap: 10,
trailing: ElevatedButton(
child: const Text("Logout"),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red),
foregroundColor:
MaterialStateProperty.all(Colors.white),
),
onPressed: () async {
auth.logout();
GoRouter.of(context).pop();
},
),
);
}),
ListTile(
title: const Text(
"We know you Love Spotube",
style: TextStyle(
color: Colors.pink,
fontWeight: FontWeight.bold,
),
),
horizontalTitleGap: 10,
trailing: ElevatedButton.icon(
icon: const Icon(Icons.favorite_outline_rounded),
label: const Text("Please Sponsor/Donate"),
style: ElevatedButton.styleFrom(
primary: Colors.red[100],
onPrimary: Colors.pinkAccent,
padding: const EdgeInsets.all(15),
),
onPressed: () {
launchUrlString("https://opencollective.com/spotube",
mode: LaunchMode.externalApplication);
},
),
),
const About()
].mapIndexed((i, child) {
return Container(
color: i % 2 == 1
? Theme.of(context).primaryColor.withOpacity(.1)
: null,
child: child,
);
}).toList(),
),
),
),
],
),
),
);
}
}