0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-28 07:31:25 -05:00

Merge pull request #456 from penpot/bugfixing

Bugfixing
This commit is contained in:
Andrey Antukh 2021-01-14 14:45:54 +01:00 committed by GitHub
commit fd4c61ece7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 276 additions and 129 deletions

View file

@ -111,11 +111,6 @@
and (ppr.is_admin = true or
ppr.is_owner = true or
ppr.can_edit = true)
union
select p.*
from project as p
where p.team_id = uuid_nil()
and p.deleted_at is null
)
select distinct f.*
from file as f

View file

@ -120,9 +120,13 @@
extremities (mapcat calc-extremities
content
(d/concat [nil] content))]
(d/concat [nil] content))
(gpr/points->selrect extremities)))
selrect (gpr/points->selrect extremities)]
(-> selrect
(update :width #(if (mth/almost-zero? %) 1 %))
(update :height #(if (mth/almost-zero? %) 1 %)))))
(defn transform-content [content transform]
(let [set-tr (fn [params px py]

View file

@ -299,7 +299,7 @@
(let [frames (select-frames objects)]
(or
(->> frames
(d/seek #(gsh/has-point? % position))
(d/seek #(and position (gsh/has-point? % position)))
:id)
uuid/zero)))

View file

@ -18,7 +18,7 @@
}
},
"auth.create-demo-account" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:136", "src/app/main/ui/auth/login.cljs:160" ],
"used-in" : [ "src/app/main/ui/auth/login.cljs:160", "src/app/main/ui/auth/register.cljs:136" ],
"translations" : {
"en" : "Create demo account",
"fr" : "Vous voulez juste essayer?",
@ -27,7 +27,7 @@
}
},
"auth.create-demo-profile" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:133", "src/app/main/ui/auth/login.cljs:157" ],
"used-in" : [ "src/app/main/ui/auth/login.cljs:157", "src/app/main/ui/auth/register.cljs:133" ],
"translations" : {
"en" : "Just wanna try it?",
"fr" : "Vous voulez juste essayer?",
@ -45,7 +45,7 @@
}
},
"auth.email" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:101", "src/app/main/ui/auth/recovery_request.cljs:47", "src/app/main/ui/auth/login.cljs:99" ],
"used-in" : [ "src/app/main/ui/auth/login.cljs:99", "src/app/main/ui/auth/register.cljs:101", "src/app/main/ui/auth/recovery_request.cljs:47" ],
"translations" : {
"en" : "Email",
"fr" : "Adresse email",
@ -196,7 +196,7 @@
}
},
"auth.password" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:106", "src/app/main/ui/auth/login.cljs:106" ],
"used-in" : [ "src/app/main/ui/auth/login.cljs:106", "src/app/main/ui/auth/register.cljs:106" ],
"translations" : {
"en" : "Password",
"fr" : "Mot de passe",
@ -259,7 +259,7 @@
}
},
"auth.register-submit" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:110", "src/app/main/ui/auth/login.cljs:134" ],
"used-in" : [ "src/app/main/ui/auth/login.cljs:134", "src/app/main/ui/auth/register.cljs:110" ],
"translations" : {
"en" : "Create an account",
"fr" : "Créer un compte",
@ -674,7 +674,7 @@
}
},
"dashboard.update-settings" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:82", "src/app/main/ui/settings/password.cljs:96", "src/app/main/ui/settings/options.cljs:72" ],
"used-in" : [ "src/app/main/ui/settings/options.cljs:72", "src/app/main/ui/settings/profile.cljs:82", "src/app/main/ui/settings/password.cljs:96" ],
"translations" : {
"en" : "Update settings",
"fr" : "Mettre à jour les paramètres",
@ -796,7 +796,7 @@
}
},
"errors.clipboard-not-implemented" : {
"used-in" : [ "src/app/main/data/workspace.cljs:1248" ],
"used-in" : [ "src/app/main/data/workspace.cljs:1251" ],
"translations" : {
"en" : "Your browser cannot do this operation, please use Ctrl-V",
"fr" : "",
@ -805,7 +805,7 @@
}
},
"errors.email-already-exists" : {
"used-in" : [ "src/app/main/ui/auth/verify_token.cljs:80", "src/app/main/ui/settings/change_email.cljs:47" ],
"used-in" : [ "src/app/main/ui/settings/change_email.cljs:47", "src/app/main/ui/auth/verify_token.cljs:80" ],
"translations" : {
"en" : "Email already used",
"fr" : "Adresse e-mail déjà utilisée",
@ -832,7 +832,7 @@
}
},
"errors.generic" : {
"used-in" : [ "src/app/main/ui/auth/verify_token.cljs:89", "src/app/main/ui/settings/profile.cljs:42", "src/app/main/ui/settings/options.cljs:32" ],
"used-in" : [ "src/app/main/ui/settings/options.cljs:32", "src/app/main/ui/settings/profile.cljs:42", "src/app/main/ui/auth/verify_token.cljs:89" ],
"translations" : {
"en" : "Something wrong has happened.",
"fr" : "Quelque chose c'est mal passé.",
@ -859,7 +859,7 @@
}
},
"errors.media-type-mismatch" : {
"used-in" : [ "src/app/main/data/workspace/persistence.cljs:393", "src/app/main/data/media.cljs:78" ],
"used-in" : [ "src/app/main/data/media.cljs:78", "src/app/main/data/workspace/persistence.cljs:394" ],
"translations" : {
"en" : "Seems that the contents of the image does not match the file extension.",
"fr" : "",
@ -868,7 +868,7 @@
}
},
"errors.media-type-not-allowed" : {
"used-in" : [ "src/app/main/data/workspace/persistence.cljs:390", "src/app/main/data/media.cljs:75" ],
"used-in" : [ "src/app/main/data/media.cljs:75", "src/app/main/data/workspace/persistence.cljs:391" ],
"translations" : {
"en" : "Seems that this is not a valid image.",
"fr" : "",
@ -913,7 +913,7 @@
}
},
"errors.unexpected-error" : {
"used-in" : [ "src/app/main/data/media.cljs:81", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66", "src/app/main/ui/auth/register.cljs:45", "src/app/main/ui/handoff/exports.cljs:41" ],
"used-in" : [ "src/app/main/data/media.cljs:81", "src/app/main/ui/auth/register.cljs:45", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66", "src/app/main/ui/handoff/exports.cljs:41" ],
"translations" : {
"en" : "An unexpected error occurred.",
"fr" : "Une erreur inattendue c'est produite",
@ -1414,7 +1414,7 @@
}
},
"labels.delete" : {
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:177", "src/app/main/ui/dashboard/files.cljs:85" ],
"used-in" : [ "src/app/main/ui/dashboard/files.cljs:85", "src/app/main/ui/dashboard/grid.cljs:177" ],
"translations" : {
"en" : "Delete",
"fr" : "Supprimer",
@ -1478,7 +1478,7 @@
}
},
"labels.hide-resolved-comments" : {
"used-in" : [ "src/app/main/ui/workspace/comments.cljs:129", "src/app/main/ui/viewer/header.cljs:175" ],
"used-in" : [ "src/app/main/ui/viewer/header.cljs:175", "src/app/main/ui/workspace/comments.cljs:129" ],
"translations" : {
"en" : "Hide resolved comments",
"es" : "Ocultar comentarios resueltos"
@ -1503,7 +1503,7 @@
}
},
"labels.members" : {
"used-in" : [ "src/app/main/ui/dashboard/team.cljs:60", "src/app/main/ui/dashboard/team.cljs:66", "src/app/main/ui/dashboard/sidebar.cljs:297" ],
"used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:297", "src/app/main/ui/dashboard/team.cljs:60", "src/app/main/ui/dashboard/team.cljs:66" ],
"translations" : {
"en" : "Members",
"es" : "Integrantes"
@ -1615,7 +1615,7 @@
}
},
"labels.rename" : {
"used-in" : [ "src/app/main/ui/dashboard/grid.cljs:176", "src/app/main/ui/dashboard/sidebar.cljs:300", "src/app/main/ui/dashboard/files.cljs:84" ],
"used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:300", "src/app/main/ui/dashboard/files.cljs:84", "src/app/main/ui/dashboard/grid.cljs:176" ],
"translations" : {
"en" : "Rename",
"es" : "Renombrar"
@ -1629,7 +1629,7 @@
}
},
"labels.settings" : {
"used-in" : [ "src/app/main/ui/settings/sidebar.cljs:80", "src/app/main/ui/dashboard/team.cljs:61", "src/app/main/ui/dashboard/team.cljs:68", "src/app/main/ui/dashboard/sidebar.cljs:298" ],
"used-in" : [ "src/app/main/ui/settings/sidebar.cljs:80", "src/app/main/ui/dashboard/sidebar.cljs:298", "src/app/main/ui/dashboard/team.cljs:61", "src/app/main/ui/dashboard/team.cljs:68" ],
"translations" : {
"en" : "Settings",
"fr" : "Settings",
@ -1647,14 +1647,14 @@
}
},
"labels.show-all-comments" : {
"used-in" : [ "src/app/main/ui/workspace/comments.cljs:117", "src/app/main/ui/viewer/header.cljs:163" ],
"used-in" : [ "src/app/main/ui/viewer/header.cljs:163", "src/app/main/ui/workspace/comments.cljs:117" ],
"translations" : {
"en" : "Show all comments",
"es" : "Mostrar todos los comentarios"
}
},
"labels.show-your-comments" : {
"used-in" : [ "src/app/main/ui/workspace/comments.cljs:122", "src/app/main/ui/viewer/header.cljs:168" ],
"used-in" : [ "src/app/main/ui/viewer/header.cljs:168", "src/app/main/ui/workspace/comments.cljs:122" ],
"translations" : {
"en" : "Show only yours comments",
"es" : "Mostrar sólo tus comentarios"
@ -1684,7 +1684,7 @@
}
},
"media.loading" : {
"used-in" : [ "src/app/main/data/workspace/persistence.cljs:471", "src/app/main/data/workspace/persistence.cljs:526", "src/app/main/data/media.cljs:60" ],
"used-in" : [ "src/app/main/data/media.cljs:60", "src/app/main/data/workspace/persistence.cljs:472", "src/app/main/data/workspace/persistence.cljs:527" ],
"translations" : {
"en" : "Loading image...",
"fr" : "Chargement de l'image...",
@ -1851,6 +1851,18 @@
"es" : "Eliminando archivo"
}
},
"modals.delete-page.body" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/sitemap.cljs:45" ],
"translations" : {
"en" : "Are you sure you want to delete this page?"
}
},
"modals.delete-page.title" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/sitemap.cljs:44" ],
"translations" : {
"en" : "Delete page"
}
},
"modals.delete-project-confirm.accept" : {
"used-in" : [ "src/app/main/ui/dashboard/files.cljs:58" ],
"translations" : {
@ -2035,7 +2047,7 @@
}
},
"notifications.profile-saved" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:38", "src/app/main/ui/settings/options.cljs:36" ],
"used-in" : [ "src/app/main/ui/settings/options.cljs:36", "src/app/main/ui/settings/profile.cljs:38" ],
"translations" : {
"en" : "Profile saved successfully!",
"fr" : "Profil enregistré avec succès!",
@ -2044,7 +2056,7 @@
}
},
"notifications.validation-email-sent" : {
"used-in" : [ "src/app/main/ui/auth/register.cljs:54", "src/app/main/ui/settings/change_email.cljs:56" ],
"used-in" : [ "src/app/main/ui/settings/change_email.cljs:56", "src/app/main/ui/auth/register.cljs:54" ],
"translations" : {
"en" : "Verification email sent to %s. Check your email!",
"es" : "Verificación de email enviada a %s. Comprueba tu correo."
@ -2060,7 +2072,7 @@
}
},
"settings.multiple" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:154", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:161", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:170", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162", "src/app/main/ui/workspace/sidebar/options/shadow.cljs:213", "src/app/main/ui/workspace/sidebar/options/blur.cljs:79" ],
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/shadow.cljs:213", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:161", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:170", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162", "src/app/main/ui/workspace/sidebar/options/blur.cljs:79", "src/app/main/ui/workspace/sidebar/options/stroke.cljs:154" ],
"translations" : {
"en" : "Mixed",
"fr" : null,
@ -3239,7 +3251,7 @@
}
},
"workspace.options.position" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/measures.cljs:146", "src/app/main/ui/workspace/sidebar/options/frame.cljs:118" ],
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/frame.cljs:118", "src/app/main/ui/workspace/sidebar/options/measures.cljs:146" ],
"translations" : {
"en" : "Position",
"fr" : "Position",
@ -3372,7 +3384,7 @@
}
},
"workspace.options.size" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/measures.cljs:118", "src/app/main/ui/workspace/sidebar/options/frame.cljs:93" ],
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/frame.cljs:93", "src/app/main/ui/workspace/sidebar/options/measures.cljs:118" ],
"translations" : {
"en" : "Size",
"fr" : "Taille",
@ -3582,7 +3594,7 @@
}
},
"workspace.options.text-options.none" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/text.cljs:153", "src/app/main/ui/workspace/sidebar/options/typography.cljs:176" ],
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/typography.cljs:176", "src/app/main/ui/workspace/sidebar/options/text.cljs:153" ],
"translations" : {
"en" : "None",
"fr" : "Aucune",
@ -3721,7 +3733,7 @@
}
},
"workspace.shape.menu.detach-instance" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:79", "src/app/main/ui/workspace/sidebar/options/component.cljs:84", "src/app/main/ui/workspace/context_menu.cljs:163", "src/app/main/ui/workspace/context_menu.cljs:173" ],
"used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:163", "src/app/main/ui/workspace/context_menu.cljs:173", "src/app/main/ui/workspace/sidebar/options/component.cljs:79", "src/app/main/ui/workspace/sidebar/options/component.cljs:84" ],
"translations" : {
"en" : "Detach instance",
"es" : "Desacoplar instancia"
@ -3749,7 +3761,7 @@
}
},
"workspace.shape.menu.go-master" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:86", "src/app/main/ui/workspace/context_menu.cljs:177" ],
"used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:177", "src/app/main/ui/workspace/sidebar/options/component.cljs:86" ],
"translations" : {
"en" : "Go to master component file",
"es" : "Ir al archivo del componente maestro"
@ -3791,7 +3803,7 @@
}
},
"workspace.shape.menu.reset-overrides" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:80", "src/app/main/ui/workspace/sidebar/options/component.cljs:85", "src/app/main/ui/workspace/context_menu.cljs:165", "src/app/main/ui/workspace/context_menu.cljs:175" ],
"used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:165", "src/app/main/ui/workspace/context_menu.cljs:175", "src/app/main/ui/workspace/sidebar/options/component.cljs:80", "src/app/main/ui/workspace/sidebar/options/component.cljs:85" ],
"translations" : {
"en" : "Reset overrides",
"es" : "Deshacer modificaciones"
@ -3805,7 +3817,7 @@
}
},
"workspace.shape.menu.show-master" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:82", "src/app/main/ui/workspace/context_menu.cljs:169" ],
"used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:169", "src/app/main/ui/workspace/sidebar/options/component.cljs:82" ],
"translations" : {
"en" : "Show master component",
"es" : "Ver componente maestro"
@ -3833,7 +3845,7 @@
}
},
"workspace.shape.menu.update-master" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:81", "src/app/main/ui/workspace/context_menu.cljs:167" ],
"used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:167", "src/app/main/ui/workspace/sidebar/options/component.cljs:81" ],
"translations" : {
"en" : "Update master component",
"es" : "Actualizar componente maestro"
@ -3849,7 +3861,7 @@
"unused" : true
},
"workspace.sidebar.sitemap" : {
"used-in" : [ "src/app/main/ui/workspace/sidebar/sitemap.cljs:164" ],
"used-in" : [ "src/app/main/ui/workspace/sidebar/sitemap.cljs:171" ],
"translations" : {
"en" : "Pages",
"fr" : "Pages",

View file

@ -77,6 +77,7 @@
width: 100%;
border-radius: 2px;
border: 1px solid $color-gray-10;
max-height: 4rem;
}
.buttons {
@ -427,6 +428,11 @@
.section-title {
color: $color-black;
}
.threads {
max-height: 25rem;
overflow: auto;
}
}
.comment {

View file

@ -211,3 +211,7 @@ $width-settings-bar: 16rem;
}
}
}
.element-list.pages-list {
max-height: 10rem;
}

