Coder Social home page Coder Social logo

bndkt / react-native-widget-extension Goto Github PK

View Code? Open in Web Editor NEW
429.0 11.0 31.0 1.17 MB

Add widgets and live activities to a React Native app

Home Page: https://bndkt.com/blog/2023/ios-live-activities

JavaScript 5.81% Ruby 2.21% TypeScript 57.91% Swift 34.08%

react-native-widget-extension's Introduction

react-native-widget-extension

Expo config plugin to add widgets and live activities to a React Native app

The widgets still need to be written in Swift (I think there's no way around that). But you can simply add a folder with Swift files to a React Native project (see folder _widgets in this repository for examples) and then add the plugin via:

npx expo install react-native-widget-extension

And add the following config to app.json (where widgetsFolder is the path to the folder with the Swift files):

"expo": {
    "name": "my-app",
    "plugins": [
        [
            "react-native-widget-extension",
            { "frequentUpdates": true, "widgetsFolder": "_widgets/PizzaDelivery" },
        ],
    ]
}

Then in React land, you can use the following:

import {
  areActivitiesEnabled,
  startActivity,
  updateActivity,
  endActivity,
} from "react-native-widget-extension";

startActivity(3, "4343", "$32.23", driverName, 47, 43);

Plugin configuration options

  • frequentUpdates (boolean, default: false): Depending on this param, NSSupportsLiveActivitiesFrequentUpdates will be set
  • widgetsFolder (string, default: "widgets"): Path from the project root to the folder containing the Swift widget files
  • deploymentTarget (string, default: "16.2"): The minimum deployment target for the app

Example

For a minimal example app, see the folder example. Example code for widgets can be found in the **_widgets__ folder.

Some background on how the PizzaDelivery example works:

  • Assets.xcassets and Info.plist: Automatically created by Xcode when you create a widget
  • Attributes.swift: The ActivityAttributes for the Live Activity are defined here. By default, this file should be named "Attributes.swift".
  • Module.swift: This file defined the native module that can then be used from React land to start/stop/update the live activity. By default, this file should be named "Module.swift".
  • The rest of the folder can be Swift files that define widgets, views, etc. and can be named and divided between files however you want.

Deployment Target

By default, this module adds a minimum deployment target of iOS 16.2, because otherwise Swift compilation fails if you try to use Live Activities. If you want to support earliert versions of iOS, you can manually set the deployment target via plugin config:

"expo": {
    "name": "my-app",
    "plugins": [
        [
            "react-native-widget-extension",
            { "deploymentTarget": "14.0" },
        ],
    ]
}

If you do this and you still use Live Activities in Swift, you have to make sure to guard the code that can only run on iOS 16.2 and later like this:

import SwiftUI
import WidgetKit

@main
struct PizzaDeliveryWidgetBundle: WidgetBundle {
    var body: some Widget {
        PizzaDeliveryWidgets()

        if #available(iOS 16.2, *) {
            PizzaDeliveryLiveActivity()
        }
    }
}

and

@available(iOS 16.2, *)
struct LockScreenLiveActivityView: View {
    ...
}

react-native-widget-extension's People

Contributors

bndkt avatar nandorojo 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  avatar  avatar  avatar  avatar  avatar

react-native-widget-extension's Issues

Minimal example

Could we have a more minimal example, everything I tried to remove from the current example broke it.
I am not sure what can and cannot be removed.
I only use it for a simple widget, so no data is passed from rn and it is completely static.

Lowering the minimum deployment version

Hey, just found this repo, looks great and will definitely follow it!

I noticed that you support both the regular widgets and Live Activities. However, for Live Activities only iOS 16.x is supported. I was wondering, if you want to support only regular widgets, could we lower the minimum deployment version to 14.0, and just throw exceptions in the Native module if the live activities methods are being invoked on iOS <16.x?

EDIT: I see in the code that all the live activities methods are already wrapped in if available, which means that it should work just fine if we use the minimum deployment version of 14.0?

Cannot find native module 'ReactNativeWidgetExtension'

Hello,

