Skip to content

Commit

Permalink
Implementation of ios push notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
kunall17 committed Jul 2, 2017
1 parent 8460f04 commit f89eec8
Show file tree
Hide file tree
Showing 20 changed files with 202 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
"jsonp", "otp", "Otp", "ascii", "Ascii", "substr", "Util", "actionsheet", "unmute",
"otp", "Otp", "ascii", "Ascii", "substr", "Util", "actionsheet", "jsonp", "actionsheet", "ionicons",
"denmark", "copenhagen", "unregister", "gcm", "unstarMessage", "Unstar", "wildcard_mentioned",
"lightbox", "resize", "remobile", "multiline", "uniqby", "zoe", "localizable",
"lightbox", "resize", "remobile", "multiline", "uniqby", "zoe", "localizable", "appid", "apns"
],
"skipIfMatch": [
"http://[^s]*",
Expand Down
57 changes: 53 additions & 4 deletions ios/ZulipMobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
17449DB932594E96A837970F /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 51E1EDA028654E17A35C5BCA /* MaterialIcons.ttf */; };
3556F3DAC2424EBE9ABF0A31 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2E41C86FA25744F998C2BB02 /* Zocial.ttf */; };
3C4249EB1EF6E09F00D245F1 /* libRNNotifications.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4249E61EF6E05C00D245F1 /* libRNNotifications.a */; };
48D1FC73615948D79D3BD31E /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A7F287C57D8A4354A8B6A3E7 /* Octicons.ttf */; };
49692FC0562C40F3946EC6D4 /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A752523B8D8E49E792F653E1 /* Foundation.ttf */; };
4B12DC82ECA043809695F227 /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9DB2E7AE39A448A98E7A4E4A /* Ionicons.ttf */; };
Expand Down Expand Up @@ -118,6 +119,13 @@
remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
remoteInfo = React;
};
3C4249E51EF6E05C00D245F1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 3C4249C61EF6E05C00D245F1 /* RNNotifications.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNNotifications;
};
78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
Expand Down Expand Up @@ -319,6 +327,8 @@
2CFB39BBD9094475BB03A3E4 /* libRCTToast.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTToast.a; sourceTree = "<group>"; };
2E41C86FA25744F998C2BB02 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; };
3074EDA2D113487A925E187C /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = "<group>"; };
3C4249C61EF6E05C00D245F1 /* RNNotifications.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNNotifications.xcodeproj; path = "../node_modules/react-native-notifications/RNNotifications/RNNotifications.xcodeproj"; sourceTree = "<group>"; };
3C4249EC1EF6E16500D245F1 /* ZulipMobile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = ZulipMobile.entitlements; path = ZulipMobile/ZulipMobile.entitlements; sourceTree = "<group>"; };
51E1EDA028654E17A35C5BCA /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = "<group>"; };
6922647B10C64653A76BF3E5 /* RCTToast.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTToast.xcodeproj; path = "../node_modules/@remobile/react-native-toast/ios/RCTToast.xcodeproj"; sourceTree = "<group>"; };
6DA76D9085EA458BB979ED8D /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -382,6 +392,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3C4249EB1EF6E09F00D245F1 /* libRNNotifications.a in Frameworks */,
CFCFE5491F00158500C295CF /* libRCTCameraRoll.a in Frameworks */,
A14EA8771EACE522009D9E83 /* libRCTAnimation.a in Frameworks */,
146834051AC3E58100842450 /* libReact.a in Frameworks */,
Expand Down Expand Up @@ -488,6 +499,7 @@
13B07FAE1A68108700A75B9A /* ZulipMobile */ = {
isa = PBXGroup;
children = (
3C4249EC1EF6E16500D245F1 /* ZulipMobile.entitlements */,
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
Expand Down Expand Up @@ -535,6 +547,14 @@
name = Frameworks;
sourceTree = "<group>";
};
3C4249C71EF6E05C00D245F1 /* Products */ = {
isa = PBXGroup;
children = (
3C4249E61EF6E05C00D245F1 /* libRNNotifications.a */,
);
name = Products;
sourceTree = "<group>";
};
58A37319FEF489FE2CFCFA3F /* Pods */ = {
isa = PBXGroup;
children = (
Expand All @@ -558,6 +578,7 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
3C4249C61EF6E05C00D245F1 /* RNNotifications.xcodeproj */,
A14EA8541EACE4CE009D9E83 /* RCTAnimation.xcodeproj */,
A155BFE71DD8E54100A8B695 /* RCTCameraRoll.xcodeproj */,
146833FF1AC3E56700842450 /* React.xcodeproj */,
Expand Down Expand Up @@ -766,7 +787,16 @@
TestTargetID = 13B07F861A680F5B00A75B9A;
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = 66KHCWMEYB;
DevelopmentTeam = 6GJ3LH2XZ2;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.BackgroundModes = {
enabled = 0;
};
com.apple.Push = {
enabled = 1;
};
};
};
};
};
Expand Down Expand Up @@ -842,6 +872,10 @@
ProductGroup = CFCFE50D1F0011FA00C295CF /* Products */;
ProjectRef = FC7EC6A752C243FB9F1B8442 /* RNFetchBlob.xcodeproj */;
},
{
ProductGroup = 3C4249C71EF6E05C00D245F1 /* Products */;
ProjectRef = 3C4249C61EF6E05C00D245F1 /* RNNotifications.xcodeproj */;
},
{
ProductGroup = A148FEDC1E9D8C9600479280 /* Products */;
ProjectRef = AF03F5DAC0924A13BDD49574 /* RNSound.xcodeproj */;
Expand Down Expand Up @@ -924,6 +958,13 @@
remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
3C4249E61EF6E05C00D245F1 /* libRNNotifications.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNNotifications.a;
remoteRef = 3C4249E51EF6E05C00D245F1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
Expand Down Expand Up @@ -1390,7 +1431,10 @@
baseConfigurationReference = 2BBAAB1FE905B6D60DE187DD /* Pods-ZulipMobile.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = ZulipMobile/ZulipMobile.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = 6GJ3LH2XZ2;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
HEADER_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -1403,6 +1447,7 @@
"$(SRCROOT)/../node_modules/react-native-safari-view",
"$(SRCROOT)/../node_modules/@remobile/react-native-toast/ios/RCTToast",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-notifications/**",
);
INFOPLIST_FILE = ZulipMobile/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
Expand All @@ -1412,8 +1457,9 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = org.zulip.Zulip;
PRODUCT_BUNDLE_IDENTIFIER = com.zulip.Zulip;
PRODUCT_NAME = ZulipMobile;
PROVISIONING_PROFILE_SPECIFIER = "";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
Expand All @@ -1423,7 +1469,8 @@
baseConfigurationReference = 8FC8D6AFD281F51DCA6E1C99 /* Pods-ZulipMobile.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = D47VARCYH7;
CODE_SIGN_ENTITLEMENTS = ZulipMobile/ZulipMobile.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
HEADER_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -1436,6 +1483,7 @@
"$(SRCROOT)/../node_modules/react-native-safari-view",
"$(SRCROOT)/../node_modules/@remobile/react-native-toast/ios/RCTToast",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-notifications/**",
);
INFOPLIST_FILE = ZulipMobile/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
Expand All @@ -1445,8 +1493,9 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = org.zulip.Zulip;
PRODUCT_BUNDLE_IDENTIFIER = com.zulip.Zulip;
PRODUCT_NAME = ZulipMobile;
PROVISIONING_PROFILE_SPECIFIER = "";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
Expand Down
25 changes: 25 additions & 0 deletions ios/ZulipMobile/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#import <Crashlytics/Crashlytics.h>
#import <asl.h>
#import "RCTLog.h"
#import "RNNotifications.h"

@implementation AppDelegate

Expand Down Expand Up @@ -99,5 +100,29 @@ - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserAct
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[RNNotifications didRegisterUserNotificationSettings:notificationSettings];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RNNotifications didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
[RNNotifications didFailToRegisterForRemoteNotificationsWithError:error];
}

// Required for the notification event.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification {
[RNNotifications didReceiveRemoteNotification:notification];
}

// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNNotifications didReceiveLocalNotification:notification];
}
@end
8 changes: 8 additions & 0 deletions ios/ZulipMobile/ZulipMobile.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
20 changes: 10 additions & 10 deletions src/account-info/LogoutButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { InitRouteAction, Auth } from '../types';
import boundActions from '../boundActions';
import { getInitialRoutes } from '../nav/routingSelectors';
import { ZulipButton } from '../common';
import unregisterGCM from '../api/unregisterGCM';
import unregisterPush from '../api/unregisterPush';
import { getAuth } from '../account/accountSelectors';

const styles = StyleSheet.create({
Expand All @@ -23,22 +23,22 @@ class LogoutButton extends Component {
accounts: any[],
initRoutes: InitRouteAction,
logout: (accounts: any[]) => void,
deleteTokenGCM: () => void,
deleteTokenPush: () => void,
auth: Auth,
gcmToken: string,
pushToken: string,
};

shutdownGCM = async () => {
const { auth, deleteTokenGCM, gcmToken } = this.props;
if (gcmToken !== '') {
await unregisterGCM(auth, gcmToken);
deleteTokenGCM();
shutdownPUSH = async () => {
const { auth, deleteTokenPush, pushToken } = this.props;
if (pushToken !== '') {
await unregisterPush(auth, pushToken);
deleteTokenPush();
}
}

logout = () => {
const { accounts } = this.props;
this.shutdownGCM();
this.shutdownPUSH();
this.props.logout(accounts);
const accountsLoggedOut = accounts.slice();
accountsLoggedOut[0].apiKey = '';
Expand All @@ -61,7 +61,7 @@ export default connect(
(state) => ({
auth: getAuth(state),
accounts: state.accounts,
gcmToken: state.realm.gcmToken
pushToken: state.realm.pushToken
}),
boundActions,
)(LogoutButton);
16 changes: 8 additions & 8 deletions src/account-info/SwitchAccountButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { connect } from 'react-redux';
import boundActions from '../boundActions';
import { ZulipButton } from '../common';
import { getAuth } from '../account/accountSelectors';
import unregisterGCM from '../api/unregisterGCM';
import unregisterPush from '../api/unregisterPush';

const styles = StyleSheet.create({
button: {
Expand All @@ -21,16 +21,16 @@ class SwitchAccountButton extends Component {
drawer: () => null,
};

shutdownGCM = async () => {
const { auth, deleteTokenGCM, gcmToken } = this.props;
if (gcmToken !== '') {
await unregisterGCM(auth, gcmToken);
deleteTokenGCM();
shutdownPUSH = async () => {
const { auth, deleteTokenPush, pushToken } = this.props;
if (pushToken !== '') {
await unregisterPush(auth, pushToken);
deleteTokenPush();
}
}

switchAccount = () => {
this.shutdownGCM();
this.shutdownPUSH();
this.context.drawer.close();
this.props.pushRoute('account');
}
Expand All @@ -51,7 +51,7 @@ export default connect(
(state) => ({
auth: getAuth(state),
accounts: state.accounts,
gcmToken: state.realm.gcmToken
pushToken: state.realm.pushToken
}),
boundActions,
)(SwitchAccountButton);
4 changes: 2 additions & 2 deletions src/actionConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ export const GET_USER_RESPONSE = 'GET_USER_RESPONSE';
export const MARK_MESSAGES_READ = 'MARK_MESSAGES_READ';
export const SETTINGS_CHANGE = 'SETTINGS_CHANGE';

export const SAVE_TOKEN_GCM = 'SAVE_TOKEN_GCM';
export const DELETE_TOKEN_GCM = 'DELETE_TOKEN_GCM';
export const SAVE_TOKEN_PUSH = 'SAVE_TOKEN_PUSH';
export const DELETE_TOKEN_PUSH = 'DELETE_TOKEN_PUSH';

export const EVENT_REALM_EMOJI_UPDATE = 'EVENT_REALM_EMOJI_UPDATE';

Expand Down
2 changes: 1 addition & 1 deletion src/api/registerGCM.js → src/api/registerPush.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { apiPost } from './apiFetch';
export default async (auth: Auth, token: string) =>
apiPost(
auth,
'users/me/android_gcm_reg_id',
'users/me/android_push_reg_id',
res => res.api_key,
{
token,
Expand Down
15 changes: 15 additions & 0 deletions src/api/registerPush.ios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* @flow */
import { Auth } from '../types';
import { apiPost } from './apiFetch';

export default async (auth: Auth, token: string) => {
apiPost(
auth,
'users/me/apns_device_token',
res => res,
{
token,
appid: 'com.zulip.Zulip'
},
);
};
11 changes: 11 additions & 0 deletions src/api/unregisterPush.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* @flow */
import { Auth } from '../types';
import { apiDelete } from './apiFetch';

export default (auth: Auth, token: string) =>
apiDelete(
auth,
'users/me/android_push_reg_id',
res => res.api_key,
{ token },
);
2 changes: 1 addition & 1 deletion src/api/unregisterGCM.js → src/api/unregisterPush.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { apiDelete } from './apiFetch';
export default (auth: Auth, token: string) =>
apiDelete(
auth,
'users/me/android_gcm_reg_id',
'users/me/apns_device_token',
res => res.api_key,
{ token },
);
2 changes: 1 addition & 1 deletion src/app/appReducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const initialState: AppState = {
isOnline: true,
isActive: true,
needsInitialFetch: false,
gcmToken: '',
pushToken: '',
eventQueueId: null,
};

Expand Down
4 changes: 2 additions & 2 deletions src/main/MainScreenContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { initializeNotifications } from '../utils/notifications';

class MainScreenContainer extends React.Component {
componentWillMount() {
const { auth, saveTokenGCM, switchNarrow } = this.props;
initializeNotifications(auth, saveTokenGCM, switchNarrow);
const { auth, saveTokenPush, switchNarrow } = this.props;
initializeNotifications(auth, saveTokenPush, switchNarrow);
}

componentWillReceiveProps(nextProps) {
Expand Down
Loading

0 comments on commit f89eec8

Please sign in to comment.