Skip to content

Commit

Permalink
Merge pull request #23 from kanzitelli/notifications
Browse files Browse the repository at this point in the history
Notifications
  • Loading branch information
kanzitelli authored Dec 19, 2020
2 parents da2e38a + 77fdfa2 commit 09ef15f
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ build/
local.properties
*.iml
*.hprof
google-services.json

# Own
#
Expand Down
5 changes: 5 additions & 0 deletions NOTIFICATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## 🎛 Notifications

<i>Detailed guide will be published soon...</i>

Meanwhile, you can check this [tutorial](https://dev.to/jakubkoci/react-native-push-notifications-313i) which helped me to set up and test notifications.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ yarn ios
yarn android
```

👁‍🗨 If you are planning to use Expo modules, such as preconfigured `expo-updates` and others, or add new ones, what I strongly recommend, then proceed to [Expo Configuration](/EXPO_CONFIGURATION.md) and follow the steps carefully.
👁‍🗨 If you are planning to use Expo modules, such as preconfigured `expo-updates` and others, or add new ones, what I strongly recommend, then proceed to [Expo Configuration](/EXPO_CONFIGURATION.md) and follow the steps.

🟢 If you would like to rename the app, you can use [react-native-rename-next](https://github.com/mayconmesquita/react-native-rename-next). Don't forget to run `yarn ios:pods` after the process is finished. Also keep in mind that bundle identifier must be valid for both platforms or change it manually.

Expand All @@ -52,28 +52,31 @@ yarn android
- [Reanimated 2](https://github.com/software-mansion/react-native-reanimated) - React Native's Animated library reimplemented
- [MobX](https://github.com/mobxjs/mobx) - simple, scalable state management, with [mobx-persist](https://github.com/pinqy520/mobx-persist) for persisting your stores
### Extra helpful libraries
- [React Native Navigation Hooks](https://github.com/underscopeio/react-native-navigation-hooks) - a set of React hooks for React Native Navigation
- [React Native Notifications](https://github.com/wix/react-native-notifications) - a library that takes care of handling notifications
- [React Native Navigation Hooks](https://github.com/underscopeio/react-native-navigation-hooks) - a set of hooks for React Native Navigation
- [React Native Vector Icons](https://github.com/oblador/react-native-vector-icons) - customizable icons for React Native. Even though Expo SDK includes `expo-icons` which you can still use, but the reason of adding `react-native-vector-icons` is to get icons as sources before launching tab based app
- [React Native Gesture Handler](https://github.com/kmagiera/react-native-gesture-handler) - native touches and gesture system for React Native
- [React Native Defice Info](https://github.com/react-native-community/react-native-device-info) - device information for React Native iOS and Android
- [Hermes Engine](https://reactnative.dev/docs/hermes) - a JavaScript engine optimized for running React Native apps on Android.
- [Typescript](https://www.typescriptlang.org/) - strict syntactical superset of JavaScript
### Small useful libraries/hooks from me
### Small useful services/hooks from me
- `useStyles()` - a hook that takes care of dark mode in your app. Supports toggling modes while you are in app. No dependencies (needs only `react-native`, so could be reusable).
- `appUpdates` - a service that shows and simplifies integration with `expo-updates`. In order to use it, you will need to change `Expo.plist` and `AndroidManifest.xml` with your actual information. More information about [expo-updates](https://docs.expo.io/versions/latest/sdk/updates/).
- `translate` - a service that shows and simplifies integration with `expo-localization` and `i18n-js`. You can see an example of `en`, `ru` and `de` localizations in `ExpoScreen`.
- `notifications` - a service that takes care of setting up notifications which utilizes [React Native Notifications](https://github.com/wix/react-native-notifications). For more information, please, take a look at this [guide](/NOTIFICATIONS.md).

## Enhancements
There are still some things I would like to add to the starter:
- 🔳 Dark Mode support.
- 🔳 Localization via [expo-localization](https://docs.expo.io/versions/latest/sdk/localization) and [i18n-js](https://github.com/fnando/i18n-js).
- ⬜️ Notifications (remote).
- 🔳 Notifications (remote) using [React Native Notifications](https://github.com/wix/react-native-notifications).

Feel free to open an issue for suggestions.

## Known issues (warnings)
- Expo splash screen. There is some weird behavior using `expo-splash-screen` with `react-native-navigation`. That is why this module has been excluded: [ios](https://github.com/kanzitelli/expo-rnn-starter/blob/master/ios/Podfile#L8) & [android](https://github.com/kanzitelli/expo-rnn-starter/blob/master/android/app/build.gradle#L196).
- Dark Mode in Android. React Native Navigation doesn't toggle navigation and tab bars' background color to dark when dark mode is toggled on. However it does so on iOS. As a workaround, we can subscribe to toggle events and then using `Navigation.mergeOptions` & `Navigation.setDefaultOptions` to change stylings for navigations and tab bars. Anyways, it needs some time to dive into it and come up with better solution. Current progress could be found [here](https://github.com/kanzitelli/expo-rnn-starter/tree/android-dark-mode).
- Notifications received in background for iOS and Android. There is an issue with getting a callback triggered for notifications received while the app in background. For more information, please, check this [issue](https://github.com/wix/react-native-notifications/issues/670).

Feel free to open an issue for any other warning or problems.

Expand Down
6 changes: 5 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ dependencies {
} else {
implementation jscFlavor
}

implementation project(':react-native-notifications')
implementation 'com.google.firebase:firebase-core:16.0.0'
}

// Run this once to be able to run the application with BUCK
Expand All @@ -226,4 +229,5 @@ task copyDownloadableDepsToLibs(type: Copy) {
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
apply plugin: 'com.google.gms.google-services'
11 changes: 11 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@

<meta-data android:name="expo.modules.updates.EXPO_RELEASE_CHANNEL" android:value="dev" />

<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/notification_icon" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />

<activity
android:name=".MainActivity"
android:label="@string/app_name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Arrays;

import com.wix.reactnativenotifications.RNNotificationsPackage;

import org.unimodules.adapters.react.ModuleRegistryAdapter;
import org.unimodules.adapters.react.ReactModuleRegistryProvider;
Expand Down
15 changes: 15 additions & 0 deletions android/app/src/main/res/drawable-anydpi-v24/notification_icon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF">
<group android:scaleX="0.92"
android:scaleY="0.92"
android:translateX="0.96"
android:translateY="0.96">
<path
android:fillColor="@android:color/white"
android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM6,7h5v1.5L6,8.5L6,7zM19,19L5,19L19,5v14zM14.5,16v2L16,18v-2h2v-1.5h-2v-2h-1.5v2h-2L12.5,16z"/>
</group>
</vector>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions android/app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorAccent">#4D7198</color>
</resources>
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ buildscript {
classpath('com.android.tools.build:gradle:4.0.0')
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.google.gms:google-services:4.3.4'
}
}

Expand Down
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ PODS:
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsinspector (0.63.4)
- react-native-notifications (3.4.1):
- React-Core
- React-RCTActionSheet (0.63.4):
- React-Core/RCTActionSheetHeaders (= 0.63.4)
- React-RCTAnimation (0.63.4):
Expand Down Expand Up @@ -383,6 +385,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-notifications (from `../node_modules/react-native-notifications`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
- React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
Expand Down Expand Up @@ -479,6 +482,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-notifications:
:path: "../node_modules/react-native-notifications"
React-RCTActionSheet:
:path: "../node_modules/react-native/Libraries/ActionSheetIOS"
React-RCTAnimation:
Expand Down Expand Up @@ -572,6 +577,7 @@ SPEC CHECKSUMS:
React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31
React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
react-native-notifications: 77c7c863273e79caaa2523f239e714b033995262
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0
Expand Down
4 changes: 2 additions & 2 deletions ios/rnn_starter.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_BUNDLE_IDENTIFIER = "io.batyr.expo-rnn-starter";
PRODUCT_NAME = rnn_starter;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
Expand All @@ -771,7 +771,7 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_BUNDLE_IDENTIFIER = "io.batyr.expo-rnn-starter";
PRODUCT_NAME = rnn_starter;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down
14 changes: 14 additions & 0 deletions ios/rnn_starter/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#import <UMReactNativeAdapter/UMNativeModulesProxy.h>
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.h>

#import "RNNotifications.h"

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
Expand Down Expand Up @@ -42,6 +44,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
InitializeFlipper(application);
#endif

[RNNotifications startMonitorNotifications];

self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]];

self.launchOptions = launchOptions;
Expand Down Expand Up @@ -89,4 +93,14 @@ - (void)appController:(EXUpdatesAppController *)appController didStartWithSucces
appController.bridge = [self initializeReactNativeApp];
}

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

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

@end
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"react-native-gesture-handler": "^1.9.0",
"react-native-navigation": "^7.6.0",
"react-native-navigation-hooks": "^6.2.0",
"react-native-notifications": "^3.4.1",
"react-native-reanimated": "2.0.0-rc.0",
"react-native-unimodules": "^0.12.0",
"react-native-vector-icons": "^7.1.0"
Expand Down
2 changes: 2 additions & 0 deletions src/services/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import React from 'react';
import NavigationService from './navigation';
import AppUpdatesService from './appUpdates';
import TranslateService from './translate';
import NotificationsService from './notifications';

export const services = {
navigation: NavigationService,
appUpdates: AppUpdatesService,
t: TranslateService,
notifications: NotificationsService,
};

const servicesContext = React.createContext(services);
Expand Down
55 changes: 55 additions & 0 deletions src/services/notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { NotificationBackgroundFetchResult, Notifications as RNNotifications } from 'react-native-notifications';

class NotificationsService implements IService {
init = async () => {
// this.registerReactNativeNotifications();
}

private registerReactNativeNotifications() {
this.registerDevice()
this.registerNotificationEvents()
}

private registerDevice() {
RNNotifications.events().registerRemoteNotificationsRegistered(event => {
// TODO: Send the token to my server so it could send back push notifications...
console.log('[RNNotification] Device Token Received', event.deviceToken)
})
RNNotifications.events().registerRemoteNotificationsRegistrationFailed(event => {
console.error(event)
})

RNNotifications.registerRemoteNotifications()
}

private registerNotificationEvents() {
RNNotifications.events().registerNotificationReceivedForeground((notification, completion) => {
console.log('[RNNotification] Notification Received - Foreground', notification)

// Calling completion on iOS with `alert: true` will present the native iOS inApp notification.
completion({ alert: false, sound: false, badge: false })
})

RNNotifications.events().registerNotificationOpened((notification, completion) => {
console.log('[RNNotification] Notification opened by device user', notification)
console.log(`[RNNotification] Notification opened with an action identifier: ${notification.identifier}`)
completion()
})

// doesn't work for some reason
RNNotifications.events().registerNotificationReceivedBackground((notification, completion) => {
console.log('[RNNotification] Notification Received - Background', notification)

// Calling completion on iOS with `alert: true` will present the native iOS inApp notification.
completion(NotificationBackgroundFetchResult.NEW_DATA);
})

RNNotifications.getInitialNotification()
.then(notification => {
console.log('[RNNotification] Initial notification was:', notification || 'N/A')
})
.catch(err => console.error('[RNNotification] getInitialNotifiation() failed', err))
}
}

export default new NotificationsService();
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7966,6 +7966,11 @@ react-native-navigation@^7.6.0:
react-lifecycles-compat "2.0.0"
tslib "1.9.3"

react-native-notifications@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/react-native-notifications/-/react-native-notifications-3.4.1.tgz#3046bae51863e1073d71820598f0b85a3b389535"
integrity sha512-jJHo5z5XR0smZIVj4yjoqDWZ3HX26TL8FMsUIBiIy1Hh9b0q/HAl1xN651sTW/HM49+Mr2F+ShSf6nXBnGB4fQ==

[email protected]:
version "2.0.0-rc.0"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.0.0-rc.0.tgz#7a1b0bfd48e3de9dfa985a524463b6a216531358"
Expand Down

0 comments on commit 09ef15f

Please sign in to comment.