I've been trying to run the example given by the package throughout the example folder as following the blog. However, I found the following problem:

"Cannot find native module 'ReactNativeWidgetExtension"

image

image

I have build the project multiple times and none of the cases the native component is found. How should I test this library properly?

Create more than one widget

Hello!! This is just a question as I didn't find the info on the readme or the blog, if I want to create more than one widget how I could make that using your plugin? No rush at all on this, is just a doubt if it's possible or if there is a plan to implement it.

Steps to run example

The app in example/ doesn't run by default. Seems we need to run a build step first:

$ npx expo start
Error: Cannot find module './plugin/build

Is it easy to list the steps to run the example?

I'm also happy to send a PR for the readme if you can point me in the right direction.

Can't install extension

When I follow the instructions on how to install this extension, my Expo app compiles, but I can't open it with Expo Go.
Whenever I do that (with an iPhone 14 Pro Max), I get the following errors:

Error: Cannot find native module 'ReactNativeWidgetExtension', js engine: hermes

Invariant Violation: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called., js engine: hermes

Does anyone know how to fix that or what went wrong?

push notifications to live activity - This is more like a discussion than an issue

Hi Guys

I'm working on integrating live activities with push notifications on my React native project, the push notification will be managed by Braze, and here is where I get some doubts on how to interact between them since I need to add this portion of code at native side at the moment where startActivity is called, but I can't find any info related and idk if it's supported by your plugin or where I can find the startActivity function on the native side as I made a find using startActivity as you have or even launchActivity.

I would like to understand a bit more about how it interacts with native code or if you have a way to do it

if let activity = try? Activity.request(attributes: activityAttributes,
content: activityContent,
// Setting your pushType as .token allows the Activity to generate push tokens for the server to watch.
pushType: .token) {
// Register your Live Activity with Braze using the pushTokenTag
AppDelegate.braze?.liveActivities.launchActivity(pushTokenTag: "live-activity-1",
activity: activity)
}

Build error when use_frameworks is enabled

Building the app with expo-build-properties/use_frameworks enabled throws the following error:

 [!] Unable to integrate the following embedded targets with their respective host targets (a host target is a "parent" target which embeds a "child" target like a framework or extension):
- App (true) and AppWidgets (false) do not both set use_frameworks!.
pod exited with non-zero code: 1

Is there any ways to enable it in the modoule?

Can run on sim but fails on eas build

image

Not sure what went wrong here...

In text:

› Copying   ios/BeaconHangOutMore/GoogleService-Info.plist ➜ ./GoogleService-Info.plist
› Copying   ios/BeaconHangOutMore/Supporting/Expo.plist ➜ ./Expo.plist
› Compiling BeaconHangOutMore » SplashScreen.storyboard
› Preparing BeaconHangOutMore » Info.plist

❌  (ios/Pods/Target Support Files/Pods-BeaconHangOutMore/ExpoModulesProvider.swift:19:8)

  17 | import ExpoLinearGradient
  18 | import ExpoSMS
> 19 | import ReactNativeWidgetExtension
     |        ^ no such module 'ReactNativeWidgetExtension'
  20 | #if EXPO_CONFIGURATION_DEBUG
  21 | import EXDevLauncher
  22 | import EXDevMenu
▸ ** ARCHIVE FAILED **
▸ The following build commands failed:
▸ 	SwiftCompile normal arm64 Compiling\ ExpoModulesProvider.swift /Users/expo/workingdir/build/ios/Pods/Target\ Support\ Files/Pods-BeaconHangOutMore/ExpoModulesProvider.swift (in target 'BeaconHangOutMore' from project 'BeaconHangOutMore')
▸ 	SwiftCompile normal arm64 /Users/expo/workingdir/build/ios/Pods/Target\ Support\ Files/Pods-BeaconHangOutMore/ExpoModulesProvider.swift (in target 'BeaconHangOutMore' from project 'BeaconHangOutMore')
▸ (2 failures)
2023-11-21 10:28:45.570 xcodebuild[34960:43004] DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default (DVTEnableCoreDevice=disabled)
** ARCHIVE FAILED **
The following build commands failed:
	SwiftCompile normal arm64 Compiling\ ExpoModulesProvider.swift /Users/expo/workingdir/build/ios/Pods/Target\ Support\ Files/Pods-BeaconHangOutMore/ExpoModulesProvider.swift (in target 'BeaconHangOutMore' from project 'BeaconHangOutMore')
	SwiftCompile normal arm64 /Users/expo/workingdir/build/ios/Pods/Target\ Support\ Files/Pods-BeaconHangOutMore/ExpoModulesProvider.swift (in target 'BeaconHangOutMore' from project 'BeaconHangOutMore')
