diff --git a/frontend/common/RunLocal.js b/frontend/common/RunLocal.js index b43e8b90b5..bf98227f80 100644 --- a/frontend/common/RunLocal.js +++ b/frontend/common/RunLocal.js @@ -38,11 +38,14 @@ export const start_local = async ({ setStatePromise, connect, launch_params }) = open_response = await fetch( with_token( - with_query_params(new URL("notebookupload", binder_session_url), { - name: new URLSearchParams(window.location.search).get("name"), - clear_frontmatter: "yesplease", - execution_allowed: "yepperz", - }) + with_query_params( + new URL(with_query_params("notebookupload", Object.fromEntries(binder_session_url.searchParams.entries())), binder_session_url), + { + name: new URLSearchParams(window.location.search).get("name"), + clear_frontmatter: "yesplease", + execution_allowed: "yepperz", + } + ) ), { method: "POST", @@ -60,7 +63,9 @@ export const start_local = async ({ setStatePromise, connect, launch_params }) = const edit_url = with_query_params(new URL("edit", binder_session_url), { id: new_notebook_id }) console.info("notebook_id:", new_notebook_id) - window.history.replaceState({}, "", edit_url) + if (!window.plutoDesktop) { + window.history.replaceState({}, "", edit_url) + } await setStatePromise( immer((/** @type {import("../components/Editor.js").EditorState} */ state) => { diff --git a/frontend/components/DesktopInterface.js b/frontend/components/DesktopInterface.js new file mode 100644 index 0000000000..8c38b79df3 --- /dev/null +++ b/frontend/components/DesktopInterface.js @@ -0,0 +1,6 @@ +export const open_from_path = () => { + window.plutoDesktop?.fileSystem.openNotebook("path") +} +export const open_from_url = (/** @type string */ url) => { + window.plutoDesktop?.fileSystem.openNotebook("url", url) +} diff --git a/frontend/components/Editor.js b/frontend/components/Editor.js index efe48c6bc5..7d390faba4 100644 --- a/frontend/components/Editor.js +++ b/frontend/components/Editor.js @@ -918,7 +918,7 @@ patch: ${JSON.stringify( this.connect = (/** @type {string | undefined} */ ws_address = undefined) => create_pluto_connection({ - ws_address: ws_address, + ws_address: ws_address ?? ws_address_from_base(this.props.launch_params.pluto_server_url ?? window.location.href), on_unrequested_update: on_update, on_connection_status: on_connection_status, on_reconnect: on_reconnect, @@ -1403,7 +1403,7 @@ patch: ${JSON.stringify( `article-view/${window?.version_info?.pluto ?? this.state.notebook.pluto_version ?? "unknown"}` ) } else { - this.connect(lp.pluto_server_url ? ws_address_from_base(lp.pluto_server_url) : undefined) + this.connect() } } diff --git a/frontend/components/FilePicker.js b/frontend/components/FilePicker.js index c44be28d57..af8dc754f7 100644 --- a/frontend/components/FilePicker.js +++ b/frontend/components/FilePicker.js @@ -48,12 +48,6 @@ const set_cm_value = (/** @type{EditorView} */ cm, /** @type {string} */ value, } } -const is_desktop = !!window.plutoDesktop - -if (is_desktop) { - console.log("Running in Desktop Environment! Found following properties/methods:", window.plutoDesktop) -} - /** * @param {{ * value: String, @@ -61,13 +55,12 @@ if (is_desktop) { * button_label: String, * placeholder: String, * on_submit: (new_path: String) => Promise, - * on_desktop_submit?: (loc?: string) => Promise, * client: import("../common/PlutoConnection.js").PlutoConnection, + * force_on_blur: Boolean * }} props */ -export const FilePicker = ({ value, suggest_new_file, button_label, placeholder, on_submit, on_desktop_submit, client }) => { +export const FilePicker = ({ value, suggest_new_file, button_label, placeholder, on_submit, client, force_on_blur = true }) => { const [is_button_disabled, set_is_button_disabled] = useState(true) - const [url_value, set_url_value] = useState("") const forced_value = useRef("") /** @type {import("../imports/Preact.js").Ref} */ const base = useRef(/** @type {any} */ (null)) @@ -89,18 +82,9 @@ export const FilePicker = ({ value, suggest_new_file, button_label, placeholder, const onSubmit = () => { const current_cm = cm.current if (current_cm == null) return - if (!is_desktop) { - const my_val = current_cm.state.doc.toString() - if (my_val === forced_value.current) { - suggest_not_tmp() - return true - } - } run(async () => { try { - if (is_desktop && on_desktop_submit) { - await on_desktop_submit((await guess_notebook_location(url_value)).path_or_url) - } else await on_submit(current_cm.state.doc.toString()) + await on_submit(current_cm.state.doc.toString()) current_cm.dom.blur() } catch (error) { set_cm_value(current_cm, forced_value.current, true) @@ -143,7 +127,7 @@ export const FilePicker = ({ value, suggest_new_file, button_label, placeholder, }, blur: (event, cm) => { setTimeout(() => { - if (!cm.hasFocus) { + if (!cm.hasFocus && force_on_blur) { set_cm_value(cm, forced_value.current, true) } }, 200) @@ -255,7 +239,7 @@ export const FilePicker = ({ value, suggest_new_file, button_label, placeholder, }) const current_cm = cm.current - if (!is_desktop) base.current.insertBefore(current_cm.dom, base.current.firstElementChild) + base.current.insertBefore(current_cm.dom, base.current.firstElementChild) // window.addEventListener("resize", () => { // if (!cm.current.hasFocus()) { // deselect(cm.current) @@ -271,24 +255,11 @@ export const FilePicker = ({ value, suggest_new_file, button_label, placeholder, } }) - return is_desktop - ? html`
- { - set_url_value(v.target.value) - }} - /> -
- -
-
` - : html` - - - - ` + return html` + + + + ` } const pathhints = diff --git a/frontend/components/welcome/Open.js b/frontend/components/welcome/Open.js index 3a0dc213c1..b2e18abad9 100644 --- a/frontend/components/welcome/Open.js +++ b/frontend/components/welcome/Open.js @@ -1,10 +1,12 @@ import _ from "../../imports/lodash.js" -import { html } from "../../imports/Preact.js" +import { html, useState } from "../../imports/Preact.js" import { FilePicker } from "../FilePicker.js" import { PasteHandler } from "../PasteHandler.js" import { guess_notebook_location } from "../../common/NotebookLocationFromURL.js" +import * as desktop from "../DesktopInterface.js" + /** * @param {{ * client: import("../../common/PlutoConnection.js").PlutoConnection?, @@ -21,40 +23,52 @@ export const Open = ({ client, connected, CustomPicker, show_samples, on_start_n window.location.href = (processed.type === "path" ? link_open_path : link_open_url)(processed.path_or_url) } - const desktop_on_open_path = async (_p) => { - window.plutoDesktop?.fileSystem.openNotebook("path") - } - - const desktop_on_open_url = async (url) => { - window.plutoDesktop?.fileSystem.openNotebook("url", url) - } - const picker = CustomPicker ?? { text: "Open a notebook", placeholder: "Enter path or URL...", } + // may be passed to FilePicker to disable autocomplete by spoofing an autocompletion client + const dummy_client = { + send: (_) => { + return { + then: (_) => {}, + } + }, + } + return html`<${PasteHandler} on_start_navigation=${on_start_navigation} />

${picker.text}

- <${FilePicker} - key=${picker.placeholder} - client=${client} - value="" - on_submit=${on_open_path} - on_desktop_submit=${desktop_on_open_path} - button_label=${window.plutoDesktop ? "Open File" : "Open"} - placeholder=${picker.placeholder} - /> - ${window.plutoDesktop && - html`<${FilePicker} - key=${picker.placeholder} - client=${client} - value="" - on_desktop_submit=${desktop_on_open_url} - button_label="Open from URL" - placeholder=${picker.placeholder} - />`} + ${window.plutoDesktop + ? html` +
+ +
— OR —
+
+ <${FilePicker} + key=${picker.placeholder} + client=${client} + value="" + on_submit=${desktop.open_from_url} + button_label=${"Open from URL"} + placeholder=${"Enter a URL..."} + client=${dummy_client} + force_on_blur=${false} + /> +
+
+ ` + : html` + <${FilePicker} + key=${picker.placeholder} + client=${client} + value="" + on_submit=${on_open_path} + button_label=${window.plutoDesktop ? "Open File" : "Open"} + placeholder=${picker.placeholder} + /> + `}
` } diff --git a/frontend/components/welcome/Welcome.js b/frontend/components/welcome/Welcome.js index f836db7cd7..a63ecb8842 100644 --- a/frontend/components/welcome/Welcome.js +++ b/frontend/components/welcome/Welcome.js @@ -94,6 +94,12 @@ export const Welcome = ({ launch_params }) => { }) }, []) + useEffect(() => { + window.plutoDesktop?.ipcRenderer.on("set-block-screen-text", (/** @type string */ block_screen_text) => { + set_block_screen_with_this_text(block_screen_text) + }) + }, []) + const { show_samples, CustomRecent, CustomPicker } = extended_components // When block_screen_with_this_text is null (default), all is fine. When it is a string, we show a big banner with that text, and disable all other UI. https://github.com/fonsp/Pluto.jl/pull/2292 diff --git a/frontend/editor.css b/frontend/editor.css index 0eeab2158f..c2048c9d86 100644 --- a/frontend/editor.css +++ b/frontend/editor.css @@ -690,8 +690,26 @@ nav#at_the_top img#logo-small { } } +.desktop_picker button { + background: var(--footer-filepicker-focus-color); + border-radius: 3px; + border: 2px solid var(--nav-filepicker-focus-color); + color: var(--white); + font-family: "Roboto Mono", monospace; + font-weight: 600; + font-size: 0.75rem; +} + +nav#at_the_top > div.desktop_picker_group span { + padding: 0 5px; + white-space: nowrap; + display: inline-flex; + align-items: center; + overflow: hidden; +} + nav#at_the_top > pluto-filepicker, -nav#at_the_top > div.desktop_picker { +nav#at_the_top > div.desktop_picker_group { width: 210px; flex-grow: 1; display: flex; @@ -699,7 +717,7 @@ nav#at_the_top > div.desktop_picker { } nav#at_the_top > pluto-filepicker .cm-editor, -nav#at_the_top > div.desktop_picker span { +div.desktop_picker_group span { height: calc(1rem + 4px + 4px + 4px); display: inline-block; min-width: 10rem; @@ -811,27 +829,27 @@ nav#at_the_top:after { @media (any-pointer: fine) { nav#at_the_top > pluto-filepicker .cm-editor, - nav#at_the_top > div.desktop_picker span { + nav#at_the_top > div.desktop_picker_group span { border: 2px solid transparent; border-right: none; transition: border 0.15s ease-in-out; } nav#at_the_top > pluto-filepicker button, - nav#at_the_top > div.desktop_picker button { + nav#at_the_top > div.desktop_picker_group button { opacity: 0; transition: opacity 0.15s ease-in-out; } header:hover > nav#at_the_top > pluto-filepicker .cm-editor, header:focus-within > nav#at_the_top > pluto-filepicker .cm-editor, - header:hover > nav#at_the_top > div.desktop_picker span, - header:focus-within > nav#at_the_top > div.desktop_picker span { + header:hover > nav#at_the_top > div.desktop_picker_group span, + header:focus-within > nav#at_the_top > div.desktop_picker_group span { border: 2px solid var(--footer-input-border-color); border-right: none; } header:hover > nav#at_the_top > pluto-filepicker button, header:focus-within > nav#at_the_top > pluto-filepicker button, - header:hover > nav#at_the_top > div.desktop_picker button, - header:focus-within > nav#at_the_top > div.desktop_picker button { + header:hover > nav#at_the_top > div.desktop_picker_group button, + header:focus-within > nav#at_the_top > div.desktop_picker_group button { opacity: 1; } } @@ -2854,6 +2872,7 @@ footer input { } header#pluto-nav pluto-filepicker button, +header#pluto-nav .desktop_picker_group button, footer button { margin: 0px; background: var(--footer-filepicker-focus-color); diff --git a/frontend/index.css b/frontend/index.css index 562862c38a..ca2998d616 100644 --- a/frontend/index.css +++ b/frontend/index.css @@ -119,7 +119,7 @@ pluto-filepicker .cm-scroller::-webkit-scrollbar { } pluto-filepicker button, -.desktop_picker button { +.desktop_picker_group button { margin: 0px; background: var(--footer-filepicker-focus-color); border-radius: 3px; @@ -132,22 +132,26 @@ pluto-filepicker button, } .desktop_picker_group { - display: inline-flex; + flex-grow: 1; + /* display: flex; */ + padding: 5px; } -.desktop_picker_group > input { - margin-left: 1em; -} - -.desktop_picker > button { +.desktop_picker_group > button { cursor: pointer; + padding: 8px; + width: 100%; } -.desktop_picker > button.full_width { - width: 100%; +.desktop_picker_group > .option_splitter { + color: gray; + font-style: italic; + text-align: center; + margin: 15px 0; + font-size: 10pt; } -pluto-filepicker button { +#new pluto-filepicker button { cursor: pointer; border-top-left-radius: 0; border-bottom-left-radius: 0; diff --git a/frontend/welcome.css b/frontend/welcome.css index 48de994018..d9469cd11c 100644 --- a/frontend/welcome.css +++ b/frontend/welcome.css @@ -91,19 +91,6 @@ section#open { /* border: 0.3rem solid #d6e0d8; */ } -#new.desktop_opener { - display: flex; - flex-direction: row; - align-content: center; - justify-content: space-around; - box-shadow: none; - position: relative; -} - -#new.desktop_opener .desktop_picker { - width: 100%; -} - section { display: flex; /* overflow: hidden; */ /* place-items: center; */ /* margin: 0rem 0rem; */