Skip to content

Commit

Permalink
feat(yt): user notifications
Browse files Browse the repository at this point in the history
ref #227
  • Loading branch information
MSOB7YY committed Jul 7, 2024
1 parent 2cbfe9f commit c3adcd1
Show file tree
Hide file tree
Showing 10 changed files with 626 additions and 193 deletions.
1 change: 1 addition & 0 deletions lib/core/enums.dart
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ enum FABType {

enum YTHomePages {
home,
notifications,
channels,
playlists,
downloads,
Expand Down
1 change: 1 addition & 0 deletions lib/core/namida_converter_ext.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,7 @@ class _NamidaConverters {
},
YTHomePages: {
YTHomePages.home: lang.HOME,
YTHomePages.notifications: lang.NOTIFICATIONS,
YTHomePages.channels: lang.CHANNELS,
YTHomePages.playlists: lang.PLAYLISTS,
YTHomePages.downloads: lang.DOWNLOADS,
Expand Down
2 changes: 2 additions & 0 deletions lib/core/translations/keys.dart
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ abstract class LanguageKeys {
String get MANAGE_YOUR_ACCOUNTS => _getKey('MANAGE_YOUR_ACCOUNTS');
String get MANUAL_BACKUP_SUBTITLE => _getKey('MANUAL_BACKUP_SUBTITLE');
String get MANUAL_BACKUP => _getKey('MANUAL_BACKUP');
String get MARK_AS_READ => _getKey('MARK_AS_READ');
String get MATCHING_TYPE => _getKey('MATCHING_TYPE');
String get MATCH_ALL_TRACKS => _getKey('MATCH_ALL_TRACKS');
String get MATCH_ALL_TRACKS_NOTE => _getKey('MATCH_ALL_TRACKS_NOTE');
Expand Down Expand Up @@ -422,6 +423,7 @@ abstract class LanguageKeys {
String get NON_ACTIVE => _getKey('NON_ACTIVE');
String get NONE => _getKey('NONE');
String get NOTE => _getKey('NOTE');
String get NOTIFICATIONS => _getKey('NOTIFICATIONS');
String get NUMBER_OF_TRACKS => _getKey('NUMBER_OF_TRACKS');
String get OF => _getKey('OF');
String get OFFLINE_SEARCH => _getKey('OFFLINE_SEARCH');
Expand Down
237 changes: 45 additions & 192 deletions lib/youtube/pages/youtube_feed_page.dart
Original file line number Diff line number Diff line change
@@ -1,215 +1,68 @@
import 'package:flutter/material.dart';
import 'package:youtipie/class/execute_details.dart';
import 'package:youtipie/class/result_wrapper/feed_result.dart';
import 'package:youtipie/class/stream_info_item/stream_info_item.dart';
import 'package:youtipie/class/stream_info_item/stream_info_item_short.dart';
import 'package:youtipie/class/youtipie_feed/playlist_info_item.dart';
import 'package:youtipie/class/youtipie_feed/yt_feed_base.dart';
import 'package:youtipie/youtipie.dart';

import 'package:namida/base/pull_to_refresh.dart';
import 'package:namida/class/route.dart';
import 'package:namida/core/dimensions.dart';
import 'package:namida/core/icon_fonts/broken_icons.dart';
import 'package:namida/core/translations/language.dart';
import 'package:namida/core/utils.dart';
import 'package:namida/ui/widgets/custom_widgets.dart';
import 'package:namida/ui/widgets/settings/extra_settings.dart';
import 'package:namida/youtube/controller/youtube_account_controller.dart';
import 'package:namida/youtube/pages/user/youtube_account_manage_page.dart';
import 'package:namida/youtube/pages/youtube_main_page_fetcher_acc_base.dart';
import 'package:namida/youtube/widgets/yt_playlist_card.dart';
import 'package:namida/youtube/widgets/yt_video_card.dart';

class YoutubeHomeFeedPage extends StatefulWidget {
class YoutubeHomeFeedPage extends StatelessWidget {
const YoutubeHomeFeedPage({super.key});

@override
State<YoutubeHomeFeedPage> createState() => _YoutubePageState();
}

class _YoutubePageState extends State<YoutubeHomeFeedPage> with AutomaticKeepAliveClientMixin<YoutubeHomeFeedPage> {
@override
bool get wantKeepAlive => true;

final _controller = ScrollController();
final _isLoadingCurrentFeed = Rxn<bool>();
final _isLoadingNext = false.obs;
final _currentFeed = Rxn<YoutiPieFeedResult>();

@override
void initState() {
super.initState();
_fetchFeed();
}

@override
void dispose() {
_controller.dispose();
_isLoadingCurrentFeed.close();
_currentFeed.close();
super.dispose();
}

Future<void> _fetchFeed() async {
_isLoadingCurrentFeed.value = true;
final val = await YoutiPie.feed.fetchFeed(details: ExecuteDetails.forceRequest());
_isLoadingCurrentFeed.value = false;
if (val != null) _currentFeed.value = val;
}

Future<void> _fetchFeedNext() async {
_isLoadingNext.value = true;
final feed = _currentFeed;
final fetched = await feed.value?.fetchNext();
if (fetched == true) feed.refresh();
_isLoadingNext.value = false;
}

@override
Widget build(BuildContext context) {
super.build(context);

const thumbnailHeight = Dimensions.youtubeThumbnailHeight;
const thumbnailWidth = Dimensions.youtubeThumbnailWidth;
const thumbnailItemExtent = thumbnailHeight + 8.0 * 2;

final header = Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
child: Text(
lang.HOME,
style: context.textTheme.displayLarge?.copyWith(fontSize: 38.0),
),
);

final pagePadding = EdgeInsets.only(top: 24.0, bottom: Dimensions.inst.globalBottomPaddingTotalR);

return BackgroundWrapper(
child: PullToRefresh(
controller: _controller,
onRefresh: _fetchFeed,
child: ObxO(
rx: YoutubeAccountController.current.activeAccountChannel,
builder: (activeAccountChannel) => activeAccountChannel == null
? Padding(
padding: pagePadding,
child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: header,
),
const SizedBox(height: 38.0),
Text(
lang.SIGN_IN_YOU_NEED_ACCOUNT_TO_VIEW_PAGE,
style: context.textTheme.displayLarge,
),
const SizedBox(height: 12.0),
NamidaInkWellButton(
sizeMultiplier: 1.1,
icon: Broken.user_edit,
text: lang.MANAGE_YOUR_ACCOUNTS,
onTap: const YoutubeAccountManagePage().navigate,
),
],
),
)
: ObxO(
rx: _isLoadingCurrentFeed,
builder: (isLoadingCurrentFeed) => ObxO(
rx: _currentFeed,
builder: (homepageFeed) {
return LazyLoadListView(
onReachingEnd: _fetchFeedNext,
scrollController: _controller,
listview: (controller) => CustomScrollView(
controller: controller,
slivers: [
SliverPadding(padding: EdgeInsets.only(top: pagePadding.top)),
SliverToBoxAdapter(
child: header,
),
isLoadingCurrentFeed == null
? const SliverToBoxAdapter()
: isLoadingCurrentFeed == true
? SliverToBoxAdapter(
child: ShimmerWrapper(
transparent: false,
shimmerEnabled: true,
child: ListView.builder(
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
itemCount: 15,
shrinkWrap: true,
itemBuilder: (context, index) {
return const YoutubeVideoCardDummy(
shimmerEnabled: true,
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
);
},
),
),
)
: homepageFeed == null
? const SliverToBoxAdapter()
: SliverFixedExtentList.builder(
itemCount: homepageFeed.items.length,
itemExtent: thumbnailItemExtent,
itemBuilder: (context, i) {
final item = homepageFeed.items[i];
return switch (item.runtimeType) {
const (StreamInfoItem) => YoutubeVideoCard(
key: Key((item as StreamInfoItem).id),
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
isImageImportantInCache: false,
video: item,
playlistID: null,
),
const (StreamInfoItemShort) => YoutubeShortVideoCard(
key: Key("${(item as StreamInfoItemShort?)?.id}"),
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
short: item as StreamInfoItemShort,
playlistID: null,
),
const (PlaylistInfoItem) => YoutubePlaylistCard(
key: Key((item as PlaylistInfoItem).id),
playlist: item,
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
subtitle: item.subtitle,
playOnTap: true,
),
_ => const YoutubeVideoCardDummy(
shimmerEnabled: true,
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
),
};
},
),
SliverToBoxAdapter(
child: ObxO(
rx: _isLoadingNext,
builder: (isLoadingNext) => isLoadingNext
? const Padding(
padding: EdgeInsets.all(12.0),
child: Center(
child: LoadingIndicator(),
),
)
: const SizedBox(),
),
),
SliverPadding(padding: EdgeInsets.only(top: pagePadding.bottom)),
],
),
);
},
),
),
return YoutubeMainPageFetcherAccBase<YoutiPieFeedResult, YoutubeFeed>(
transparentShimmer: false,
title: lang.HOME,
cacheReader: YoutiPie.cacheBuilder.forFeedItems(),
networkFetcher: (details) => YoutiPie.feed.fetchFeed(details: details),
itemExtent: thumbnailItemExtent,
dummyCard: const YoutubeVideoCardDummy(
shimmerEnabled: true,
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
),
),
);
itemBuilder: (item, i, _) {
return switch (item.runtimeType) {
const (StreamInfoItem) => YoutubeVideoCard(
key: Key((item as StreamInfoItem).id),
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
isImageImportantInCache: false,
video: item,
playlistID: null,
),
const (StreamInfoItemShort) => YoutubeShortVideoCard(
key: Key("${(item as StreamInfoItemShort?)?.id}"),
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
short: item as StreamInfoItemShort,
playlistID: null,
),
const (PlaylistInfoItem) => YoutubePlaylistCard(
key: Key((item as PlaylistInfoItem).id),
playlist: item,
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
subtitle: item.subtitle,
playOnTap: true,
),
_ => const YoutubeVideoCardDummy(
shimmerEnabled: true,
thumbnailWidth: thumbnailWidth,
thumbnailHeight: thumbnailHeight,
),
};
});
}
}
2 changes: 2 additions & 0 deletions lib/youtube/pages/youtube_home_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:namida/core/enums.dart';
import 'package:namida/core/namida_converter_ext.dart';
import 'package:namida/ui/widgets/custom_widgets.dart';
import 'package:namida/youtube/pages/youtube_feed_page.dart';
import 'package:namida/youtube/pages/youtube_notifications_page.dart';
import 'package:namida/youtube/pages/yt_channels_page.dart';
import 'package:namida/youtube/pages/yt_downloads_page.dart';
import 'package:namida/youtube/youtube_playlists_view.dart';
Expand All @@ -28,6 +29,7 @@ class YouTubeHomeView extends StatelessWidget with NamidaRouteWidget {
},
children: const [
YoutubeHomeFeedPage(),
YoutubeNotificationsPage(),
YoutubeChannelsPage(),
YoutubePlaylistsView(),
YTDownloadsPage(),
Expand Down
Loading

0 comments on commit c3adcd1

Please sign in to comment.