(2 failures)
Exit status: 65
+-------------+-------------------------+
|           Build environment           |
+-------------+-------------------------+
| xcode_path  | /Applications/Xcode.app |
| gym_version | 2.213.0                 |
| sdk         | iPhoneOS16.4.sdk        |
+-------------+-------------------------+
Looks like fastlane ran into a build/archive error with your project
It's hard to tell what's causing the error, so we wrote some guides on how
to troubleshoot build and signing issues: https://docs.fastlane.tools/codesigning/getting-started/
Before submitting an issue on GitHub, please follow the guide above and make
sure your project is set up correctly.
fastlane uses `xcodebuild` commands to generate your binary, you can see the
the full commands printed out in yellow in the above log.
Make sure to inspect the output above, as usually you'll find more error information there
[!] Error building the application - see the log above
Error: The "Run fastlane" step failed with an unknown error. Refer to "Xcode Logs" below for additional, more detailed logs.

Can't change parameters for use on react native side

Hello,

I'm trying to use this module with a few requirements in mind for my project:

  • I need to re prebuild the native ios folder every time
  • I can't manually change anything in the node_modules folder or the native ios folder

I was trying to change the parameters and such for the update and end activity functions, but I noticed that in the node_modules, the parameters were not correct.
I also noticed that your startActivity will take any arguments and simply pass it to the native side, but your update and end activity function have explicitly stated the parameters.
I tried to manually change the node_modules file but, once I run prebuild again, it overwrites the contents of the node_modules file anyways.

Am I doing something wrong?

No such module 'ReactNativeWidgetExtension'

Hi,

Thanks for the great work, when trying to build, i get this issue:

12 | import ExpoLinearGradient
  13 | import ExpoSystemUI
