diff --git a/app/definitions/INotification.ts b/app/definitions/INotification.ts new file mode 100644 index 000000000..77467d9d7 --- /dev/null +++ b/app/definitions/INotification.ts @@ -0,0 +1,12 @@ +export interface INotification { + message: string; + style: string; + ejson: string; + collapse_key: string; + notId: string; + msgcnt: string; + title: string; + from: string; + image: string; + soundname: string; +} diff --git a/app/definitions/index.ts b/app/definitions/index.ts index f9ca20d4a..80eeb88ca 100644 --- a/app/definitions/index.ts +++ b/app/definitions/index.ts @@ -2,6 +2,13 @@ import { RouteProp } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import { Dispatch } from 'redux'; +export * from './IAttachment'; +export * from './IMessage'; +export * from './INotification'; +export * from './IRoom'; +export * from './IServer'; +export * from './ISubscription'; + export interface IBaseScreen, S extends string> { navigation: StackNavigationProp; route: RouteProp; diff --git a/app/notifications/push/index.js b/app/notifications/push/index.js deleted file mode 100644 index 074e22bf3..000000000 --- a/app/notifications/push/index.js +++ /dev/null @@ -1,50 +0,0 @@ -import EJSON from 'ejson'; - -import store from '../../lib/createStore'; -import { deepLinkingOpen } from '../../actions/deepLinking'; -import { isFDroidBuild } from '../../constants/environment'; -import PushNotification from './push'; - -export const onNotification = notification => { - if (notification) { - const data = notification.getData(); - if (data) { - try { - const { rid, name, sender, type, host, messageType, messageId } = EJSON.parse(data.ejson); - - const types = { - c: 'channel', - d: 'direct', - p: 'group', - l: 'channels' - }; - let roomName = type === 'd' ? sender.username : name; - if (type === 'l') { - roomName = sender.name; - } - - const params = { - host, - rid, - messageId, - path: `${types[type]}/${roomName}`, - isCall: messageType === 'jitsi_call_started' - }; - store.dispatch(deepLinkingOpen(params)); - } catch (e) { - console.warn(e); - } - } - } -}; - -export const getDeviceToken = () => PushNotification.getDeviceToken(); -export const setBadgeCount = count => PushNotification.setBadgeCount(count); -export const initializePushNotifications = () => { - if (!isFDroidBuild) { - setBadgeCount(); - return PushNotification.configure({ - onNotification - }); - } -}; diff --git a/app/notifications/push/index.ts b/app/notifications/push/index.ts new file mode 100644 index 000000000..af25c9eed --- /dev/null +++ b/app/notifications/push/index.ts @@ -0,0 +1,57 @@ +import EJSON from 'ejson'; + +import store from '../../lib/createStore'; +import { deepLinkingOpen } from '../../actions/deepLinking'; +import { isFDroidBuild } from '../../constants/environment'; +import PushNotification from './push'; +import { INotification, SubscriptionType } from '../../definitions'; + +interface IEjson { + rid: string; + name: string; + sender: { username: string; name: string }; + type: string; + host: string; + messageType: string; + messageId: string; +} + +export const onNotification = (notification: INotification): void => { + if (notification) { + try { + const { rid, name, sender, type, host, messageType, messageId }: IEjson = EJSON.parse(notification.ejson); + + const types: Record = { + c: 'channel', + d: 'direct', + p: 'group', + l: 'channels' + }; + let roomName = type === SubscriptionType.DIRECT ? sender.username : name; + if (type === SubscriptionType.OMNICHANNEL) { + roomName = sender.name; + } + + const params = { + host, + rid, + messageId, + path: `${types[type]}/${roomName}`, + isCall: messageType === 'jitsi_call_started' + }; + // TODO REDUX MIGRATION TO TS + store.dispatch(deepLinkingOpen(params)); + } catch (e) { + console.warn(e); + } + } +}; + +export const getDeviceToken = (): string => PushNotification.getDeviceToken(); +export const setBadgeCount = (count?: number): void => PushNotification.setBadgeCount(count); +export const initializePushNotifications = (): Promise | undefined => { + if (!isFDroidBuild) { + setBadgeCount(); + return PushNotification.configure(onNotification); + } +}; diff --git a/app/notifications/push/push.android.js b/app/notifications/push/push.android.js deleted file mode 100644 index 51e767ad3..000000000 --- a/app/notifications/push/push.android.js +++ /dev/null @@ -1,32 +0,0 @@ -import { NotificationsAndroid, PendingNotifications } from 'react-native-notifications'; - -class PushNotification { - constructor() { - this.onRegister = null; - this.onNotification = null; - this.deviceToken = null; - - NotificationsAndroid.setRegistrationTokenUpdateListener(deviceToken => { - this.deviceToken = deviceToken; - }); - - NotificationsAndroid.setNotificationOpenedListener(notification => { - this.onNotification(notification); - }); - } - - getDeviceToken() { - return this.deviceToken; - } - - setBadgeCount = () => {}; - - configure(params) { - this.onRegister = params.onRegister; - this.onNotification = params.onNotification; - NotificationsAndroid.refreshToken(); - return PendingNotifications.getInitialNotification(); - } -} - -export default new PushNotification(); diff --git a/app/notifications/push/push.ios.js b/app/notifications/push/push.ios.js deleted file mode 100644 index 068be4ee9..000000000 --- a/app/notifications/push/push.ios.js +++ /dev/null @@ -1,61 +0,0 @@ -import NotificationsIOS, { NotificationAction, NotificationCategory } from 'react-native-notifications'; - -import reduxStore from '../../lib/createStore'; -import I18n from '../../i18n'; - -const replyAction = new NotificationAction({ - activationMode: 'background', - title: I18n.t('Reply'), - textInput: { - buttonTitle: I18n.t('Reply'), - placeholder: I18n.t('Type_message') - }, - identifier: 'REPLY_ACTION' -}); - -class PushNotification { - constructor() { - this.onRegister = null; - this.onNotification = null; - this.deviceToken = null; - - NotificationsIOS.addEventListener('remoteNotificationsRegistered', deviceToken => { - this.deviceToken = deviceToken; - }); - - NotificationsIOS.addEventListener('notificationOpened', (notification, completion) => { - const { background } = reduxStore.getState().app; - if (background) { - this.onNotification(notification); - } - completion(); - }); - - const actions = []; - actions.push( - new NotificationCategory({ - identifier: 'MESSAGE', - actions: [replyAction] - }) - ); - NotificationsIOS.requestPermissions(actions); - } - - getDeviceToken() { - return this.deviceToken; - } - - setBadgeCount = (count = 0) => { - NotificationsIOS.setBadgesCount(count); - }; - - async configure(params) { - this.onRegister = params.onRegister; - this.onNotification = params.onNotification; - - const initial = await NotificationsIOS.getInitialNotification(); - // NotificationsIOS.consumeBackgroundQueue(); - return Promise.resolve(initial); - } -} -export default new PushNotification(); diff --git a/app/notifications/push/push.ios.ts b/app/notifications/push/push.ios.ts new file mode 100644 index 000000000..92c2d3a6c --- /dev/null +++ b/app/notifications/push/push.ios.ts @@ -0,0 +1,63 @@ +// @ts-ignore +// TODO BUMP LIB VERSION +import NotificationsIOS, { NotificationAction, NotificationCategory, Notification } from 'react-native-notifications'; + +import reduxStore from '../../lib/createStore'; +import I18n from '../../i18n'; +import { INotification } from '../../definitions/INotification'; + +class PushNotification { + onNotification: (notification: Notification) => void; + deviceToken: string; + + constructor() { + this.onNotification = () => {}; + this.deviceToken = ''; + + NotificationsIOS.addEventListener('remoteNotificationsRegistered', (deviceToken: string) => { + this.deviceToken = deviceToken; + }); + + NotificationsIOS.addEventListener('notificationOpened', (notification: Notification, completion: () => void) => { + // TODO REDUX MIGRATION TO TS + const { background } = reduxStore.getState().app; + if (background) { + this.onNotification(notification?.getData()); + } + completion(); + }); + + const actions = [ + new NotificationCategory({ + identifier: 'MESSAGE', + actions: [ + new NotificationAction({ + activationMode: 'background', + title: I18n.t('Reply'), + textInput: { + buttonTitle: I18n.t('Reply'), + placeholder: I18n.t('Type_message') + }, + identifier: 'REPLY_ACTION' + }) + ] + }) + ]; + NotificationsIOS.requestPermissions(actions); + } + + getDeviceToken() { + return this.deviceToken; + } + + setBadgeCount = (count = 0) => { + NotificationsIOS.setBadgesCount(count); + }; + + async configure(onNotification: (notification: INotification) => void) { + this.onNotification = onNotification; + const initial = await NotificationsIOS.getInitialNotification(); + return Promise.resolve(initial); + } +} +export default new PushNotification(); diff --git a/app/notifications/push/push.ts b/app/notifications/push/push.ts new file mode 100644 index 000000000..16aa8cf5c --- /dev/null +++ b/app/notifications/push/push.ts @@ -0,0 +1,36 @@ +// @ts-ignore +// TODO BUMP LIB VERSION +import { NotificationsAndroid, PendingNotifications, Notification } from 'react-native-notifications'; + +import { INotification } from '../../definitions/INotification'; + +class PushNotification { + onNotification: (notification: Notification) => void; + deviceToken: string; + constructor() { + this.onNotification = () => {}; + this.deviceToken = ''; + + NotificationsAndroid.setRegistrationTokenUpdateListener((deviceToken: string) => { + this.deviceToken = deviceToken; + }); + + NotificationsAndroid.setNotificationOpenedListener((notification: Notification) => { + this.onNotification(notification?.getData()); + }); + } + + getDeviceToken() { + return this.deviceToken; + } + + setBadgeCount = (_?: number) => {}; + + configure(onNotification: (notification: INotification) => void) { + this.onNotification = onNotification; + NotificationsAndroid.refreshToken(); + return PendingNotifications.getInitialNotification(); + } +} + +export default new PushNotification(); diff --git a/package.json b/package.json index d05db7ecb..e8ebd4a24 100644 --- a/package.json +++ b/package.json @@ -143,6 +143,7 @@ "@rocket.chat/eslint-config": "^0.4.0", "@storybook/addon-storyshots": "5.3.21", "@storybook/react-native": "5.3.25", + "@types/ejson": "^2.1.3", "@types/jest": "^26.0.24", "@types/lodash": "^4.14.171", "@types/react": "^17.0.14", diff --git a/yarn.lock b/yarn.lock index 2713d13ad..923363782 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4198,6 +4198,11 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/ejson@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@types/ejson/-/ejson-2.1.3.tgz#29a0028db4180b589b62eb2b6b9367c65b0c1864" + integrity sha512-Sd+XISmDWOypfDcsKeQkhykSMgYVAWJxhf7f0ySvfy2tYo+im26M/6FfqjCEiPSDAEugiuZKtA+wWeANKueWIg== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"