Skip to content

Commit

Permalink
feat(yt): edit yt playlists
Browse files Browse the repository at this point in the history
comes with rework of many yt playlist-related parts
  • Loading branch information
MSOB7YY committed Aug 5, 2024
1 parent b2c9534 commit a632fd4
Show file tree
Hide file tree
Showing 19 changed files with 538 additions and 222 deletions.
2 changes: 1 addition & 1 deletion lib/controller/indexer_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -645,11 +645,11 @@ class Indexer {
_removeThisTrackFromAlbumGenreArtistEtc(tr);
},
);
recentlyDeltedFileWrite.flush().then((_) => recentlyDeltedFileWrite.close());
SearchSortController.inst.trackSearchList.refresh();
SearchSortController.inst.trackSearchTemp.refresh();
Folders.inst.currentFolder.refresh();
await _saveTrackFileToStorage();
recentlyDeltedFileWrite.flush().then((_) => recentlyDeltedFileWrite.close());
}

Future<void> reindexTracks({
Expand Down
101 changes: 83 additions & 18 deletions lib/core/functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -672,24 +672,50 @@ Future<void> showCalendarDialog<T extends ItemWithDate, E>({
);
}

class BottomSheetTextFieldConfig {
final String? initalControllerText;
final String hintText;
final String labelText;
final int? maxLength;
final String? Function(String? value)? validator;

const BottomSheetTextFieldConfig({
this.initalControllerText,
required this.hintText,
required this.labelText,
this.maxLength,
required this.validator,
});
}

class BottomSheetTextFieldConfigWC extends BottomSheetTextFieldConfig {
final TextEditingController controller;

const BottomSheetTextFieldConfigWC({
required this.controller,
required super.hintText,
required super.labelText,
super.maxLength,
required super.validator,
}) : super(initalControllerText: null);
}

Future<String?> showNamidaBottomSheetWithTextField({
required BuildContext context,
bool isScrollControlled = true,
bool useRootNavigator = true,
bool showDragHandle = true,
required String title,
String? initalControllerText,
required String hintText,
required String labelText,
int? maxLength,
required String? Function(String? value)? validator,
required BottomSheetTextFieldConfig textfieldConfig,
List<BottomSheetTextFieldConfigWC>? extraTextfieldsConfig,
required String buttonText,
TextStyle? buttonTextStyle,
Color? buttonColor,
required FutureOr<bool> Function(String text) onButtonTap,
Widget Function(FormState formState)? extraItemsBuilder,
Rx<bool>? isInitiallyLoading,
}) async {
final controller = TextEditingController(text: initalControllerText);
final localController = textfieldConfig is BottomSheetTextFieldConfigWC ? textfieldConfig.controller : TextEditingController(text: textfieldConfig.initalControllerText);
final GlobalKey<FormState> formKey = GlobalKey<FormState>();

final focusNode = FocusNode();
Expand All @@ -706,12 +732,12 @@ Future<String?> showNamidaBottomSheetWithTextField({
isScrollControlled: isScrollControlled,
builder: (context) {
final bottomPadding = MediaQuery.viewInsetsOf(context).bottom + MediaQuery.paddingOf(context).bottom;
return Padding(
final child = Padding(
padding: const EdgeInsets.symmetric(horizontal: 28.0).add(EdgeInsets.only(bottom: 18.0 + bottomPadding)),
child: Form(
key: formKey,
child: NamidaLoadingSwitcher(
builder: (startLoading, stopLoading, isLoading) => Column(
builder: (loadingController) => Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
Expand All @@ -721,11 +747,22 @@ Future<String?> showNamidaBottomSheetWithTextField({
const SizedBox(height: 18.0),
CustomTagTextField(
focusNode: focusNode,
controller: controller,
hintText: hintText,
labelText: labelText,
validator: validator,
maxLength: maxLength,
controller: localController,
hintText: textfieldConfig.hintText,
labelText: textfieldConfig.labelText,
validator: textfieldConfig.validator,
maxLength: textfieldConfig.maxLength,
),
...?extraTextfieldsConfig?.map(
(e) {
return CustomTagTextField(
controller: e.controller,
hintText: e.hintText,
labelText: e.labelText,
validator: e.validator,
maxLength: e.maxLength,
);
},
),
if (extraItemsBuilder != null) extraItemsBuilder(formKey.currentState!),
const SizedBox(height: 18.0),
Expand All @@ -749,11 +786,11 @@ Future<String?> showNamidaBottomSheetWithTextField({
),
onTap: () async {
if (formKey.currentState!.validate()) {
startLoading();
final didAgree = await onButtonTap(controller.text);
stopLoading();
loadingController.startLoading();
final didAgree = await onButtonTap(localController.text);
loadingController.stopLoading();
if (didAgree) {
finalText = controller.text;
finalText = localController.text;
if (context.mounted) context.safePop();
}
}
Expand All @@ -767,9 +804,37 @@ Future<String?> showNamidaBottomSheetWithTextField({
),
),
);
return isInitiallyLoading != null
? ObxO(
rx: isInitiallyLoading,
builder: (initiallyLoading) {
return Stack(
children: [
AnimatedEnabled(
enabled: !initiallyLoading,
child: child,
),
if (initiallyLoading)
const Positioned(
top: 0,
right: 32.0,
child: SizedBox(
width: 32.0,
height: 32.0,
child: CircularProgressIndicator(strokeWidth: 4.0),
),
),
],
);
},
)
: child;
},
);
controller.disposeAfterAnimation(also: focusNode.dispose);
Future.delayed(const Duration(milliseconds: 2000), () {
if (localController is! BottomSheetTextFieldConfigWC) localController.dispose();
focusNode.dispose();
});
return finalText;
}

Expand Down
37 changes: 1 addition & 36 deletions lib/core/namida_converter_ext.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import 'package:flutter/material.dart';

import 'package:history_manager/history_manager.dart';
import 'package:path/path.dart' as p;
import 'package:youtipie/class/result_wrapper/playlist_result_base.dart';
import 'package:youtipie/class/streams/audio_stream.dart';
import 'package:youtipie/class/streams/video_stream.dart';
import 'package:youtipie/core/enum.dart';
Expand Down Expand Up @@ -58,7 +57,6 @@ import 'package:namida/youtube/functions/add_to_playlist_sheet.dart';
import 'package:namida/youtube/functions/download_sheet.dart';
import 'package:namida/youtube/pages/youtube_home_view.dart';
import 'package:namida/youtube/pages/yt_playlist_download_subpage.dart';
import 'package:namida/youtube/pages/yt_playlist_subpage.dart';
import 'package:namida/youtube/yt_utils.dart';

extension MediaTypeUtils on MediaType {
Expand Down Expand Up @@ -442,17 +440,7 @@ extension OnYoutubeLinkOpenActionUtils on OnYoutubeLinkOpenAction {
}
}

void _showAskDialog(void Function(OnYoutubeLinkOpenAction action) onTap, {YoutiPiePlaylistResultBase? playlistToOpen, YoutiPiePlaylistResultBase? playlistToAddAs}) {
String playlistNameToAddAs = playlistToAddAs?.basicInfo.title ?? '';
String suffix = '';
int suffixIndex = 1;
while (ytplc.YoutubePlaylistController.inst.playlistsMap.value["$playlistNameToAddAs$suffix"] != null) {
suffixIndex++;
suffix = ' ($suffixIndex)';
}
playlistNameToAddAs += suffix;

final didAddToPlaylist = false.obs;
void _showAskDialog(void Function(OnYoutubeLinkOpenAction action) onTap) {
final isItemEnabled = <OnYoutubeLinkOpenAction, bool>{
OnYoutubeLinkOpenAction.playNext: true,
OnYoutubeLinkOpenAction.playAfter: true,
Expand All @@ -463,7 +451,6 @@ extension OnYoutubeLinkOpenActionUtils on OnYoutubeLinkOpenAction {

NamidaNavigator.inst.navigateDialog(
onDisposing: () {
didAddToPlaylist.close();
isItemEnabled.close();
},
dialog: CustomBlurryDialog(
Expand All @@ -474,12 +461,6 @@ extension OnYoutubeLinkOpenActionUtils on OnYoutubeLinkOpenAction {
],
child: Column(
children: [
if (playlistToOpen != null)
CustomListTile(
icon: Broken.export_2,
title: lang.OPEN,
onTap: YTHostedPlaylistSubpage(playlist: playlistToOpen).navigate,
),
...[
OnYoutubeLinkOpenAction.showDownload,
OnYoutubeLinkOpenAction.play,
Expand Down Expand Up @@ -510,22 +491,6 @@ extension OnYoutubeLinkOpenActionUtils on OnYoutubeLinkOpenAction {
);
},
),
if (playlistNameToAddAs != '')
Obx(
() => CustomListTile(
enabled: !didAddToPlaylist.valueR,
icon: Broken.add_square,
title: lang.ADD_AS_A_NEW_PLAYLIST,
subtitle: playlistNameToAddAs,
onTap: () {
didAddToPlaylist.value = true;
ytplc.YoutubePlaylistController.inst.addNewPlaylist(
playlistNameToAddAs,
videoIds: playlistToAddAs?.items.map((e) => e.id),
);
},
),
),
],
),
),
Expand Down
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ Future<void> _initializeIntenties() async {
settings.youtube.onYoutubeLinkOpen.value.execute(youtubeIds);
} else if (ytPlaylistsIds.isNotEmpty) {
for (final plid in ytPlaylistsIds) {
YTHostedPlaylistSubpage.fromId(playlistId: plid).navigate();
YTHostedPlaylistSubpage.fromId(playlistId: plid, userPlaylist: null).navigate();
}
} else {
final existing = paths.where((element) => File(element).existsSync()); // this for sussy links
Expand Down
6 changes: 3 additions & 3 deletions lib/packages/miniplayer_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ class _TrackInfo<T, E> extends StatelessWidget {
final isUserLiked = currentLikeStatus == LikeStatus.liked;
return NamidaLoadingSwitcher(
size: 32.0,
builder: (startLoading, stopLoading, isLoading) => NamidaRawLikeButton(
builder: (loadingController) => NamidaRawLikeButton(
isLiked: isUserLiked,
likedIcon: textData.likedIcon,
normalIcon: textData.normalIcon,
Expand All @@ -1343,8 +1343,8 @@ class _TrackInfo<T, E> extends StatelessWidget {
page: YoutubeInfoController.current.currentVideoPage.value,
isActive: isLiked,
action: isLiked ? LikeAction.removeLike : LikeAction.addLike,
onStart: startLoading,
onEnd: stopLoading,
onStart: loadingController.startLoading,
onEnd: loadingController.stopLoading,
),
);
},
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/pages/main_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ class NamidaSearchBar extends StatelessWidget {
try {
final ytPlaylistId = NamidaLinkUtils.extractPlaylistId(val);
if (ytPlaylistId != null && ytPlaylistId != '') {
YTHostedPlaylistSubpage.fromId(playlistId: ytPlaylistId).navigate();
YTHostedPlaylistSubpage.fromId(playlistId: ytPlaylistId, userPlaylist: null).navigate();
return;
}
} catch (_) {}
Expand Down
33 changes: 25 additions & 8 deletions lib/ui/widgets/custom_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1357,8 +1357,20 @@ class NamidaWheelSlider extends StatelessWidget {
}
}

class NamidaLoadingController {
final void Function() startLoading;
final void Function() stopLoading;
bool isLoading;

NamidaLoadingController({
required this.startLoading,
required this.stopLoading,
required this.isLoading,
});
}

class NamidaLoadingSwitcher extends StatefulWidget {
final Widget Function(void Function() startLoading, void Function() stopLoading, bool isLoading) builder;
final Widget Function(NamidaLoadingController loadingController) builder;
final double? size;
final bool showLoading;

Expand All @@ -1374,32 +1386,37 @@ class NamidaLoadingSwitcher extends StatefulWidget {
}

class _NamidaLoadingSwitcherState extends State<NamidaLoadingSwitcher> {
bool _isLoading = false;
late final loadingController = NamidaLoadingController(
startLoading: _startLoading,
stopLoading: _stopLoading,
isLoading: false,
);

void _startLoading() {
if (mounted) setState(() => _isLoading = true);
if (mounted) setState(() => loadingController.isLoading = true);
}

void _stopLoading() {
if (mounted) setState(() => _isLoading = false);
if (mounted) setState(() => loadingController.isLoading = false);
}

@override
Widget build(BuildContext context) {
final child = widget.builder(_startLoading, _stopLoading, _isLoading);
final child = widget.builder(loadingController);
final isLoading = loadingController.isLoading;
return Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: [
AnimatedOpacity(
opacity: _isLoading ? 0.5 : 1.0,
opacity: isLoading ? 0.5 : 1.0,
duration: const Duration(milliseconds: 200),
child: child,
),
if (_isLoading && widget.showLoading)
if (isLoading && widget.showLoading)
IgnorePointer(
child: AnimatedOpacity(
opacity: _isLoading ? 0.8 : 0.0,
opacity: isLoading ? 0.8 : 0.0,
duration: const Duration(milliseconds: 200),
child: SizedBox(
width: widget.size,
Expand Down
Loading

0 comments on commit a632fd4

Please sign in to comment.