Skip to content

Commit

Permalink
✨ New: Download quality picker
Browse files Browse the repository at this point in the history
  • Loading branch information
devaryakjha committed Oct 22, 2023
1 parent 2eff3fb commit f9d42a2
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 104 deletions.
17 changes: 17 additions & 0 deletions lib/cubits/download/download_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import 'package:background_downloader/background_downloader.dart';
import 'package:equatable/equatable.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:rxdart/rxdart.dart';
import 'package:varanasi_mobile_app/models/app_config.dart';
import 'package:varanasi_mobile_app/models/download.dart';
import 'package:varanasi_mobile_app/models/download_url.dart';
import 'package:varanasi_mobile_app/models/media_playlist.dart';
import 'package:varanasi_mobile_app/models/playable_item.dart';
import 'package:varanasi_mobile_app/models/song.dart';
Expand Down Expand Up @@ -120,6 +122,8 @@ class DownloadCubit extends AppCubit<DownloadState> {
Future<void> downloadSong(PlayableMedia song) async {
assert(song is Song, 'Only songs can be downloaded');
if (song is! Song) return;
final quality = await getDownloadQuality();
if (quality == null) return;
_songMap[song.itemId] = song;
final queued = await _downloader.enqueue(_songToTask(song));
_logger.i('Queued ${song.itemId} status: $queued');
Expand Down Expand Up @@ -256,4 +260,17 @@ class DownloadCubit extends AppCubit<DownloadState> {
_downloadBox.containsKey(song.itemId);

bool _isNotDownloaded(PlayableMedia song) => !_isDownloaded(song);

Future<DownloadQuality?> getDownloadQuality() async {
final savedQuality = AppConfig.effectiveDlQuality;
if (savedQuality != null) return savedQuality;
AppConfig.effectiveDlQuality = await AppDialog.showOptionsPicker(
null,
savedQuality ?? DownloadQuality.high,
DownloadQuality.values,
(q) => q.describeQuality,
title: "Select Download Quality",
);
return AppConfig.effectiveDlQuality;
}
}
147 changes: 53 additions & 94 deletions lib/features/settings/ui/settings_page.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import 'package:another_flushbar/flushbar_helper.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:settings_ui/settings_ui.dart';
import 'package:varanasi_mobile_app/cubits/config/config_cubit.dart';
import 'package:varanasi_mobile_app/flavors.dart';
Expand Down Expand Up @@ -41,12 +39,51 @@ class SettingsPage extends StatelessWidget {
0,
appConfig.copyWith(
isDataSaverEnabled: value,
downloadQuality:
streamingQuality:
value ? DownloadQuality.low : DownloadQuality.extreme,
),
);
},
),
SettingsTile.navigation(
title: const Text('Download quality'),
leading: const Icon(Icons.download_outlined),
value: Text(
appConfig.downloadingQuality?.describeQuality ?? "",
),
onPressed: (ctx) {
AppDialog.showOptionsPicker(
ctx,
appConfig.downloadingQuality,
DownloadQuality.values,
(e) => e?.describeQuality ?? "",
title: "Select Download Quality",
).then((value) {
if (value != null) {
AppConfig.effectiveDlQuality = value;
}
});
},
),
SettingsTile.navigation(
title: const Text('Streaming quality'),
leading: const Icon(Icons.music_note_outlined),
value: Text(appConfig.streamingQuality?.describeQuality ?? ""),
onPressed: (ctx) {
AppDialog.showOptionsPicker(
ctx,
appConfig.streamingQuality,
DownloadQuality.values,
(e) => e?.describeQuality ?? "",
title: "Select Streaming Quality",
).then((value) {
if (value != null) {
AppConfig.getBox
.put(0, appConfig.copyWith(streamingQuality: value));
}
});
},
),
SettingsTile.switchTile(
initialValue: appConfig.isAdvancedModeEnabled,
title: const Text("Advanced Settings"),
Expand All @@ -56,7 +93,7 @@ class SettingsPage extends StatelessWidget {
0,
appConfig.copyWith(
isAdvancedModeEnabled: value,
downloadQuality: !value ? DownloadQuality.extreme : null,
streamingQuality: !value ? DownloadQuality.extreme : null,
colorScheme: !value ? 41 : null,
),
);
Expand All @@ -70,37 +107,26 @@ class SettingsPage extends StatelessWidget {
tiles: [
if (!appConfig.isDataSaverEnabled)
SettingsTile.navigation(
title: const Text('Streaming quality'),
leading: const Icon(Icons.music_note_outlined),
value: Text(appConfig.downloadQuality?.describeQuality ?? ""),
leading: const Icon(Icons.format_paint_outlined),
title: const Text('Theme'),
value: Text(appConfig.scheme.describeScheme),
onPressed: (ctx) {
_showOptionsPicker(
AppDialog.showOptionsPicker(
ctx,
appConfig.downloadQuality,
DownloadQuality.values,
(e) => e?.describeQuality ?? "",
appConfig.scheme,
FlexScheme.values,
(e) => e.describeScheme,
title: "Select Theme",
).then((value) {
if (value != null) {
AppConfig.getBox
.put(0, appConfig.copyWith(downloadQuality: value));
AppConfig.getBox.put(
0,
appConfig.copyWith(colorScheme: value.index),
);
}
});
},
),
SettingsTile.navigation(
leading: const Icon(Icons.format_paint_outlined),
title: const Text('Theme'),
value: Text(appConfig.scheme.describeScheme),
onPressed: (ctx) {
_showOptionsPicker(ctx, appConfig.scheme, FlexScheme.values,
(e) => e.describeScheme).then((value) {
if (value != null) {
AppConfig.getBox
.put(0, appConfig.copyWith(colorScheme: value.index));
}
});
},
),
SettingsTile(
leading: const Icon(Icons.delete_forever_outlined),
title: const Text("Clear cache"),
Expand Down Expand Up @@ -169,73 +195,6 @@ class SettingsPage extends StatelessWidget {
}
}

Future<T?> _showOptionsPicker<T>(
BuildContext context,
T initialValue,
List<T> options,
String Function(T) labelMapper,
) async {
return await showCupertinoModalPopup<T>(
context: context,
builder: (context) {
var selectedScheme = initialValue;
final viewInsets = MediaQuery.viewInsetsOf(context);
return StatefulBuilder(builder: (context, setState) {
return Container(
height: 300,
margin: EdgeInsets.only(bottom: viewInsets.bottom),
color: CupertinoColors.systemBackground.resolveFrom(context),
child: SafeArea(
top: false,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CupertinoButton(
child: const Text("Close"),
onPressed: () => context.pop(),
),
CupertinoButton(
child: const Text("Save"),
onPressed: () => context.pop(selectedScheme),
),
],
),
Expanded(
child: CupertinoPicker(
magnification: 1.2,
useMagnifier: true,
itemExtent: 36,
onSelectedItemChanged: (int value) {
setState(() => selectedScheme = options[value]);
},
squeeze: 1.2,
scrollController: FixedExtentScrollController(
initialItem: options.indexOf(initialValue),
),
children: options
.map((s) => Center(child: Text(labelMapper(s))))
.toList(),
),
),
],
),
),
);
});
},
);
// if (value != null) {
// await AppConfig.getBox.put(0, appConfig.copyWith(colorScheme: value));
// if (context.mounted) {
// FlushbarHelper.createSuccess(
// message: "Theme changed 👍🏻",
// ).show(context);
// }
// }
}

