diff --git a/src/App.res b/src/App.res
index 21f3cc0..d69e314 100644
--- a/src/App.res
+++ b/src/App.res
@@ -19,13 +19,27 @@ let make = () => {
| list{"misto", ..._} =>
- {switch List.tail(url.path) {
- | Some(list{}) =>
- | Some(list{placeId}) =>
- | Some(list{placeId, "nastaveni"}) =>
- | Some(list{placeId, "nastaveni", "osob"}) =>
- | _ =>
- }}
+ {
+ let maybePlaceSubPath = List.tail(url.path)
+ switch maybePlaceSubPath {
+ | None
+ | Some(list{}) =>
+
+ | Some(placeSubPath) => {
+ let placeId = List.headExn(placeSubPath)
+ let placeIdSub = List.tail(placeSubPath)
+ <>
+
+ {switch placeIdSub {
+ | Some(list{}) =>
+ | Some(list{"nastaveni"}) =>
+ | Some(list{"nastaveni", "osob"}) =>
+ | _ =>
+ }}
+ >
+ }
+ }
+ }
| list{"s", linkId} =>
diff --git a/src/backend/Firebase.res b/src/backend/Firebase.res
index 1360200..7800872 100644
--- a/src/backend/Firebase.res
+++ b/src/backend/Firebase.res
@@ -437,14 +437,21 @@ module AppCheckProvider = {
module Messaging = {
type t
- type getTokenOptions = { vapidKey: string }
+ @module("firebase/messaging")
+ external getMessaging: FirebaseApp.t => t = "getMessaging"
+
+ type getTokenOptions = {vapidKey: string}
+ // Subscribes the Messaging instance to push notifications. Returns a Firebase Cloud Messaging registration token that
+ // can be used to send push messages to that Messaging instance. If notification permission isn't already granted,
+ // this method asks the user for permission. The returned promise rejects if the user does not allow the app to show
+ // notifications.
@module("firebase/messaging")
- external getToken: (t, getTokenOptions) => unit = "getToken"
-}
+ external _getToken: (t, getTokenOptions) => promise = "getToken"
-@module("firebase/messaging")
-external getMessaging: FirebaseApp.t => Messaging.t = "getMessaging"
+ let getToken = (messaging: t) =>
+ _getToken(messaging, {vapidKey: %raw(`import.meta.env.VITE_FIREBASE_VAPID_KEY`)})
+}
module Timestamp = {
@genType.import("firebase/firestore") @genType.as("Timestamp")
diff --git a/src/backend/NotificationEvents.res b/src/backend/NotificationEvents.res
index beb5edf..108ed0b 100644
--- a/src/backend/NotificationEvents.res
+++ b/src/backend/NotificationEvents.res
@@ -5,14 +5,6 @@ type notificationEvent =
@module("./NotificationEvents.ts")
external notificationEvent: notificationEvent = "NotificationEvent"
-let notificationEventFromInt = (notificationEvent: int) =>
- switch notificationEvent {
- | 0 => Some(Unsubscribed)
- | 1 => Some(FreeTable)
- | 2 => Some(FreshKeg)
- | _ => None
- }
-
let roleI18n = (notificationEvent: notificationEvent) =>
switch notificationEvent {
| Unsubscribed => "Nepřihlášen"
diff --git a/src/backend/Reactfire.res b/src/backend/Reactfire.res
index 1c3a418..77a7c48 100644
--- a/src/backend/Reactfire.res
+++ b/src/backend/Reactfire.res
@@ -30,6 +30,14 @@ module FunctionsProvider = {
"FunctionsProvider"
}
+let messagingContext = React.createContext((None: option))
+
+module MessagingProvider = {
+ let make = React.Context.provider(messagingContext)
+}
+
+let useMessaging = () => React.useContext(messagingContext)->Option.getExn
+
type observableStatus<'a> = {
data: option<'a>,
error: option,
diff --git a/src/components/FcmTokenSync/FcmTokenSync.res b/src/components/FcmTokenSync/FcmTokenSync.res
new file mode 100644
index 0000000..d94c1cb
--- /dev/null
+++ b/src/components/FcmTokenSync/FcmTokenSync.res
@@ -0,0 +1,50 @@
+let isSubscribedToNotificationsRx = (auth, firestore, placeId) => {
+ open Rxjs
+ let currentUserRx = Rxfire.user(auth)->op(keepMap(Null.toOption))
+ let placeRef = Db.placeDocument(firestore, placeId)
+ let placeRx = Rxfire.docData(placeRef)
+ combineLatest2(currentUserRx, placeRx)->op(
+ map(((currentUser: Firebase.User.t, place: option), _) => {
+ switch (currentUser, place) {
+ | (user, Some(place)) =>
+ place.accounts
+ ->Dict.get(user.uid)
+ ->Option.map(((_, notificationSetting)) => notificationSetting > 0)
+ ->Option.getOr(false)
+ | _ => false
+ }
+ }),
+ )
+}
+
+@react.component
+let make = (~placeId) => {
+ let auth = Reactfire.useAuth()
+ let firestore = Reactfire.useFirestore()
+ let messaging = Reactfire.useMessaging()
+ let updateNotificationToken = NotificationEvents.useUpdateNotificationToken()
+ let isStandaloneModeStatus = DomUtils.useIsStandaloneMode()
+ let isSubscribedToNotifications = Reactfire.useObservable(
+ ~observableId="isSubscribedToNotifications",
+ ~source=isSubscribedToNotificationsRx(auth, firestore, placeId),
+ )
+ React.useEffect2(() => {
+ switch (isSubscribedToNotifications.data, isStandaloneModeStatus.data) {
+ | (Some(true), Some(true)) =>
+ messaging
+ ->Firebase.Messaging.getToken
+ ->Promise.then(updateNotificationToken)
+ ->Promise.then(_ => Promise.resolve())
+ ->Promise.catch(error => {
+ let exn = Js.Exn.asJsExn(error)->Option.getExn
+ LogUtils.captureException(exn)
+ Promise.resolve()
+ })
+ ->ignore
+ | _ => ()
+ }
+ None
+ }, (isSubscribedToNotifications.data, isStandaloneModeStatus.data))
+
+ React.null
+}
diff --git a/src/components/FirebaseAuthProvider/FirebaseAuthProvider.res b/src/components/FirebaseAuthProvider/FirebaseAuthProvider.res
index e1f58f5..ea4652c 100644
--- a/src/components/FirebaseAuthProvider/FirebaseAuthProvider.res
+++ b/src/components/FirebaseAuthProvider/FirebaseAuthProvider.res
@@ -15,11 +15,14 @@ let make = (~children) => {
let analytics = app->Analytics.getAnalytics
let functions = app->Functions.getFunctions
+ let messaging = app->Messaging.getMessaging
- {children}
+
+ {children}
+