From a922bd2d0bb9f206f3f4872722bfc94802a466ec Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Sun, 21 Jun 2026 09:03:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(editor):=20open=20the=20Openverse=20regist?= =?UTF-8?q?er=20link=20from=20Settings=20=E2=86=92=20Images?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Register at Openverse" link in Settings → Images → Advanced was painted but inert. Add a hit-test (register_link_rect → ImagesHit::OpenRegisterLink → AgentSettingsHit::OpenImageRegisterLink) and open https://api.openverse.org/v1/auth_tokens/register/ on click — default browser on desktop (open/xdg-open/start) and a new tab on web (window.open). --- .../src/widgets/agent_settings_images.rs | 20 ++++++++++++++ .../agent_settings_images_profile_tests.rs | 27 +++++++++++++++++++ .../src/widgets/agent_settings_panel.rs | 4 +++ .../src/widget_host/press_helpers.rs | 19 +++++++++++++ .../src/widget_host/agent_settings_press.rs | 9 +++++++ 5 files changed, 79 insertions(+) diff --git a/crates/op-editor-ui/src/widgets/agent_settings_images.rs b/crates/op-editor-ui/src/widgets/agent_settings_images.rs index 9eb74eef3..d2696e438 100644 --- a/crates/op-editor-ui/src/widgets/agent_settings_images.rs +++ b/crates/op-editor-ui/src/widgets/agent_settings_images.rs @@ -29,6 +29,10 @@ const ADD_BTN_W: f32 = 72.0; const BTN_H: f32 = 28.0; const BODY_GAP: f32 = 14.0; const REGISTER_ROW_H: f32 = 36.0; +// Fixed hit-rect width for the "Register at Openverse" link. Covers the +// link text + trailing chevron across all locales without reaching the +// right-aligned Test button. +const REGISTER_LINK_W: f32 = 220.0; const PROFILE_ROW_H: f32 = 32.0; const PROFILE_ROW_GAP: f32 = 6.0; const PROFILE_ROW_INSET_X: f32 = 8.0; @@ -48,6 +52,7 @@ const PROVIDER_OPTION_H: f32 = 24.0; pub enum ImagesHit { ToggleAdvanced, FocusSearchField(ImageSearchField), + OpenRegisterLink, TestSearch, AddGenConfig, ToggleGenConfigEditor(usize), @@ -117,6 +122,18 @@ fn register_link_y(content: Rect) -> f32 { content.origin.y + TITLE_H + ADVANCED_ROW_H + SUBTITLE_H + ROW_H + ROW_VGAP + ROW_H + BODY_GAP } +/// Click target for the "Register at Openverse" link (text + chevron). +/// A fixed `REGISTER_LINK_W` width covers every locale's link label +/// without reaching the right-aligned Test button. +pub(super) fn register_link_rect(content: Rect) -> Rect { + Rect::xywh( + content.origin.x, + register_link_y(content), + REGISTER_LINK_W, + REGISTER_ROW_H, + ) +} + #[rustfmt::skip] fn search_field_rect(content: Rect, index: usize) -> Rect { let y = content.origin.y @@ -249,6 +266,9 @@ pub fn hit_test(content: Rect, settings: &AgentSettings, scrolled: Point2D) -> I if (search_field_rect(content, 1)).contains(scrolled) { return ImagesHit::FocusSearchField(ImageSearchField::ClientSecret); } + if (register_link_rect(content)).contains(scrolled) { + return ImagesHit::OpenRegisterLink; + } if search_test_enabled(settings) && (test_btn_rect(content, settings)).contains(scrolled) { return ImagesHit::TestSearch; } diff --git a/crates/op-editor-ui/src/widgets/agent_settings_images_profile_tests.rs b/crates/op-editor-ui/src/widgets/agent_settings_images_profile_tests.rs index 0208c4e16..b42ac86dd 100644 --- a/crates/op-editor-ui/src/widgets/agent_settings_images_profile_tests.rs +++ b/crates/op-editor-ui/src/widgets/agent_settings_images_profile_tests.rs @@ -644,3 +644,30 @@ fn expanded_image_gen_profile_card_is_inset_from_content_clip_edges() { "profile card should leave horizontal room inside the clipped content area" ); } + +#[test] +fn images_register_link_hit_test_returns_open_register_link() { + use crate::widgets::agent_settings_images::{self, register_link_rect, ImagesHit}; + use crate::widgets::agent_settings_panel_geometry::content_rect; + + let mut state = EditorState::default(); + state.editor_ui.agent_settings.tab = AgentSettingsTab::Images; + state.editor_ui.agent_settings.images_advanced_open = true; + + let panel = AgentSettingsPanel::for_editor(&state); + let rect = panel.rect(1200.0, 800.0); + let content = content_rect(rect); + + // Aim at the centre of the link's click target. + let link = register_link_rect(content); + let point = Point2D::new( + link.origin.x + link.size.x / 2.0, + link.origin.y + link.size.y / 2.0, + ); + + assert_eq!( + agent_settings_images::hit_test(content, &state.editor_ui.agent_settings, point), + ImagesHit::OpenRegisterLink, + "clicking the Register-at-Openverse link should map to OpenRegisterLink" + ); +} diff --git a/crates/op-editor-ui/src/widgets/agent_settings_panel.rs b/crates/op-editor-ui/src/widgets/agent_settings_panel.rs index 8dda3d98a..26cf55411 100644 --- a/crates/op-editor-ui/src/widgets/agent_settings_panel.rs +++ b/crates/op-editor-ui/src/widgets/agent_settings_panel.rs @@ -83,6 +83,7 @@ pub enum AgentSettingsHit { CopyMcpClientConfig, ToggleImagesAdvanced, FocusSearchField(ImageSearchField), + OpenImageRegisterLink, TestImageSearch, AddGenConfig, ToggleGenConfigEditor(usize), @@ -249,6 +250,9 @@ impl<'a> AgentSettingsPanel<'a> { ImagesHit::FocusSearchField(field) => { return AgentSettingsHit::FocusSearchField(field); } + ImagesHit::OpenRegisterLink => { + return AgentSettingsHit::OpenImageRegisterLink; + } ImagesHit::TestSearch => return AgentSettingsHit::TestImageSearch, ImagesHit::AddGenConfig => return AgentSettingsHit::AddGenConfig, ImagesHit::ToggleGenConfigEditor(index) => { diff --git a/crates/op-host-native/src/widget_host/press_helpers.rs b/crates/op-host-native/src/widget_host/press_helpers.rs index 03a399d27..c5ea8a7b4 100644 --- a/crates/op-host-native/src/widget_host/press_helpers.rs +++ b/crates/op-host-native/src/widget_host/press_helpers.rs @@ -169,6 +169,10 @@ impl WidgetHostNative { ); self.set_settings_input_text(text); } + AgentSettingsHit::OpenImageRegisterLink => { + self.commit_settings_focus_if_any(); + open_external_url("https://api.openverse.org/v1/auth_tokens/register/"); + } AgentSettingsHit::TestImageSearch => { self.commit_settings_focus_if_any(); let settings = &mut self.editor_state.editor_ui.agent_settings; @@ -884,6 +888,21 @@ pub(in crate::widget_host) fn color_target( } } +/// Open `url` in the user's default browser. Spawns the platform's +/// URL launcher detached and ignores any error — opening a help link +/// must never block or panic the editor. Used by the agent-settings +/// "Register at Openverse" link. +fn open_external_url(url: &str) { + #[cfg(target_os = "macos")] + let _ = std::process::Command::new("open").arg(url).spawn(); + #[cfg(target_os = "windows")] + let _ = std::process::Command::new("cmd") + .args(["/C", "start", "", url]) + .spawn(); + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + let _ = std::process::Command::new("xdg-open").arg(url).spawn(); +} + #[cfg(test)] mod tests { use super::create_initial_size_for_tool; diff --git a/crates/op-host-web/src/widget_host/agent_settings_press.rs b/crates/op-host-web/src/widget_host/agent_settings_press.rs index 2975e5fb1..0dc522709 100644 --- a/crates/op-host-web/src/widget_host/agent_settings_press.rs +++ b/crates/op-host-web/src/widget_host/agent_settings_press.rs @@ -110,6 +110,15 @@ impl WidgetHost { Some(SettingsFocus::ImageSearch(field)); self.set_settings_input_text(text); } + AgentSettingsHit::OpenImageRegisterLink => { + self.commit_settings_focus(); + if let Some(w) = web_sys::window() { + let _ = w.open_with_url_and_target( + "https://api.openverse.org/v1/auth_tokens/register/", + "_blank", + ); + } + } AgentSettingsHit::TestImageSearch => { self.commit_settings_focus(); let settings = &mut self.editor_state.editor_ui.agent_settings;