86 lines
2.4 KiB
Dart
86 lines
2.4 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:gal/gal.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
/// 与 [GenerateResultScreen] 保存相册逻辑一致,供 History 卡片 Download 使用。
|
|
Future<void> saveHistoryMediaToGallery({
|
|
required BuildContext context,
|
|
required String taskId,
|
|
required String resultUrl,
|
|
}) async {
|
|
final u = resultUrl.trim();
|
|
if (!u.startsWith('http://') && !u.startsWith('https://')) {
|
|
if (context.mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(
|
|
'Invalid media URL',
|
|
style: GoogleFonts.inter(fontWeight: FontWeight.w600),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
try {
|
|
final ok = await Gal.hasAccess();
|
|
if (!ok) {
|
|
await Gal.requestAccess();
|
|
}
|
|
final uri = Uri.parse(u);
|
|
final res = await http.get(uri);
|
|
if (res.statusCode < 200 || res.statusCode >= 300) {
|
|
throw HttpException('HTTP ${res.statusCode}');
|
|
}
|
|
final isVideo = historyUrlLooksLikeVideo(u);
|
|
final ext = isVideo ? historyGuessVideoExt(u) : '.jpg';
|
|
final file = File(
|
|
'${Directory.systemTemp.path}/funymee_hist_${taskId}_$ext',
|
|
);
|
|
await file.writeAsBytes(res.bodyBytes);
|
|
if (isVideo) {
|
|
await Gal.putVideo(file.path);
|
|
} else {
|
|
await Gal.putImage(file.path);
|
|
}
|
|
if (!context.mounted) return;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(
|
|
'Saved to Photos',
|
|
style: GoogleFonts.inter(fontWeight: FontWeight.w600),
|
|
),
|
|
),
|
|
);
|
|
} on GalException catch (e) {
|
|
if (!context.mounted) return;
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(SnackBar(content: Text(e.type.message)));
|
|
} catch (e) {
|
|
if (!context.mounted) return;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Save failed: $e')),
|
|
);
|
|
}
|
|
}
|
|
|
|
bool historyUrlLooksLikeVideo(String url) {
|
|
if (url.isEmpty) return false;
|
|
final lower = url.toLowerCase();
|
|
const hints = ['.mp4', '.m3u8', '.webm', '.mov', '.mkv', '.avi'];
|
|
return hints.any((h) => lower.contains(h));
|
|
}
|
|
|
|
String historyGuessVideoExt(String url) {
|
|
final lower = url.toLowerCase();
|
|
if (lower.contains('.webm')) return '.webm';
|
|
if (lower.contains('.mov')) return '.mov';
|
|
if (lower.contains('.m3u8')) return '.mp4';
|
|
return '.mp4';
|
|
}
|