Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2025-02-06 09:38:47 +01:00
commit 33887711f7
17 changed files with 406 additions and 309 deletions

View file

@ -207,12 +207,14 @@
ptk/WatchEvent
(watch [_ state _]
(rx/concat
(rx/of
(rt/nav :workspace
(-> (rt/get-params state)
(assoc :page-id (:page-id thread))
(dissoc :comment-id))
{::rt/replace true}))
(if (some? thread)
(rx/of
(rt/nav :workspace
(-> (rt/get-params state)
(assoc :page-id (:page-id thread))
(dissoc :comment-id))
{::rt/replace true}))
(rx/empty))
(->> (rx/of
(dwd/select-for-drawing :comments)
(center-to-comment-thread thread)

View file

@ -476,3 +476,24 @@
(rx/take 1)
(rx/map #(svg/add-svg-shapes id % position {:ignore-selection? true
:change-selection? false}))))))
(defn create-svg-shape-with-images
[file-id id name svg-string position on-success on-error]
(ptk/reify ::create-svg-shape-with-images
ptk/WatchEvent
(watch [_ _ _]
(->> (svg->clj [name svg-string])
(rx/take 1)
(rx/mapcat
(fn [svg-data]
(->> (svg/upload-images svg-data file-id)
(rx/map #(assoc svg-data :image-data %)))))
(rx/map
(fn [svg-data]
(svg/add-svg-shapes
id
svg-data
position
{:ignore-selection? true
:change-selection? false})))
(rx/tap on-success)
(rx/catch on-error)))))

View file

@ -455,6 +455,7 @@
.modal-team-container-workspace {
top: $s-40;
z-index: $z-index-modal;
}
.modal-title {

View file

@ -35,6 +35,11 @@
project-id (:id project)
team-id (:team-id project)
shared? (:is-shared file)
persistence
(mf/deref refs/persistence)
persistence-status
(get persistence :status)
read-only? (mf/use-ctx ctx/workspace-read-only?)
@ -108,6 +113,25 @@
{:class (stl/css :file-name)
:title file-name
:on-double-click start-editing-name}
;;-- Persistende state widget
[:div {:class (case persistence-status
:pending (stl/css :status-notification :pending-status)
:saving (stl/css :status-notification :saving-status)
:saved (stl/css :status-notification :saved-status)
:error (stl/css :status-notification :error-status)
(stl/css :status-notification))
:title (case persistence-status
:pending (tr "workspace.header.saving")
:saving (tr "workspace.header.saving")
:saved (tr "workspace.header.saved")
:error (tr "workspace.header.save-error")
nil)}
(case persistence-status
:pending i/status-alert
:saving i/status-alert
:saved i/status-tick
:error i/status-wrong
nil)]
file-name])]
(when ^boolean shared?
[:span {:class (stl/css :shared-badge)} i/library])

View file

@ -49,6 +49,9 @@
@include smallTitleTipography;
text-transform: none;
color: var(--title-foreground-color-hover);
align-items: center;
display: flex;
flex-direction: row;
}
.file-name-input {
@ -80,3 +83,41 @@
width: $s-16;
}
}
.status-notification {
width: $s-6;
height: $s-6;
border-radius: 50%;
margin-right: $s-4;
flex-shrink: 0;
background-color: var(--status-widget-background-color-pending);
&.pending-status {
background-color: var(--status-widget-background-color-warning);
}
&.saving-status {
background-color: var(--status-widget-background-color-pending);
}
&.saved-status {
background-color: var(--status-widget-background-color-success);
animation: jump 0.3s ease-out;
}
&.error-status {
background-color: var(--status-widget-background-color-error);
}
}
@keyframes jump {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-4px);
}
100% {
transform: translateY(0);
}
}

View file

