Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion examples/SampleApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
"react-native-blob-util": "^0.22.2",
"react-native-fast-image": "^8.6.3",
"react-native-gesture-handler": "^2.31.0",
"react-native-haptic-feedback": "^2.3.3",
"react-native-image-picker": "^8.2.1",
"react-native-maps": "1.20.1",
"react-native-nitro-modules": "^0.31.3",
Expand Down
1 change: 0 additions & 1 deletion examples/TypeScriptMessaging/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"react-native-audio-recorder-player": "^3.6.13",
"react-native-blob-util": "^0.22.2",
"react-native-gesture-handler": "^2.26.0",
"react-native-haptic-feedback": "^2.3.3",
"react-native-image-picker": "^8.2.1",
"react-native-reanimated": "^4.0.1",
"react-native-safe-area-context": "^5.4.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@

public class StreamChatExpoPackage extends TurboReactPackage {
private static final String STREAM_VIDEO_THUMBNAIL_MODULE = "StreamVideoThumbnail";
private static final String STREAM_HAPTIC_FEEDBACK_MODULE = "StreamHapticFeedback";

@Nullable
@Override
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
if (name.equals(STREAM_VIDEO_THUMBNAIL_MODULE) && BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
if (name.equals(STREAM_HAPTIC_FEEDBACK_MODULE)) {
return new StreamHapticFeedbackModule(reactContext);
} else if (name.equals(STREAM_VIDEO_THUMBNAIL_MODULE) && BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
return createNewArchModule("com.streamchatexpo.StreamVideoThumbnailModule", reactContext);
}

Expand All @@ -31,6 +34,17 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() {
return () -> {
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
moduleInfos.put(
STREAM_HAPTIC_FEEDBACK_MODULE,
new ReactModuleInfo(
STREAM_HAPTIC_FEEDBACK_MODULE,
STREAM_HAPTIC_FEEDBACK_MODULE,
false, // canOverrideExistingModule
false, // needsEagerInit
false, // hasConstants
false, // isCxxModule
false // isTurboModule
));
moduleInfos.put(
STREAM_VIDEO_THUMBNAIL_MODULE,
new ReactModuleInfo(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.streamchatexpo

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.streamchatreactnative.shared.StreamHapticFeedback

class StreamHapticFeedbackModule(
reactContext: ReactApplicationContext,
) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String = NAME

@ReactMethod
fun triggerHaptic(type: String) {
StreamHapticFeedback.trigger(currentActivity, type)
}

companion object {
const val NAME = "StreamHapticFeedback"
}
}
4 changes: 0 additions & 4 deletions package/expo-package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"expo-clipboard": "*",
"expo-document-picker": "*",
"expo-file-system": "*",
"expo-haptics": "*",
"expo-image-manipulator": "*",
"expo-image-picker": "*",
"expo-media-library": "*",
Expand Down Expand Up @@ -74,9 +73,6 @@
},
"expo-sharing": {
"optional": true
},
"expo-haptics": {
"optional": true
}
},
"devDependencies": {
Expand Down
49 changes: 5 additions & 44 deletions package/expo-package/src/optionalDependencies/triggerHaptic.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,9 @@
let Haptics;
import { NativeModules } from 'react-native';

try {
Haptics = require('expo-haptics');
} catch (e) {
// do nothing
}
const { StreamHapticFeedback } = NativeModules;

if (!Haptics) {
console.log(
'expo-haptics is not installed. Installing this package will enable haptic feedback when scaling images in the image gallery if the scaling hits the higher or lower limits for its value.',
);
}

type HapticFeedbackTypes =
| 'impactHeavy'
| 'impactLight'
| 'impactMedium'
| 'notificationError'
| 'notificationSuccess'
| 'notificationWarning';

export const triggerHaptic = Haptics
? (method: HapticFeedbackTypes) => {
switch (method) {
case 'impactHeavy':
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy);
break;
case 'impactLight':
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
break;
case 'impactMedium':
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
break;
case 'notificationError':
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
break;
case 'notificationSuccess':
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
break;
case 'notificationWarning':
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning);
break;
default:
Haptics.selectionAsync();
}
export const triggerHaptic = StreamHapticFeedback
? (method: string) => {
StreamHapticFeedback.triggerHaptic(method);
}
: () => {};
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@

public class StreamChatReactNativePackage extends TurboReactPackage {
private static final String STREAM_VIDEO_THUMBNAIL_MODULE = "StreamVideoThumbnail";
private static final String STREAM_HAPTIC_FEEDBACK_MODULE = "StreamHapticFeedback";

@Nullable
@Override
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
if (name.equals(StreamChatReactNativeModule.NAME)) {
return new StreamChatReactNativeModule(reactContext);
} else if (name.equals(STREAM_HAPTIC_FEEDBACK_MODULE)) {
return new StreamHapticFeedbackModule(reactContext);
} else if (name.equals(STREAM_VIDEO_THUMBNAIL_MODULE) && BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
return createNewArchModule(
"com.streamchatreactnative.StreamVideoThumbnailModule",
Expand All @@ -47,6 +50,17 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() {
false, // isCxxModule
isTurboModule // isTurboModule
));
moduleInfos.put(
STREAM_HAPTIC_FEEDBACK_MODULE,
new ReactModuleInfo(
STREAM_HAPTIC_FEEDBACK_MODULE,
STREAM_HAPTIC_FEEDBACK_MODULE,
false, // canOverrideExistingModule
false, // needsEagerInit
false, // hasConstants
false, // isCxxModule
false // isTurboModule
));
moduleInfos.put(
STREAM_VIDEO_THUMBNAIL_MODULE,
new ReactModuleInfo(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.streamchatreactnative

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.streamchatreactnative.shared.StreamHapticFeedback

class StreamHapticFeedbackModule(
reactContext: ReactApplicationContext,
) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String = NAME

@ReactMethod
fun triggerHaptic(type: String) {
StreamHapticFeedback.trigger(currentActivity, type)
}

companion object {
const val NAME = "StreamHapticFeedback"
}
}
4 changes: 0 additions & 4 deletions package/native-package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"react-native-audio-recorder-player": ">=3.6.13",
"react-native-nitro-sound": ">=0.2.9",
"react-native-blob-util": ">=0.22.0",
"react-native-haptic-feedback": ">=2.3.0",
"react-native-image-picker": ">=7.1.2",
"react-native-share": ">=11.0.0",
"react-native-video": ">=6.18.0"
Expand All @@ -59,9 +58,6 @@
"@react-native-documents/picker": {
"optional": true
},
"react-native-haptic-feedback": {
"optional": true
},
"react-native-image-picker": {
"optional": true
},
Expand Down
47 changes: 5 additions & 42 deletions package/native-package/src/optionalDependencies/triggerHaptic.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,9 @@
let ReactNativeHapticFeedback;
import { NativeModules } from 'react-native';

try {
ReactNativeHapticFeedback = require('react-native-haptic-feedback').default;
} catch (e) {
console.warn('react-native-haptic-feedback is not installed.');
}
const { StreamHapticFeedback } = NativeModules;

/**
* Since react-native-haptic-feedback isn't installed by default, we've
* copied the types from the package here.
*
* @see https://github.com/junina-de/react-native-haptic-feedback/blob/master/index.d.ts
* */
export type HapticFeedbackTypes =
| 'selection'
| 'impactLight'
| 'impactMedium'
| 'impactHeavy'
| 'rigid'
| 'soft'
| 'notificationSuccess'
| 'notificationWarning'
| 'notificationError'
| 'clockTick'
| 'contextClick'
| 'keyboardPress'
| 'keyboardRelease'
| 'keyboardTap'
| 'longPress'
| 'textHandleMove'
| 'virtualKey'
| 'virtualKeyRelease'
| 'effectClick'
| 'effectDoubleClick'
| 'effectHeavyClick'
| 'effectTick';

export const triggerHaptic = ReactNativeHapticFeedback
? (method: HapticFeedbackTypes) => {
ReactNativeHapticFeedback.trigger(method, {
enableVibrateFallback: false,
ignoreAndroidSystemSettings: false,
});
export const triggerHaptic = StreamHapticFeedback
? (method: string) => {
StreamHapticFeedback.triggerHaptic(method);
}
: () => {};
29 changes: 29 additions & 0 deletions package/shared-native/android/StreamHapticFeedback.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.streamchatreactnative.shared

import android.app.Activity
import android.os.Build
import android.view.HapticFeedbackConstants

object StreamHapticFeedback {
fun trigger(activity: Activity?, type: String) {
val view = activity?.window?.decorView ?: return
val constant = when (type) {
"impactLight" -> HapticFeedbackConstants.KEYBOARD_TAP
"impactMedium" -> HapticFeedbackConstants.VIRTUAL_KEY
"impactHeavy" -> HapticFeedbackConstants.LONG_PRESS
"notificationSuccess" -> if (Build.VERSION.SDK_INT >= 30) {
HapticFeedbackConstants.CONFIRM
} else {
HapticFeedbackConstants.VIRTUAL_KEY
}
"notificationWarning" -> HapticFeedbackConstants.VIRTUAL_KEY
"notificationError" -> if (Build.VERSION.SDK_INT >= 30) {
HapticFeedbackConstants.REJECT
} else {
HapticFeedbackConstants.LONG_PRESS
}
else -> HapticFeedbackConstants.CLOCK_TICK
}
view.performHapticFeedback(constant, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING)
}
}
23 changes: 23 additions & 0 deletions package/shared-native/ios/StreamHapticFeedback.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import UIKit

@objcMembers
public final class StreamHapticFeedback: NSObject {
public static func trigger(_ type: String) {
switch type {
case "impactLight":
UIImpactFeedbackGenerator(style: .light).impactOccurred()
case "impactMedium":
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
case "impactHeavy":
UIImpactFeedbackGenerator(style: .heavy).impactOccurred()
case "notificationSuccess":
UINotificationFeedbackGenerator().notificationOccurred(.success)
case "notificationWarning":
UINotificationFeedbackGenerator().notificationOccurred(.warning)
case "notificationError":
UINotificationFeedbackGenerator().notificationOccurred(.error)
default:
UISelectionFeedbackGenerator().selectionChanged()
}
}
}
4 changes: 4 additions & 0 deletions package/shared-native/ios/StreamHapticFeedbackModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#import <React/RCTBridgeModule.h>

@interface StreamHapticFeedbackModule : NSObject <RCTBridgeModule>
@end
31 changes: 31 additions & 0 deletions package/shared-native/ios/StreamHapticFeedbackModule.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#import "StreamHapticFeedbackModule.h"

#if __has_include(<stream_chat_react_native/stream_chat_react_native-Swift.h>)
#import <stream_chat_react_native/stream_chat_react_native-Swift.h>
#elif __has_include(<stream_chat_expo/stream_chat_expo-Swift.h>)
#import <stream_chat_expo/stream_chat_expo-Swift.h>
#elif __has_include("stream_chat_react_native-Swift.h")
#import "stream_chat_react_native-Swift.h"
#elif __has_include("stream_chat_expo-Swift.h")
#import "stream_chat_expo-Swift.h"
#else
#error "Unable to import generated Swift header for StreamHapticFeedback."
#endif

@implementation StreamHapticFeedbackModule

RCT_EXPORT_MODULE(StreamHapticFeedback)

RCT_EXPORT_METHOD(triggerHaptic:(NSString *)type)
{
dispatch_async(dispatch_get_main_queue(), ^{
[StreamHapticFeedback trigger:type];
});
}

+ (BOOL)requiresMainQueueSetup
{
return NO;
}

@end
Loading