Giter Club home page Giter Club logo

react-native-spotlight-search's Introduction

react-native-spotlight-search

🌟 This project is looking for maintainers! If you're interested to help maintain this repository by fixing bugs, updating dependencies and reviewing other contributions, please open an issue in the repository with a little bit about yourself 🌟

A React Native module for iOS that provides Spotlight search functionality. This allows you to index content from within your React Native app so that it appears in the iOS device's Spotlight search index, potentially increasing the exposure of your app.

Current Features

  • Adding items.
  • Updating items.
  • Deleting items.
  • Register a callback to handle when a search item is tapped.
  • Support for images

Spotlight Search Demo

Installation

With yarn (recommended): $ yarn add react-native-spotlight-search

Or with NPM: $ npm install react-native-spotlight-search --save

iOS

Expo

Prebuild Plugin

This package cannot be used in the "Expo Go" app because it requires custom native code.

After installing this npm package, add the config plugin to the plugins array of your app.json or app.config.js:

{
  "expo": {
    "plugins": ["react-native-spotlight-search"]
  }
}

Next, rebuild your app as described in the "Adding custom native code" guide.

RN >= 0.60

Auto linking or Manually below

RN < 0.60

react-native link react-native-spotlight-search or Manually below

Simply add RCTSpotlightSearch.xcodeproj to Libraries and add libRCTSpotlightSearch.a to Link Binary With Libraries under Build Phases. More info and screenshots about how to do this is available in the React Native documentation.

In Your AppDelegate (Optional)

If you wish to be able to handle search item tapped callbacks, you'll need to add the following code to your AppDelegate file:

#import "RCTSpotlightSearch.h"

- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * _Nullable))restorationHandler {
  [RCTSpotlightSearch handleContinueUserActivity:userActivity];
  return YES;
}

If Xcode complains about being unable to find the header file, please ensure that your project's header search includes the following:

$(SRCROOT)/../node_modules/react-native-spotlight-search

Like this:

Header Search Paths

Usage

First up, import the module:

import SpotlightSearch from "react-native-spotlight-search";

Indexing Items

You can either add an array of items:

SpotlightSearch.indexItems([
  {
    title: "Strawberry",
    contentDescription: "A sweet and juicy fruit.",
    uniqueIdentifier: "1",
    domain: "fruit",
    thumbnailName: "strawberry",
  },
  {
    title: "Kiwi",
    contentDescription: "Not a type of bird.",
    uniqueIdentifier: "2",
    domain: "fruit",
    thumbnailName: "kiwi",
  },
]);

Or individual items:

SpotlightSearch.indexItem({
  title: "Strawberry",
  contentDescription: "A sweet and juicy fruit.",
  uniqueIdentifier: "1",
  thumbnailName: "strawberry",
});

Search Item Properties

Property Description Type Required
title The title of the search item. string Yes
contentDescription A description which appears below the title in the search results. string No
uniqueIdentifier A unique and stable identifier. Used to refer to the item. string Yes
domain A string for grouping related items together in a way that makes sense. Not displayed to the user. string Yes
thumbnailName A local file name/key to a thumbnail image. See A Note About Thumbnails. string No
thumbnailData A base64 string representation of a thumbnail image. See A Note About Thumbnails. string No
keywords An array of keywords which can be used to help inform the search index. Not visible to the user. [string] No

Updating Items

Simply use the same method as adding items. Be sure to reference the same key when indexing the item so that any new metadata changes will be reflected in the Spotlight index.

Removing Items

Items can be removed by identifier:

SpotlightSearch.deleteItemsWithIdentifiers(["1", "2"]);

Or by domain:

SpotlightSearch.deleteItemsInDomains(["fruit"]);

Alternatively, you can delete all items indexed by your app:

SpotlightSearch.deleteAllItems();

Promises

All API index and delete methods are asynchronous and return promises. You can chain things like this:

SpotlightSearch.deleteAllItems().then(() => {
  SpotlightSearch.indexItem({
    title: "Strawberry",
    contentDescription: "A sweet and juicy fruit.",
    uniqueIdentifier: "1",
    thumbnailName: "strawberry",
  });
});

Handling User Interactions

You can choose to add a custom handler that will be invoked in the event of a user tapping one of the search items in the Spotlight results:

SpotlightSearch.searchItemTapped((uniqueIdentifier) => {
  alert(`You tapped on ${uniqueIdentifier}!`);
});

Optionally, if you want to capture the search item that was tapped to open the app (perhaps the listener was set after the event was triggered):

SpotlightSearch.getInitialSearchItem().then((uniqueIdentifier) => {
  alert(`You tapped on ${uniqueIdentifier} and opened the app!`);
});

// example in a useEffect with listener cleanup
useEffect(() => {
    const spotlightListener = SpotlightSearch.searchItemTapped((uniqueIdentifier) => {
        alert(`You tapped on ${uniqueIdentifier} and opened the app!`);
    })
    return () => {
        // cleanup listener
        spotlightListener.remove()
    }
}, [])

The parameter will be the uniqueIdentifier that the item was indexed with. You can use this to lookup the item and display information about it, e.g. by navigating to a relevant page in your app.

A Note About Thumbnails

Currently, in order to use an image path it must exist locally on the device in the project assets folder. This is a limitation of iOS rather than of this library.

To use images that are not in your assets folder (local or remote files), read them as base64 and include the string value using the thumbnailData property.

To-do

  • Support additional built in types (location etc).
  • Public links.
  • Initial release.
  • New iOS 10 features.

PRs welcome ❤️

react-native-spotlight-search's People

Contributors

bang9 avatar jdmunro avatar jedashford avatar jedijashwa avatar jordanduncan avatar robertherber avatar sakshya73 avatar stief510 avatar vtolochk avatar wsliaw avatar yannickoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

react-native-spotlight-search's Issues

searchItemTapped does not appear to be working

searchItemTapped does not appear to be working in RN 0.59.5

I am able to index items into spotlight. However, the callback never executes.

Example Code: index.ios.js
Using simulator: iPhone X 12.2
react-native-spotlight-search version: 1.1.0

import {AppRegistry}      from 'react-native';
import App                from './App';
import {name as appName}  from './app.json';
import SpotlightSearch  from 'react-native-spotlight-search';

const sampleFruits = [
  {
    name: 'Strawberry',
    details: 'A sweet and juicy fruit.',
    key: '1',
    keywords: ['delicious', 'edible'],
  },
  {
    name: 'Banana',
    details: 'A bright yellow fruit.',
    key: '2',
    keywords: ['plantain'],
  },
  {
    name: 'Kiwi',
    details: 'Not a type of bird.',
    key: '3',
    keywords: ['new zealand'],
  },
];

SpotlightSearch.searchItemTapped((uniqueIdentifier) => {
  const selectedFruit = sampleFruits.filter((fruit) => fruit.key === uniqueIdentifier)[0];
  alert(`You tapped on ${selectedFruit.name}!`);
});

SpotlightSearch.indexItems(sampleFruits.map((fruit) => {
  return {
    title: fruit.name,
    contentDescription: fruit.details,
    uniqueIdentifier: fruit.key,
    keywords: fruit.keywords,
  };
}));

AppRegistry.registerComponent(appName, () => App);

CSIndexErrorDomain after calling indexItem()

Possible Unhandled Promise Rejection (id: 0):
Error: The operation couldn’t be completed. (CSIndexErrorDomain error -1001.)

Call with the following:

SpotlightSearch.indexItem({
  title: 'Agrian Mobile',
  contentDescription: 'Agrian Mobile',
  uniqueIdentifier: 1,
  domain: 'Agrian',
});

Installed with pod install.

Support non asset images through thumbnailData

Lookin over the documentation, it seems that a way to support images not in the Xcode assets such as images added after the creation of the app would be to use the thumbnailData attribute on CSSearchableItem. I haven't gotten a chance to play with it much to see if it works but if this seems like a viable option I can try to create a fork and add it. It probably wouldn't be for a few weeks though.

