mirror of
https://github.com/penpot/penpot.git
synced 2026-06-15 11:52:10 +00:00
🐛 Fix openPage plugin problem (#10085)
* 🐛 Fix openPage plugin problem * 🐛 Make history safer for tests
This commit is contained in:
parent
c66ee1803f
commit
92cf0cda7b
@ -88,6 +88,7 @@
|
||||
(let [page (dsh/lookup-page state file-id page-id)
|
||||
uris (into #{} xf:collect-file-media (:objects page))]
|
||||
(rx/merge
|
||||
(rx/of (ptk/data-event ::initialized page-id))
|
||||
(->> (rx/from uris)
|
||||
(rx/map #(http/fetch-data-uri % false))
|
||||
(rx/ignore))
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
[app.main.data.workspace.colors :as dwc]
|
||||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.media :as dwm]
|
||||
[app.main.data.workspace.pages :as dwpg]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.variants :as dwv]
|
||||
[app.main.data.workspace.wasm-text :as dwwt]
|
||||
@ -54,7 +55,8 @@
|
||||
[app.util.object :as obj]
|
||||
[app.util.theme :as theme]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]))
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
;;
|
||||
;; PLUGINS PUBLIC API - The plugins will able to access this functions
|
||||
@ -571,11 +573,20 @@
|
||||
(let [id (cond
|
||||
(page/page-proxy? page) (obj/get page "$id")
|
||||
(string? page) (uuid/parse* page)
|
||||
:else nil)
|
||||
new-window (if (boolean? new-window) new-window false)]
|
||||
:else nil)]
|
||||
(if (nil? id)
|
||||
(u/not-valid plugin-id :openPage "Expected a Page object or a page UUID string")
|
||||
(st/emit! (dcm/go-to-workspace :page-id id ::rt/new-window new-window)))))
|
||||
(if (true? new-window)
|
||||
(do (st/emit! (dcm/go-to-workspace :page-id id ::rt/new-window true))
|
||||
(js/Promise.resolve nil))
|
||||
(js/Promise.
|
||||
(fn [resolve _]
|
||||
(->> st/stream
|
||||
(rx/filter (ptk/type? ::dwpg/initialized))
|
||||
(rx/filter #(= (deref %) id))
|
||||
(rx/take 1)
|
||||
(rx/subs! #(resolve nil)))
|
||||
(st/emit! (dcm/go-to-workspace :page-id id))))))))
|
||||
|
||||
:alignHorizontal
|
||||
(fn [shapes direction]
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.guides :as dwgu]
|
||||
[app.main.data.workspace.interactions :as dwi]
|
||||
[app.main.data.workspace.pages :as dwpg]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.router :as-alias rt]
|
||||
[app.main.store :as st]
|
||||
@ -32,7 +33,8 @@
|
||||
[app.plugins.utils :as u]
|
||||
[app.util.object :as obj]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]))
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(declare page-proxy)
|
||||
|
||||
@ -269,9 +271,19 @@
|
||||
(not (r/check-permission plugin-id "content:read"))
|
||||
(u/not-valid plugin-id :openPage "Plugin doesn't have 'content:read' permission")
|
||||
|
||||
(true? new-window)
|
||||
(do (st/emit! (dcm/go-to-workspace :page-id id ::rt/new-window true))
|
||||
(js/Promise.resolve nil))
|
||||
|
||||
:else
|
||||
(let [new-window (if (boolean? new-window) new-window false)]
|
||||
(st/emit! (dcm/go-to-workspace :page-id id ::rt/new-window new-window)))))
|
||||
(js/Promise.
|
||||
(fn [resolve _]
|
||||
(->> st/stream
|
||||
(rx/filter (ptk/type? ::dwpg/initialized))
|
||||
(rx/filter #(= (deref %) id))
|
||||
(rx/take 1)
|
||||
(rx/subs! #(resolve nil)))
|
||||
(st/emit! (dcm/go-to-workspace :page-id id))))))
|
||||
|
||||
:createFlow
|
||||
(fn [name frame]
|
||||
|
||||
@ -40,7 +40,7 @@ goog.scope(function() {
|
||||
};
|
||||
|
||||
self.set_token_BANG_ = function(instance, token) {
|
||||
instance.setToken(token);
|
||||
instance?.setToken(token);
|
||||
}
|
||||
|
||||
self.replace_token_BANG_ = function(instance, token) {
|
||||
|
||||
@ -842,10 +842,11 @@
|
||||
([uri name]
|
||||
(open-new-window uri name "noopener,noreferrer"))
|
||||
([uri name features]
|
||||
(when-let [new-window (.open js/window (str uri) name features)]
|
||||
(when (not= name "_blank")
|
||||
(when-let [location (.-location new-window)]
|
||||
(.reload location))))))
|
||||
(when (exists? js/window)
|
||||
(when-let [new-window (.open js/window (str uri) name features)]
|
||||
(when (not= name "_blank")
|
||||
(when-let [location (.-location new-window)]
|
||||
(.reload location)))))))
|
||||
|
||||
(defn browser-back
|
||||
[]
|
||||
|
||||
94
frontend/test/frontend_tests/plugins/page_test.cljs
Normal file
94
frontend/test/frontend_tests/plugins/page_test.cljs
Normal file
@ -0,0 +1,94 @@
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
||||
|
||||
(ns frontend-tests.plugins.page-test
|
||||
(:require
|
||||
[app.common.test-helpers.files :as cthf]
|
||||
[app.main.data.workspace.pages :as dwpg]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.api :as api]
|
||||
[app.util.object :as obj]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.helpers.state :as ths]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(defn- setup
|
||||
"Creates a file with two pages (page1 as current) and a plugin context."
|
||||
[]
|
||||
(let [file (-> (cthf/sample-file :file1 :page-label :page1)
|
||||
(cthf/add-sample-page :page2)
|
||||
(cthf/switch-to-page :page1))
|
||||
store (ths/setup-store file)
|
||||
_ (set! st/state store)
|
||||
_ (set! st/stream (ptk/input-stream store))
|
||||
context (api/create-context "00000000-0000-0000-0000-000000000000")]
|
||||
{:file file :store store :context context}))
|
||||
|
||||
(defn- mock-page-initialized
|
||||
"Simulates the two effects of initialize-page* without routing:
|
||||
updates current-page-id in state, then emits the public ::dwpg/initialized event."
|
||||
[store page-id]
|
||||
(ptk/emit! store #(assoc % :current-page-id page-id))
|
||||
(ptk/emit! store (ptk/data-event ::dwpg/initialized page-id)))
|
||||
|
||||
(t/deftest test-open-page-returns-promise
|
||||
(let [{:keys [context]} (setup)
|
||||
^js pages (.. context -currentFile -pages)
|
||||
^js page2 (aget pages 1)]
|
||||
(t/is (instance? js/Promise (.openPage context page2)))))
|
||||
|
||||
(t/deftest test-open-page-new-window-returns-promise
|
||||
(let [{:keys [context]} (setup)
|
||||
^js pages (.. context -currentFile -pages)
|
||||
^js page2 (aget pages 1)]
|
||||
(t/is (instance? js/Promise (.openPage context page2 true)))))
|
||||
|
||||
(t/deftest test-open-page-invalid-arg-returns-nil
|
||||
(let [{:keys [context]} (setup)]
|
||||
(t/is (nil? (.openPage context "not-a-page")))))
|
||||
|
||||
(t/deftest test-open-page-resolves-when-page-changes
|
||||
(t/async done
|
||||
(let [{:keys [store context]} (setup)
|
||||
^js pages (.. context -currentFile -pages)
|
||||
^js page2 (aget pages 1)
|
||||
page2-id (obj/get page2 "$id")]
|
||||
|
||||
(-> (.openPage context page2)
|
||||
(.then (fn [_]
|
||||
(t/is (= (:current-page-id @store) page2-id))
|
||||
(done))))
|
||||
|
||||
(mock-page-initialized store page2-id))))
|
||||
|
||||
(t/deftest test-open-page-does-not-resolve-for-wrong-page
|
||||
;; Promise should not resolve when a different page is initialized
|
||||
(t/async done
|
||||
(let [{:keys [store context]} (setup)
|
||||
^js pages (.. context -currentFile -pages)
|
||||
^js page1 (aget pages 0)
|
||||
^js page2 (aget pages 1)
|
||||
page1-id (obj/get page1 "$id")
|
||||
page2-id (obj/get page2 "$id")
|
||||
resolved? (atom false)]
|
||||
|
||||
(-> (.openPage context page2)
|
||||
(.then (fn [_] (reset! resolved? true))))
|
||||
|
||||
;; Initialize page1 (wrong page) — promise should not resolve
|
||||
(mock-page-initialized store page1-id)
|
||||
|
||||
;; Give microtasks a chance to run, then verify promise is still pending
|
||||
(js/setTimeout
|
||||
(fn []
|
||||
(t/is (not @resolved?))
|
||||
;; Now initialize the correct page and confirm it resolves
|
||||
(-> (.openPage context page2)
|
||||
(.then (fn [_]
|
||||
(t/is (= (:current-page-id @store) page2-id))
|
||||
(done))))
|
||||
(mock-page-initialized store page2-id))
|
||||
0))))
|
||||
@ -25,6 +25,7 @@
|
||||
[frontend-tests.logic.pasting-in-containers-test]
|
||||
[frontend-tests.main-errors-test]
|
||||
[frontend-tests.plugins.context-shapes-test]
|
||||
[frontend-tests.plugins.page-test]
|
||||
[frontend-tests.plugins.parser-test]
|
||||
[frontend-tests.plugins.tokens-test]
|
||||
[frontend-tests.plugins.utils-test]
|
||||
@ -74,6 +75,7 @@
|
||||
frontend-tests.logic.groups-test
|
||||
frontend-tests.logic.pasting-in-containers-test
|
||||
frontend-tests.plugins.context-shapes-test
|
||||
frontend-tests.plugins.page-test
|
||||
frontend-tests.plugins.parser-test
|
||||
frontend-tests.plugins.tokens-test
|
||||
frontend-tests.plugins.utils-test
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
- **plugins-runtime**: Added `version` field that returns the current version
|
||||
- **plugins-runtime**: Added optional parameter `throwOnError` to `penpot.ui.sendMessage` (default false, backwards-compatible)
|
||||
- **plugin-types**: Added a flags subcontexts with the flag `naturalChildrenOrdering`
|
||||
- **plugin-types**: `penpot.openPage()` now returns `Promise<void>` and should be awaited before performing operations on the new page
|
||||
- **plugin-types**: Fix penpot.openPage() to navigate in same tab by default
|
||||
- **plugin-types:** Change `LibraryComponent.isVariant()` return type to type guard `this is LibraryVariantComponent`
|
||||
- **plugin-types**: Added `createVariantFromComponents`
|
||||
|
||||
4
plugins/libs/plugin-types/index.d.ts
vendored
4
plugins/libs/plugin-types/index.d.ts
vendored
@ -1279,10 +1279,10 @@ export interface Context {
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* context.openPage(page);
|
||||
* await context.openPage(page);
|
||||
* ```
|
||||
*/
|
||||
openPage(page: Page | string, newWindow?: boolean): void;
|
||||
openPage(page: Page | string, newWindow?: boolean): Promise<void>;
|
||||
|
||||
/**
|
||||
* Aligning will move all the selected layers to a position relative to one
|
||||
|
||||
@ -348,9 +348,9 @@ export function createApi(
|
||||
return plugin.context.createPage();
|
||||
},
|
||||
|
||||
openPage(page: Page | string, newWindow?: boolean): void {
|
||||
openPage(page: Page | string, newWindow?: boolean): Promise<void> {
|
||||
checkPermission('content:read');
|
||||
plugin.context.openPage(page, newWindow ?? false);
|
||||
return plugin.context.openPage(page, newWindow ?? false);
|
||||
},
|
||||
|
||||
alignHorizontal(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user