diff --git a/lib/extensions/string.dart b/lib/extensions/string.dart index 72ced3b4..8757fd8f 100644 --- a/lib/extensions/string.dart +++ b/lib/extensions/string.dart @@ -57,6 +57,8 @@ extension ParseUrl on String { } if (mod == 'viewthread' && queryParameters.containsKey('tid')) { + final order = queryParameters['ordertype']?.parseToInt(); + // When anchor is used, means need to scroll to a target post by its pid. // // In this situation, do NOT override page order because the page number @@ -69,6 +71,7 @@ extension ParseUrl on String { if (queryParameters.containsKey('page')) 'pageNumber': "${queryParameters['page']}", if (anchor != null) 'overrideReverseOrder': 'false', + if (order != null) 'overrideWithExactOrder': '$order', if (anchor != null) 'pid': anchor, if (queryParameters.containsKey('authorid')) 'onlyVisibleUid': "${queryParameters['authorid']}", diff --git a/lib/features/thread/bloc/thread_bloc.dart b/lib/features/thread/bloc/thread_bloc.dart index 2374852c..3a2e6fcf 100644 --- a/lib/features/thread/bloc/thread_bloc.dart +++ b/lib/features/thread/bloc/thread_bloc.dart @@ -23,6 +23,7 @@ class ThreadBloc extends Bloc with LoggerMixin { required String? pid, required String? onlyVisibleUid, required bool? reverseOrder, + required int? exactOrder, required ThreadRepository threadRepository, }) : _threadRepository = threadRepository, super( @@ -31,6 +32,7 @@ class ThreadBloc extends Bloc with LoggerMixin { pid: pid, onlyVisibleUid: onlyVisibleUid, reverseOrder: reverseOrder, + exactOrder: exactOrder, ), ) { on(_onThreadLoadMoreRequested); @@ -59,6 +61,7 @@ class ThreadBloc extends Bloc with LoggerMixin { pageNumber: event.pageNumber, onlyVisibleUid: state.onlyVisibleUid, reverseOrder: state.reverseOrder, + exactOrder: state.exactOrder, ) .match( (e) { @@ -85,6 +88,7 @@ class ThreadBloc extends Bloc with LoggerMixin { pid: state.pid, onlyVisibleUid: state.onlyVisibleUid, reverseOrder: state.reverseOrder, + exactOrder: state.exactOrder, ) .match( (e) { @@ -112,6 +116,7 @@ class ThreadBloc extends Bloc with LoggerMixin { pageNumber: event.pageNumber, onlyVisibleUid: state.onlyVisibleUid, reverseOrder: state.reverseOrder, + exactOrder: state.exactOrder, ) .map( (v) => @@ -147,6 +152,7 @@ class ThreadBloc extends Bloc with LoggerMixin { pageNumber: state.currentPage, onlyVisibleUid: event.uid, reverseOrder: state.reverseOrder, + exactOrder: state.exactOrder, ) .match( (e) { @@ -186,6 +192,7 @@ class ThreadBloc extends Bloc with LoggerMixin { pid: state.pid, pageNumber: state.currentPage, reverseOrder: state.reverseOrder, + exactOrder: state.exactOrder, ) .match( (e) { @@ -230,6 +237,7 @@ class ThreadBloc extends Bloc with LoggerMixin { pageNumber: state.currentPage, onlyVisibleUid: state.onlyVisibleUid, reverseOrder: state.reverseOrder, + exactOrder: state.exactOrder, ) .match( (e) { @@ -375,6 +383,7 @@ class ThreadBloc extends Bloc with LoggerMixin { onlyVisibleUid: (clearOnlyVisibleUid ?? false) ? null : state.onlyVisibleUid, reverseOrder: state.reverseOrder, + exactOrder: state.exactOrder, isDraft: isDraft ?? false, latestModAct: latestModAct, ); diff --git a/lib/features/thread/bloc/thread_state.dart b/lib/features/thread/bloc/thread_state.dart index a14301a5..19294b52 100644 --- a/lib/features/thread/bloc/thread_state.dart +++ b/lib/features/thread/bloc/thread_state.dart @@ -38,6 +38,7 @@ class ThreadState with ThreadStateMappable { this.threadType, this.onlyVisibleUid, this.reverseOrder, + this.exactOrder, this.isDraft = false, this.latestModAct, }); @@ -124,6 +125,11 @@ class ThreadState with ThreadStateMappable { /// * Not force order if `null`. final bool? reverseOrder; + /// The exact thread order in state. + /// + /// Specify this field if want to override with the app one. + final int? exactOrder; + /// Indicating current thread is a draft or not. final bool isDraft; diff --git a/lib/features/thread/repository/thread_repository.dart b/lib/features/thread/repository/thread_repository.dart index 5b916dbe..95ba9dbe 100644 --- a/lib/features/thread/repository/thread_repository.dart +++ b/lib/features/thread/repository/thread_repository.dart @@ -32,6 +32,7 @@ class ThreadRepository { int pageNumber = 1, String? onlyVisibleUid, bool? reverseOrder, + int? exactOrder, }) => AsyncEither(() async { assert( @@ -56,10 +57,11 @@ class ThreadRepository { // to find a post in a certain page number, in this use case a manually // other override may going into different page that does NOT contain // the target post. - final orderType = switch (reverseOrder) { - true => '&ordertype=1', - false => '&ordertype=2', - null => '', + final orderType = switch ((exactOrder, reverseOrder)) { + (final int i, _) => '&ordertype=$i', + (null, true) => '&ordertype=1', + (null, false) => '&ordertype=2', + (null, null) => '', }; _pageNumber = pageNumber; diff --git a/lib/features/thread/view/thread_page.dart b/lib/features/thread/view/thread_page.dart index 96eae227..dad67fd9 100644 --- a/lib/features/thread/view/thread_page.dart +++ b/lib/features/thread/view/thread_page.dart @@ -39,6 +39,7 @@ class ThreadPage extends StatefulWidget { required this.findPostID, required this.pageNumber, required this.overrideReverseOrder, + required this.overrideWithExactOrder, this.title, this.threadType, this.onlyVisibleUid, @@ -80,8 +81,28 @@ class ThreadPage extends StatefulWidget { /// This flag is used in situation that user is heading to a certain page /// contains a target post. If set to `true`, override order may cause going /// to a wrong page. + /// + /// Additionally, the effect has less priority compared to + /// [overrideWithExactOrder] where the latter one is specifying the exact + /// order type and current field only determines using the order specified by + /// app if has. final bool overrideReverseOrder; + /// Carries the exact order required by external reasons. + /// + /// If value is not null, the final thread order is override by the value no + /// matter [overrideReverseOrder] is true or false. + /// + /// Actually this field is a patch on is the following situation: + /// + /// ```console + /// ${HOST}/...&ordertype=N + /// ``` + /// + /// where order type is directly specified in url before dispatching, and + /// should override any order in app settings. + final int? overrideWithExactOrder; + /// Thread type. /// /// Sometimes we do not know the thread type before we load it, redirect from @@ -220,6 +241,7 @@ class _ThreadPageState extends State threadRepository: context.repo(), reverseOrder: widget.overrideReverseOrder ? threadReverseOrder : null, + exactOrder: widget.overrideWithExactOrder, )..add(ThreadLoadMoreRequested(int.tryParse(widget.pageNumber) ?? 1)), ), BlocProvider( diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index e024d06f..f8e1476d 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -145,6 +145,8 @@ final router = GoRouter( } else { overrideReverseOrder = true; } + final overrideWithExactOrder = + state.uri.queryParameters['overrideWithExactOrder']?.parseToInt(); assert( tid != null || pid != null, @@ -158,6 +160,7 @@ final router = GoRouter( findPostID: pid, pageNumber: pageNumber ?? '1', overrideReverseOrder: overrideReverseOrder, + overrideWithExactOrder: overrideWithExactOrder, onlyVisibleUid: onlyVisibleUid, ); }, diff --git a/lib/routes/screen_paths.dart b/lib/routes/screen_paths.dart index 2cf826ba..83cc7478 100644 --- a/lib/routes/screen_paths.dart +++ b/lib/routes/screen_paths.dart @@ -79,6 +79,9 @@ class ScreenPaths { /// /// `overrideReverseOrder`: set to "false" keep the original post order in /// thread, for some use case user heading to a page contains a certain post. + /// + /// `overrideWithExactOrder`: set the exact thread order type, this value + /// is usually specified by the original source (in url). static const String thread = '/thread'; /// Notice page.