[v6] Implement App Indexing

This commit is contained in:
ehesp
2019-06-05 14:54:37 +01:00
parent d67cbe1d10
commit 494646e770
18 changed files with 604 additions and 8 deletions

View File

@@ -0,0 +1,65 @@
# Built application files
android/*/build/
# Crashlytics configuations
android/com_crashlytics_export_strings.xml
# Local configuration file (sdk path, etc)
android/local.properties
# Gradle generated files
android/.gradle/
# Signing files
android/.signing/
# User-specific configurations
android/.idea/gradle.xml
android/.idea/libraries/
android/.idea/workspace.xml
android/.idea/tasks.xml
android/.idea/.name
android/.idea/compiler.xml
android/.idea/copyright/profiles_settings.xml
android/.idea/encodings.xml
android/.idea/misc.xml
android/.idea/modules.xml
android/.idea/scopes/scope_settings.xml
android/.idea/vcs.xml
android/*.iml
# Xcode
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
*.xcuserstate
ios/Pods
ios/build
*project.xcworkspace*
*xcuserdata*
# OS-specific files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.dbandroid/gradle
android/gradlew
android/build
android/gradlew.bat
android/gradle/
.idea
coverage
yarn.lock
e2e/
.github
.vscode
.nyc_output
android/.settings
*.coverage.json
.circleci
.eslintignore

32
packages/indexing/LICENSE Normal file
View File

@@ -0,0 +1,32 @@
Apache-2.0 License
------------------
Copyright (c) 2016-present Invertase Limited <oss@invertase.io> & Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this library except in compliance with the License.
You may obtain a copy of the Apache-2.0 License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Creative Commons Attribution 3.0 License
----------------------------------------
Copyright (c) 2016-present Invertase Limited <oss@invertase.io> & Contributors
Documentation and other instructional materials provided for this project
(including on a separate documentation repository or it's documentation website) are
licensed under the Creative Commons Attribution 3.0 License. Code samples/blocks
contained therein are licensed under the Apache License, Version 2.0 (the "License"), as above.
You may obtain a copy of the Creative Commons Attribution 3.0 License at
https://creativecommons.org/licenses/by/3.0/

View File

@@ -0,0 +1,52 @@
<p align="center">
<a href="https://invertase.io/oss/react-native-firebase">
<img width="160px" src="https://i.imgur.com/JIyBtKW.png"><br/>
</a>
<h4 align="center">React Native Firebase - Indexing</h2>
</p>
<p align="center">
<a href="https://api.rnfirebase.io/coverage/indexing/detail"><img src="https://api.rnfirebase.io/coverage/indexing/badge?style=flat-square" alt="Coverage"></a>
<a href="https://www.npmjs.com/package/@react-native-firebase/indexing"><img src="https://img.shields.io/npm/dm/@react-native-firebase/indexing.svg?style=flat-square" alt="NPM downloads"></a>
<a href="https://www.npmjs.com/package/@react-native-firebase/indexing"><img src="https://img.shields.io/npm/v/@react-native-firebase/indexing.svg?style=flat-square" alt="NPM version"></a>
<a href="/LICENSE"><img src="https://img.shields.io/npm/l/react-native-firebase.svg?style=flat-square" alt="License"></a>
<a href="#backers"><img src="https://opencollective.com/react-native-firebase/backers/badge.svg?style=flat-square" alt="Backers on Open Collective"></a>
<a href="#sponsors"><img src="https://opencollective.com/react-native-firebase/sponsors/badge.svg?style=flat-square" alt="Sponsors on Open Collective"></a>
<a href="https://discord.gg/C9aK28N"><img src="https://img.shields.io/discord/295953187817521152.svg?logo=discord&style=flat-square&colorA=7289da&label=discord" alt="Chat"></a>
<a href="https://twitter.com/rnfirebase"><img src="https://img.shields.io/twitter/follow/rnfirebase.svg?style=social&label=Follow" alt="Follow on Twitter"></a>
</p>
----
> This is for the upcoming v6.0.0 release of React Native Firebase, please use the [react-native-firebase](https://www.npmjs.com/package/react-native-firebase) package instead, unless you're early adopting/testing the new packages - in which case please use the latest alpha/beta/next tag release on npm and not the `latest` tagged release for this package.
Indexing description.
[> Learn More](https://firebase.google.com/products/indexing/)
## Installation
Requires `@react-native-firebase/app` to be installed.
```bash
yarn add @react-native-firebase/indexing
react-native link @react-native-firebase/indexing
```
## Documentation
- [Guides](#TODO)
- [Installation](#TODO)
- [Reference](#TODO)
## License
- See [LICENSE](/LICENSE)
----
Built and maintained with 💛 by [Invertase](https://invertase.io).
- [💼 Hire Us](https://invertase.io/hire-us)
- [☕️ Sponsor Us](https://opencollective.com/react-native-firebase)
- [👩‍💻 Work With Us](https://invertase.io/jobs)

View File

@@ -0,0 +1,22 @@
require 'json'
package = JSON.parse(File.read('../package.json'))
Pod::Spec.new do |s|
s.name = "RNFBIndexing"
s.version = package["version"]
s.description = package["description"]
s.summary = <<-DESC
A well tested feature rich Firebase implementation for React Native, supporting iOS & Android.
DESC
s.homepage = "http://invertase.io/oss/react-native-firebase"
s.license = package['license']
s.authors = "Invertase Limited"
s.source = { :git => "https://github.com/invertase/react-native-firebase.git", :tag => "v#{s.version}" }
s.social_media_url = 'http://twitter.com/invertaseio'
s.platform = :ios, "10.0"
s.source_files = 'ios/**/*.{h,m}'
s.dependency 'React'
s.dependency 'Firebase/Core', '~> 5.20.2'
s.dependency 'RNFBApp'
s.static_framework = true
end

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
describe('indexing()', () => {
describe('namespace', () => {
it('accessible from firebase.app()', () => {
const app = firebase.app();
should.exist(app.indexing);
app.indexing().app.should.equal(app);
});
});
describe('getInitialURL()', () => {
it('should return null with no deeplink', async () => {
const url = await firebase.indexing().getInitialURL();
should.equal(url, null);
});
// does not work on ios simulator
android.it('should be a string when app launches from a URL', async () => {
const url = 'invertase://foo.bar';
await device.relaunchApp({
url,
newInstance: true,
});
const opened = await firebase.indexing().getInitialURL();
should.equal(opened, url);
});
});
describe('onOpenURL()', () => {
it('throw when no function is provided', () => {
try {
firebase.indexing().onOpenURL('foo');
return Promise.reject(new Error('Did not throw Error.'));
} catch (error) {
error.message.should.containEql(`'listener' must be a function`);
return Promise.resolve();
}
});
it('returns an unsubscribe function', () => {
const sub = () => {};
const unsubscribe = firebase.indexing().onOpenURL(sub);
unsubscribe.should.be.a.Function();
unsubscribe();
});
it('subscribes to and receives URL events', async () => {
const url = 'invertase://foo.bar';
const callback = sinon.spy();
const unsubscribe = firebase.indexing().onOpenURL(callback);
await device.openURL({
url,
});
await Utils.sleep(200);
callback.should.be.calledOnce();
callback.should.be.calledWith(url);
unsubscribe();
});
});
});

