summaryrefslogtreecommitdiff
path: root/rust/crates/commands/src/bookmarks.rs
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-07-28 19:41:16 +0200
committercashmere <cashmere@autistici.org>2026-07-28 19:41:16 +0200
commitf5a82152394fde4d8f740f664ab7737b82861618 (patch)
tree5a51b181abead1ce03d2dbfc12b77918d3be0e1b /rust/crates/commands/src/bookmarks.rs
parente837e7504379e100ff3b56282577ec67bb88bec9 (diff)
downloadopencut-f5a82152394fde4d8f740f664ab7737b82861618.tar.gz
feat: GPUI desktop port foundation
- scene crate: full project/scene/element model, serde round-trip proven against the web SerializedProject shape - transfer crate: .ocp zip container, cross-compat with web fflate archives proven in both directions - storage crate: filesystem project store replacing IndexedDB, .ocp import/export - media crate: ffmpeg-next 8 decoder (frames, audio, thumbnails, waveform summaries) - playback crate: wall-clock anchored, frame-rounded playback clock - gpu crate: native texture readback; compositor renders headless offscreen on Vulkan (spike test) - flake devshell: rust toolchain, GPUI native deps, ffmpeg dev, bindgen clang args; GPUI hello-world builds - port plan in notes/gpui-port.md
Diffstat (limited to 'rust/crates/commands/src/bookmarks.rs')
-rw-r--r--rust/crates/commands/src/bookmarks.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/rust/crates/commands/src/bookmarks.rs b/rust/crates/commands/src/bookmarks.rs
new file mode 100644
index 00000000..79a73015
--- /dev/null
+++ b/rust/crates/commands/src/bookmarks.rs
@@ -0,0 +1,94 @@
+use scene::Bookmark;
+use time::{FrameRate, MediaTime};
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct BookmarkPatch {
+ pub note: Option<Option<String>>,
+ pub color: Option<Option<String>>,
+ pub duration: Option<Option<MediaTime>>,
+}
+
+pub fn find_bookmark_index(bookmarks: &[Bookmark], frame_time: MediaTime) -> Option<usize> {
+ bookmarks.iter().position(|bookmark| bookmark.time == frame_time)
+}
+
+pub fn is_bookmark_at_time(bookmarks: &[Bookmark], frame_time: MediaTime) -> bool {
+ find_bookmark_index(bookmarks, frame_time).is_some()
+}
+
+pub fn toggle_bookmark_in_array(
+ bookmarks: &[Bookmark],
+ frame_time: MediaTime,
+) -> Vec<Bookmark> {
+ if let Some(index) = find_bookmark_index(bookmarks, frame_time) {
+ return bookmarks
+ .iter()
+ .enumerate()
+ .filter(|(bookmark_index, _)| *bookmark_index != index)
+ .map(|(_, bookmark)| bookmark.clone())
+ .collect();
+ }
+
+ let mut next = bookmarks.to_vec();
+ next.push(Bookmark {
+ time: frame_time,
+ note: None,
+ color: None,
+ duration: None,
+ });
+ next.sort_by_key(|bookmark| bookmark.time);
+ next
+}
+
+pub fn remove_bookmark_from_array(
+ bookmarks: &[Bookmark],
+ frame_time: MediaTime,
+) -> Vec<Bookmark> {
+ bookmarks
+ .iter()
+ .filter(|bookmark| bookmark.time != frame_time)
+ .cloned()
+ .collect()
+}
+
+pub fn update_bookmark_in_array(
+ bookmarks: &[Bookmark],
+ frame_time: MediaTime,
+ updates: &BookmarkPatch,
+) -> Vec<Bookmark> {
+ let Some(index) = find_bookmark_index(bookmarks, frame_time) else {
+ return bookmarks.to_vec();
+ };
+
+ let mut next = bookmarks.to_vec();
+ let bookmark = &mut next[index];
+ if let Some(note) = &updates.note {
+ bookmark.note = note.clone();
+ }
+ if let Some(color) = &updates.color {
+ bookmark.color = color.clone();
+ }
+ if let Some(duration) = &updates.duration {
+ bookmark.duration = *duration;
+ }
+ next
+}
+
+pub fn move_bookmark_in_array(
+ bookmarks: &[Bookmark],
+ from_time: MediaTime,
+ to_time: MediaTime,
+) -> Vec<Bookmark> {
+ let Some(index) = find_bookmark_index(bookmarks, from_time) else {
+ return bookmarks.to_vec();
+ };
+
+ let mut next = bookmarks.to_vec();
+ next[index].time = to_time;
+ next.sort_by_key(|bookmark| bookmark.time);
+ next
+}
+
+pub fn get_frame_time(time: MediaTime, fps: FrameRate) -> MediaTime {
+ time.round_to_frame(fps).unwrap_or(time)
+}