@ -19,6 +19,7 @@
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.context :as ctx]
[app.main.ui.dashboard.team]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.exports.assets :refer [export-progress-widget]]
[app.main.ui.formats :as fmt]
@ -32,39 +33,6 @@
(def ref:persistence-status
(l/derived :status refs/persistence))
;; --- Persistence state Widget
(mf/defc persistence-state-widget
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[]
(let [status (mf/deref ref:persistence-status)
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)]
(when-not workspace-read-only?
[:div {:class (stl/css :persistence-status-widget)}
(case status
:pending
[:div {:class (stl/css :status-icon :pending-status)
:title (tr "workspace.header.unsaved")}
i/status-alert]
:saving
[:div {:class (stl/css :status-icon :pending-status)
:title (tr "workspace.header.unsaved")}
i/status-alert]
:saved
[:div {:class (stl/css :status-icon :saved-status)
:title (tr "workspace.header.saved")}
i/status-tick]
:error
[:div {:class (stl/css :status-icon :error-status)
:title "There was an error saving the data. Please refresh if this persists."}
i/status-wrong]
nil)])))
;; --- Zoom Widget
(mf/defc zoom-widget-workspace
@ -216,8 +184,6 @@
[:div {:class (stl/css :users-section)}
[:& active-sessions]]
[:& persistence-state-widget]
[:& export-progress-widget]
[:div {:class (stl/css :separator)}]

View file

@ -320,7 +320,7 @@
(tr "workspace.assets.not-found")]])]))
(mf/defc file-library*
[{:keys [file is-local is-default-open? filters]}]
[{:keys [file is-local is-default-open filters]}]
(let [file-id (:id file)
file-name (:name file)
page-id (dm/get-in file [:data :pages 0])
@ -376,7 +376,7 @@
;; if the user has closed it specifically, respect that
false
(or force-lib-open?
(d/nilv (:library open-status) is-default-open?)))
(d/nilv (:library open-status) is-default-open)))
unselect-all
(mf/use-fn

View file

@ -346,6 +346,25 @@
(st/emit! (dwm/create-svg-shape id "svg" svg-string (gpt/point 0 0)))
(shape/shape-proxy plugin-id file-id page-id id))))
:createShapeFromSvgWithImages
(fn [svg-string]
(js/Promise.
(fn [resolve reject]
(cond
(or (not (string? svg-string)) (empty? svg-string))
(do
(u/display-not-valid :createShapeFromSvg "Svg not valid")
(reject "Svg not valid"))
:else
(let [id (uuid/next)
file-id (:current-file-id @st/state)
page-id (:current-page-id @st/state)]
(st/emit! (dwm/create-svg-shape-with-images
file-id id "svg" svg-string (gpt/point 0 0)
#(resolve (shape/shape-proxy plugin-id file-id page-id id))
reject)))))))
:createBoolean
(fn [bool-type shapes]
(let [bool-type (keyword bool-type)]

View file

@ -641,7 +641,7 @@
:else
(let [component (u/proxy->library-component self)
value (dm/str (d/nilv (:path component) "") " / " value)]
(st/emit! (dwl/rename-component id value)))))}
(st/emit! (dwl/rename-component-and-main-instance id value)))))}
:path
{:this true

View file

@ -211,7 +211,7 @@
(u/display-not-valid :name value)
:else
(st/emit! (dwsh/update-shapes [id] #(assoc % :name value))))))}
(st/emit! (dw/end-rename-shape id value)))))}
:blocked
{:this true
@ -515,9 +515,10 @@
;; not enumerable so there are no infinite loops
:enumerable false
:get (fn [self]
(let [shape (u/proxy->shape self)
parent-id (:parent-id shape)]
(shape-proxy plugin-id (obj/get self "$file") (obj/get self "$page") parent-id)))}
(let [shape (u/proxy->shape self)]
(when-not (cfh/root? shape)
(let [parent-id (:parent-id shape)]
(shape-proxy plugin-id (obj/get self "$file") (obj/get self "$page") parent-id)))))}
:parentX
{:this true

View file

@ -8,11 +8,11 @@
(:require
[app.common.data.macros :as dm]
[app.common.spec :as us]
[app.common.uuid :as uuid]
[app.main.data.workspace.viewport :as dwv]
[app.main.data.workspace.zoom :as dwz]
[app.main.store :as st]
[app.plugins.format :as format]
[app.plugins.shape :as ps]
[app.plugins.utils :as u]
[app.util.object :as obj]))
@ -85,12 +85,13 @@
:zoomIntoView
(fn [shapes]
(let [ids
(->> shapes
(map (fn [v]
(if (string? v)
(uuid/uuid v)
(uuid/uuid (obj/get v "x"))))))]
(st/emit! (dwz/fit-to-shapes ids))))))
(cond
(not (every? ps/shape-proxy? shapes))
(u/display-not-valid :zoomIntoView "Argument should be valid shapes")
:else
(let [ids (->> shapes
(map (fn [shape] (obj/get shape "$id"))))]
(st/emit! (dwz/fit-to-shapes ids)))))))