Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
779355a
fix: ensure we always save the notifications-enabled setting when cha…
seanstrom Apr 16, 2025
b8d12b9
feat: implement the push-notification-disabled banner
seanstrom Apr 16, 2025
8f6a803
wip: adjust enable-notifications screen and flows
seanstrom Apr 21, 2025
0273a1f
wip: adjust notification settings screen with nested ui
seanstrom Apr 22, 2025
4c0c9af
chore: clean up translations for onboarding
seanstrom May 8, 2025
18bc5da
chore: cleanup notifications settings screen
seanstrom May 8, 2025
205d3a4
fix: ensure we use the correct customization color when during onboar…
seanstrom May 8, 2025
cd4a61a
fix: ensure we use the default customization colour when onboarding p…
seanstrom May 9, 2025
ef2d132
fix: ensure we navigate to the notifications setup screen from any sc…
seanstrom May 11, 2025
f254fa0
fix: ensure the third-party checkbox only defaults to true when the n…
seanstrom May 11, 2025
eea665b
fix: add deps array to use-callback in enable-notifications screen
seanstrom May 12, 2025
b1d2727
fix: feature-flag the enable-notifications screen
seanstrom May 12, 2025
5035f1a
chore: mark unused variable with underscore
seanstrom May 12, 2025
e585136
chore: remove empty wrapper view
seanstrom May 12, 2025
8ba6578
fix: ensure we have reader-conditionals for release builds
seanstrom May 12, 2025
fc6326e
chore: update google-services plist for ios release
seanstrom May 13, 2025
5ae114b
chore: refactor kv_storage events, effects, and interceptors
seanstrom May 14, 2025
8a53015
chore: cleanup view-id access
seanstrom May 14, 2025
a7cbcfa
chore: cleanup subscription
seanstrom May 14, 2025
51a73b0
chore: revise cond to if expression
seanstrom May 14, 2025
9cb5928
chore: use boolean? function instead of if-expression
seanstrom May 14, 2025
64adafb
fix: use customization color for checkbox
seanstrom May 14, 2025
2c477ad
chore: use rn/stylesheet-absolute-fill
seanstrom May 14, 2025
a32f148
chore: inline event handlers
seanstrom May 14, 2025
44a9533
chore: simplify cond-expression to if-expression
seanstrom May 14, 2025
a2735f2
fix: ensure we finalize notification setup when syncing during onboar…
seanstrom May 14, 2025
4ea25cf
chore: remove unneeded key-uid
seanstrom May 15, 2025
00a3218
fix: ensure we disable the toggle
seanstrom May 15, 2025
2df1099
fix: ensure we retain the checked state when disabled
seanstrom May 15, 2025
a66ca16
fix: ensure we register the event handlers correctly
seanstrom May 15, 2025
a5bdf6e
fix: ensure we use set-object
seanstrom May 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ios/GoogleService-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>854811651919-30s20e3l0me0ins0vc4185jbnj7ja49o.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.854811651919-30s20e3l0me0ins0vc4185jbnj7ja49o</string>
<key>API_KEY</key>
<string>AIzaSyAm5D6giymR_2llh-8SbCRL3oPxX_v3EZs</string>
<string>AIzaSyB_ZCi76uSX1RBqGiLIllUnJ8D6_cKrRGQ</string>
<key>GCM_SENDER_ID</key>
<string>854811651919</string>
<key>PLIST_VERSION</key>
Expand Down
19 changes: 18 additions & 1 deletion shadow-cljs.edn
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,24 @@
:fn-invoke-direct true
:optimizations :advanced
:js-options {:js-provider :closure}
:reader-features #{:mobile}}}}
:reader-features #{:mobile
;; NOTE(@seanstrom): Here we are allowing for an
;; environment variable to configure the intended store
;; where a user could download the app. For example, we
;; support the FDroid and Google Play stores, so we can
;; configure the app to build for FDroid by setting the
;; `ANDROID_STORE` environment variable to `fdroid`.
;;
;; This value is used for configuring Shadow-CLJS to
;; only require namespaces that will be compatible with
;; some restrictions imposed by the Android stores. For
;; example, FDroid does not allow for Google Play
;; services like Firebase, so we use the
;; reader-conditional of `:fdroid` or `:google` to
;; clearly avoid importing Firebase dependencies in the
;; FDroid builds.
#shadow/env ["ANDROID_STORE" :as :keyword :default
:google]}}}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In release builds it might be better to avoid certain defaults. The idea is that it's better to fail early on somehow rather than to build with incorrect parameters. Ideally, the release build script should fail if required environment vars are missing, but I don't know if we have this capability implemented. My feedback is not a big deal, just a nice to have.

