Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-05-21 11:48:42 +08:00
parent 1efd62803a
commit ac60ac417b
130 changed files with 1631 additions and 2132 deletions

View File

@@ -91,6 +91,31 @@ Widget imageView(
};
}
void onTap(BuildContext context, int index) {
if (callback != null) {
callback(picArr.map((item) => item.url).toList(), index);
} else {
onViewImage?.call();
context.imageView(
initialPage: index,
imgList: picArr.map(
(item) {
bool isLive = item.isLivePhoto && enableLivePhoto;
return SourceModel(
sourceType:
isLive ? SourceType.livePhoto : SourceType.networkImage,
url: item.url,
liveUrl: isLive ? item.liveUrl : null,
width: isLive ? parseSize(item.width) : null,
height: isLive ? parseSize(item.height) : null,
);
},
).toList(),
onDismissed: onDismissed,
);
}
}
return NineGridView(
type: NineGridType.weiBo,
margin: const EdgeInsets.only(top: 6),
@@ -103,30 +128,7 @@ Widget imageView(
itemBuilder: (context, index) => Hero(
tag: picArr[index].url,
child: GestureDetector(
onTap: () {
if (callback != null) {
callback(picArr.map((item) => item.url).toList(), index);
} else {
onViewImage?.call();
context.imageView(
initialPage: index,
imgList: picArr.map(
(item) {
bool isLive = item.isLivePhoto && enableLivePhoto;
return SourceModel(
sourceType:
isLive ? SourceType.livePhoto : SourceType.networkImage,
url: item.url,
liveUrl: isLive ? item.liveUrl : null,
width: isLive ? parseSize(item.width) : null,
height: isLive ? parseSize(item.height) : null,
);
},
).toList(),
onDismissed: onDismissed,
);
}
},
onTap: () => onTap(context, index),
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,

View File

@@ -110,8 +110,9 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
setStatusBar();
}
if (widget.sources[currentIndex.value].sourceType == SourceType.livePhoto) {
_onPlay(currentIndex.value);
var item = widget.sources[currentIndex.value];
if (item.sourceType == SourceType.livePhoto) {
_onPlay(item.liveUrl!);
}
}
@@ -148,9 +149,9 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
);
}
}
for (int index = 0; index < widget.sources.length; index++) {
if (widget.sources[index].sourceType == SourceType.networkImage) {
CachedNetworkImageProvider(_getActualUrl(index)).evict();
for (var item in widget.sources) {
if (item.sourceType == SourceType.networkImage) {
CachedNetworkImageProvider(_getActualUrl(item.url)).evict();
}
}
super.dispose();
@@ -209,10 +210,10 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
}
}
void _onPlay(int index) {
void _onPlay(String liveUrl) {
_player ??= Player();
_videoController ??= VideoController(_player!);
_player!.open(Media(widget.sources[index].liveUrl!));
_player!.open(Media(liveUrl));
}
/// When the page view changed its page, the source will animate back into the
@@ -222,8 +223,9 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
void _onPageChanged(int page) {
_player?.pause();
currentIndex.value = page;
if (widget.sources[page].sourceType == SourceType.livePhoto) {
_onPlay(page);
var item = widget.sources[page];
if (item.sourceType == SourceType.livePhoto) {
_onPlay(item.liveUrl!);
}
widget.onPageChanged?.call(page);
if (_transformationController!.value != Matrix4.identity()) {
@@ -240,10 +242,10 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
}
}
String _getActualUrl(int index) {
String _getActualUrl(String url) {
return _quality != 100
? Utils.thumbnailImgUrl(widget.sources[index].url, _quality)
: widget.sources[index].url.http2https;
? Utils.thumbnailImgUrl(url, _quality)
: url.http2https;
}
void onClose() {
@@ -287,6 +289,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
_enablePageView ? null : const NeverScrollableScrollPhysics(),
itemCount: widget.sources.length,
itemBuilder: (BuildContext context, int index) {
final item = widget.sources[index];
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onClose,
@@ -294,10 +297,9 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
_doubleTapLocalPosition = details.localPosition;
},
onDoubleTap: onDoubleTap,
onLongPress:
widget.sources[index].sourceType == SourceType.fileImage
? null
: onLongPress,
onLongPress: item.sourceType == SourceType.fileImage
? null
: () => onLongPress(item),
child: widget.itemBuilder != null
? widget.itemBuilder!(
context,
@@ -305,7 +307,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
index == currentIndex.value,
_enablePageView,
)
: _itemBuilder(index),
: _itemBuilder(index, item),
);
},
),
@@ -356,53 +358,40 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
alignment: Alignment.centerRight,
child: PopupMenuButton(
itemBuilder: (context) {
final item = widget.sources[currentIndex.value];
return [
PopupMenuItem(
onTap: () => DownloadUtils.onShareImg(
widget.sources[currentIndex.value].url),
onTap: () => DownloadUtils.onShareImg(item.url),
child: const Text("分享图片"),
),
PopupMenuItem(
onTap: () {
Utils.copyText(
widget.sources[currentIndex.value].url);
},
onTap: () => Utils.copyText(item.url),
child: const Text("复制链接"),
),
PopupMenuItem(
onTap: () {
DownloadUtils.downloadImg(
this.context,
[widget.sources[currentIndex.value].url],
);
},
onTap: () => DownloadUtils.downloadImg(
this.context,
[item.url],
),
child: const Text("保存图片"),
),
if (widget.sources.length > 1)
PopupMenuItem(
onTap: () {
DownloadUtils.downloadImg(
this.context,
widget.sources
.map((item) => item.url)
.toList(),
);
},
onTap: () => DownloadUtils.downloadImg(
this.context,
widget.sources.map((item) => item.url).toList(),
),
child: const Text("保存全部"),
),
if (widget.sources[currentIndex.value].sourceType ==
SourceType.livePhoto)
if (item.sourceType == SourceType.livePhoto)
PopupMenuItem(
onTap: () {
DownloadUtils.downloadLivePhoto(
context: this.context,
url: widget.sources[currentIndex.value].url,
liveUrl: widget
.sources[currentIndex.value].liveUrl!,
width:
widget.sources[currentIndex.value].width!,
height: widget
.sources[currentIndex.value].height!,
url: item.url,
liveUrl: item.liveUrl!,
width: item.width!,
height: item.height!,
);
},
child: const Text("保存 Live Photo"),
@@ -420,25 +409,25 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
);
}
Widget _itemBuilder(index) {
Widget _itemBuilder(int index, SourceModel item) {
return Center(
child: Hero(
tag: widget.sources[index].url,
child: switch (widget.sources[index].sourceType) {
tag: item.url,
child: switch (item.sourceType) {
SourceType.fileImage => Image(
filterQuality: FilterQuality.low,
image: FileImage(File(widget.sources[index].url)),
image: FileImage(File(item.url)),
),
SourceType.networkImage => CachedNetworkImage(
fadeInDuration: Duration.zero,
fadeOutDuration: Duration.zero,
imageUrl: _getActualUrl(index),
imageUrl: _getActualUrl(item.url),
placeholderFadeInDuration: Duration.zero,
placeholder: (context, url) {
return CachedNetworkImage(
fadeInDuration: Duration.zero,
fadeOutDuration: Duration.zero,
imageUrl: Utils.thumbnailImgUrl(widget.sources[index].url),
imageUrl: Utils.thumbnailImgUrl(item.url),
);
},
),
@@ -502,7 +491,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
.whenComplete(() => _onScaleChanged(targetScale));
}
void onLongPress() {
void onLongPress(SourceModel item) {
showDialog(
context: context,
builder: (context) {
@@ -514,8 +503,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
children: [
ListTile(
onTap: () {
DownloadUtils.onShareImg(
widget.sources[currentIndex.value].url);
DownloadUtils.onShareImg(item.url);
Get.back();
},
dense: true,
@@ -524,7 +512,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
ListTile(
onTap: () {
Get.back();
Utils.copyText(widget.sources[currentIndex.value].url);
Utils.copyText(item.url);
},
dense: true,
title: const Text('复制链接', style: TextStyle(fontSize: 14)),
@@ -534,7 +522,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
Get.back();
DownloadUtils.downloadImg(
this.context,
[widget.sources[currentIndex.value].url],
[item.url],
);
},
dense: true,
@@ -552,17 +540,16 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
dense: true,
title: const Text('保存全部图片', style: TextStyle(fontSize: 14)),
),
if (widget.sources[currentIndex.value].sourceType ==
SourceType.livePhoto)
if (item.sourceType == SourceType.livePhoto)
ListTile(
onTap: () {
Get.back();
DownloadUtils.downloadLivePhoto(
context: this.context,
url: widget.sources[currentIndex.value].url,
liveUrl: widget.sources[currentIndex.value].liveUrl!,
width: widget.sources[currentIndex.value].width!,
height: widget.sources[currentIndex.value].height!,
url: item.url,
liveUrl: item.liveUrl!,
width: item.width!,
height: item.height!,
);
},
dense: true,

View File

@@ -70,9 +70,7 @@ class PendantAvatar extends StatelessWidget {
Positioned(
bottom: 0,
child: InkWell(
onTap: () {
Get.toNamed('/liveRoom?roomid=$roomId');
},
onTap: () => Get.toNamed('/liveRoom?roomid=$roomId'),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 1),
decoration: BoxDecoration(

View File

@@ -593,7 +593,7 @@ class RefreshIndicatorState extends State<RefreshIndicator>
_positionController
.animateTo(1.0 / _kDragSizeFactorLimit,
duration: _kIndicatorSnapDuration)
.then<void>((void value) {
.whenComplete(() {
if (mounted && _status == RefreshIndicatorStatus.snap) {
setState(() {
// Show the indeterminate progress indicator.

View File

@@ -40,9 +40,7 @@ class VideoCustomActions {
Icon(MdiIcons.circleOutline, size: 16),
],
),
() {
Utils.copyText(videoItem.bvid!);
},
() => Utils.copyText(videoItem.bvid!),
),
VideoCustomAction(
'稍后再看',
@@ -59,11 +57,9 @@ class VideoCustomActions {
'访问:${videoItem.owner.name}',
'visit',
const Icon(MdiIcons.accountCircleOutline, size: 16),
() {
Get.toNamed('/member?mid=${videoItem.owner.mid}', arguments: {
'heroTag': '${videoItem.owner.mid}',
});
},
() => Get.toNamed('/member?mid=${videoItem.owner.mid}', arguments: {
'heroTag': '${videoItem.owner.mid}',
}),
),
if (videoItem is! SpaceArchiveItem)
VideoCustomAction(
@@ -234,42 +230,40 @@ class VideoCustomActions {
'拉黑:${videoItem.owner.name}',
'block',
const Icon(MdiIcons.cancel, size: 16),
() {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('提示'),
content: Text(
'确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
'\n\n被拉黑的Up可以在隐私设置-黑名单管理中解除'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text(
'点错了',
style: TextStyle(
color: Theme.of(context).colorScheme.outline),
),
() => showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('提示'),
content:
Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
'\n\n被拉黑的Up可以在隐私设置-黑名单管理中解除'),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'点错了',
style: TextStyle(
color: Theme.of(context).colorScheme.outline),
),
TextButton(
onPressed: () async {
var res = await VideoHttp.relationMod(
mid: videoItem.owner.mid!,
act: 5,
reSrc: 11,
);
GStorage.setBlackMid(videoItem.owner.mid!);
Get.back();
SmartDialog.showToast(res['msg'] ?? '成功');
},
child: const Text('确认'),
)
],
);
},
);
},
),
TextButton(
onPressed: () async {
var res = await VideoHttp.relationMod(
mid: videoItem.owner.mid!,
act: 5,
reSrc: 11,
);
GStorage.setBlackMid(videoItem.owner.mid!);
Get.back();
SmartDialog.showToast(res['msg'] ?? '成功');
},
child: const Text('确认'),
)
],
);
},
),
),
VideoCustomAction(
"${MineController.anonymity.value ? '退出' : '进入'}无痕模式",