mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: share/save video cover
Closes #563 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -72,6 +72,17 @@ void imageSaveDialog({
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
|
IconButton(
|
||||||
|
tooltip: '分享',
|
||||||
|
onPressed: () {
|
||||||
|
DownloadUtils.onShareImg(cover ?? '');
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.share,
|
||||||
|
size: 20,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: '保存封面图',
|
tooltip: '保存封面图',
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -89,7 +100,7 @@ void imageSaveDialog({
|
|||||||
size: 20,
|
size: 20,
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:PiliPlus/http/init.dart';
|
|
||||||
import 'package:PiliPlus/utils/download.dart';
|
import 'package:PiliPlus/utils/download.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
import 'package:media_kit_video/media_kit_video.dart';
|
import 'package:media_kit_video/media_kit_video.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:share_plus/share_plus.dart';
|
|
||||||
import 'interactive_viewer_boundary.dart';
|
import 'interactive_viewer_boundary.dart';
|
||||||
import 'interactive_viewer.dart' as custom;
|
import 'interactive_viewer.dart' as custom;
|
||||||
|
|
||||||
@@ -380,7 +375,7 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
|||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
return [
|
return [
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () => onShareImg(
|
onTap: () => DownloadUtils.onShareImg(
|
||||||
widget.sources[currentIndex.value].url),
|
widget.sources[currentIndex.value].url),
|
||||||
child: const Text("分享图片"),
|
child: const Text("分享图片"),
|
||||||
),
|
),
|
||||||
@@ -442,34 +437,6 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图片分享
|
|
||||||
void onShareImg(String imgUrl) async {
|
|
||||||
try {
|
|
||||||
SmartDialog.showLoading();
|
|
||||||
var response = await Request()
|
|
||||||
.get(imgUrl, options: Options(responseType: ResponseType.bytes));
|
|
||||||
final temp = await getTemporaryDirectory();
|
|
||||||
SmartDialog.dismiss();
|
|
||||||
String imgName =
|
|
||||||
"plpl_pic_${DateTime.now().toString().split('-').join()}.jpg";
|
|
||||||
var path = '${temp.path}/$imgName';
|
|
||||||
File(path).writeAsBytesSync(response.data);
|
|
||||||
|
|
||||||
Rect? sharePositionOrigin;
|
|
||||||
if (Platform.isIOS && (await Utils.isIpad())) {
|
|
||||||
sharePositionOrigin = Rect.fromLTWH(0, 0, Get.width, Get.height / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Share.shareXFiles(
|
|
||||||
[XFile(path)],
|
|
||||||
subject: imgUrl,
|
|
||||||
sharePositionOrigin: sharePositionOrigin,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
SmartDialog.showToast(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _itemBuilder(index) {
|
Widget _itemBuilder(index) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Hero(
|
child: Hero(
|
||||||
@@ -573,7 +540,8 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
onShareImg(widget.sources[currentIndex.value].url);
|
DownloadUtils.onShareImg(
|
||||||
|
widget.sources[currentIndex.value].url);
|
||||||
Get.back();
|
Get.back();
|
||||||
},
|
},
|
||||||
dense: true,
|
dense: true,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import 'package:PiliPlus/pages/video/detail/member/horizontal_member_page.dart';
|
|||||||
import 'package:PiliPlus/pages/video/detail/reply_reply/view.dart';
|
import 'package:PiliPlus/pages/video/detail/reply_reply/view.dart';
|
||||||
import 'package:PiliPlus/pages/video/detail/view_point/view_points_page.dart';
|
import 'package:PiliPlus/pages/video/detail/view_point/view_points_page.dart';
|
||||||
import 'package:PiliPlus/pages/video/detail/widgets/ai_detail.dart';
|
import 'package:PiliPlus/pages/video/detail/widgets/ai_detail.dart';
|
||||||
|
import 'package:PiliPlus/utils/download.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/global_data.dart';
|
import 'package:PiliPlus/utils/global_data.dart';
|
||||||
import 'package:PiliPlus/utils/id_utils.dart';
|
import 'package:PiliPlus/utils/id_utils.dart';
|
||||||
@@ -1047,6 +1048,12 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
case 'note':
|
case 'note':
|
||||||
videoDetailController.showNoteList(context);
|
videoDetailController.showNoteList(context);
|
||||||
break;
|
break;
|
||||||
|
case 'savePic':
|
||||||
|
DownloadUtils.downloadImg(
|
||||||
|
context,
|
||||||
|
[videoDetailController.videoItem['pic']],
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
itemBuilder: (BuildContext context) =>
|
itemBuilder: (BuildContext context) =>
|
||||||
@@ -1060,6 +1067,11 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
value: 'note',
|
value: 'note',
|
||||||
child: Text('查看笔记'),
|
child: Text('查看笔记'),
|
||||||
),
|
),
|
||||||
|
if (videoDetailController.videoItem['pic'] != null)
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'savePic',
|
||||||
|
child: Text('保存封面'),
|
||||||
|
),
|
||||||
const PopupMenuItem<String>(
|
const PopupMenuItem<String>(
|
||||||
value: 'report',
|
value: 'report',
|
||||||
child: Text('举报'),
|
child: Text('举报'),
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import 'package:PiliPlus/pages/video/detail/member/horizontal_member_page.dart';
|
|||||||
import 'package:PiliPlus/pages/video/detail/reply_reply/view.dart';
|
import 'package:PiliPlus/pages/video/detail/reply_reply/view.dart';
|
||||||
import 'package:PiliPlus/pages/video/detail/view_point/view_points_page.dart';
|
import 'package:PiliPlus/pages/video/detail/view_point/view_points_page.dart';
|
||||||
import 'package:PiliPlus/pages/video/detail/widgets/ai_detail.dart';
|
import 'package:PiliPlus/pages/video/detail/widgets/ai_detail.dart';
|
||||||
|
import 'package:PiliPlus/utils/download.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/global_data.dart';
|
import 'package:PiliPlus/utils/global_data.dart';
|
||||||
import 'package:PiliPlus/utils/id_utils.dart';
|
import 'package:PiliPlus/utils/id_utils.dart';
|
||||||
@@ -889,6 +890,17 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
.showNoteList(
|
.showNoteList(
|
||||||
context);
|
context);
|
||||||
break;
|
break;
|
||||||
|
case 'savePic':
|
||||||
|
DownloadUtils
|
||||||
|
.downloadImg(
|
||||||
|
context,
|
||||||
|
[
|
||||||
|
videoDetailController
|
||||||
|
.videoItem[
|
||||||
|
'pic']
|
||||||
|
],
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
itemBuilder: (BuildContext
|
itemBuilder: (BuildContext
|
||||||
@@ -906,6 +918,14 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
value: 'note',
|
value: 'note',
|
||||||
child: Text('查看笔记'),
|
child: Text('查看笔记'),
|
||||||
),
|
),
|
||||||
|
if (videoDetailController
|
||||||
|
.videoItem['pic'] !=
|
||||||
|
null)
|
||||||
|
const PopupMenuItem<
|
||||||
|
String>(
|
||||||
|
value: 'savePic',
|
||||||
|
child: Text('保存封面'),
|
||||||
|
),
|
||||||
const PopupMenuItem<String>(
|
const PopupMenuItem<String>(
|
||||||
value: 'report',
|
value: 'report',
|
||||||
child: Text('举报'),
|
child: Text('举报'),
|
||||||
@@ -1456,6 +1476,12 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
case 'note':
|
case 'note':
|
||||||
videoDetailController.showNoteList(context);
|
videoDetailController.showNoteList(context);
|
||||||
break;
|
break;
|
||||||
|
case 'savePic':
|
||||||
|
DownloadUtils.downloadImg(
|
||||||
|
context,
|
||||||
|
[videoDetailController.videoItem['pic']],
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
itemBuilder: (BuildContext context) =>
|
itemBuilder: (BuildContext context) =>
|
||||||
@@ -1469,6 +1495,11 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
value: 'note',
|
value: 'note',
|
||||||
child: Text('查看笔记'),
|
child: Text('查看笔记'),
|
||||||
),
|
),
|
||||||
|
if (videoDetailController.videoItem['pic'] != null)
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'savePic',
|
||||||
|
child: Text('保存封面'),
|
||||||
|
),
|
||||||
const PopupMenuItem<String>(
|
const PopupMenuItem<String>(
|
||||||
value: 'report',
|
value: 'report',
|
||||||
child: Text('举报'),
|
child: Text('举报'),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
|||||||
import 'package:PiliPlus/pages/bangumi/introduction/controller.dart';
|
import 'package:PiliPlus/pages/bangumi/introduction/controller.dart';
|
||||||
import 'package:PiliPlus/pages/setting/widgets/switch_item.dart';
|
import 'package:PiliPlus/pages/setting/widgets/switch_item.dart';
|
||||||
import 'package:PiliPlus/pages/video/detail/introduction/widgets/action_item.dart';
|
import 'package:PiliPlus/pages/video/detail/introduction/widgets/action_item.dart';
|
||||||
|
import 'package:PiliPlus/utils/download.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/id_utils.dart';
|
import 'package:PiliPlus/utils/id_utils.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
@@ -163,6 +164,19 @@ class HeaderControlState extends State<HeaderControl> {
|
|||||||
leading: const Icon(Icons.note_alt_outlined, size: 20),
|
leading: const Icon(Icons.note_alt_outlined, size: 20),
|
||||||
title: const Text('查看笔记', style: titleStyle),
|
title: const Text('查看笔记', style: titleStyle),
|
||||||
),
|
),
|
||||||
|
if (widget.videoDetailCtr.videoItem['pic'] != null)
|
||||||
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
onTap: () {
|
||||||
|
Get.back();
|
||||||
|
DownloadUtils.downloadImg(
|
||||||
|
context,
|
||||||
|
[widget.videoDetailCtr.videoItem['pic']],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
leading: const Icon(Icons.image_outlined, size: 20),
|
||||||
|
title: const Text('保存封面', style: titleStyle),
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: true,
|
dense: true,
|
||||||
onTap: () => {Get.back(), scheduleExit()},
|
onTap: () => {Get.back(), scheduleExit()},
|
||||||
@@ -1118,13 +1132,19 @@ class HeaderControlState extends State<HeaderControl> {
|
|||||||
SmartDialog.showToast('已保存');
|
SmartDialog.showToast('已保存');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Share.shareXFiles([
|
Share.shareXFiles(
|
||||||
XFile.fromData(
|
[
|
||||||
res.data,
|
XFile.fromData(
|
||||||
name: name,
|
res.data,
|
||||||
mimeType: 'application/json',
|
name: name,
|
||||||
)
|
mimeType: 'application/json',
|
||||||
]);
|
),
|
||||||
|
],
|
||||||
|
sharePositionOrigin: await Utils.isIpad()
|
||||||
|
? Rect.fromLTWH(
|
||||||
|
0, 0, Get.width, Get.height / 2)
|
||||||
|
: null,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -7,13 +7,44 @@ import 'package:device_info_plus/device_info_plus.dart';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
import 'package:live_photo_maker/live_photo_maker.dart';
|
import 'package:live_photo_maker/live_photo_maker.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:saver_gallery/saver_gallery.dart';
|
import 'package:saver_gallery/saver_gallery.dart';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
||||||
class DownloadUtils {
|
class DownloadUtils {
|
||||||
|
// 图片分享
|
||||||
|
static void onShareImg(String imgUrl) async {
|
||||||
|
try {
|
||||||
|
SmartDialog.showLoading();
|
||||||
|
var response = await Request()
|
||||||
|
.get(imgUrl, options: Options(responseType: ResponseType.bytes));
|
||||||
|
final temp = await getTemporaryDirectory();
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
String imgName =
|
||||||
|
"plpl_pic_${DateTime.now().toString().split('-').join()}.jpg";
|
||||||
|
var path = '${temp.path}/$imgName';
|
||||||
|
File(path).writeAsBytesSync(response.data);
|
||||||
|
|
||||||
|
Rect? sharePositionOrigin;
|
||||||
|
if (Platform.isIOS && (await Utils.isIpad())) {
|
||||||
|
sharePositionOrigin = Rect.fromLTWH(0, 0, Get.width, Get.height / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Share.shareXFiles(
|
||||||
|
[XFile(path)],
|
||||||
|
subject: imgUrl,
|
||||||
|
sharePositionOrigin: sharePositionOrigin,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
SmartDialog.showToast(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取存储权限
|
// 获取存储权限
|
||||||
static Future<bool> requestStoragePer(BuildContext context) async {
|
static Future<bool> requestStoragePer(BuildContext context) async {
|
||||||
await Permission.storage.request();
|
await Permission.storage.request();
|
||||||
|
|||||||
Reference in New Issue
Block a user