;; the tests are ran with node, react-native dependencies are mocked
;; by using node --require override.js, which uses the node-library
;; produced by the target :mocks below and redefines node require
Expand Down
5 changes: 4 additions & 1 deletion src/legacy/status_im/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
(let [new-account? (get db :onboarding/new-account?)
app-in-background-since (get db :app-in-background-since)
signed-up? (get-in db [:profile/profile :signed-up?])
notifications-settings? (= (:view-id db) :screen/settings.notifications)
requires-bio-auth (and
signed-up?
(= (:auth-method db) "biometric")
Expand All @@ -121,7 +122,9 @@
#(when-let [chat-id (:current-chat-id db)]
{:dispatch [:chat/mark-all-as-read chat-id]})
#(when requires-bio-auth
{:dispatch [:biometric/authenticate {:on-fail on-biometric-auth-fail}]}))))
{:dispatch [:biometric/authenticate {:on-fail on-biometric-auth-fail}]})
#(when notifications-settings?
{:dispatch [:notifications/check-notifications-blocked]}))))
Comment on lines +125 to +127
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we're conditionally dispatching the :notifications/check-notifications-blocked event to refresh the screen UI if the user has recently unblocked or allowed notification permissions from outside the Status app and then returned to the notifications settings screen.


(rf/defn on-going-in-background
[{:keys [db now]}]
Expand Down
6 changes: 5 additions & 1 deletion src/react_native/permissions.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns react-native.permissions
(:require
["react-native-permissions" :refer
[check checkNotifications PERMISSIONS requestMultiple
[check checkNotifications openSettings PERMISSIONS requestMultiple
requestNotifications RESULTS]]
[clojure.string :as string]
[promesa.core :as promesa]
Expand Down Expand Up @@ -95,3 +95,7 @@
[]
(-> (checkNotifications)
(promesa/then notification-permissions->notification-permission-statuses)))

(defn open-notification-settings
[]
(openSettings "notifications"))
Comment on lines +98 to +101
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we're creating a function that should open the OS system settings screen for the app, and if possible it will display the notification related settings for the app (from the OS System pov, not inside Status app).

19 changes: 19 additions & 0 deletions src/status_im/common/kv_storage/effects.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(ns status-im.common.kv-storage.effects
(:require
[react-native.mmkv :as mmkv]
[utils.re-frame :as rf]))

(rf/reg-fx :effects.kv/set-object
(fn [{:keys [id value]}]
(mmkv/set-object id value)))

(rf/reg-fx :effects.kv/merge-object
(fn [{key-id :key
:keys [value]}]
(let [kv-object (mmkv/get-object key-id {})]
(mmkv/set-object key-id
(merge kv-object value)))))

(rf/reg-fx :effects.kv/delete-key
(fn [key-id]
(mmkv/delete-key key-id)))
15 changes: 9 additions & 6 deletions src/status_im/contexts/onboarding/enable_biometrics/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,28 @@
[insets]
(let [supported-biometric-type (rf/sub [:biometrics/supported-type])
bio-type-label (biometric/get-label-by-type supported-biometric-type)
profile-color (or (:color (rf/sub [:onboarding/profile]))
onboarding-profile (rf/sub [:onboarding/profile])
profile-color (or (:color onboarding-profile)
(rf/sub [:profile/customization-color]))
syncing? (= (rf/sub [:view-id]) :screen/onboarding.syncing-biometric)
syncing? (:syncing? onboarding-profile)
biometric-type (rf/sub [:biometrics/supported-type])]
[rn/view {:style (style/buttons insets)}
[quo/button
{:size 40
:accessibility-label :enable-biometrics-button
:icon-left (biometric/get-icon-by-type biometric-type)
:customization-color profile-color
:on-press #(rf/dispatch [:onboarding/enable-biometrics])}
:on-press #(rf/dispatch [:onboarding/biometrics-setup-start
{:enable-biometrics? true
:syncing? syncing?}])}
Comment on lines +36 to +38
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we're using a different pattern for dispatching events from the onboarding screens. Instead of dispatching different events from the screen, we attempt to dispatch the same event with different parameters.

This pattern is an attempt to simplify how we manage the onboarding screens, for example, if we choose to expand the onboarding steps, it would be ideal that we can refactor mostly the event layer instead of needing to refactor both the event layer and view layer.

(i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})]
[quo/button
{:accessibility-label :maybe-later-button
:background :blur
:type :grey
:on-press #(rf/dispatch (if syncing?
[:onboarding/finish-onboarding false]
[:onboarding/create-account-and-login]))
:on-press #(rf/dispatch [:onboarding/biometrics-setup-start
{:enable-biometrics? false
:syncing? syncing?}])
:container-style {:margin-top 12}}
(i18n/label :t/maybe-later)]]))

Expand Down
10 changes: 10 additions & 0 deletions src/status_im/contexts/onboarding/enable_notifications/style.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,13 @@
[insets]
{:margin default-margin
:margin-bottom (+ 14 (:bottom insets))})

(def news-notifications-checkbox-container
{:flex-direction :row
:gap 8
:padding-top 8
:padding-bottom 12
:padding-horizontal 20})

(def news-notifications-checkbox-text
{:flex 1})
140 changes: 102 additions & 38 deletions src/status_im/contexts/onboarding/enable_notifications/view.cljs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
(ns status-im.contexts.onboarding.enable-notifications.view
(:require
[quo.context]
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[status-im.common.resources :as resources]
[status-im.contexts.onboarding.common.background.view :as background]
[status-im.contexts.onboarding.enable-notifications.style :as style]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))

