Skip to content

Commit

Permalink
feat(yt): description and comments native style
Browse files Browse the repository at this point in the history
  • Loading branch information
MSOB7YY committed Jun 28, 2024
1 parent e82f32a commit 938af52
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 153 deletions.
28 changes: 28 additions & 0 deletions lib/youtube/pages/yt_playlist_subpage.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:youtipie/class/result_wrapper/list_wrapper_base.dart';
import 'package:youtipie/class/result_wrapper/playlist_result.dart';
import 'package:youtipie/class/result_wrapper/playlist_result_base.dart';
import 'package:youtipie/class/stream_info_item/stream_info_item.dart';
import 'package:youtipie/class/youtipie_feed/playlist_basic_info.dart';
import 'package:youtipie/youtipie.dart';

import 'package:namida/base/youtube_streams_manager.dart';
Expand Down Expand Up @@ -370,6 +371,11 @@ class YTHostedPlaylistSubpage extends StatefulWidget with NamidaRouteWidget {
required this.playlist,
});

YTHostedPlaylistSubpage.fromId({
super.key,
required String playlistId,
}) : playlist = _EmptyPlaylistResult(playlistId: playlistId);

@override
State<YTHostedPlaylistSubpage> createState() => _YTHostedPlaylistSubpageState();
}
Expand Down Expand Up @@ -705,3 +711,25 @@ class _YTHostedPlaylistSubpageState extends State<YTHostedPlaylistSubpage> with
);
}
}

/// not meant for usage, just a placeholder instead of nullifying everything
class _EmptyPlaylistResult extends YoutiPiePlaylistResultBase {
_EmptyPlaylistResult({
required String playlistId,
}) : super(
basicInfo: PlaylistBasicInfo(id: playlistId, title: '', videosCountText: null, videosCount: null, thumbnails: []),
items: [],
cacheKey: null,
continuation: null,
);

@override
Future<bool> fetchNextFunction(ExecuteDetails? details) async {
return false;
}

@override
Map<String, dynamic> toMap() {
return {};
}
}
46 changes: 22 additions & 24 deletions lib/youtube/widgets/namida_read_more.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'package:flutter/material.dart';

