Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
Handle notif reminder prompt (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
piazzatron committed Dec 10, 2020
1 parent 03a0ad0 commit 9d46ffb
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React, { RefObject, useCallback } from 'react'
import { checkNotifications, RESULTS } from 'react-native-permissions'

import { MessagePostingWebView } from '../../types/MessagePostingWebView'
import { postMessage } from '../../utils/postMessage'
import { postMessage as postMessageUtil } from '../../utils/postMessage'
import useSessionCount from '../../utils/useSessionCount'
import { MessageType } from '../../message'
import { Message, MessageType } from '../../message'

const REMINDER_EVERY_N_SESSIONS = 10

Expand All @@ -20,45 +20,51 @@ const NotificationReminderWrapper = ({ webRef, isSignedIn }: OwnProps) => {
return null
}

const NotificationReminder = ({ webRef }: { webRef: RefObject<MessagePostingWebView> }) => {

const remindUserToTurnOnNotifications = useCallback((count: number) => {
if (webRef.current) {
checkNotifications().then(({status}) => {
switch (status) {
case RESULTS.UNAVAILABLE:
// Notifications are not available (on this device / in this context).
// Do nothing.
return
case RESULTS.LIMITED:
// Some subset of notification features are enabled, let the user be.
// Do nothing.
return
case RESULTS.GRANTED:
// The user already has given notifications permissions!
// Do nothing.
return
case RESULTS.BLOCKED:
// The user has explicitly blocked notifications.
// Don't be a jerk.
// Do nothing.
return
case RESULTS.DENIED:
// The permission has not been requested or has been denied but it still requestable
// Appeal to the user to enable notifications
postMessage(webRef.current, {
type: MessageType.ENABLE_PUSH_NOTIFICATIONS_REMINDER,
isAction: true
})
}
}).catch((error) => {
// Not sure what happened, but swallow the error. Not worth blocking on.
console.error(error)
})
// Sends a notification to the WebApp to turn on push notifications if we're in the DENIED
// state. Is called from the `NotificationsReminder` component as well as `handleMessage`
export const remindUserToTurnOnNotifications = (postMessage: (message: Message) => void) => {
checkNotifications().then(({status}) => {
switch (status) {
case RESULTS.UNAVAILABLE:
// Notifications are not available (on this device / in this context).
// Do nothing.
return
case RESULTS.LIMITED:
// Some subset of notification features are enabled, let the user be.
// Do nothing.
return
case RESULTS.GRANTED:
// The user already has given notifications permissions!
// Do nothing.
return
case RESULTS.BLOCKED:
// The user has explicitly blocked notifications.
// Don't be a jerk.
// Do nothing.
return
case RESULTS.DENIED:
// The permission has not been requested or has been denied but it still requestable
// Appeal to the user to enable notifications
postMessage({
type: MessageType.ENABLE_PUSH_NOTIFICATIONS_REMINDER,
isAction: true
})
}
}, [webRef])
}).catch((error) => {
// Not sure what happened, but swallow the error. Not worth blocking on.
console.error(error)
})
}

useSessionCount(remindUserToTurnOnNotifications, REMINDER_EVERY_N_SESSIONS)
const NotificationReminder = ({ webRef }: { webRef: RefObject<MessagePostingWebView> }) => {

// Sets up reminders to turn on push notifications
const reminder = useCallback(() => {
const sender = webRef.current
if (!sender) return
remindUserToTurnOnNotifications((msg: Message) => postMessageUtil(sender, msg))
}, [webRef])
useSessionCount(reminder, REMINDER_EVERY_N_SESSIONS)
// No UI component
return null
}
Expand Down
11 changes: 4 additions & 7 deletions packages/audius-mobile-client/src/components/web/WebApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import {
Platform,
NativeSyntheticEvent,
AppState as RNState,
AppStateStatus,
Linking,
Keyboard,
View,
BackHandler
} from 'react-native'
import React, { useRef, useState, useEffect, RefObject, useCallback } from 'react'
Expand All @@ -30,6 +27,7 @@ import { MessagePostingWebView } from '../../types/MessagePostingWebView'
import useAppState from '../../utils/useAppState'
import useKeyboardListeners from '../../utils/useKeyboardListeners'
import NotificationReminder from '../notification-reminder/NotificationReminder'
import {postMessage as postMessageUtil} from '../../utils/postMessage'

const USE_LOCALHOST_APP = Config.USE_LOCALHOST_APP
const LOCALHOST_APP_URL = 'http://localhost:3000/feed'
Expand Down Expand Up @@ -247,7 +245,7 @@ const WebApp = ({
} else {
webRef.current.goBack()
}
}
}
// Prevent default (exit app)
return true
}
Expand Down Expand Up @@ -376,7 +374,7 @@ const WebApp = ({
onMessage(
message,
// @ts-ignore
webRef.current.postMessage,
(message: Message) => postMessageUtil(webRef.current, message),
// @ts-ignore
reload,
// @ts-ignore
Expand Down Expand Up @@ -476,7 +474,6 @@ const WebApp = ({
const { title, url } = nativeEvent
if (url === '' || title === '') reloadViewOnServerError()
}}

/>
</PullToRefresh>
<SplashScreen
Expand Down Expand Up @@ -512,7 +509,7 @@ const mapStateToProps = (state: AppState) => ({
const mapDispatchToProps = (dispatch: Dispatch) => ({
onMessage: (
message: Message,
postMessage: (message: string) => void,
postMessage: (message: Message) => void,
reload: () => void,
state: AppState
) => {
Expand Down
33 changes: 20 additions & 13 deletions packages/audius-mobile-client/src/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Identify, Track, Screen, AnalyticsMessage } from './types/analytics'
import { checkConnectivity, Connectivity } from './utils/connectivity'
import { Provider } from './store/oauth/reducer'
import { handleWebAppLog } from './utils/logging'
import { remindUserToTurnOnNotifications } from './components/notification-reminder/NotificationReminder'

let sentInitialTheme = false

Expand Down Expand Up @@ -52,6 +53,7 @@ export enum MessageType {
DISABLE_PUSH_NOTIFICATIONS = 'disable-push-notifications',
RESET_NOTIFICATIONS_BADGE_COUNT = 'reset-notifications-badge-count',
ENABLE_PUSH_NOTIFICATIONS_REMINDER = 'action/enable-push-notifications-reminder',
PROMPT_PUSH_NOTIFICATION_REMINDER = 'prompt-push-notifications-reminder',

// Haptics
HAPTIC_FEEDBACK = 'haptic-feedback',
Expand Down Expand Up @@ -108,7 +110,7 @@ const isIos = Platform.OS === 'ios'
export const handleMessage = async (
message: Message | AnalyticsMessage,
dispatch: Dispatch,
postMessage: (message: string) => void,
postMessage: (message: Message) => void,
reload: () => void,
state: AppState
) => {
Expand All @@ -121,12 +123,12 @@ export const handleMessage = async (
case MessageType.SEEK_TRACK:
return dispatch(audioActions.seek(message))
case MessageType.GET_POSITION:
postMessage(JSON.stringify({
postMessage({
type: message.type,
id: message.id,
// @ts-ignore
...global.progress
}))
})
break
case MessageType.PERSIST_QUEUE:
return dispatch(audioActions.persistQueue(message))
Expand Down Expand Up @@ -159,29 +161,34 @@ export const handleMessage = async (
{
PushNotifications.requestPermission()
const info = await PushNotifications.getToken()
postMessage(JSON.stringify({
postMessage({
type: message.type,
id: message.id,
...info
}))
})
break
}
case MessageType.DISABLE_PUSH_NOTIFICATIONS:
{
const info = await PushNotifications.getToken()
PushNotifications.deregister()
postMessage(JSON.stringify({
postMessage({
type: message.type,
id: message.id,
...info
}))
})
break
}
case MessageType.RESET_NOTIFICATIONS_BADGE_COUNT:
{
PushNotifications.setBadgeCount(0)
break
}
case MessageType.PROMPT_PUSH_NOTIFICATION_REMINDER:
{
remindUserToTurnOnNotifications(postMessage)
break
}

// OAuth
case MessageType.REQUEST_TWITTER_AUTH:
Expand All @@ -196,21 +203,21 @@ export const handleMessage = async (
return dispatch(lifecycleActions.signedIn())
case MessageType.REQUEST_NETWORK_CONNECTED:
const isConnected = checkConnectivity(Connectivity.netInfo)
postMessage(JSON.stringify({
postMessage({
type: MessageType.IS_NETWORK_CONNECTED,
isConnected,
isAction: true
}))
})
break

// Version
case MessageType.GET_VERSION:
const version = VersionNumber.appVersion
postMessage(JSON.stringify({
postMessage({
type: message.type,
id: message.id,
version
}))
})
break

// Android specific
Expand All @@ -229,11 +236,11 @@ export const handleMessage = async (
} else {
prefers = await getPrefersDarkModeChange()
}
postMessage(JSON.stringify({
postMessage({
type: message.type,
id: message.id,
prefersDarkMode: prefers
}))
})
break

case MessageType.SHARE:
Expand Down
11 changes: 10 additions & 1 deletion packages/audius-mobile-client/src/utils/postMessage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { MessageType, Message } from "src/message"
import { MessageType, Message } from "../message"

export type MessageSender = {
postMessage: (message: string) => void
}

const SPAMMY_MESSAGES = new Set([MessageType.GET_POSITION])

// Stringifies the message, logs it, and sends it
export const postMessage = (sender: MessageSender, message: Message) => {
const stringified = JSON.stringify(message)

// Log it if it isn't spammy
if (!SPAMMY_MESSAGES.has(message.type)) {
console.debug(`Sending message to web client: ${stringified}`)
}

sender.postMessage(stringified)
}
4 changes: 2 additions & 2 deletions packages/audius-mobile-client/src/utils/useSessionCount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const incrementSessionCount = async () => {
* @param startAt which session to start at
*/
const useSessionCount = (
callback: (count?: number) => void,
callback: () => void,
frequency: number,
startAt: number = 1
) => {
Expand All @@ -37,7 +37,7 @@ const useSessionCount = (
count % frequency === 0 &&
count !== calledAtCount
) {
callback(count)
callback()
setCalledAtCount(count)
}
}
Expand Down

0 comments on commit 9d46ffb

Please sign in to comment.