diff --git a/CHANGELOG.md b/CHANGELOG.md index e696fd35..26a33b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 12.0.5 +- **FEAT**(editor-audio): Add `safeFilePath` method to `EditorAudio` that returns a file path for the audio source. For file sources, it returns the path directly. For memory, asset, and network sources, it writes the data to a temporary file. File extension is automatically extracted from asset paths and network URLs. + ## 12.0.4 - **FIX**(wasm): Resolve WASM incompatibility caused by unconditional `dart:isolate` import. The `IsolateManager` is now loaded via a conditional import, so web/WASM builds use a stub that falls back to single-threaded processing. diff --git a/lib/core/models/editor_audio.dart b/lib/core/models/editor_audio.dart index a2d009cd..f91b0964 100644 --- a/lib/core/models/editor_audio.dart +++ b/lib/core/models/editor_audio.dart @@ -1,7 +1,8 @@ import 'dart:typed_data'; +import '/core/platform/io/io_helper.dart'; +import '/shared/utils/converters.dart'; import '/shared/utils/file_constructor_utils.dart'; -import '../platform/io/io_helper.dart'; /// Represents an audio source used in the editor. /// @@ -66,4 +67,88 @@ class EditorAudio { /// Indicates whether the `assetPath` property is not null. bool get hasAssetPath => assetPath != null; + + /// Returns the type of the audio source, determined by the available + /// properties. + EditorAudioType get type { + if (hasFile) { + return EditorAudioType.file; + } else if (hasBytes) { + return EditorAudioType.memory; + } else if (hasNetworkUrl) { + return EditorAudioType.network; + } else { + return EditorAudioType.asset; + } + } + + /// A future that retrieves a file path for the audio. + /// + /// If the audio is already a file, returns its path directly. + /// Otherwise, writes the audio data to a temporary file and returns + /// that path. + /// + /// The [fileExtension] parameter specifies the file extension for the + /// temporary file (e.g., '.mp3', '.wav'). If not provided, it will be + /// extracted from the asset path or network URL. Defaults to '.mp3' if + /// extraction fails. + Future safeFilePath({String? fileExtension}) async { + switch (type) { + case EditorAudioType.file: + return file!.path; + case EditorAudioType.memory: + return _writeBytesToTempFile(bytes!, fileExtension ?? '.mp3'); + case EditorAudioType.asset: + final ext = fileExtension ?? _extractExtension(assetPath!) ?? '.mp3'; + final assetBytes = await loadAssetImageAsUint8List(assetPath!); + bytes = assetBytes; + return _writeBytesToTempFile(assetBytes, ext); + case EditorAudioType.network: + final ext = fileExtension ?? _extractExtension(networkUrl!) ?? '.mp3'; + final networkBytes = await fetchImageAsUint8List(networkUrl!); + bytes = networkBytes; + return _writeBytesToTempFile(networkBytes, ext); + } + } + + /// Extracts the file extension from a path or URL. + /// Returns null if no extension could be extracted. + String? _extractExtension(String path) { + final uri = Uri.tryParse(path); + final pathSegment = uri?.pathSegments.lastOrNull ?? path; + final lastDot = pathSegment.lastIndexOf('.'); + if (lastDot != -1 && lastDot < pathSegment.length - 1) { + return pathSegment.substring(lastDot); + } + return null; + } + + Future _writeBytesToTempFile( + Uint8List data, + String fileExtension, + ) async { + final tempDir = Directory.systemTemp; + final timestamp = DateTime.now().millisecondsSinceEpoch; + final tempFile = File( + '${tempDir.path}/editor_audio_$timestamp$fileExtension', + ); + await tempFile.writeAsBytes(data); + return tempFile.path; + } +} + +/// The `EditorAudioType` enum represents different types of audio sources +/// that can be used with the `EditorAudio` class. +enum EditorAudioType { + /// Represents audio loaded from a file. + file, + + /// Represents audio loaded from a network URL. + network, + + /// Represents audio loaded from memory (byte array). + memory, + + /// Represents audio loaded from an asset path. + asset, } diff --git a/lib/core/platform/io/io_web.dart b/lib/core/platform/io/io_web.dart index abb9b655..b27e3ca8 100644 --- a/lib/core/platform/io/io_web.dart +++ b/lib/core/platform/io/io_web.dart @@ -60,6 +60,11 @@ class File { throw ArgumentError('This function is not supported on the web.'); } + /// Write bytes to the file + Future writeAsBytes(List bytes) async { + throw ArgumentError('This function is not supported on the web.'); + } + /// Read bytes async Future readAsBytes() async { throw ArgumentError('This function is not supported on the web.'); diff --git a/pubspec.yaml b/pubspec.yaml index e04df520..249cad9d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: pro_image_editor description: "A Flutter image editor: Seamlessly enhance your images with user-friendly editing features." -version: 12.0.4 +version: 12.0.5 homepage: https://github.com/hm21/pro_image_editor/ repository: https://github.com/hm21/pro_image_editor/ documentation: https://github.com/hm21/pro_image_editor/ @@ -60,6 +60,12 @@ flutter: android: package: ch.waio.pro_image_editor pluginClass: ProImageEditorPlugin + ios: + pluginClass: ProImageEditorPlugin + sharedDarwinSource: true + macos: + pluginClass: ProImageEditorPlugin + sharedDarwinSource: true assets: - path: lib/web/web_worker.dart.js platforms: [web]