Compare commits

...
Author SHA1 Message Date
Yevheniia Berdnyk 8e8ce65167 Temp check of mentions - to be deleted 2023-04-19 00:23:00 +03:00
Churikova Tetiana 8090f37bdd e2e: ??? 2023-04-18 11:05:59 +02:00
Churikova Tetiana 54825c6735 e2e: more fixes 2023-04-17 17:45:46 +02:00
Churikova Tetiana 030f17fc49 e2e: fix mentions 2023-04-17 15:26:56 +02:00
frank 2bc7d15683 fix [#15616] Sometimes mentions list does not appear after typing @ in chat input filed
https://github.com/status-im/status-go/compare/4cc53630...2eccfda1
2023-04-17 10:39:43 +08:00
Ibrahem Khalil 8af7011eb4 [15128] Introduce muting for a specific duration (#15253) 2023-04-16 17:31:39 +02:00
Parvesh Monu f6d74df80b fix pressing jump-to in the community screen is navigating to home screen instead of shell (#15647) 2023-04-14 13:20:06 +05:30
Ulises Manuel Cárdenas 6c1929096c Add blur variants for context-tag (#15621)
- Split context-tags into context-tag.view & context-tag.style namespaces
- Fix context-tags preview screen & add blur option
2023-04-13 12:07:05 -06:00
Icaro Motta d902fb10d1 New component - URL Preview List (#15620)
Implements the URL Preview List component.

Fixes https://github.com/status-im/status-mobile/issues/15617

Notes
=====

The quo component view implements the pattern recently described by @ulisesmac.
See his great explanation here:
https://github.com/status-im/status-mobile/issues/15552#issuecomment-1492590074.

Steps to test: Go to `Quo2.0 Preview` > `links` > `url-preview-list`
2023-04-13 10:52:27 -03:00
Siddarth Kumar 270f5ab258 Add `extractNativeLibs' flag to reduce apk size (#15638) 2023-04-13 17:21:58 +05:30
jakub c3e52dbf47 ios: provide explicit NODE_ARGS in Nix shell
Some users have reported local `make run-ios` failures with errors like:
```
Command PhaseScriptExecution failed with a nonzero exit code
```
Where the actual error that can be found in `ios/logs/react-native-xcode.log` is:
```
node: bad option: --openssl-legacy-provider
```
Caused by a flag we apply to our pinned Node.js `18.9.1` to fix:
```
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'
```
From: https://github.com/status-im/status-mobile/pull/15167

And the need for that should go away once we upgrade Node.js further.
But for now a decent fix is to not apply that flag directly in Xcode
config so as to avoid the `bad option` error when Xcode us called
outside of Nix context.

Fixes: https://github.com/status-im/status-mobile/issues/15631

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-04-13 09:36:42 +02:00
35 changed files with 640 additions and 359 deletions
+4 -1
View File
@@ -32,7 +32,10 @@
android:theme="@style/Theme.AppSplash"
android:name=".MainApplication"
android:largeHeap="true"
android:usesCleartextTraffic="true">
android:usesCleartextTraffic="true"
android:extractNativeLibs="true">
<!-- After upgrading Android Gradle Plugin to 4.2.0 and above we must get rid of `extractNativeLibs="true"`
and use`useLegacyPackaging` flag in our app's `build.gradle`-->
<meta-data android:name="commitHash" android:value="${commitHash}"/>
<activity
android:name=".MainActivity"
+2 -2
View File
@@ -544,7 +544,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/usr/bin/env sh";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\" --openssl-legacy-provider --max-old-space-size=16384 \"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
};
3AAD2AD524A3A60E0075D594 /* Bundle React Native code and images */ = {
isa = PBXShellScriptBuildPhase;
@@ -558,7 +558,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/usr/bin/env sh";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\" --openssl-legacy-provider --max-old-space-size=16384 \"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
};
3AAD2AD724A3A60E0075D594 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+2
View File
@@ -5,6 +5,8 @@ mkShell {
shellHook = ''
# Fix for ERR_OSSL_EVP_UNSUPPORTED error.
export NODE_OPTIONS="--openssl-legacy-provider";
# Same fix but for Xcode React Native script.
export NODE_ARGS="--openssl-legacy-provider --max-old-space-size=16384";
# Fix Xcode using system Node.js version.
export NODE_BINARY="${nodejs}/bin/node";
@@ -0,0 +1,49 @@
(ns quo2.components.links.url-preview-list.component-spec
(:require
[oops.core :as oops]
[quo2.components.links.url-preview-list.view :as view]
[test-helpers.component :as h]))
(def previews
(->> (range 3)
(map inc)
(mapv (fn [index]
{:title (str "Title " index)
:body (str "status.im." index)
:loading? false
:url (str "status.im." index)}))))
(h/describe "Links - URL Preview List"
(h/test "default render"
(h/render [view/view
{:data previews
:key-fn :url
:horizontal-spacing 10}])
(-> (count (h/query-all-by-label-text :url-preview))
(h/expect)
(.toEqual 3))
(-> (map #(oops/oget % "props.children")
(h/query-all-by-label-text :title))
(clj->js)
(h/expect)
(.toStrictEqual #js ["Title 1" "Title 2" "Title 3"])))
(h/test "on-clear event is individually handled by each preview"
(let [on-clear (h/mock-fn)]
(h/render [view/view
{:data previews
:key-fn :url
:on-clear on-clear}])
(h/fire-event :press (first (h/get-all-by-label-text :button-clear-preview)))
(h/fire-event :press (second (h/get-all-by-label-text :button-clear-preview)))
(h/was-called-times on-clear 2)))
(h/test "previews have separate loading states"
(h/render [view/view
{:data (assoc-in previews [1 :loading?] true)
:key-fn :url}])
(h/is-truthy (h/get-by-label-text :url-preview-loading))
(-> (count (h/query-all-by-label-text :url-preview))
(h/expect)
(.toEqual 2))))
@@ -0,0 +1,8 @@
(ns quo2.components.links.url-preview-list.style)
(def url-preview-gap 12)
(def url-preview-separator
{:width url-preview-gap
:padding-top 12
:padding-bottom 8})
@@ -0,0 +1,86 @@
(ns quo2.components.links.url-preview-list.view
(:require
[oops.core :as oops]
[quo2.components.links.url-preview-list.style :as style]
[quo2.components.links.url-preview.view :as url-preview]
[react-native.core :as rn]
[reagent.core :as reagent]))
(defn- use-scroll-to-last-item
[flat-list-ref item-count item-width]
(rn/use-effect
(fn []
(when (and (pos? item-count) (pos? item-width))
;; We use a delay because calling `scrollToOffset` without a delay does
;; nothing while the flatlist is still rendering its children.
;; `scrollToEnd` doesn't work because it positions the item off-center
;; and there's no argument to offset it.
(let [timer-id (js/setTimeout
(fn []
(when (and @flat-list-ref (pos? item-count))
(.scrollToOffset ^js @flat-list-ref
#js
{:animated true
:offset (* (+ item-width style/url-preview-gap)
(max 0 (dec item-count)))})))
25)]
(fn []
(js/clearTimeout timer-id)))))
[item-count item-width]))
(defn- separator
[]
[rn/view {:style style/url-preview-separator}])
(defn- item-component
[{:keys [title body loading? logo]} _ _
{:keys [width on-clear loading-message container-style]}]
[url-preview/view
{:logo logo
:title title
:body body
:loading? loading?
:loading-message loading-message
:on-clear on-clear
:container-style (merge container-style {:width width})}])
(defn- calculate-width
[preview-width horizontal-spacing ^js e]
(reset! preview-width
(- (oops/oget e "nativeEvent.layout.width")
(* 2 horizontal-spacing))))
(defn- view-component
[]
(let [preview-width (reagent/atom 0)
flat-list-ref (atom nil)]
(fn [{:keys [data key-fn horizontal-spacing on-clear loading-message
container-style container-style-item]}]
(use-scroll-to-last-item flat-list-ref (count data) @preview-width)
;; We need to use a wrapping view expanded to 100% instead of "flex 1",
;; otherwise `on-layout` will be triggered multiple times as the flat list
;; renders its children.
[rn/view
{:style (merge container-style {:width "100%"})
:accessibility-label :url-preview-list}
[rn/flat-list
{:ref #(reset! flat-list-ref %)
:key-fn key-fn
:on-layout #(calculate-width preview-width horizontal-spacing %)
:horizontal true
:deceleration-rate :fast
:on-scroll-to-index-failed identity
:content-container-style {:padding-horizontal horizontal-spacing}
:separator [separator]
:snap-to-interval (+ @preview-width style/url-preview-gap)
:shows-horizontal-scroll-indicator false
:data data
:render-fn item-component
:render-data {:width @preview-width
:on-clear on-clear
:loading-message loading-message
:container-style container-style-item}}]])))
(defn view
[props]
[:f> view-component props])
+11 -11
View File
@@ -30,18 +30,18 @@
(when on-press
{:on-press on-press}))
[rn/view
{:style {:flex-direction :row
:flex-grow 0
:flex-shrink 1
:padding-horizontal 20
:align-items :center}}
{:style (cond-> {:flex-direction :row
:flex-grow 0
:flex-shrink 1
:align-items :center}
icon (assoc :padding-horizontal 20))}
[rn/view
{:style {:width 20
:height 20
:align-items :center
:justify-content :center
:margin-right 12}}
[icons/icon icon {:color icon-color}]]
{:style (cond-> {:width 20
:height 20
:align-items :center
:justify-content :center}
icon (assoc :margin-right 12))}
(when icon [icons/icon icon {:color icon-color}])]
[rn/view
[text/text
{:weight :medium
@@ -0,0 +1,55 @@
(ns quo2.components.tags.context-tag.style
(:require [quo2.foundations.colors :as colors]))
(defn base-tag
[override-theme blur?]
{:border-radius 100
:padding-vertical 3
:flex-direction :row
:padding-right 8
:padding-left 8
:background-color (if blur?
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 override-theme)
(colors/theme-colors colors/neutral-10 colors/neutral-90 override-theme))})
(def context-tag-image
{:width 20
:border-radius 10
:background-color :white
:height 20})
(defn context-tag-icon-color
[blur?]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40)
(colors/theme-colors colors/neutral-50 colors/neutral-40)))
(def context-tag-text-container
{:align-items :center
:flex-direction :row})
(def audio-tag-container
{:padding-left 2
:padding-vertical 2})
(def audio-tag-icon-container
{:width 20
:height 20
:border-radius 10
:align-items :center
:justify-content :center
:background-color colors/primary-50})
(def audio-tag-icon-color colors/white)
(defn audio-tag-text-color
[override-theme]
(colors/theme-colors colors/neutral-100 colors/white override-theme))
(def community-tag
{:padding-vertical 2})
(defn community-tag-text
[override-theme]
{:margin-left 2
:color (colors/theme-colors colors/neutral-100 colors/white override-theme)})
@@ -0,0 +1,85 @@
(ns quo2.components.tags.context-tag.view
(:require [quo2.components.avatars.group-avatar :as group-avatar]
[quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[quo2.components.tags.context-tag.style :as style]
[react-native.core :as rn]))
(defn trim-public-key
[pk]
(str (subs pk 0 6) "..." (subs pk (- (count pk) 3))))
(defn base-tag
[{:keys [override-theme style blur?]} & children]
(into
[rn/view {:style (merge (style/base-tag override-theme blur?) style)}]
children))
(defn group-avatar-tag
[label opts]
[base-tag
(-> opts
(select-keys [:override-theme :style :blur?])
(assoc-in [:style :padding-left] 3)
(assoc-in [:style :padding-vertical] 2))
[group-avatar/group-avatar opts]
[text/text
{:weight :medium
:size :paragraph-2
:style (:text-style opts)}
(str " " label)]])
(defn public-key-tag
[params public-key]
[base-tag params
[text/text
{:weight :monospace
:size :paragraph-2}
(trim-public-key public-key)]])
(defn context-tag
[{:keys [text-style blur?] :as params} photo name channel-name]
(let [text-params {:weight :medium
:size :paragraph-2
:style (assoc text-style :justify-content :center)}]
[base-tag (assoc-in params [:style :padding-left] 3)
[rn/image
{:style style/context-tag-image
:source photo}]
[rn/view {:style style/context-tag-text-container}
[text/text text-params (str " " name)]
(when channel-name
[:<>
[icons/icon
:i/chevron-right
{:color (style/context-tag-icon-color blur?)
:size 16}]
[text/text text-params (str "# " channel-name)]])]]))
(defn user-avatar-tag
[params username photo]
[context-tag params {:uri photo} username])
(defn audio-tag
[duration params]
[base-tag (merge {:style style/audio-tag-container} params)
[rn/view {:style style/audio-tag-icon-container}
[icons/icon
:i/play
{:color style/audio-tag-icon-color
:size 12}]]
[text/text
{:weight :medium
:size :paragraph-2
:style {:margin-left 4
:color (style/audio-tag-text-color (:override-theme params))}}
duration]])
(defn community-tag
[avatar community-name {:keys [override-theme] :as params}]
[context-tag
(merge {:style style/community-tag
:text-style (style/community-tag-text override-theme)}
params)
avatar
community-name])
-126
View File
@@ -1,126 +0,0 @@
(ns quo2.components.tags.context-tags
(:require [quo2.components.avatars.group-avatar :as group-avatar]
[quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[quo2.theme :as quo2.theme]
[react-native.core :as rn]))
(defn trim-public-key
[pk]
(str (subs pk 0 6) "..." (subs pk (- (count pk) 3))))
(defn base-tag
[_ _]
(fn [{:keys [override-theme style]} & children]
(let [theme (or override-theme (quo2.theme/get-theme))]
(into
[rn/view
(merge
{:border-radius 100
:padding-vertical 3
:flex-direction :row
:padding-right 8
:padding-left 8
:background-color (if (= theme :light)
colors/neutral-10
colors/neutral-90)}
style)]
children))))
(defn group-avatar-tag
[_ _]
(fn [label opts]
[base-tag
(-> opts
(select-keys [:override-theme :style])
(assoc-in [:style :padding-left] 3)
(assoc-in [:style :padding-vertical] 2))
[group-avatar/group-avatar opts]
[text/text
{:weight :medium
:size :paragraph-2
:style (:text-style opts)}
(str " " label)]]))
(defn public-key-tag
[_ _]
(fn [params public-key]
[base-tag params
[text/text
{:weight :monospace
:size :paragraph-2}
(trim-public-key public-key)]]))
(defn context-tag
[_ _]
(fn [params photo name channel-name]
(let [text-style (:text-style params)
text-params {:weight :medium
:size :paragraph-2
:style (assoc text-style :justify-content :center)}
icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40)]
[base-tag (assoc-in params [:style :padding-left] 3)
[rn/image
{:style {:width 20
:border-radius 10
:background-color :white
:height 20}
:source photo}]
[rn/view
{:style {:align-items :center
:flex-direction :row}}
[text/text text-params (str " " name)]
(when channel-name
[:<>
[icons/icon
:i/chevron-right
{:color icon-color
:size 16}]
[text/text text-params (str "# " channel-name)]])]])))
(defn user-avatar-tag
[]
(fn [params username photo]
[context-tag params {:uri photo} username]))
(defn audio-tag
[duration params]
[base-tag
(merge
{:style {:padding-left 2
:padding-vertical 2}}
params)
[rn/view
{:width 20
:height 20
:border-radius 10
:align-items :center
:justify-content :center
:background-color colors/primary-50}
[icons/icon
:i/play
{:color colors/white
:size 12}]]
[text/text
{:weight :medium
:size :paragraph-2
:style {:margin-left 4
:color (colors/theme-colors
colors/neutral-100
colors/white
(:override-theme params))}}
duration]])
(defn community-tag
[avatar community-name params]
[context-tag
(merge
{:style {:padding-vertical 2}
:text-style {:margin-left 2
:color (colors/theme-colors
colors/neutral-100
colors/white
(:override-theme params))}}
params)
avatar community-name])
+8 -7
View File
@@ -34,6 +34,7 @@
quo2.components.inputs.title-input.view
quo2.components.inputs.profile-input.view
quo2.components.links.url-preview.view
quo2.components.links.url-preview-list.view
quo2.components.list-items.channel
quo2.components.list-items.menu-item
quo2.components.list-items.preview-list
@@ -66,7 +67,7 @@
quo2.components.tabs.segmented-tab
quo2.components.tabs.account-selector
quo2.components.tabs.tabs
quo2.components.tags.context-tags
quo2.components.tags.context-tag.view
quo2.components.tags.status-tags
quo2.components.tags.permission-tag
quo2.components.tags.tag
@@ -90,12 +91,11 @@
(def system-message quo2.components.messages.system-message/system-message)
(def reaction quo2.components.reactions.reaction/reaction)
(def add-reaction quo2.components.reactions.reaction/add-reaction)
(def user-avatar-tag quo2.components.tags.context-tags/user-avatar-tag)
(def context-tag quo2.components.tags.context-tags/context-tag)
(def group-avatar-tag quo2.components.tags.context-tags/group-avatar-tag)
(def audio-tag quo2.components.tags.context-tags/audio-tag)
(def community-tag quo2.components.tags.context-tags/community-tag)
(def user-avatar-tag quo2.components.tags.context-tag.view/user-avatar-tag)
(def context-tag quo2.components.tags.context-tag.view/context-tag)
(def group-avatar-tag quo2.components.tags.context-tag.view/group-avatar-tag)
(def audio-tag quo2.components.tags.context-tag.view/audio-tag)
(def community-tag quo2.components.tags.context-tag.view/community-tag)
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
(def page-nav quo2.components.navigation.page-nav/page-nav)
(def disclaimer quo2.components.selectors.disclaimer.view/view)
@@ -199,3 +199,4 @@
;;;; LINKS
(def url-preview quo2.components.links.url-preview.view/view)
(def url-preview-list quo2.components.links.url-preview-list.view/view)
+1
View File
@@ -13,6 +13,7 @@
[quo2.components.inputs.input.component-spec]
[quo2.components.inputs.profile-input.component-spec]
[quo2.components.inputs.title-input.component-spec]
[quo2.components.links.url-preview-list.component-spec]
[quo2.components.links.url-preview.component-spec]
[quo2.components.markdown.--tests--.text-component-spec]
[quo2.components.onboarding.small-option-card.component-spec]
+22 -64
View File
@@ -4,7 +4,6 @@
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[utils.re-frame :as rf]
[status-im.utils.platform :as platform]
[taoensso.timbre :as log]
[status-im.native-module.core :as status]))
@@ -91,38 +90,29 @@
(assoc-in [:chats/mentions chat-id :mentions] state)
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments))}))
(rf/defn on-text-input
{:events [:mention/on-text-input]}
[{:keys [db]} {:keys [previous-text start end] :as args}]
(let [previous-text
;; NOTE(rasom): on iOS `previous-text` contains entire input's text. To
;; get only removed part of text we have cut it.
(if platform/android?
previous-text
(subs previous-text start end))
chat-id (:current-chat-id db)
state (merge args {:previous-text previous-text})
state (set/rename-keys state
{:previous-text :PreviousText
:new-text :NewText
:start :Start
:end :End})
params [chat-id state]
method "wakuext_chatMentionOnTextInput"]
(log/debug "[mentions] on-text-input" {:params params})
(rf/defn on-change-text
{:events [:mention/on-change-text]}
[{:keys [db]} text]
(let [chat-id (:current-chat-id db)
params [chat-id text]
method "wakuext_chatMentionOnChangeText"]
(log/debug "[mentions] on-change-text" {:params params})
{:json-rpc/call [{:method method
:params [chat-id state]
:on-success #(rf/dispatch [:mention/on-text-input-success %])
:params params
:on-success #(rf/dispatch [:mention/on-change-text-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
(rf/defn on-text-input-success
{:events [:mention/on-text-input-success]}
(rf/defn on-change-text-success
{:events [:mention/on-change-text-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-text-input-success" {:result result})
(let [{:keys [state chat-id]} (transfer-mention-result result)]
{:db (assoc-in db [:chats/mentions chat-id :mentions] state)}))
(let [{:keys [state chat-id mentionable-users input-segments]} (transfer-mention-result result)]
{:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] mentionable-users)
(assoc-in [:chats/mentions chat-id :mentions] state)
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments))}))
(rf/defn recheck-at-idxs
[{:keys [db]} public-key]
@@ -175,16 +165,6 @@
;; programmatic change. By calling `reset-text-input-cursor` we force the
;; keyboard's cursor position to be changed before the next input.
(reset-text-input-cursor text-input-ref cursor)
;; NOTE(roman): on-text-input event is not dispatched when we change input
;; programmatically, so we have to call `on-text-input` manually
(on-text-input
(let [match-len (count match)
start (inc at-sign-idx)
end (+ start match-len)]
{:new-text match
:previous-text searched-text
:start start
:end end}))
(recheck-at-idxs public-key))))
(rf/defn clear-suggestions
@@ -220,7 +200,7 @@
(when text
(log/debug "[mentions] check-selection" {:params params})
{:json-rpc/call [{:method method
:params [chat-id text start end]
:params params
:on-success #(rf/dispatch [:mention/on-handle-selection-change-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
@@ -230,8 +210,11 @@
{:events [:mention/on-handle-selection-change-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-check-selection-success" {:result result})
(let [{:keys [state chat-id]} (transfer-mention-result result)]
{:db (assoc-in db [:chats/mentions chat-id :mentions] (rename-state state))}))
(let [{:keys [state chat-id mentionable-users input-segments]} (transfer-mention-result result)]
{:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] mentionable-users)
(assoc-in [:chats/mentions chat-id :mentions] state)
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments))}))
(re-frame/reg-fx
::reset-text-input-cursor
@@ -240,28 +223,3 @@
(status/reset-keyboard-input
(rn/find-node-handle (react/current-ref ref))
cursor))))
(rf/defn calculate-suggestions
{:events [:mention/calculate-suggestions]}
[{:keys [db]}]
(let [chat-id (:current-chat-id db)
text (get-in db [:chat/inputs chat-id :input-text])
params [chat-id text]
method "wakuext_chatMentionCalculateSuggestions"]
(log/debug "[mentions] calculate-suggestions" {:params params})
{:json-rpc/call [{:method method
:params [chat-id text]
:on-success #(rf/dispatch [:mention/on-calculate-suggestions-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
(rf/defn on-calculate-suggestions-success
{:events [:mention/on-calculate-suggestions-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-calculate-suggestions-success" {:result result})
(let [{:keys [state chat-id mentionable-users input-segments]} (transfer-mention-result result)]
{:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] mentionable-users)
(assoc-in [:chats/mentions chat-id :mentions] state)
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments))}))
+1 -1
View File
@@ -87,7 +87,7 @@
:identicon (.-identicon chat)
:muted (.-muted chat)
:joined (.-joined chat)
:muted-till (.-mutetill chat)
:chat-id (.-id chat)
:community-id (.-communityId chat)
:synced-from (.-syncedFrom chat)
+3 -2
View File
@@ -12,7 +12,8 @@
status-im2.navigation.core
status-im2.subs.root ; so integration tests can run independently
[taoensso.timbre :as log]
[utils.security.core :as security]))
[utils.security.core :as security]
[status-im2.constants :as constants]))
(def password "testabc")
@@ -295,7 +296,7 @@
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
(is @(rf/subscribe [:chats/chat chat-id]))
(rf/dispatch-sync [:chat.ui/mute chat-id true])
(rf/dispatch-sync [:chat.ui/mute chat-id true constants/mute-till-unmuted])
(rf-test/wait-for
[:chat/mute-successfully]
(is @(rf/subscribe [:chats/muted chat-id]))
@@ -198,11 +198,7 @@
(when platform/android?
(reset! last-text-change (js/Date.now)))
(on-text-change text chat-id)
;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`,
;; that's why mention suggestions are calculated on `on-change`
(when platform/ios?
(re-frame/dispatch [:mention/calculate-suggestions]))))
(on-text-change text chat-id)))
(rf/defn set-input-text
"Set input text for current-chat. Takes db and input text and cofx
@@ -220,26 +216,10 @@
(defn on-text-input
[chat-id args]
(let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event)
previous-text (.-previousText ^js native-event)
range (.-range ^js native-event)
start (.-start ^js range)
end (.-end ^js range)]
(let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event)]
(when (and (not (get @mentions-enabled chat-id)) (string/index-of text "@"))
(swap! mentions-enabled assoc chat-id true))
(re-frame/dispatch
[:mention/on-text-input
{:new-text text
:previous-text previous-text
:start start
:end end}])
;; NOTE(rasom): on Android `on-text-input` is dispatched after
;; `on-change`, that's why mention suggestions are calculated
;; on `on-change`
(when platform/android?
(re-frame/dispatch [:mention/calculate-suggestions]))))
(swap! mentions-enabled assoc chat-id true))))
(defn text-input
[{:keys [set-active-panel refs chat-id sending-image]}]
@@ -13,7 +13,8 @@
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.profile.components.sheets :as sheets]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[status-im2.constants :as constants]))
(defn actions
[{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?]
@@ -43,7 +44,9 @@
:selected muted?
:disabled blocked?
:action (when-not blocked?
#(re-frame/dispatch [:chat.ui/mute public-key (not muted?)]))}]
#(re-frame/dispatch [:chat.ui/mute public-key (not muted?)
(when-not muted?
constants/mute-till-unmuted)]))}]
[{:label (i18n/label (if blocked? :t/unblock :t/block))
:negative true
:selected blocked?
@@ -141,33 +141,15 @@
(reset! last-text-change (js/Date.now)))
(on-text-change text chat-id)
;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`,
;; that's why mention suggestions are calculated on `on-change`
(when platform/ios?
(rf/dispatch [:mention/calculate-suggestions]))))
(rf/dispatch [:mention/on-change-text text])))
(defn on-text-input
[chat-id args]
(let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event)
previous-text (.-previousText ^js native-event)
range (.-range ^js native-event)
start (.-start ^js range)
end (.-end ^js range)]
(let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event)]
(when (and (not (get @mentions-enabled? chat-id)) (string/index-of text "@"))
(swap! mentions-enabled? assoc chat-id true))
(rf/dispatch
[:mention/on-text-input
{:new-text text
:previous-text previous-text
:start start
:end end}])
;; NOTE(rasom): on Android `on-text-input` is dispatched after
;; `on-change`, that's why mention suggestions are calculated
;; on `on-change`
(when platform/android?
(rf/dispatch [:mention/calculate-suggestions]))))
(swap! mentions-enabled? assoc chat-id true))))
(defn text-input-style
[chat-id]
+1 -1
View File
@@ -51,7 +51,7 @@
(defn mute-chat-action
[chat-id]
(hide-sheet-and-dispatch [:chat.ui/mute chat-id true]))
(hide-sheet-and-dispatch [:chat.ui/mute chat-id true constants/mute-till-unmuted]))
(defn unmute-chat-action
[chat-id]
@@ -0,0 +1,8 @@
(ns status-im2.common.mute-chat-drawer.style
(:require [quo2.foundations.colors :as colors]))
(defn header-text
[]
{:margin-left 20
:margin-bottom 10
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)})
@@ -0,0 +1,65 @@
(ns status-im2.common.mute-chat-drawer.view
(:require [utils.i18n :as i18n]
[quo2.core :as quo]
[react-native.core :as rn]
[status-im2.constants :as constants]
[utils.re-frame :as rf]
[status-im2.common.mute-chat-drawer.style :as style]))
(defn hide-sheet-and-dispatch
[event]
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch event))
(defn mute-chat-drawer
[chat-id accessibility-label]
[rn/view {:accessibility-label accessibility-label}
[quo/text
{:weight :medium
:size :paragraph-2
:style (style/header-text)} (i18n/label :t/mute-channel)]
[quo/menu-item
{:type :transparent
:title (i18n/label :t/mute-for-15-mins)
:icon-bg-color :transparent
:container-padding-vertical 12
:title-column-style {:margin-left 2}
:on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/mute chat-id true
constants/mute-for-15-mins-type]))}]
[quo/menu-item
{:type :transparent
:title (i18n/label :t/mute-for-1-hour)
:icon-bg-color :transparent
:container-padding-vertical 12
:title-column-style {:margin-left 2}
:on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/mute chat-id true
constants/mute-for-1-hour-type]))}]
[quo/menu-item
{:type :transparent
:title (i18n/label :t/mute-for-8-hours)
:icon-bg-color :transparent
:container-padding-vertical 12
:title-column-style {:margin-left 2}
:on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/mute chat-id true
constants/mute-for-8-hours-type]))}]
[quo/menu-item
{:type :transparent
:title (i18n/label :t/mute-for-1-week)
:icon-bg-color :transparent
:container-padding-vertical 12
:title-column-style {:margin-left 2}
:on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/mute chat-id true
constants/mute-for-1-week]))}]
[quo/menu-item
{:type :transparent
:title (i18n/label :t/mute-till-unmute)
:icon-bg-color :transparent
:container-padding-vertical 12
:title-column-style {:margin-left 2}
:on-press (fn []
(hide-sheet-and-dispatch [:chat.ui/mute chat-id true
constants/mute-till-unmuted]))}]])
+6
View File
@@ -36,6 +36,12 @@
(def ^:const activity-center-membership-status-accepted 2)
(def ^:const activity-center-membership-status-declined 3)
(def ^:const mute-for-15-mins-type 1)
(def ^:const mute-for-1-hour-type 2)
(def ^:const mute-for-8-hours-type 3)
(def ^:const mute-for-1-week 4)
(def ^:const mute-till-unmuted 5)
(def ^:const activity-center-mark-all-as-read-undo-time-limit-ms 4000)
(def ^:const activity-center-max-unread-count 99)
+17 -13
View File
@@ -64,13 +64,15 @@
(defn map-chats
[{:keys [db] :as cofx}]
(fn [val]
(assoc
(merge
(or (get (:chats db) (:chat-id val))
(create-new-chat (:chat-id val) cofx))
val)
:invitation-admin
(:invitation-admin val))))
(let [chat (or (get (:chats db) (:chat-id val))
(create-new-chat (:chat-id val) cofx))]
(assoc
(merge
(cond-> chat
(comp not :muted) (dissoc chat :muted-till))
val)
:invitation-admin
(:invitation-admin val)))))
(rf/defn leave-removed-chat
[{{:keys [view-id current-chat-id chats]} :db
@@ -292,18 +294,20 @@
(rf/defn mute-chat-toggled-successfully
{:events [:chat/mute-successfully]}
[_ chat-id]
(log/debug "muted chat successfully" chat-id))
[{:keys [db]} chat-id muted-till]
(log/debug "muted chat successfully" chat-id " for" muted-till)
{:db (assoc-in db [:chats chat-id :muted-till] muted-till)})
(rf/defn mute-chat
{:events [:chat.ui/mute]}
[{:keys [db]} chat-id muted?]
(let [method (if muted? "wakuext_muteChat" "wakuext_unmuteChat")]
[{:keys [db]} chat-id muted? mute-type]
(let [method (if muted? "wakuext_muteChatV2" "wakuext_unmuteChat")
params (if muted? [{:chatId chat-id :mutedType mute-type}] [chat-id])]
{:db (assoc-in db [:chats chat-id :muted] muted?)
:json-rpc/call [{:method method
:params [chat-id]
:params params
:on-error #(rf/dispatch [:chat/mute-failed chat-id muted? %])
:on-success #(rf/dispatch [:chat/mute-successfully chat-id])}]}))
:on-success #(rf/dispatch [:chat/mute-successfully chat-id %])}]}))
(rf/defn show-clear-history-confirmation
{:events [:chat.ui/show-clear-history-confirmation]}
@@ -8,7 +8,8 @@
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im2.common.home.actions.view :as actions]
[utils.re-frame :as rf]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[status-im2.constants :as constants]))
(defn back-button
[]
@@ -191,7 +192,8 @@
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :toggle-mute
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)])}
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)
(when-not muted constants/mute-till-unmuted)])}
[quo/icon (if muted :i/muted :i/activity-center)
{:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
@@ -118,7 +118,7 @@
(defn chat-list-item
[{:keys [chat-id group-chat color name unviewed-messages-count unviewed-mentions-count
timestamp last-message]
timestamp last-message muted]
:as item}]
(let [display-name (if group-chat
name
@@ -143,8 +143,9 @@
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(get-in last-message [:content :text])]
[render-subheader (get-in last-message [:content :parsed-text])])]
(if (> unviewed-mentions-count 0)
[quo/info-count {:style {:top 16}}
unviewed-mentions-count]
(when (> unviewed-messages-count 0)
[rn/view {:style (style/count-container)}]))]))
(when-not muted
(if (> unviewed-mentions-count 0)
[quo/info-count {:style {:top 16}}
unviewed-mentions-count]
(when (> unviewed-messages-count 0)
[rn/view {:style (style/count-container)}])))]))
@@ -0,0 +1,47 @@
(ns status-im2.contexts.quo-preview.links.url-preview-list
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]
utils.number))
(def descriptor
[{:label "Number of previews"
:key :previews-length
:type :text}])
(defn cool-preview
[]
(let [state (reagent/atom {:previews-length "3"})]
(fn []
(let [previews-length (min 6 (utils.number/parse-int (:previews-length @state)))]
[rn/view {:style {:padding-bottom 150}}
[preview/customizer state descriptor]
[rn/view
{:style {:align-items :center
:margin-top 50}}
[quo/url-preview-list
{:horizontal-spacing 20
:on-clear #(js/alert "Clear button pressed")
:key-fn :url
:data (for [index (range previews-length)
:let [index (inc index)]]
{:title (str "Title " index)
:body (str "status.im." index)
:logo (resources/get-mock-image :status-logo)
:loading? false
:url (str "status.im." index)})}]]]))))
(defn preview
[]
[rn/view
{:style {:background-color (colors/theme-colors colors/white colors/neutral-95)
:flex 1}}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
@@ -40,6 +40,7 @@
[status-im2.contexts.quo-preview.inputs.profile-input :as profile-input]
[status-im2.contexts.quo-preview.inputs.title-input :as title-input]
[status-im2.contexts.quo-preview.links.url-preview :as url-preview]
[status-im2.contexts.quo-preview.links.url-preview-list :as url-preview-list]
[status-im2.contexts.quo-preview.list-items.channel :as channel]
[status-im2.contexts.quo-preview.list-items.preview-lists :as preview-lists]
[status-im2.contexts.quo-preview.markdown.text :as text]
@@ -183,7 +184,10 @@
:component title-input/preview-title-input}]
:links [{:name :url-preview
:options {:insets {:top? true}}
:component url-preview/preview}]
:component url-preview/preview}
{:name :url-preview-list
:options {:insets {:top? true}}
:component url-preview-list/preview}]
:list-items [{:name :channel
:insets {:top false}
:component channel/preview-channel}
@@ -1,10 +1,10 @@
(ns status-im2.contexts.quo-preview.tags.context-tags
(:require [quo2.components.tags.context-tags :as quo2]
(:require [quo2.components.tags.context-tag.view :as quo2]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def group-avatar-default-params
@@ -20,7 +20,7 @@
(def example-photo2
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=")
(def coinbase-community (resources/get-mock-image :coinbase))
(def coinbase-community-image (resources/get-mock-image :coinbase))
(def main-descriptor
[{:label "Type"
@@ -37,7 +37,10 @@
{:key :audio
:value "Audio"}
{:key :community
:value "Community"}]}])
:value "Community"}]}
{:label "Blur"
:key :blur?
:type :boolean}])
(def context-tag-descriptor
[{:label "Label"
@@ -51,73 +54,113 @@
[]
(let [state (reagent/atom {:label "Name"
:channel-name "Channel"
:type :group-avatar})]
:type :group-avatar
:duration "00:32"})]
(fn []
(let [contacts {example-pk {:public-key example-pk
:primary-name "Automatic incompatible Coati"
:photo example-photo}
example-pk2 {:public-key example-pk2
:primary-name "Clearcut Flickering Rattlesnake"
:photo example-photo2}}
(let [contacts {example-pk {:public-key example-pk
:primary-name "Automatic incompatible Coati"
:photo example-photo}
example-pk2 {:public-key example-pk2
:primary-name "Clearcut Flickering Rattlesnake"
:photo example-photo2}}
contacts-public-keys (map (fn [{:keys [public-key]}]
{:key public-key
:value (get-in contacts [public-key :primary-name])})
(vals contacts))
current-username (if (seq (:contact @state))
(->> @state
:contact
contacts
multiaccounts/displayed-name)
"Please select a user")
descriptor
(cond
(= (:type @state) :context-tag) (into main-descriptor context-tag-descriptor)
(= (:type @state) :group-avatar) (conj main-descriptor
{:label "Label"
:key :label
:type :text})
(= (:type @state) :avatar) (let [photo (-> @state :contact contacts :photo)]
(when-not (contains? @state :contacts)
(swap! state assoc :contacts contacts-public-keys))
(when-not (= (:photo @state)
photo)
(swap! state assoc :photo photo))
(conj main-descriptor
{:label "Contacts"
:key :contact
:type :select
:options contacts-public-keys})))]
current-username (if (seq (:contact @state))
(->> @state
:contact
contacts
multiaccounts/displayed-name)
"Please select a user")
descriptor (cond
(= (:type @state) :context-tag)
(into main-descriptor context-tag-descriptor)
(= (:type @state) :group-avatar)
(conj main-descriptor
{:label "Label"
:key :label
:type :text})
(= (:type @state) :avatar)
(let [photo (-> @state :contact contacts :photo)]
(when-not (contains? @state :contacts)
(swap! state assoc :contacts contacts-public-keys))
(when-not (= (:photo @state)
photo)
(swap! state assoc :photo photo))
(conj main-descriptor
{:label "Contacts"
:key :contact
:type :select
:options contacts-public-keys}))
(= (:type @state) :community)
(conj main-descriptor
{:label "Community name"
:key :label
:type :text})
(= (:type @state) :audio)
(conj main-descriptor
{:label "Duration"
:key :duration
:type :text})
:else
main-descriptor)]
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
[rn/view {:flex 1}
[rn/view {:style {:padding-bottom 150}}
[rn/view {:style {:flex 1}}
[preview/customizer state descriptor]]
[rn/view
{:padding-vertical 60
:flex-direction :row
:justify-content :center}
(case (:type @state)
:context-tag
[quo2/context-tag group-avatar-default-params {:uri example-photo2} (:label @state)
(:channel-name @state)]
:group-avatar
[quo2/group-avatar-tag (:label @state) group-avatar-default-params]
:public-key
[quo2/public-key-tag {} example-pk]
:avatar
[quo2/user-avatar-tag {} current-username (:photo @state)]
:audio
[quo2/audio-tag "00:32"]
:community
[quo2/community-tag coinbase-community "Coinbase"])]]]))))
[rn/view {:style {:padding-vertical 60}}
[preview/blur-view
{:style {:flex 1
:margin-vertical 20
:margin-horizontal 40}
:show-blur-background? (:blur? @state)}
(case (:type @state)
:context-tag [quo2/context-tag
{:blur? (:blur? @state)
:size :small
:color :purple}
{:uri example-photo2}
(:label @state)
(:channel-name @state)]
:group-avatar [quo2/group-avatar-tag (:label @state)
{:blur? (:blur? @state)
:size :small
:color :purple}]
:public-key [quo2/public-key-tag
{:blur? (:blur? @state)
:size :small
:color :purple}
example-pk]
:avatar [quo2/user-avatar-tag
{:blur? (:blur? @state)
:size :small
:color :purple}
current-username (:photo @state)]
:audio [quo2/audio-tag (:duration @state) {:blur? (:blur? @state)}]
:community [quo2/community-tag
coinbase-community-image
(:label @state)
{:blur? (:blur? @state)}])]]]]))))
(defn preview-context-tags
[]
[rn/view
{:background-color (colors/theme-colors colors/white
colors/neutral-95)
:flex 1}
{:style {:background-color (colors/theme-colors colors/white
colors/neutral-95)
:flex 1}}
[rn/flat-list
{:flex 1
{:style {:flex 1}
:keyboardShouldPersistTaps :always
:header [cool-preview]
:key-fn str}]])
+1 -1
View File
@@ -25,7 +25,7 @@
(re-frame/reg-fx
:shell/navigate-from-shell-fx
(fn [stack-id]
(js/setTimeout #(animation/bottom-tab-on-press stack-id) 500)))
(animation/bottom-tab-on-press stack-id)))
(re-frame/reg-fx
:shell/reset-bottom-tabs
+9 -7
View File
@@ -156,17 +156,19 @@
(fn [chats]
(let [{:keys [chats-stack community-stack]}
(reduce
(fn [acc [_ {:keys [unviewed-messages-count unviewed-mentions-count chat-type]}]]
(fn [acc [_ {:keys [unviewed-messages-count unviewed-mentions-count chat-type muted]}]]
(case chat-type
constants/community-chat-type
(-> acc
(update-in [:community-stack :unviewed-messages-count] + unviewed-messages-count)
(update-in [:community-stack :unviewed-mentions-count] + unviewed-mentions-count))
(when-not muted
(-> acc
(update-in [:community-stack :unviewed-messages-count] + unviewed-messages-count)
(update-in [:community-stack :unviewed-mentions-count] + unviewed-mentions-count)))
(constants/private-group-chat-type constants/one-to-one-chat-type)
(-> acc
(update-in [:chats-stack :unviewed-messages-count] + unviewed-messages-count)
(update-in [:chats-stack :unviewed-mentions-count] + unviewed-mentions-count))
(when-not muted
(-> acc
(update-in [:chats-stack :unviewed-messages-count] + unviewed-messages-count)
(update-in [:chats-stack :unviewed-mentions-count] + unviewed-mentions-count)))
acc))
{:chats-stack {:unviewed-messages-count 0 :unviewed-mentions-count 0}
+6
View File
@@ -61,6 +61,8 @@
"Pretty-print to STDOUT the current component tree."
(with-node-or-screen :debug))
(def within rtl/within)
(defn fire-event
([event-name node]
(fire-event event-name node nil))
@@ -188,3 +190,7 @@
(defn was-called
[mock]
(.toHaveBeenCalled (js/expect mock)))
(defn was-called-times
[^js mock number-of-times]
(.toHaveBeenCalledTimes (js/expect mock) number-of-times))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.144.0",
"commit-sha1": "ba1ba1ac0203948339be5877ea6e970efb7b8ee0",
"src-sha256": "0r2gxivnx201zfnm69g2mk1izcjid4lf9s4ln721kwrnc1v288sf"
"version": "fix/15616",
"commit-sha1": "2eccfda1c9495a3a6ecfd96f24efefff1b53461f",
"src-sha256": "0dhibgmfix23nmmg5nhyhg6qr069575mi1hp4gqd4rp54wygigvv"
}
@@ -332,7 +332,6 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase):
self.errors.verify_no_errors()
@marks.testrail_id(702957)
@marks.xfail(reason="Blocked by 15500")
def test_activity_center_mentions(self):
self.home_1.jump_to_communities_home()
self.home_2.jump_to_card_by_text('# %s' % self.channel_name)
+1 -1
View File
@@ -811,7 +811,7 @@ class ChatView(BaseView):
self.set_community_image_button = Button(self.driver, translation_id='community-thumbnail-image',
suffix='/following-sibling::android.view.ViewGroup')
self.confirm_create_in_community_button = Button(self.driver, translation_id="create")
self.mentions_list = BaseElement(self.driver, accessibility_id="mentions-list")
self.mentions_list = BaseElement(self.driver, accessibility_id="user-list")
# New UI
self.pinned_messages_count = Button(self.driver,
+7 -1
View File
@@ -2064,5 +2064,11 @@
"enable-biometrics": "Enable biometrics",
"use-biometrics": "Use biometrics to fill in your password",
"name-must-have-at-least-characters": "Name must have at least {{min-chars}} characters",
"name-is-not-valid": "Name is not valid"
"name-is-not-valid": "Name is not valid",
"mute-for-15-mins": "For 15 min",
"mute-for-1-hour": "For 1 hour",
"mute-for-8-hours": "For 8 hours",
"mute-for-1-week": "For 7 days",
"mute-till-unmute": "Until you turn it back on",
"mute-channel": "Mute channel"
}