From 9a63e2347837aa5cf5191a94c890e03fe41a984a Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Thu, 29 May 2025 21:11:57 +0800 Subject: [PATCH] opt handle data Signed-off-by: bggRGjQaUbCoE --- .gitignore | 4 +- .../interactiveviewer_gallery.dart | 11 ++++-- lib/pages/danmaku/controller.dart | 3 ++ lib/pages/danmaku_block/controller.dart | 10 +++-- lib/pages/dynamics/controller.dart | 25 ++++++++----- lib/pages/dynamics_create/view.dart | 28 +++++++------- lib/pages/fav/pgc/controller.dart | 13 ++++--- lib/pages/fav/video/view.dart | 5 ++- lib/pages/fav/view.dart | 15 +++++--- lib/pages/follow/child_controller.dart | 5 ++- lib/pages/follow/child_view.dart | 7 ++-- lib/pages/follow/controller.dart | 5 ++- lib/pages/later/controller.dart | 5 ++- lib/pages/member_favorite/controller.dart | 10 +++-- lib/pages/member_favorite/view.dart | 6 +-- lib/pages/rcmd/view.dart | 11 +++--- lib/pages/video/controller.dart | 4 ++ .../video/introduction/pgc/controller.dart | 10 ++--- .../video/introduction/ugc/controller.dart | 10 ++--- lib/pages/video/member/view.dart | 6 +-- lib/pages/video/reply_reply/view.dart | 8 ++-- lib/pages/video/view.dart | 37 ++++++++----------- lib/pages/video/widgets/header_control.dart | 23 ++++++++---- lib/plugin/pl_player/controller.dart | 2 + 24 files changed, 147 insertions(+), 116 deletions(-) diff --git a/.gitignore b/.gitignore index 7b1ebb105..8abc91c7b 100644 --- a/.gitignore +++ b/.gitignore @@ -135,4 +135,6 @@ app.*.symbols !/dev/ci/**/Gemfile.lock !.vscode/settings.json -/lib/build_config.dart \ No newline at end of file +/lib/build_config.dart + +devtools_options.yaml diff --git a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart index 4c2646733..bbfb0a27c 100644 --- a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart +++ b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; @@ -295,11 +296,13 @@ class _InteractiveviewerGalleryState extends State final item = widget.sources[index]; return GestureDetector( behavior: HitTestBehavior.opaque, - onTap: onClose, + onTap: () => EasyThrottle.throttle( + 'preview', const Duration(milliseconds: 555), onClose), onDoubleTapDown: (TapDownDetails details) { _doubleTapLocalPosition = details.localPosition; }, - onDoubleTap: onDoubleTap, + onDoubleTap: () => EasyThrottle.throttle( + 'preview', const Duration(milliseconds: 555), onDoubleTap), onLongPress: item.sourceType == SourceType.fileImage ? null : () => onLongPress(item), @@ -500,14 +503,14 @@ class _InteractiveviewerGalleryState extends State builder: (context) { return AlertDialog( clipBehavior: Clip.hardEdge, - contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), + contentPadding: const EdgeInsets.symmetric(vertical: 12), content: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( onTap: () { - DownloadUtils.onShareImg(item.url); Get.back(); + DownloadUtils.onShareImg(item.url); }, dense: true, title: const Text('分享', style: TextStyle(fontSize: 14)), diff --git a/lib/pages/danmaku/controller.dart b/lib/pages/danmaku/controller.dart index 650c7bf20..a6d1e07cd 100644 --- a/lib/pages/danmaku/controller.dart +++ b/lib/pages/danmaku/controller.dart @@ -38,6 +38,9 @@ class PlDanmakuController { if (result.isSuccess) { final data = result.data; + if (data.state == 1) { + plPlayerController.dmState.add(cid); + } if (data.elems.isNotEmpty) { final Map counts = {}; if (mergeDanmaku) { diff --git a/lib/pages/danmaku_block/controller.dart b/lib/pages/danmaku_block/controller.dart index 7818fec8c..cab13b8a7 100644 --- a/lib/pages/danmaku_block/controller.dart +++ b/lib/pages/danmaku_block/controller.dart @@ -46,8 +46,9 @@ class DanmakuBlockController extends GetxController var result = await DanmakuFilterHttp.danmakuFilterDel(ids: id); SmartDialog.dismiss(); if (result['status']) { - ruleTypes[type]!.remove(id); - ruleTypes.refresh(); + ruleTypes + ..[type]!.remove(id) + ..refresh(); } SmartDialog.showToast(result['msg']); } @@ -60,8 +61,9 @@ class DanmakuBlockController extends GetxController SmartDialog.dismiss(); if (result['status']) { SimpleRule rule = result['data']; - ruleTypes[type]![rule.id] = rule.filter; - ruleTypes.refresh(); + ruleTypes + ..[type]![rule.id] = rule.filter + ..refresh(); SmartDialog.showToast('添加成功'); } else { SmartDialog.showToast(result['msg']); diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index 5d2446917..d26c5b1a7 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -108,8 +108,9 @@ class DynamicsController extends GetxController if (isQuerying) return; isQuerying = true; if (!isLogin.value) { - upData.value.errMsg = '账号未登录'; - upData.refresh(); + upData + ..value.errMsg = '账号未登录' + ..refresh(); } upData.value.errMsg = null; if (GStorage.setting @@ -125,11 +126,13 @@ class DynamicsController extends GetxController final res0 = await f1; if (!res0.isSuccess) { SmartDialog.showToast("获取关注动态失败:$res0"); - upData.value.errMsg = (res0 as Error).errMsg; - upData.refresh(); + upData + ..value.errMsg = (res0 as Error).errMsg + ..refresh(); } else { - upData.value.liveUsers = res0.data.liveUsers; - upData.refresh(); + upData + ..value.liveUsers = res0.data.liveUsers + ..refresh(); hasUpdatedUps = res0.data.upList!; } List allFollowedUps = []; @@ -151,8 +154,9 @@ class DynamicsController extends GetxController allFollowedUpsPage += 1; allFollowedUpsTotal = res1.data.total!; } - upData.value.upList = hasUpdatedUps + allFollowedUps; - upData.refresh(); + upData + ..value.upList = hasUpdatedUps + allFollowedUps + ..refresh(); } else { var res = await DynamicsHttp.followUp(); if (res.isSuccess) { @@ -161,8 +165,9 @@ class DynamicsController extends GetxController mid.value = -1; } } else { - upData.value.errMsg = (res as Error).errMsg; - upData.refresh(); + upData + ..value.errMsg = (res as Error).errMsg + ..refresh(); } } isQuerying = false; diff --git a/lib/pages/dynamics_create/view.dart b/lib/pages/dynamics_create/view.dart index 64bc08b7d..9603219aa 100644 --- a/lib/pages/dynamics_create/view.dart +++ b/lib/pages/dynamics_create/view.dart @@ -200,14 +200,14 @@ class _CreateDynPanelState extends CommonPublishPageState { ); } - Widget _buildImageList(ThemeData theme) => Obx( - () => SizedBox( - height: 100, - width: double.infinity, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( + Widget _buildImageList(ThemeData theme) => SizedBox( + height: 100, + width: double.infinity, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Obx( + () => Row( spacing: 10, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -504,13 +504,11 @@ class _CreateDynPanelState extends CommonPublishPageState { padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Obx( () => ToolbarIconButton( - onPressed: () { - updatePanelType( - panelType.value == PanelType.emoji - ? PanelType.keyboard - : PanelType.emoji, - ); - }, + onPressed: () => updatePanelType( + panelType.value == PanelType.emoji + ? PanelType.keyboard + : PanelType.emoji, + ), icon: const Icon(Icons.emoji_emotions, size: 22), tooltip: '表情', selected: panelType.value == PanelType.emoji, diff --git a/lib/pages/fav/pgc/controller.dart b/lib/pages/fav/pgc/controller.dart index 735e6b906..f32bb258e 100644 --- a/lib/pages/fav/pgc/controller.dart +++ b/lib/pages/fav/pgc/controller.dart @@ -80,9 +80,11 @@ class FavPgcController try { final ctr = Get.find(tag: '$type$followStatus'); if (ctr.loadingState.value.isSuccess) { - ctr.loadingState.value.data! - .insertAll(0, updateList.map((item) => item..checked = null)); - ctr.loadingState.refresh(); + ctr.loadingState + ..value + .data! + .insertAll(0, updateList.map((item) => item..checked = null)) + ..refresh(); ctr.allSelected.value = false; } } catch (e) { @@ -104,8 +106,9 @@ class FavPgcController try { final ctr = Get.find(tag: '$type$followStatus'); if (ctr.loadingState.value.isSuccess) { - ctr.loadingState.value.data!.insert(0, item); - ctr.loadingState.refresh(); + ctr.loadingState + ..value.data?.insert(0, item) + ..refresh(); ctr.allSelected.value = false; } } catch (e) { diff --git a/lib/pages/fav/video/view.dart b/lib/pages/fav/video/view.dart index 32204fc99..0ce96cbea 100644 --- a/lib/pages/fav/video/view.dart +++ b/lib/pages/fav/video/view.dart @@ -83,8 +83,9 @@ class _FavVideoPageState extends State }, ); if (res == true) { - _favController.loadingState.value.data!.removeAt(index); - _favController.loadingState.refresh(); + _favController.loadingState + ..value.data!.removeAt(index) + ..refresh(); } }, ); diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index 6842ac9c9..775472f40 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/widgets/scroll_physics.dart'; +import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/fav_type.dart'; import 'package:PiliPlus/models/user/fav_folder.dart'; import 'package:PiliPlus/pages/fav/article/controller.dart'; @@ -59,12 +60,16 @@ class _FavPageState extends State with SingleTickerProviderStateMixin { onPressed: () => Get.toNamed('/createFav')?.then( (data) { if (data != null) { - List list = + List? list = _favController.loadingState.value.isSuccess - ? _favController.loadingState.value.data! - : []; - list.insert(list.isNotEmpty ? 1 : 0, data); - _favController.loadingState.refresh(); + ? _favController.loadingState.value.data + : null; + if (list?.isNotEmpty == true) { + list!.insert(1, data); + _favController.loadingState.refresh(); + } else { + _favController.loadingState.value = Success([data]); + } } }, ), diff --git a/lib/pages/follow/child_controller.dart b/lib/pages/follow/child_controller.dart index 9939128e7..8454cf942 100644 --- a/lib/pages/follow/child_controller.dart +++ b/lib/pages/follow/child_controller.dart @@ -35,8 +35,9 @@ class FollowChildController tagid == null && isRefresh && controller!.followState.value.isSuccess) { - controller!.tabs[0].count = response.response.total; - controller!.tabs.refresh(); + controller!.tabs + ..[0].count = response.response.total + ..refresh(); } } catch (_) {} } diff --git a/lib/pages/follow/child_view.dart b/lib/pages/follow/child_view.dart index 6a661d094..9a60418b7 100644 --- a/lib/pages/follow/child_view.dart +++ b/lib/pages/follow/child_view.dart @@ -94,10 +94,9 @@ class _FollowChildPageState extends State isOwner: widget.controller?.isOwner, onSelect: widget.onSelect, callback: (attr) { - List list = - _followController.loadingState.value.data!; - list[index].attribute = attr == 0 ? -1 : 0; - _followController.loadingState.refresh(); + _followController.loadingState + ..value.data![index].attribute = attr == 0 ? -1 : 0 + ..refresh(); }, ); }, diff --git a/lib/pages/follow/controller.dart b/lib/pages/follow/controller.dart index 01d51b01d..fef60426b 100644 --- a/lib/pages/follow/controller.dart +++ b/lib/pages/follow/controller.dart @@ -73,8 +73,9 @@ class FollowController extends GetxController with GetTickerProviderStateMixin { Future onUpdateTag(int index, tagid, String tagName) async { final res = await MemberHttp.updateFollowTag(tagid, tagName); if (res['status']) { - tabs[index].name = tagName; - tabs.refresh(); + tabs + ..[index].name = tagName + ..refresh(); SmartDialog.showToast('修改成功'); } else { SmartDialog.showToast(res['msg']); diff --git a/lib/pages/later/controller.dart b/lib/pages/later/controller.dart index 47616ca5f..7864ef5e0 100644 --- a/lib/pages/later/controller.dart +++ b/lib/pages/later/controller.dart @@ -104,10 +104,11 @@ class LaterController extends MultiSelectController { Get.back(); var res = await UserHttp.toViewDel(aids: [aid]); if (res['status']) { - loadingState.value.data!.removeAt(index); baseCtr.counts[laterViewType] = baseCtr.counts[laterViewType]! - 1; - loadingState.refresh(); + loadingState + ..value.data!.removeAt(index) + ..refresh(); } SmartDialog.showToast(res['msg']); }, diff --git a/lib/pages/member_favorite/controller.dart b/lib/pages/member_favorite/controller.dart index 9e1b90634..c2f171089 100644 --- a/lib/pages/member_favorite/controller.dart +++ b/lib/pages/member_favorite/controller.dart @@ -71,8 +71,9 @@ class MemberFavoriteCtr extends CommonDataController { ?.map((item) => SpaceFavItemModel.fromJson(item)) .toList() ?? []; - first.value.mediaListResponse?.list?.addAll(list); - first.refresh(); + first + ..value.mediaListResponse?.list?.addAll(list) + ..refresh(); } else { firstEnd.value = true; } @@ -97,8 +98,9 @@ class MemberFavoriteCtr extends CommonDataController { ?.map((item) => SpaceFavItemModel.fromJson(item)) .toList() ?? []; - second.value.mediaListResponse?.list?.addAll(list); - second.refresh(); + second + ..value.mediaListResponse?.list?.addAll(list) + ..refresh(); } else { secondEnd.value = true; } diff --git a/lib/pages/member_favorite/view.dart b/lib/pages/member_favorite/view.dart index 9317dab9d..0ffe0cd55 100644 --- a/lib/pages/member_favorite/view.dart +++ b/lib/pages/member_favorite/view.dart @@ -122,9 +122,9 @@ class _MemberFavoriteState extends State item: item, callback: (res) { if (res == true) { - _controller.first.value.mediaListResponse?.list - ?.remove(item); - _controller.first.refresh(); + _controller + ..first.value.mediaListResponse?.list?.remove(item) + ..first.refresh(); } }, ), diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index e852b4fdb..239df63e5 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -105,17 +105,18 @@ class _RcmdPageState extends CommonPageState controller.lastRefreshAt = controller.lastRefreshAt! - 1; } - controller.loadingState.value.data! - .removeAt(actualIndex); - controller.loadingState.refresh(); + controller.loadingState + ..value.data!.removeAt(actualIndex) + ..refresh(); }, ); } else { return VideoCardV( videoItem: response[index], onRemove: () { - controller.loadingState.value.data!.removeAt(index); - controller.loadingState.refresh(); + controller.loadingState + ..value.data!.removeAt(index) + ..refresh(); }, ); } diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index c783652e8..0f9d041c3 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -938,6 +938,10 @@ class VideoDetailController extends GetxController /// 发送弹幕 Future showShootDanmakuSheet() async { + if (plPlayerController.dmState.contains(cid.value)) { + SmartDialog.showToast('UP主已关闭弹幕'); + return; + } bool isPlaying = plPlayerController.playerStatus.status.value == PlayerStatus.playing; if (isPlaying) { diff --git a/lib/pages/video/introduction/pgc/controller.dart b/lib/pages/video/introduction/pgc/controller.dart index 7145138ff..057961cec 100644 --- a/lib/pages/video/introduction/pgc/controller.dart +++ b/lib/pages/video/introduction/pgc/controller.dart @@ -352,12 +352,10 @@ class BangumiIntroController extends GetxController { // 选择文件夹 void onChoose(bool checkValue, int index) { feedBack(); - List datalist = favFolderData.value.list!; - datalist[index].favState = checkValue ? 1 : 0; - datalist[index].mediaCount = checkValue - ? datalist[index].mediaCount! + 1 - : datalist[index].mediaCount! - 1; - favFolderData.value.list = datalist; + FavFolderItemData item = favFolderData.value.list![index]; + item + ..favState = checkValue ? 1 : 0 + ..mediaCount = checkValue ? item.mediaCount! + 1 : item.mediaCount! - 1; favFolderData.refresh(); } diff --git a/lib/pages/video/introduction/ugc/controller.dart b/lib/pages/video/introduction/ugc/controller.dart index f85d9d9c7..be55aac7d 100644 --- a/lib/pages/video/introduction/ugc/controller.dart +++ b/lib/pages/video/introduction/ugc/controller.dart @@ -558,12 +558,10 @@ class VideoIntroController extends GetxController { // 选择文件夹 void onChoose(bool checkValue, int index) { feedBack(); - List datalist = favFolderData.value.list!; - datalist[index].favState = checkValue ? 1 : 0; - datalist[index].mediaCount = checkValue - ? datalist[index].mediaCount! + 1 - : datalist[index].mediaCount! - 1; - favFolderData.value.list = datalist; + FavFolderItemData item = favFolderData.value.list![index]; + item + ..favState = checkValue ? 1 : 0 + ..mediaCount = checkValue ? item.mediaCount! + 1 : item.mediaCount! - 1; favFolderData.refresh(); } diff --git a/lib/pages/video/member/view.dart b/lib/pages/video/member/view.dart index 35f6e75e2..fe54a858f 100644 --- a/lib/pages/video/member/view.dart +++ b/lib/pages/video/member/view.dart @@ -332,9 +332,9 @@ class _HorizontalMemberPageState extends State { mid: widget.mid, isFollow: memberInfoModel.isFollowed ?? false, callback: (attribute) { - _controller.userState.value.data.isFollowed = - attribute != 0; - _controller.userState.refresh(); + _controller + ..userState.value.data.isFollowed = attribute != 0 + ..userState.refresh(); }, ); } diff --git a/lib/pages/video/reply_reply/view.dart b/lib/pages/video/reply_reply/view.dart index 77ecf3b75..670ba4816 100644 --- a/lib/pages/video/reply_reply/view.dart +++ b/lib/pages/video/reply_reply/view.dart @@ -354,10 +354,10 @@ class _VideoReplyReplyPanelState if (res != null) { _savedReplies.remove(key); ReplyInfo replyInfo = RequestUtils.replyCast(res); - _videoReplyReplyController.loadingState.value.dataOrNull - ?.insert(index + 1, replyInfo); - _videoReplyReplyController.count.value += 1; - _videoReplyReplyController.loadingState.refresh(); + _videoReplyReplyController + ..count.value += 1 + ..loadingState.value.dataOrNull?.insert(index + 1, replyInfo) + ..loadingState.refresh(); if (_videoReplyReplyController.enableCommAntifraud && mounted) { _videoReplyReplyController.onCheckReply(context, replyInfo); } diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index 82792e5eb..75a269f3a 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -2179,25 +2179,17 @@ class _VideoDetailPageVState extends State if (isSeason) { // reverse season - videoIntroController.videoDetail.value.ugcSeason! - .sections![videoDetailController.seasonIndex.value].isReversed = - !videoIntroController.videoDetail.value.ugcSeason! - .sections![videoDetailController.seasonIndex.value].isReversed; - videoIntroController.videoDetail.value.ugcSeason! - .sections![videoDetailController.seasonIndex.value].episodes = - videoIntroController - .videoDetail - .value - .ugcSeason! - .sections![videoDetailController.seasonIndex.value] - .episodes! - .reversed - .toList(); + final item = videoIntroController.videoDetail.value.ugcSeason! + .sections![videoDetailController.seasonIndex.value]; + item + ..isReversed = !item.isReversed + ..episodes = item.episodes!.reversed.toList(); if (videoDetailController.plPlayerController.reverseFromFirst.not) { // keep current episode - videoDetailController.seasonIndex.refresh(); - videoDetailController.cid.refresh(); + videoDetailController + ..seasonIndex.refresh() + ..cid.refresh(); } else { // switch to first episode dynamic episode = videoIntroController.videoDetail.value.ugcSeason! @@ -2206,16 +2198,17 @@ class _VideoDetailPageVState extends State changeEpisode(episode); videoDetailController.seasonCid = episode.cid; } else { - videoDetailController.seasonIndex.refresh(); - videoDetailController.cid.refresh(); + videoDetailController + ..seasonIndex.refresh() + ..cid.refresh(); } } } else { // reverse part - videoIntroController.videoDetail.value.isPageReversed = - !videoIntroController.videoDetail.value.isPageReversed; - videoIntroController.videoDetail.value.pages = - videoIntroController.videoDetail.value.pages!.reversed.toList(); + final item = videoIntroController.videoDetail.value; + item + ..isPageReversed = !item.isPageReversed + ..pages = item.pages!.reversed.toList(); if (videoDetailController.plPlayerController.reverseFromFirst.not) { // keep current episode videoDetailController.cid.refresh(); diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index ca4df3edf..77a9aacae 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -1911,13 +1911,22 @@ class HeaderControlState extends State { builder: (context, constraints) { return Obx( () { - String title = videoIntroController - .videoDetail.value.pages - ?.firstWhereOrNull((e) => - e.cid == videoDetailCtr.cid.value) - ?.pagePart ?? - videoIntroController - .videoDetail.value.title!; + String title; + + if (videoIntroController + .videoDetail.value.videos == + 1) { + title = videoIntroController + .videoDetail.value.title!; + } else { + title = videoIntroController + .videoDetail.value.pages + ?.firstWhereOrNull((e) => + e.cid == videoDetailCtr.cid.value) + ?.pagePart ?? + videoIntroController + .videoDetail.value.title!; + } final textPainter = TextPainter( text: TextSpan( text: title, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 623c57d60..9428e2a50 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -249,6 +249,7 @@ class PlPlayerController { // 关联弹幕控制器 DanmakuController? danmakuController; bool showDanmaku = true; + Set dmState = {}; late final mergeDanmaku = GStorage.mergeDanmaku; // 弹幕相关配置 late Set blockTypes; @@ -1521,6 +1522,7 @@ class PlPlayerController { } return; } + dmState.clear(); _playerCount.value = 0; Utils.channel.setMethodCallHandler(null); pause();