update dependencies (#4958)
* update dependencies * revert keychain update * Update dependencies & Fastlane * set path agnostic for bash in scrips * Fix open from push notification race * patch react-native-localize
This commit is contained in:
parent
4f668f0fdf
commit
b226d451f3
62 changed files with 2848 additions and 2896 deletions
|
|
@ -250,7 +250,7 @@ dependencies {
|
|||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
|
||||
implementation project(':reactnativenotifications')
|
||||
implementation 'com.google.firebase:firebase-messaging:17.3.4'
|
||||
implementation "com.google.firebase:firebase-messaging:$firebaseVersion"
|
||||
|
||||
// For animated GIF support
|
||||
implementation 'com.facebook.fresco:fresco:2.0.0'
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@
|
|||
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
|
||||
<meta-data android:name="android.content.APP_RESTRICTIONS"
|
||||
android:resource="@xml/app_restrictions" />
|
||||
|
||||
<meta-data android:name="com.wix.reactnativenotifications.gcmSenderId" android:value="184930218130\"/>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
|
|
|
|||
|
|
@ -300,11 +300,11 @@ public class CustomPushNotification extends PushNotification {
|
|||
|
||||
private Notification.MessagingStyle getMessagingStyle(Bundle bundle) {
|
||||
Notification.MessagingStyle messagingStyle;
|
||||
String senderId = bundle.getString("sender_id");
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P || senderId == null) {
|
||||
messagingStyle = new Notification.MessagingStyle("");
|
||||
} else {
|
||||
String senderId = bundle.getString("sender_id");
|
||||
Person sender = new Person.Builder()
|
||||
.setKey(senderId)
|
||||
.setName("")
|
||||
|
|
@ -364,7 +364,7 @@ public class CustomPushNotification extends PushNotification {
|
|||
int bundleCount = bundleList.size() - 1;
|
||||
for (int i = bundleCount; i >= 0; i--) {
|
||||
Bundle data = bundleList.get(i);
|
||||
String message = data.getString("message");
|
||||
String message = data.getString("message", data.getString("body"));
|
||||
String senderId = data.getString("sender_id");
|
||||
if (senderId == null) {
|
||||
senderId = "sender_id";
|
||||
|
|
@ -372,7 +372,7 @@ public class CustomPushNotification extends PushNotification {
|
|||
Bundle userInfoBundle = data.getBundle("userInfo");
|
||||
String senderName = getSenderName(data);
|
||||
if (userInfoBundle != null) {
|
||||
boolean localPushNotificationTest = userInfoBundle.getBoolean("localTest");
|
||||
boolean localPushNotificationTest = userInfoBundle.getBoolean("test");
|
||||
if (localPushNotificationTest) {
|
||||
senderName = "Test";
|
||||
}
|
||||
|
|
@ -403,13 +403,15 @@ public class CustomPushNotification extends PushNotification {
|
|||
|
||||
NotificationChannel notificationChannel = mHighImportanceChannel;
|
||||
|
||||
boolean localPushNotificationTest = false;
|
||||
boolean testNotification = false;
|
||||
boolean localNotification = false;
|
||||
Bundle userInfoBundle = bundle.getBundle("userInfo");
|
||||
if (userInfoBundle != null) {
|
||||
localPushNotificationTest = userInfoBundle.getBoolean("localTest");
|
||||
testNotification = userInfoBundle.getBoolean("test");
|
||||
localNotification = userInfoBundle.getBoolean("local");
|
||||
}
|
||||
|
||||
if (mAppLifecycleFacade.isAppVisible() && !localPushNotificationTest) {
|
||||
if (mAppLifecycleFacade.isAppVisible() && !testNotification && !localNotification) {
|
||||
notificationChannel = mMinImportanceChannel;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ buildscript {
|
|||
targetSdkVersion = 29
|
||||
supportLibVersion = "28.0.0"
|
||||
kotlinVersion = "1.3.61"
|
||||
firebaseVersion = "21.0.0"
|
||||
RNNKotlinVersion = kotlinVersion
|
||||
|
||||
}
|
||||
|
|
@ -20,7 +21,7 @@ buildscript {
|
|||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
classpath 'com.google.gms:google-services:4.2.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
rootProject.name = 'Mattermost'
|
||||
include ':reactnativenotifications'
|
||||
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/android/app')
|
||||
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/lib/android/app')
|
||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||
include ':app'
|
||||
|
|
|
|||
|
|
@ -293,6 +293,8 @@ export function markChannelViewedAndRead(channelId, previousChannelId, markOnSer
|
|||
const actions = markAsViewedAndReadBatch(state, channelId, previousChannelId, markOnServer);
|
||||
|
||||
dispatch(batchActions(actions, 'BATCH_MARK_CHANNEL_VIEWED_AND_READ'));
|
||||
|
||||
return {data: true};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {isTimezoneEnabled} from '@mm-redux/selectors/entities/timezone';
|
|||
import {getCurrentUserId} from '@mm-redux/selectors/entities/users';
|
||||
|
||||
import {setAppCredentials} from 'app/init/credentials';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import PushNotifications from '@init/push_notifications';
|
||||
import {getDeviceTimezone} from 'app/utils/timezone';
|
||||
import {setCSRFFromCookie} from 'app/utils/security';
|
||||
import {loadConfigAndLicense} from 'app/actions/views/root';
|
||||
|
|
@ -94,11 +94,11 @@ export function scheduleExpiredNotification(intl) {
|
|||
});
|
||||
|
||||
if (expiresAt) {
|
||||
PushNotifications.localNotificationSchedule({
|
||||
date: new Date(expiresAt),
|
||||
message,
|
||||
PushNotifications.scheduleNotification({
|
||||
fireDate: expiresAt,
|
||||
body: message,
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
local: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,17 +66,17 @@ export function loadConfigAndLicense() {
|
|||
export function loadFromPushNotification(notification) {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const {data} = notification;
|
||||
const {payload} = notification;
|
||||
const {currentTeamId, teams, myMembers: myTeamMembers} = state.entities.teams;
|
||||
const {channels} = state.entities.channels;
|
||||
|
||||
let channelId = '';
|
||||
let teamId = currentTeamId;
|
||||
if (data) {
|
||||
channelId = data.channel_id;
|
||||
if (payload) {
|
||||
channelId = payload.channel_id;
|
||||
|
||||
// when the notification does not have a team id is because its from a DM or GM
|
||||
teamId = data.team_id || currentTeamId;
|
||||
teamId = payload.team_id || currentTeamId;
|
||||
}
|
||||
|
||||
// load any missing data
|
||||
|
|
@ -96,6 +96,8 @@ export function loadFromPushNotification(notification) {
|
|||
}
|
||||
|
||||
dispatch(handleSelectTeamAndChannel(teamId, channelId));
|
||||
|
||||
return {data: true};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {Client4} from '@mm-redux/client';
|
|||
import {getConfig} from '@mm-redux/selectors/entities/general';
|
||||
import {isMinimumServerVersion} from '@mm-redux/utils/helpers';
|
||||
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import PushNotifications from '@init/push_notifications';
|
||||
|
||||
const sortByNewest = (a, b) => {
|
||||
if (a.create_at > b.create_at) {
|
||||
|
|
@ -56,11 +56,11 @@ export function scheduleExpiredNotification(intl) {
|
|||
if (expiresAt) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Schedule Session Expiry Local Push Notification', expiresAt);
|
||||
PushNotifications.localNotificationSchedule({
|
||||
date: new Date(expiresAt),
|
||||
message,
|
||||
PushNotifications.scheduleNotification({
|
||||
fireDate: expiresAt,
|
||||
body: message,
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
local: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import networkConnectionListener, {checkConnection} from '@utils/network';
|
|||
import {t} from '@utils/i18n';
|
||||
|
||||
import mattermostBucket from 'app/mattermost_bucket';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import PushNotifications from '@init/push_notifications';
|
||||
|
||||
const MAX_WEBSOCKET_RETRIES = 3;
|
||||
const CONNECTION_RETRY_SECONDS = 5;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {loadMe, logout} from '@actions/views/user';
|
|||
import LocalConfig from '@assets/config';
|
||||
import {NavigationTypes, ViewTypes} from '@constants';
|
||||
import {getTranslations, resetMomentLocale} from '@i18n';
|
||||
import PushNotifications from '@init/push_notifications';
|
||||
import {setAppState, setServerVersion} from '@mm-redux/actions/general';
|
||||
import {getTeams} from '@mm-redux/actions/teams';
|
||||
import {autoUpdateTimezone} from '@mm-redux/actions/timezone';
|
||||
|
|
@ -38,7 +39,6 @@ import {getDeviceTimezone} from '@utils/timezone';
|
|||
|
||||
import mattermostBucket from 'app/mattermost_bucket';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
|
||||
import {getAppCredentials, removeAppCredentials} from './credentials';
|
||||
import emmProvider from './emm_provider';
|
||||
|
|
@ -384,12 +384,12 @@ class GlobalEventHandler {
|
|||
}
|
||||
|
||||
handleInAppNotification = (notification) => {
|
||||
const {data} = notification;
|
||||
const {payload} = notification;
|
||||
const {getState} = Store.redux;
|
||||
const state = getState();
|
||||
const currentChannelId = getCurrentChannelId(state);
|
||||
|
||||
if (data && data.channel_id !== currentChannelId) {
|
||||
if (payload?.channel_id !== currentChannelId) {
|
||||
const screen = 'Notification';
|
||||
const passProps = {
|
||||
notification,
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import semver from 'semver/preload';
|
|||
|
||||
import {MinServerVersion} from '@assets/config';
|
||||
import * as I18n from '@i18n';
|
||||
import PushNotification from '@init/push_notifications';
|
||||
import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
import Store from '@store/store';
|
||||
import intitialState from '@store/initial_state';
|
||||
|
||||
import PushNotification from 'app/push_notifications';
|
||||
import mattermostBucket from 'app/mattermost_bucket';
|
||||
|
||||
import GlobalEventHandler from './global_event_handler';
|
||||
|
|
@ -29,14 +29,6 @@ jest.mock('@utils/error_handling', () => ({
|
|||
},
|
||||
}));
|
||||
|
||||
jest.mock('react-native-notifications', () => ({
|
||||
addEventListener: jest.fn(),
|
||||
cancelAllLocalNotifications: jest.fn(),
|
||||
setBadgesCount: jest.fn(),
|
||||
NotificationAction: jest.fn(),
|
||||
NotificationCategory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('react-native-status-bar-size', () => ({
|
||||
addEventListener: jest.fn(),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,189 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Platform} from 'react-native';
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
|
||||
import {markChannelViewedAndRead, fetchPostActionWithRetry} from '@actions/views/channel';
|
||||
import {dismissAllModals, popToRoot} from '@actions/navigation';
|
||||
import {getPosts} from '@actions/views/post';
|
||||
import {
|
||||
createPostForNotificationReply,
|
||||
loadFromPushNotification,
|
||||
} from '@actions/views/root';
|
||||
import {logout} from '@actions/views/user';
|
||||
import {NavigationTypes, ViewTypes} from '@constants';
|
||||
import {getLocalizedMessage} from '@i18n';
|
||||
import {getCurrentServerUrl, getAppCredentials} from '@init/credentials';
|
||||
import {setDeviceToken} from '@mm-redux/actions/general';
|
||||
import {Client4} from '@mm-redux/client';
|
||||
import {General} from '@mm-redux/constants';
|
||||
import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
import {getCurrentLocale} from '@selectors/i18n';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import Store from '@store/store';
|
||||
import {waitForHydration} from '@store/utils';
|
||||
import {t} from '@utils/i18n';
|
||||
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
|
||||
const NOTIFICATION_TYPE = {
|
||||
CLEAR: 'clear',
|
||||
MESSAGE: 'message',
|
||||
SESSION: 'session',
|
||||
};
|
||||
|
||||
class PushNotificationUtils {
|
||||
constructor() {
|
||||
this.configured = false;
|
||||
this.replyNotificationData = null;
|
||||
}
|
||||
|
||||
configure = async () => {
|
||||
return PushNotifications.configure({
|
||||
onRegister: this.onRegisterDevice,
|
||||
onNotification: this.onPushNotification,
|
||||
onReply: this.onPushNotificationReply,
|
||||
popInitialNotification: true,
|
||||
requestPermissions: true,
|
||||
});
|
||||
};
|
||||
|
||||
loadFromNotification = async (notification) => {
|
||||
await Store.redux.dispatch(loadFromPushNotification(notification));
|
||||
|
||||
// if we have a componentId means that the app is already initialized
|
||||
const componentId = EphemeralStore.getNavigationTopComponentId();
|
||||
if (componentId) {
|
||||
EventEmitter.emit(NavigationTypes.CLOSE_MAIN_SIDEBAR);
|
||||
EventEmitter.emit(NavigationTypes.CLOSE_SETTINGS_SIDEBAR);
|
||||
|
||||
await dismissAllModals();
|
||||
await popToRoot();
|
||||
|
||||
PushNotifications.resetNotification();
|
||||
}
|
||||
};
|
||||
|
||||
onPushNotification = async (deviceNotification) => {
|
||||
const {dispatch} = Store.redux;
|
||||
const {data, foreground, message, userInfo, userInteraction} = deviceNotification;
|
||||
const notification = {
|
||||
data,
|
||||
message,
|
||||
userInfo,
|
||||
};
|
||||
|
||||
waitForHydration(Store.redux, () => {
|
||||
switch (data.type) {
|
||||
case NOTIFICATION_TYPE.CLEAR:
|
||||
dispatch(markChannelViewedAndRead(data.channel_id, null, false));
|
||||
break;
|
||||
case NOTIFICATION_TYPE.MESSAGE:
|
||||
// get the posts for the channel as soon as possible
|
||||
dispatch(fetchPostActionWithRetry(getPosts(data.channel_id)));
|
||||
|
||||
if (foreground) {
|
||||
EventEmitter.emit(ViewTypes.NOTIFICATION_IN_APP, notification);
|
||||
} else if (userInteraction && !notification?.userInfo?.localNotification && !notification?.data?.localNotification) {
|
||||
this.loadFromNotification(notification);
|
||||
}
|
||||
break;
|
||||
case NOTIFICATION_TYPE.SESSION:
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Session expired notification');
|
||||
dispatch(logout());
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onPushNotificationReply = async (data, text, completion) => {
|
||||
const {dispatch, getState} = Store.redux;
|
||||
const state = getState();
|
||||
const credentials = await getAppCredentials(); // TODO Change to handle multiple servers
|
||||
const url = await getCurrentServerUrl(); // TODO Change to handle multiple servers
|
||||
const token = credentials.password;
|
||||
const usernameParsed = credentials.username.split(',');
|
||||
const [, currentUserId] = usernameParsed;
|
||||
|
||||
if (currentUserId) {
|
||||
// one thing to note is that for android it will reply to the last post in the stack
|
||||
const rootId = data.root_id || data.post_id;
|
||||
const post = {
|
||||
user_id: currentUserId,
|
||||
channel_id: data.channel_id,
|
||||
root_id: rootId,
|
||||
parent_id: rootId,
|
||||
message: text,
|
||||
};
|
||||
|
||||
if (!Client4.getUrl()) {
|
||||
// Make sure the Client has the server url set
|
||||
Client4.setUrl(url);
|
||||
}
|
||||
|
||||
if (!Client4.getToken()) {
|
||||
// Make sure the Client has the server token set
|
||||
Client4.setToken(token);
|
||||
}
|
||||
|
||||
dispatch(fetchPostActionWithRetry(getPosts(data.channel_id)));
|
||||
const result = await dispatch(createPostForNotificationReply(post));
|
||||
if (result.error) {
|
||||
const locale = getCurrentLocale(state);
|
||||
PushNotifications.localNotification({
|
||||
message: getLocalizedMessage(locale, t('mobile.reply_post.failed')),
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
localTest: true,
|
||||
channel_id: data.channel_id,
|
||||
},
|
||||
});
|
||||
completion();
|
||||
return;
|
||||
}
|
||||
|
||||
this.replyNotificationData = null;
|
||||
|
||||
PushNotifications.getDeliveredNotifications((notifications) => {
|
||||
PushNotifications.setApplicationIconBadgeNumber(notifications.length);
|
||||
completion();
|
||||
});
|
||||
} else {
|
||||
this.replyNotificationData = {
|
||||
data,
|
||||
text,
|
||||
completion,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
onRegisterDevice = (data) => {
|
||||
const {dispatch} = Store.redux;
|
||||
|
||||
let prefix;
|
||||
if (Platform.OS === 'ios') {
|
||||
prefix = General.PUSH_NOTIFY_APPLE_REACT_NATIVE;
|
||||
if (DeviceInfo.getBundleId().includes('rnbeta')) {
|
||||
prefix = `${prefix}beta`;
|
||||
}
|
||||
} else {
|
||||
prefix = General.PUSH_NOTIFY_ANDROID_REACT_NATIVE;
|
||||
}
|
||||
|
||||
EphemeralStore.deviceToken = `${prefix}:${data.token}`;
|
||||
|
||||
// TODO: Remove when realm is ready
|
||||
waitForHydration(Store.redux, () => {
|
||||
this.configured = true;
|
||||
dispatch(setDeviceToken(EphemeralStore.deviceToken));
|
||||
});
|
||||
};
|
||||
|
||||
getNotification = () => {
|
||||
return PushNotifications.getNotification();
|
||||
};
|
||||
}
|
||||
|
||||
export default new PushNotificationUtils();
|
||||
|
|
@ -3,37 +3,12 @@
|
|||
|
||||
/* eslint-disable no-import-assign */
|
||||
|
||||
import NotificationsIOS from 'react-native-notifications';
|
||||
import {Notifications} from 'react-native-notifications';
|
||||
|
||||
import * as ViewSelectors from '@selectors/views';
|
||||
import Store from '@store/store';
|
||||
|
||||
import PushNotification from './push_notifications.ios';
|
||||
|
||||
jest.mock('react-native-notifications', () => {
|
||||
let badgesCount = 0;
|
||||
let deliveredNotifications = [];
|
||||
|
||||
return {
|
||||
getBadgesCount: jest.fn((callback) => callback(badgesCount)),
|
||||
setBadgesCount: jest.fn((count) => {
|
||||
badgesCount = count;
|
||||
}),
|
||||
addEventListener: jest.fn(),
|
||||
setDeliveredNotifications: jest.fn((notifications) => {
|
||||
deliveredNotifications = notifications;
|
||||
}),
|
||||
getDeliveredNotifications: jest.fn(async (callback) => {
|
||||
await callback(deliveredNotifications);
|
||||
}),
|
||||
removeDeliveredNotifications: jest.fn((ids) => {
|
||||
deliveredNotifications = deliveredNotifications.filter((n) => !ids.includes(n.identifier));
|
||||
}),
|
||||
cancelAllLocalNotifications: jest.fn(),
|
||||
NotificationAction: jest.fn(),
|
||||
NotificationCategory: jest.fn(),
|
||||
};
|
||||
});
|
||||
import PushNotification from './push_notifications';
|
||||
|
||||
describe('PushNotification', () => {
|
||||
const channel1ID = 'channel-1-id';
|
||||
|
|
@ -66,18 +41,15 @@ describe('PushNotification', () => {
|
|||
channel_id: channel2ID,
|
||||
},
|
||||
];
|
||||
NotificationsIOS.setDeliveredNotifications(deliveredNotifications);
|
||||
Notifications.setDeliveredNotifications(deliveredNotifications);
|
||||
|
||||
const notificationCount = deliveredNotifications.length;
|
||||
expect(notificationCount).toBe(5);
|
||||
|
||||
NotificationsIOS.setBadgesCount(notificationCount);
|
||||
NotificationsIOS.getBadgesCount((count) => expect(count).toBe(notificationCount));
|
||||
|
||||
// Clear channel1 notifications
|
||||
await PushNotification.clearChannelNotifications(channel1ID);
|
||||
|
||||
await NotificationsIOS.getDeliveredNotifications(async (deliveredNotifs) => {
|
||||
await Notifications.ios.getDeliveredNotifications(async (deliveredNotifs) => {
|
||||
expect(deliveredNotifs.length).toBe(2);
|
||||
const channel1DeliveredNotifications = deliveredNotifs.filter((n) => n.channel_id === channel1ID);
|
||||
const channel2DeliveredNotifications = deliveredNotifs.filter((n) => n.channel_id === channel2ID);
|
||||
|
|
@ -92,33 +64,33 @@ describe('PushNotification', () => {
|
|||
|
||||
PushNotification.clearNotifications();
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledWith(0);
|
||||
expect(NotificationsIOS.setBadgesCount).toHaveBeenCalledWith(0);
|
||||
expect(Notifications.ios.setBadgeCount).toHaveBeenCalledWith(0);
|
||||
expect(cancelAllLocalNotifications).toHaveBeenCalled();
|
||||
expect(NotificationsIOS.cancelAllLocalNotifications).toHaveBeenCalled();
|
||||
expect(Notifications.cancelAllLocalNotifications).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('clearChannelNotifications should set app badge number from to delivered notification count when redux store is not set', () => {
|
||||
it('clearChannelNotifications should set app badge number from to delivered notification count when redux store is not set', async () => {
|
||||
Store.redux = null;
|
||||
const setApplicationIconBadgeNumber = jest.spyOn(PushNotification, 'setApplicationIconBadgeNumber');
|
||||
const deliveredNotifications = [{identifier: 1}, {identifier: 2}];
|
||||
NotificationsIOS.setDeliveredNotifications(deliveredNotifications);
|
||||
Notifications.setDeliveredNotifications(deliveredNotifications);
|
||||
|
||||
PushNotification.clearChannelNotifications();
|
||||
await PushNotification.clearChannelNotifications();
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledWith(deliveredNotifications.length);
|
||||
});
|
||||
|
||||
it('clearChannelNotifications should set app badge number from redux store when set', () => {
|
||||
it('clearChannelNotifications should set app badge number from redux store when set', async () => {
|
||||
Store.redux = {
|
||||
getState: jest.fn(),
|
||||
};
|
||||
const setApplicationIconBadgeNumber = jest.spyOn(PushNotification, 'setApplicationIconBadgeNumber');
|
||||
const deliveredNotifications = [{identifier: 1}, {identifier: 2}];
|
||||
NotificationsIOS.setDeliveredNotifications(deliveredNotifications);
|
||||
Notifications.setDeliveredNotifications(deliveredNotifications);
|
||||
|
||||
const stateBadgeCount = 2 * deliveredNotifications.length;
|
||||
ViewSelectors.getBadgeCount = jest.fn().mockReturnValue(stateBadgeCount);
|
||||
|
||||
PushNotification.clearChannelNotifications();
|
||||
await PushNotification.clearChannelNotifications();
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledWith(stateBadgeCount);
|
||||
});
|
||||
});
|
||||
254
app/init/push_notifications.ts
Normal file
254
app/init/push_notifications.ts
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {AppState, NativeModules, Platform} from 'react-native';
|
||||
import DeviceInfo from 'react-native-device-info';
|
||||
import {
|
||||
Notification,
|
||||
NotificationAction,
|
||||
NotificationBackgroundFetchResult,
|
||||
NotificationCategory,
|
||||
NotificationCompletion,
|
||||
Notifications,
|
||||
NotificationTextInput,
|
||||
Registered,
|
||||
} from 'react-native-notifications';
|
||||
|
||||
import {dismissAllModals, popToRoot} from '@actions/navigation';
|
||||
import {markChannelViewedAndRead, fetchPostActionWithRetry} from '@actions/views/channel';
|
||||
import {getPosts} from '@actions/views/post';
|
||||
import {loadFromPushNotification} from '@actions/views/root';
|
||||
import {logout} from '@actions/views/user';
|
||||
import {NavigationTypes, ViewTypes} from '@constants';
|
||||
import {getLocalizedMessage} from '@i18n';
|
||||
import {setDeviceToken} from '@mm-redux/actions/general';
|
||||
import {General} from '@mm-redux/constants';
|
||||
import EventEmitter from '@mm-redux/utils/event_emitter';
|
||||
import {getCurrentLocale} from '@selectors/i18n';
|
||||
import {getBadgeCount} from '@selectors/views';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import Store from '@store/store';
|
||||
import {waitForHydration} from '@store/utils';
|
||||
import {t} from '@utils/i18n';
|
||||
|
||||
import type {DispatchFunc} from '@mm-redux/types/actions';
|
||||
|
||||
const CATEGORY = 'CAN_REPLY';
|
||||
const REPLY_ACTION = 'REPLY_ACTION';
|
||||
const AndroidNotificationPreferences = Platform.OS === 'android' ? NativeModules.NotificationPreferences : null;
|
||||
const NOTIFICATION_TYPE = {
|
||||
CLEAR: 'clear',
|
||||
MESSAGE: 'message',
|
||||
SESSION: 'session',
|
||||
};
|
||||
|
||||
interface NotificationWithChannel extends Notification {
|
||||
identifier: string;
|
||||
channel_id: string;
|
||||
}
|
||||
|
||||
class PushNotifications {
|
||||
configured = false;
|
||||
|
||||
constructor() {
|
||||
Notifications.registerRemoteNotifications();
|
||||
Notifications.events().registerNotificationOpened(this.onNotificationOpened);
|
||||
Notifications.events().registerRemoteNotificationsRegistered(this.onRemoteNotificationsRegistered);
|
||||
Notifications.events().registerNotificationReceivedBackground(this.onNotificationReceivedBackground);
|
||||
Notifications.events().registerNotificationReceivedForeground(this.onNotificationReceivedForeground);
|
||||
|
||||
this.getInitialNotification();
|
||||
}
|
||||
|
||||
cancelAllLocalNotifications() {
|
||||
Notifications.cancelAllLocalNotifications();
|
||||
}
|
||||
|
||||
clearNotifications = () => {
|
||||
this.setApplicationIconBadgeNumber(0);
|
||||
|
||||
// TODO: Only cancel the local notifications that belong to this server
|
||||
this.cancelAllLocalNotifications();
|
||||
};
|
||||
|
||||
clearChannelNotifications = async (channelId: string) => {
|
||||
if (Platform.OS === 'android') {
|
||||
const notifications = await AndroidNotificationPreferences.getDeliveredNotifications();
|
||||
const notificationForChannel = notifications.find((n: NotificationWithChannel) => n.channel_id === channelId);
|
||||
if (notificationForChannel) {
|
||||
AndroidNotificationPreferences.removeDeliveredNotifications(notificationForChannel.identifier, channelId);
|
||||
}
|
||||
} else {
|
||||
const ids: string[] = [];
|
||||
const notifications = await Notifications.ios.getDeliveredNotifications();
|
||||
let badgeCount = notifications.length;
|
||||
|
||||
if (Store.redux) {
|
||||
const totalMentions = getBadgeCount(Store.redux.getState());
|
||||
if (totalMentions > -1) {
|
||||
badgeCount = totalMentions;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < notifications.length; i++) {
|
||||
const notification = notifications[i] as NotificationWithChannel;
|
||||
if (notification.channel_id === channelId) {
|
||||
ids.push(notification.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.length) {
|
||||
Notifications.ios.removeDeliveredNotifications(ids);
|
||||
}
|
||||
|
||||
this.setApplicationIconBadgeNumber(badgeCount);
|
||||
}
|
||||
}
|
||||
|
||||
createReplyCategory = () => {
|
||||
const {getState} = Store.redux!;
|
||||
const state = getState();
|
||||
const locale = getCurrentLocale(state);
|
||||
|
||||
const replyTitle = getLocalizedMessage(locale, t('mobile.push_notification_reply.title'));
|
||||
const replyButton = getLocalizedMessage(locale, t('mobile.push_notification_reply.button'));
|
||||
const replyPlaceholder = getLocalizedMessage(locale, t('mobile.push_notification_reply.placeholder'));
|
||||
const replyTextInput: NotificationTextInput = {
|
||||
buttonTitle: replyButton,
|
||||
placeholder: replyPlaceholder,
|
||||
};
|
||||
const replyAction = new NotificationAction(REPLY_ACTION, 'background', replyTitle, true, replyTextInput);
|
||||
return new NotificationCategory(CATEGORY, [replyAction]);
|
||||
}
|
||||
|
||||
getInitialNotification = async () => {
|
||||
const notification: NotificationWithData | undefined = await Notifications.getInitialNotification();
|
||||
|
||||
if (notification) {
|
||||
EphemeralStore.setStartFromNotification(true);
|
||||
notification.userInteraction = true;
|
||||
|
||||
// getInitialNotification may run before the store is set
|
||||
// that is why we run on an interval until the store is available
|
||||
// once we handle the notification the interval is cleared.
|
||||
const interval = setInterval(() => {
|
||||
if (Store.redux) {
|
||||
clearInterval(interval);
|
||||
this.handleNotification(notification);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
handleNotification = (notification: NotificationWithData) => {
|
||||
const {payload, foreground, userInteraction} = notification;
|
||||
|
||||
if (Store.redux && payload) {
|
||||
const dispatch = Store.redux.dispatch as DispatchFunc;
|
||||
|
||||
waitForHydration(Store.redux, async () => {
|
||||
switch (payload.type) {
|
||||
case NOTIFICATION_TYPE.CLEAR:
|
||||
dispatch(markChannelViewedAndRead(payload.channel_id, null, false));
|
||||
break;
|
||||
case NOTIFICATION_TYPE.MESSAGE:
|
||||
// get the posts for the channel as soon as possible
|
||||
dispatch(fetchPostActionWithRetry(getPosts(payload.channel_id)));
|
||||
|
||||
if (foreground) {
|
||||
EventEmitter.emit(ViewTypes.NOTIFICATION_IN_APP, notification);
|
||||
} else if (userInteraction && !payload.userInfo?.local) {
|
||||
dispatch(loadFromPushNotification(notification));
|
||||
const componentId = EphemeralStore.getNavigationTopComponentId();
|
||||
if (componentId) {
|
||||
EventEmitter.emit(NavigationTypes.CLOSE_MAIN_SIDEBAR);
|
||||
EventEmitter.emit(NavigationTypes.CLOSE_SETTINGS_SIDEBAR);
|
||||
|
||||
await dismissAllModals();
|
||||
await popToRoot();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NOTIFICATION_TYPE.SESSION:
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Session expired notification');
|
||||
dispatch(logout());
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
localNotification = (notification: Notification) => {
|
||||
Notifications.postLocalNotification(notification);
|
||||
}
|
||||
|
||||
onNotificationOpened = (notification: NotificationWithData, completion: () => void) => {
|
||||
notification.userInteraction = true;
|
||||
this.handleNotification(notification);
|
||||
completion();
|
||||
}
|
||||
|
||||
onNotificationReceivedBackground = (notification: NotificationWithData, completion: (response: NotificationBackgroundFetchResult) => void) => {
|
||||
this.handleNotification(notification);
|
||||
completion(NotificationBackgroundFetchResult.NO_DATA);
|
||||
};
|
||||
|
||||
onNotificationReceivedForeground = (notification: NotificationWithData, completion: (response: NotificationCompletion) => void) => {
|
||||
notification.foreground = AppState.currentState === 'active';
|
||||
completion({alert: false, sound: true, badge: true});
|
||||
this.handleNotification(notification);
|
||||
};
|
||||
|
||||
onRemoteNotificationsRegistered = (event: Registered) => {
|
||||
if (!this.configured) {
|
||||
this.configured = true;
|
||||
const {deviceToken} = event;
|
||||
let prefix;
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
prefix = General.PUSH_NOTIFY_APPLE_REACT_NATIVE;
|
||||
if (DeviceInfo.getBundleId().includes('rnbeta')) {
|
||||
prefix = `${prefix}beta`;
|
||||
}
|
||||
} else {
|
||||
prefix = General.PUSH_NOTIFY_ANDROID_REACT_NATIVE;
|
||||
}
|
||||
|
||||
EphemeralStore.deviceToken = `${prefix}:${deviceToken}`;
|
||||
if (Store.redux) {
|
||||
const dispatch = Store.redux.dispatch as DispatchFunc;
|
||||
waitForHydration(Store.redux, () => {
|
||||
this.requestNotificationReplyPermissions();
|
||||
dispatch(setDeviceToken(EphemeralStore.deviceToken));
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
requestNotificationReplyPermissions = () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
const replyCategory = this.createReplyCategory();
|
||||
Notifications.setCategories([replyCategory]);
|
||||
}
|
||||
};
|
||||
|
||||
setApplicationIconBadgeNumber = (value: number) => {
|
||||
if (Platform.OS === 'ios') {
|
||||
const count = value < 0 ? 0 : value;
|
||||
Notifications.ios.setBadgeCount(count);
|
||||
}
|
||||
};
|
||||
|
||||
scheduleNotification = (notification: Notification) => {
|
||||
if (notification.fireDate) {
|
||||
if (Platform.OS === 'ios') {
|
||||
notification.fireDate = new Date(notification.fireDate).toISOString();
|
||||
}
|
||||
|
||||
Notifications.postLocalNotification(notification);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default new PushNotifications();
|
||||
|
|
@ -17,7 +17,6 @@ import emmProvider from '@init/emm_provider';
|
|||
import '@init/device';
|
||||
import '@init/fetch';
|
||||
import globalEventHandler from '@init/global_event_handler';
|
||||
import pushNotifications from '@init/push_notifications';
|
||||
import {registerScreens} from '@screens';
|
||||
import configureStore from '@store';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
|
|
@ -37,7 +36,6 @@ const init = async () => {
|
|||
const MMKVStorage = await getStorage();
|
||||
const {store} = configureStore(MMKVStorage);
|
||||
|
||||
await pushNotifications.configure();
|
||||
globalEventHandler.configure({
|
||||
launchApp,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import PushNotifications from './push_notifications';
|
||||
export default PushNotifications;
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {AppState, NativeModules} from 'react-native';
|
||||
import {NotificationsAndroid, PendingNotifications} from 'react-native-notifications';
|
||||
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
|
||||
const {NotificationPreferences} = NativeModules;
|
||||
|
||||
class PushNotification {
|
||||
constructor() {
|
||||
this.onRegister = null;
|
||||
this.onNotification = null;
|
||||
this.deviceNotification = null;
|
||||
this.deviceToken = null;
|
||||
|
||||
NotificationsAndroid.setRegistrationTokenUpdateListener((deviceToken) => {
|
||||
this.deviceToken = deviceToken;
|
||||
if (this.onRegister) {
|
||||
this.onRegister({token: this.deviceToken});
|
||||
}
|
||||
});
|
||||
|
||||
NotificationsAndroid.setNotificationReceivedListener((notification) => {
|
||||
if (notification) {
|
||||
const data = notification.getData();
|
||||
this.handleNotification(data, false);
|
||||
}
|
||||
});
|
||||
|
||||
NotificationsAndroid.setNotificationOpenedListener((notification) => {
|
||||
if (notification) {
|
||||
EphemeralStore.setStartFromNotification(true);
|
||||
const data = notification.getData();
|
||||
this.handleNotification(data, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleNotification = (data, userInteraction) => {
|
||||
const foreground = !userInteraction && AppState.currentState === 'active';
|
||||
this.deviceNotification = {
|
||||
data,
|
||||
foreground,
|
||||
message: data.message,
|
||||
userInfo: data.userInfo,
|
||||
userInteraction,
|
||||
};
|
||||
|
||||
if (this.onNotification && (foreground || userInteraction)) {
|
||||
this.onNotification(this.deviceNotification);
|
||||
}
|
||||
};
|
||||
|
||||
configure(options) {
|
||||
this.onRegister = options.onRegister;
|
||||
this.onNotification = options.onNotification;
|
||||
|
||||
if (this.onRegister && this.deviceToken) {
|
||||
this.onRegister({token: this.deviceToken});
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
if (!options.popInitialNotification) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
PendingNotifications.getInitialNotification().
|
||||
then((notification) => {
|
||||
if (notification) {
|
||||
const data = notification.getData();
|
||||
if (data) {
|
||||
EphemeralStore.setStartFromNotification(true);
|
||||
this.handleNotification(data, true);
|
||||
}
|
||||
}
|
||||
}).
|
||||
catch((err) => {
|
||||
console.log('Android getInitialNotifiation() failed', err); //eslint-disable-line no-console
|
||||
}).
|
||||
finally(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
localNotificationSchedule(notification) {
|
||||
if (notification.date) {
|
||||
notification.fireDate = notification.date.getTime();
|
||||
Reflect.deleteProperty(notification, 'date');
|
||||
NotificationsAndroid.scheduleLocalNotification(notification);
|
||||
}
|
||||
}
|
||||
|
||||
localNotification(notification) {
|
||||
NotificationsAndroid.localNotification(notification);
|
||||
}
|
||||
|
||||
cancelAllLocalNotifications() {
|
||||
NotificationsAndroid.cancelAllLocalNotifications();
|
||||
}
|
||||
|
||||
setApplicationIconBadgeNumber() {
|
||||
// Not supported for Android
|
||||
}
|
||||
|
||||
getNotification() {
|
||||
return this.deviceNotification;
|
||||
}
|
||||
|
||||
resetNotification() {
|
||||
this.deviceNotification = null;
|
||||
}
|
||||
|
||||
async clearChannelNotifications(channelId) {
|
||||
const notifications = await NotificationPreferences.getDeliveredNotifications();
|
||||
const notificationForChannel = notifications.find((n) => n.channel_id === channelId);
|
||||
if (notificationForChannel) {
|
||||
NotificationPreferences.removeDeliveredNotifications(notificationForChannel.identifier, channelId);
|
||||
}
|
||||
}
|
||||
|
||||
clearNotifications = () => {
|
||||
this.cancelAllLocalNotifications(); // TODO: Only cancel the local notifications that belong to this server
|
||||
}
|
||||
}
|
||||
|
||||
export default new PushNotification();
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {AppState} from 'react-native';
|
||||
import NotificationsIOS, {
|
||||
NotificationAction,
|
||||
NotificationCategory,
|
||||
DEVICE_REMOTE_NOTIFICATIONS_REGISTERED_EVENT,
|
||||
DEVICE_NOTIFICATION_RECEIVED_FOREGROUND_EVENT,
|
||||
DEVICE_NOTIFICATION_OPENED_EVENT,
|
||||
} from 'react-native-notifications';
|
||||
|
||||
import {getLocalizedMessage} from '@i18n';
|
||||
import {getCurrentLocale} from '@selectors/i18n';
|
||||
import {getBadgeCount} from '@selectors/views';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import Store from '@store/store';
|
||||
import {t} from '@utils/i18n';
|
||||
|
||||
const CATEGORY = 'CAN_REPLY';
|
||||
const REPLY_ACTION = 'REPLY_ACTION';
|
||||
|
||||
class PushNotification {
|
||||
constructor() {
|
||||
this.deviceNotification = null;
|
||||
this.onRegister = null;
|
||||
this.onNotification = null;
|
||||
|
||||
NotificationsIOS.addEventListener(DEVICE_REMOTE_NOTIFICATIONS_REGISTERED_EVENT, this.onRemoteNotificationsRegistered);
|
||||
NotificationsIOS.addEventListener(DEVICE_NOTIFICATION_RECEIVED_FOREGROUND_EVENT, this.onNotificationReceivedForeground);
|
||||
NotificationsIOS.addEventListener(DEVICE_NOTIFICATION_OPENED_EVENT, this.onNotificationOpened);
|
||||
}
|
||||
|
||||
handleNotification = (data, foreground, userInteraction) => {
|
||||
this.deviceNotification = {
|
||||
data,
|
||||
foreground,
|
||||
message: data.body || data.message,
|
||||
userInfo: data.userInfo,
|
||||
userInteraction,
|
||||
};
|
||||
|
||||
if (this.onNotification) {
|
||||
this.onNotification(this.deviceNotification);
|
||||
}
|
||||
};
|
||||
|
||||
configure(options) {
|
||||
this.onRegister = options.onRegister;
|
||||
this.onNotification = options.onNotification;
|
||||
|
||||
this.requestNotificationReplyPermissions();
|
||||
|
||||
return new Promise((resolve) => {
|
||||
if (!options.popInitialNotification) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
NotificationsIOS.getInitialNotification().
|
||||
then((notification) => {
|
||||
if (notification) {
|
||||
const data = notification.getData();
|
||||
if (data) {
|
||||
EphemeralStore.setStartFromNotification(true);
|
||||
this.handleNotification(data, false, true);
|
||||
}
|
||||
}
|
||||
}).
|
||||
catch((err) => {
|
||||
console.log('iOS getInitialNotifiation() failed', err); //eslint-disable-line no-console
|
||||
}).
|
||||
finally(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
requestNotificationReplyPermissions = () => {
|
||||
const replyCategory = this.createReplyCategory();
|
||||
this.requestPermissions([replyCategory]);
|
||||
}
|
||||
|
||||
createReplyCategory = () => {
|
||||
const {getState} = Store.redux;
|
||||
const state = getState();
|
||||
const locale = getCurrentLocale(state);
|
||||
|
||||
const replyTitle = getLocalizedMessage(locale, t('mobile.push_notification_reply.title'));
|
||||
const replyButton = getLocalizedMessage(locale, t('mobile.push_notification_reply.button'));
|
||||
const replyPlaceholder = getLocalizedMessage(locale, t('mobile.push_notification_reply.placeholder'));
|
||||
|
||||
const replyAction = new NotificationAction({
|
||||
activationMode: 'background',
|
||||
title: replyTitle,
|
||||
textInput: {
|
||||
buttonTitle: replyButton,
|
||||
placeholder: replyPlaceholder,
|
||||
},
|
||||
authenticationRequired: true,
|
||||
identifier: REPLY_ACTION,
|
||||
});
|
||||
|
||||
return new NotificationCategory({
|
||||
identifier: CATEGORY,
|
||||
actions: [replyAction],
|
||||
context: 'default',
|
||||
});
|
||||
}
|
||||
|
||||
requestPermissions = (permissions) => {
|
||||
NotificationsIOS.requestPermissions(permissions);
|
||||
};
|
||||
|
||||
localNotificationSchedule(notification) {
|
||||
if (notification.date) {
|
||||
const deviceNotification = {
|
||||
fireDate: notification.date.toISOString(),
|
||||
body: notification.message,
|
||||
alertAction: '',
|
||||
userInfo: notification.userInfo,
|
||||
};
|
||||
|
||||
NotificationsIOS.localNotification(deviceNotification);
|
||||
}
|
||||
}
|
||||
|
||||
localNotification(notification) {
|
||||
this.deviceNotification = {
|
||||
body: notification.message,
|
||||
alertAction: '',
|
||||
userInfo: notification.userInfo,
|
||||
};
|
||||
|
||||
NotificationsIOS.localNotification(this.deviceNotification);
|
||||
}
|
||||
|
||||
cancelAllLocalNotifications() {
|
||||
NotificationsIOS.cancelAllLocalNotifications();
|
||||
}
|
||||
|
||||
onNotificationReceivedBackground = (notification) => {
|
||||
const userInteraction = AppState.currentState === 'active';
|
||||
|
||||
// mark the app as started as soon as possible
|
||||
if (userInteraction) {
|
||||
EphemeralStore.setStartFromNotification(true);
|
||||
}
|
||||
|
||||
const data = notification.getData();
|
||||
const info = {
|
||||
...data,
|
||||
message: data.body || notification.getMessage(),
|
||||
};
|
||||
|
||||
if (!userInteraction) {
|
||||
this.handleNotification(info, false, userInteraction);
|
||||
}
|
||||
};
|
||||
|
||||
onNotificationReceivedForeground = (notification) => {
|
||||
const data = notification.getData();
|
||||
const info = {
|
||||
...data,
|
||||
message: data.body || notification.getMessage(),
|
||||
};
|
||||
this.handleNotification(info, true, false);
|
||||
};
|
||||
|
||||
onNotificationOpened = (notification, completion) => {
|
||||
const data = notification.getData();
|
||||
const info = {
|
||||
...data,
|
||||
message: data.body || notification.getMessage(),
|
||||
};
|
||||
this.handleNotification(info, false, true);
|
||||
completion();
|
||||
};
|
||||
|
||||
onRemoteNotificationsRegistered = (deviceToken) => {
|
||||
if (this.onRegister) {
|
||||
this.onRegister({token: deviceToken});
|
||||
}
|
||||
};
|
||||
|
||||
setApplicationIconBadgeNumber(number) {
|
||||
const count = number < 0 ? 0 : number;
|
||||
NotificationsIOS.setBadgesCount(count);
|
||||
}
|
||||
|
||||
getNotification() {
|
||||
return this.deviceNotification;
|
||||
}
|
||||
|
||||
resetNotification() {
|
||||
this.deviceNotification = null;
|
||||
}
|
||||
|
||||
getDeliveredNotifications(callback) {
|
||||
NotificationsIOS.getDeliveredNotifications(callback);
|
||||
}
|
||||
|
||||
clearChannelNotifications(channelId) {
|
||||
NotificationsIOS.getDeliveredNotifications((notifications) => {
|
||||
const ids = [];
|
||||
let badgeCount = notifications.length;
|
||||
|
||||
if (Store.redux) {
|
||||
const totalMentions = getBadgeCount(Store.redux.getState());
|
||||
if (totalMentions > -1) {
|
||||
badgeCount = totalMentions;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < notifications.length; i++) {
|
||||
const notification = notifications[i];
|
||||
|
||||
if (notification.channel_id === channelId) {
|
||||
ids.push(notification.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.length) {
|
||||
NotificationsIOS.removeDeliveredNotifications(ids);
|
||||
}
|
||||
|
||||
this.setApplicationIconBadgeNumber(badgeCount);
|
||||
});
|
||||
}
|
||||
|
||||
clearNotifications = () => {
|
||||
this.setApplicationIconBadgeNumber(0);
|
||||
this.cancelAllLocalNotifications(); // TODO: Only cancel the local notifications that belong to this server
|
||||
}
|
||||
}
|
||||
|
||||
export default new PushNotification();
|
||||
|
|
@ -19,7 +19,7 @@ import {preventDoubleTap} from '@utils/tap';
|
|||
import {setNavigatorStyles} from '@utils/theme';
|
||||
import tracker from '@utils/time_tracker';
|
||||
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import PushNotifications from '@init/push_notifications';
|
||||
import telemetry from 'app/telemetry';
|
||||
|
||||
export let ClientUpgradeListener;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {intlShape} from 'react-intl';
|
|||
|
||||
import Badge from '@components/badge';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import PushNotifications from '@init/push_notifications';
|
||||
import {preventDoubleTap} from '@utils/tap';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {t} from '@utils/i18n';
|
||||
|
|
|
|||
|
|
@ -2,41 +2,14 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import NotificationsIOS from 'react-native-notifications';
|
||||
|
||||
import Badge from '@components/badge';
|
||||
import Preferences from '@mm-redux/constants/preferences';
|
||||
|
||||
import Badge from 'app/components/badge';
|
||||
import PushNotification from 'app/push_notifications/push_notifications.ios';
|
||||
import PushNotification from '@init/push_notifications';
|
||||
import {shallowWithIntl} from 'test/intl-test-helper';
|
||||
|
||||
import MainSidebarDrawerButton from './main_sidebar_drawer_button';
|
||||
|
||||
jest.mock('react-native-notifications', () => {
|
||||
let badgesCount = 0;
|
||||
let deliveredNotifications = {};
|
||||
|
||||
return {
|
||||
getBadgesCount: jest.fn((callback) => callback(badgesCount)),
|
||||
setBadgesCount: jest.fn((count) => {
|
||||
badgesCount = count;
|
||||
}),
|
||||
addEventListener: jest.fn(),
|
||||
setDeliveredNotifications: jest.fn((notifications) => {
|
||||
deliveredNotifications = notifications;
|
||||
}),
|
||||
getDeliveredNotifications: jest.fn(async (callback) => {
|
||||
await callback(deliveredNotifications);
|
||||
}),
|
||||
removeDeliveredNotifications: jest.fn((ids) => {
|
||||
deliveredNotifications = deliveredNotifications.filter((n) => !ids.includes(n.identifier));
|
||||
}),
|
||||
cancelAllLocalNotifications: jest.fn(),
|
||||
NotificationAction: jest.fn(),
|
||||
NotificationCategory: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
describe('MainSidebarDrawerButton', () => {
|
||||
const baseProps = {
|
||||
openSidebar: jest.fn(),
|
||||
|
|
@ -45,7 +18,7 @@ describe('MainSidebarDrawerButton', () => {
|
|||
visible: false,
|
||||
};
|
||||
|
||||
afterEach(() => NotificationsIOS.setBadgesCount(0));
|
||||
afterEach(() => PushNotification.setApplicationIconBadgeNumber(0));
|
||||
|
||||
test('should match, full snapshot', () => {
|
||||
const wrapper = shallowWithIntl(
|
||||
|
|
@ -73,7 +46,6 @@ describe('MainSidebarDrawerButton', () => {
|
|||
<MainSidebarDrawerButton {...props}/>,
|
||||
);
|
||||
expect(setApplicationIconBadgeNumber).not.toBeCalled();
|
||||
NotificationsIOS.getBadgesCount((count) => expect(count).toBe(0));
|
||||
});
|
||||
|
||||
test('should set app icon badge on mount', () => {
|
||||
|
|
@ -87,7 +59,6 @@ describe('MainSidebarDrawerButton', () => {
|
|||
<MainSidebarDrawerButton {...props}/>,
|
||||
);
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledTimes(1);
|
||||
NotificationsIOS.getBadgesCount((count) => expect(count).toBe(1));
|
||||
});
|
||||
|
||||
test('should set app icon badge update', () => {
|
||||
|
|
@ -100,12 +71,10 @@ describe('MainSidebarDrawerButton', () => {
|
|||
const wrapper = shallowWithIntl(
|
||||
<MainSidebarDrawerButton {...props}/>,
|
||||
);
|
||||
NotificationsIOS.getBadgesCount((count) => expect(count).toBe(0));
|
||||
|
||||
wrapper.setProps({badgeCount: 2});
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledTimes(1);
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledWith(2);
|
||||
NotificationsIOS.getBadgesCount((count) => expect(count).toBe(2));
|
||||
});
|
||||
|
||||
test('should set remove icon badge on update', () => {
|
||||
|
|
@ -120,11 +89,9 @@ describe('MainSidebarDrawerButton', () => {
|
|||
);
|
||||
wrapper.setProps({badgeCount: 2});
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledWith(2);
|
||||
NotificationsIOS.getBadgesCount((count) => expect(count).toBe(2));
|
||||
|
||||
wrapper.setProps({badgeCount: -1});
|
||||
expect(setApplicationIconBadgeNumber).toHaveBeenCalledWith(-1);
|
||||
NotificationsIOS.getBadgesCount((count) => expect(count).toBe(0));
|
||||
});
|
||||
|
||||
test('Should be accessible', () => {
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Gallery should match snapshot 1`] = `
|
||||
<React.Fragment>
|
||||
<GalleryViewer
|
||||
files={
|
||||
Array [
|
||||
Object {
|
||||
"caption": "Caption 1",
|
||||
"data": "data",
|
||||
"source": "source",
|
||||
},
|
||||
Object {
|
||||
"caption": "Caption 2",
|
||||
"data": "data",
|
||||
"source": "source",
|
||||
},
|
||||
]
|
||||
}
|
||||
footerVisible={true}
|
||||
height={400}
|
||||
initialIndex={0}
|
||||
isLandscape={false}
|
||||
onClose={[Function]}
|
||||
onPageSelected={[Function]}
|
||||
onTap={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
"awayIndicator": "#ffbc42",
|
||||
"buttonBg": "#166de0",
|
||||
"buttonColor": "#ffffff",
|
||||
"centerChannelBg": "#ffffff",
|
||||
"centerChannelColor": "#3d3c40",
|
||||
"codeTheme": "github",
|
||||
"dndIndicator": "#f74343",
|
||||
"errorTextColor": "#fd5960",
|
||||
"linkColor": "#2389d7",
|
||||
"mentionBg": "#ffffff",
|
||||
"mentionBj": "#ffffff",
|
||||
"mentionColor": "#145dbf",
|
||||
"mentionHighlightBg": "#ffe577",
|
||||
"mentionHighlightLink": "#166de0",
|
||||
"newMessageSeparator": "#ff8800",
|
||||
"onlineIndicator": "#06d6a0",
|
||||
"sidebarBg": "#145dbf",
|
||||
"sidebarHeaderBg": "#1153ab",
|
||||
"sidebarHeaderTextColor": "#ffffff",
|
||||
"sidebarText": "#ffffff",
|
||||
"sidebarTextActiveBorder": "#579eff",
|
||||
"sidebarTextActiveColor": "#ffffff",
|
||||
"sidebarTextHoverBg": "#4578bf",
|
||||
"sidebarUnreadText": "#ffffff",
|
||||
"type": "Mattermost",
|
||||
}
|
||||
}
|
||||
width={300}
|
||||
/>
|
||||
<InjectIntl(Footer)
|
||||
file={
|
||||
Object {
|
||||
"caption": "Caption 1",
|
||||
"data": "data",
|
||||
"source": "source",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
|
@ -32,7 +32,7 @@ import {
|
|||
pinchGestureHandler,
|
||||
useValue,
|
||||
vec,
|
||||
} from 'react-native-redash';
|
||||
} from 'react-native-redash/lib/module/v1';
|
||||
import {Platform} from 'react-native';
|
||||
import {State} from 'react-native-gesture-handler';
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export default class Gallery extends PureComponent {
|
|||
sharedElementTransitions.push({
|
||||
fromId: `gallery-${file.id}`,
|
||||
toId: `image-${file.id}`,
|
||||
interpolation: 'accelerateDecelerate',
|
||||
interpolation: {mode: 'accelerateDecelerate'},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import React, {useEffect, useMemo, useRef, useState} from 'react';
|
|||
import {Platform, StyleSheet, View} from 'react-native';
|
||||
import {PanGestureHandler, PinchGestureHandler, State, TapGestureHandler, TapGestureHandlerStateChangeEvent} from 'react-native-gesture-handler';
|
||||
import Animated, {abs, add, and, call, clockRunning, cond, divide, eq, floor, greaterOrEq, greaterThan, multiply, neq, not, onChange, set, sub, useCode} from 'react-native-reanimated';
|
||||
import {clamp, snapPoint, timing, useClock, usePanGestureHandler, usePinchGestureHandler, useTapGestureHandler, useValue, vec} from 'react-native-redash';
|
||||
import {clamp, snapPoint, timing, useClock, usePanGestureHandler, usePinchGestureHandler, useTapGestureHandler, useValue, vec} from 'react-native-redash/lib/module/v1';
|
||||
import {isImage, isVideo} from '@utils/file';
|
||||
import {calculateDimensions} from '@utils/images';
|
||||
import {makeStyleSheetFromTheme} from '@utils/theme';
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ import {gestureHandlerRootHOC} from 'react-native-gesture-handler';
|
|||
import RootWrapper from '@components/root';
|
||||
let store;
|
||||
|
||||
const withGestures = (screen) => {
|
||||
const withGestures = (screen, styles) => {
|
||||
if (Platform.OS === 'android') {
|
||||
return gestureHandlerRootHOC(screen);
|
||||
return gestureHandlerRootHOC(screen, styles);
|
||||
}
|
||||
|
||||
return screen;
|
||||
|
|
@ -204,7 +204,7 @@ Navigation.setLazyComponentRegistrator((screenName) => {
|
|||
}
|
||||
|
||||
if (screen) {
|
||||
Navigation.registerComponent(screenName, () => withGestures(withReduxProvider(screen)), extraStyles, () => screen);
|
||||
Navigation.registerComponent(screenName, () => withGestures(withReduxProvider(screen), extraStyles), () => screen);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import NotificationTitle from './notification_title';
|
|||
|
||||
interface NotificationProps {
|
||||
componentId: string;
|
||||
notification: PushNotificationData;
|
||||
notification: NotificationWithData;
|
||||
}
|
||||
|
||||
interface SlideAnimation extends Animatable.CustomAnimation {
|
||||
|
|
@ -78,7 +78,7 @@ const Notification = ({componentId, notification}: NotificationProps) => {
|
|||
EventEmitter.emit(NavigationTypes.CLOSE_SETTINGS_SIDEBAR);
|
||||
dismiss();
|
||||
|
||||
if (!notification.userInfo?.localNotification) {
|
||||
if (!notification.payload?.userInfo?.local) {
|
||||
dispatch(loadFromPushNotification(notification));
|
||||
}
|
||||
};
|
||||
|
|
@ -112,10 +112,7 @@ const Notification = ({componentId, notification}: NotificationProps) => {
|
|||
return () => EventEmitter.off(NavigationTypes.NAVIGATION_SHOW_OVERLAY, dismiss);
|
||||
}, []);
|
||||
|
||||
let message = notification.message;
|
||||
if (typeof notification.message === 'object') {
|
||||
message = notification.message.body;
|
||||
}
|
||||
const message = notification.payload?.body || notification.payload?.message;
|
||||
|
||||
return (
|
||||
<PanGestureHandler
|
||||
|
|
@ -136,13 +133,13 @@ const Notification = ({componentId, notification}: NotificationProps) => {
|
|||
activeOpacity={1}
|
||||
>
|
||||
<NotificationIcon
|
||||
fromWebhook={notification.data?.from_webhook === 'true'}
|
||||
senderId={notification.data?.sender_id || ''}
|
||||
useUserIcon={notification.data?.use_user_icon === 'true'}
|
||||
overrideIconUrl={notification.data?.override_icon_url}
|
||||
fromWebhook={notification.payload?.from_webhook === 'true'}
|
||||
senderId={notification.payload?.sender_id || ''}
|
||||
useUserIcon={notification.payload?.use_user_icon === 'true'}
|
||||
overrideIconUrl={notification.payload?.override_icon_url}
|
||||
/>
|
||||
<View style={styles.titleContainer}>
|
||||
<NotificationTitle channelName={notification.data?.channel_name || ''}/>
|
||||
<NotificationTitle channelName={notification.payload?.channel_name || ''}/>
|
||||
<View style={styles.flex}>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
|
|
|
|||
|
|
@ -16,16 +16,15 @@ import {
|
|||
import deepEqual from 'deep-equal';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import RadioButtonGroup from '@components/radio_button';
|
||||
import StatusBar from '@components/status_bar';
|
||||
import PushNotifications from '@init/push_notifications';
|
||||
import {RequestStatus} from '@mm-redux/constants';
|
||||
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import RadioButtonGroup from 'app/components/radio_button';
|
||||
import SectionItem from '@screens/settings/section_item';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {getNotificationProps} from '@utils/notify_props';
|
||||
import NotificationPreferences from 'app/notification_preferences';
|
||||
import PushNotifications from 'app/push_notifications';
|
||||
import StatusBar from 'app/components/status_bar';
|
||||
import SectionItem from 'app/screens/settings/section_item';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import {getNotificationProps} from 'app/utils/notify_props';
|
||||
|
||||
import NotificationSettingsMobileBase from './notification_settings_mobile_base';
|
||||
|
||||
|
|
@ -698,13 +697,13 @@ class NotificationSettingsMobileAndroid extends NotificationSettingsMobileBase {
|
|||
const {intl} = this.props;
|
||||
|
||||
PushNotifications.localNotification({
|
||||
message: intl.formatMessage({
|
||||
body: intl.formatMessage({
|
||||
id: 'mobile.notification_settings_mobile.test_push',
|
||||
defaultMessage: 'This is a test push notification',
|
||||
}),
|
||||
userInfo: {
|
||||
localNotification: true,
|
||||
localTest: true,
|
||||
local: true,
|
||||
test: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const SAVE_STATE_ACTIONS = [
|
|||
'CONNECTION_CHANGED',
|
||||
'DATA_CLEANUP',
|
||||
'LOGIN',
|
||||
'BATCH_LOAD_ME',
|
||||
'Offline/STATUS_CHANGED',
|
||||
'persist/REHYDRATE',
|
||||
'RECEIVED_APP_STATE',
|
||||
|
|
|
|||
38
app/types/push_notification.d.ts
vendored
38
app/types/push_notification.d.ts
vendored
|
|
@ -2,35 +2,31 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
interface NotificationUserInfo {
|
||||
localNotification: boolean;
|
||||
localTest: boolean;
|
||||
channel_id?: string;
|
||||
local: boolean;
|
||||
test?: boolean;
|
||||
}
|
||||
|
||||
interface NotificationData {
|
||||
body?: string;
|
||||
channel_id: string;
|
||||
channel_name?: string;
|
||||
from_webhook?: string;
|
||||
post_id: string;
|
||||
root_id?: string;
|
||||
type: string;
|
||||
use_user_icon?: string;
|
||||
message?: string;
|
||||
override_icon_url?: string;
|
||||
override_username?: string;
|
||||
version: string;
|
||||
post_id: string;
|
||||
root_id?: string;
|
||||
sender_id?: string;
|
||||
}
|
||||
|
||||
interface NotificationMessage {
|
||||
body: string;
|
||||
}
|
||||
|
||||
interface PushNotificationData {
|
||||
date?: Date;
|
||||
data?: NotificationData;
|
||||
fireDate?: string;
|
||||
foreground: boolean;
|
||||
message: NotificationMessage | string;
|
||||
team_id?: string;
|
||||
type: string;
|
||||
use_user_icon?: string;
|
||||
userInfo?: NotificationUserInfo;
|
||||
userInteraction: boolean;
|
||||
version: string;
|
||||
}
|
||||
|
||||
interface NotificationWithData extends Notification {
|
||||
identifier: string;
|
||||
payload?: NotificationData;
|
||||
foreground?: boolean;
|
||||
userInteraction?: boolean;
|
||||
}
|
||||
|
|
@ -94,14 +94,14 @@ export function openGalleryAtIndex(index, files) {
|
|||
sharedElementTransitions.push({
|
||||
fromId: `image-${file.id}`,
|
||||
toId: `gallery-${file.id}`,
|
||||
interpolation: 'overshoot',
|
||||
interpolation: {mode: 'overshoot'},
|
||||
});
|
||||
} else {
|
||||
contentPush.y = {
|
||||
from: windowHeight,
|
||||
to: 0,
|
||||
duration: 300,
|
||||
interpolation: 'decelerate',
|
||||
interpolation: {mode: 'decelerate'},
|
||||
};
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
|
|
|
|||
|
|
@ -422,7 +422,6 @@
|
|||
"mobile.rename_channel.name_maxLength": "URL must be less than {maxLength, number} characters",
|
||||
"mobile.rename_channel.name_minLength": "URL must be {minLength, number} or more characters",
|
||||
"mobile.rename_channel.name_required": "URL is required",
|
||||
"mobile.reply_post.failed": "Message failed to send.",
|
||||
"mobile.request.invalid_response": "Received invalid response from the server.",
|
||||
"mobile.reset_status.alert_cancel": "Cancel",
|
||||
"mobile.reset_status.alert_ok": "Ok",
|
||||
|
|
|
|||
801
detox/package-lock.json
generated
801
detox/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -8,15 +8,15 @@
|
|||
"@babel/plugin-transform-modules-commonjs": "7.12.1",
|
||||
"@babel/plugin-transform-runtime": "7.12.1",
|
||||
"@babel/preset-env": "7.12.1",
|
||||
"axios": "0.20.0",
|
||||
"babel-jest": "26.6.0",
|
||||
"axios": "0.21.0",
|
||||
"babel-jest": "26.6.3",
|
||||
"babel-plugin-module-resolver": "4.0.0",
|
||||
"deepmerge": "4.2.2",
|
||||
"detox": "17.10.3",
|
||||
"detox": "17.12.0",
|
||||
"form-data": "3.0.0",
|
||||
"jest": "26.6.0",
|
||||
"jest-circus": "26.6.0",
|
||||
"jest-cli": "26.6.0",
|
||||
"jest": "26.6.3",
|
||||
"jest-circus": "26.6.3",
|
||||
"jest-cli": "26.6.3",
|
||||
"jest-html-reporters": "2.1.0",
|
||||
"jest-junit": "12.0.0",
|
||||
"sanitize-filename": "1.6.3",
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ GEM
|
|||
public_suffix (>= 2.0.2, < 5.0)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.1.0)
|
||||
aws-partitions (1.388.0)
|
||||
aws-sdk-core (3.109.1)
|
||||
aws-partitions (1.393.0)
|
||||
aws-sdk-core (3.109.2)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
|
|
@ -15,7 +15,7 @@ GEM
|
|||
aws-sdk-kms (1.39.0)
|
||||
aws-sdk-core (~> 3, >= 3.109.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.83.1)
|
||||
aws-sdk-s3 (1.84.1)
|
||||
aws-sdk-core (~> 3, >= 3.109.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
|
|
@ -34,7 +34,7 @@ GEM
|
|||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.7.6)
|
||||
emoji_regex (3.2.0)
|
||||
emoji_regex (3.2.1)
|
||||
excon (0.78.0)
|
||||
faraday (1.1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
|
|
@ -45,7 +45,7 @@ GEM
|
|||
faraday_middleware (1.0.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.0)
|
||||
fastlane (2.165.0)
|
||||
fastlane (2.167.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
|
|
@ -123,7 +123,7 @@ GEM
|
|||
json (2.3.1)
|
||||
jwt (2.2.2)
|
||||
memoist (0.16.2)
|
||||
mini_magick (4.10.1)
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
multi_json (1.15.0)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
#import "RNNotifications.h"
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#import <React/RCTRootView.h>
|
||||
#import <React/RCTLinkingManager.h>
|
||||
#import <ReactNativeNavigation/ReactNativeNavigation.h>
|
||||
#import "RNNotifications.h"
|
||||
#import <UploadAttachments/UploadAttachments-Swift.h>
|
||||
#import <UserNotifications/UserNotifications.h>
|
||||
#import "Mattermost-Swift.h"
|
||||
|
|
|
|||
|
|
@ -54,10 +54,10 @@ NSString *const ReplyActionID = @"REPLY_ACTION";
|
|||
NSString *completionKey = response.notification.request.identifier;
|
||||
NSDictionary *parsedResponse = [RNNotificationParser parseNotificationResponse:response];
|
||||
NSString *message = [parsedResponse valueForKeyPath:@"action.text"];
|
||||
NSString *channelId = [parsedResponse valueForKeyPath:@"payload.channel_id"];
|
||||
NSString *rootId = [parsedResponse valueForKeyPath:@"payload.root_id"];
|
||||
NSString *channelId = [parsedResponse valueForKeyPath:@"notification.channel_id"];
|
||||
NSString *rootId = [parsedResponse valueForKeyPath:@"notification.root_id"];
|
||||
if (rootId == nil) {
|
||||
rootId = [parsedResponse valueForKeyPath:@"payload.post_id"];
|
||||
rootId = [parsedResponse valueForKeyPath:@"notification.post_id"];
|
||||
}
|
||||
|
||||
NSDictionary *post = @{
|
||||
|
|
@ -114,17 +114,17 @@ NSString *const ReplyActionID = @"REPLY_ACTION";
|
|||
[self setNotificationCenter:notificationCenter];
|
||||
}
|
||||
|
||||
NSString *id = [[NSUUID UUID] UUIDString];;
|
||||
NSNumber *id = [NSNumber numberWithInteger:[NSDate timeIntervalSinceReferenceDate] * 10000];
|
||||
NSDictionary *notification = @{
|
||||
@"body": @"Message failed to send.",
|
||||
@"alertAction": @"",
|
||||
@"userInfo": @{
|
||||
@"localNotification": @YES,
|
||||
@"localTest": @YES,
|
||||
@"local": @YES,
|
||||
@"test": @NO,
|
||||
@"channel_id": channelId
|
||||
}
|
||||
};
|
||||
[notificationCenter sendLocalNotification:notification withId:id];
|
||||
[notificationCenter postLocalNotification:notification withId:id];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completionHandler();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
||||
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
||||
|
||||
platform :ios, '10.0'
|
||||
platform :ios, '11.0'
|
||||
|
||||
target 'Mattermost' do
|
||||
# Pods for Mattermost
|
||||
|
|
|
|||
108
ios/Podfile.lock
108
ios/Podfile.lock
|
|
@ -32,9 +32,9 @@ PODS:
|
|||
- libwebp/mux (1.1.0):
|
||||
- libwebp/demux
|
||||
- libwebp/webp (1.1.0)
|
||||
- MMKV (1.2.2):
|
||||
- MMKVCore (~> 1.2.2)
|
||||
- MMKVCore (1.2.2)
|
||||
- MMKV (1.2.4):
|
||||
- MMKVCore (~> 1.2.4)
|
||||
- MMKVCore (1.2.4)
|
||||
- Permission-Camera (2.2.2):
|
||||
- RNPermissions
|
||||
- Permission-PhotoLibrary (2.2.2):
|
||||
|
|
@ -212,7 +212,7 @@ PODS:
|
|||
- React
|
||||
- react-native-cookies (3.2.0):
|
||||
- React
|
||||
- react-native-document-picker (4.0.0):
|
||||
- react-native-document-picker (4.1.0):
|
||||
- React-Core
|
||||
- react-native-hw-keyboard-event (0.0.4):
|
||||
- React
|
||||
|
|
@ -220,18 +220,18 @@ PODS:
|
|||
- React-Core
|
||||
- react-native-local-auth (1.6.0):
|
||||
- React
|
||||
- react-native-mmkv-storage (0.3.7):
|
||||
- MMKV (= 1.2.2)
|
||||
- react-native-mmkv-storage (0.4.1):
|
||||
- MMKV (= 1.2.4)
|
||||
- React
|
||||
- react-native-netinfo (5.9.7):
|
||||
- React-Core
|
||||
- react-native-notifications (2.1.7):
|
||||
- React
|
||||
- react-native-notifications (3.4.0):
|
||||
- React-Core
|
||||
- react-native-passcode-status (1.1.2):
|
||||
- React
|
||||
- react-native-safe-area (0.5.1):
|
||||
- React
|
||||
- react-native-safe-area-context (3.1.8):
|
||||
- react-native-safe-area-context (3.1.9):
|
||||
- React-Core
|
||||
- react-native-video (5.1.0-alpha8):
|
||||
- React
|
||||
|
|
@ -300,31 +300,35 @@ PODS:
|
|||
- React-Core (= 0.63.3)
|
||||
- React-cxxreact (= 0.63.3)
|
||||
- React-jsi (= 0.63.3)
|
||||
- ReactNativeExceptionHandler (2.10.8):
|
||||
- React
|
||||
- ReactNativeExceptionHandler (2.10.9):
|
||||
- React-Core
|
||||
- ReactNativeKeyboardTrackingView (5.7.0):
|
||||
- React
|
||||
- ReactNativeNavigation (7.1.0):
|
||||
- ReactNativeNavigation (7.3.0):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- React-RCTText
|
||||
- ReactNativeNavigation/Core (= 7.3.0)
|
||||
- ReactNativeNavigation/Core (7.3.0):
|
||||
- React-Core
|
||||
- React-RCTImage
|
||||
- React-RCTText
|
||||
- ReactNativeNavigation/Core (= 7.1.0)
|
||||
- rn-fetch-blob (0.12.0):
|
||||
- React-Core
|
||||
- RNCAsyncStorage (1.12.1):
|
||||
- React-Core
|
||||
- RNCClipboard (1.5.0):
|
||||
- RNCClipboard (1.5.1):
|
||||
- React-Core
|
||||
- RNCMaskedView (0.1.10):
|
||||
- React
|
||||
- RNDeviceInfo (7.0.2):
|
||||
- RNDeviceInfo (7.1.0):
|
||||
- React-Core
|
||||
- RNDevMenu (4.0.2):
|
||||
- React-Core
|
||||
- React-Core/DevSupport
|
||||
- React-RCTNetwork
|
||||
- RNFastImage (8.3.2):
|
||||
- React
|
||||
- RNFastImage (8.3.4):
|
||||
- React-Core
|
||||
- SDWebImage (~> 5.8)
|
||||
- SDWebImageWebPCoder (~> 0.6.1)
|
||||
- RNFileViewer (2.1.4):
|
||||
|
|
@ -333,38 +337,38 @@ PODS:
|
|||
- React
|
||||
- RNKeychain (4.0.5):
|
||||
- React
|
||||
- RNLocalize (1.4.2):
|
||||
- RNLocalize (2.0.0):
|
||||
- React-Core
|
||||
- RNPermissions (2.2.2):
|
||||
- React-Core
|
||||
- RNReactNativeHapticFeedback (1.11.0):
|
||||
- React-Core
|
||||
- RNReanimated (1.13.1):
|
||||
- React
|
||||
- RNReanimated (1.13.2):
|
||||
- React-Core
|
||||
- RNRudderSdk (1.0.0):
|
||||
- React
|
||||
- Rudder
|
||||
- RNScreens (2.11.0):
|
||||
- React
|
||||
- RNSentry (1.9.0):
|
||||
- RNScreens (2.15.0):
|
||||
- React-Core
|
||||
- Sentry (~> 5.2.0)
|
||||
- RNShare (3.8.1):
|
||||
- RNSentry (2.0.0):
|
||||
- React-Core
|
||||
- Sentry (~> 6.0.3)
|
||||
- RNShare (4.1.0):
|
||||
- React-Core
|
||||
- RNSVG (12.1.0):
|
||||
- React
|
||||
- RNVectorIcons (7.1.0):
|
||||
- React
|
||||
- Rudder (1.0.4)
|
||||
- SDWebImage (5.8.4):
|
||||
- SDWebImage/Core (= 5.8.4)
|
||||
- SDWebImage/Core (5.8.4)
|
||||
- Rudder (1.0.9)
|
||||
- SDWebImage (5.9.4):
|
||||
- SDWebImage/Core (= 5.9.4)
|
||||
- SDWebImage/Core (5.9.4)
|
||||
- SDWebImageWebPCoder (0.6.1):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.7)
|
||||
- Sentry (5.2.1):
|
||||
- Sentry/Core (= 5.2.1)
|
||||
- Sentry/Core (5.2.1)
|
||||
- Sentry (6.0.7):
|
||||
- Sentry/Core (= 6.0.7)
|
||||
- Sentry/Core (6.0.7)
|
||||
- Swime (3.0.6)
|
||||
- XCDYouTubeKit (2.8.2)
|
||||
- Yoga (1.14.0)
|
||||
|
|
@ -606,8 +610,8 @@ SPEC CHECKSUMS:
|
|||
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
|
||||
jail-monkey: 80c9e34da2cd54023e5ad08bf7051ec75bd43d5b
|
||||
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
|
||||
MMKV: b14909757d8b70e2aa89ff1c6d56a7b239e10a29
|
||||
MMKVCore: 6225324fe5006026bc86ef8641d567e00c6582f3
|
||||
MMKV: f15696ad598023bf6cbb17eadee13efc185c5028
|
||||
MMKVCore: 9a9c10e4faf3b3068367fb2efe5419722f3d2e8a
|
||||
Permission-Camera: 375576c57ea625c88137d2cc52ba6dfeb21db036
|
||||
Permission-PhotoLibrary: bb20a7ac8aec0f7459558e5fbe2bd0a6f2744be3
|
||||
RCTRequired: 48884c74035a0b5b76dbb7a998bd93bcfc5f2047
|
||||
|
|
@ -623,16 +627,16 @@ SPEC CHECKSUMS:
|
|||
React-jsinspector: 8e68ffbfe23880d3ee9bafa8be2777f60b25cbe2
|
||||
react-native-cameraroll: 9d2b7c1707204d2040d2812f960c6cebdbd9f670
|
||||
react-native-cookies: 854d59c4135c70b92a02ca4930e68e4e2eb58150
|
||||
react-native-document-picker: b3e78a8f7fef98b5cb069f20fc35797d55e68e28
|
||||
react-native-document-picker: 37b870da56cf33b8432212842e3f374b9fe98889
|
||||
react-native-hw-keyboard-event: b517cefb8d5c659a38049c582de85ff43337dc53
|
||||
react-native-image-picker: 32d1ad2c0024ca36161ae0d5c2117e2d6c441f11
|
||||
react-native-local-auth: 359af242caa1e5c501ac9dfe33b1e238ad8f08c6
|
||||
react-native-mmkv-storage: a452e035494ecb7f641ec192b2dccdb50021a826
|
||||
react-native-mmkv-storage: ceaec36b6967c680e60f3be5e91ba3f66d488697
|
||||
react-native-netinfo: e36c1bb6df27ab84aa933679b3f5bbf9d180b18f
|
||||
react-native-notifications: 24706907104a0f00c35c4bde7e0ca76a50f730e1
|
||||
react-native-notifications: 1e4912c8f11741799c823f263beaf9f7f829955b
|
||||
react-native-passcode-status: 88c4f6e074328bc278bd127646b6c694ad5a530a
|
||||
react-native-safe-area: e8230b0017d76c00de6b01e2412dcf86b127c6a3
|
||||
react-native-safe-area-context: 01158a92c300895d79dee447e980672dc3fb85a6
|
||||
react-native-safe-area-context: 86612d2c9a9e94e288319262d10b5f93f0b395f5
|
||||
react-native-video: 8d97379f3c2322a569f1e27542ad1a646cad9444
|
||||
react-native-webview: 0d1c2b4e7ffb0543a74fa0512f2f8dc5fb0e49e2
|
||||
React-RCTActionSheet: 53ea72699698b0b47a6421cb1c8b4ab215a774aa
|
||||
|
|
@ -645,38 +649,38 @@ SPEC CHECKSUMS:
|
|||
React-RCTText: 65a6de06a7389098ce24340d1d3556015c38f746
|
||||
React-RCTVibration: 8e9fb25724a0805107fc1acc9075e26f814df454
|
||||
ReactCommon: 4167844018c9ed375cc01a843e9ee564399e53c3
|
||||
ReactNativeExceptionHandler: 8025d98049c25f186835a3af732dd7c9974d6dce
|
||||
ReactNativeExceptionHandler: f1638ffd507ef1b1794af25884fa0eb30dd5c551
|
||||
ReactNativeKeyboardTrackingView: 02137fac3b2ebd330d74fa54ead48b14750a2306
|
||||
ReactNativeNavigation: 65025dab27b404053678593b2450ed7a022e3173
|
||||
ReactNativeNavigation: c2dcda2b86e32090c443182206c915107d03106f
|
||||
rn-fetch-blob: 17961aec08caae68bb8fc0e5b40f93b3acfa6932
|
||||
RNCAsyncStorage: cb9a623793918c6699586281f0b51cbc38f046f9
|
||||
RNCClipboard: 8f9f12fabf3c06e976f19f87a62c89e28dfedfca
|
||||
RNCClipboard: 5e299c6df8e0c98f3d7416b86ae563d3a9f768a3
|
||||
RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
|
||||
RNDeviceInfo: a37a15a98822c31c3982cb28eba6d336ba4d0968
|
||||
RNDeviceInfo: 2c198acf2cef2dc8e5bf2b502fdde0e7e5ef3520
|
||||
RNDevMenu: 9f80d65b80ba1fa84e5361d017b8c854a2f05005
|
||||
RNFastImage: e19ba191922e7dab9d932a4d59d62d76660aa222
|
||||
RNFastImage: d4870d58f5936111c56218dbd7fcfc18e65b58ff
|
||||
RNFileViewer: 83cc066ad795b1f986791d03b56fe0ee14b6a69f
|
||||
RNGestureHandler: 7a5833d0f788dbd107fbb913e09aa0c1ff333c39
|
||||
RNKeychain: 840f8e6f13be0576202aefcdffd26a4f54bfe7b5
|
||||
RNLocalize: 4071198b59b461f3b74eebc5fee8c50f13e39e79
|
||||
RNLocalize: dc432c370fe76ad48cb380386232ca68d534a52a
|
||||
RNPermissions: 067727df624665d4a6c8e2cffcc172ba608b96ed
|
||||
RNReactNativeHapticFeedback: 653a8c126a0f5e88ce15ffe280b3ff37e1fbb285
|
||||
RNReanimated: dd8c286ab5dd4ba36d3a7fef8bff7e08711b5476
|
||||
RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad
|
||||
RNRudderSdk: 5d99b1a5a582ab55d6213b38018d35e98818af63
|
||||
RNScreens: 0e91da98ab26d5d04c7b59a9b6bd694124caf88c
|
||||
RNSentry: 1adaa43b01c6a3ab5091d4d1add66b7c58558898
|
||||
RNShare: 26eb3a3a3a83f059318cafb0b09547e099969058
|
||||
RNScreens: 2ad555d4d9fa10b91bb765ca07fe9b29d59573f0
|
||||
RNSentry: cb4ef23400fb6690f6ac8f6acef0c023a8a4f37d
|
||||
RNShare: 106a76243ac90f43ddb9028dcb78ade406b8adff
|
||||
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
|
||||
RNVectorIcons: bc69e6a278b14842063605de32bec61f0b251a59
|
||||
Rudder: 57a48709b714c4746a96f4d4d00f33e78a62a5ee
|
||||
SDWebImage: cf6922231e95550934da2ada0f20f2becf2ceba9
|
||||
Rudder: 90ed801a09c73017184e6fc901370be1754eb182
|
||||
SDWebImage: b69257f4ab14e9b6a2ef53e910fdf914d8f757c1
|
||||
SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21
|
||||
Sentry: 7d075cae43a9a518fdd51e258b6212f0527c51cd
|
||||
Sentry: e2c691627ae1dc0029acebbd1b0b4af4df12af73
|
||||
Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b
|
||||
XCDYouTubeKit: 79baadb0560673a67c771eba45f83e353fd12c1f
|
||||
Yoga: 7d13633d129fd179e01b8953d38d47be90db185a
|
||||
YoutubePlayer-in-WKWebView: af2f5929fc78882d94bfdfeea999b661b78d9717
|
||||
|
||||
PODFILE CHECKSUM: 1aabd16b6a9ed2037b4d7443027d222817790468
|
||||
PODFILE CHECKSUM: 876d4bb13b09f8d0961bb18b2338fc5936aa5e63
|
||||
|
||||
COCOAPODS: 1.10.0.rc.1
|
||||
|
|
|
|||
2473
package-lock.json
generated
2473
package-lock.json
generated
File diff suppressed because it is too large
Load diff
76
package.json
76
package.json
|
|
@ -7,29 +7,29 @@
|
|||
"license": "Apache 2.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.12.1",
|
||||
"@babel/runtime": "7.12.5",
|
||||
"@react-native-community/async-storage": "1.12.1",
|
||||
"@react-native-community/cameraroll": "4.0.1",
|
||||
"@react-native-community/clipboard": "1.5.0",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/masked-view": "0.1.10",
|
||||
"@react-native-community/netinfo": "5.9.7",
|
||||
"@react-navigation/native": "5.7.6",
|
||||
"@react-navigation/stack": "5.9.3",
|
||||
"@react-navigation/native": "5.8.9",
|
||||
"@react-navigation/stack": "5.12.6",
|
||||
"@rudderstack/rudder-sdk-react-native": "1.0.3",
|
||||
"@sentry/react-native": "1.9.0",
|
||||
"@sentry/react-native": "2.0.0",
|
||||
"analytics-react-native": "1.2.0",
|
||||
"commonmark": "github:mattermost/commonmark.js#f6ab98dede6ce4b4e7adea140ac77249bfb2d6ce",
|
||||
"commonmark-react-renderer": "github:mattermost/commonmark-react-renderer#3a2ac19cab725ad28b170fdc1d397dddedcf87eb",
|
||||
"core-js": "3.6.5",
|
||||
"core-js": "3.7.0",
|
||||
"deep-equal": "2.0.4",
|
||||
"deepmerge": "4.2.2",
|
||||
"emoji-regex": "9.2.0",
|
||||
"form-data": "3.0.0",
|
||||
"fuse.js": "6.4.2",
|
||||
"fuse.js": "6.4.3",
|
||||
"intl": "1.2.5",
|
||||
"jail-monkey": "2.3.3",
|
||||
"mime-db": "1.45.0",
|
||||
"moment-timezone": "0.5.31",
|
||||
"moment-timezone": "0.5.32",
|
||||
"prop-types": "15.7.2",
|
||||
"react": "16.13.1",
|
||||
"react-intl": "2.8.0",
|
||||
|
|
@ -39,11 +39,11 @@
|
|||
"react-native-button": "3.0.1",
|
||||
"react-native-calendars": "1.403.0",
|
||||
"react-native-cookies": "github:mattermost/react-native-cookies#b35bafc388ae09c83bd875e887daf6a0755e0b40",
|
||||
"react-native-device-info": "7.0.2",
|
||||
"react-native-document-picker": "4.0.0",
|
||||
"react-native-device-info": "7.1.0",
|
||||
"react-native-document-picker": "4.1.0",
|
||||
"react-native-elements": "2.3.2",
|
||||
"react-native-exception-handler": "2.10.8",
|
||||
"react-native-fast-image": "8.3.2",
|
||||
"react-native-exception-handler": "2.10.9",
|
||||
"react-native-fast-image": "8.3.4",
|
||||
"react-native-file-viewer": "2.1.4",
|
||||
"react-native-gesture-handler": "1.8.0",
|
||||
"react-native-haptic-feedback": "1.11.0",
|
||||
|
|
@ -54,19 +54,19 @@
|
|||
"react-native-keychain": "4.0.5",
|
||||
"react-native-linear-gradient": "2.5.6",
|
||||
"react-native-local-auth": "1.6.0",
|
||||
"react-native-localize": "1.4.2",
|
||||
"react-native-mmkv-storage": "0.3.7",
|
||||
"react-native-navigation": "7.1.0",
|
||||
"react-native-notifications": "2.1.7",
|
||||
"react-native-localize": "2.0.0",
|
||||
"react-native-mmkv-storage": "0.4.1",
|
||||
"react-native-navigation": "7.3.0",
|
||||
"react-native-notifications": "3.4.0",
|
||||
"react-native-passcode-status": "1.1.2",
|
||||
"react-native-permissions": "2.2.2",
|
||||
"react-native-reanimated": "1.13.1",
|
||||
"react-native-redash": "14.2.4",
|
||||
"react-native-reanimated": "1.13.2",
|
||||
"react-native-redash": "15.11.1",
|
||||
"react-native-safe-area": "0.5.1",
|
||||
"react-native-safe-area-context": "3.1.8",
|
||||
"react-native-screens": "2.11.0",
|
||||
"react-native-safe-area-context": "3.1.9",
|
||||
"react-native-screens": "2.15.0",
|
||||
"react-native-section-list-get-item-layout": "2.2.3",
|
||||
"react-native-share": "3.8.1",
|
||||
"react-native-share": "4.1.0",
|
||||
"react-native-slider": "0.11.0",
|
||||
"react-native-status-bar-size": "0.3.3",
|
||||
"react-native-svg": "12.1.0",
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
"react-native-video": "5.1.0-alpha8",
|
||||
"react-native-webview": "github:mattermost/react-native-webview#b5e22940a613869d3999feac9451ee65352f4fbe",
|
||||
"react-native-youtube": "2.0.1",
|
||||
"react-redux": "7.2.1",
|
||||
"react-redux": "7.2.2",
|
||||
"redux": "4.0.5",
|
||||
"redux-action-buffer": "1.2.0",
|
||||
"redux-batched-actions": "0.5.0",
|
||||
|
|
@ -97,20 +97,20 @@
|
|||
"@babel/preset-env": "7.12.1",
|
||||
"@babel/register": "7.12.1",
|
||||
"@react-native-community/eslint-config": "2.0.0",
|
||||
"@storybook/addon-knobs": "6.0.26",
|
||||
"@storybook/addon-knobs": "6.0.28",
|
||||
"@storybook/addon-ondevice-knobs": "5.3.23",
|
||||
"@storybook/react-native": "5.3.23",
|
||||
"@storybook/react-native-server": "5.3.23",
|
||||
"@testing-library/react-native": "7.1.0",
|
||||
"@types/enzyme": "3.10.7",
|
||||
"@types/enzyme": "3.10.8",
|
||||
"@types/enzyme-adapter-react-16": "1.0.6",
|
||||
"@types/jest": "26.0.15",
|
||||
"@types/moment-timezone": "0.5.30",
|
||||
"@types/react": "16.9.53",
|
||||
"@types/react-native": "0.63.30",
|
||||
"@types/react": "16.9.56",
|
||||
"@types/react-native": "0.63.35",
|
||||
"@types/react-native-share": "3.3.0",
|
||||
"@types/react-native-video": "5.0.3",
|
||||
"@types/react-redux": "7.1.9",
|
||||
"@types/react-redux": "7.1.11",
|
||||
"@types/react-test-renderer": "16.9.3",
|
||||
"@types/shallow-equals": "1.0.0",
|
||||
"@types/tinycolor2": "1.4.2",
|
||||
|
|
@ -118,33 +118,33 @@
|
|||
"@typescript-eslint/eslint-plugin": "3.10.1",
|
||||
"@typescript-eslint/parser": "3.10.1",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "26.6.1",
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-jest": "26.6.3",
|
||||
"babel-loader": "8.2.1",
|
||||
"babel-plugin-module-resolver": "4.0.0",
|
||||
"babel-plugin-transform-remove-console": "6.9.4",
|
||||
"deep-freeze": "0.0.1",
|
||||
"detox": "17.10.3",
|
||||
"detox": "17.12.0",
|
||||
"enzyme": "3.11.0",
|
||||
"enzyme-adapter-react-16": "1.15.5",
|
||||
"enzyme-to-json": "3.6.1",
|
||||
"eslint": "7.11.0",
|
||||
"eslint": "7.13.0",
|
||||
"eslint-plugin-header": "3.1.0",
|
||||
"eslint-plugin-jest": "24.1.0",
|
||||
"eslint-plugin-jest": "24.1.3",
|
||||
"eslint-plugin-mattermost": "github:mattermost/eslint-plugin-mattermost#070ce792d105482ffb2b27cfc0b7e78b3d20acee",
|
||||
"eslint-plugin-react": "7.21.5",
|
||||
"harmony-reflect": "1.6.1",
|
||||
"husky": "4.3.0",
|
||||
"isomorphic-fetch": "3.0.0",
|
||||
"jest": "26.6.1",
|
||||
"jest-cli": "26.6.1",
|
||||
"jest": "26.6.3",
|
||||
"jest-cli": "26.6.3",
|
||||
"jest-enzyme": "7.1.2",
|
||||
"jetifier": "1.6.6",
|
||||
"jsdom-global": "3.0.2",
|
||||
"metro-react-native-babel-preset": "0.63.0",
|
||||
"metro-react-native-babel-preset": "0.64.0",
|
||||
"mmjstool": "github:mattermost/mattermost-utilities#519b99a4e51e6c67a0dbd46a6efdff27dc835aaa",
|
||||
"mock-async-storage": "2.2.0",
|
||||
"mock-socket": "9.0.3",
|
||||
"nock": "13.0.4",
|
||||
"nock": "13.0.5",
|
||||
"nyc": "15.1.0",
|
||||
"patch-package": "6.2.2",
|
||||
"react-dom": "16.13.1",
|
||||
|
|
@ -154,8 +154,8 @@
|
|||
"redux-mock-store": "1.5.4",
|
||||
"redux-persist-node-storage": "2.0.0",
|
||||
"socketcluster": "16.0.1",
|
||||
"ts-jest": "26.4.1",
|
||||
"typescript": "4.0.3",
|
||||
"ts-jest": "26.4.4",
|
||||
"typescript": "4.0.5",
|
||||
"underscore": "1.11.0",
|
||||
"util": "0.12.3"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,12 +18,10 @@ module.exports = [
|
|||
'app/init/emm_provider.js',
|
||||
'app/init/fetch.js',
|
||||
'app/init/global_event_handler.js',
|
||||
'app/init/push_notifications.js',
|
||||
'app/init/push_notifications.ts',
|
||||
'app/mattermost.js',
|
||||
'app/mattermost_managed/index.js',
|
||||
'app/mattermost_managed/mattermost-managed.android.js',
|
||||
'app/push_notifications/index.js',
|
||||
'app/push_notifications/push_notifications.android.js',
|
||||
'app/screens/index.js',
|
||||
'app/store/ephemeral_store.js',
|
||||
'app/store/helpers.ts',
|
||||
|
|
|
|||
|
|
@ -18,12 +18,10 @@ module.exports = [
|
|||
'./node_modules/app/init/emm_provider.js',
|
||||
'./node_modules/app/init/fetch.js',
|
||||
'./node_modules/app/init/global_event_handler.js',
|
||||
'./node_modules/app/init/push_notifications.js',
|
||||
'./node_modules/app/init/push_notifications.ts',
|
||||
'./node_modules/app/mattermost.js',
|
||||
'./node_modules/app/mattermost_managed/index.js',
|
||||
'./node_modules/app/mattermost_managed/mattermost-managed.android.js',
|
||||
'./node_modules/app/push_notifications/index.js',
|
||||
'./node_modules/app/push_notifications/push_notifications.android.js',
|
||||
'./node_modules/app/screens/index.js',
|
||||
'./node_modules/app/store/ephemeral_store.js',
|
||||
'./node_modules/app/store/helpers.ts',
|
||||
|
|
|
|||
|
|
@ -18,12 +18,10 @@ module.exports = [
|
|||
'./node_modules/app/init/emm_provider.js',
|
||||
'./node_modules/app/init/fetch.js',
|
||||
'./node_modules/app/init/global_event_handler.js',
|
||||
'./node_modules/app/init/push_notifications.js',
|
||||
'./node_modules/app/init/push_notifications.ts',
|
||||
'./node_modules/app/mattermost.js',
|
||||
'./node_modules/app/mattermost_managed/index.js',
|
||||
'./node_modules/app/mattermost_managed/mattermost-managed.ios.js',
|
||||
'./node_modules/app/push_notifications/index.js',
|
||||
'./node_modules/app/push_notifications/push_notifications.ios.js',
|
||||
'./node_modules/app/screens/index.js',
|
||||
'./node_modules/app/store/ephemeral_store.js',
|
||||
'./node_modules/app/store/helpers.ts',
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
diff --git a/node_modules/mime-db/db.json b/node_modules/mime-db/db.json
|
||||
index e69f352..b21d9da 100644
|
||||
--- a/node_modules/mime-db/db.json
|
||||
+++ b/node_modules/mime-db/db.json
|
||||
@@ -2004,7 +2004,7 @@
|
||||
},
|
||||
"application/vnd.apple.keynote": {
|
||||
"source": "iana",
|
||||
- "extensions": ["keynote"]
|
||||
+ "extensions": ["key"]
|
||||
},
|
||||
"application/vnd.apple.mpegurl": {
|
||||
"source": "iana",
|
||||
41
patches/react-native-localize+2.0.0.patch
Normal file
41
patches/react-native-localize+2.0.0.patch
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
diff --git a/node_modules/react-native-localize/android/src/main/java/com/zoontek/rnlocalize/RNLocalizeModule.java b/node_modules/react-native-localize/android/src/main/java/com/zoontek/rnlocalize/RNLocalizeModule.java
|
||||
index 73fcd14..8c9e447 100644
|
||||
--- a/node_modules/react-native-localize/android/src/main/java/com/zoontek/rnlocalize/RNLocalizeModule.java
|
||||
+++ b/node_modules/react-native-localize/android/src/main/java/com/zoontek/rnlocalize/RNLocalizeModule.java
|
||||
@@ -48,7 +48,6 @@ public class RNLocalizeModule extends ReactContextBaseJavaModule implements Life
|
||||
private final List<String> USES_RTL_LAYOUT =
|
||||
Arrays.asList("ar", "ckb", "fa", "he", "ks", "lrc", "mzn", "ps", "ug", "ur", "yi");
|
||||
|
||||
- private @Nullable final BroadcastReceiver mBroadcastReceiver;
|
||||
private boolean mMainActivityVisible = true;
|
||||
private boolean mEmitChangeOnResume = false;
|
||||
|
||||
@@ -62,7 +61,7 @@ public class RNLocalizeModule extends ReactContextBaseJavaModule implements Life
|
||||
filter.addAction(Intent.ACTION_TIME_CHANGED);
|
||||
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
||||
|
||||
- mBroadcastReceiver = new BroadcastReceiver() {
|
||||
+ BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction() != null) {
|
||||
@@ -72,7 +71,7 @@ public class RNLocalizeModule extends ReactContextBaseJavaModule implements Life
|
||||
};
|
||||
|
||||
reactContext.addLifecycleEventListener(this);
|
||||
- reactContext.registerReceiver(mBroadcastReceiver, filter);
|
||||
+ reactContext.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,9 +111,7 @@ public class RNLocalizeModule extends ReactContextBaseJavaModule implements Life
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void onHostDestroy() {
|
||||
- getReactApplicationContext().unregisterReceiver(mBroadcastReceiver);
|
||||
- }
|
||||
+ public void onHostDestroy() {}
|
||||
|
||||
private void emitLocalizationDidChange() {
|
||||
if (getReactApplicationContext().hasActiveCatalystInstance()) {
|
||||
|
|
@ -1,19 +1,22 @@
|
|||
diff --git a/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m b/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m
|
||||
index fe0ee2b..5bdde1d 100644
|
||||
index 2875bda..8235771 100644
|
||||
--- a/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m
|
||||
+++ b/node_modules/react-native-mmkv-storage/ios/MMKVStorage.m
|
||||
@@ -45,7 +45,10 @@ - (id)init
|
||||
@@ -45,10 +45,10 @@ - (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
- [MMKV initialize];
|
||||
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
|
||||
- NSString *libraryPath = (NSString *) [paths firstObject];
|
||||
- NSString *rootDir = [libraryPath stringByAppendingPathComponent:@"mmkv"];
|
||||
- [MMKV initializeMMKV:rootDir];
|
||||
+ NSBundle *bundle = [NSBundle mainBundle];
|
||||
+ NSString *APP_GROUP_ID = [bundle objectForInfoDictionaryKey:@"AppGroupIdentifier"];
|
||||
+ NSString *groupDir = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_ID].path;
|
||||
+ [MMKV initializeMMKV:nil groupDir:groupDir logLevel:MMKVLogInfo];
|
||||
|
||||
secureStorage = [[SecureStorage alloc]init];
|
||||
IdStore = [[IDStore alloc] initWithMMKV:[MMKV mmkvWithID:@"mmkvIdStore"]];
|
||||
mmkvMap = [NSMutableDictionary dictionary];
|
||||
diff --git a/node_modules/react-native-mmkv-storage/ios/SecureStorage.m b/node_modules/react-native-mmkv-storage/ios/SecureStorage.m
|
||||
index 70f3a01..07e1af0 100644
|
||||
--- a/node_modules/react-native-mmkv-storage/ios/SecureStorage.m
|
||||
|
|
@ -44,27 +44,11 @@ index 3bfbc0b..cdb0d05 100644
|
|||
}
|
||||
});
|
||||
}
|
||||
diff --git a/node_modules/react-native-navigation/lib/ios/RNNCommandsHandler.m b/node_modules/react-native-navigation/lib/ios/RNNCommandsHandler.m
|
||||
index f7aba70..f8d3f38 100644
|
||||
--- a/node_modules/react-native-navigation/lib/ios/RNNCommandsHandler.m
|
||||
+++ b/node_modules/react-native-navigation/lib/ios/RNNCommandsHandler.m
|
||||
@@ -312,10 +312,9 @@ - (void)dismissAllModals:(NSDictionary *)mergeOptions commandId:(NSString*)comma
|
||||
[CATransaction begin];
|
||||
[CATransaction setCompletionBlock:^{
|
||||
[self->_eventEmitter sendOnNavigationCommandCompletion:dismissAllModals commandId:commandId];
|
||||
- completion();
|
||||
}];
|
||||
RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:mergeOptions];
|
||||
- [_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES] completion:nil];
|
||||
+ [_modalManager dismissAllModalsAnimated:[options.animations.dismissModal.enable getWithDefaultValue:YES] completion:completion];
|
||||
|
||||
[CATransaction commit];
|
||||
}
|
||||
diff --git a/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m b/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m
|
||||
index f98f7a1..26ecb83 100644
|
||||
index f5187d9..d97e766 100644
|
||||
--- a/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m
|
||||
+++ b/node_modules/react-native-navigation/lib/ios/RNNViewLocation.m
|
||||
@@ -31,11 +31,7 @@ - (CGFloat)getCornerRadius:(UIView *)view {
|
||||
@@ -32,11 +32,7 @@ - (CGFloat)getClippedCornerRadius:(UIView *)view {
|
||||
|
||||
- (CATransform3D)getTransform:(UIView *)view {
|
||||
if (view) {
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
diff --git a/node_modules/react-native-notifications/RNNotifications/RNNotificationsStore.m b/node_modules/react-native-notifications/RNNotifications/RNNotificationsStore.m
|
||||
index d5e953a..08d4d46 100644
|
||||
--- a/node_modules/react-native-notifications/RNNotifications/RNNotificationsStore.m
|
||||
+++ b/node_modules/react-native-notifications/RNNotifications/RNNotificationsStore.m
|
||||
@@ -40,7 +40,9 @@ - (void)setPresentationCompletionHandler:(void (^)(UNNotificationPresentationOpt
|
||||
- (void)completeAction:(NSString *)completionKey {
|
||||
void (^completionHandler)() = (void (^)())[_actionCompletionHandlers valueForKey:completionKey];
|
||||
if (completionHandler) {
|
||||
- completionHandler();
|
||||
+ dispatch_async(dispatch_get_main_queue(), ^{
|
||||
+ completionHandler();
|
||||
+ });
|
||||
[_actionCompletionHandlers removeObjectForKey:completionKey];
|
||||
}
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/AndroidManifest.xml b/node_modules/react-native-notifications/android/app/src/main/AndroidManifest.xml
|
||||
index 7053040..ad63eff 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/AndroidManifest.xml
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/AndroidManifest.xml
|
||||
@@ -11,6 +11,7 @@
|
||||
android:protectionLevel="signature" />
|
||||
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
|
||||
<application>
|
||||
|
||||
@@ -29,7 +30,11 @@
|
||||
|
||||
<service
|
||||
android:name=".fcm.FcmInstanceIdRefreshHandlerService"
|
||||
+ android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="false" />
|
||||
+ <receiver android:name=".core.notification.PushNotificationPublisher"
|
||||
+ android:enabled="true"
|
||||
+ android:exported="false" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java
|
||||
index 7b47aed..200cca8 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java
|
||||
@@ -99,12 +99,26 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule implements
|
||||
pushNotification.onPostRequest(notificationId);
|
||||
}
|
||||
|
||||
+ @ReactMethod
|
||||
+ public void scheduleLocalNotification(ReadableMap notificationPropsMap, int notificationId) {
|
||||
+ Log.d(LOGTAG, "Native method invocation: scheduleLocalNotification");
|
||||
+ final Bundle notificationProps = Arguments.toBundle(notificationPropsMap);
|
||||
+ final IPushNotification pushNotification = PushNotification.get(getReactApplicationContext().getApplicationContext(), notificationProps);
|
||||
+ pushNotification.onScheduleRequest(notificationId);
|
||||
+ }
|
||||
+
|
||||
@ReactMethod
|
||||
public void cancelLocalNotification(int notificationId) {
|
||||
IPushNotificationsDrawer notificationsDrawer = PushNotificationsDrawer.get(getReactApplicationContext().getApplicationContext());
|
||||
notificationsDrawer.onNotificationClearRequest(notificationId);
|
||||
}
|
||||
|
||||
+ @ReactMethod
|
||||
+ public void cancelAllLocalNotifications() {
|
||||
+ IPushNotificationsDrawer notificationDrawer = PushNotificationsDrawer.get(getReactApplicationContext().getApplicationContext());
|
||||
+ notificationDrawer.onCancelAllLocalNotifications();
|
||||
+ }
|
||||
+
|
||||
@ReactMethod
|
||||
public void cancelDeliveredNotification(String tag, int notificationId) {
|
||||
IPushNotificationsDrawer notificationsDrawer = PushNotificationsDrawer.get(getReactApplicationContext().getApplicationContext());
|
||||
@@ -126,6 +140,6 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule implements
|
||||
final Context appContext = getReactApplicationContext().getApplicationContext();
|
||||
final Intent tokenFetchIntent = new Intent(appContext, FcmInstanceIdRefreshHandlerService.class);
|
||||
tokenFetchIntent.putExtra(extraFlag, true);
|
||||
- appContext.startService(tokenFetchIntent);
|
||||
+ FcmInstanceIdRefreshHandlerService.enqueueWork(appContext, tokenFetchIntent);
|
||||
}
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/helpers/ScheduleNotificationHelper.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/helpers/ScheduleNotificationHelper.java
|
||||
new file mode 100644
|
||||
index 0000000..c35076d
|
||||
--- /dev/null
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/helpers/ScheduleNotificationHelper.java
|
||||
@@ -0,0 +1,90 @@
|
||||
+package com.wix.reactnativenotifications.core.helpers;
|
||||
+
|
||||
+import android.app.AlarmManager;
|
||||
+import android.os.Build;
|
||||
+import android.os.Bundle;
|
||||
+import android.content.Context;
|
||||
+import android.content.Intent;
|
||||
+import android.app.PendingIntent;
|
||||
+import android.content.SharedPreferences;
|
||||
+import android.util.Log;
|
||||
+
|
||||
+import com.wix.reactnativenotifications.core.notification.PushNotificationProps;
|
||||
+import com.wix.reactnativenotifications.core.notification.PushNotificationPublisher;
|
||||
+
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
+
|
||||
+public class ScheduleNotificationHelper {
|
||||
+ public static ScheduleNotificationHelper sInstance;
|
||||
+ public static final String PREFERENCES_KEY = "rn_push_notification";
|
||||
+ static final String NOTIFICATION_ID = "notificationId";
|
||||
+
|
||||
+ private final SharedPreferences scheduledNotificationsPersistence;
|
||||
+ protected final Context mContext;
|
||||
+
|
||||
+ private ScheduleNotificationHelper(Context context) {
|
||||
+ this.mContext = context;
|
||||
+ this.scheduledNotificationsPersistence = context.getSharedPreferences(ScheduleNotificationHelper.PREFERENCES_KEY, Context.MODE_PRIVATE);
|
||||
+ }
|
||||
+
|
||||
+ public static ScheduleNotificationHelper getInstance(Context context) {
|
||||
+ if (sInstance == null) {
|
||||
+ sInstance = new ScheduleNotificationHelper(context);
|
||||
+ }
|
||||
+ return sInstance;
|
||||
+ }
|
||||
+
|
||||
+ public PendingIntent createPendingNotificationIntent(Bundle bundle) {
|
||||
+ Integer notificationId = Integer.valueOf(bundle.getString("id"));
|
||||
+ Intent notificationIntent = new Intent(mContext, PushNotificationPublisher.class);
|
||||
+ notificationIntent.putExtra(ScheduleNotificationHelper.NOTIFICATION_ID, notificationId);
|
||||
+ notificationIntent.putExtras(bundle);
|
||||
+ return PendingIntent.getBroadcast(mContext, notificationId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
+ }
|
||||
+
|
||||
+ public void schedulePendingNotificationIntent(PendingIntent intent, long fireDate) {
|
||||
+ AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
|
||||
+
|
||||
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
+ alarmManager.setExact(AlarmManager.RTC_WAKEUP, fireDate, intent);
|
||||
+ } else {
|
||||
+ alarmManager.set(AlarmManager.RTC_WAKEUP, fireDate, intent);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void cancelScheduledNotificationIntent(PendingIntent intent) {
|
||||
+ AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
|
||||
+ alarmManager.cancel(intent);
|
||||
+ }
|
||||
+
|
||||
+ public boolean savePreferences(String notificationId, PushNotificationProps notificationProps) {
|
||||
+ SharedPreferences.Editor editor = scheduledNotificationsPersistence.edit();
|
||||
+ editor.putString(notificationId, notificationProps.toString());
|
||||
+ commit(editor);
|
||||
+
|
||||
+ return scheduledNotificationsPersistence.contains(notificationId);
|
||||
+ }
|
||||
+
|
||||
+ public void removePreference(String notificationId) {
|
||||
+ if (scheduledNotificationsPersistence.contains(notificationId)) {
|
||||
+ // remove it from local storage
|
||||
+ SharedPreferences.Editor editor = scheduledNotificationsPersistence.edit();
|
||||
+ editor.remove(notificationId);
|
||||
+ commit(editor);
|
||||
+ } else {
|
||||
+ Log.w(LOGTAG, "Unable to find notification " + notificationId);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public java.util.Set<String> getPreferencesKeys() {
|
||||
+ return scheduledNotificationsPersistence.getAll().keySet();
|
||||
+ }
|
||||
+
|
||||
+ private static void commit(SharedPreferences.Editor editor) {
|
||||
+ if (Build.VERSION.SDK_INT < 9) {
|
||||
+ editor.commit();
|
||||
+ } else {
|
||||
+ editor.apply();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java
|
||||
index 0d70024..47b962e 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java
|
||||
@@ -26,5 +26,20 @@ public interface IPushNotification {
|
||||
*/
|
||||
int onPostRequest(Integer notificationId);
|
||||
|
||||
+ /**
|
||||
+ * Handle a request to schedule this notification.
|
||||
+ *
|
||||
+ * @param notificationId The specific ID to associated with the notification.
|
||||
+ */
|
||||
+ void onScheduleRequest(Integer notificationId);
|
||||
+
|
||||
+ /**
|
||||
+ * Handle a request to post this scheduled notification.
|
||||
+ *
|
||||
+ * @param notificationId The specific ID to associated with the notification.
|
||||
+ * @return The ID assigned to the notification.
|
||||
+ */
|
||||
+ int onPostScheduledRequest(Integer notificationId);
|
||||
+
|
||||
PushNotificationProps asProps();
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
index 524ff07..a9f28e0 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.wix.reactnativenotifications.core.notification;
|
||||
|
||||
+import android.app.AlarmManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
@@ -20,7 +21,9 @@ import com.wix.reactnativenotifications.core.InitialNotificationHolder;
|
||||
import com.wix.reactnativenotifications.core.JsIOHelper;
|
||||
import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
|
||||
import com.wix.reactnativenotifications.core.ProxyService;
|
||||
+import com.wix.reactnativenotifications.core.helpers.ScheduleNotificationHelper;
|
||||
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_OPENED_EVENT_NAME;
|
||||
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME;
|
||||
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_FOREGROUND_EVENT_NAME;
|
||||
@@ -31,7 +34,7 @@ public class PushNotification implements IPushNotification {
|
||||
final protected AppLifecycleFacade mAppLifecycleFacade;
|
||||
final protected AppLaunchHelper mAppLaunchHelper;
|
||||
final protected JsIOHelper mJsIOHelper;
|
||||
- final protected PushNotificationProps mNotificationProps;
|
||||
+ protected PushNotificationProps mNotificationProps;
|
||||
final protected AppVisibilityListener mAppVisibilityListener = new AppVisibilityListener() {
|
||||
@Override
|
||||
public void onAppVisible() {
|
||||
@@ -80,6 +83,41 @@ public class PushNotification implements IPushNotification {
|
||||
return postNotification(notificationId);
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public void onScheduleRequest(Integer notificationId) {
|
||||
+ Bundle bundle = mNotificationProps.asBundle();
|
||||
+
|
||||
+ if (bundle.getString("message") == null) {
|
||||
+ Log.e(LOGTAG, "No message specified for the scheduled notification");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ double date = bundle.getDouble("fireDate");
|
||||
+ if (date == 0) {
|
||||
+ Log.e(LOGTAG, "No date specified for the scheduled notification");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+ String notificationIdStr = Integer.toString(notificationId);
|
||||
+ boolean isSaved = helper.savePreferences(notificationIdStr, mNotificationProps);
|
||||
+ if (!isSaved) {
|
||||
+ Log.e(LOGTAG, "Failed to save preference for notificationId " + notificationIdStr);
|
||||
+ }
|
||||
+
|
||||
+ PendingIntent pendingIntent = helper.createPendingNotificationIntent(bundle);
|
||||
+ long fireDate = (long) date;
|
||||
+ helper.schedulePendingNotificationIntent(pendingIntent, fireDate);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int onPostScheduledRequest(Integer notificationId) {
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+ helper.removePreference(String.valueOf(notificationId));
|
||||
+
|
||||
+ return postNotification(notificationId);
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public PushNotificationProps asProps() {
|
||||
return mNotificationProps.copy();
|
||||
@@ -140,7 +178,9 @@ public class PushNotification implements IPushNotification {
|
||||
}
|
||||
|
||||
protected Notification buildNotification(PendingIntent intent) {
|
||||
- return getNotificationBuilder(intent).build();
|
||||
+ Notification.Builder builder = getNotificationBuilder(intent);
|
||||
+ Notification notification = builder.build();
|
||||
+ return notification;
|
||||
}
|
||||
|
||||
protected Notification.Builder getNotificationBuilder(PendingIntent intent) {
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotificationPublisher.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotificationPublisher.java
|
||||
new file mode 100644
|
||||
index 0000000..58ff887
|
||||
--- /dev/null
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotificationPublisher.java
|
||||
@@ -0,0 +1,27 @@
|
||||
+package com.wix.reactnativenotifications.core.notification;
|
||||
+
|
||||
+import android.app.Application;
|
||||
+import android.content.BroadcastReceiver;
|
||||
+import android.content.Context;
|
||||
+import android.content.Intent;
|
||||
+import android.util.Log;
|
||||
+
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
+
|
||||
+public class PushNotificationPublisher extends BroadcastReceiver {
|
||||
+ final static String NOTIFICATION_ID = "notificationId";
|
||||
+
|
||||
+ @Override
|
||||
+ public void onReceive(Context context, Intent intent) {
|
||||
+ Log.d(LOGTAG, "Received scheduled notification intent");
|
||||
+ int notificationId = intent.getIntExtra(NOTIFICATION_ID, 0);
|
||||
+ long currentTime = System.currentTimeMillis();
|
||||
+
|
||||
+ Application applicationContext = (Application) context.getApplicationContext();
|
||||
+ final IPushNotification pushNotification = PushNotification.get(applicationContext, intent.getExtras());
|
||||
+
|
||||
+ Log.i(LOGTAG, "PushNotificationPublisher: Prepare To Publish: " + notificationId + ", Now Time: " + currentTime);
|
||||
+
|
||||
+ pushNotification.onPostScheduledRequest(notificationId);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java
|
||||
index e22cd62..48aa1cd 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java
|
||||
@@ -11,4 +11,5 @@ public interface IPushNotificationsDrawer {
|
||||
void onNotificationClearRequest(int id);
|
||||
void onNotificationClearRequest(String tag, int id);
|
||||
void onAllNotificationsClearRequest();
|
||||
+ void onCancelAllLocalNotifications();
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java
|
||||
index dea6958..2c0f1c7 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java
|
||||
@@ -2,10 +2,16 @@ package com.wix.reactnativenotifications.core.notificationdrawer;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.NotificationManager;
|
||||
+import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
+import android.os.Bundle;
|
||||
+import android.util.Log;
|
||||
|
||||
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
||||
import com.wix.reactnativenotifications.core.InitialNotificationHolder;
|
||||
+import com.wix.reactnativenotifications.core.helpers.ScheduleNotificationHelper;
|
||||
+
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
|
||||
public class PushNotificationsDrawer implements IPushNotificationsDrawer {
|
||||
|
||||
@@ -72,8 +78,41 @@ public class PushNotificationsDrawer implements IPushNotificationsDrawer {
|
||||
notificationManager.cancelAll();
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public void onCancelAllLocalNotifications() {
|
||||
+ clearAll();
|
||||
+ cancelAllScheduledNotifications();
|
||||
+ }
|
||||
+
|
||||
protected void clearAll() {
|
||||
final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancelAll();
|
||||
}
|
||||
+
|
||||
+ protected void cancelAllScheduledNotifications() {
|
||||
+ Log.i(LOGTAG, "Cancelling all scheduled notifications");
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+
|
||||
+ for (String notificationId : helper.getPreferencesKeys()) {
|
||||
+ cancelScheduledNotification(notificationId);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ protected void cancelScheduledNotification(String notificationId) {
|
||||
+ Log.i(LOGTAG, "Cancelling scheduled notification: " + notificationId);
|
||||
+
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+
|
||||
+ // Remove it from the alarm manger schedule
|
||||
+ Bundle bundle = new Bundle();
|
||||
+ bundle.putString("id", notificationId);
|
||||
+ PendingIntent pendingIntent = helper.createPendingNotificationIntent(bundle);
|
||||
+ helper.cancelScheduledNotificationIntent(pendingIntent);
|
||||
+
|
||||
+ helper.removePreference(notificationId);
|
||||
+
|
||||
+ // Remove it from the notification center
|
||||
+ final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
+ notificationManager.cancel(Integer.parseInt(notificationId));
|
||||
+ }
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/fcm/FcmInstanceIdRefreshHandlerService.java b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/fcm/FcmInstanceIdRefreshHandlerService.java
|
||||
index dd2cc9a..f1ef15a 100644
|
||||
--- a/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/fcm/FcmInstanceIdRefreshHandlerService.java
|
||||
+++ b/node_modules/react-native-notifications/android/app/src/main/java/com/wix/reactnativenotifications/fcm/FcmInstanceIdRefreshHandlerService.java
|
||||
@@ -1,19 +1,22 @@
|
||||
package com.wix.reactnativenotifications.fcm;
|
||||
|
||||
-import android.app.IntentService;
|
||||
+import android.support.annotation.NonNull;
|
||||
+import android.support.v4.app.JobIntentService;
|
||||
+import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
-public class FcmInstanceIdRefreshHandlerService extends IntentService {
|
||||
+public class FcmInstanceIdRefreshHandlerService extends JobIntentService {
|
||||
|
||||
public static String EXTRA_IS_APP_INIT = "isAppInit";
|
||||
public static String EXTRA_MANUAL_REFRESH = "doManualRefresh";
|
||||
+ static final int JOB_ID = 1000;
|
||||
|
||||
- public FcmInstanceIdRefreshHandlerService() {
|
||||
- super(FcmInstanceIdRefreshHandlerService.class.getSimpleName());
|
||||
+ public static void enqueueWork(Context context, Intent work) {
|
||||
+ enqueueWork(context, FcmInstanceIdRefreshHandlerService.class, JOB_ID, work);
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected void onHandleIntent(Intent intent) {
|
||||
+ protected void onHandleWork(@NonNull Intent intent) {
|
||||
IFcmToken fcmToken = FcmToken.get(this);
|
||||
if (fcmToken == null) {
|
||||
return;
|
||||
diff --git a/node_modules/react-native-notifications/lib/src/index.android.js b/node_modules/react-native-notifications/lib/src/index.android.js
|
||||
index ac2fe5c..18bee18 100644
|
||||
--- a/node_modules/react-native-notifications/lib/src/index.android.js
|
||||
+++ b/node_modules/react-native-notifications/lib/src/index.android.js
|
||||
@@ -67,10 +67,23 @@ export class NotificationsAndroid {
|
||||
return id;
|
||||
}
|
||||
|
||||
+ static scheduleLocalNotification(notification: Object) {
|
||||
+ const id = Math.random() * 100000000 | 0; // Bitwise-OR forces value onto a 32bit limit
|
||||
+ if (!notification.hasOwnProperty('id')) {
|
||||
+ notification.id = id.toString();
|
||||
+ }
|
||||
+ RNNotifications.scheduleLocalNotification(notification, id);
|
||||
+ return id;
|
||||
+ }
|
||||
+
|
||||
static cancelLocalNotification(id) {
|
||||
RNNotifications.cancelLocalNotification(id);
|
||||
}
|
||||
|
||||
+ static cancelAllLocalNotifications() {
|
||||
+ RNNotifications.cancelAllLocalNotifications();
|
||||
+ }
|
||||
+
|
||||
static cancelDeliveredNotification(tag, id) {
|
||||
RNNotifications.cancelDeliveredNotification(tag, id);
|
||||
}
|
||||
499
patches/react-native-notifications+3.4.0.patch
Normal file
499
patches/react-native-notifications+3.4.0.patch
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/AndroidManifest.xml b/node_modules/react-native-notifications/lib/android/app/src/main/AndroidManifest.xml
|
||||
index abd988a..4ac4725 100644
|
||||
--- a/node_modules/react-native-notifications/lib/android/app/src/main/AndroidManifest.xml
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/AndroidManifest.xml
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wix.reactnativenotifications">
|
||||
|
||||
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<application>
|
||||
|
||||
<!--
|
||||
@@ -22,6 +23,9 @@
|
||||
android:name=".fcm.FcmInstanceIdRefreshHandlerService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
+ <receiver android:name=".core.notification.PushNotificationPublisher"
|
||||
+ android:enabled="true"
|
||||
+ android:exported="false" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java
|
||||
index db9eaba..af65d0e 100644
|
||||
--- a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsModule.java
|
||||
@@ -100,7 +100,12 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule implements
|
||||
if(BuildConfig.DEBUG) Log.d(LOGTAG, "Native method invocation: postLocalNotification");
|
||||
final Bundle notificationProps = Arguments.toBundle(notificationPropsMap);
|
||||
final IPushNotification pushNotification = PushNotification.get(getReactApplicationContext().getApplicationContext(), notificationProps);
|
||||
- pushNotification.onPostRequest(notificationId);
|
||||
+ double date = notificationProps.getDouble("fireDate", 0);
|
||||
+ if (date == 0) {
|
||||
+ pushNotification.onPostRequest(notificationId);
|
||||
+ } else {
|
||||
+ pushNotification.onScheduleRequest(notificationId);
|
||||
+ }
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@@ -109,6 +114,12 @@ public class RNNotificationsModule extends ReactContextBaseJavaModule implements
|
||||
notificationsDrawer.onNotificationClearRequest(notificationId);
|
||||
}
|
||||
|
||||
+ @ReactMethod
|
||||
+ public void cancelAllLocalNotifications() {
|
||||
+ IPushNotificationsDrawer notificationDrawer = PushNotificationsDrawer.get(getReactApplicationContext().getApplicationContext());
|
||||
+ notificationDrawer.onCancelAllLocalNotifications();
|
||||
+ }
|
||||
+
|
||||
@ReactMethod
|
||||
public void setCategories(ReadableArray categories) {
|
||||
|
||||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/helpers/ScheduleNotificationHelper.java b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/helpers/ScheduleNotificationHelper.java
|
||||
new file mode 100644
|
||||
index 0000000..dde4a2c
|
||||
--- /dev/null
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/helpers/ScheduleNotificationHelper.java
|
||||
@@ -0,0 +1,89 @@
|
||||
+package com.wix.reactnativenotifications.core.helpers;
|
||||
+
|
||||
+import android.app.AlarmManager;
|
||||
+import android.os.Build;
|
||||
+import android.os.Bundle;
|
||||
+import android.content.Context;
|
||||
+import android.content.Intent;
|
||||
+import android.app.PendingIntent;
|
||||
+import android.content.SharedPreferences;
|
||||
+import android.util.Log;
|
||||
+
|
||||
+import com.wix.reactnativenotifications.core.notification.PushNotificationProps;
|
||||
+import com.wix.reactnativenotifications.core.notification.PushNotificationPublisher;
|
||||
+
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
+
|
||||
+public class ScheduleNotificationHelper {
|
||||
+ public static ScheduleNotificationHelper sInstance;
|
||||
+ public static final String PREFERENCES_KEY = "rn_push_notification";
|
||||
+ static final String NOTIFICATION_ID = "notificationId";
|
||||
+
|
||||
+ private final SharedPreferences scheduledNotificationsPersistence;
|
||||
+ protected final Context mContext;
|
||||
+
|
||||
+ private ScheduleNotificationHelper(Context context) {
|
||||
+ this.mContext = context;
|
||||
+ this.scheduledNotificationsPersistence = context.getSharedPreferences(ScheduleNotificationHelper.PREFERENCES_KEY, Context.MODE_PRIVATE);
|
||||
+ }
|
||||
+
|
||||
+ public static ScheduleNotificationHelper getInstance(Context context) {
|
||||
+ if (sInstance == null) {
|
||||
+ sInstance = new ScheduleNotificationHelper(context);
|
||||
+ }
|
||||
+ return sInstance;
|
||||
+ }
|
||||
+
|
||||
+ public PendingIntent createPendingNotificationIntent(Integer notificationId, Bundle bundle) {
|
||||
+ Intent notificationIntent = new Intent(mContext, PushNotificationPublisher.class);
|
||||
+ notificationIntent.putExtra(ScheduleNotificationHelper.NOTIFICATION_ID, notificationId);
|
||||
+ notificationIntent.putExtras(bundle);
|
||||
+ return PendingIntent.getBroadcast(mContext, notificationId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
+ }
|
||||
+
|
||||
+ public void schedulePendingNotificationIntent(PendingIntent intent, long fireDate) {
|
||||
+ AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
|
||||
+
|
||||
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
+ alarmManager.setExact(AlarmManager.RTC_WAKEUP, fireDate, intent);
|
||||
+ } else {
|
||||
+ alarmManager.set(AlarmManager.RTC_WAKEUP, fireDate, intent);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void cancelScheduledNotificationIntent(PendingIntent intent) {
|
||||
+ AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
|
||||
+ alarmManager.cancel(intent);
|
||||
+ }
|
||||
+
|
||||
+ public boolean savePreferences(String notificationId, PushNotificationProps notificationProps) {
|
||||
+ SharedPreferences.Editor editor = scheduledNotificationsPersistence.edit();
|
||||
+ editor.putString(notificationId, notificationProps.toString());
|
||||
+ commit(editor);
|
||||
+
|
||||
+ return scheduledNotificationsPersistence.contains(notificationId);
|
||||
+ }
|
||||
+
|
||||
+ public void removePreference(String notificationId) {
|
||||
+ if (scheduledNotificationsPersistence.contains(notificationId)) {
|
||||
+ // remove it from local storage
|
||||
+ SharedPreferences.Editor editor = scheduledNotificationsPersistence.edit();
|
||||
+ editor.remove(notificationId);
|
||||
+ commit(editor);
|
||||
+ } else {
|
||||
+ Log.w(LOGTAG, "Unable to find notification " + notificationId);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public java.util.Set<String> getPreferencesKeys() {
|
||||
+ return scheduledNotificationsPersistence.getAll().keySet();
|
||||
+ }
|
||||
+
|
||||
+ private static void commit(SharedPreferences.Editor editor) {
|
||||
+ if (Build.VERSION.SDK_INT < 9) {
|
||||
+ editor.commit();
|
||||
+ } else {
|
||||
+ editor.apply();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java
|
||||
index 0d70024..b9e6c88 100644
|
||||
--- a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/IPushNotification.java
|
||||
@@ -26,5 +26,21 @@ public interface IPushNotification {
|
||||
*/
|
||||
int onPostRequest(Integer notificationId);
|
||||
|
||||
+ /**
|
||||
+ * Handle a request to schedule this notification.
|
||||
+ *
|
||||
+ * @param notificationId The specific ID to associated with the notification.
|
||||
+ */
|
||||
+ void onScheduleRequest(Integer notificationId);
|
||||
+
|
||||
+ /**
|
||||
+ * Handle a request to post this scheduled notification.
|
||||
+ *
|
||||
+ * @param notificationId The specific ID to associated with the notification.
|
||||
+ * @return The ID assigned to the notification.
|
||||
+ */
|
||||
+ int onPostScheduledRequest(Integer notificationId);
|
||||
+
|
||||
+
|
||||
PushNotificationProps asProps();
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
index f6ac8ec..08154fc 100644
|
||||
--- a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.wix.reactnativenotifications.core.notification;
|
||||
|
||||
+import android.app.AlarmManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
@@ -8,6 +9,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
+import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
||||
@@ -18,7 +20,9 @@ import com.wix.reactnativenotifications.core.InitialNotificationHolder;
|
||||
import com.wix.reactnativenotifications.core.JsIOHelper;
|
||||
import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
|
||||
import com.wix.reactnativenotifications.core.ProxyService;
|
||||
+import com.wix.reactnativenotifications.core.helpers.ScheduleNotificationHelper;
|
||||
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_OPENED_EVENT_NAME;
|
||||
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME;
|
||||
import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_BACKGROUND_EVENT_NAME;
|
||||
@@ -29,7 +33,7 @@ public class PushNotification implements IPushNotification {
|
||||
final protected AppLifecycleFacade mAppLifecycleFacade;
|
||||
final protected AppLaunchHelper mAppLaunchHelper;
|
||||
final protected JsIOHelper mJsIOHelper;
|
||||
- final protected PushNotificationProps mNotificationProps;
|
||||
+ protected PushNotificationProps mNotificationProps;
|
||||
final protected AppVisibilityListener mAppVisibilityListener = new AppVisibilityListener() {
|
||||
@Override
|
||||
public void onAppVisible() {
|
||||
@@ -78,6 +82,42 @@ public class PushNotification implements IPushNotification {
|
||||
return postNotification(notificationId);
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public void onScheduleRequest(Integer notificationId) {
|
||||
+ Bundle bundle = mNotificationProps.asBundle();
|
||||
+
|
||||
+ if (bundle.getString("body") == null) {
|
||||
+ Log.e(LOGTAG, "No message specified for the scheduled notification");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ double date = bundle.getDouble("fireDate", 0);
|
||||
+ if (date == 0) {
|
||||
+ Log.e(LOGTAG, "No date specified for the scheduled notification");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+ String notificationIdStr = Integer.toString(notificationId);
|
||||
+ boolean isSaved = helper.savePreferences(notificationIdStr, mNotificationProps);
|
||||
+ if (!isSaved) {
|
||||
+ Log.e(LOGTAG, "Failed to save preference for notificationId " + notificationIdStr);
|
||||
+ }
|
||||
+
|
||||
+ PendingIntent pendingIntent = helper.createPendingNotificationIntent(notificationId, bundle);
|
||||
+ long fireDate = (long) date;
|
||||
+ helper.schedulePendingNotificationIntent(pendingIntent, fireDate);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int onPostScheduledRequest(Integer notificationId) {
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+ helper.removePreference(String.valueOf(notificationId));
|
||||
+
|
||||
+ return postNotification(notificationId);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
@Override
|
||||
public PushNotificationProps asProps() {
|
||||
return mNotificationProps.copy();
|
||||
@@ -140,7 +180,9 @@ public class PushNotification implements IPushNotification {
|
||||
}
|
||||
|
||||
protected Notification buildNotification(PendingIntent intent) {
|
||||
- return getNotificationBuilder(intent).build();
|
||||
+ Notification.Builder builder = getNotificationBuilder(intent);
|
||||
+ Notification notification = builder.build();
|
||||
+ return notification;
|
||||
}
|
||||
|
||||
protected Notification.Builder getNotificationBuilder(PendingIntent intent) {
|
||||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotificationPublisher.java b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotificationPublisher.java
|
||||
new file mode 100644
|
||||
index 0000000..58ff887
|
||||
--- /dev/null
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotificationPublisher.java
|
||||
@@ -0,0 +1,27 @@
|
||||
+package com.wix.reactnativenotifications.core.notification;
|
||||
+
|
||||
+import android.app.Application;
|
||||
+import android.content.BroadcastReceiver;
|
||||
+import android.content.Context;
|
||||
+import android.content.Intent;
|
||||
+import android.util.Log;
|
||||
+
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
+
|
||||
+public class PushNotificationPublisher extends BroadcastReceiver {
|
||||
+ final static String NOTIFICATION_ID = "notificationId";
|
||||
+
|
||||
+ @Override
|
||||
+ public void onReceive(Context context, Intent intent) {
|
||||
+ Log.d(LOGTAG, "Received scheduled notification intent");
|
||||
+ int notificationId = intent.getIntExtra(NOTIFICATION_ID, 0);
|
||||
+ long currentTime = System.currentTimeMillis();
|
||||
+
|
||||
+ Application applicationContext = (Application) context.getApplicationContext();
|
||||
+ final IPushNotification pushNotification = PushNotification.get(applicationContext, intent.getExtras());
|
||||
+
|
||||
+ Log.i(LOGTAG, "PushNotificationPublisher: Prepare To Publish: " + notificationId + ", Now Time: " + currentTime);
|
||||
+
|
||||
+ pushNotification.onPostScheduledRequest(notificationId);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java
|
||||
index e22cd62..48aa1cd 100644
|
||||
--- a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/IPushNotificationsDrawer.java
|
||||
@@ -11,4 +11,5 @@ public interface IPushNotificationsDrawer {
|
||||
void onNotificationClearRequest(int id);
|
||||
void onNotificationClearRequest(String tag, int id);
|
||||
void onAllNotificationsClearRequest();
|
||||
+ void onCancelAllLocalNotifications();
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java
|
||||
index a14089f..1262e6d 100644
|
||||
--- a/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java
|
||||
+++ b/node_modules/react-native-notifications/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawer.java
|
||||
@@ -2,9 +2,15 @@ package com.wix.reactnativenotifications.core.notificationdrawer;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.NotificationManager;
|
||||
+import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
+import android.os.Bundle;
|
||||
+import android.util.Log;
|
||||
|
||||
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
||||
+import com.wix.reactnativenotifications.core.helpers.ScheduleNotificationHelper;
|
||||
+
|
||||
+import static com.wix.reactnativenotifications.Defs.LOGTAG;
|
||||
|
||||
public class PushNotificationsDrawer implements IPushNotificationsDrawer {
|
||||
|
||||
@@ -62,4 +68,37 @@ public class PushNotificationsDrawer implements IPushNotificationsDrawer {
|
||||
final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.cancelAll();
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public void onCancelAllLocalNotifications() {
|
||||
+ onAllNotificationsClearRequest();
|
||||
+ cancelAllScheduledNotifications();
|
||||
+ }
|
||||
+
|
||||
+ protected void cancelAllScheduledNotifications() {
|
||||
+ Log.i(LOGTAG, "Cancelling all scheduled notifications");
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+
|
||||
+ for (String notificationId : helper.getPreferencesKeys()) {
|
||||
+ cancelScheduledNotification(notificationId);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ protected void cancelScheduledNotification(String notificationId) {
|
||||
+ Log.i(LOGTAG, "Cancelling scheduled notification: " + notificationId);
|
||||
+
|
||||
+ ScheduleNotificationHelper helper = ScheduleNotificationHelper.getInstance(mContext);
|
||||
+
|
||||
+ // Remove it from the alarm manger schedule
|
||||
+ Bundle bundle = new Bundle();
|
||||
+ bundle.putString("id", notificationId);
|
||||
+ PendingIntent pendingIntent = helper.createPendingNotificationIntent(Integer.parseInt(notificationId), bundle);
|
||||
+ helper.cancelScheduledNotificationIntent(pendingIntent);
|
||||
+
|
||||
+ helper.removePreference(notificationId);
|
||||
+
|
||||
+ // Remove it from the notification center
|
||||
+ final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
+ notificationManager.cancel(Integer.parseInt(notificationId));
|
||||
+ }
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/lib/dist/DTO/Notification.d.ts b/node_modules/react-native-notifications/lib/dist/DTO/Notification.d.ts
|
||||
index 7b2b3b1..3a2f872 100644
|
||||
--- a/node_modules/react-native-notifications/lib/dist/DTO/Notification.d.ts
|
||||
+++ b/node_modules/react-native-notifications/lib/dist/DTO/Notification.d.ts
|
||||
@@ -1,4 +1,5 @@
|
||||
export declare class Notification {
|
||||
+ fireDate?: number | string;
|
||||
identifier: string;
|
||||
payload: any;
|
||||
constructor(payload: object);
|
||||
diff --git a/node_modules/react-native-notifications/lib/dist/DTO/Notification.js b/node_modules/react-native-notifications/lib/dist/DTO/Notification.js
|
||||
index ad7fc1a..a04ec6b 100644
|
||||
--- a/node_modules/react-native-notifications/lib/dist/DTO/Notification.js
|
||||
+++ b/node_modules/react-native-notifications/lib/dist/DTO/Notification.js
|
||||
@@ -5,6 +5,7 @@ class Notification {
|
||||
constructor(payload) {
|
||||
this.payload = payload;
|
||||
this.identifier = this.payload.identifier;
|
||||
+ this.fireDate = undefined;
|
||||
}
|
||||
get title() {
|
||||
return this.payload.title;
|
||||
diff --git a/node_modules/react-native-notifications/lib/dist/Notifications.d.ts b/node_modules/react-native-notifications/lib/dist/Notifications.d.ts
|
||||
index 34e8170..10600d2 100644
|
||||
--- a/node_modules/react-native-notifications/lib/dist/Notifications.d.ts
|
||||
+++ b/node_modules/react-native-notifications/lib/dist/Notifications.d.ts
|
||||
@@ -23,7 +23,7 @@ export declare class NotificationsRoot {
|
||||
/**
|
||||
* postLocalNotification
|
||||
*/
|
||||
- postLocalNotification(notification: Notification, id: number): number;
|
||||
+ postLocalNotification(notification: Notification, id?: number): number;
|
||||
/**
|
||||
* getInitialNotification
|
||||
*/
|
||||
@@ -36,6 +36,10 @@ export declare class NotificationsRoot {
|
||||
* cancelLocalNotification
|
||||
*/
|
||||
cancelLocalNotification(notificationId: string): void;
|
||||
+ /**
|
||||
+ * cancelAllLocalNotifications
|
||||
+ */
|
||||
+ cancelAllLocalNotifications(): void;
|
||||
/**
|
||||
* removeAllDeliveredNotifications
|
||||
*/
|
||||
diff --git a/node_modules/react-native-notifications/lib/dist/Notifications.js b/node_modules/react-native-notifications/lib/dist/Notifications.js
|
||||
index 15eea09..48b3d23 100644
|
||||
--- a/node_modules/react-native-notifications/lib/dist/Notifications.js
|
||||
+++ b/node_modules/react-native-notifications/lib/dist/Notifications.js
|
||||
@@ -55,6 +55,12 @@ class NotificationsRoot {
|
||||
cancelLocalNotification(notificationId) {
|
||||
return this.commands.cancelLocalNotification(notificationId);
|
||||
}
|
||||
+ /**
|
||||
+ * cancelAllLocalNotifications
|
||||
+ */
|
||||
+ cancelAllLocalNotifications() {
|
||||
+ this.commands.cancelAllLocalNotifications();
|
||||
+ }
|
||||
/**
|
||||
* removeAllDeliveredNotifications
|
||||
*/
|
||||
diff --git a/node_modules/react-native-notifications/lib/dist/interfaces/NotificationCategory.d.ts b/node_modules/react-native-notifications/lib/dist/interfaces/NotificationCategory.d.ts
|
||||
index 0e78cb5..ae90bd1 100644
|
||||
--- a/node_modules/react-native-notifications/lib/dist/interfaces/NotificationCategory.d.ts
|
||||
+++ b/node_modules/react-native-notifications/lib/dist/interfaces/NotificationCategory.d.ts
|
||||
@@ -13,5 +13,5 @@ export declare class NotificationAction {
|
||||
title: string;
|
||||
authenticationRequired: boolean;
|
||||
textInput?: NotificationTextInput;
|
||||
- constructor(identifier: string, activationMode: 'foreground' | 'authenticationRequired' | 'destructive', title: string, authenticationRequired: boolean, textInput?: NotificationTextInput);
|
||||
+ constructor(identifier: string, activationMode: 'background' | 'foreground' | 'authenticationRequired' | 'destructive', title: string, authenticationRequired: boolean, textInput?: NotificationTextInput);
|
||||
}
|
||||
diff --git a/node_modules/react-native-notifications/lib/ios/RNNotificationCenter.m b/node_modules/react-native-notifications/lib/ios/RNNotificationCenter.m
|
||||
index 1fbd2a5..ab44587 100644
|
||||
--- a/node_modules/react-native-notifications/lib/ios/RNNotificationCenter.m
|
||||
+++ b/node_modules/react-native-notifications/lib/ios/RNNotificationCenter.m
|
||||
@@ -58,7 +58,7 @@ - (void)getDeliveredNotifications:(RCTResponseSenderBlock)callback {
|
||||
for (UNNotification *notification in notifications) {
|
||||
[formattedNotifications addObject:[RCTConvert UNNotificationPayload:notification]];
|
||||
}
|
||||
- callback(@[formattedNotifications]);
|
||||
+ callback(formattedNotifications);
|
||||
}];
|
||||
}
|
||||
|
||||
diff --git a/node_modules/react-native-notifications/lib/src/Notifications.ts b/node_modules/react-native-notifications/lib/src/Notifications.ts
|
||||
index 44956df..551fac2 100644
|
||||
--- a/node_modules/react-native-notifications/lib/src/Notifications.ts
|
||||
+++ b/node_modules/react-native-notifications/lib/src/Notifications.ts
|
||||
@@ -54,7 +54,7 @@ export class NotificationsRoot {
|
||||
/**
|
||||
* postLocalNotification
|
||||
*/
|
||||
- public postLocalNotification(notification: Notification, id: number) {
|
||||
+ public postLocalNotification(notification: Notification, id?: number) {
|
||||
return this.commands.postLocalNotification(notification, id);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,13 @@ export class NotificationsRoot {
|
||||
return this.commands.cancelLocalNotification(notificationId);
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * cancelAllLocalNotifications
|
||||
+ */
|
||||
+ public cancelAllLocalNotifications() {
|
||||
+ this.commands.cancelAllLocalNotifications();
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* removeAllDeliveredNotifications
|
||||
*/
|
||||
diff --git a/node_modules/react-native-notifications/lib/src/NotificationsIOS.ts b/node_modules/react-native-notifications/lib/src/NotificationsIOS.ts
|
||||
index b4218ab..38388c5 100644
|
||||
--- a/node_modules/react-native-notifications/lib/src/NotificationsIOS.ts
|
||||
+++ b/node_modules/react-native-notifications/lib/src/NotificationsIOS.ts
|
||||
@@ -52,13 +52,6 @@ export class NotificationsIOS {
|
||||
return this.commands.setBadgeCount(count);
|
||||
}
|
||||
|
||||
- /**
|
||||
- * cancelAllLocalNotifications
|
||||
- */
|
||||
- public cancelAllLocalNotifications() {
|
||||
- this.commands.cancelAllLocalNotifications();
|
||||
- }
|
||||
-
|
||||
/**
|
||||
* checkPermissions
|
||||
*/
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function execute() {
|
||||
cd fastlane && NODE_ENV=production bundle exec fastlane $1 $2
|
||||
|
|
@ -60,7 +60,7 @@ function setup() {
|
|||
|
||||
echo "Installing Fastane"
|
||||
if !gem list bundler -i --version 2.1.4 > /dev/null 2>&1; then
|
||||
gem install bundler --versio 2.1.4
|
||||
gem install bundler --version 2.1.4
|
||||
fi
|
||||
cd fastlane && bundle install && cd .. || exit 1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo Cleaning started
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
if !gem list bundler -i --version 2.1.4 > /dev/null 2>&1; then
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
jsfiles=$(git diff --cached --name-only --diff-filter=ACM | grep -E '.js$|.ts$|.tsx$')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
mkdir -p tmp
|
||||
cp assets/base/i18n/en.json tmp/en.json
|
||||
|
|
|
|||
|
|
@ -228,6 +228,37 @@ jest.mock('react-native-navigation', () => {
|
|||
};
|
||||
});
|
||||
|
||||
jest.mock('react-native-notifications', () => {
|
||||
let deliveredNotifications = [];
|
||||
|
||||
return {
|
||||
Notifications: {
|
||||
registerRemoteNotifications: jest.fn(),
|
||||
addEventListener: jest.fn(),
|
||||
setDeliveredNotifications: jest.fn((notifications) => {
|
||||
deliveredNotifications = notifications;
|
||||
}),
|
||||
cancelAllLocalNotifications: jest.fn(),
|
||||
NotificationAction: jest.fn(),
|
||||
NotificationCategory: jest.fn(),
|
||||
events: () => ({
|
||||
registerNotificationOpened: jest.fn(),
|
||||
registerRemoteNotificationsRegistered: jest.fn(),
|
||||
registerNotificationReceivedBackground: jest.fn(),
|
||||
registerNotificationReceivedForeground: jest.fn(),
|
||||
}),
|
||||
ios: {
|
||||
getDeliveredNotifications: jest.fn().mockImplementation(() => Promise.resolve(deliveredNotifications)),
|
||||
removeDeliveredNotifications: jest.fn((ids) => {
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
deliveredNotifications = deliveredNotifications.filter((n) => !ids.includes(n.identifier));
|
||||
}),
|
||||
setBadgeCount: jest.fn(),
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('react-native-share', () => ({
|
||||
default: jest.fn(),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -48,7 +48,10 @@
|
|||
"@telemetry/*": ["/app/telemetry/*"],
|
||||
"@utils/*": ["app/utils/*"],
|
||||
"@websocket": ["app/client/websocket"],
|
||||
"*": ["./*", "node_modules/*"]
|
||||
"*": ["./*", "node_modules/*"],
|
||||
"react-native-redash/lib/module/v1": [
|
||||
"./node_modules/react-native-redash/lib/typescript/v1/index.d.ts"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": ["app/**/*", "share_extensionn/**/*", "test/**/*", "detox/**/*", "types/**/*"],
|
||||
|
|
|
|||
Loading…
Reference in a new issue