Skip to content

Commit d14733c

Browse files
committed
[*] refactor: video-editor
1 parent ccc8ee4 commit d14733c

File tree

14 files changed

+185
-40
lines changed

14 files changed

+185
-40
lines changed

lib/video-editor/src/media/playlist.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,14 @@ impl Playlist {
195195

196196
let item_name = name.unwrap_or_else(|| {
197197
file_path
198-
.file_stem()
198+
.file_name()
199199
.and_then(|s| s.to_str())
200-
.unwrap_or("Unknown")
200+
.unwrap_or_else(|| {
201+
file_path
202+
.file_stem()
203+
.and_then(|s| s.to_str())
204+
.unwrap_or("Unknown")
205+
})
201206
.to_string()
202207
});
203208

todo.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
1. 创建项目预览配置应该使用下拉图标,而不是switch
2-
2. 预览视频下应该添加也给全局定位时间轴,方便快速跳转时间轴
3-
3. playlist/library列表应该保留文件扩展名
4-
4. playlist/library图标太小, 鼠标放到图片上应该使用tooltip显示文件名。右键应该弹出是否删除或添加到轨道的选项
1+
## 问题
52
5. 点击跳转到最后按钮没有刷新预览图片
6-
6. 轨道头再次点击无法取消选中
7-
7. segment再次点击也无法取消选中
8-
8. segment没有任何filter的时候应该显示空图片,表示没有任何filter
93
9. 左右声道db显示没有实现
104
10. 视频轨道声音波形没有实现
115
11. `Timeline cursor must be within the segment` 错误。
@@ -14,10 +8,20 @@
148
14. 将视频添加到轨道时会自动解码这个视频的音频。阻塞UI线程
159
15. 轨道声音波形不对,幅度很小
1610
16. 没有轨道操作都会解码音视频数据。造成UI严重卡顿
17-
17. 点击segment,选中的segment不会在界面上改变
18-
18. 关闭时,playlist和preview没有清除
1911
19. 打开项目会解码整个视频文件。
12+
20. 视频已经暂停了,但是点击时间轴跳转的时候,会播放1秒左右的音频
13+
14+
21. 保存项目的目录有问题,选中的是/home/blue,会保存到/home目录下
15+
16+
## 待验证
17+
18. 关闭时,playlist和preview没有清除
18+
6. 轨道头UI没有toggle选中和没选中状态
19+
6. 轨道头再次点击无法取消选中
20+
17. 点击segment,选中的segment不会在界面上改变(有问题)
21+
22+
2023

2124

2225
## 待实现功能
2326
1. 没有定时自动保存功能
27+
2. 预览视频下应该添加也给全局定位时间轴,方便快速跳转时间轴

wayshot/src/logic/video_editor/project.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use video_editor::{
2424
tracks::manager::Manager,
2525
};
2626

27-
pub const PROJECT_EXT: &str = "swp";
27+
pub const PROJECT_EXT: &str = "wayshot";
2828
pub const RECENT_ID: &str = "video_editor_recent";
2929
pub const UI_STATE_ID: &str = "video_editor_ui_state";
3030
pub const LIBRARY_ID: &str = "video_editor_library";
@@ -389,7 +389,11 @@ fn video_editor_close_project_with_save(ui: &AppWindow) {
389389

390390
fn video_editor_close_project_without_save(ui: &AppWindow) {
391391
global_store!(ui).set_video_editor_tracks_manager(UIVideoEditorTracksManager::default());
392+
global_store!(ui).set_video_editor_preview_image(slint::Image::default());
392393
global_store!(ui).set_video_editor_is_unsaved(false);
394+
global_store!(ui).set_video_editor_is_previewing(false);
395+
global_store!(ui).set_video_editor_timeline_offset(0);
396+
store_video_editor_playlist!(ui).set_vec(vec![]);
393397
*PROJECT_STATE.lock().unwrap() = Some(ProjectState::default());
394398
}
395399

wayshot/src/logic/video_editor/segment.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub fn init(ui: &AppWindow) {
6868
ui,
6969
selected_segment,
7070
index
71+
_flag,
7172
);
7273
logic_cb!(video_editor_selected_segment, ui);
7374
logic_cb!(video_editor_remove_segments, ui);
@@ -92,9 +93,7 @@ fn video_editor_add_selected_segment(ui: &AppWindow, index: UISelectedSegmentInd
9293
selected_indices.push(index.clone());
9394
}
9495
} else if index.modifiers.shift {
95-
// Range selection (from last selected to current)
9696
if let Some(last) = selected_indices.last() {
97-
// Range selection within the same track
9897
if last.track_index == index.track_index {
9998
let start = last.index.min(index.index);
10099
let end = last.index.max(index.index);
@@ -117,8 +116,12 @@ fn video_editor_add_selected_segment(ui: &AppWindow, index: UISelectedSegmentInd
117116
selected_indices.push(index.clone());
118117
}
119118
} else {
120-
selected_indices.clear();
121-
selected_indices.push(index.clone());
119+
if is_selected && selected_indices.len() == 1 {
120+
selected_indices.clear();
121+
} else {
122+
selected_indices.clear();
123+
selected_indices.push(index.clone());
124+
}
122125
}
123126

124127
store_video_editor_selected_segments_index!(ui).set_vec(selected_indices);
@@ -176,6 +179,7 @@ fn video_editor_is_selected_segment(
176179
_ui: &AppWindow,
177180
selected_segment: ModelRc<UISelectedSegmentIndex>,
178181
index: UISelectedSegmentIndex,
182+
_flag: bool,
179183
) -> bool {
180184
selected_segment
181185
.iter()

wayshot/src/logic/video_editor/track.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ pub fn init(ui: &AppWindow) {
5656
logic_cb!(video_editor_is_overlay_track, ui, index);
5757
logic_cb!(video_editor_contain_audio_track, ui, index);
5858
logic_cb!(video_editor_contain_subtitle_track, ui, index);
59-
logic_cb!(video_editor_is_selected_track, ui, selected_tracks, index);
59+
logic_cb!(
60+
video_editor_is_selected_track,
61+
ui,
62+
selected_tracks,
63+
index,
64+
_flag
65+
);
6066
}
6167

6268
fn video_editor_add_track(ui: &AppWindow, ty: VideoEditorTrackType) {
@@ -428,8 +434,12 @@ fn video_editor_add_selected_track(ui: &AppWindow, index: SelectedTrackIndex) {
428434
selected_indices.push(index.clone());
429435
}
430436
} else {
431-
selected_indices.clear();
432-
selected_indices.push(index.clone());
437+
if is_selected && selected_indices.len() == 1 {
438+
selected_indices.clear();
439+
} else {
440+
selected_indices.clear();
441+
selected_indices.push(index.clone());
442+
}
433443
}
434444

435445
store_video_editor_selected_tracks_index!(ui).set_vec(selected_indices);
@@ -523,6 +533,7 @@ fn video_editor_is_selected_track(
523533
_ui: &AppWindow,
524534
selected_tracks: ModelRc<SelectedTrackIndex>,
525535
index: i32,
536+
_flag: bool,
526537
) -> bool {
527538
let count = selected_tracks.row_count();
528539
for i in 0..count {

wayshot/ui/base/collapse.slint

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,74 @@ export component Collapse inherits Rectangle {
105105
}
106106
}
107107
}
108+
109+
export component SingleCollapse inherits Rectangle {
110+
in-out property <string> title;
111+
in-out property <bool> is-open;
112+
in-out property <image> title-icon;
113+
114+
in-out property <color> title-color: Theme.primary-text-color;
115+
in-out property <length> title-font-size: Theme.title3-font-size;
116+
in-out property <int> title-font-weight: Theme.bold-font-weight;
117+
118+
in-out property <image> open-icon: Icons.arrow-down-light;
119+
in-out property <image> close-icon: Icons.arrow-up-light;
120+
121+
in-out property <length> spacing: Theme.spacing * 2;
122+
in-out property <length> hpadding: Theme.padding * 2;
123+
in-out property <length> vpadding: Theme.padding * 2;
124+
125+
callback toggle(state: bool);
126+
127+
background: Theme.secondary-background;
128+
border-radius: Theme.border-radius;
129+
130+
TouchArea {
131+
clicked => {
132+
root.is-open = !root.is-open;
133+
toggle(root.is-open);
134+
}
135+
}
136+
137+
HorizontalLayout {
138+
alignment: LayoutAlignment.space-between;
139+
spacing: Theme.spacing * 2;
140+
padding-left: root.hpadding;
141+
padding-right: root.hpadding;
142+
padding-top: root.vpadding;
143+
padding-bottom: root.vpadding;
144+
145+
HorizontalLayout {
146+
spacing: root.spacing;
147+
148+
if root.title-icon.width > 0: VerticalLayout {
149+
alignment: LayoutAlignment.center;
150+
151+
Image {
152+
width: Theme.icon-size;
153+
height: self.width;
154+
colorize: Theme.icon-color;
155+
source: root.title-icon;
156+
}
157+
}
158+
159+
lb := Label {
160+
overflow: elide;
161+
text: root.title;
162+
font-size: root.title-font-size;
163+
color: root.title-color;
164+
font-weight: root.title-font-weight;
165+
}
166+
}
167+
168+
VerticalLayout {
169+
alignment: LayoutAlignment.center;
170+
Image {
171+
width: Theme.icon-size;
172+
height: self.width;
173+
colorize: Theme.icon-color;
174+
source: root.is-open ? root.close-icon : root.open-icon;
175+
}
176+
}
177+
}
178+
}

wayshot/ui/base/widgets.slint

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ import { PinCodesCount, PinCodes } from "pin-codes.slint";
109109
import { Badge } from "badge.slint";
110110
import { Select } from "select.slint";
111111
import { Slider } from "slider.slint";
112-
import { Collapse, CollapseEntry } from "collapse.slint";
112+
import { Collapse, CollapseEntry, SingleCollapse } from "collapse.slint";
113113
import { Stretch } from "stretch.slint";
114114
import { Search } from "search.slint";
115115
import {
@@ -256,6 +256,7 @@ export {
256256
Select,
257257
Slider,
258258
Collapse,
259+
SingleCollapse,
259260
CollapseEntry,
260261
Search,
261262
PopupAction,

wayshot/ui/logic.slint

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ export global Logic {
300300
pure callback video-editor-is-overlay-track(index: int) -> bool;
301301
pure callback video-editor-contain-audio-track(index: int) -> bool;
302302
pure callback video-editor-contain-subtitle-track(index: int) -> bool;
303-
pure callback video-editor-is-selected-track(selected-tracks: [SelectedTrackIndex], index: int) -> bool;
303+
pure callback video-editor-is-selected-track(selected-tracks: [SelectedTrackIndex], index: int, _falg: bool) -> bool;
304304

305305
callback video-editor-remove-segments();
306306
callback video-editor-split-segment();
@@ -317,7 +317,7 @@ export global Logic {
317317
callback video-editor-segment-remove-gap(index: SelectedSegmentIndex);
318318
callback video-editor-segment-remove-left-gap(index: SelectedSegmentIndex);
319319
callback video-editor-segment-remove-right-gap(index: SelectedSegmentIndex);
320-
pure callback video-editor-is-selected-segment(selected-segment: [SelectedSegmentIndex], index: SelectedSegmentIndex) -> bool;
320+
pure callback video-editor-is-selected-segment(selected-segment: [SelectedSegmentIndex], index: SelectedSegmentIndex, _flag: bool) -> bool;
321321
pure callback video-editor-selected-segment() -> VideoEditorTrackSegment; // 获取当前选中的segment
322322

323323
callback video-editor-playlist-item-add-to-track(index: int);

wayshot/ui/panel/desktop/video-editor/left-panel/playlist.slint

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ component DetailItem inherits Rectangle {
118118
}
119119

120120
hbox := HorizontalLayout {
121-
spacing: Theme.spacing * 8;
121+
spacing: Theme.spacing * 4;
122122
padding: Theme.padding * 2;
123123
alignment: space-between;
124124

@@ -141,19 +141,20 @@ component DetailItem inherits Rectangle {
141141
}
142142
}
143143

144-
HorizontalLayout {
145-
padding-left: Theme.padding * 4;
146-
Label {
147-
text: playlist-item.name;
148-
overflow: elide;
149-
}
144+
Label {
145+
text: playlist-item.name;
146+
overflow: elide;
150147
}
151148
}
152149

153150
HorizontalLayout {
154151
alignment: end;
155152
spacing: Theme.spacing * 4;
156153

154+
Label {
155+
text: playlist-item.duration;
156+
}
157+
157158
Label {
158159
text: playlist-item.file-size;
159160
}
@@ -196,6 +197,7 @@ component ThumbnailItem inherits Rectangle {
196197
in property <VideoEditorPlaylistItem> playlist-item;
197198

198199
callback double-clicked <=> ta.double-clicked;
200+
callback right-clicked(absolute-x: length, absolute-y: length);
199201

200202
public pure function get-media-icon(ty: MediaType) -> image {
201203
if (ty == MediaType.Video) {
@@ -213,6 +215,12 @@ component ThumbnailItem inherits Rectangle {
213215

214216
ta := TouchArea {
215217
mouse-cursor: MouseCursor.pointer;
218+
219+
pointer-event(event) => {
220+
if (event.button == PointerEventButton.right) {
221+
root.right-clicked(self.absolute-position.x, self.absolute-position.y + self.preferred-height);
222+
}
223+
}
216224
}
217225

218226
rec := Rectangle {
@@ -229,7 +237,7 @@ component ThumbnailItem inherits Rectangle {
229237
alignment: center;
230238

231239
Image {
232-
width: rec.width * Theme.golden-ratio;
240+
width: rec.width * 0.8;
233241
source: playlist-item.thumbnail;
234242
}
235243
}
@@ -258,12 +266,13 @@ component ThumbnailItem inherits Rectangle {
258266
export component ThumbnailView inherits ListView {
259267
in-out property <[VideoEditorPlaylistItem]> playlist;
260268

261-
private property <length> thumbnail-size: Theme.icon-size * 5;
269+
private property <length> thumbnail-size: Theme.icon-size * 6;
262270
private property <int> column-count: clamp(root.width / (thumbnail-size + Theme.spacing), 1, 20);
263271

264272
private property <int> row-count: playlist.length == 0 ? 0 : (mod(playlist.length, column-count) == 0 ? playlist.length / column-count : playlist.length / column-count + 1);
265273

266274
callback double-clicked(index: int);
275+
callback right-clicked(index: int, absolute-x: length, absolute-y: length);
267276

268277
for row-index in row-count: HorizontalLayout {
269278
alignment: space-around;
@@ -277,6 +286,10 @@ export component ThumbnailView inherits ListView {
277286
double-clicked => {
278287
root.double-clicked(self.index);
279288
}
289+
290+
right-clicked(absolute-x, absolute-y) => {
291+
root.right-clicked(self.index, absolute-x, absolute-y);
292+
}
280293
}
281294
}
282295
}
@@ -333,6 +346,23 @@ export component Playlist inherits Rectangle {
333346
width: root.width;
334347
playlist <=> root.playlist;
335348

349+
right-clicked(index, absolute-x, absolute-y) => {
350+
PopupActionSetting.show(absolute-x, absolute-y + self.preferred-height, [
351+
{
352+
icon: Icons.add-light,
353+
text: Logic.tr("Add To Track"),
354+
action: "video-editor-playlist-item-add-to-track",
355+
user-data: index,
356+
},
357+
{
358+
icon: Icons.clear-light,
359+
text: Logic.tr("Remove"),
360+
action: "video-editor-playlist-item-remove",
361+
user-data: index,
362+
},
363+
]);
364+
}
365+
336366
double-clicked(index) => {
337367
Logic.video-editor-playlist-item-add-to-track(index);
338368
}

0 commit comments

Comments
 (0)