|
@@ -1,12 +1,10 @@
|
|
|
(ns mobile.components.ui
|
|
|
"Mobile ui"
|
|
|
- (:require [cljs-bean.core :as bean]
|
|
|
- [logseq.shui.silkhq]
|
|
|
- [frontend.handler.notification :as notification]
|
|
|
+ (:require [frontend.handler.notification :as notification]
|
|
|
[frontend.rum :as r]
|
|
|
[frontend.state :as state]
|
|
|
- [logseq.shui.ui :as shui]
|
|
|
[logseq.shui.silkhq :as silkhq]
|
|
|
+ [logseq.shui.ui :as shui]
|
|
|
[medley.core :as medley]
|
|
|
[mobile.state :as mobile-state]
|
|
|
[react-transition-group :refer [CSSTransition TransitionGroup]]
|
|
@@ -27,10 +25,10 @@
|
|
|
[:div.ui__notifications-content
|
|
|
[:div.pointer-events-auto.notification-clear
|
|
|
(shui/button
|
|
|
- {:size :sm
|
|
|
- :on-click (fn []
|
|
|
- (notification/clear-all!))}
|
|
|
- "clear all")]])
|
|
|
+ {:size :sm
|
|
|
+ :on-click (fn []
|
|
|
+ (notification/clear-all!))}
|
|
|
+ "clear all")]])
|
|
|
|
|
|
(rum/defc notification-content
|
|
|
[state content status uid]
|
|
@@ -52,7 +50,7 @@
|
|
|
[:div.ui__notifications-content
|
|
|
{:style
|
|
|
(when (or (= state "exiting")
|
|
|
- (= state "exited"))
|
|
|
+ (= state "exited"))
|
|
|
{:z-index -1})}
|
|
|
[:div.max-w-sm.w-full.shadow-lg.rounded-lg.pointer-events-auto.notification-area
|
|
|
{:class (case state
|
|
@@ -74,36 +72,36 @@
|
|
|
[:div.flex-shrink-0.flex {:style {:margin-top -9
|
|
|
:margin-right -18}}
|
|
|
(shui/button
|
|
|
- {:variant :icon
|
|
|
- :size :sm
|
|
|
- :on-click (fn []
|
|
|
- (notification/clear! uid))}
|
|
|
- [:span {:slot "icon-only"}
|
|
|
- (shui/tabler-icon "x")])]]]]]])))
|
|
|
+ {:variant :icon
|
|
|
+ :size :sm
|
|
|
+ :on-click (fn []
|
|
|
+ (notification/clear! uid))}
|
|
|
+ [:span {:slot "icon-only"}
|
|
|
+ (shui/tabler-icon "x")])]]]]]])))
|
|
|
|
|
|
(rum/defc install-notifications < rum/reactive
|
|
|
[]
|
|
|
(let [contents (state/sub :notification/contents)]
|
|
|
(transition-group
|
|
|
- {:class-name "notifications ui__notifications"}
|
|
|
- (let [notifications
|
|
|
- (map (fn [el]
|
|
|
- (let [k (first el)
|
|
|
- v (second el)]
|
|
|
- (css-transition
|
|
|
- {:timeout 100
|
|
|
- :key (name k)}
|
|
|
- (fn [state]
|
|
|
- (notification-content state (:content v) (:status v) k)))))
|
|
|
- contents)
|
|
|
- clear-all (when (> (count contents) 3)
|
|
|
- (css-transition
|
|
|
- {:timeout 100
|
|
|
- :k "clear-all"}
|
|
|
- (fn [_state]
|
|
|
- (notification-clear-all))))
|
|
|
- items (if clear-all (cons clear-all notifications) notifications)]
|
|
|
- (doall items)))))
|
|
|
+ {:class-name "notifications ui__notifications"}
|
|
|
+ (let [notifications
|
|
|
+ (map (fn [el]
|
|
|
+ (let [k (first el)
|
|
|
+ v (second el)]
|
|
|
+ (css-transition
|
|
|
+ {:timeout 100
|
|
|
+ :key (name k)}
|
|
|
+ (fn [state]
|
|
|
+ (notification-content state (:content v) (:status v) k)))))
|
|
|
+ contents)
|
|
|
+ clear-all (when (> (count contents) 3)
|
|
|
+ (css-transition
|
|
|
+ {:timeout 100
|
|
|
+ :k "clear-all"}
|
|
|
+ (fn [_state]
|
|
|
+ (notification-clear-all))))
|
|
|
+ items (if clear-all (cons clear-all notifications) notifications)]
|
|
|
+ (doall items)))))
|
|
|
|
|
|
(defonce *modals (atom []))
|
|
|
(defonce ^:private *id (atom 0))
|
|
@@ -115,45 +113,45 @@
|
|
|
(case type
|
|
|
:action-sheet
|
|
|
(silkhq/bottom-sheet
|
|
|
- (merge modal-props
|
|
|
- {:presented true
|
|
|
- :onPresentedChange (fn [v?] (when (false? v?)
|
|
|
- (js/setTimeout #(close!) 200)))})
|
|
|
- (let [title (or title header content)
|
|
|
- content (for [{:keys [role text] :as item} buttons]
|
|
|
- [:a.as-item-btn
|
|
|
- {:data-role role
|
|
|
- :on-pointer-down (fn []
|
|
|
- (some-> on-action (apply [item]))
|
|
|
- (close!))}
|
|
|
- text])]
|
|
|
- (silkhq/bottom-sheet-portal
|
|
|
- (silkhq/bottom-sheet-view {:as-child true}
|
|
|
- (silkhq/bottom-sheet-backdrop)
|
|
|
- (silkhq/bottom-sheet-content
|
|
|
- [:div.flex.flex-col.items-center.gap-2.app-silk-action-sheet-modal-content
|
|
|
- (silkhq/bottom-sheet-handle {:class "my-2"})
|
|
|
- (some-> title (silkhq/bottom-sheet-title))
|
|
|
- [:div.as-list-container content]])))))
|
|
|
+ (merge modal-props
|
|
|
+ {:presented true
|
|
|
+ :onPresentedChange (fn [v?] (when (false? v?)
|
|
|
+ (js/setTimeout #(close!) 200)))})
|
|
|
+ (let [title (or title header content)
|
|
|
+ content (for [{:keys [role text] :as item} buttons]
|
|
|
+ [:a.as-item-btn
|
|
|
+ {:data-role role
|
|
|
+ :on-pointer-down (fn []
|
|
|
+ (some-> on-action (apply [item]))
|
|
|
+ (close!))}
|
|
|
+ text])]
|
|
|
+ (silkhq/bottom-sheet-portal
|
|
|
+ (silkhq/bottom-sheet-view {:as-child true}
|
|
|
+ (silkhq/bottom-sheet-backdrop)
|
|
|
+ (silkhq/bottom-sheet-content
|
|
|
+ [:div.flex.flex-col.items-center.gap-2.app-silk-action-sheet-modal-content
|
|
|
+ (silkhq/bottom-sheet-handle {:class "my-2"})
|
|
|
+ (some-> title (silkhq/bottom-sheet-title))
|
|
|
+ [:div.as-list-container content]])))))
|
|
|
|
|
|
;; default
|
|
|
(silkhq/bottom-sheet
|
|
|
- (merge modal-props
|
|
|
- {:presented true
|
|
|
- :onPresentedChange (fn [v?] (when (false? v?) (close!)))})
|
|
|
- (silkhq/bottom-sheet-portal
|
|
|
- (silkhq/bottom-sheet-view {:as-child true}
|
|
|
- (silkhq/bottom-sheet-backdrop)
|
|
|
- (silkhq/bottom-sheet-content
|
|
|
- (if (fn? content)
|
|
|
- (content) content))))))))
|
|
|
+ (merge modal-props
|
|
|
+ {:presented true
|
|
|
+ :onPresentedChange (fn [v?] (when (false? v?) (close!)))})
|
|
|
+ (silkhq/bottom-sheet-portal
|
|
|
+ (silkhq/bottom-sheet-view {:as-child true}
|
|
|
+ (silkhq/bottom-sheet-backdrop)
|
|
|
+ (silkhq/bottom-sheet-content
|
|
|
+ (if (fn? content)
|
|
|
+ (content) content))))))))
|
|
|
|
|
|
(defn get-modal
|
|
|
([] (some-> @*modals last))
|
|
|
([id]
|
|
|
(when id
|
|
|
(some->> (medley/indexed @*modals)
|
|
|
- (filter #(= id (:id (second %)))) (first)))))
|
|
|
+ (filter #(= id (:id (second %)))) (first)))))
|
|
|
|
|
|
(defn- upsert-modal!
|
|
|
[config]
|
|
@@ -170,11 +168,11 @@
|
|
|
(defn open-modal!
|
|
|
[content & {:keys [id type] :as props}]
|
|
|
(upsert-modal!
|
|
|
- (merge props
|
|
|
- {:id (or id (gen-id))
|
|
|
- :type (or type :default) ;; :alert :confirm :page
|
|
|
- :as-page? (= type :page)
|
|
|
- :content content})))
|
|
|
+ (merge props
|
|
|
+ {:id (or id (gen-id))
|
|
|
+ :type (or type :default) ;; :alert :confirm :page
|
|
|
+ :as-page? (= type :page)
|
|
|
+ :content content})))
|
|
|
|
|
|
(defn close-modal!
|
|
|
([] (some-> @*modals (last) :id (close-modal!)))
|
|
@@ -183,13 +181,13 @@
|
|
|
(defn open-popup!
|
|
|
[content-fn opts]
|
|
|
(mobile-state/set-popup!
|
|
|
- {:open? true
|
|
|
- :content-fn content-fn
|
|
|
- :opts opts}))
|
|
|
+ {:open? true
|
|
|
+ :content-fn content-fn
|
|
|
+ :opts opts}))
|
|
|
|
|
|
(defn close-popup! []
|
|
|
(some-> mobile-state/*popup-data
|
|
|
- (swap! assoc :open? false)))
|
|
|
+ (swap! assoc :open? false)))
|
|
|
|
|
|
(rum/defc install-modals []
|
|
|
(let [_ (r/use-atom *modals)]
|
|
@@ -198,4 +196,4 @@
|
|
|
:let [close! #(close-modal! id)
|
|
|
props' (assoc props :close! close!)]]
|
|
|
(x-modal props'
|
|
|
- (if (fn? content) (content props') content)))]))
|
|
|
+ (if (fn? content) (content props') content)))]))
|