Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
87 changes: 86 additions & 1 deletion lib/core/models/editor_audio.dart
Original file line number Diff line number Diff line change
@@ -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.
///
Expand Down Expand Up @@ -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<String> 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<String> _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,
}
5 changes: 5 additions & 0 deletions lib/core/platform/io/io_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ class File {
throw ArgumentError('This function is not supported on the web.');
}

/// Write bytes to the file
Future<File> writeAsBytes(List<int> bytes) async {
throw ArgumentError('This function is not supported on the web.');
}

/// Read bytes async
Future<Uint8List> readAsBytes() async {
throw ArgumentError('This function is not supported on the web.');
Expand Down
8 changes: 7 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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/
Expand Down Expand Up @@ -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]
Expand Down