save method
Saves state and returns the project id (a new one when id is null).
Implementation
Future<String> save({
String? id,
required String title,
required ProjectState state,
}) async {
final projectId = id ?? 'project_${DateTime.now().microsecondsSinceEpoch}';
final root = await _root();
final dir = Directory('${root.path}/$projectId');
final media = Directory('${dir.path}/media');
await media.create(recursive: true);
final temp = await _tempPath();
final copied = <String, String>{};
Future<File> keep(File file) async {
final path = file.path;
if (temp == null || !path.startsWith(temp) || !await file.exists()) {
return file;
}
final known = copied[path];
if (known != null) return File(known);
final target = File('${media.path}/${fileBaseName(path)}');
if (!await target.exists() ||
await target.length() != await file.length()) {
await file.copy(target.path);
}
copied[path] = target.path;
return target;
}
final clips = <VideoEditorClip>[];
for (final clip in state.clips) {
final thumbs = <File>[];
for (final thumb in clip.thumbnails) {
thumbs.add(await keep(thumb));
}
clips.add(clip.copyWith(file: await keep(clip.file), thumbnails: thumbs));
}
final tracks = <VideoEditorAudioTrack>[];
for (final track in state.audioTracks) {
tracks.add(track.copyWith(file: await keep(track.file)));
}
final saved = ProjectState(
clips: clips,
audioTracks: tracks,
textOverlays: state.textOverlays,
effects: state.effects,
aspectRatio: state.aspectRatio,
);
final duration = clips.fold<Duration>(
Duration.zero,
(sum, c) => sum + c.effectiveDuration,
);
String? thumbnail;
if (clips.isNotEmpty) {
final first = clips.first;
thumbnail = first.isImage
? first.file.path
: (first.thumbnails.isEmpty ? null : first.thumbnails.first.path);
}
final document = {
'version': 1,
'id': projectId,
'title': title,
'modified': DateTime.now().toIso8601String(),
'durationMs': duration.inMilliseconds,
'thumbnail': thumbnail,
'aspect': state.aspectRatio.label,
'state': saved.toJson(),
};
final file = File('${dir.path}/project.json');
final tmp = File('${dir.path}/project.json.tmp');
await tmp.writeAsString(jsonEncode(document), flush: true);
await tmp.rename(file.path);
return projectId;
}