diff --git a/deps/shui/src/logseq/shui/silkhq.cljs b/deps/shui/src/logseq/shui/silkhq.cljs index 0c712b7143..3fa576015e 100644 --- a/deps/shui/src/logseq/shui/silkhq.cljs +++ b/deps/shui/src/logseq/shui/silkhq.cljs @@ -109,6 +109,18 @@ (def parallax-page-stack-topbar-title-outlet (silkhq-wrap "ParallaxPageStack.TopBarTitleOutlet")) (def parallax-page-stack-topbar-title-container (silkhq-wrap "ParallaxPageStack.TopBarTitleContainer")) +(def page (silkhq-wrap "Page.Root")) +(def page-portal (silkhq-wrap "Page.Portal")) +(def page-handle (silkhq-wrap "Page.Handle")) +(def page-content (silkhq-wrap "Page.Content")) +(def page-title (silkhq-wrap "Page.Title")) +(def page-description (silkhq-wrap "Page.Description")) +(def page-trigger (silkhq-wrap "Page.Trigger")) +(def page-outlet (silkhq-wrap "Page.Outlet")) +(def page-backdrop (silkhq-wrap "Page.Backdrop")) +(def page-view (silkhq-wrap "Page.View")) + + (def card-sheet (silkhq-wrap "CardSheet.Root")) (def card-sheet-portal (silkhq-wrap "CardSheet.Portal")) (def card-sheet-handle (silkhq-wrap "CardSheet.Handle")) diff --git a/packages/ui/src/silkhq/Page.css b/packages/ui/src/silkhq/Page.css new file mode 100644 index 0000000000..a533acb48a --- /dev/null +++ b/packages/ui/src/silkhq/Page.css @@ -0,0 +1,16 @@ +.Page-view { + /* SELF-LAYOUT */ + z-index: 1; + /* Adding 60px to make it fully visible below iOS Safari's bottom UI */ + height: calc(var(--silk-100-lvh-dvh-pct) + 60px); +} + +.Page-content { + /* SELF-LAYOUT */ + box-sizing: border-box; + width: 100%; + + /* APPEARANCE */ + background-color: white; + box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); +} diff --git a/packages/ui/src/silkhq/Page.tsx b/packages/ui/src/silkhq/Page.tsx new file mode 100644 index 0000000000..33a61e39e6 --- /dev/null +++ b/packages/ui/src/silkhq/Page.tsx @@ -0,0 +1,104 @@ +import React from 'react' +import { Sheet } from '@silk-hq/components' +import './Page.css' + +// ================================================================================================ +// Root +// ================================================================================================ + +type SheetRootProps = React.ComponentPropsWithoutRef; +type PageRootProps = Omit & { + license?: SheetRootProps['license']; +}; + +const PageRoot = React.forwardRef, PageRootProps>( + ({ children, ...restProps }, ref) => { + return ( + + {children} + + ) + } +) +PageRoot.displayName = 'Page.Root' + +// ================================================================================================ +// View +// ================================================================================================ + +const PageView = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ children, className, ...restProps }, ref) => { + return ( + + {children} + + ) +}) +PageView.displayName = 'Page.View' + +// ================================================================================================ +// Backdrop +// ================================================================================================ + +const PageBackdrop = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...restProps }, ref) => { + return ( + + ) +}) +PageBackdrop.displayName = 'Page.Backdrop' + +// ================================================================================================ +// Content +// ================================================================================================ + +const PageContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ children, className, ...restProps }, ref) => { + return ( + + {children} + + ) +}) +PageContent.displayName = 'Page.Content' + +// ================================================================================================ +// Unchanged Components +// ================================================================================================ + +const PagePortal = Sheet.Portal +const PageTrigger = Sheet.Trigger +const PageHandle = Sheet.Handle +const PageOutlet = Sheet.Outlet +const PageTitle = Sheet.Title +const PageDescription = Sheet.Description + +export const Page = { + Root: PageRoot, + Portal: PagePortal, + View: PageView, + Backdrop: PageBackdrop, + Content: PageContent, + Trigger: PageTrigger, + Handle: PageHandle, + Outlet: PageOutlet, + Title: PageTitle, + Description: PageDescription, +} diff --git a/packages/ui/src/silkhq/silkhq.ts b/packages/ui/src/silkhq/silkhq.ts index 47335630d2..47cf942bc5 100644 --- a/packages/ui/src/silkhq/silkhq.ts +++ b/packages/ui/src/silkhq/silkhq.ts @@ -7,6 +7,7 @@ import { SheetWithStacking, SheetWithStackingStack } from './SheetWithStacking' import { ParallaxPage, ParallaxPageStack } from './ParallaxPage' import { Toast } from './Toast' import { Card } from './Card' +import { Page } from './Page' declare global { var LSSilkhq: any @@ -18,7 +19,7 @@ const silkhq = { SheetWithStacking, SheetWithDetent, SheetWithStackingStack, ParallaxPage, ParallaxPageStack, - Toast, CardSheet: Card, + Toast, CardSheet: Card, Page } window.LSSilkhq = silkhq diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 82235b2254..b0aae85dcd 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -695,7 +695,6 @@ (rum/defcs ^:large-vars/cleanup-todo page-inner < (rum/local false ::mouse-down?) - (rum/local false ::hover?) "The inner div of page reference component page-name-in-block is the overridable name of the page (legacy) @@ -707,8 +706,7 @@ :or {with-parent? true} :as config} page-entity children label] - (let [*hover? (::hover? state) - *mouse-down? (::mouse-down? state) + (let [*mouse-down? (::mouse-down? state) tag? (:tag? config) page-name (when (:block/title page-entity) (util/page-name-sanity-lc (:block/title page-entity))) @@ -728,8 +726,6 @@ :draggable true :on-drag-start (fn [e] (editor-handler/block->data-transfer! page-name e true)) - :on-mouse-over #(reset! *hover? true) - :on-mouse-leave #(reset! *hover? false) :on-pointer-down (fn [^js e] (cond (util/link? (.-target e)) @@ -833,26 +829,18 @@ (let [*el-trigger (hooks/use-ref nil)] (hooks/use-effect! (fn [] - (when-not (state/editing?) - (when (true? visible?) - (shui/popup-show! - (hooks/deref *el-trigger) render - {:root-props {:onOpenChange (fn [v] (set-visible! v)) - :modal false} - :content-props {:class "ls-preview-popup" - :onInteractOutside (fn [^js e] (.preventDefault e)) - :onEscapeKeyDown (fn [^js e] - (when (state/editing?) - (.preventDefault e) - (some-> (hooks/deref *el-popup) (.focus))))} - :as-dropdown? false})) - - (when (false? visible?) - (shui/popup-hide!) - (when (state/get-edit-block) - (state/clear-edit!))) - (hooks/set-ref! *timer nil) - (hooks/set-ref! *timer1 nil)) + (when (true? visible?) + (shui/popup-show! + (hooks/deref *el-trigger) render + {:root-props {:onOpenChange (fn [v] (set-visible! v)) + :modal false} + :content-props {:class "ls-preview-popup" + :onInteractOutside (fn [^js e] (.preventDefault e)) + :onEscapeKeyDown (fn [^js e] + (when (state/editing?) + (.preventDefault e) + (some-> (hooks/deref *el-popup) (.focus))))} + :as-dropdown? false})) ;; teardown (fn [] @@ -862,17 +850,17 @@ [:span.preview-ref-link {:ref *el-trigger - :on-mouse-enter (fn [^js e] - (when (= (some-> (.-target e) (.closest ".preview-ref-link")) - (hooks/deref *el-trigger)) - (let [timer (hooks/deref *timer) - timer1 (hooks/deref *timer1)] - (when-not timer - (hooks/set-ref! *timer - (js/setTimeout #(set-visible! true) 1000))) - (when timer1 - (js/clearTimeout timer1) - (hooks/set-ref! *timer1 nil))))) + :on-mouse-move (fn [^js e] + (when (= (some-> (.-target e) (.closest ".preview-ref-link")) + (hooks/deref *el-trigger)) + (let [timer (hooks/deref *timer) + timer1 (hooks/deref *timer1)] + (when-not timer + (hooks/set-ref! *timer + (js/setTimeout #(set-visible! true) 1000))) + (when timer1 + (js/clearTimeout timer1) + (hooks/set-ref! *timer1 nil))))) :on-mouse-leave (fn [] (let [timer (hooks/deref *timer) timer1 (hooks/deref *timer1)] @@ -941,8 +929,7 @@ (if (boolean? in-popup?) (if (and (not (:preview? config)) (not in-popup?) - (or (not manual?) open?) - (not (state/editing?))) + (or (not manual?) open?)) (popup-preview-impl children {:visible? visible? :set-visible! set-visible! :*timer *timer :*timer1 *timer1 @@ -2655,13 +2642,7 @@ selection-blocks (state/get-selection-blocks) starting-block (state/get-selection-start-block-or-first) mobile-selection? (and (util/capacitor-new?) (seq selection-blocks)) - block-dom-element (util/rec-get-node target "ls-block") - cursor-range (if (util/ios?) - (:block/title block) - (some-> block-dom-element - (dom/by-class "block-content-inner") - first - util/caret-range))] + block-dom-element (util/rec-get-node target "ls-block")] (if mobile-selection? (let [ids (set (state/get-selection-block-ids))] @@ -2722,7 +2703,13 @@ (->> title (property-file/remove-built-in-properties-when-file-based (state/get-current-repo) format) - (drawer/remove-logbook)))] + (drawer/remove-logbook))) + cursor-range (if (util/ios?) + (:block/title block) + (some-> block-dom-element + (dom/by-class "block-content-inner") + first + util/caret-range))] (state/set-editing! edit-input-id content diff --git a/src/main/frontend/handler/db_based/rtc_flows.cljs b/src/main/frontend/handler/db_based/rtc_flows.cljs index 3378dd4cb8..12e15fb104 100644 --- a/src/main/frontend/handler/db_based/rtc_flows.cljs +++ b/src/main/frontend/handler/db_based/rtc_flows.cljs @@ -1,6 +1,7 @@ (ns frontend.handler.db-based.rtc-flows "Flows related to RTC" (:require [frontend.common.missionary :as c.m] + [frontend.common.thread-api :as thread-api :refer [def-thread-api]] [frontend.flows :as flows] [frontend.mobile.flows :as mobile-flows] [frontend.state :as state] @@ -94,6 +95,10 @@ conditions: (assert (some? repo)) (reset! *rtc-start-trigger repo)) +(def-thread-api :thread-api/rtc-start-request + [repo] + (trigger-rtc-start repo)) + (def ^:private document-visible&rtc-not-running-flow (m/ap (let [visibility (m/?< flows/document-visibility-state-flow)] diff --git a/src/main/frontend/log.cljs b/src/main/frontend/log.cljs index 409f0978ff..af8c4a5dfb 100644 --- a/src/main/frontend/log.cljs +++ b/src/main/frontend/log.cljs @@ -10,4 +10,4 @@ (if config/dev? (log/set-levels {:glogi/root :info}) - (log/set-levels {:glogi/root :warn})) + (log/set-levels {:glogi/root :info})) diff --git a/src/main/frontend/worker/db_worker.cljs b/src/main/frontend/worker/db_worker.cljs index 42ba275758..7b400f1808 100644 --- a/src/main/frontend/worker/db_worker.cljs +++ b/src/main/frontend/worker/db_worker.cljs @@ -33,6 +33,7 @@ [frontend.worker.thread-atom] [frontend.worker.util :as worker-util] [goog.object :as gobj] + [lambdaisland.glogi :as log] [lambdaisland.glogi.console :as glogi-console] [logseq.common.util :as common-util] [logseq.db :as ldb] @@ -841,6 +842,7 @@ (into {}) bean/->js)] (glogi-console/install!) + (log/set-levels {:glogi/root :info}) (check-worker-scope!) (outliner-register-op-handlers!) ( e ex-data :type)) + ;; if fail reason is websocket-timeout, try to restart rtc + (worker-state/ .as-left, .as-right { + @apply flex items-center col-span-2 gap-2; + + .ui__button { + @apply opacity-50 px-1; + + &:active { + @apply opacity-80; + } + } + } + + > .as-right { + @apply justify-end px-1; + } + + > .title { + @apply font-semibold overflow-hidden text-ellipsis whitespace-nowrap col-span-4 + block text-center; + } +} + +.app-silk-tabs { + @apply flex items-center h-[54px] border-t overflow-hidden + bg-gray-02 fixed left-0 bottom-0 w-full z-10 dark:bg-gray-01; + + bottom: 0; + + > .as-item { + @apply flex flex-1 flex-col items-center pb-1 transition-opacity; + @apply opacity-40 active:opacity-70; + + &.active { + @apply text-accent-10 opacity-100; + + > small { + @apply font-semibold; + } + } + + > small { + @apply text-[9px] -mt-2; + } + } +} \ No newline at end of file diff --git a/src/main/mobile/components/demos.cljs b/src/main/mobile/components/demos.cljs index 2637c66600..39efe4444a 100644 --- a/src/main/mobile/components/demos.cljs +++ b/src/main/mobile/components/demos.cljs @@ -1,6 +1,7 @@ (ns mobile.components.demos (:require [logseq.shui.ui :as shui] [rum.core :as rum] + [mobile.components.ui-silk :as ui-silk] [logseq.shui.silkhq :as silkhq])) (rum/defc depth-view-example @@ -43,66 +44,98 @@ (silkhq/stacking-sheet-portal (stacking-view-example {:nested? false}))))]))) +(rum/defc page-view-example + [] + (silkhq/page-portal + (silkhq/page-view + (silkhq/page-backdrop) + (silkhq/page-content + (silkhq/scroll {:as-child true} + (silkhq/scroll-view + {:class "h-full"} + (silkhq/scroll-content {:as-child true} + [:article.p-6 + (for [_ (range 80)] + [:h2.text-lg.font-medium.my-4.bg-green-100 + "inner page"])]))))))) + (rum/defc silkhq-demos-page [] (silkhq/depth-sheet-stack {:as-child true} (silkhq/depth-sheet-scenery-outlets - ;; as root page - (silkhq/parallax-page-stack {:as-child true} - (silkhq/parallax-page-stack-scenery-outlet {:as-child true} - (silkhq/scroll {:as-child true} - (silkhq/scroll-view - {:safeArea "none" - :pageScroll true - :nativePageScrollReplacement true} - (silkhq/scroll-content {:class "app-silk-index-scroll-content"} - [:div.app-silk-index-container - [:h2.text-xl.font-semibold.pt-4 "Silk sheets demos"] + (silkhq/scroll {:as-child true} + (silkhq/scroll-view + {:safeArea "none" + :pageScroll true + :nativePageScrollReplacement true} + (silkhq/scroll-content {:class "app-silk-index-scroll-content"} + [:div.app-silk-index-container + [:h2.text-xl.font-semibold.pt-2 "Silk sheets demos"] - ;; Bottom Sheet case - (silkhq/bottom-sheet - (silkhq/bottom-sheet-trigger - {:class "w-full"} - (shui/button {:variant :secondary :class "w-full"} "0. Static Bottom Sheet")) - (silkhq/bottom-sheet-portal - (silkhq/bottom-sheet-view - (silkhq/bottom-sheet-backdrop) - (silkhq/bottom-sheet-content - {:class "flex flex-col items-center p-2"} - (silkhq/bottom-sheet-handle) - [:div.py-60.flex - [:h1.my-4.text-2xl "hello silkhq"]])))) + ;; Bottom Sheet case + (silkhq/bottom-sheet + (silkhq/bottom-sheet-trigger + {:class "w-full"} + (shui/button {:variant :secondary :class "w-full"} "0. Static Bottom Sheet")) + (silkhq/bottom-sheet-portal + (silkhq/bottom-sheet-view + (silkhq/bottom-sheet-backdrop) + (silkhq/bottom-sheet-content + {:class "flex flex-col items-center p-2"} + (silkhq/bottom-sheet-handle) + [:div.py-60.flex + [:h1.my-4.text-2xl "hello silkhq"]])))) - ;; Detent Sheet case - (silkhq/detent-sheet - (silkhq/detent-sheet-trigger - {:class "w-full"} - (shui/button {:variant :secondary :class "w-full"} "1. Detent Bottom Sheet")) - (silkhq/detent-sheet-portal - (silkhq/detent-sheet-view - (silkhq/detent-sheet-backdrop) - (silkhq/detent-sheet-content - {:class "flex flex-col items-center p-2"} - (silkhq/detent-sheet-handle) - [:div.py-60.flex - [:h1.my-4.text-2xl "hello silkhq"]])))) + ;; Detent Sheet case + (silkhq/detent-sheet + (silkhq/detent-sheet-trigger + {:class "w-full"} + (shui/button {:variant :secondary :class "w-full"} "1. Detent Bottom Sheet")) + (silkhq/detent-sheet-portal + (silkhq/detent-sheet-view + (silkhq/detent-sheet-backdrop) + (silkhq/detent-sheet-content + {:class "flex flex-col items-center p-2"} + (silkhq/detent-sheet-handle) + [:div.py-60.flex + [:h1.my-4.text-2xl "hello silkhq"]])))) - ;; Depth Sheet case - (silkhq/depth-sheet - (silkhq/depth-sheet-trigger - {:class "w-full"} - (shui/button {:variant :secondary :class "w-full"} "2. Depth Bottom Sheet")) - (silkhq/depth-sheet-portal - (depth-view-example {:nested? false}))) + ;; Depth Sheet case + (silkhq/depth-sheet + (silkhq/depth-sheet-trigger + {:class "w-full"} + (shui/button {:variant :secondary :class "w-full"} "2. Depth Bottom Sheet")) + (silkhq/depth-sheet-portal + (depth-view-example {:nested? false}))) - ;; Stacking depth sheet case - (silkhq/stacking-sheet-stack - {:as-child true} - (silkhq/stacking-sheet - (silkhq/stacking-sheet-trigger - {:class "w-full"} - (shui/button {:variant :secondary :class "w-full"} "3. Stacking Bottom Sheet")) + ;; Stacking depth sheet case + (silkhq/stacking-sheet-stack + {:as-child true} + (silkhq/stacking-sheet + (silkhq/stacking-sheet-trigger + {:class "w-full"} + (shui/button {:variant :secondary :class "w-full"} "3. Stacking Bottom Sheet")) - (silkhq/stacking-sheet-portal - (stacking-view-example {:nested? false})))) - ])))))))) \ No newline at end of file + (silkhq/stacking-sheet-portal + (stacking-view-example {:nested? false})))) + + ;; parallax page + (silkhq/page + (silkhq/page-trigger + {:class "w-full"} + (shui/button {:variant :secondary :class "w-full"} "4. Single page")) + (page-view-example))]))) + + ;; app topbar + (ui-silk/app-silk-topbar + {:title "Silk Demos " + :left-render (shui/button {:variant :icon :size :sm} + (shui/tabler-icon "chevron-left" {:size 22})) + :right-render [:<> + (shui/button {:variant :icon :size :sm} + (shui/tabler-icon "plus" {:size 22})) + (shui/button {:variant :icon :size :sm} + (shui/tabler-icon "dots" {:size 22}))]}) + ;; app tabs + (ui-silk/app-silk-tabs) + ))) \ No newline at end of file diff --git a/src/main/mobile/components/ui_silk.cljs b/src/main/mobile/components/ui_silk.cljs new file mode 100644 index 0000000000..af17869077 --- /dev/null +++ b/src/main/mobile/components/ui_silk.cljs @@ -0,0 +1,35 @@ +(ns mobile.components.ui-silk + (:require [logseq.shui.ui :as shui] + [rum.core :as rum])) + +(rum/defc app-silk-topbar + [{:keys [left-render right-render title]}] + [:div.app-silk-topbar + [:div.as-left (if (fn? left-render) + (left-render) left-render)] + [:strong.title title] + [:div.as-right (if (fn? right-render) + (right-render) right-render)]]) + +(rum/defc app-silk-tabs [] + [:div.app-silk-tabs + [:span.as-item.active + (shui/button {:variant :icon} + (shui/tabler-icon "home" {:size 23})) + [:small "Journals"]] + [:span.as-item + (shui/button {:variant :icon} + (shui/tabler-icon "search" {:size 23})) + [:small "Search"]] + [:span.as-item + (shui/button {:variant :icon} + (shui/tabler-icon "plus" {:size 23})) + [:small "Quick add"]] + [:span.as-item + (shui/button {:variant :icon} + (shui/tabler-icon "settings" {:size 23})) + [:small "Settings"]] + [:span.as-item + (shui/button {:variant :icon} + (shui/tabler-icon "bug" {:size 23})) + [:small "Demos"]]]) \ No newline at end of file