Skip to content

Commit 4cb6932

Browse files
committed
[*] refactor: video-editor
1 parent 78a7175 commit 4cb6932

File tree

11 files changed

+240
-413
lines changed

11 files changed

+240
-413
lines changed

lib/video-editor/src/project/project.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,16 @@ pub struct ManagerData {
414414
pub inner: Option<Manager>,
415415
}
416416

417+
impl ManagerData {
418+
pub fn new(manager: Manager) -> Self {
419+
Self {
420+
version: CURRENT_PROJECT_VERSION,
421+
created_at: chrono::Utc::now(),
422+
inner: Some(manager),
423+
}
424+
}
425+
}
426+
417427
impl TryFrom<&ProjectFile> for ManagerData {
418428
type Error = crate::Error;
419429

lib/video-editor/src/project/recent.rs

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use crate::Result;
22
use serde::{Deserialize, Serialize};
33
use std::{
4-
collections::VecDeque,
54
fs,
6-
io::{BufReader, BufWriter},
75
path::PathBuf,
86
time::{Duration, SystemTime},
97
};
@@ -56,64 +54,42 @@ impl RecentFile {
5654
}
5755
}
5856

59-
#[derive(Debug)]
57+
#[derive(Debug, Clone, Serialize, Deserialize)]
6058
pub struct RecentFilesManager {
61-
recent_files: VecDeque<RecentFile>,
59+
recent_files: Vec<RecentFile>,
6260
max_files: usize,
63-
config_path: PathBuf,
6461
}
6562