115
packages/indexing/lib/index.d.ts vendored Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import {
ReactNativeFirebaseModule,
ReactNativeFirebaseModuleAndStatics,
ReactNativeFirebaseNamespace,
} from '@react-native-firebase/app-types';
/**
* Firebase Indexing package for React Native.
*
* #### Example 1
*
* Access the firebase export from the `indexing` package:
*
* ```js
* import { firebase } from '@react-native-firebase/indexing';
*
* // firebase.indexing().X
* ```
*
* #### Example 2
*
* Using the default export from the `indexing` package:
*
* ```js
* import indexing from '@react-native-firebase/indexing';
*
* // indexing().X
* ```
*
* #### Example 3
*
* Using the default export from the `app` package:
*
* ```js
* import firebase from '@react-native-firebase/app';
* import '@react-native-firebase/indexing';
*
* // firebase.indexing().X
* ```
*
* @firebase indexing
*/
export namespace Indexing {
export interface Statics {}
/**
*
* The Firebase Indexing service interface.
*
* > This module is available for the default app only.
*
* #### Example
*
* Get the Indexing service for the default app:
*
* ```js
* const defaultAppIndexing = firebase.indexing();
* ```
*/
export interface Module extends ReactNativeFirebaseModule {
/**
* If the application was launched via a deep link URL, the URL is returned, otherwise
* value is `null`.
*/
getInitialURL(): Promise<string | null>;
/**
* Listen to deep link URL events which the application handles. The URL is passed to the
* provided listener function.
*
* Returns an unsubscribe function.
*
* @param listener Function called when a deep link URL is handled for this app.
*/
onOpenURL(listener: Function): Function;
}
}
declare module '@react-native-firebase/indexing' {
import { ReactNativeFirebaseNamespace } from '@react-native-firebase/app-types';
const FirebaseNamespaceExport: {} & ReactNativeFirebaseNamespace;
export const firebase = FirebaseNamespaceExport;
const IndexingDefaultExport: ReactNativeFirebaseModuleAndStatics<
Indexing.Module,
Indexing.Statics
>;
export default IndexingDefaultExport;
}
declare module '@react-native-firebase/app-types' {
interface ReactNativeFirebaseNamespace {
indexing: ReactNativeFirebaseModuleAndStatics<Indexing.Module, Indexing.Statics>;
}
interface FirebaseApp {
indexing(): Indexing.Module;
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { Linking } from 'react-native';
import {
createModuleNamespace,
FirebaseModule,
getFirebaseRoot,
} from '@react-native-firebase/app/lib/internal';
import version from './version';
import { isFunction } from '@react-native-firebase/common';
const statics = {};
const namespace = 'indexing';
const nativeModuleName = 'RNFBIndexingModule';
class FirebaseIndexingModule extends FirebaseModule {
/**
*
*/
getInitialURL() {
return Linking.getInitialURL();
}
/**
*
* @param listener
* @returns {function(): *}
*/
onOpenURL(listener) {
if (!isFunction(listener)) {
throw new Error(`firebase.indexing().onOpenURL(*) 'listener' must be a function.`);
}
Linking.addEventListener('url', ({ url }) => listener(url));
return () => Linking.removeEventListener('url', listener);
}
}
// import { SDK_VERSION } from '@react-native-firebase/indexing';
export const SDK_VERSION = version;
// import indexing from '@react-native-firebase/indexing';
// indexing().X(...);
export default createModuleNamespace({
statics,
version,
namespace,
nativeModuleName,
nativeEvents: false,
hasMultiAppSupport: false,
hasCustomUrlOrRegionSupport: false,
ModuleClass: FirebaseIndexingModule,
});
// import indexing, { firebase } from '@react-native-firebase/indexing';
// indexing().X(...);
// firebase.indexing().X(...);
export const firebase = getFirebaseRoot();

View File

@@ -0,0 +1,84 @@
/* eslint-disable import/no-duplicates */
/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import type { ReactNativeFirebaseModule } from '@react-native-firebase/app-types/index.js.flow';
export interface Statics {}
export interface Module extends ReactNativeFirebaseModule {
/**
* If the application was launched via a deep link URL, the URL is returned, otherwise
* value is `null`.
*/
getInitialURL(): Promise<string | null>;
/**
* Listen to deep link URL events which the application handles. The URL is passed to the
* provided listener function.
*
* Returns an unsubscribe function.
*
* @param listener Function called when a deep link URL is handled for this app.
*/
onOpenURL(listener: Function): Function;
}
declare module '@react-native-firebase/indexing' {
import type {
ReactNativeFirebaseNamespace,
ReactNativeFirebaseModuleAndStatics,
} from '@react-native-firebase/app-types/index.js.flow';
/**
* @example
* ```js
* import { firebase } from '@react-native-firebase/indexing';
* firebase.indexing().X(...);
* ```
*/
declare export var firebase: {} & ReactNativeFirebaseNamespace;
/**
* @example
* ```js
* import indexing from '@react-native-firebase/indexing';
* indexing().X(...);
* ```
*/
declare export default ReactNativeFirebaseModuleAndStatics<Module, Statics>;
}
/**
* Attach namespace to `firebase.` and `FirebaseApp.`.
*/
declare module '@react-native-firebase/app-types' {
import type { ReactNativeFirebaseModuleAndStatics } from '@react-native-firebase/app-types/index.js.flow';
declare interface ReactNativeFirebaseNamespace {
/**
* Indexing
*/
indexing: ReactNativeFirebaseModuleAndStatics<Module, Statics>;
}
declare interface FirebaseApp {
/**
* Indexing
*/
indexing(): Module;
}
}

View File

@@ -0,0 +1,35 @@
{
"name": "@react-native-firebase/indexing",
"version": "6.0.0-alpha.25",
"author": "Invertase <oss@invertase.io> (http://invertase.io)",
"description": "React Native Firebase - Indexing",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"build": "genversion --semi lib/version.js",
"build:clean": "rimraf android/build && rimraf ios/build",
"prepare": "yarn run build"
},
"repository": {
"type": "git",
"url": "https://github.com/invertase/react-native-firebase/tree/master/packages/indexing"
},
"license": "Apache-2.0",
"keywords": [
"react",
"react-native",
"firebase",
"indexing"
],
"peerDependencies": {
"@react-native-firebase/app": "6.0.0-alpha.25"
},
"dependencies": {
"@react-native-firebase/app-types": "6.0.0-alpha.25",
"@react-native-firebase/common": "6.0.0-alpha.25"
},
"gitHead": "2787d4413eb70c61a687c4d6913add6a6a01f582",
"publishConfig": {
"access": "public"
}
}

View File

@@ -113,6 +113,17 @@
android:host="je786.app.goo.gl"
android:scheme="https" />
</intent-filter>
<!-- App Indexing Test -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="foo.bar"
android:scheme="invertase" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>

View File

@@ -33,6 +33,7 @@ import '@react-native-firebase/functions';
import '@react-native-firebase/ml-natural-language';
import '@react-native-firebase/storage';
import '@react-native-firebase/iid';
import '@react-native-firebase/indexing';
import '@react-native-firebase/invites';
import '@react-native-firebase/perf';
import firebase from '@react-native-firebase/app';

View File

@@ -41,6 +41,7 @@ const PACKAGES = [
'auth',
'database',
'storage',
'indexing',
// 'firestore',
// 'links',
// 'messaging',

View File

@@ -15,6 +15,7 @@ target 'testing' do
'RCTNetwork',
'RCTImage',
'RCTWebSocket',
'RCTLinkingIOS',
]
pod "yoga", :path => "#{react_native_path}/ReactCommon/yoga"

View File

@@ -256,6 +256,8 @@ PODS:
- React/RCTImage (0.59.5):
- React/Core
- React/RCTNetwork
- React/RCTLinkingIOS (0.59.5):
- React/Core
- React/RCTNetwork (0.59.5):
- React/Core
- React/RCTText (0.59.5):
@@ -347,6 +349,7 @@ DEPENDENCIES:
- React/CxxBridge (from `../node_modules/react-native`)
- React/DevSupport (from `../node_modules/react-native`)
- React/RCTImage (from `../node_modules/react-native`)
- React/RCTLinkingIOS (from `../node_modules/react-native`)
- React/RCTNetwork (from `../node_modules/react-native`)
- React/RCTText (from `../node_modules/react-native`)
- React/RCTWebSocket (from `../node_modules/react-native`)
@@ -505,6 +508,6 @@ SPEC CHECKSUMS:
RNFBUtils: 878820c66794f122ac1a3ad3adcbf31bd311b2e3
yoga: 2e571f113e8cbeb0eb752aeebc86c1bfe7a8200c
PODFILE CHECKSUM: 59e0d70ffe8e37cf6d821d46b4850b1ee1d9cb7f
PODFILE CHECKSUM: 3335499582aff6f2aa73ab7e31be5286ed8e5eaf
COCOAPODS: 1.7.0

View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@@ -204,6 +204,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);

