From cc774015f981a895e4016bcd560cceb2a63f1f74 Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Fri, 28 Mar 2025 21:25:39 +0800 Subject: [PATCH] feat: fav note page Signed-off-by: bggRGjQaUbCoE --- lib/http/api.dart | 10 ++- lib/http/init.dart | 6 +- lib/http/video.dart | 86 +++++++++++++++++- lib/pages/common/common_controller.dart | 7 +- lib/pages/fav/note/child_view.dart | 85 ++++++++++++++++++ lib/pages/fav/note/controller.dart | 22 +++++ lib/pages/fav/note/view.dart | 87 ++++++++++++++++++ lib/pages/fav/note/widget/item.dart | 84 +++++++++++++++++ lib/pages/fav/video/view.dart | 7 +- lib/pages/fav/view.dart | 3 +- .../member_contribute/member_contribute.dart | 53 +++++------ lib/pages/search_result/view.dart | 89 +++++++++---------- lib/pages/video/detail/controller.dart | 8 ++ .../video/detail/note/note_list_page.dart | 4 + lib/pages/webview/webview_page.dart | 27 +++++- 15 files changed, 487 insertions(+), 91 deletions(-) create mode 100644 lib/pages/fav/note/child_view.dart create mode 100644 lib/pages/fav/note/controller.dart create mode 100644 lib/pages/fav/note/view.dart create mode 100644 lib/pages/fav/note/widget/item.dart diff --git a/lib/http/api.dart b/lib/http/api.dart index 22354df6..acd3d5a7 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -725,5 +725,13 @@ class Api { static const String pgcIndexResult = '/pgc/season/index/result'; - static const String noteList = '/x/note/publish/list/archive'; + static const String archiveNoteList = '/x/note/publish/list/archive'; + + static const String noteList = '/x/note/list'; + + static const String userNoteList = '/x/note/publish/list/user'; + + static const String addNote = '/x/note/add'; + + static const String archiveNote = '/x/note/list/archive'; } diff --git a/lib/http/init.dart b/lib/http/init.dart index 4c7e0856..ed723317 100644 --- a/lib/http/init.dart +++ b/lib/http/init.dart @@ -272,9 +272,11 @@ class Request { static String headerUa({type = 'mob'}) { return type == 'mob' ? Platform.isIOS - ? 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1' + ? 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 BiliApp/62000200' : 'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36' - : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15'; + : type == 'ios' + ? 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 BiliApp/62000200' + : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15'; } static String responseDecoder(List responseBytes, RequestOptions options, diff --git a/lib/http/video.dart b/lib/http/video.dart index 89c05b26..e4dd1380 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -1074,7 +1074,7 @@ class VideoHttp { required int page, }) async { var res = await Request().get( - Api.noteList, + Api.archiveNoteList, queryParameters: { 'csrf': Accounts.main.csrf, 'oid': oid, @@ -1090,4 +1090,88 @@ class VideoHttp { return LoadingState.error(res.data['message']); } } + + static Future noteList({ + required int page, + }) async { + var res = await Request().get( + Api.noteList, + queryParameters: { + 'pn': page, + 'ps': 10, + 'csrf': Accounts.main.csrf, + }, + ); + if (res.data['code'] == 0) { + return LoadingState.success(res.data['data']?['list']); + } else { + return LoadingState.error(res.data['message']); + } + } + + static Future userNoteList({ + required int page, + }) async { + var res = await Request().get( + Api.userNoteList, + queryParameters: { + 'pn': page, + 'ps': 10, + 'csrf': Accounts.main.csrf, + }, + ); + if (res.data['code'] == 0) { + return LoadingState.success(res.data['data']?['list']); + } else { + return LoadingState.error(res.data['message']); + } + } + + static Future addNote({ + required oid, + required String title, + required String summary, + }) async { + String noteId = ''; + try { + final res = await Request().get(Api.archiveNote, queryParameters: { + 'oid': oid, + 'oid_type': 0, + 'csrf': Accounts.main.csrf, + }); + if (res.data['code'] == 0) { + if (res.data['data']['noteIds'] != null) { + noteId = res.data['data']['noteIds'].first; + } + } + } catch (_) {} + + var res = await Request().post( + Api.addNote, + data: { + 'cont_len': summary.length, + 'note_id': noteId, + 'oid': oid, + 'oid_type': 0, + 'platform': 'web', + 'title': title, + 'summary': summary, + 'content': jsonEncode([ + {"insert": summary}, + ]), + 'from': 'close', + 'hash': DateTime.now().millisecondsSinceEpoch, + 'tags': '', + 'csrf': Accounts.main.csrf, + }, + options: Options( + contentType: Headers.formUrlEncodedContentType, + ), + ); + if (res.data['code'] == 0) { + return LoadingState.success(res.data['data']?['list']); + } else { + return LoadingState.error(res.data['message']); + } + } } diff --git a/lib/pages/common/common_controller.dart b/lib/pages/common/common_controller.dart index dda69716..a1b6e966 100644 --- a/lib/pages/common/common_controller.dart +++ b/lib/pages/common/common_controller.dart @@ -59,18 +59,19 @@ abstract class CommonController extends GetxController LoadingState response = await customGetData(); if (response is Success) { if (!customHandleResponse(response)) { - if ((response.response as List?).isNullOrEmpty) { + List dataList = (response.response as List?) ?? []; + if (dataList.isEmpty) { isEnd = true; } List currentList = loadingState.value is Success ? (loadingState.value as Success).response : []; - List? handleList = handleListResponse(currentList, response.response); + List? handleList = handleListResponse(currentList, dataList); loadingState.value = isRefresh ? handleList != null ? LoadingState.success(handleList) : response - : LoadingState.success(currentList + response.response); + : LoadingState.success(currentList + dataList); // handleSuccess(currentList, response.response); } currentPage++; diff --git a/lib/pages/fav/note/child_view.dart b/lib/pages/fav/note/child_view.dart new file mode 100644 index 00000000..ef776fe6 --- /dev/null +++ b/lib/pages/fav/note/child_view.dart @@ -0,0 +1,85 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/skeleton/video_card_h.dart'; +import 'package:PiliPlus/common/widgets/http_error.dart'; +import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/fav/note/controller.dart'; +import 'package:PiliPlus/pages/fav/note/widget/item.dart'; +import 'package:PiliPlus/utils/grid.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class FavNoteChildPage extends StatefulWidget { + const FavNoteChildPage({super.key, required this.isPublish}); + + final bool isPublish; + + @override + State createState() => _FavNoteChildPageState(); +} + +class _FavNoteChildPageState extends State + with AutomaticKeepAliveClientMixin { + late final FavNoteController _favNoteController = + Get.put(FavNoteController(widget.isPublish), tag: '${widget.isPublish}'); + + @override + Widget build(BuildContext context) { + super.build(context); + return refreshIndicator( + onRefresh: () async { + await _favNoteController.onRefresh(); + }, + child: CustomScrollView( + slivers: [ + Obx(() => _buildBody(_favNoteController.loadingState.value)), + ], + ), + ); + } + + Widget _buildBody(LoadingState loadingState) { + return switch (loadingState) { + Loading() => SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: 2, + maxCrossAxisExtent: Grid.mediumCardWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.2, + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return const VideoCardHSkeleton(); + }, + childCount: 10, + ), + ), + Success() => (loadingState.response as List?)?.isNotEmpty == true + ? SliverPadding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 80), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: 2, + maxCrossAxisExtent: Grid.mediumCardWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.7, + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return FavNoteItem(item: loadingState.response[index]); + }, + childCount: loadingState.response.length, + ), + ), + ) + : HttpError(callback: _favNoteController.onReload), + Error() => HttpError( + errMsg: loadingState.errMsg, + callback: _favNoteController.onReload, + ), + LoadingState() => throw UnimplementedError(), + }; + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/pages/fav/note/controller.dart b/lib/pages/fav/note/controller.dart new file mode 100644 index 00000000..4af3b39f --- /dev/null +++ b/lib/pages/fav/note/controller.dart @@ -0,0 +1,22 @@ +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/video.dart'; +import 'package:PiliPlus/pages/common/multi_select_controller.dart'; + +class FavNoteController extends MultiSelectController { + FavNoteController(this.isPublish); + + final bool isPublish; + + @override + void onInit() { + super.onInit(); + queryData(); + } + + @override + Future customGetData() { + return isPublish + ? VideoHttp.userNoteList(page: currentPage) + : VideoHttp.noteList(page: currentPage); + } +} diff --git a/lib/pages/fav/note/view.dart b/lib/pages/fav/note/view.dart new file mode 100644 index 00000000..6c674268 --- /dev/null +++ b/lib/pages/fav/note/view.dart @@ -0,0 +1,87 @@ +import 'package:PiliPlus/pages/fav/note/child_view.dart'; +import 'package:flutter/material.dart'; + +class FavNotePage extends StatefulWidget { + const FavNotePage({super.key}); + + @override + State createState() => _FavNotePageState(); +} + +class _FavNotePageState extends State + with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin { + late final TabController _tabController = + TabController(length: 2, vsync: this); + + @override + bool get wantKeepAlive => true; + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + super.build(context); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: TabBar( + overlayColor: WidgetStateProperty.all(Colors.transparent), + splashFactory: NoSplash.splashFactory, + isScrollable: true, + tabAlignment: TabAlignment.start, + controller: _tabController, + padding: const EdgeInsets.symmetric(horizontal: 8), + dividerHeight: 0, + indicatorWeight: 0, + indicatorPadding: + const EdgeInsets.symmetric(horizontal: 3, vertical: 8), + indicator: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: BorderRadius.circular(20), + ), + indicatorSize: TabBarIndicatorSize.tab, + labelStyle: TabBarTheme.of(context) + .labelStyle + ?.copyWith(fontSize: 14) ?? + const TextStyle(fontSize: 14), + labelColor: Theme.of(context).colorScheme.onSecondaryContainer, + unselectedLabelColor: Theme.of(context).colorScheme.outline, + tabs: [ + Tab(text: '未发布笔记'), + Tab(text: '公开笔记'), + ], + ), + ), + TextButton( + style: TextButton.styleFrom( + foregroundColor: Theme.of(context).colorScheme.onSurfaceVariant, + visualDensity: VisualDensity(horizontal: -2, vertical: -2), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + onPressed: () {}, + child: const Text('管理'), + ), + const SizedBox(width: 12), + ], + ), + Expanded( + child: TabBarView( + controller: _tabController, + physics: const NeverScrollableScrollPhysics(), + children: [ + FavNoteChildPage(isPublish: false), + FavNoteChildPage(isPublish: true), + ], + ), + ), + ], + ); + } +} diff --git a/lib/pages/fav/note/widget/item.dart b/lib/pages/fav/note/widget/item.dart new file mode 100644 index 00000000..ade1affa --- /dev/null +++ b/lib/pages/fav/note/widget/item.dart @@ -0,0 +1,84 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; + +class FavNoteItem extends StatelessWidget { + const FavNoteItem({super.key, required this.item}); + + final dynamic item; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + Utils.handleWebview(item['web_url'], inApp: true); + }, + onLongPress: () {}, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: 5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + item['title'], + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + height: 1.4, + fontSize: 14, + fontWeight: FontWeight.bold, + ), + ), + ), + const SizedBox(height: 1), + Text( + item['summary'], + maxLines: 1, + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + ), + ), + const SizedBox(height: 1), + Text( + item['message'], + maxLines: 1, + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + ), + ), + ], + ), + ), + if (item['arc']?['pic'] != null) ...[ + const SizedBox(width: 10), + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder( + builder: + (BuildContext context, BoxConstraints boxConstraints) { + return NetworkImgLayer( + src: item['arc']?['pic'], + width: boxConstraints.maxWidth, + height: boxConstraints.maxHeight, + ); + }, + ), + ), + ], + ], + ), + ), + ); + } +} diff --git a/lib/pages/fav/video/view.dart b/lib/pages/fav/video/view.dart index 3869cf72..07b63e63 100644 --- a/lib/pages/fav/video/view.dart +++ b/lib/pages/fav/video/view.dart @@ -18,11 +18,16 @@ class FavVideoPage extends StatefulWidget { State createState() => _FavVideoPageState(); } -class _FavVideoPageState extends State { +class _FavVideoPageState extends State + with AutomaticKeepAliveClientMixin { final FavController _favController = Get.find(); + @override + bool get wantKeepAlive => true; + @override Widget build(BuildContext context) { + super.build(context); return refreshIndicator( onRefresh: () async { await _favController.onRefresh(); diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index 939ec4d7..af3b3e73 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/fav/note/view.dart'; import 'package:PiliPlus/pages/fav/video/index.dart'; import 'package:PiliPlus/pages/fav_search/view.dart'; import 'package:flutter/material.dart'; @@ -95,7 +96,7 @@ class _FavPageState extends State with SingleTickerProviderStateMixin { _FavType.bangumi => Center(child: Text(item.title)), _FavType.cinema => Center(child: Text(item.title)), _FavType.article => Center(child: Text(item.title)), - _FavType.note => Center(child: Text(item.title)), + _FavType.note => const FavNotePage(), }, ) .toList(), diff --git a/lib/pages/member/new/content/member_contribute/member_contribute.dart b/lib/pages/member/new/content/member_contribute/member_contribute.dart index 46ca872f..14808e94 100644 --- a/lib/pages/member/new/content/member_contribute/member_contribute.dart +++ b/lib/pages/member/new/content/member_contribute/member_contribute.dart @@ -43,38 +43,29 @@ class _MemberContributeState extends State return _controller.tabs != null ? Column( children: [ - Container( - width: double.infinity, - color: Theme.of(context).colorScheme.surface, - child: Theme( - data: ThemeData( - splashColor: Colors.transparent, - highlightColor: Colors.transparent, - ), - child: TabBar( - padding: const EdgeInsets.symmetric(horizontal: 8), - isScrollable: true, - tabs: _controller.tabs!, - tabAlignment: TabAlignment.start, - controller: _controller.tabController, - dividerHeight: 0, - indicatorWeight: 0, - indicatorPadding: - const EdgeInsets.symmetric(horizontal: 3, vertical: 8), - indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: BorderRadius.circular(20), - ), - indicatorSize: TabBarIndicatorSize.tab, - labelStyle: TabBarTheme.of(context) - .labelStyle - ?.copyWith(fontSize: 14) ?? - const TextStyle(fontSize: 14), - labelColor: - Theme.of(context).colorScheme.onSecondaryContainer, - unselectedLabelColor: Theme.of(context).colorScheme.outline, - ), + TabBar( + overlayColor: WidgetStateProperty.all(Colors.transparent), + splashFactory: NoSplash.splashFactory, + padding: const EdgeInsets.symmetric(horizontal: 8), + isScrollable: true, + tabs: _controller.tabs!, + tabAlignment: TabAlignment.start, + controller: _controller.tabController, + dividerHeight: 0, + indicatorWeight: 0, + indicatorPadding: + const EdgeInsets.symmetric(horizontal: 3, vertical: 8), + indicator: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: BorderRadius.circular(20), ), + indicatorSize: TabBarIndicatorSize.tab, + labelStyle: TabBarTheme.of(context) + .labelStyle + ?.copyWith(fontSize: 14) ?? + const TextStyle(fontSize: 14), + labelColor: Theme.of(context).colorScheme.onSecondaryContainer, + unselectedLabelColor: Theme.of(context).colorScheme.outline, ), Expanded( child: TabBarView( diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index e11abd29..fdfee93c 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -86,56 +86,49 @@ class _SearchResultPageState extends State ), body: Column( children: [ - Container( + SizedBox( width: double.infinity, - padding: const EdgeInsets.only(top: 4), - color: Theme.of(context).colorScheme.surface, - child: Theme( - data: ThemeData( - splashColor: Colors.transparent, // 点击时的水波纹颜色设置为透明 - highlightColor: Colors.transparent, // 点击时的背景高亮颜色设置为透明 - ), - child: TabBar( - padding: const EdgeInsets.symmetric(horizontal: 8), - controller: _tabController, - tabs: SearchType.values - .map( - (item) => Obx( - () { - int count = _searchResultController.count[item.index]; - return Tab( - text: - '${item.label}${count != -1 ? ' ${count > 99 ? '99+' : count}' : ''}'); - }, - ), - ) - .toList(), - isScrollable: true, - indicatorWeight: 0, - indicatorPadding: - const EdgeInsets.symmetric(horizontal: 3, vertical: 8), - indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: const BorderRadius.all(Radius.circular(20)), - ), - indicatorSize: TabBarIndicatorSize.tab, - labelColor: Theme.of(context).colorScheme.onSecondaryContainer, - labelStyle: TabBarTheme.of(context) - .labelStyle - ?.copyWith(fontSize: 13) ?? - const TextStyle(fontSize: 13), - dividerColor: Colors.transparent, - dividerHeight: 0, - unselectedLabelColor: Theme.of(context).colorScheme.outline, - tabAlignment: TabAlignment.start, - onTap: (index) { - if (_tabController.indexIsChanging.not) { - Get.find( - tag: SearchType.values[index].name + _tag) - .animateToTop(); - } - }, + child: TabBar( + overlayColor: WidgetStateProperty.all(Colors.transparent), + splashFactory: NoSplash.splashFactory, + padding: const EdgeInsets.only(top: 4, left: 8, right: 8), + controller: _tabController, + tabs: SearchType.values + .map( + (item) => Obx( + () { + int count = _searchResultController.count[item.index]; + return Tab( + text: + '${item.label}${count != -1 ? ' ${count > 99 ? '99+' : count}' : ''}'); + }, + ), + ) + .toList(), + isScrollable: true, + indicatorWeight: 0, + indicatorPadding: + const EdgeInsets.symmetric(horizontal: 3, vertical: 8), + indicator: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: const BorderRadius.all(Radius.circular(20)), ), + indicatorSize: TabBarIndicatorSize.tab, + labelColor: Theme.of(context).colorScheme.onSecondaryContainer, + labelStyle: + TabBarTheme.of(context).labelStyle?.copyWith(fontSize: 13) ?? + const TextStyle(fontSize: 13), + dividerColor: Colors.transparent, + dividerHeight: 0, + unselectedLabelColor: Theme.of(context).colorScheme.outline, + tabAlignment: TabAlignment.start, + onTap: (index) { + if (_tabController.indexIsChanging.not) { + Get.find( + tag: SearchType.values[index].name + _tag) + .animateToTop(); + } + }, ), ), Expanded( diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 05ef8908..a1cb3344 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -1622,6 +1622,11 @@ class VideoDetailController extends GetxController } void showNoteList(BuildContext context) async { + String? title; + try { + title = + Get.find(tag: heroTag).videoDetail.value.title; + } catch (_) {} if (plPlayerController.isFullScreen.value) { Utils.showFSSheet( context, @@ -1633,6 +1638,7 @@ class VideoDetailController extends GetxController enableSlide: false, heroTag: heroTag, isStein: graphVersion != null, + title: title, ), ) : NoteListPage( @@ -1640,6 +1646,7 @@ class VideoDetailController extends GetxController enableSlide: false, heroTag: heroTag, isStein: graphVersion != null, + title: title, ), isFullScreen: () => plPlayerController.isFullScreen.value, ); @@ -1650,6 +1657,7 @@ class VideoDetailController extends GetxController oid: oid.value, heroTag: heroTag, isStein: graphVersion != null, + title: title, ), ); } diff --git a/lib/pages/video/detail/note/note_list_page.dart b/lib/pages/video/detail/note/note_list_page.dart index 7f40fefd..33eeae8c 100644 --- a/lib/pages/video/detail/note/note_list_page.dart +++ b/lib/pages/video/detail/note/note_list_page.dart @@ -20,12 +20,14 @@ class NoteListPage extends CommonSlidePage { this.oid, this.upperMid, required this.isStein, + required this.title, }); final dynamic heroTag; final dynamic oid; final dynamic upperMid; final bool isStein; + final dynamic title; @override State createState() => _NoteListPageState(); @@ -109,6 +111,8 @@ class _NoteListPageState extends CommonSlidePageState { onPressed: () { _key.currentState?.showBottomSheet( (context) => WebviewPageNew( + oid: widget.oid, + title: widget.title, url: 'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}', ), diff --git a/lib/pages/webview/webview_page.dart b/lib/pages/webview/webview_page.dart index aa5e7fc9..1c92a826 100644 --- a/lib/pages/webview/webview_page.dart +++ b/lib/pages/webview/webview_page.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'package:PiliPlus/http/init.dart'; +import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/utils/accounts/account.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/cache_manage.dart'; @@ -33,17 +34,23 @@ extension _WebviewMenuItemExt on _WebviewMenuItem { } class WebviewPageNew extends StatefulWidget { - const WebviewPageNew({super.key, this.url}); + const WebviewPageNew( + {super.key, this.url, this.oid, this.title, this.uaType}); final String? url; + // note + final int? oid; + final String? title; + final String? uaType; + @override State createState() => _WebviewPageNewState(); } class _WebviewPageNewState extends State { late final String _url = widget.url ?? Get.parameters['url'] ?? ''; - final uaType = Get.parameters['uaType'] ?? 'mob'; + late final uaType = widget.uaType ?? Get.parameters['uaType'] ?? 'mob'; final _titleStream = StreamController(); final _progressStream = StreamController(); bool? _inApp; @@ -183,7 +190,21 @@ class _WebviewPageNewState extends State { _webViewController?.addJavaScriptHandler( handlerName: 'finishButtonClicked', callback: (args) { - Get.back(); + _webViewController?.evaluateJavascript(source: """ + Array.from(document.querySelectorAll('.ql-editor > p')).map(p => p.textContent).join('\\n'); +""").then((value) { + try { + String? summary = (value as String?); + if (summary?.isNotEmpty == true) { + VideoHttp.addNote( + oid: widget.oid!, + title: widget.title!, + summary: summary!, + ); + } + } catch (_) {} + Get.back(); + }); }, ); },