class _VisibileWhenSection extends SettingsSection {
const _VisibileWhenSection({
required super.tiles,
Expand Down
25 changes: 20 additions & 5 deletions lib/models/app_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,40 @@ class AppConfig extends HiveObject with EquatableMixin {
@HiveField(3, defaultValue: false)
final bool isDataSaverEnabled;
@HiveField(4)
final DownloadQuality? downloadQuality;
final DownloadQuality? streamingQuality;
@HiveField(5, defaultValue: false)
final bool isAdvancedModeEnabled;
@HiveField(6)
final DownloadQuality? downloadingQuality;

AppConfig({
this.sortBy = SortBy.custom,
this.repeatMode = 0,
this.colorScheme = 41,
this.isDataSaverEnabled = false,
this.downloadQuality,
this.streamingQuality,
this.isAdvancedModeEnabled = false,
this.downloadingQuality,
});

AppConfig copyWith({
SortBy? sortBy,
int? repeatMode,
int? colorScheme,
bool? isDataSaverEnabled,
DownloadQuality? downloadQuality,
DownloadQuality? streamingQuality,
bool? isAdvancedModeEnabled,
DownloadQuality? downloadingQuality,
}) {
return AppConfig(
sortBy: sortBy ?? this.sortBy,
repeatMode: repeatMode ?? this.repeatMode,
colorScheme: colorScheme ?? this.colorScheme,
isDataSaverEnabled: isDataSaverEnabled ?? this.isDataSaverEnabled,
downloadQuality: downloadQuality ?? this.downloadQuality,
streamingQuality: streamingQuality ?? this.streamingQuality,
isAdvancedModeEnabled:
isAdvancedModeEnabled ?? this.isAdvancedModeEnabled,
downloadingQuality: downloadingQuality ?? this.downloadingQuality,
);
}

Expand All @@ -58,8 +63,9 @@ class AppConfig extends HiveObject with EquatableMixin {
repeatMode,
colorScheme,
isDataSaverEnabled,
downloadQuality,
streamingQuality,
isAdvancedModeEnabled,
downloadingQuality,
];

@override
Expand All @@ -72,4 +78,13 @@ class AppConfig extends HiveObject with EquatableMixin {

static Future<Box<AppConfig>> openBox() =>
Hive.openBox<AppConfig>(AppStrings.configBoxName);

static DownloadQuality? get effectiveDlQuality =>
getBox.get(0)?.downloadingQuality;

static set effectiveDlQuality(DownloadQuality? quality) => getBox.put(
0,
getBox.get(0)?.copyWith(downloadingQuality: quality) ??
AppConfig(downloadingQuality: quality),
);
}
11 changes: 7 additions & 4 deletions lib/models/app_config.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/models/playable_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ abstract class PlayableMedia extends Equatable {
artist = artists.map((e) => e.name ?? '').join(', ');
final isDataSaverEnabled =
AppConfig.getBox.get(0)?.isDataSaverEnabled ?? false;
final effectiveQuality = AppConfig.getBox.get(0)?.downloadQuality ??
final effectiveQuality = AppConfig.getBox.get(0)?.streamingQuality ??
(isDataSaverEnabled ? DownloadQuality.low : DownloadQuality.extreme);

id = song.downloadUrl
Expand Down
Loading

0 comments on commit f9d42a2

Please sign in to comment.