mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-21 06:52:18 +02:00
refactor(share): share the widget capture helper
The lyrics card and the rewind slide both rendered a RepaintBoundary to a temp PNG. captureBoundaryToPngFile does that; pixel ratio, file name, frame waiting and share parameters stay with each caller.
This commit is contained in:
1 parent
da2fc2c9c9
commit
b10370e4fc
4 files changed
+45
-29
No files matched your search
@@ -1,17 +1,14 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui' show ImageByteFormat, ImageFilter;
|
||||
import 'dart:ui' show ImageFilter;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart' show RenderRepaintBoundary;
|
||||
import 'package:flutter/semantics.dart' show CustomSemanticsAction;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:material_3_expressive/material_3_expressive.dart'
|
||||
show M3EShapeKind;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:share_plus/share_plus.dart' show ShareParams, SharePlus, XFile;
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/providers/listening_rewind_provider.dart';
|
||||
@@ -19,6 +16,7 @@ import 'package:spotiflac_android/services/listening_rewind.dart';
|
||||
import 'package:spotiflac_android/theme/app_motion.dart';
|
||||
import 'package:spotiflac_android/theme/app_tokens.dart';
|
||||
import 'package:spotiflac_android/theme/mornye_theme.dart';
|
||||
import 'package:spotiflac_android/utils/widget_capture.dart';
|
||||
import 'package:spotiflac_android/widgets/app_action_button.dart';
|
||||
import 'package:spotiflac_android/widgets/app_bottom_sheet.dart';
|
||||
import 'package:spotiflac_android/widgets/app_content_card.dart';
|
||||
|
||||
@@ -137,17 +137,12 @@ class _RewindStoryState extends State<_RewindStory>
|
||||
final pixelRatio = MediaQuery.devicePixelRatioOf(context);
|
||||
setState(() => _sharing = true);
|
||||
try {
|
||||
final boundary =
|
||||
_captureKey.currentContext?.findRenderObject()
|
||||
as RenderRepaintBoundary?;
|
||||
if (boundary == null) return;
|
||||
final image = await boundary.toImage(pixelRatio: pixelRatio);
|
||||
final bytes = await image.toByteData(format: ImageByteFormat.png);
|
||||
image.dispose();
|
||||
if (bytes == null) return;
|
||||
final directory = await getTemporaryDirectory();
|
||||
final file = File('${directory.path}/spotiflac_rewind.png');
|
||||
await file.writeAsBytes(bytes.buffer.asUint8List(), flush: true);
|
||||
final file = await captureBoundaryToPngFile(
|
||||
_captureKey,
|
||||
pixelRatio: pixelRatio,
|
||||
fileName: 'spotiflac_rewind.png',
|
||||
);
|
||||
if (file == null) return;
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
files: [XFile(file.path, mimeType: 'image/png')],
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import 'dart:io';
|
||||
import 'dart:ui' show ImageByteFormat, ImageFilter;
|
||||
import 'dart:ui' show ImageFilter;
|
||||
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart' show RenderRepaintBoundary;
|
||||
import 'package:material_3_expressive/material_3_expressive.dart'
|
||||
show M3EShapeKind;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:share_plus/share_plus.dart' show ShareParams, SharePlus, XFile;
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/theme/app_tokens.dart';
|
||||
import 'package:spotiflac_android/theme/cover_palette.dart';
|
||||
import 'package:spotiflac_android/utils/lyrics_parser.dart';
|
||||
import 'package:spotiflac_android/utils/widget_capture.dart';
|
||||
import 'package:spotiflac_android/widgets/app_icon.dart';
|
||||
import 'package:spotiflac_android/widgets/app_icon_button.dart';
|
||||
import 'package:spotiflac_android/widgets/app_shape.dart';
|
||||
@@ -151,16 +149,12 @@ class _LyricsShareScreenState extends State<LyricsShareScreen> {
|
||||
// Share is tapped. Capture the current card after that frame finishes.
|
||||
await WidgetsBinding.instance.endOfFrame;
|
||||
if (!mounted) return;
|
||||
final boundary =
|
||||
_cardKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
|
||||
if (boundary == null) throw StateError('Card is not laid out');
|
||||
final image = await boundary.toImage(pixelRatio: 3);
|
||||
final bytes = await image.toByteData(format: ImageByteFormat.png);
|
||||
image.dispose();
|
||||
if (bytes == null) throw StateError('Card could not be encoded');
|
||||
final directory = await getTemporaryDirectory();
|
||||
final file = File('${directory.path}/spotiflac_lyrics.png');
|
||||
await file.writeAsBytes(bytes.buffer.asUint8List(), flush: true);
|
||||
final file = await captureBoundaryToPngFile(
|
||||
_cardKey,
|
||||
pixelRatio: 3,
|
||||
fileName: 'spotiflac_lyrics.png',
|
||||
);
|
||||
if (file == null) throw StateError('Card could not be captured');
|
||||
await SharePlus.instance.share(
|
||||
ShareParams(
|
||||
files: [XFile(file.path, mimeType: 'image/png')],
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'dart:io';
|
||||
import 'dart:ui' show ImageByteFormat;
|
||||
|
||||
import 'package:flutter/rendering.dart' show RenderRepaintBoundary;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
/// Renders the [RepaintBoundary] behind [boundaryKey] to a PNG named
|
||||
/// [fileName] in the temporary directory.
|
||||
///
|
||||
/// Returns null when the boundary is not laid out or the image cannot be
|
||||
/// encoded, so each caller decides how to report that.
|
||||
Future<File?> captureBoundaryToPngFile(
|
||||
GlobalKey boundaryKey, {
|
||||
required double pixelRatio,
|
||||
required String fileName,
|
||||
}) async {
|
||||
final boundary =
|
||||
boundaryKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
|
||||
if (boundary == null) return null;
|
||||
final image = await boundary.toImage(pixelRatio: pixelRatio);
|
||||
final bytes = await image.toByteData(format: ImageByteFormat.png);
|
||||
image.dispose();
|
||||
if (bytes == null) return null;
|
||||
final directory = await getTemporaryDirectory();
|
||||
final file = File('${directory.path}/$fileName');
|
||||
await file.writeAsBytes(bytes.buffer.asUint8List(), flush: true);
|
||||
return file;
|
||||
}
|
||||
Reference in new issue
Block a user