about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-05-15 11:49:07 -0700
committerGitHub <noreply@github.com>2024-05-15 11:49:07 -0700
commitbf7b66d5c1c0d7f7bdcc1c1aa43b6881d797d1e8 (patch)
treedfbbd3babc73b4251883b8dc786b1dbea7f08c1a /src
parent31868b255f7be001821e03033b3bdd1070ea28cf (diff)
downloadvoidsky-bf7b66d5c1c0d7f7bdcc1c1aa43b6881d797d1e8.tar.zst
Add push notification extensions (#4005)
* add wav

* add sound to config

* add extension to `updateExtensions.sh`

* add ios source files

* add a build extension

* add a new module

* use correct type on ios

* update the build plugin

* add android handler

* create a patch for expo-notifications

* basic android implementation

* add entitlements for notifications extension

* add some generic logic for ios

* add age check logic

* add extension to app config

* remove dash

* move directory

* rename again

* update privacy manifest

* add prefs storage ios

* better types

* create interface for setting and getting prefs

* add notifications prefs for android

* add functions to module

* add types to js

* add prefs context

* add web stub

* wrap the app

* fix types

* more preferences for ios

* add a test toggle

* swap vars

* update patch

* fix patch error

* fix typo

* sigh

* sigh

* get stored prefs on launch

* anotehr type

* simplify

* about finished

* comment

* adjust plugin

* use supported file types

* update NSE

* futureproof ios

* futureproof android

* update sound file name

* handle initialization

* more cleanup

* update js types

* strict js types

* set the notification channel

* rm

* add silent channel

* add mute logic

* update patch

* podfile

* adjust channels

* fix android channel

* update readme

* oreo or higher

* nit

* don't use getValue

* nit
Diffstat (limited to 'src')
-rw-r--r--src/App.native.tsx11
-rw-r--r--src/App.web.tsx9
-rw-r--r--src/lib/hooks/useNotificationHandler.ts25
-rw-r--r--src/screens/Messages/Settings.tsx15
4 files changed, 52 insertions, 8 deletions
diff --git a/src/App.native.tsx b/src/App.native.tsx
index 9356be7a7..425d6ac6e 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -47,6 +47,7 @@ import {ThemeProvider as Alf} from '#/alf'
 import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
 import {Provider as PortalProvider} from '#/components/Portal'
 import {Splash} from '#/Splash'
+import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
 import I18nProvider from './locale/i18nProvider'
 import {listenSessionDropped} from './state/events'
 
@@ -102,10 +103,12 @@ function InnerApp() {
                           <LoggedOutViewProvider>
                             <SelectedFeedProvider>
                               <UnreadNotifsProvider>
-                                <GestureHandlerRootView style={s.h100pct}>
-                                  <TestCtrls />
-                                  <Shell />
-                                </GestureHandlerRootView>
+                                <BackgroundNotificationPreferencesProvider>
+                                  <GestureHandlerRootView style={s.h100pct}>
+                                    <TestCtrls />
+                                    <Shell />
+                                  </GestureHandlerRootView>
+                                </BackgroundNotificationPreferencesProvider>
                               </UnreadNotifsProvider>
                             </SelectedFeedProvider>
                           </LoggedOutViewProvider>
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 40ceb6942..900ceefd7 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -39,6 +39,7 @@ import {Shell} from 'view/shell/index'
 import {ThemeProvider as Alf} from '#/alf'
 import {useColorModeTheme} from '#/alf/util/useColorModeTheme'
 import {Provider as PortalProvider} from '#/components/Portal'
+import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
 import I18nProvider from './locale/i18nProvider'
 import {listenSessionDropped} from './state/events'
 
@@ -92,9 +93,11 @@ function InnerApp() {
                       <LoggedOutViewProvider>
                         <SelectedFeedProvider>
                           <UnreadNotifsProvider>
-                            <SafeAreaProvider>
-                              <Shell />
-                            </SafeAreaProvider>
+                            <BackgroundNotificationPreferencesProvider>
+                              <SafeAreaProvider>
+                                <Shell />
+                              </SafeAreaProvider>
+                            </BackgroundNotificationPreferencesProvider>
                           </UnreadNotifsProvider>
                         </SelectedFeedProvider>
                       </LoggedOutViewProvider>
diff --git a/src/lib/hooks/useNotificationHandler.ts b/src/lib/hooks/useNotificationHandler.ts
index 3240a4854..6f5fbd66b 100644
--- a/src/lib/hooks/useNotificationHandler.ts
+++ b/src/lib/hooks/useNotificationHandler.ts
@@ -8,6 +8,7 @@ import {track} from 'lib/analytics/analytics'
 import {useAccountSwitcher} from 'lib/hooks/useAccountSwitcher'
 import {NavigationProp} from 'lib/routes/types'
 import {logEvent} from 'lib/statsig/statsig'
+import {isAndroid} from 'platform/detection'
 import {useCurrentConvoId} from 'state/messages/current-convo-id'
 import {RQKEY as RQKEY_NOTIFS} from 'state/queries/notifications/feed'
 import {invalidateCachedUnreadPage} from 'state/queries/notifications/unread'
@@ -40,7 +41,7 @@ type NotificationPayload =
     }
 
 const DEFAULT_HANDLER_OPTIONS = {
-  shouldShowAlert: false,
+  shouldShowAlert: true,
   shouldPlaySound: false,
   shouldSetBadge: true,
 }
@@ -61,6 +62,28 @@ export function useNotificationsHandler() {
   const prevDate = React.useRef(0)
 
   React.useEffect(() => {
+    if (!isAndroid) return
+
+    Notifications.setNotificationChannelAsync('chat-messages', {
+      name: 'Chat',
+      importance: Notifications.AndroidImportance.MAX,
+      sound: 'dm.mp3',
+      showBadge: true,
+      vibrationPattern: [250],
+      lockscreenVisibility: Notifications.AndroidNotificationVisibility.PRIVATE,
+    })
+
+    Notifications.setNotificationChannelAsync('chat-messages-muted', {
+      name: 'Chat - Muted',
+      importance: Notifications.AndroidImportance.MAX,
+      sound: null,
+      showBadge: true,
+      vibrationPattern: [250],
+      lockscreenVisibility: Notifications.AndroidNotificationVisibility.PRIVATE,
+    })
+  }, [])
+
+  React.useEffect(() => {
     const handleNotification = (payload?: NotificationPayload) => {
       if (!payload) return
 
diff --git a/src/screens/Messages/Settings.tsx b/src/screens/Messages/Settings.tsx
index e4fff1251..7ad21b400 100644
--- a/src/screens/Messages/Settings.tsx
+++ b/src/screens/Messages/Settings.tsx
@@ -15,8 +15,10 @@ import * as Toast from '#/view/com/util/Toast'
 import {ViewHeader} from '#/view/com/util/ViewHeader'
 import {CenteredView} from '#/view/com/util/Views'
 import {atoms as a} from '#/alf'
+import * as Toggle from '#/components/forms/Toggle'
 import {RadioGroup} from '#/components/RadioGroup'
 import {Text} from '#/components/Typography'
+import {useBackgroundNotificationPreferences} from '../../../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
 import {ClipClopGate} from './gate'
 
 type AllowIncoming = 'all' | 'none' | 'following'
@@ -28,6 +30,7 @@ export function MessagesSettingsScreen({}: Props) {
   const {data: profile} = useProfileQuery({
     did: currentAccount!.did,
   }) as UseQueryResult<AppBskyActorDefs.ProfileViewDetailed, Error>
+  const {preferences, setPref} = useBackgroundNotificationPreferences()
 
   const {mutate: updateDeclaration} = useUpdateActorDeclaration({
     onError: () => {
@@ -65,6 +68,18 @@ export function MessagesSettingsScreen({}: Props) {
           onSelect={onSelectItem}
         />
       </View>
+      <View style={[a.px_md, a.py_lg, a.gap_md]}>
+        <Toggle.Item
+          name="a"
+          label="Click me"
+          value={preferences.playSoundChat}
+          onChange={() => {
+            setPref('playSoundChat', !preferences.playSoundChat)
+          }}>
+          <Toggle.Checkbox />
+          <Toggle.LabelText>Notification Sounds</Toggle.LabelText>
+        </Toggle.Item>
+      </View>
     </CenteredView>
   )
 }