View file

@ -366,8 +366,8 @@
:else
(assoc local :vbox (assoc size
:x (- (:x srect) 40)
:y (- (:y srect) 40))))))
:x (+ (:x srect) (/ (- (:width srect) width) 2))
:y (+ (:y srect) (/ (- (:height srect) height) 2)))))))
(setup [state local]
(if (:vbox local)

View file

@ -16,6 +16,7 @@
[app.common.spec :as us]
[app.common.uuid :as uuid]
[app.main.worker :as uw]
[app.main.streams :as ms]
[app.util.logging :as log]
[app.util.timers :as ts]
[beicon.core :as rx]
@ -558,10 +559,12 @@
name (-> objects
(retrieve-used-names)
(generate-unique-name (:name attrs)))
position @ms/mouse-position
frame-id (if (= :frame (:type attrs))
uuid/zero
(or (:frame-id attrs)
(cp/frame-id-by-position objects attrs)))
(cp/frame-id-by-position objects position)))
[rchanges uchanges] (add-shape-changes page-id (assoc attrs
:id id

View file

@ -16,7 +16,9 @@
[app.common.geom.shapes.path :as gsp]
[app.main.streams :as ms]
[app.util.geom.path :as path]
[app.main.data.workspace.drawing.common :as common]))
[app.main.data.workspace.drawing.common :as common]
[app.main.data.workspace.common :as dwc]
[app.common.pages :as cp]))
(def simplify-tolerance 0.3)
@ -27,7 +29,6 @@
(assoc-in state [:workspace-drawing :object :initialized?] true))
(defn insert-point-segment [state point]
(let [segments (-> state
(get-in [:workspace-drawing :object :segments])
(or [])
@ -42,7 +43,17 @@
:selrect selrect
:points points))))
(defn setup-frame-curve []
(ptk/reify ::setup-frame-path
ptk/UpdateEvent
(update [_ state]
(let [objects (dwc/lookup-page-objects state)
content (get-in state [:workspace-drawing :object :content] [])
position (get-in content [0 :params] nil)
frame-id (cp/frame-id-by-position objects position)]
(-> state
(assoc-in [:workspace-drawing :object :frame-id] frame-id))))))
(defn curve-to-path [{:keys [segments] :as shape}]
(let [content (gsp/segments->content segments)
@ -74,5 +85,6 @@
(->> mouse
(rx/map (fn [pt] #(insert-point-segment % pt)))
(rx/take-until stoper))
(rx/of finish-drawing-curve
(rx/of (setup-frame-curve)
finish-drawing-curve
common/handle-finish-drawing))))))

View file

@ -24,7 +24,8 @@
[app.main.store :as st]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.drawing.common :as common]
[app.common.geom.shapes.path :as gsp]))
[app.common.geom.shapes.path :as gsp]
[app.common.pages :as cp]))
;; SCHEMAS
@ -269,8 +270,7 @@
fix-angle? shift?
{:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path id])
position (cond-> (gpt/point x y)
fix-angle? (position-fixed-angle last-point))
]
fix-angle? (position-fixed-angle last-point))]
(if-not (= last-point position)
(-> state
(assoc-in [:workspace-local :edit-path id :last-point] position)
@ -809,6 +809,18 @@
(assoc-in [:workspace-local :edit-path id :selected-handlers] #{})
(assoc-in [:workspace-local :edit-path id :selected-points] #{}))))))
(defn setup-frame-path []
(ptk/reify ::setup-frame-path
ptk/UpdateEvent
(update [_ state]
(let [objects (dwc/lookup-page-objects state)
content (get-in state [:workspace-drawing :object :content] [])
position (get-in content [0 :params] nil)
frame-id (cp/frame-id-by-position objects position)]
(-> state
(assoc-in [:workspace-drawing :object :frame-id] frame-id))))))
(defn handle-new-shape-result [shape-id]
(ptk/reify ::handle-new-shape-result
ptk/UpdateEvent
@ -821,7 +833,8 @@
ptk/WatchEvent
(watch [_ state stream]
(->> (rx/of common/handle-finish-drawing
(->> (rx/of (setup-frame-path)
common/handle-finish-drawing
(dwc/start-edition-mode shape-id)
(start-path-edit shape-id)
(change-edit-mode :draw))))))

View file

@ -77,8 +77,10 @@
(fn [event]
(when (kbd/ctrl? event)
(dom/prevent-default event)
(let [event (.getBrowserEvent ^js event)]
(if (pos? (.-deltaY ^js event))
(let [event (.getBrowserEvent ^js event)
delta (+ (.-deltaY ^js event)
(.-deltaX ^js event))]
(if (pos? delta)
(st/emit! dv/decrease-zoom)
(st/emit! dv/increase-zoom))))))

View file

@ -148,9 +148,9 @@
:else 0)
offset-y (cond (< rect-y (:y bounds)) (- (:y bounds) rect-y)
(> (+ rect-y distance-pill-height) (+ (:y bounds) bounds-height))
(- (+ (:y bounds) bounds-height) (+ rect-y distance-pill-height))
:else 0)]
(> (+ rect-y distance-pill-height) (+ (:y bounds) bounds-height))
(- (+ (:y bounds) bounds-height) (+ rect-y distance-pill-height (/ distance-pill-height 2)))
:else 0)]
[:g.distance-pill
[:rect {:x (+ rect-x offset-x)
:y (+ rect-y offset-y)
@ -197,7 +197,9 @@
h-lines (->> (calculate-distance-lines (:x1 from) (:x2 from) (:x1 to) (:x2 to))
(map (fn [[start end]] [start fixed-y end fixed-y])))
lines (d/concat [] v-lines h-lines)]
lines (d/concat [] v-lines h-lines)
distance-line-stroke (/ distance-line-stroke zoom)]
(for [[x1 y1 x2 y2] lines]
(let [center-x (+ x1 (/ (- x2 x1) 2))

View file

@ -34,7 +34,7 @@
(:fill-color-gradient shape)
(obj/merge! attrs #js {:fill (str/format "url(#%s)" fill-color-gradient-id)})
(or (:fill-color shape) (:fill-opacity shape))
(not (:fill-color-gradient shape))
(obj/merge! attrs #js {:fill (or (:fill-color shape) "transparent")
:fillOpacity (:fill-opacity shape nil)})

View file

@ -9,12 +9,12 @@
(ns app.main.ui.shapes.filters
(:require
[rumext.alpha :as mf]
[cuerdas.core :as str]
[app.util.color :as color]
[app.common.data :as d]
[app.common.math :as mth]
[app.common.uuid :as uuid]
[app.util.color :as color]
[cuerdas.core :as str]
[rumext.alpha :as mf]))
[app.common.uuid :as uuid]))
(defn get-filter-id []
(str "filter_" (uuid/next)))
@ -109,6 +109,49 @@
:in2 filter-in
:result filter-id}])
(defn filter-bounds [shape filter-entry]
(let [{:keys [x y width height]} (:selrect shape)
{:keys [offset-x offset-y blur spread] :or {offset-x 0 offset-y 0 blur 0 spread 0}} (:params filter-entry)
filter-x (min x (+ x offset-x (- spread) (- blur) -5))
filter-y (min y (+ y offset-y (- spread) (- blur) -5))
filter-width (+ width (mth/abs offset-x) (* spread 2) (* blur 2) 10)
filter-height (+ height (mth/abs offset-x) (* spread 2) (* blur 2) 10)]
{:x1 filter-x
:y1 filter-y
:x2 (+ filter-x filter-width)
:y2 (+ filter-y filter-height)}))
(defn get-filters-bounds
[shape filters blur-value]
(if (and (= :svg-raw (:type shape))
(not= :svg (get-in shape [:content :tag])))
;; When is a raw-svg but not the root we use the whole svg as bound for the filter. Is the maximum
;; we're allowed to display
{:x 0 :y 0 :width (get-in shape [:selrect :width]) :height (get-in shape [:selrect :height])}
;; Otherwise we calculate the bound
(let [filter-bounds (->> filters
(filter #(= :drop-shadow (:type %)))
(map (partial filter-bounds shape) ))
;; We add the selrect so the minimum size will be the selrect
filter-bounds (conj filter-bounds (:selrect shape))
x1 (apply min (map :x1 filter-bounds))
y1 (apply min (map :y1 filter-bounds))
x2 (apply max (map :x2 filter-bounds))
y2 (apply max (map :y2 filter-bounds))
x1 (- x1 (* blur-value 2))
x2 (+ x2 (* blur-value 2))
y1 (- y1 (* blur-value 2))
y2 (+ y2 (* blur-value 2))]
{:x x1
:y y1
:width (- x2 x1)
:height (- y2 y1)})))
(defn blur-filters [type value]
(->> [value]
(remove :hidden)
@ -154,11 +197,18 @@
(->> shape :blur (blur-filters :layer-blur)))
;; Adds the previous filter as `filter-in` parameter
filters (map #(assoc %1 :filter-in %2) filters (cons nil (map :id filters)))]
filters (map #(assoc %1 :filter-in %2) filters (cons nil (map :id filters)))
bounds (get-filters-bounds shape filters (or (-> shape :blur :value) 0))]
[:*
(when (> (count filters) 2)
[:filter {:id filter-id
:x (:x bounds)
:y (:y bounds)
:width (:width bounds)
:height (:height bounds)
:filterUnits "userSpaceOnUse"
:color-interpolation-filters "sRGB"}
(for [entry filters]

View file

@ -207,6 +207,7 @@
(let [on-click
(fn [event]
(dom/stop-propagation event)
(st/emit! (dcm/close-thread))
(let [mode (get state :interactions-mode)]
(when (= mode :show-on-click)
(st/emit! dv/flash-interactions))))
@ -215,15 +216,12 @@
(fn [event]
(when (kbd/ctrl? event)
(dom/prevent-default event)
(let [event (.getBrowserEvent ^js event)]
(if (pos? (.-deltaY ^js event))
(let [event (.getBrowserEvent ^js event)
delta (+ (.-deltaY ^js event) (.-deltaX ^js event))]
(if (pos? delta)
(st/emit! dv/decrease-zoom)
(st/emit! dv/increase-zoom)))))
on-click
(fn [event]
(st/emit! (dcm/close-thread)))
on-key-down
(fn [event]
(when (kbd/esc? event)
@ -234,8 +232,8 @@
;; bind with passive=false to allow the event to be cancelled
;; https://stackoverflow.com/a/57582286/3219895
(let [key1 (events/listen goog/global "wheel" on-mouse-wheel #js {"passive" false})
key2 (events/listen js/document "keydown" on-key-down)
key3 (events/listen js/document "click" on-click)]
key2 (events/listen js/window "keydown" on-key-down)
key3 (events/listen js/window "click" on-click)]
(fn []
(events/unlistenByKey key1)
(events/unlistenByKey key2)

View file

@ -103,9 +103,10 @@
(mf/use-callback
(mf/deps max-offset)
(fn [event]
(if (pos? (.. event -nativeEvent -deltaY))
(on-right-arrow-click event)
(on-left-arrow-click event))))
(let [delta (+ (.. event -nativeEvent -deltaY) (.. event -nativeEvent -deltaX))]
(if (pos? delta)
(on-right-arrow-click event)
(on-left-arrow-click event)))))
on-resize
(mf/use-callback

View file

@ -56,7 +56,7 @@
(dom/prevent-default event)
(when-not blocked
(cond
(or (not= 1 button) drawing? ctrl?)
(or (not= 1 button) drawing? ctrl? edition)
nil
(= type :frame)

View file

@ -10,6 +10,7 @@
(ns app.main.ui.workspace.frame-grid
(:require
[rumext.alpha :as mf]
[okulary.core :as l]
[app.main.refs :as refs]
[app.common.math :as mth]
[app.common.pages :as cp]
@ -81,10 +82,17 @@
:row [:> layout-grid props]))))))
(def shapes-moving-ref
(let [moving-shapes (fn [local]
(when (= :move (:transform local))
(:selected local)))]
(l/derived moving-shapes refs/workspace-local)))
(mf/defc frame-grid [{:keys [zoom]}]
(let [frames (mf/deref refs/workspace-frames)]
(let [frames (mf/deref refs/workspace-frames)
shapes-moving (mf/deref shapes-moving-ref)]
[:g.grid-display {:style {:pointer-events "none"}}
(for [frame frames]
(for [frame (->> frames (remove #(contains? shapes-moving (:id %))))]
[:& grid-display-frame {:key (str "grid-" (:id frame))
:zoom zoom
:frame (gsh/transform-shape frame)}])]))

View file

@ -42,6 +42,7 @@
(def selection-rect-color-normal "#1FDEA7")
(def selection-rect-color-component "#00E0FF")
(def selection-rect-width 1)
(def min-selrect-side 10)
(mf/defc selection-rect [{:keys [transform rect zoom color]}]
(when rect
@ -57,56 +58,65 @@
:fill "transparent"}}])))
(defn- handlers-for-selection [{:keys [x y width height]}]
[;; TOP-LEFT
{:type :rotation
:position :top-left
:props {:cx x :cy y}}
(->>
[ ;; TOP-LEFT
{:type :rotation
:position :top-left
:props {:cx x :cy y}}
{:type :resize-point
:position :top-left
:props {:cx x :cy y}}
(when (and (> width min-selrect-side) (> height min-selrect-side))
{:type :resize-point
:position :top-left
:props {:cx x :cy y}})
{:type :rotation
:position :top-right
:props {:cx (+ x width) :cy y}}
{:type :rotation
:position :top-right
:props {:cx (+ x width) :cy y}}
{:type :resize-point
:position :top-right
:props {:cx (+ x width) :cy y}}
(when (and (> width min-selrect-side) (> height min-selrect-side))
{:type :resize-point
:position :top-right
:props {:cx (+ x width) :cy y}})
{:type :rotation
:position :bottom-right
:props {:cx (+ x width) :cy (+ y height)}}
{:type :rotation
:position :bottom-right
:props {:cx (+ x width) :cy (+ y height)}}
{:type :resize-point
:position :bottom-right
:props {:cx (+ x width) :cy (+ y height)}}
(when (and (> width min-selrect-side) (> height min-selrect-side))
{:type :resize-point
:position :bottom-right
:props {:cx (+ x width) :cy (+ y height)}})
{:type :rotation
:position :bottom-left
:props {:cx x :cy (+ y height)}}
{:type :rotation
:position :bottom-left
:props {:cx x :cy (+ y height)}}
{:type :resize-point
:position :bottom-left
:props {:cx x :cy (+ y height)}}
(when (and (> width min-selrect-side) (> height min-selrect-side))
{:type :resize-point
:position :bottom-left
:props {:cx x :cy (+ y height)}})
{:type :resize-side
:position :top
:props {:x x :y y :length width :angle 0 }}
(when (> height min-selrect-side)
{:type :resize-side
:position :top
:props {:x x :y y :length width :angle 0 }})
{:type :resize-side
:position :right
:props {:x (+ x width) :y y :length height :angle 90 }}
(when (> width min-selrect-side)
{:type :resize-side
:position :right
:props {:x (+ x width) :y y :length height :angle 90 }})
{:type :resize-side
:position :bottom
:props {:x (+ x width) :y (+ y height) :length width :angle 180 }}
(when (> height min-selrect-side)
{:type :resize-side
:position :bottom
:props {:x (+ x width) :y (+ y height) :length width :angle 180 }})
{:type :resize-side
:position :left
:props {:x x :y (+ y height) :length height :angle 270 }}
(when (> width min-selrect-side)
{:type :resize-side
:position :left
:props {:x x :y (+ y height) :length height :angle 270 }})]
])
(filterv (comp not nil?))))
(mf/defc rotation-handler [{:keys [cx cy transform position rotation zoom on-rotate]}]
(let [size (/ rotation-handler-size zoom)
@ -171,6 +181,17 @@
:cursor (if (#{:left :right} position)
(cur/resize-ew rotation)
(cur/resize-ns rotation)) }}]))
(defn minimum-selrect [{:keys [x y width height] :as selrect}]
(let [final-width (max width min-selrect-side)
final-height (max height min-selrect-side)
offset-x (/ (- final-width width) 2)
offset-y (/ (- final-height height) 2)]
{:x (- x offset-x)
:y (- y offset-y)
:width final-width
:height final-height}))
(mf/defc controls
{::mf/wrap-props false}
[props]
@ -181,7 +202,8 @@
on-rotate (obj/get props "on-rotate")
current-transform (mf/deref refs/current-transform)
selrect (:selrect shape)
selrect (-> (:selrect shape)
minimum-selrect)
transform (geom/transform-matrix shape {:no-flip true})]
(when (not (#{:move :rotate} current-transform))

View file

@ -19,7 +19,7 @@
[app.main.ui.icons :as i]
[app.main.ui.keyboard :as kbd]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [t]]
[app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt]
[cuerdas.core :as str]
[okulary.core :as l]
@ -34,9 +34,17 @@
id (:id page)
delete-fn (mf/use-callback (mf/deps id) #(st/emit! (dw/delete-page id)))
on-delete (mf/use-callback (mf/deps id) #(modal/show! :confirm {:on-accept delete-fn}))
navigate-fn (mf/use-callback (mf/deps id) #(st/emit! (dw/go-to-page id)))
on-delete
(mf/use-callback
(mf/deps id)
(st/emitf (modal/show
{:type :confirm
:title (tr "modals.delete-page.title")
:message (tr "modals.delete-page.body")
:on-accept delete-fn})))
on-double-click
(mf/use-callback
(fn [event]
@ -136,7 +144,7 @@
(let [pages (:pages file)
deletable? (> (count pages) 1)
current-page-id (mf/use-ctx ctx/current-page-id)]
[:ul.element-list
[:ul.element-list.pages-list
[:& hooks/sortable-container {}
(for [[index page-id] (d/enumerate pages)]
[:& page-item-wrapper
@ -151,7 +159,6 @@
(mf/defc sitemap
[{:keys [layout] :as props}]
(let [create (mf/use-callback #(st/emit! dw/create-empty-page))
locale (mf/deref i18n/locale)
show-pages? (mf/use-state true)
file (mf/deref refs/workspace-file)
@ -161,7 +168,7 @@
[:div.sitemap.tool-window
[:div.tool-window-bar
[:span (t locale "workspace.sidebar.sitemap")]
[:span (tr "workspace.sidebar.sitemap")]
[:div.add-page {:on-click create} i/close]
[:div.collapse-pages {:on-click toggle-pages} i/arrow-slide]]

View file

@ -427,9 +427,11 @@
pos @ms/mouse-position]
(dom/prevent-default event)
(dom/stop-propagation event)
(if (pos? (.-deltaY event))
(st/emit! (dw/decrease-zoom pos))
(st/emit! (dw/increase-zoom pos))))
(let [delta (+ (.-deltaY ^js event)
(.-deltaX ^js event))]
(if (pos? delta)
(st/emit! (dw/decrease-zoom pos))
(st/emit! (dw/increase-zoom pos)))))
(.contains ^js node target)
(let [event (.getBrowserEvent ^js event)
@ -440,13 +442,18 @@
(= delta-mode WheelEvent.DeltaMode.LINE) 16
(= delta-mode WheelEvent.DeltaMode.PAGE) 100)
delta (* (.-deltaY ^js event) unit)
delta (/ delta @refs/selected-zoom)]
delta-y (-> (.-deltaY ^js event)
(* unit)
(/ @refs/selected-zoom))
delta-x (-> (.-deltaX ^js event)
(* unit)
(/ @refs/selected-zoom))]
(dom/prevent-default event)
(dom/stop-propagation event)
(if (kbd/shift? event)
(st/emit! (dw/update-viewport-position {:x #(+ % delta)}))
(st/emit! (dw/update-viewport-position {:y #(+ % delta)}))))))))
(st/emit! (dw/update-viewport-position {:x #(+ % delta-y)}))
(st/emit! (dw/update-viewport-position {:x #(+ % delta-x)
:y #(+ % delta-y)}))))))))
on-drag-enter
(mf/use-callback
@ -544,8 +551,9 @@
(fn [event]
;; We disable the paste just after mouse-up of a middle button so when panning won't
;; paste the content into the workspace
(when (not @disable-paste)
(st/emit! (dw/paste-from-event event)))))
(let [tag-name (-> event dom/get-target dom/get-tag-name)]
(when (and (not (#{"INPUT" "TEXTAREA"} tag-name)) (not @disable-paste))
(st/emit! (dw/paste-from-event event))))))
on-resize
(mf/use-callback