class NamidaReadMoreText extends StatefulWidget {
final String text;
final TextSpan span;
final int lines;
final Locale? locale;
final Widget Function(
String text,
TextSpan span,
int? lines,
bool isExpanded,
bool exceededMaxLines,
Expand All @@ -14,7 +14,7 @@ class NamidaReadMoreText extends StatefulWidget {

const NamidaReadMoreText({
super.key,
required this.text,
required this.span,
required this.lines,
this.locale,
required this.builder,
Expand All @@ -30,27 +30,25 @@ class _ReadMoreTextState extends State<NamidaReadMoreText> {

@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final locale = widget.locale ?? Localizations.maybeLocaleOf(context);
final span = TextSpan(text: widget.text);
final tp = TextPainter(
text: span,
locale: locale,
maxLines: widget.lines,
textDirection: Directionality.of(context),
);
tp.layout(maxWidth: constraints.maxWidth);
final exceededMaxLines = tp.didExceedMaxLines;
tp.dispose();
return widget.builder(
widget.text,
_isTextExpanded || !exceededMaxLines ? null : widget.lines,
_isTextExpanded,
exceededMaxLines,
_onReadMoreClicked,
);
},
final locale = widget.locale ?? Localizations.maybeLocaleOf(context);
final tp = TextPainter(
text: widget.span,
locale: locale,
maxLines: widget.lines,
textDirection: Directionality.of(context),
);
bool exceededMaxLines = false;
try {
tp.layout();
exceededMaxLines = tp.didExceedMaxLines;
} catch (_) {}
tp.dispose();
return widget.builder(
widget.span,
_isTextExpanded || !exceededMaxLines ? null : widget.lines,
_isTextExpanded,
exceededMaxLines,
_onReadMoreClicked,
);
}
}
157 changes: 71 additions & 86 deletions lib/youtube/widgets/yt_comment_card.dart
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:selectable_autolink_text/selectable_autolink_text.dart';
import 'package:youtipie/class/comments/comment_info_item.dart';

import 'package:namida/controller/navigator_controller.dart';
import 'package:namida/controller/player_controller.dart';
import 'package:namida/core/constants.dart';
import 'package:namida/core/extensions.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/youtube/pages/yt_channel_subpage.dart';
import 'package:namida/youtube/widgets/namida_read_more.dart';
import 'package:namida/youtube/widgets/yt_description_widget.dart';
import 'package:namida/youtube/widgets/yt_shimmer.dart';
import 'package:namida/youtube/widgets/yt_thumbnail.dart';
import 'package:youtipie/class/comments/comment_info_item.dart';

class YTCommentCard extends StatelessWidget {
final EdgeInsetsGeometry? margin;
final String? videoId;
final CommentInfoItem? comment;
const YTCommentCard({super.key, required this.comment, required this.margin});
const YTCommentCard({super.key, required this.videoId, required this.comment, required this.margin});

@override
Widget build(BuildContext context) {
final uploaderAvatar = comment?.authorAvatarUrl ?? comment?.author?.avatarThumbnailUrl;
final author = comment?.author?.displayName;
final isArtist = comment?.author?.isArtist ?? false;
final uploadedFrom = comment?.publishedTimeText;
final commentTextParsed = comment?.text;
final commentContent = comment?.content;
final likeCount = comment?.likesCount;
final repliesCount = comment?.repliesCount;
final isHearted = comment?.isHearted ?? false;
Expand All @@ -41,6 +40,7 @@ class YTCommentCard extends StatelessWidget {
fontWeight: FontWeight.w400,
color: authorTextColor,
);

return Stack(
children: [
Padding(
Expand Down Expand Up @@ -148,88 +148,72 @@ class YTCommentCard extends StatelessWidget {
),
const SizedBox(height: 4.0),
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: commentTextParsed == null
? Column(
children: [
...List.filled(
(4 - 1).getRandomNumberBelow(1),
const Padding(
padding: EdgeInsets.only(top: 2.0),
child: NamidaDummyContainer(
width: null,
height: 12.0,
borderRadius: 4.0,
shimmerEnabled: true,
child: null,
),
),
),
],
)
: NamidaReadMoreText(
text: commentTextParsed,
lines: 5,
builder: (text, lines, isExpanded, exceededMaxLines, toggle) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableAutoLinkText(
text,
maxLines: lines,
style: context.textTheme.displaySmall?.copyWith(
fontSize: 13.5,
fontWeight: FontWeight.w500,
color: context.theme.colorScheme.onSurface.withAlpha(220),
),
linkStyle: context.textTheme.displayMedium?.copyWith(
color: context.theme.colorScheme.primary.withAlpha(210),
fontSize: 13.5,
duration: const Duration(milliseconds: 200),
child: commentContent == null
? Column(
children: [
...List.filled(
(4 - 1).getRandomNumberBelow(1),
const Padding(
padding: EdgeInsets.only(top: 2.0),
child: NamidaDummyContainer(
width: null,
height: 12.0,
borderRadius: 4.0,
shimmerEnabled: true,
child: null,
),
highlightedLinkStyle: TextStyle(
color: context.theme.colorScheme.primary.withAlpha(220),
backgroundColor: context.theme.colorScheme.onSurface.withAlpha(40),
fontSize: 13.5,
),
scrollPhysics: const NeverScrollableScrollPhysics(),
linkRegExpPattern: NamidaLinkRegex.all,
onTap: (url) async {
final dur = NamidaLinkUtils.parseDuration(url);
if (dur != null) {
Player.inst.seek(dur);
} else {
NamidaLinkUtils.openLink(url);
}
},
),
if (exceededMaxLines)
Padding(
padding: const EdgeInsets.all(8.0),
child: TapDetector(
onTap: toggle,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
),
],
)
: commentContent.rawText == null
? const SizedBox()
: YoutubeDescriptionWidget(
videoId: videoId,
content: commentContent,
linkColor: context.theme.colorScheme.primary.withAlpha(210),
childBuilder: (span) {
return NamidaReadMoreText(
span: span,
lines: 5,
builder: (span, lines, isExpanded, exceededMaxLines, toggle) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isExpanded ? '' : lang.SHOW_MORE,
style: context.textTheme.displaySmall?.copyWith(color: readmoreColor),
),
const SizedBox(width: 8),
Icon(
isExpanded ? Broken.arrow_up_3 : Broken.arrow_down_2,
size: 18.0,
color: readmoreColor,
Text.rich(
span,
maxLines: lines,
),
if (exceededMaxLines)
Padding(
padding: const EdgeInsets.all(8.0),
child: TapDetector(
onTap: toggle,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
isExpanded ? '' : lang.SHOW_MORE,
style: context.textTheme.displaySmall?.copyWith(color: readmoreColor),
),
const SizedBox(width: 8),
Icon(
isExpanded ? Broken.arrow_up_3 : Broken.arrow_down_2,
size: 18.0,
color: readmoreColor,
),
],
),
),
),
],
),
),
),
],
);
},
),
),
);
},
);
},
)),
const SizedBox(height: 8.0),
Row(
children: [
Expand Down Expand Up @@ -289,8 +273,9 @@ class YTCommentCard extends StatelessWidget {
icon: Broken.copy,
title: lang.COPY,
onTap: () {
if (commentTextParsed != null) {
Clipboard.setData(ClipboardData(text: commentTextParsed));
final rawText = comment?.content.rawText;
if (rawText != null) {
Clipboard.setData(ClipboardData(text: rawText));
}
},
),
Expand Down Expand Up @@ -325,7 +310,7 @@ class YTCommentCardCompact extends StatelessWidget {
final uploaderAvatar = comment?.authorAvatarUrl ?? comment?.author?.avatarThumbnailUrl;
final author = comment?.author?.displayName;
final uploadedFrom = comment?.publishedTimeText;
final commentTextParsed = comment?.text;
final commentTextParsed = comment?.content.rawText;
final likeCount = comment?.likesCount;
final repliesCount = comment?.repliesCount;
final isHearted = comment?.isHearted ?? false;
Expand Down
Loading

0 comments on commit 938af52

Please sign in to comment.