mirror of
https://github.com/logseq/logseq.git
synced 2026-05-28 06:34:34 +00:00
feat(icon): :suppress mode for single-click hide of inherited icon
When an entity inherits a class default-icon but has no own override,
the trash button now writes `{:type :none}` directly with one click,
labelled "Hide inherited icon". Recovery is via the page-title Restore
affordance. Previously the trash button disappeared in this state,
leaving no way to opt out of inheritance.
Also fixes the icon-picker on-chosen wrapper to be variadic and forward
the action keyword — without this, asset-picker / text-picker delete
clicks silently dropped `:remove-entirely` and the entity wrote `nil`
instead of `:none`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -3970,9 +3970,12 @@
|
||||
(:db/id block)
|
||||
:logseq.property.class/default-icon
|
||||
icon-data)))
|
||||
;; del — branch on action keyword from the dropdown
|
||||
(case action
|
||||
:remove-entirely
|
||||
;; del — branch on action keyword from the dropdown.
|
||||
;; Use `cond` not `case` — CLJS `case` with keyword
|
||||
;; tests has shown subtle interaction bugs elsewhere
|
||||
;; in this file.
|
||||
(cond
|
||||
(= action :remove-entirely)
|
||||
;; Suppress inheritance: write the :none sentinel.
|
||||
;; Don't touch class default-icon — user wants
|
||||
;; "no icon" only on THIS entity.
|
||||
@@ -3981,6 +3984,7 @@
|
||||
:logseq.property/icon
|
||||
{:type :none})
|
||||
|
||||
:else
|
||||
;; :revert (from dropdown) or :remove / nil (from
|
||||
;; single-option immediate delete): retract the
|
||||
;; property so inheritance kicks in.
|
||||
|
||||
@@ -3901,6 +3901,14 @@
|
||||
:on-click #(reset-and-call :remove)}
|
||||
trash-icon)
|
||||
|
||||
(= delete-mode :suppress)
|
||||
(shui/button {:variant :outline :size :sm :data-action "del"
|
||||
:data-topbar-stop "trash"
|
||||
:title (t :icon/hide-inherited-icon)
|
||||
:aria-label (t :icon/hide-inherited-icon)
|
||||
:on-click #(reset-and-call :remove-entirely)}
|
||||
trash-icon)
|
||||
|
||||
(= delete-mode :two-option)
|
||||
(shui/dropdown-menu
|
||||
(shui/dropdown-menu-trigger
|
||||
@@ -6345,6 +6353,13 @@
|
||||
:on-click #(flag-delete-and-call :remove)}
|
||||
trash-icon)
|
||||
|
||||
(= delete-mode :suppress)
|
||||
(shui/button {:variant :outline :size :sm :data-action "del"
|
||||
:title (t :icon/hide-inherited-icon)
|
||||
:aria-label (t :icon/hide-inherited-icon)
|
||||
:on-click #(flag-delete-and-call :remove-entirely)}
|
||||
trash-icon)
|
||||
|
||||
(= delete-mode :two-option)
|
||||
(shui/dropdown-menu
|
||||
(shui/dropdown-menu-trigger
|
||||
@@ -6467,9 +6482,13 @@
|
||||
- `:remove` — entity has an own icon but no class inheritance source
|
||||
(or scope is class default-icon itself, which has no inheritance above
|
||||
it). Single-click retract.
|
||||
- `:hidden` — nothing to delete: entity has no own icon, OR entity is
|
||||
suppressed via `:type :none` (restoration lives in the page-title
|
||||
affordance, not here).
|
||||
- `:suppress` — entity has NO own icon but IS inheriting a class
|
||||
default-icon. Single-click writes `{:type :none}` to hide the
|
||||
inherited icon on this entity only. Recovery is via the page-title
|
||||
'Restore icon' affordance.
|
||||
- `:hidden` — nothing to act on: no own icon and no class default
|
||||
to suppress, OR entity is already suppressed via `:type :none`
|
||||
(restoration lives in the page-title affordance, not here).
|
||||
|
||||
Reads `:block/tags` + `:logseq.property.class/default-icon` so
|
||||
`db-mixins/query` registers them as render deps — the trash UI updates
|
||||
@@ -6491,13 +6510,20 @@
|
||||
;; sync-clear path at :3974-3980 already handles this as one action.
|
||||
synced-class? (and entity
|
||||
(ldb/class? entity)
|
||||
(= own (:logseq.property/icon entity))
|
||||
(= own (:logseq.property.class/default-icon entity)))]
|
||||
(cond
|
||||
none? :hidden
|
||||
(not has-real-own?) :hidden
|
||||
synced-class? :remove
|
||||
(or class-default tag-icon) :two-option
|
||||
:else :remove)))
|
||||
none? :hidden
|
||||
;; No own override but a class default-icon inherits in.
|
||||
;; Single-click "Hide inherited" writes :none sentinel.
|
||||
;; Tag-icon inheritance (a tag's OWN icon, not its class default)
|
||||
;; is intentionally excluded — that's not a "user opted into a
|
||||
;; default" relationship, so suppression has no clear UX story there.
|
||||
(and (not has-real-own?) class-default) :suppress
|
||||
(not has-real-own?) :hidden
|
||||
synced-class? :remove
|
||||
(or class-default tag-icon) :two-option
|
||||
:else :remove)))
|
||||
|
||||
(rum/defcs ^:large-vars/cleanup-todo icon-search < rum/reactive db-mixins/query
|
||||
(rum/local "" ::q)
|
||||
@@ -7168,6 +7194,17 @@
|
||||
:on-click #(reset-and-call :remove)}
|
||||
trash-icon)
|
||||
|
||||
(= delete-mode :suppress)
|
||||
;; Same trash glyph + single click as :remove, but the action
|
||||
;; is :remove-entirely (writes :none) to hide the inherited
|
||||
;; class default-icon on this entity. Tooltip differentiates.
|
||||
(shui/button {:variant :outline :size :sm :data-action "del"
|
||||
:data-topbar-stop "trash"
|
||||
:title (t :icon/hide-inherited-icon)
|
||||
:aria-label (t :icon/hide-inherited-icon)
|
||||
:on-click #(reset-and-call :remove-entirely)}
|
||||
trash-icon)
|
||||
|
||||
(= delete-mode :two-option)
|
||||
(shui/dropdown-menu
|
||||
(shui/dropdown-menu-trigger
|
||||
@@ -7404,7 +7441,7 @@
|
||||
(constantly [])
|
||||
(fn [{:keys [id]}]
|
||||
(icon-search
|
||||
{:on-chosen (fn [e icon-value keep-popup?]
|
||||
{:on-chosen (fn [e icon-value & [keep-popup?]]
|
||||
;; Set the optimistic local mirror BEFORE the
|
||||
;; async DB write fires. Lives at this
|
||||
;; outermost wrapper so every commit path
|
||||
@@ -7413,7 +7450,13 @@
|
||||
;; picker close commits) — they all funnel
|
||||
;; through this on-chosen.
|
||||
(set-pending-icon! icon-value)
|
||||
(on-chosen e icon-value)
|
||||
;; Forward the third arg as-is — it carries either
|
||||
;; `keep-popup?` (a bool, for in-picker partial
|
||||
;; commits) or an `action` keyword (for delete
|
||||
;; flows like :revert / :remove-entirely). The
|
||||
;; downstream on-chosen handles both shapes; we
|
||||
;; just need to NOT drop it.
|
||||
(on-chosen e icon-value keep-popup?)
|
||||
(when-not (true? keep-popup?) (shui/popup-hide! id)))
|
||||
:icon-value normalized-icon-value
|
||||
:page-title page-title
|
||||
|
||||
@@ -864,6 +864,7 @@
|
||||
|
||||
:icon/back "Back"
|
||||
:icon/emojis-count "Emojis ({1})"
|
||||
:icon/hide-inherited-icon "Hide inherited icon"
|
||||
:icon/icons-count "Icons ({1})"
|
||||
:icon/matched-count "Matched ({1})"
|
||||
:icon/remove-entirely "Remove entirely"
|
||||
|
||||
@@ -860,6 +860,7 @@
|
||||
|
||||
:icon/back "返回"
|
||||
:icon/emojis-count "表情符号({1})"
|
||||
:icon/hide-inherited-icon "隐藏继承的图标"
|
||||
:icon/icons-count "图标({1})"
|
||||
:icon/matched-count "匹配结果({1})"
|
||||
:icon/remove-entirely "完全移除"
|
||||
|
||||
Reference in New Issue
Block a user