Expand All @@ -17,51 +21,111 @@
:description (i18n/label :t/enable-notifications-sub-title)
:description-accessibility-label :notifications-sub-title}])

(defn enable-notification-buttons
[{:keys [insets]}]
(let [profile-color (rf/sub [:onboarding/customization-color])
ask-permission (fn []
(rf/dispatch
[:request-notifications
{:on-allowed (fn []
(js/setTimeout
#(rf/dispatch [:onboarding/finish-onboarding true])
300))
:on-denied (fn []
(js/setTimeout
#(rf/dispatch [:onboarding/finish-onboarding false])
300))}]))
skip-permission #(rf/dispatch [:onboarding/finish-onboarding false])]
[rn/view {:style (style/buttons insets)}
[quo/button
{:on-press ask-permission
:type :primary
:icon-left :i/notifications
:accessibility-label :enable-notifications-button
:customization-color profile-color}
(i18n/label :t/intro-wizard-title6)]
[quo/button
{:on-press skip-permission
:accessibility-label :enable-notifications-later-button
:type :grey
:background :blur
:container-style {:margin-top 12}}
(i18n/label :t/maybe-later)]]))
(defn on-notifications-setup-start
[params]
(rf/dispatch [:onboarding/notifications-setup-start params]))

(defn enable-notifications-simple
(defn notifications-info-view
[{:keys [blur?]}]
[quo/documentation-drawers
{:title (i18n/label :t/enable-notifications)
:show-button? true
:shell? blur?
:button-label (i18n/label :t/read-more)
:button-icon :i/info}
[quo/text (i18n/label :t/enable-notifications-info-description)]])
Comment on lines +28 to +36
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This drawer view still needs the correct verbiage from the docs team (I think ?)
Reference: https://www.figma.com/design/JlpPhJp0SMnEyBQy4nOZHo/Settings----Mobile?node-id=9395-120255&t=IZIHOX0Oys0QGyTf-4


(defn on-open-info
[{:keys [blur? theme]
:or {blur? true}}]
(rf/dispatch [:show-bottom-sheet
{:content (fn []
[notifications-info-view {:blur? blur?}])
:theme theme
:shell? blur?}]))

(defn enable-notification-form
[{:keys [insets params]}]
(let [profile-color (rf/sub [:onboarding/customization-color
{:onboarding? (:onboarding? params)}])
[third-party-checked?
set-third-party-checked] (rn/use-state
(boolean? (ff/enabled? ::ff/settings.news-notifications)))
on-enable-notifications (rn/use-callback
(fn []
(on-notifications-setup-start
(assoc params
:enable-notifications? true
:enable-news-notifications? third-party-checked?)))
[params third-party-checked?])
on-skip-notifications (rn/use-callback
(fn []
(on-notifications-setup-start
(assoc params
:enable-notifications? false
:enable-news-notifications? false)))
[params])]
[rn/view
(when (and platform/android?
(ff/enabled? ::ff/settings.news-notifications))
[rn/view
{:style style/news-notifications-checkbox-container}
[quo/selectors
{:type :checkbox
:blur? true
:customization-color profile-color
:checked? third-party-checked?
:on-change set-third-party-checked}]
[quo/text
{:size :paragraph-2
:style style/news-notifications-checkbox-text}
(i18n/label :t/enable-news-notifications-third-party)]])
[rn/view {:style (style/buttons insets)}
[quo/button
{:on-press on-enable-notifications
:type :primary
:icon-left :i/notifications
:accessibility-label :enable-notifications-button
:customization-color profile-color}
(i18n/label :t/intro-wizard-title6)]
[quo/button
{:on-press on-skip-notifications
:accessibility-label :enable-notifications-later-button
:type :grey
:background :blur
:container-style {:margin-top 12}}
(i18n/label :t/maybe-later)]]]))

(defn enable-notifications-illustration
[]
(let [width (:width (rn/get-window))]
[rn/image
{:resize-mode :contain
:style (style/page-illustration width)
:source (resources/get-image :notifications)}]))

(defn background-image
[]
[rn/view {:style rn/stylesheet-absolute-fill}
[background/view true]])

(defn view
[]
(let [insets safe-area/insets]
[rn/view {:style (style/page-container insets)}
[rn/view {:style style/page-heading}
[quo/page-nav {:type :no-title :background :blur}]
[page-title]]
[enable-notifications-simple]
[enable-notification-buttons {:insets insets}]]))
(let [insets safe-area/insets
params (quo.context/use-screen-params)]
[:<>
(when-not (:onboarding? params)
[background-image])
[rn/view {:style (style/page-container insets)}
[rn/view {:style style/page-heading}
[quo/page-nav
{:type :no-title
:background :blur
:right-side [{:icon-name :i/info
:on-press on-open-info
:accessibility-label :notifications-info-button}]}]
[page-title]]
[enable-notifications-illustration]
[enable-notification-form
{:insets insets
:params params}]]]))
Loading