> 14 | import ReactNativeWidgetExtension
     |        ^ no such module 'ReactNativeWidgetExtension'
  15 | 
  16 | @objc(ExpoModulesProvider)
  17 | public class ExpoModulesProvider: ModulesProvider {

expo app on macOS, i configured as the doc says and the widget is working in xcode,

Thanks,

Théo

Not working in association with Sentry pkg on Expo SDK 51

Description

Step to reproduce

  1. Update to Expo SDK51
  2. Run the following cmd according to Sentry installation guide :
    npx @sentry/wizard@latest -i reactNative
  3. Create a development build with npx expo prebuild -p ios & npx expo run:ios

Expected behavior

The build is successful

Actual behavior

› Compiling Pods/Sentry » SentryViewHierarchyIntegration.m

❌  (ios/Pods/Sentry/Sources/Sentry/include/SentryMetricKitIntegration.h:24:57)

  22 | API_UNAVAILABLE(tvos, watchos)
  23 | @interface SentryMetricKitIntegration
> 24 |     : SentryBaseIntegration <SentryIntegrationProtocol, SentryMXManagerDelegate>
     |                                                         ^ cannot find protocol declaration for 'SentryMXManagerDelegate'
  25 | 
  26 | @end
  27 | 

› Compiling Pods/Sentry » SentryViewHierarchy.m

❌  (ios/Pods/Sentry/Sources/Sentry/SentryViewHierarchy.m:118:35)

  116 |     int result = 0;
  117 |     tryJson(sentrycrashjson_beginObject(context, NULL));
> 118 |     const char *viewClassName = [[SwiftDescriptor getObjectClassName:view] UTF8String];
      |                                   ^ unknown receiver 'SwiftDescriptor'; did you mean 'NSSortDescriptor'?
  119 |     tryJson(sentrycrashjson_addStringElement(
  120 |         context, "type", viewClassName, SentryCrashJSON_SIZE_AUTOMATIC));
  121 | 


❌  (ios/Pods/Sentry/Sources/Sentry/SentryViewHierarchy.m:118:51)

  116 |     int result = 0;
  117 |     tryJson(sentrycrashjson_beginObject(context, NULL));
> 118 |     const char *viewClassName = [[SwiftDescriptor getObjectClassName:view] UTF8String];
      |                                                   ^ no known class method for selector 'getObjectClassName:'
  119 |     tryJson(sentrycrashjson_addStringElement(
  120 |         context, "type", viewClassName, SentryCrashJSON_SIZE_AUTOMATIC));
  121 | 


❌  (ios/Pods/Sentry/Sources/Sentry/SentryViewHierarchy.m:138:19)

  136 |         if (vc.view == view) {
  137 |             const char *viewControllerClassName =
> 138 |                 [[SwiftDescriptor getObjectClassName:vc] UTF8String];
      |                   ^ unknown receiver 'SwiftDescriptor'; did you mean 'NSSortDescriptor'?
  139 |             tryJson(sentrycrashjson_addStringElement(context, "view_controller",
  140 |                 viewControllerClassName, SentryCrashJSON_SIZE_AUTOMATIC));
  141 |         }


❌  (ios/Pods/Sentry/Sources/Sentry/SentryViewHierarchy.m:138:35)

  136 |         if (vc.view == view) {
  137 |             const char *viewControllerClassName =
> 138 |                 [[SwiftDescriptor getObjectClassName:vc] UTF8String];
      |                                   ^ no known class method for selector 'getObjectClassName:'
  139 |             tryJson(sentrycrashjson_addStringElement(context, "view_controller",
  140 |                 viewControllerClassName, SentryCrashJSON_SIZE_AUTOMATIC));
  141 |         }

Development Workflow

I've just gotten started with this amazing library, however I am wondering on best possible development workflow.
Is there a way to update the Widget Swift Code without needing to create a new build after every change?

EAS build failure

This is amazing! Thank you!

I'm getting this error when building a development version with eas

21 | import ExpoSystemUI
  22 | import EXUpdates
> 23 | import ReactNativeWidgetExtension
     |        ^ no such module 'ReactNativeWidgetExtension'
  24 | #if EXPO_CONFIGURATION_DEBUG
  25 | import EXDevLauncher
  26 | import EXDevMenu

Any tips?

Bundle ID Apple

Is there a way to modify the bundle id?
Thanks for your work!

Combine With OneSignal

This is great for getting the live activity to show, but to use OneSignal push notifications to update this how would I go about it?

This is the code I use Natively but I can't work out how to include and init the OneSignal framework in your module?

let attributes = MatchActivityAttributes(id: fixture!.id, matchDate: matchDate, homeTeam: fixture?.home_team ?? "n/a", awayTeam: fixture?.away_team ?? "", homeLogo: homeUrl, awayLogo: awayUrl, competitionName: fixture?.competition.name ?? "n/a", competitionLogo: "")
let contentState = MatchActivityAttributes.ContentState(homeScore: "\(fixture?.home_score ?? 0)", awayScore: "\(fixture?.away_score ?? 0)", status: "\(fixture?.status ?? "")", minutes: "\(fixture?.status ?? "")")

let activity = try Activity<MatchActivityAttributes>.request(
    
    attributes: attributes,
    contentState: contentState,
    pushType: .token)
Task {
    self.followButton.isEnabled = false
    self.followButton.backgroundColor = .systemGray
    for await data in activity.pushTokenUpdates {
        let myToken = data.map {String(format: "%02x", $0)}.joined()
        OneSignal.enterLiveActivity("fixture_\(fixture?.id ?? 0)", withToken: myToken)
        print("Activity started for fixture_\(fixture!.id)")
    }
}

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.