6663
impl RecentFilesManager {
67-
pub fn new(config_path: PathBuf, max_files: usize) -> Self {
64+
pub fn new(max_files: usize) -> Self {
6865
Self {
69-
recent_files: VecDeque::new(),
66+
recent_files: Vec::new(),
7067
max_files,
71-
config_path,
7268
}
7369
}
7470

75-
pub fn load(&mut self) -> Result<()> {
76-
if !self.config_path.exists() {
77-
return Ok(());
78-
}
79-
80-
let file = fs::File::open(&self.config_path)?;
81-
let reader = BufReader::new(file);
82-
let files: Vec<RecentFile> = serde_json::from_reader(reader)?;
83-
84-
self.recent_files = files.into_iter().collect();
85-
Ok(())
71+
pub fn to_json(&self) -> Result<String> {
72+
Ok(serde_json::to_string_pretty(self)?)
8673
}
8774

88-
pub fn save(&self) -> Result<()> {
89-
if let Some(parent) = self.config_path.parent() {
90-
fs::create_dir_all(parent)?;
91-
}
92-
93-
let file = fs::File::create(&self.config_path)?;
94-
let writer = BufWriter::new(file);
95-
let files: Vec<&RecentFile> = self.recent_files.iter().collect();
96-
serde_json::to_writer_pretty(writer, &files)?;
97-
Ok(())
75+
pub fn from_json(json: &str) -> Result<Self> {
76+
Ok(serde_json::from_str(json)?)
9877
}
9978

10079
pub fn add_file(&mut self, path: PathBuf) -> Result<()> {
10180
self.recent_files.retain(|f| f.path != path);
10281
let recent_file = RecentFile::new(path.clone())?;
103-
self.recent_files.push_front(recent_file);
82+
self.recent_files.insert(0, recent_file);
10483

10584
while self.recent_files.len() > self.max_files {
106-
self.recent_files.pop_back();
85+
self.recent_files.pop();
10786
}
10887

109-
self.save()?;
11088
Ok(())
11189
}
11290

113-
pub fn remove_file(&mut self, path: &PathBuf) -> Result<()> {
91+
pub fn remove_file(&mut self, path: &PathBuf) {
11492
self.recent_files.retain(|f| f.path != *path);
115-
self.save()?;
116-
Ok(())
11793
}
11894

11995
pub fn get_recent_files(&self) -> Vec<&RecentFile> {
@@ -124,16 +100,12 @@ impl RecentFilesManager {
124100
self.recent_files.iter().filter(|f| f.exists()).collect()
125101
}
126102

127-
pub fn clear_all(&mut self) -> Result<()> {
103+
pub fn clear_all(&mut self) {
128104
self.recent_files.clear();
129-
self.save()?;
130-
Ok(())
131105
}
132106

133-
pub fn clear_missing(&mut self) -> Result<()> {
107+
pub fn clear_missing(&mut self) {
134108
self.recent_files.retain(|f| f.exists());
135-
self.save()?;
136-
Ok(())
137109
}
138110

139111
pub fn file_count(&self) -> usize {
@@ -147,7 +119,7 @@ impl RecentFilesManager {
147119
pub fn set_max_files(&mut self, max: usize) {
148120
self.max_files = max;
149121
while self.recent_files.len() > self.max_files {
150-
self.recent_files.pop_back();
122+
self.recent_files.pop();
151123
}
152124
}
153125
}

wayshot/src/logic/video_editor/common_type.rs

Lines changed: 25 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,13 @@
1-
//! # Common Types for Video Editor UI
2-
//!
3-
//! This module provides type conversions between Slint UI types and Rust-native types.
4-
//!
5-
//! ## Design Philosophy
6-
//!
7-
//! **These types are NOT duplicates** of `video_editor` library types. They serve as an
8-
//! **adaptation layer** with specific purposes:
9-
//!
10-
//! 1. **UI Bridge**: Convert between Slint UI types (which require special serialization)
11-
//! and Rust-native types for backend logic
12-
//!
13-
//! 2. **Serialization Support**: Provide `Serialize`/`Deserialize` for project persistence
14-
//! through serde, while UI types are Slint-specific and cannot be serialized directly
15-
//!
16-
//! 3. **UI-Specific Fields**: Include UI-only data like thumbnails (`Image`), audio samples,
17-
//! and screenshots that don't belong in the core `video_editor` library
18-
//!
19-
//! ## Type Mapping
20-
//!
21-
//! - `VideoEditorTracksManager` ↔ `video_editor::tracks::manager::Manager`
22-
//! - `VideoEditorTrack` ↔ `video_editor::tracks::track::Track`
23-
//! - `VideoEditorTrackSegment` ↔ `video_editor::tracks::segment::Segment`
24-
//!
25-
//! See `conversion.rs` for the actual conversion logic.
26-
//!
27-
//! ## Priority: video_editor Library First
28-
//!
29-
//! Core video editing logic uses `video_editor` library types directly.
30-
//! These common types are ONLY used for:
31-
//! - UI state serialization/deserialization
32-
//! - Temporary data transfer between UI and backend
33-
//! - UI-specific features (thumbnails, screenshots, audio visualization)
34-
351
use super::project::UI_STATE_ID;
362
use crate::slint_generatedAppWindow::{
373
AudioChannels as UIAudioChannels, AudioFormat as UIAudioFormat,
384
AudioSampleRate as UIAudioSampleRate, Fps as UIFps, MediaType as UIMediaType,
39-
RecentEntry as UIRecentEntry, Resolution as UIResolution, SegmentFilter as UISegmentFilter,
40-
SubtitleType as UISubtitleType, VideoEditorExportAudioConfig as UIVideoEditorExportAudioConfig,
5+
Resolution as UIResolution, SegmentFilter as UISegmentFilter, SubtitleType as UISubtitleType,
6+
VideoEditorExportAudioConfig as UIVideoEditorExportAudioConfig,
417
VideoEditorExportQueueItem as UIVideoEditorExportQueueItem,
428
VideoEditorExportVideoConfig as UIVideoEditorExportVideoConfig,
43-
VideoEditorFilter as UIVideoEditorFilter,
44-
VideoEditorNewProjectConfig as UIVideoEditorNewProjectConfig,
45-
VideoEditorPlaylistItem as UIVideoEditorPlaylistItem,
46-
VideoEditorPreviewConfig as UIVideoEditorPreviewConfig,
9+
VideoEditorFilter as UIVideoEditorFilter, VideoEditorPlaylistItem as UIVideoEditorPlaylistItem,
10+
VideoEditorRecentEntry as UIVideoEditorRecentEntry,
4711
VideoEditorSubtitle as UIVideoEditorSubtitle, VideoEditorTrack as UIVideoEditorTrack,
4812
VideoEditorTrackSegment as UIVideoEditorTrackSegment,
4913
VideoEditorTrackType as UIVideoEditorTrackType,
@@ -54,11 +18,13 @@ use derivative::Derivative;
5418
use pmacro::SlintFromConvert;
5519
use serde::{Deserialize, Serialize};
5620
use slint::{Image, Model};
21+
use std::time::SystemTime;
22+
use video_editor::project::recent::RecentFile;
5723

58-
crate::impl_slint_enum_serde!(UIVideoEditorTrackType, Audio, Video, Subtitle, Overlay);
5924
crate::impl_slint_enum_serde!(UISubtitleType, Srt, Vtt, Ass);
60-
crate::impl_slint_enum_serde!(UIMediaType, Video, Audio, Image, Subtitle, Text);
6125
crate::impl_slint_enum_serde!(UIAudioFormat, Aac, Mp3, Ogg, Wav, Flac);
26+
crate::impl_slint_enum_serde!(UIMediaType, Video, Audio, Image, Subtitle, Text);
27+
crate::impl_slint_enum_serde!(UIVideoEditorTrackType, Audio, Video, Subtitle, Overlay);
6228
crate::impl_slint_enum_serde!(UIAudioChannels, Mono, Stereo);
6329
crate::impl_slint_enum_serde!(
6430
UIAudioSampleRate,
@@ -190,31 +156,6 @@ pub struct VideoEditorTracksManager {
190156
pub tracks: Vec<VideoEditorTrack>,
191157
}
192158

193-
#[derive(Serialize, Deserialize, Debug, Clone, Derivative, SlintFromConvert)]
194-
#[derivative(Default)]
195-
#[from("UIVideoEditorPreviewConfig")]
196-
#[serde(default)]
197-
pub struct VideoEditorPreviewConfig {
198-
#[from("fps")]
199-
pub fps: UIFps,
200-
#[from("resolution")]
201-
pub resolution: UIResolution,
202-
#[from("channels")]
203-
pub channels: UIAudioChannels,
204-
#[from("sample_rate")]
205-
pub sample_rate: UIAudioSampleRate,
206-
}
207-
208-
#[derive(Serialize, Deserialize, Debug, Clone, Derivative, SlintFromConvert)]
209-
#[derivative(Default)]
210-
#[from("UIVideoEditorNewProjectConfig")]
211-
#[serde(default)]
212-
pub struct VideoEditorNewProjectConfig {
213-
pub name: String,
214-
#[from("preview_config")]
215-
pub preview_config: VideoEditorPreviewConfig,
216-
}
217-
218159
#[derive(Serialize, Deserialize, Debug, Clone, Derivative, SlintFromConvert)]
219160
#[derivative(Default)]
220161
#[from("UIVideoEditorPlaylistItem")]
@@ -292,12 +233,21 @@ pub struct VideoEditorSubtitle {
292233
pub subtitle: String,
293234
}
294235

295-
#[derive(Serialize, Deserialize, Debug, Clone, Derivative, SlintFromConvert)]
296-
#[derivative(Default)]
297-
#[from("UIRecentEntry")]
298-
#[serde(default)]
299-
pub struct RecentEntry {
300-
pub name: String,
301-
pub path: String,
302-
pub modify_at: String,
236+
impl From<RecentFile> for UIVideoEditorRecentEntry {
237+
fn from(rf: RecentFile) -> Self {
238+
let modified_at = if let Ok(modified) =
239+
rf.last_modified.duration_since(SystemTime::UNIX_EPOCH)
240+
&& let Some(datetime) = chrono::DateTime::from_timestamp(modified.as_secs() as i64, 0)
241+
{
242+
datetime.format("%Y-%m-%d").to_string().into()
243+
} else {
244+
"--:--:--".to_string().into()
245+
};
246+
247+
UIVideoEditorRecentEntry {
248+
name: rf.name.into(),
249+
path: rf.path.to_string_lossy().to_string().into(),
250+
modified_at,
251+
}
252+
}
303253
}

0 commit comments

Comments
 (0)