diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index c9cae410db..0c0ed72e7e 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -139,6 +139,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return ( (def react-native-svg #js {:ClipPath #js {:render identity} + :Circle #js {:render identity} :Defs #js {:render identity} :Path #js {:render identity} :Rect #js {:render identity} diff --git a/src/quo2/components/dividers/strength_divider/component_spec.cljs b/src/quo2/components/dividers/strength_divider/component_spec.cljs new file mode 100644 index 0000000000..3e0b696e6d --- /dev/null +++ b/src/quo2/components/dividers/strength_divider/component_spec.cljs @@ -0,0 +1,38 @@ +(ns quo2.components.dividers.strength-divider.component-spec + (:require [quo2.components.dividers.strength-divider.view :as strength-divider] + [test-helpers.component :as h])) + +(h/describe "select-profile component" + (h/test "render component" + (h/render [strength-divider/view {:type :okay}]) + (-> (h/expect (h/get-by-label-text :strength-divider)) + (.toBeTruthy))) + (h/test "render component with :type :very-weak" + (h/render [strength-divider/view {:type :very-weak}]) + (-> (h/expect (h/get-by-translation-text :strength-divider-very-weak-label)) + (.toBeTruthy))) + (h/test "render component with :type :weak" + (h/render [strength-divider/view {:type :weak}]) + (-> (h/expect (h/get-by-translation-text :strength-divider-weak-label)) + (.toBeTruthy))) + (h/test "render component with :type :okay" + (h/render [strength-divider/view {:type :okay}]) + (-> (h/expect (h/get-by-translation-text :strength-divider-okay-label)) + (.toBeTruthy))) + (h/test "render component with :type :strong" + (h/render [strength-divider/view {:type :strong}]) + (-> (h/expect (h/get-by-translation-text :strength-divider-strong-label)) + (.toBeTruthy))) + (h/test "render component with :type :very-strong" + (h/render [strength-divider/view {:type :very-strong}]) + (-> (h/expect (h/get-by-translation-text :strength-divider-very-strong-label)) + (.toBeTruthy))) + (h/test "render component with :type :alert" + (h/render [strength-divider/view {:type :alert} "Text message"]) + (-> (h/expect (h/get-by-text "Text message")) + (.toBeTruthy))) + (h/test "render component with :type :info" + (h/render [strength-divider/view {:type :info} "Text Info"]) + (-> (h/expect (h/get-by-text "Text Info")) + (.toBeTruthy)))) + diff --git a/src/quo2/components/dividers/strength_divider/style.cljs b/src/quo2/components/dividers/strength_divider/style.cljs new file mode 100644 index 0000000000..b232c09fc7 --- /dev/null +++ b/src/quo2/components/dividers/strength_divider/style.cljs @@ -0,0 +1,13 @@ +(ns quo2.components.dividers.strength-divider.style) + +(def container + {:height 40 + :flex-direction :row + :padding-horizontal 20 + :align-items :center}) + +(defn text + [color] + {:color color + :margin-left 4}) + diff --git a/src/quo2/components/dividers/strength_divider/view.cljs b/src/quo2/components/dividers/strength_divider/view.cljs new file mode 100644 index 0000000000..11b9ddc527 --- /dev/null +++ b/src/quo2/components/dividers/strength_divider/view.cljs @@ -0,0 +1,85 @@ +(ns quo2.components.dividers.strength-divider.view + (:require [quo2.components.dividers.strength-divider.style :as style] + [quo2.components.icon :as icon] + [quo2.components.markdown.text :as text] + [quo2.foundations.colors :as colors] + [react-native.core :as rn] + [react-native.linear-gradient :as linear-gradient] + [react-native.svg :as svg] + [utils.i18n :as i18n])) + +(def strength-divider-types + {:very-weak {:default-text (i18n/label :t/strength-divider-very-weak-label) + :color colors/danger-60 + :percentage 20} + :weak {:default-text (i18n/label :t/strength-divider-weak-label) + :color (colors/custom-color :orange 60) + :percentage 40} + :okay {:default-text (i18n/label :t/strength-divider-okay-label) + :color (colors/custom-color :yellow 60) + :percentage 60} + :strong {:default-text (i18n/label :t/strength-divider-strong-label) + :color colors/success-60 + :percentage 80} + :very-strong {:default-text (i18n/label :t/strength-divider-very-strong-label) + :color colors/success-60 + :percentage 100} + :info {:color colors/white-opa-40} + :alert {:color colors/danger-60}}) + +(defn circular-progress + [{:keys [color percentage]}] + (let [strength-indicator-radius 6.5 + strength-indicator-circumference (* 2 Math/PI strength-indicator-radius)] + [svg/svg + {:view-box "0 0 16 16" + :width 14.2 + :transform [{:rotate "270deg"}] + :height 14.2} + [svg/circle + {:cx 8 + :cy 8 + :r strength-indicator-radius + :fill :transparent + :stroke-width 1.2 + :stroke (colors/alpha color 0.2)}] + [svg/circle + {:cx 8 + :cy 8 + :r strength-indicator-radius + :fill :transparent + :stroke-width 1.2 + :stroke-dasharray strength-indicator-circumference + :stroke-dashoffset (* (- 100 percentage) 0.01 strength-indicator-circumference) + :stroke color}] + [svg/circle]])) + +(defn strength-indicator + [type] + (let [{:keys [color percentage]} (strength-divider-types type)] + (case type + :info nil + :alert [icon/icon :i/alert + {:color color + :size 16}] + [circular-progress {:color color :percentage percentage}]))) + +(defn view + "Options + - `:type` `:very-weak`/`:weak`/`:okay`/`:strong`/`:very-strong`/`:info`/`:alert`) + + `text` message string(only works when type is `info`/`alert`)" + [{:keys [type] :or {type :very-weak}} text] + (let [{:keys [color default-text]} (strength-divider-types type)] + [linear-gradient/linear-gradient + {:colors [(colors/alpha color 0.05) (colors/alpha color 0)]} + [rn/view + {:style style/container + :accessibility-label :strength-divider} + [strength-indicator type] + [text/text + {:size :paragraph-2 + :weight :medium + :style (style/text color)} + (or default-text text)]]])) + diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index e2dd9b03d4..74c008c687 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -21,6 +21,7 @@ quo2.components.dividers.date quo2.components.dividers.divider-label quo2.components.dividers.new-messages + quo2.components.dividers.strength-divider.view quo2.components.drawers.action-drawers.view quo2.components.drawers.drawer-buttons.view quo2.components.drawers.permission-context.view @@ -131,6 +132,7 @@ (def divider-label quo2.components.dividers.divider-label/divider-label) (def new-messages quo2.components.dividers.new-messages/new-messages) (def divider-date quo2.components.dividers.date/date) +(def strength-divider quo2.components.dividers.strength-divider.view/view) ;;;; DRAWERS (def action-drawer quo2.components.drawers.action-drawers.view/action-drawer) diff --git a/src/quo2/core_spec.cljs b/src/quo2/core_spec.cljs index 5323f7a035..25341dd211 100644 --- a/src/quo2/core_spec.cljs +++ b/src/quo2/core_spec.cljs @@ -3,6 +3,7 @@ [quo2.components.buttons.--tests--.buttons-component-spec] [quo2.components.counter.--tests--.counter-component-spec] [quo2.components.dividers.--tests--.divider-label-component-spec] + [quo2.components.dividers.strength-divider.component-spec] [quo2.components.drawers.action-drawers.component-spec] [quo2.components.drawers.drawer-buttons.component-spec] [quo2.components.drawers.permission-context.component-spec] diff --git a/src/react_native/svg.cljs b/src/react_native/svg.cljs index e349fe8531..972be29752 100644 --- a/src/react_native/svg.cljs +++ b/src/react_native/svg.cljs @@ -7,3 +7,5 @@ (def rect (reagent/adapt-react-class Svg/Rect)) (def clippath (reagent/adapt-react-class Svg/ClipPath)) (def defs (reagent/adapt-react-class Svg/Defs)) +(def circle (reagent/adapt-react-class Svg/Circle)) + diff --git a/src/status_im2/contexts/communities/menus/community_options/component_spec.cljs b/src/status_im2/contexts/communities/menus/community_options/component_spec.cljs index a1fe218a5d..59bb1501e7 100644 --- a/src/status_im2/contexts/communities/menus/community_options/component_spec.cljs +++ b/src/status_im2/contexts/communities/menus/community_options/component_spec.cljs @@ -21,164 +21,164 @@ (h/test "joined options - Non token Gated" (setup-sub {:joined true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "View members")) + (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View Community Rules")) + (-> (h/expect (h/get-by-translation-text :view-community-rules)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mark as read")) + (-> (h/expect (h/get-by-translation-text :mark-as-read)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mute community")) + (-> (h/expect (h/get-by-translation-text :mute-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Notification settings")) + (-> (h/expect (h/get-by-translation-text :community-notification-settings)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Leave community")) + (-> (h/expect (h/get-by-translation-text :leave-community)) (.toBeTruthy))) (h/test "joined options - Token Gated" (setup-sub {:joined true :token-gated? true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "View members")) + (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View Community Rules")) + (-> (h/expect (h/get-by-translation-text :view-community-rules)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View token gating")) + (-> (h/expect (h/get-by-translation-text :view-token-gating)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mark as read")) + (-> (h/expect (h/get-by-translation-text :mark-as-read)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mute community")) + (-> (h/expect (h/get-by-translation-text :mute-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Notification settings")) + (-> (h/expect (h/get-by-translation-text :community-notification-settings)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Leave community")) + (-> (h/expect (h/get-by-translation-text :leave-community)) (.toBeTruthy))) (h/test "admin options - Non token Gated" (setup-sub {:admin true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "View members")) + (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View Community Rules")) + (-> (h/expect (h/get-by-translation-text :view-community-rules)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Edit community")) + (-> (h/expect (h/get-by-translation-text :edit-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mark as read")) + (-> (h/expect (h/get-by-translation-text :mark-as-read)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mute community")) + (-> (h/expect (h/get-by-translation-text :mute-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Notification settings")) + (-> (h/expect (h/get-by-translation-text :community-notification-settings)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy))) (h/test "admin options - Token Gated" (setup-sub {:admin true :token-gated? true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "View members")) + (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View Community Rules")) + (-> (h/expect (h/get-by-translation-text :view-community-rules)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Edit community")) + (-> (h/expect (h/get-by-translation-text :edit-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mark as read")) + (-> (h/expect (h/get-by-translation-text :mark-as-read)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Mute community")) + (-> (h/expect (h/get-by-translation-text :mute-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Notification settings")) + (-> (h/expect (h/get-by-translation-text :community-notification-settings)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy))) (h/test "request sent options - Non token Gated" (setup-sub {:requested-to-join-at true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "View members")) + (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View Community Rules")) + (-> (h/expect (h/get-by-translation-text :view-community-rules)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Cancel request to join")) + (-> (h/expect (h/get-by-translation-text :cancel-request-to-join)) (.toBeTruthy))) (h/test "request sent options - Token Gated" (setup-sub {:requested-to-join-at 100 :token-gated? true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View token gating")) + (-> (h/expect (h/get-by-translation-text :view-token-gating)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Cancel request to join")) + (-> (h/expect (h/get-by-translation-text :cancel-request-to-join)) (.toBeTruthy))) (h/test "banned options - Non token Gated" (setup-sub {:banList true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "View members")) + (-> (h/expect (h/get-by-translation-text :view-members)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View Community Rules")) + (-> (h/expect (h/get-by-translation-text :view-community-rules)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy))) (h/test "banned options - Token Gated" (setup-sub {:banList 100 :token-gated? true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View token gating")) + (-> (h/expect (h/get-by-translation-text :view-token-gating)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy))) (h/test "banned options - Token Gated" (setup-sub {:banList 100 :token-gated? true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "Invite people from contact list")) + (-> (h/expect (h/get-by-translation-text :invite-people-from-contacts)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "View token gating")) + (-> (h/expect (h/get-by-translation-text :view-token-gating)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Show QR code")) + (-> (h/expect (h/get-by-translation-text :show-qr)) (.toBeTruthy)) - (-> (h/expect (h/get-by-text "Share community")) + (-> (h/expect (h/get-by-translation-text :share-community)) (.toBeTruthy))) (h/test "joined and muted community" @@ -186,7 +186,7 @@ :muted true :token-gated? true}) (h/render [options/community-options-bottom-sheet {:id "test"}]) - (-> (h/expect (h/get-by-text "Unmute community")) + (-> (h/expect (h/get-by-translation-text :unmute-community)) (.toBeTruthy)))) diff --git a/src/status_im2/contexts/quo_preview/dividers/strength_divider.cljs b/src/status_im2/contexts/quo_preview/dividers/strength_divider.cljs new file mode 100644 index 0000000000..58afc73663 --- /dev/null +++ b/src/status_im2/contexts/quo_preview/dividers/strength_divider.cljs @@ -0,0 +1,55 @@ +(ns status-im2.contexts.quo-preview.dividers.strength-divider + (:require [quo2.core :as quo] + [quo2.foundations.colors :as colors] + [react-native.core :as rn] + [reagent.core :as reagent] + [status-im2.contexts.quo-preview.preview :as preview])) + +(def descriptor + [{:label "Type" + :key :type + :type :select + :options [{:key :very-weak + :value "Very weak"} + {:key :weak + :value "Weak"} + {:key :okay + :value "Okay"} + {:key :strong + :value "Strong"} + {:key :very-strong + :value "Very strong"} + {:key :alert + :value "Alert"} + {:key :info + :value "Info"}]} + {:label "Text(only works for info/alert)" + :key :text + :type :text}]) + +(defn cool-preview + [] + (let [state (reagent/atom {:text "Common password, shouldn’t be used" + :type :alert}) + text (reagent/cursor state [:text]) + type (reagent/cursor state [:type])] + (fn [] + [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} + [rn/view {:padding-bottom 150} + [preview/customizer state descriptor] + [rn/view {:padding-vertical 60 :background-color colors/neutral-95} + [quo/strength-divider {:type @type} @text]]]]))) + +(defn preview-strength-divider + [] + [rn/view + {: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}]]) + diff --git a/src/status_im2/contexts/quo_preview/main.cljs b/src/status_im2/contexts/quo_preview/main.cljs index 0ff7e73d14..fa93774993 100644 --- a/src/status_im2/contexts/quo_preview/main.cljs +++ b/src/status_im2/contexts/quo_preview/main.cljs @@ -29,6 +29,7 @@ [status-im2.contexts.quo-preview.dividers.date :as divider-date] [status-im2.contexts.quo-preview.dividers.divider-label :as divider-label] [status-im2.contexts.quo-preview.dividers.new-messages :as new-messages] + [status-im2.contexts.quo-preview.dividers.strength-divider :as strength-divider] [status-im2.contexts.quo-preview.drawers.action-drawers :as action-drawers] [status-im2.contexts.quo-preview.drawers.drawer-buttons :as drawer-buttons] [status-im2.contexts.quo-preview.drawers.permission-drawers :as permission-drawers] @@ -142,7 +143,10 @@ :component new-messages/preview-new-messages} {:name :divider-date :insets {:top false} - :component divider-date/preview-divider-date}] + :component divider-date/preview-divider-date} + {:name :strength-divider + :insets {:top false} + :component strength-divider/preview-strength-divider}] :drawers [{:name :action-drawers :insets {:top false} :component action-drawers/preview-action-drawers} diff --git a/src/test_helpers/component.cljs b/src/test_helpers/component.cljs index ee10412089..3d6f02f1eb 100644 --- a/src/test_helpers/component.cljs +++ b/src/test_helpers/component.cljs @@ -34,6 +34,10 @@ [label] (rtl/screen.getByLabelText (name label))) +(defn get-by-translation-text + [keyword] + (get-by-text (str "tx:" (name keyword)))) + (defn get-all-by-label-text [label] (rtl/screen.getAllByLabelText (name label))) diff --git a/test/jest/jestSetup.js b/test/jest/jestSetup.js index 15f7a5f3c4..c92fffdb9a 100644 --- a/test/jest/jestSetup.js +++ b/test/jest/jestSetup.js @@ -60,6 +60,11 @@ jest.mock('@react-native-community/audio-toolkit', () => ({ }, })); +jest.mock("i18n-js", () => ({ + ...jest.requireActual("i18n-js"), + t: (label) => `tx:${label}` +})); + NativeModules.ReactLocalization = { language: 'en', locale: 'en', diff --git a/translations/en.json b/translations/en.json index 859ca21196..157b4b2cdc 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1970,5 +1970,10 @@ "only-6-images": "You can only add 6 images to your message", "delivered": "Delivered", "mark-all-notifications-as-read": "Mark all notifications as read", - "notifications-marked-as-read": "{{count}} notifications marked as read" + "notifications-marked-as-read": "{{count}} notifications marked as read", + "strength-divider-very-weak-label": "Very weak", + "strength-divider-weak-label": "Weak", + "strength-divider-okay-label": "Okay", + "strength-divider-strong-label": "Strong", + "strength-divider-very-strong-label": "Very strong" }