fix(web): link plugins to desktop app
Keep browser entry points visible while explaining that native plugins require a desktop install. Refs #567
This commit is contained in:
parent
2424eeb74d
commit
fcc6e1f8e1
9 changed files with 92 additions and 48 deletions
|
|
@ -81,9 +81,10 @@ on the web.
|
|||
|
||||
Marketplace plugins are native `.dll`, `.so`, or `.dylib` packages launched in
|
||||
an isolated child process. Browsers cannot load those libraries or spawn the
|
||||
plugin runner, so the web build does not show the Plugin Manager or register
|
||||
its commands. Installed desktop plugins remain in the per-user plugins folder
|
||||
and load again on the next desktop launch.
|
||||
plugin runner. The web Plugin button and `PLUGINS` command therefore show a
|
||||
short explanation with a link to download the desktop app instead of opening
|
||||
the marketplace. Installed desktop plugins remain in the per-user plugins
|
||||
folder and load again on the next desktop launch.
|
||||
|
||||
### Platform shims (`src/sys.rs`)
|
||||
- `open_url`: `open::that` on native, `window.open(_blank)` on web.
|
||||
|
|
|
|||
|
|
@ -334,8 +334,9 @@ plugin dead, and reports a `CallTimeout` error via the normal plugin error path.
|
|||
## Marketplace
|
||||
|
||||
The desktop **Plugin Manager** (`PLUGINS` / `PLUGINMANAGER`, or the Start-page
|
||||
button) installs plugins from GitHub Releases. It is hidden in the browser
|
||||
build because marketplace packages are native dynamic libraries:
|
||||
button) installs plugins from GitHub Releases. In the browser, the same entry
|
||||
points show a desktop-download notice because marketplace packages are native
|
||||
dynamic libraries:
|
||||
|
||||
- **Curated registry** — [`plugins/registry.json`](../plugins/registry.json) in
|
||||
this repo lists discoverable plugins. The host fetches it from `main` at
|
||||
|
|
|
|||
|
|
@ -236,6 +236,8 @@ pub fn start_allowed(cmd: &str) -> bool {
|
|||
| "REPORT"
|
||||
| "CHANGELOG"
|
||||
| "ABOUT"
|
||||
| "PLUGINS"
|
||||
| "PLUGINMANAGER"
|
||||
| "DONATE"
|
||||
| "WEBVERSION"
|
||||
| "HELP"
|
||||
|
|
@ -245,8 +247,6 @@ pub fn start_allowed(cmd: &str) -> bool {
|
|||
| "CUILOAD"
|
||||
| "CUIIMPORT"
|
||||
)
|
||||
|| (!cfg!(target_arch = "wasm32")
|
||||
&& matches!(cmd, "PLUGINS" | "PLUGINMANAGER"))
|
||||
}
|
||||
|
||||
// ── Autocomplete registry — one-shot commands ──────────────────────────────
|
||||
|
|
|
|||
|
|
@ -212,17 +212,10 @@ impl OpenCADStudio {
|
|||
return Some(Task::done(Message::AboutOpen));
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
"PLUGINS" | "PLUGINMANAGER" => {
|
||||
return Some(Task::done(Message::PluginManagerOpen));
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
"PLUGINS" | "PLUGINMANAGER" => {
|
||||
self.command_line
|
||||
.push_info("External plugins are available in the desktop app.");
|
||||
}
|
||||
|
||||
"CHANGELOG" => {
|
||||
crate::sys::open_url("https://github.com/HakanSeven12/OpenCADStudio/releases");
|
||||
self.command_line.push_info("Opening release notes...");
|
||||
|
|
|
|||
|
|
@ -521,6 +521,7 @@ pub(super) struct OpenCADStudio {
|
|||
external_plugins: Vec<crate::plugin::external::ExternalPlugin>,
|
||||
/// Ids of external packages actually loaded this session (a subset of
|
||||
/// `external_plugins` — compatible, with a library, dlopen'd at startup).
|
||||
#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
||||
loaded_plugin_ids: rustc_hash::FxHashSet<String>,
|
||||
/// Curated plugin registry fetched from the OpenCADStudio repo.
|
||||
plugin_registry: Vec<crate::plugin::external::RegistryEntry>,
|
||||
|
|
@ -1313,7 +1314,6 @@ impl ClipboardDeps {
|
|||
pub enum ModalKind {
|
||||
About,
|
||||
Shortcuts,
|
||||
#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
||||
PluginManager,
|
||||
UpdateNotice,
|
||||
Layers,
|
||||
|
|
|
|||
|
|
@ -4058,8 +4058,7 @@ impl OpenCADStudio {
|
|||
Message::PluginManagerOpen => {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
self.command_line
|
||||
.push_info("External plugins are available in the desktop app.");
|
||||
self.active_modal = Some(super::ModalKind::PluginManager);
|
||||
return Task::none();
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
|
|
|||
|
|
@ -2300,11 +2300,11 @@ pub(super) fn start_page_view<'a>(
|
|||
.into(),
|
||||
outline_btn("Options", Message::OptionsOpen).into(),
|
||||
];
|
||||
// External plugins are native dynamic libraries and the web build is
|
||||
// already in the browser, so both actions are desktop-only.
|
||||
secondary_items.push(outline_btn("Plugins", Message::PluginManagerOpen).into());
|
||||
// The web build is already in the browser, so only the desktop offers a
|
||||
// link to the web version.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
secondary_items.push(outline_btn("Plugins", Message::PluginManagerOpen).into());
|
||||
// Filled with the active theme's primary colour.
|
||||
secondary_items.push(
|
||||
button(text("OCS Web").size(14))
|
||||
|
|
|
|||
|
|
@ -71,7 +71,10 @@ impl OpenCADStudio {
|
|||
520,
|
||||
500,
|
||||
),
|
||||
super::super::ModalKind::PluginManager => sized(
|
||||
super::super::ModalKind::PluginManager => {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
sized(
|
||||
crate::ui::window::plugin_manager::view_window(
|
||||
&self.disabled_plugins,
|
||||
&self.external_plugins,
|
||||
|
|
@ -80,7 +83,8 @@ impl OpenCADStudio {
|
|||
registry: &self.plugin_registry,
|
||||
registry_loading: self.plugin_registry_loading,
|
||||
registry_error: self.plugin_registry_error.as_deref(),
|
||||
registry_error_details_open: self.plugin_registry_error_details_open,
|
||||
registry_error_details_open: self
|
||||
.plugin_registry_error_details_open,
|
||||
input: &self.plugin_repo_input,
|
||||
search: &self.plugin_search_input,
|
||||
repos: &self.plugin_repos,
|
||||
|
|
@ -95,7 +99,17 @@ impl OpenCADStudio {
|
|||
),
|
||||
940,
|
||||
600,
|
||||
),
|
||||
)
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
sized(
|
||||
crate::ui::window::plugin_manager::view_web_notice(),
|
||||
520,
|
||||
260,
|
||||
)
|
||||
}
|
||||
}
|
||||
super::super::ModalKind::UpdateNotice => {
|
||||
let latest = self.update_notice_version.as_deref().unwrap_or("?");
|
||||
let body = self.update_notice_body.as_deref().unwrap_or("");
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
//! launches). Dynamic loading still comes with the phase-2 loader; see
|
||||
//! `docs/plugin-architecture.md`.
|
||||
|
||||
#![cfg_attr(target_arch = "wasm32", allow(dead_code))]
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::plugin::external::{ExternalPlugin, RegistryEntry};
|
||||
use iced::widget::{
|
||||
|
|
@ -33,9 +35,13 @@ pub struct MarketView<'a> {
|
|||
pub status: &'a str,
|
||||
}
|
||||
|
||||
// External plugins are native dynamic libraries, so the browser build must not
|
||||
// advertise a manager it cannot use.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
/// Latest desktop builds, used by the browser-only plugin notice.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub const DESKTOP_DOWNLOAD_URL: &str =
|
||||
"https://github.com/HakanSeven12/OpenCADStudio/releases/latest";
|
||||
|
||||
// Register the command names for autocomplete. On the web they open a desktop
|
||||
// download notice instead of the native marketplace.
|
||||
inventory::submit!(crate::command::CommandRegistration {
|
||||
names: &["PLUGINS", "PLUGINMANAGER"]
|
||||
});
|
||||
|
|
@ -844,6 +850,36 @@ pub fn view_window<'a>(
|
|||
.into()
|
||||
}
|
||||
|
||||
/// Browser replacement for the native Plugin Manager.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn view_web_notice<'a>() -> Element<'a, Message> {
|
||||
let download = button(text("Download desktop app").size(13))
|
||||
.on_press(Message::OpenUrl(DESKTOP_DOWNLOAD_URL.to_string()))
|
||||
.padding([8, 16])
|
||||
.style(button::primary);
|
||||
|
||||
container(
|
||||
column![
|
||||
text("Plugins require the desktop app").size(20),
|
||||
text(
|
||||
"Open CAD Studio plugins are native packages and cannot run inside a browser. \
|
||||
Install the desktop app to browse, install, and use plugins.",
|
||||
)
|
||||
.size(13)
|
||||
.style(muted_style),
|
||||
Space::new().height(8),
|
||||
download,
|
||||
]
|
||||
.spacing(8)
|
||||
.padding(24)
|
||||
.width(Fill),
|
||||
)
|
||||
.center(Fill)
|
||||
.width(Fill)
|
||||
.height(Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{newest_update, registry_error_message, repository_display_name};
|
||||
|
|
|
|||
Loading…
Reference in a new issue