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
35 changes: 33 additions & 2 deletions apps/desktop/src/view/cnb_media.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ pub(super) fn extensions(
repository: &str,
cli: Option<&Path>,
locale: Language,
native_player_visible: bool,
) -> MarkdownExtensions {
MarkdownExtensions::default().plugin(MediaPlugin {
repository: repository.to_owned(),
cli: cli.map(Path::to_path_buf),
locale,
native_player_visible,
})
}

struct MediaPlugin {
repository: String,
cli: Option<PathBuf>,
locale: Language,
native_player_visible: bool,
}

enum Part {
Expand Down Expand Up @@ -133,11 +136,18 @@ impl MarkdownPlugin for MediaPlugin {
label.clone(),
self.cli.clone(),
self.locale,
self.native_player_visible,
cx,
)
},
);
state.update(cx, |state, _| state.locale = self.locale);
state.update(cx, |state, cx| {
state.locale = self.locale;
if state.native_player_visible != self.native_player_visible {
state.native_player_visible = self.native_player_visible;
cx.notify();
}
});
body = body.child(state);
}
}
Expand All @@ -151,6 +161,7 @@ struct MediaView {
label: String,
cli: Option<PathBuf>,
locale: Language,
native_player_visible: bool,
loaded: Option<Result<LoadedMedia, LocalizedText>>,
task: Task<()>,
abort: Option<tokio::task::AbortHandle>,
Expand All @@ -164,6 +175,7 @@ impl MediaView {
label: String,
cli: Option<PathBuf>,
locale: Language,
native_player_visible: bool,
cx: &mut Context<Self>,
) -> Self {
cx.on_release(|view, cx| {
Expand All @@ -179,6 +191,7 @@ impl MediaView {
label,
cli,
locale,
native_player_visible,
loaded: None,
task: Task::ready(()),
abort: None,
Expand Down Expand Up @@ -264,6 +277,22 @@ impl Render for MediaView {
.gap_2()
.text_size(px(12.))
.text_color(rgb(colors.muted));
#[cfg(test)]
let frame = if self.source.kind == MediaKind::Image {
frame
} else {
let selector = if self.native_player_visible {
"cnb-native-player-visible"
} else {
"cnb-native-player-obscured"
};
frame.child(
div()
.absolute()
.size(px(0.))
.debug_selector(move || selector.to_owned()),
)
};
let content = match &self.loaded {
None => div()
.p_4()
Expand Down Expand Up @@ -315,7 +344,9 @@ impl Render for MediaView {
);
}
match self.player.as_ref().expect("player initialized") {
Ok(player) => player.element(self.source.kind).into_any_element(),
Ok(player) => player
.element(self.source.kind, self.native_player_visible)
.into_any_element(),
Err(error) => self.error(error, cx).into_any_element(),
}
}
Expand Down
40 changes: 35 additions & 5 deletions apps/desktop/src/view/cnb_media/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ pub(super) struct Player {
struct PlayerBounds {
full: Bounds<Pixels>,
visible: Bounds<Pixels>,
unobscured: bool,
}

impl PlayerBounds {
fn should_show(self) -> bool {
self.unobscured && self.visible.size.width > px(0.) && self.visible.size.height > px(0.)
}
}

#[derive(serde::Deserialize)]
Expand Down Expand Up @@ -101,7 +108,7 @@ impl Player {
})
}

pub(super) fn element(&self, kind: MediaKind) -> impl IntoElement {
pub(super) fn element(&self, kind: MediaKind, unobscured: bool) -> impl IntoElement {
let webview = self.webview.clone();
let last_bounds = self.bounds.clone();
div()
Expand All @@ -121,13 +128,14 @@ impl Player {
let next = PlayerBounds {
full: bounds,
visible,
unobscured,
};
let previous = last_bounds.get();
if previous == Some(next) {
return;
}
last_bounds.set(Some(next));
let shown = visible.size.width > px(0.) && visible.size.height > px(0.);
let shown = next.should_show();
if shown {
let _ = webview.set_bounds(Rect {
position: LogicalPosition::new(
Expand All @@ -149,9 +157,7 @@ impl Player {
f32::from(bounds.origin.y - visible.origin.y),
));
}
let was_shown = previous.is_some_and(|last| {
last.visible.size.width > px(0.) && last.visible.size.height > px(0.)
});
let was_shown = previous.is_some_and(PlayerBounds::should_show);
if shown != was_shown {
let _ = webview.set_visible(shown);
}
Expand Down Expand Up @@ -255,6 +261,30 @@ addEventListener('wheel',e=>{{if(e.ctrlKey)return;const scale=e.deltaMode===1?16
mod tests {
use super::*;

#[test]
fn cnb_player_hides_while_a_gpui_overlay_is_open() {
let visible = Bounds {
origin: gpui::point(px(0.), px(0.)),
size: gpui::size(px(640.), px(360.)),
};
assert!(
PlayerBounds {
full: visible,
visible,
unobscured: true,
}
.should_show()
);
assert!(
!PlayerBounds {
full: visible,
visible,
unobscured: false,
}
.should_show()
);
}

#[tokio::test]
async fn cnb_player_serves_byte_ranges_only_for_its_attachment() {
use crate::infrastructure::cnb_media::LocalMedia;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/view/issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ impl NexusView {
issues.repository.as_deref().unwrap_or_default(),
issues.cli.as_ref().map(|cli| cli.path.as_path()),
self.presenter.model().language,
self.issue_launch.is_none(),
)
} else {
Default::default()
Expand Down
15 changes: 15 additions & 0 deletions apps/desktop/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2796,6 +2796,11 @@ mod catalog_model_tests {
let mut issue = cnb_issue("1");
issue.body = "截图说明\n\n![截图](https://example.test/screenshot.png)\n\n[录屏.mp4](undefined/team/repo/-/files/issues/1/clip.mp4)\n\nhttps://example.test/sound.mp3\n\n[普通链接](https://example.test/page)\n\n```text\nhttps://example.test/code.mp4\n```".into();
finish_issue_request(&mut view.presenter, IssueProvider::Cnb, Response::Detail(Ok(issue)));
finish_issue_request(
&mut view.presenter,
IssueProvider::Cnb,
Response::Comments(Ok(Vec::new())),
);
cx.notify();
});
cx.run_until_parked();
Expand All @@ -2804,6 +2809,16 @@ mod catalog_model_tests {
assert!(cx.debug_bounds("cnb-media-image").is_some());
assert!(cx.debug_bounds("cnb-media-video").is_some());
assert!(cx.debug_bounds("cnb-media-audio").is_some());
assert!(cx.debug_bounds("cnb-native-player-visible").is_some());
click_debug(cx, "cnb-chat");
cx.run_until_parked();
assert!(cx.debug_bounds("issue-launch-surface").is_some());
assert!(cx.debug_bounds("cnb-native-player-visible").is_none());
assert!(cx.debug_bounds("cnb-native-player-obscured").is_some());
click_debug(cx, "issue-launch-close");
cx.run_until_parked();
assert!(cx.debug_bounds("issue-launch-surface").is_none());
assert!(cx.debug_bounds("cnb-native-player-visible").is_some());
click_debug(cx, "cnb-back");
cx.run_until_parked();
assert!(cx.debug_bounds("cnb-issue-1").is_some());
Expand Down