https://developer.apple.com/documentation/corespotlight/cssearchableitemattributeset/1621582-thumbnaildata

Attempting to load the view of a view controller while it is deallocating

This message is seen in the console when tapping an indexed item in the Spotlight search results. This may be a bug in React Native itself.

2016-06-30 07:19:39.330 example[43985:10106534] Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior (<UIAlertController: 0x7a15ea00>)

Steps to reproduce:

  1. Search for an indexed item.
  2. Tap the item.
  3. View the warning message in the console.

Repo Ownership - Angel Studios

We would be interested in owning the react-native-spotlight-search repo. We made some changes to fix the known issues: #58

We have been around since 2015 as VidAngel and rebranded in 2020 to Angel Studios and headed toward a decade of mobile video streaming. Angel Studios is a streaming service for crowdfunded content on all major platforms: web, iOS, Android, Android TV, FireTV, AppleTV, Roku, and more coming. We're committed to the future of React Native and keeping as much open source as possible.

Github:
https://github.com/Angel-Studios

Website:
https://www.angel.com

Some News with our most recent theatrical release:
https://www.prnewswire.com/news-releases/fathom-events-notches-highest-grossing-event-in-company-history-with-the-chosen-season-three-episode-1--2-301694666.html

Flow types

Add flow types for the public JS interface.

There's just a few methods and arguments so this would be a great first issue for someone to tackle.

iOS AppDelegate integration

In AppDelegate the method - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * _Nullable))restorationHandler { returns (quote from Apple Docs)

YES to indicate that your app handled the activity or NO to let iOS know that your app did not handle the activity.

The instructions for this library are to call a void method [RCTSpotlightSearch handleContinueUserActivity:userActivity]; and then always return YES. I want to add another potential method return [RNBranch continueUserActivity:userActivity];
For the correct return value and processing logic [RCTSpotlightSearch handleContinueUserActivity:userActivity] should therefore not be void but return YES or NO

thumbnailData base64 string not working

When I provide a base64 string to the thumbnailData property it is not taken into account.
What I see is the app icon not the icon I provide.

const item = {
  {
    uniqueIdentifier: '1',
    title: 'title',
    contentDescription: 'desc',
    domain: item.domain,
    keywords: [
      'test', 'key'
    ],
    thumbnailData: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII='
  }

This should be correct, right? Or did I make a mistake?

Callback on Release called just once

Hej there,

with your module it has been a pleasure to implement spotlight search :)

When I built it the first time in Release mode I faced a surprise, though:
Compared to Development mode, where it responds to multiple interactions, in Release it only reacts to the first user interaction.

I solved it by recursively listening for user taps, but I wonder whether that is a bug in your module, or a constraint by Apple.

While looking at your code I found something with an activity queue, so I assume your intention was to support multiple interactions. But here my Objective C skills end.

([email protected], [email protected])

getInitialSearchItem return empty initialIdentifier ignore the handleContinueUserActivity value

Hi, this lib comes in handy, but I struggle with a bug:

I just debug the case:

self.initialIdentifier has value in handleContinueUserActivity:

self.initialIdentifier = uniqueItemIdentifier; // set break point here and got the correct value
- (void)handleContinueUserActivity:(NSUserActivity *)userActivity {
    NSString *uniqueItemIdentifier = userActivity.userInfo[CSSearchableItemActivityIdentifier];
    
    if (!uniqueItemIdentifier) {
        return;
    }

    self.initialIdentifier = uniqueItemIdentifier;
    
    if (!self.hasListeners) {
        return;
    }
    
    [self sendEventWithName:kSpotlightSearchItemTapped body:uniqueItemIdentifier];
}

But self.initialIdentifier became nil here:

RCT_EXPORT_METHOD(getInitialSearchItem:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
    resolve(self.initialIdentifier);
}

It leads to undefined on JS:

SpotlightSearch.getInitialSearchItem().then(console.log);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.