feat: add messages gap component (#13860)
|
@ -1,6 +1,7 @@
|
|||
module.exports = {
|
||||
bracketSpacing: false,
|
||||
jsxBracketSameLine: true,
|
||||
bracketSameLine: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'all',
|
||||
tabWidth: 4,
|
||||
};
|
|
@ -640,7 +640,7 @@ SPEC CHECKSUMS:
|
|||
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
|
||||
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
|
||||
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
|
||||
glog: 36ce0530c6d2c3a5a4326885ef4069564887a1db
|
||||
glog: 64a900d72fb14cd1b2cdf3b717a5555ceb889d49
|
||||
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
|
||||
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
|
||||
libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c
|
||||
|
|
After Width: | Height: | Size: 842 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,148 @@
|
|||
(ns quo2.components.messages-gap
|
||||
(:require
|
||||
[oops.core :refer [oget]]
|
||||
[quo.react-native :as rn]
|
||||
[quo.theme :as theme]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.ui.components.react :refer [pressable-class]]
|
||||
[status-im.utils.handlers :refer [>evt]]))
|
||||
|
||||
;;; helpers
|
||||
(def themes
|
||||
{:light {:icon colors/neutral-40
|
||||
:time colors/neutral-50
|
||||
:background colors/neutral-5}
|
||||
:dark {:icon colors/neutral-60
|
||||
:time colors/neutral-40
|
||||
:background colors/neutral-95}})
|
||||
|
||||
(defn get-color [key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
|
||||
(def ui-images
|
||||
{:light {:horizontal (js/require "../resources/images/ui/message-gap-hborder-light.png")
|
||||
:vertical (js/require "../resources/images/ui/message-gap-vborder-light.png")
|
||||
:circles (js/require "../resources/images/ui/message-gap-circle-bg-light.png")}
|
||||
:dark {:horizontal (js/require "../resources/images/ui/message-gap-hborder-dark.png")
|
||||
:circles (js/require "../resources/images/ui/message-gap-circle-bg-dark.png")}})
|
||||
|
||||
(defn get-image [key]
|
||||
(get-in ui-images [(theme/get-theme) key]))
|
||||
|
||||
;;; components
|
||||
;;;; borders
|
||||
(defn hborder [{:keys [type style]}]
|
||||
[rn/image {:source (get-image :horizontal)
|
||||
:resize-mode :repeat
|
||||
:style (merge {:position :absolute
|
||||
:left 0
|
||||
:padding-horizontal 4
|
||||
:overflow :hidden
|
||||
:width "110%"
|
||||
:height 8
|
||||
:margin-left -4}
|
||||
(if (= type :top)
|
||||
{:top 0}
|
||||
{:transform [{:rotateZ "180deg"}]
|
||||
:bottom 0})
|
||||
style)}])
|
||||
|
||||
(defn vborder [type body-height]
|
||||
(let [height @body-height
|
||||
img (get-image :vertical)]
|
||||
(when (and img height)
|
||||
[rn/image {:source img
|
||||
:resize-mode :repeat
|
||||
:style (merge
|
||||
{:position :absolute
|
||||
:top 4
|
||||
:height (- height 8)
|
||||
:width 4}
|
||||
(if (= type :left)
|
||||
{:left 0}
|
||||
{:transform [{:rotate "180deg"}]
|
||||
:right 0}))}])))
|
||||
|
||||
;;;; others
|
||||
(defn circle []
|
||||
[rn/view
|
||||
{:width 8
|
||||
:height 8
|
||||
:border-width 1
|
||||
:margin 4
|
||||
:flex 0
|
||||
:border-color (get-color :icon)
|
||||
:border-radius 50}])
|
||||
|
||||
(defn timestamp [str]
|
||||
[text/text {:size :label
|
||||
:style {:text-transform :none
|
||||
:color (get-color :time)}} str])
|
||||
|
||||
(defn info-button [on-press]
|
||||
[pressable-class
|
||||
{:on-press on-press}
|
||||
[icon/icon "message-gap-info" {:size 12 :no-color true :container-style {:padding 4}}]])
|
||||
|
||||
;;;; left/right
|
||||
(defn left []
|
||||
[rn/view {:flex 0
|
||||
:padding-left 11.5
|
||||
:margin-right 20.5
|
||||
:align-items :center
|
||||
:justify-content :space-between}
|
||||
[circle]
|
||||
[rn/image {:style {:flex 1} :source (get-image :circles) :resize-mode :repeat}]
|
||||
[circle]])
|
||||
|
||||
(defn right [timestamp-far timestamp-near chat-id gap-ids on-info-button-pressed]
|
||||
[rn/view {:flex 1}
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between
|
||||
:margin-right 2}
|
||||
[timestamp timestamp-far]
|
||||
(when on-info-button-pressed [info-button on-info-button-pressed])]
|
||||
|
||||
[pressable-class
|
||||
{:style {:flex 1 :margin-top 16 :margin-bottom 20}
|
||||
:on-press #(when (and chat-id gap-ids)
|
||||
(>evt [:chat.ui/fill-gaps chat-id gap-ids]))}
|
||||
[text/text
|
||||
(i18n/label :messages-gap-warning)]]
|
||||
|
||||
[timestamp timestamp-near]])
|
||||
|
||||
;;; main
|
||||
(defn messages-gap
|
||||
"if `gap-ids` and `chat-id` are provided, press the main text area to fetch messages
|
||||
if `on-info-button-pressed` fn is provided, the info button will show up and is pressable"
|
||||
[{:keys [timestamp-far
|
||||
timestamp-near
|
||||
gap-ids
|
||||
chat-id
|
||||
on-info-button-pressed
|
||||
style]}]
|
||||
(let [body-height (reagent/atom nil)]
|
||||
(fn []
|
||||
[rn/view
|
||||
{:on-layout #(reset! body-height (oget % "nativeEvent.layout.height"))
|
||||
:overflow :hidden}
|
||||
[hborder {:type :top}]
|
||||
[hborder {:type :bottom}]
|
||||
[rn/view (merge {:width "100%"
|
||||
:background-color (get-color :background)
|
||||
:flex-direction :row
|
||||
:padding 20
|
||||
:margin-vertical 4}
|
||||
style)
|
||||
|
||||
[left]
|
||||
[right timestamp-far timestamp-near chat-id gap-ids on-info-button-pressed]]
|
||||
[vborder :left body-height]
|
||||
[vborder :right body-height]])))
|
|
@ -1,28 +1,29 @@
|
|||
(ns quo2.screens.main
|
||||
(:require [quo.react-native :as rn]
|
||||
[quo.theme :as theme]
|
||||
(:require [quo.components.safe-area :as safe-area]
|
||||
[quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[quo2.screens.button :as button]
|
||||
[quo2.screens.token-overview :as token-overview]
|
||||
[quo2.screens.text :as text]
|
||||
[quo2.screens.tabs :as tabs]
|
||||
[quo2.screens.status-tags :as status-tags]
|
||||
[quo2.screens.context-tags :as context-tags]
|
||||
[quo2.screens.group-avatar :as group-avatar]
|
||||
[quo.react-native :as rn]
|
||||
[quo.theme :as theme]
|
||||
[quo2.screens.activity-logs :as activity-logs]
|
||||
[quo2.screens.token-tag :as token-tag]
|
||||
[quo2.screens.button :as button]
|
||||
[quo2.screens.community-card-view :as community-card]
|
||||
[quo2.screens.context-tags :as context-tags]
|
||||
[quo2.screens.counter :as counter]
|
||||
[quo2.screens.wallet-user-avatar :as wallet-user-avatar]
|
||||
[quo2.screens.filter-tags :as filter-tags]
|
||||
[quo2.screens.group-avatar :as group-avatar]
|
||||
[quo2.screens.icon-avatar :as icon-avatar]
|
||||
[quo2.screens.segmented :as segmented]
|
||||
[quo2.screens.info-message :as info-message]
|
||||
[quo2.screens.information-box :as information-box]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[quo2.screens.messages-gap :as messages-gap]
|
||||
[quo2.screens.permission-tag :as permission-tag]
|
||||
[quo2.screens.community-card-view :as community-card]
|
||||
[quo2.screens.filter-tags :as filter-tags]
|
||||
[quo.core :as quo]))
|
||||
[quo2.screens.segmented :as segmented]
|
||||
[quo2.screens.status-tags :as status-tags]
|
||||
[quo2.screens.tabs :as tabs]
|
||||
[quo2.screens.text :as text]
|
||||
[quo2.screens.token-overview :as token-overview]
|
||||
[quo2.screens.token-tag :as token-tag]
|
||||
[quo2.screens.wallet-user-avatar :as wallet-user-avatar]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(def screens [{:name :quo2-texts
|
||||
:insets {:top false}
|
||||
|
@ -42,6 +43,9 @@
|
|||
{:name :quo2-status-tags
|
||||
:insets {:top false}
|
||||
:component status-tags/preview-status-tags}
|
||||
{:name :quo2-messages-gap
|
||||
:insets {:top false}
|
||||
:component messages-gap/preview-messages-gap}
|
||||
{:name :quo2-context-tags
|
||||
:insets {:top false}
|
||||
:component context-tags/preview-context-tags}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
(ns quo2.screens.messages-gap
|
||||
(:require
|
||||
[quo.previews.preview :as preview]
|
||||
[quo.react-native :as rn]
|
||||
[quo2.components.messages-gap :as quo2]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def descriptor [{:label "Timestamp Far"
|
||||
:key :timestamp-far
|
||||
:type :text}
|
||||
{:label "Timestamp Near"
|
||||
:key :timestamp-near
|
||||
:type :text}])
|
||||
|
||||
(defn preview []
|
||||
(let [state (reagent/atom {:timestamp-far "Jan 8 · 09:12" :timestamp-near "Mar 8 · 22:42" :on-info-button-pressed identity})]
|
||||
(fn []
|
||||
[rn/view {:margin-bottom 50}
|
||||
[rn/view {:padding 16}
|
||||
[preview/customizer state descriptor]]
|
||||
[rn/view {:padding-vertical 60
|
||||
:align-items :center}
|
||||
[quo2/messages-gap @state]]])))
|
||||
|
||||
(defn preview-messages-gap []
|
||||
[rn/view {:flex 1}
|
||||
[rn/flat-list {:flex 1
|
||||
:header [preview]
|
||||
:key-fn str}]])
|
|
@ -11,6 +11,7 @@
|
|||
"account-color": "Account color",
|
||||
"anyone": "Anyone",
|
||||
"messages-from-contacts-only-subtitle": "Only people you added as contacts can start a new chat with you or invite you to a group",
|
||||
"messages-gap-warning": "Some messages might be missing",
|
||||
"accept-new-chats-from": "Accept new chats from",
|
||||
"account-name": "Account name",
|
||||
"account-settings": "Account settings",
|
||||
|
|