View File

@@ -21,6 +21,7 @@
#import <React/RCTRootView.h>
#import <Firebase/Firebase.h>
#import <RNFBInvites/RNFBInvitesModule.h>
#import <React/RCTLinkingManager.h>
@import Firebase;
@@ -49,16 +50,24 @@
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString *, id> *)options {
return [RNFBInvitesModule application:application openURL:url options:options];
// if ([RNFBInvitesModule application:application openURL:url options:options]) {
// return YES;
// }
return [RCTLinkingManager application:application openURL:url options:options];
}
- (BOOL)application:(nonnull UIApplication *)application continueUserActivity :(nonnull NSUserActivity *)userActivity restorationHandler:
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 12000) /* __IPHONE_12_0 */
(nonnull void (^)(NSArray<id <UIUserActivityRestoring>> *_Nullable))restorationHandler {
#else
(nonnull void (^)(NSArray *_Nullable))restorationHandler {
#endif
return [RNFBInvitesModule application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
// return [RNFBInvitesModule application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}

View File

@@ -29,6 +29,16 @@
<string>com.googleusercontent.apps.448618578101-28tsenal97nceuij1msj7iuqinv48t02</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.testing</string>
<key>CFBundleURLSchemes</key>
<array>
<string>invertase</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
@@ -49,8 +59,6 @@
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
@@ -61,11 +69,13 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>rnfirebase_meta_testing_string</key>
<string>abc</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>rnfirebase_meta_testing_boolean_false</key>
<false/>
<key>rnfirebase_meta_testing_boolean_true</key>
<true/>
<key>rnfirebase_meta_testing_string</key>
<string>abc</string>
</dict>
</plist>

View File

@@ -18,6 +18,7 @@
"@react-native-firebase/firestore": "6.0.0-alpha.25",
"@react-native-firebase/functions": "6.0.0-alpha.25",
"@react-native-firebase/iid": "6.0.0-alpha.25",
"@react-native-firebase/indexing": "^6.0.0-alpha.25",
"@react-native-firebase/invites": "6.0.0-alpha.25",
"@react-native-firebase/ml-natural-language": "6.0.0-alpha.25",
"@react-native-firebase/perf": "6.0.0-alpha.25",