Skip to content

Commit

Permalink
feat(*): parse and show packet all taken away state
Browse files Browse the repository at this point in the history
  • Loading branch information
realth000 committed Sep 27, 2024
1 parent 29acbd5 commit 30d3dc3
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 56 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- 帖子:我的帖子页面中显示更多帖子信息。
- 帖子:我的帖子页面中修改帖子卡片布局。
- 帖子:支持解析新人报道分区的帖子中的新人报道表格。
- 帖子:现在已被领完的红包会直接显示领完了。
- 消息:现在来源于帖子中的消息会直接跳转到帖子的相应楼层,而不经过消息详情页。
- app:支持设置和使用代理。
- 默认关闭,可在设置 -> 高级 -> 启用代理中打开。
Expand Down
12 changes: 9 additions & 3 deletions lib/features/packet/cubit/packet_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ part 'packet_state.dart';
/// Cubit of read packets.
class PacketCubit extends Cubit<PacketState> with LoggerMixin {
/// Constructor.
PacketCubit({required PacketRepository packetRepository})
: _packetRepository = packetRepository,
super(const PacketState());
PacketCubit({
required PacketRepository packetRepository,
required bool allTaken,
}) : _packetRepository = packetRepository,
super(
allTaken
? const PacketState(status: PacketStatus.takenAway)
: const PacketState(),
);

final PacketRepository _packetRepository;

Expand Down
6 changes: 6 additions & 0 deletions lib/features/settings/view/debug_showcase_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:tsdm_client/features/theme/cubit/theme_cubit.dart';
import 'package:tsdm_client/shared/models/models.dart';
import 'package:tsdm_client/utils/html/html_muncher.dart';
import 'package:tsdm_client/widgets/card/packet_card.dart';
import 'package:tsdm_client/widgets/card/rate_card.dart';
import 'package:universal_html/parsing.dart';

Expand Down Expand Up @@ -188,6 +189,9 @@ class _HtmlFragment extends StatelessWidget {
</ol>
</div>
</div>
<!-- Music iframe player -->
<iframe src="//music.163.com/outchain/player?id=1962823032"></iframe>
</body>
''';

Expand All @@ -203,6 +207,8 @@ class _HtmlFragment extends StatelessWidget {
parseLockedWithPurchase: true,
),
RateCard(Rate.fromRateLogNode(parseHtmlDocument(rateBlockData).body)!),
const PacketCard('', allTaken: false),
const PacketCard('', allTaken: true),
],
);
}
Expand Down
7 changes: 6 additions & 1 deletion lib/i18n/strings.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,8 @@
"share": "Copy share link"
},
"packetCard": {
"title": "You found a packet!",
"title": "Packet",
"detail": "You found a packet!",
"open": "Open It",
"failedToOpen": "Failed to open",
"allTakenAway": "All packets were taken away"
Expand Down Expand Up @@ -627,5 +628,9 @@
"newcomerReportCard": {
"title": "Detail Info"
}
},
"musicCard": {
"title": "Music",
"openLink": "Open link"
}
}
7 changes: 6 additions & 1 deletion lib/i18n/strings_zh-CN.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,8 @@
"share": "复制分享链接"
},
"packetCard": {
"title": "你找到了一个红包!",
"title": "红包",
"detail": "你找到了一个红包!",
"open": "打开",
"failedToOpen": "打开失败",
"allTakenAway": "红包都领完了"
Expand Down Expand Up @@ -627,5 +628,9 @@
"newcomerReportCard": {
"title": "详细信息"
}
},
"musicCard": {
"title": "音乐",
"openLink": "打开链接"
}
}
7 changes: 6 additions & 1 deletion lib/i18n/strings_zh-TW.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,8 @@
"share": "複製分享連結"
},
"packetCard": {
"title": "你找到一個紅包了!",
"title": "紅包",
"detail": "你找到一個紅包了!",
"open": "開啟",
"failedToOpen": "打開失敗",
"allTakenAway": "红包都領完了"
Expand Down Expand Up @@ -627,5 +628,9 @@
"newcomerReportCard": {
"title": "詳細資料"
}
},
"musicCard": {
"title": "音樂",
"openLink": "開啟連結"
}
}
12 changes: 12 additions & 0 deletions lib/shared/models/post.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
part of 'models.dart';

/// Image url of empty packet.
const _emptyPacketImageUrl = 'static/image/post/rp-2.svg';

extension _ParseExtension on uh.Element {
static final _rateActionRe = RegExp("'rate', '(?<url>forum.php[^']*)',");

Expand Down Expand Up @@ -29,6 +32,7 @@ class Post with PostMappable {
required this.shareLink,
required this.page,
required this.isDraft,
required this.packetAllTaken,
this.locked = const [],
this.rate,
this.packetUrl,
Expand Down Expand Up @@ -74,6 +78,9 @@ class Post with PostMappable {
/// Optional.
final String? packetUrl;

/// Is all packet taken away.
final bool packetAllTaken;

/// Url to edit this post.
///
/// Generally this field is not null only when current user is the author
Expand Down Expand Up @@ -232,6 +239,10 @@ class Post with PostMappable {
?.querySelector('div.pct > div#ts_packet > a')
?.attributes['href']
?.prependHost();
final packetAllTaken = postDataNode
?.querySelector('div.pct > div#ts_packet > a > img')
?.attributes['src'] ==
_emptyPacketImageUrl;

// Parse rate action:
// * If current post is the first floor in thread, rate action node is in <div id="fj">...</div>.
Expand Down Expand Up @@ -301,6 +312,7 @@ class Post with PostMappable {
rate: rate,
rateAction: rateAction,
packetUrl: packetUrl,
packetAllTaken: packetAllTaken,
editUrl: editUrl,
lastEditUsername: lastEditUsername,
lastEditTime: lastEditTime,
Expand Down
2 changes: 1 addition & 1 deletion lib/utils/html/html_muncher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ final class _Muncher with LoggerMixin {

/// Regex to match netease player iframe.
final _neteasePlayerRe =
RegExp(r'//music\.163\.com/outchain/player\?.+id=(?<id>\d+).*');
RegExp(r'//music\.163\.com/outchain/player\?.*id=(?<id>\d+).*');

List<InlineSpan>? _munch(uh.Element rootElement) {
final spanList = <InlineSpan>[];
Expand Down
80 changes: 44 additions & 36 deletions lib/utils/html/netease_card.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:fpdart/fpdart.dart' as fp;
import 'package:tsdm_client/constants/layout.dart';
import 'package:tsdm_client/i18n/strings.g.dart';
import 'package:tsdm_client/instance.dart';
import 'package:tsdm_client/shared/providers/net_client_provider/net_client_provider.dart';
import 'package:tsdm_client/shared/providers/providers.dart';
Expand Down Expand Up @@ -47,49 +48,56 @@ class _NeteaseCardState extends State<NeteaseCard> with LoggerMixin {

@override
Widget build(BuildContext context) {
final tr = context.t.musicCard;
final primaryColor = Theme.of(context).colorScheme.primary;
final primaryStyle = Theme.of(context).textTheme.titleMedium?.copyWith(
color: primaryColor,
);
final infoStyle = Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Theme.of(context).colorScheme.secondary,
);
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () async => launchUrlString('$urlPrefix${widget.id}'),
child: Card(
child: Padding(
padding: edgeInsetsL12T12R12B12,
child: Row(

return Card(
child: Padding(
padding: edgeInsetsL16T16R16B16,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
Icons.music_note_outlined,
color: Theme.of(context).colorScheme.secondary,
),
Icon(Icons.music_note_outlined, color: primaryColor),
sizedBoxW8H8,
Expanded(
child: FutureBuilder(
future: getIt
.get<NetClientProvider>(
instanceName: ServiceKeys.noCookie,
)
.get('$urlPrefix${widget.id}')
.run(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return switch (snapshot.data!) {
fp.Left() => Text(fallbackInfo, style: infoStyle),
fp.Right(:final value) => Text(
_parseMusicInfo(value.data as String),
style: infoStyle,
),
};
}

return sizedCircularProgressIndicator;
},
),
),
Text(tr.title, style: primaryStyle),
],
),
),
sizedBoxW12H12,
FutureBuilder(
future: getIt
.get<NetClientProvider>(
instanceName: ServiceKeys.noCookie,
)
.get('$urlPrefix${widget.id}')
.run(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return switch (snapshot.data!) {
fp.Left() => Text(fallbackInfo, style: infoStyle),
fp.Right(:final value) => Text(
_parseMusicInfo(value.data as String),
style: infoStyle,
),
};
}
return sizedCircularProgressIndicator;
},
),
sizedBoxW12H12,
OutlinedButton.icon(
icon: const Icon(Icons.launch_outlined),
label: Text(tr.openLink),
onPressed: () async => launchUrlString('$urlPrefix${widget.id}'),
),
],
),
),
);
Expand Down
49 changes: 37 additions & 12 deletions lib/widgets/card/packet_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,33 @@ import 'package:tsdm_client/i18n/strings.g.dart';
/// 红包
class PacketCard extends StatelessWidget {
/// Constructor.
const PacketCard(this.packetUrl, {super.key});
const PacketCard(
this.packetUrl, {
required this.allTaken,
super.key,
});

/// Url to fetch/receive the packet.
final String packetUrl;

/// Are all packet taken away.
final bool allTaken;

@override
Widget build(BuildContext context) {
final primaryColor = Theme.of(context).colorScheme.primary;
final tr = context.t.packetCard;

return MultiBlocProvider(
providers: [
RepositoryProvider(
create: (_) => PacketRepository(),
),
BlocProvider<PacketCubit>(
create: (context) =>
PacketCubit(packetRepository: RepositoryProvider.of(context)),
create: (context) => PacketCubit(
packetRepository: RepositoryProvider.of(context),
allTaken: allTaken,
),
),
],
child: BlocListener<PacketCubit, PacketState>(
Expand All @@ -34,15 +46,15 @@ class PacketCard extends StatelessWidget {
.showSnackBar(SnackBar(content: Text(state.reason!)));
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.t.packetCard.failedToOpen)),
SnackBar(content: Text(tr.failedToOpen)),
);
}
} else if (state.status == PacketStatus.success) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(state.reason!)));
} else if (state.status == PacketStatus.takenAway) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.t.packetCard.allTakenAway)),
SnackBar(content: Text(tr.allTakenAway)),
);
}
},
Expand All @@ -62,9 +74,9 @@ class PacketCard extends StatelessWidget {
PacketStatus.loading => const Text(''),
PacketStatus.initial ||
PacketStatus.success ||
PacketStatus.failed ||
PacketStatus.takenAway =>
Text(context.t.packetCard.open),
PacketStatus.failed =>
Text(tr.open),
PacketStatus.takenAway => Text(tr.allTakenAway),
};

final callback = switch (state.status) {
Expand All @@ -80,15 +92,28 @@ class PacketCard extends StatelessWidget {
child: Padding(
padding: edgeInsetsL16T16R16B16,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.t.packetCard.title,
style: Theme.of(context).textTheme.titleMedium,
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(FontAwesomeIcons.coins, color: primaryColor),
sizedBoxW8H8,
Text(
tr.title,
style:
Theme.of(context).textTheme.titleMedium?.copyWith(
color: primaryColor,
),
),
],
),
sizedBoxW12H12,
Text(tr.detail),
sizedBoxW12H12,
SizedBox(
width: sizeButtonInCardMinWidth,
child: FilledButton.icon(
child: OutlinedButton.icon(
icon: body,
label: label,
onPressed: callback,
Expand Down
5 changes: 4 additions & 1 deletion lib/widgets/card/post_card/post_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,10 @@ class _PostCardState extends State<PostCard>
...widget.post.locked.where((e) => e.isValid()).map(LockedCard.new),
if (widget.post.packetUrl != null) ...[
sizedBoxW12H12,
PacketCard(widget.post.packetUrl!),
PacketCard(
widget.post.packetUrl!,
allTaken: widget.post.packetAllTaken,
),
],
// Rate status if any.
if (widget.post.rate != null) ...[
Expand Down

0 comments on commit 30d3dc3

Please sign in to comment.