Skip to content

Commit

Permalink
fix(*): Fix unexpected time offset in html doc parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
realth000 committed Dec 23, 2023
1 parent e1c0a4a commit 25abfc6
Show file tree
Hide file tree
Showing 18 changed files with 75 additions and 31 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

## Fixed

- 修复页面中时间显示和网页端有误差的问题。

## [0.2.0] - 2023-12-22

### Added
Expand Down
7 changes: 5 additions & 2 deletions lib/extensions/date_time.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:tsdm_client/providers/small_providers.dart';

extension DateTimeExtension on DateTime {
String yyyyMMDD() {
return '$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}';
}

String elapsedTillNow() {
final duration = DateTime.now().difference(this);
String elapsedTillNow(WidgetRef ref) {
final duration = ref.read(serverDateTimeProvider).difference(this);
return duration.inDays > 0
? '${duration.inDays}天'
: duration.inHours > 0
Expand Down
9 changes: 5 additions & 4 deletions lib/providers/auth_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import 'package:dio/dio.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/extensions/universal_html.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/providers/settings_provider.dart';
import 'package:tsdm_client/utils/debug.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

part '../generated/providers/auth_provider.g.dart';

Expand Down Expand Up @@ -146,7 +146,7 @@ class Auth extends _$Auth {
return (LoginResult.requestFailed, '$message');
}

final document = parseHtmlDocument(resp.data as String);
final document = ref.read(htmlParserProvider.notifier).parseResp(resp);
final messageNode = document.getElementById('messagetext');
if (messageNode == null) {
// Impossible.
Expand Down Expand Up @@ -188,7 +188,7 @@ class Auth extends _$Auth {
);
return false;
}
final document = parseHtmlDocument(resp.data as String);
final document = ref.read(htmlParserProvider.notifier).parseResp(resp);
final uid = await _parseUidInDocument(document);
if (uid == null) {
debug('unnecessary logout: not authed');
Expand Down Expand Up @@ -216,7 +216,8 @@ class Auth extends _$Auth {
return false;
}

final logoutDocument = parseHtmlDocument(logoutResp.data as String);
final logoutDocument =
ref.read(htmlParserProvider.notifier).parseResp(logoutResp);
final logoutMessage = logoutDocument.getElementById('messagetext');
if (logoutMessage == null || !logoutMessage.innerHtmlEx().contains('已退出')) {
debug('failed to logout: logout message not found');
Expand Down
4 changes: 2 additions & 2 deletions lib/providers/check_in_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/models/check_in_feeling.dart';
import 'package:tsdm_client/providers/auth_provider.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/providers/small_providers.dart';
import 'package:tsdm_client/utils/debug.dart';
import 'package:universal_html/parsing.dart';

part '../generated/providers/check_in_provider.g.dart';

Expand Down Expand Up @@ -65,7 +65,7 @@ class CheckIn extends _$CheckIn {
return (CheckInResult.webRequestFailed, '${resp.statusCode}');
}

final document = parseHtmlDocument(resp.data as String);
final document = ref.read(htmlParserProvider.notifier).parseResp(resp);
final re = RegExp(r'formhash" value="(?<FormHash>\w+)"');
final formHashMatch = re.firstMatch(document.body?.innerHtml ?? '');
final formHash = formHashMatch?.namedGroup('FormHash');
Expand Down
30 changes: 30 additions & 0 deletions lib/providers/html_parser_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:dio/dio.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:tsdm_client/extensions/string.dart';
import 'package:tsdm_client/providers/small_providers.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

part '../generated/providers/html_parser_provider.g.dart';

@Riverpod()
class HtmlParser extends _$HtmlParser {
@override
void build() {}

uh.HtmlDocument parseResp<T>(Response<T> resp) {
final doc = parseHtmlDocument((resp.data ?? '') as String);
final serverTime = doc
.querySelector('p.xs0')
?.childNodes
.elementAtOrNull(0)
?.text
?.split(',')
.lastOrNull
?.trim()
.parseToDateTimeUtc8() ??
DateTime.now();
ref.read(serverDateTimeProvider.notifier).state = serverTime;
return doc;
}
}
7 changes: 4 additions & 3 deletions lib/providers/root_content_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/extensions/universal_html.dart';
import 'package:tsdm_client/providers/auth_provider.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/providers/settings_provider.dart';
import 'package:tsdm_client/providers/small_providers.dart';
import 'package:tsdm_client/utils/debug.dart';
import 'package:universal_html/html.dart';
import 'package:universal_html/parsing.dart';

part '../generated/providers/root_content_provider.g.dart';

Expand Down Expand Up @@ -101,7 +101,7 @@ class RootContent extends _$RootContent {
while (i < 3) {
final resp = await ref.read(netClientProvider()).get(_rootPage);
if (resp.statusCode == HttpStatus.ok) {
_doc = parseHtmlDocument(resp.data as String);
_doc = ref.read(htmlParserProvider.notifier).parseResp(resp);
await ref.read(authProvider.notifier).loginFromDocument(_doc);
final username = ref.read(authProvider.notifier).loggedUsername;
await _cache.analyze(_doc, username);
Expand All @@ -124,7 +124,8 @@ class RootContent extends _$RootContent {
final profileResp =
await ref.read(netClientProvider()).get('$_profilePage$uid');
if (profileResp.statusCode == HttpStatus.ok) {
_profileDoc = parseHtmlDocument(profileResp.data as String);
_profileDoc =
ref.read(htmlParserProvider.notifier).parseResp(profileResp);
_avatarUrl = _profileDoc!
.querySelector('div#wp.wp div#ct.ct2 div.sd div.hm > p > a > img')
?.attributes['src'];
Expand Down
4 changes: 2 additions & 2 deletions lib/providers/search_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/extensions/string.dart';
import 'package:tsdm_client/extensions/universal_html.dart';
import 'package:tsdm_client/models/searched_thread.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:universal_html/parsing.dart';

part '../generated/providers/search_provider.g.dart';

Expand Down Expand Up @@ -115,7 +115,7 @@ class Search extends _$Search {
return const SearchResult.empty();
}

final document = parseHtmlDocument(resp.data as String);
final document = ref.read(htmlParserProvider.notifier).parseResp(resp);

final threadList = document
.querySelectorAll('div#ct > div#ct_shell > div#left_s > div.ts_se_rs')
Expand Down
2 changes: 2 additions & 0 deletions lib/providers/small_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ final appNavigationBarIndexProvider = StateProvider((ref) => 0);
final isCheckingInProvider = StateProvider((ref) => false);

final topicsTabBarIndexProvider = StateProvider((ref) => 0);

final serverDateTimeProvider = StateProvider((ref) => DateTime.now());
4 changes: 2 additions & 2 deletions lib/screens/forum/forum_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:tsdm_client/generated/i18n/strings.g.dart';
import 'package:tsdm_client/models/forum.dart';
import 'package:tsdm_client/models/normal_thread.dart';
import 'package:tsdm_client/packages/html_muncher/lib/src/html_muncher.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/jump_page_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/routes/screen_paths.dart';
Expand All @@ -22,7 +23,6 @@ import 'package:tsdm_client/widgets/forum_card.dart';
import 'package:tsdm_client/widgets/list_app_bar.dart';
import 'package:tsdm_client/widgets/thread_card.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

/// Forum page.
class ForumPage extends ConsumerStatefulWidget {
Expand Down Expand Up @@ -185,7 +185,7 @@ class _ForumPageState extends ConsumerState<ForumPage>
'${widget._fetchUrl}&page=$_pageNumber',
);
if (d1.statusCode == HttpStatus.ok) {
document = parseHtmlDocument(d1.data as String);
document = ref.read(htmlParserProvider.notifier).parseResp(d1);
break;
}

Expand Down
5 changes: 3 additions & 2 deletions lib/screens/notice/notice_detail_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import 'package:tsdm_client/generated/i18n/strings.g.dart';
import 'package:tsdm_client/models/notice.dart';
import 'package:tsdm_client/models/post.dart';
import 'package:tsdm_client/models/reply_parameters.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/utils/debug.dart';
import 'package:tsdm_client/utils/show_toast.dart';
import 'package:tsdm_client/widgets/post_card.dart';
import 'package:tsdm_client/widgets/reply_bar.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

/// Show details for a single notice, also provides interaction:
/// * Reply to the notice if notice type is [NoticeType.reply] or [NoticeType.mention].
Expand Down Expand Up @@ -183,7 +183,8 @@ class _NoticeDetailPage extends ConsumerState<NoticeDetailPage> {
}
if (snapshot.hasData) {
final data = snapshot.data!;
final document = parseHtmlDocument(data.data as String);
final document =
ref.read(htmlParserProvider.notifier).parseResp(data);
return _buildBody(context, document);
}
return Center(
Expand Down
4 changes: 2 additions & 2 deletions lib/screens/notice/notice_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import 'package:tsdm_client/constants/layout.dart';
import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/generated/i18n/strings.g.dart';
import 'package:tsdm_client/models/notice.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/utils/debug.dart';
import 'package:tsdm_client/utils/show_toast.dart';
import 'package:tsdm_client/widgets/notice_card.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

/// Notice page, shows [Notice] and PrivateMessage of current user.
class NoticePage extends ConsumerStatefulWidget {
Expand All @@ -39,7 +39,7 @@ class _NoticePageState extends ConsumerState<NoticePage> {
while (true) {
final resp = await ref.read(netClientProvider()).get(url);
if (resp.statusCode == HttpStatus.ok) {
document = parseHtmlDocument(resp.data as String);
document = ref.read(htmlParserProvider.notifier).parseResp(resp);
break;
}

Expand Down
5 changes: 3 additions & 2 deletions lib/screens/profile/profile_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/extensions/universal_html.dart';
import 'package:tsdm_client/generated/i18n/strings.g.dart';
import 'package:tsdm_client/providers/auth_provider.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/providers/root_content_provider.dart';
import 'package:tsdm_client/routes/screen_paths.dart';
Expand All @@ -17,7 +18,6 @@ import 'package:tsdm_client/widgets/check_in_button.dart';
import 'package:tsdm_client/widgets/debounce_buttons.dart';
import 'package:tsdm_client/widgets/obscure_list_tile.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

class ProfilePage extends ConsumerStatefulWidget {
const ProfilePage({this.uid, super.key});
Expand Down Expand Up @@ -275,7 +275,8 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {

if (snapshot.hasData) {
final resp = snapshot.data;
final document = parseHtmlDocument(resp!.data as String);
final document =
ref.read(htmlParserProvider.notifier).parseResp(resp!);
return _buildProfile(context, document);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/screens/thread/post_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:tsdm_client/generated/i18n/strings.g.dart';
import 'package:tsdm_client/models/normal_thread.dart';
import 'package:tsdm_client/models/reply_parameters.dart';
import 'package:tsdm_client/packages/html_muncher/lib/html_muncher.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/jump_page_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/providers/screen_state_provider.dart';
Expand All @@ -21,7 +22,6 @@ import 'package:tsdm_client/utils/debug.dart';
import 'package:tsdm_client/utils/show_toast.dart';
import 'package:tsdm_client/widgets/list_app_bar.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

// enum _MenuActions {
// refresh,
Expand Down Expand Up @@ -147,7 +147,7 @@ class _PostListState<T> extends ConsumerState<PostList<T>> {
'${widget.fetchUrl}${widget.canFetchMorePages ? "&page=$_pageNumber" : ""}',
);
if (d1.statusCode == HttpStatus.ok) {
document = parseHtmlDocument(d1.data as String);
document = ref.read(htmlParserProvider.notifier).parseResp(d1);
break;
}
if (!mounted) {
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/forum_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class _ForumCardState extends ConsumerState<ForumCard> {
maxLines: 2,
),
subtitle: widget.forum.latestThreadTime != null
? Text(widget.forum.latestThreadTime!.elapsedTillNow())
? Text(widget.forum.latestThreadTime!.elapsedTillNow(ref))
: null,
),
if (showShortCut)
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/post_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class _PostCardState extends ConsumerState<PostCard>
),
),
title: Text(widget.post.author.name),
subtitle: Text('${widget.post.publishTime?.elapsedTillNow()}'),
subtitle: Text('${widget.post.publishTime?.elapsedTillNow(ref)}'),
trailing: widget.post.postFloor == null
? null
: Text('#${widget.post.postFloor}'),
Expand Down
6 changes: 3 additions & 3 deletions lib/widgets/refresh_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:tsdm_client/constants/layout.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:universal_html/html.dart' as uh;
import 'package:universal_html/parsing.dart';

/// A refreshable [ListView].
///
Expand Down Expand Up @@ -84,7 +84,7 @@ class _RefreshListState<T> extends ConsumerState<RefreshList<T>> {
if (!mounted) {
return;
}
final document = parseHtmlDocument(resp.data as String);
final document = ref.read(htmlParserProvider.notifier).parseResp(resp);
final data = await widget.buildDataCallback(document);
setState(() {
_allData.addAll(data);
Expand All @@ -101,7 +101,7 @@ class _RefreshListState<T> extends ConsumerState<RefreshList<T>> {
return;
}
final resp = await ref.read(netClientProvider()).get(_nextPageUrl!);
final document = parseHtmlDocument(resp.data as String);
final document = ref.read(htmlParserProvider.notifier).parseResp(resp);
final data = await widget.buildDataCallback(document);
setState(() {
_allData.addAll(data);
Expand Down
5 changes: 3 additions & 2 deletions lib/widgets/reply_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import 'package:tsdm_client/constants/layout.dart';
import 'package:tsdm_client/constants/url.dart';
import 'package:tsdm_client/generated/i18n/strings.g.dart';
import 'package:tsdm_client/models/reply_parameters.dart';
import 'package:tsdm_client/providers/html_parser_provider.dart';
import 'package:tsdm_client/providers/net_client_provider.dart';
import 'package:tsdm_client/utils/debug.dart';
import 'package:tsdm_client/utils/show_dialog.dart';
import 'package:universal_html/parsing.dart';

class ReplyBar extends ConsumerStatefulWidget {
const ReplyBar({required this.controller, super.key});
Expand Down Expand Up @@ -133,7 +133,8 @@ class _ReplyBarState extends ConsumerState<ReplyBar> {
return false;
}

final replyWindowDoc = parseHtmlDocument(replyWindowResp.data as String);
final replyWindowDoc =
ref.read(htmlParserProvider.notifier).parseResp(replyWindowResp);
final inputList = replyWindowDoc.querySelectorAll('input');

String? formHash;
Expand Down
2 changes: 1 addition & 1 deletion lib/widgets/thread_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class _CardLayout extends ConsumerWidget {
if (latestReplyTime != null)
(
Icons.timelapse_outlined,
latestReplyTime!.elapsedTillNow(),
latestReplyTime!.elapsedTillNow(ref),
),
if ((price ?? 0) > 0) (FontAwesomeIcons.coins, '$price'),
];
Expand Down

0 comments on commit 25abfc6

Please sign in to comment.