mattermost-mobile/patches/react-native-incall-manager+4.2.0.patch
Christopher Poile 92bdb2847b
[MM-57486] [MM-58008] Calls: Mobile ringing for incoming calls (#7984)
* notification ringing, settings screen, native code patch, ringing mp3s

* i18n

* play preview on first press

* prevent playing from background (only affects Android) to match iOS beh

* stop ringing/vibration on entering background

* ring when coming back from background and new incoming call is present

* no push notification sound when it's a call; improve ringing

* move sounds to asset folder; copy on postinstall for android bundling

* make Ringtone type a string enum

* make Android ring async + await ring and stop; changes from PR comments

* missing fields after merge

* release lock on an exception

* cancel sample ringing when turning notifications off

* copy sound files for android build

* typo

* update snapshots

* testing if the problem is copying the mp3 files

* fix android mp3 assets when building for non-release

* add sounds to .gitignore

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
2024-07-03 10:22:46 -04:00

335 lines
14 KiB
Diff

diff --git a/node_modules/react-native-incall-manager/android/src/main/java/com/zxcpoiu/incallmanager/InCallManagerModule.java b/node_modules/react-native-incall-manager/android/src/main/java/com/zxcpoiu/incallmanager/InCallManagerModule.java
index 10cb1e5..ba5d918 100644
--- a/node_modules/react-native-incall-manager/android/src/main/java/com/zxcpoiu/incallmanager/InCallManagerModule.java
+++ b/node_modules/react-native-incall-manager/android/src/main/java/com/zxcpoiu/incallmanager/InCallManagerModule.java
@@ -1040,107 +1040,107 @@ public class InCallManagerModule extends ReactContextBaseJavaModule implements L
}
@ReactMethod
- public void startRingtone(final String ringtoneUriType, final int seconds) {
- Thread thread = new Thread() {
- @Override
- public void run() {
+ public void startRingtone(final String ringtoneUriType, final int seconds, Promise promise) {
+ try {
+ Log.d(TAG, "startRingtone(): UriType=" + ringtoneUriType);
+ if (mRingtone != null) {
+ if (mRingtone.isPlaying()) {
+ Log.d(TAG, "startRingtone(): is already playing");
+ promise.reject("ringtone is already playing", "no error");
+ return;
+ }
try {
- Looper.prepare();
-
- Log.d(TAG, "startRingtone(): UriType=" + ringtoneUriType);
- if (mRingtone != null) {
- if (mRingtone.isPlaying()) {
- Log.d(TAG, "startRingtone(): is already playing");
- return;
- } else {
- stopRingtone(); // --- use brandnew instance
- }
- }
+ stopRingtone(); // ensure no ringtone is currently playing
+ } catch (Exception e) {
+ promise.reject("stopRingtone() failed", e);
+ return;
+ }
+ }
- //if (!audioManager.isStreamMute(AudioManager.STREAM_RING)) {
- //if (origRingerMode == AudioManager.RINGER_MODE_NORMAL) {
- if (audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0) {
- Log.d(TAG, "startRingtone(): ringer is silent. leave without play.");
- return;
- }
+ if (audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0) {
+ Log.d(TAG, "startRingtone(): ringer is silent. leave without play.");
+ promise.reject("ringer is silent. leave without playing", "no error");
+ return;
+ }
- // --- there is no _DTMF_ option in startRingtone()
- Uri ringtoneUri = getRingtoneUri(ringtoneUriType);
- if (ringtoneUri == null) {
- Log.d(TAG, "startRingtone(): no available media");
- return;
- }
+ // --- there is no _DTMF_ option in startRingtone()
+ Uri ringtoneUri = getRingtoneUri(ringtoneUriType);
+ if (ringtoneUri == null) {
+ Log.d(TAG, "startRingtone(): no available media");
+ promise.reject("no available media", "no error");
+ return;
+ }
- if (audioManagerActivated) {
- InCallManagerModule.this.stop();
- }
+ if (audioManagerActivated) {
+ InCallManagerModule.this.stop();
+ }
- wakeLockUtils.acquirePartialWakeLock();
+ wakeLockUtils.acquirePartialWakeLock();
- storeOriginalAudioSetup();
- Map data = new HashMap<String, Object>();
- mRingtone = new myMediaPlayer();
+ storeOriginalAudioSetup();
+ Map data = new HashMap<String, Object>();
+ mRingtone = new myMediaPlayer();
- data.put("name", "mRingtone");
- data.put("sourceUri", ringtoneUri);
- data.put("setLooping", true);
+ data.put("name", "mRingtone");
+ data.put("sourceUri", ringtoneUri);
+ data.put("setLooping", true);
- //data.put("audioStream", AudioManager.STREAM_RING); // --- lagacy
- data.put("audioUsage", AudioAttributes.USAGE_NOTIFICATION_RINGTONE); // --- USAGE_NOTIFICATION_COMMUNICATION_REQUEST?
- data.put("audioContentType", AudioAttributes.CONTENT_TYPE_MUSIC);
+ //data.put("audioStream", AudioManager.STREAM_RING); // --- lagacy
+ data.put("audioUsage", AudioAttributes.USAGE_NOTIFICATION_RINGTONE); // --- USAGE_NOTIFICATION_COMMUNICATION_REQUEST?
+ data.put("audioContentType", AudioAttributes.CONTENT_TYPE_MUSIC);
- setMediaPlayerEvents((MediaPlayer) mRingtone, "mRingtone");
+ setMediaPlayerEvents((MediaPlayer) mRingtone, "mRingtone");
- mRingtone.startPlay(data);
+ mRingtone.startPlay(data);
- if (seconds > 0) {
- mRingtoneCountDownHandler = new Handler();
- mRingtoneCountDownHandler.postDelayed(new Runnable() {
- public void run() {
- try {
- Log.d(TAG, String.format("mRingtoneCountDownHandler.stopRingtone() timeout after %d seconds", seconds));
- stopRingtone();
- } catch(Exception e) {
- Log.d(TAG, "mRingtoneCountDownHandler.stopRingtone() failed.");
- }
- }
- }, seconds * 1000);
+ if (seconds > 0) {
+ mRingtoneCountDownHandler = new Handler();
+ mRingtoneCountDownHandler.postDelayed(() -> {
+ try {
+ Log.d(TAG, String.format("mRingtoneCountDownHandler.stopRingtone() timeout after %d seconds", seconds));
+ stopRingtone();
+ } catch (Exception e) {
+ Log.d(TAG, "mRingtoneCountDownHandler.stopRingtone() failed.");
}
-
- Looper.loop();
- } catch(Exception e) {
- wakeLockUtils.releasePartialWakeLock();
- Log.e(TAG, "startRingtone() failed", e);
- }
+ }, seconds * 1000);
}
- };
+ } catch (Exception e) {
+ wakeLockUtils.releasePartialWakeLock();
+ Log.e(TAG, "startRingtone() failed", e);
+ promise.reject("startRingtone() failed", e);
+ }
- thread.start();
+ promise.resolve(null);
}
+
@ReactMethod
- public void stopRingtone() {
- Thread thread = new Thread() {
- @Override
- public void run() {
- try {
- if (mRingtone != null) {
- mRingtone.stopPlay();
- mRingtone = null;
- restoreOriginalAudioSetup();
- }
- if (mRingtoneCountDownHandler != null) {
- mRingtoneCountDownHandler.removeCallbacksAndMessages(null);
- mRingtoneCountDownHandler = null;
- }
- } catch (Exception e) {
- Log.d(TAG, "stopRingtone() failed");
- }
- wakeLockUtils.releasePartialWakeLock();
- }
- };
+ public void stopRingtone(Promise promise) {
+ try {
+ stopRingtone();
+ } catch (Exception e) {
+ promise.reject("stopRingtone() failed", e);
+ }
+ promise.resolve(null);
+ }
- thread.start();
+ private void stopRingtone() {
+ try {
+ if (mRingtone != null) {
+ mRingtone.stopPlay();
+ mRingtone = null;
+ restoreOriginalAudioSetup();
+ }
+ if (mRingtoneCountDownHandler != null) {
+ mRingtoneCountDownHandler.removeCallbacksAndMessages(null);
+ mRingtoneCountDownHandler = null;
+ }
+ } catch (Exception e) {
+ Log.d(TAG, "stopRingtone() failed");
+ wakeLockUtils.releasePartialWakeLock();
+ throw e;
+ }
+ wakeLockUtils.releasePartialWakeLock();
}
private void setMediaPlayerEvents(MediaPlayer mp, final String name) {
@@ -1267,6 +1267,32 @@ public class InCallManagerModule extends ReactContextBaseJavaModule implements L
return getAudioUri(type, fileBundle, fileBundleExt, fileSysWithExt, fileSysPath, "bundleBusytoneUri", "defaultBusytoneUri");
}
+ private Uri getRingtoneUriFromBundle(final String filename) {
+ if (audioUriMap.containsKey(filename)) {
+ Log.d(TAG, "getAudioUri() using: " + filename);
+ return audioUriMap.get(filename);
+ }
+
+ int res = 0;
+ ReactContext reactContext = getReactApplicationContext();
+ if (reactContext == null) {
+ Log.d(TAG, "getAudioUri() reactContext is null");
+ } else {
+ res = reactContext.getResources().getIdentifier(filename, "raw", mPackageName);
+ }
+
+ if (res <= 0) {
+ Log.d(TAG, String.format("getAudioUri() %s.%s not found in bundle.", filename, "mp3"));
+ audioUriMap.put(filename, null);
+ return null;
+ }
+
+ Uri uri = Uri.parse("android.resource://" + mPackageName + "/" + Integer.toString(res));
+ audioUriMap.put(filename, uri);
+ Log.d(TAG, "getAudioUri() using: " + filename);
+ return uri;
+ }
+
private Uri getAudioUri(final String _type, final String fileBundle, final String fileBundleExt, final String fileSysWithExt, final String fileSysPath, final String uriBundle, final String uriDefault) {
String type = _type;
if (type.equals("_BUNDLE_")) {
@@ -1300,6 +1326,12 @@ public class InCallManagerModule extends ReactContextBaseJavaModule implements L
final String target = fileSysPath + "/" + type;
Uri _uri = getSysFileUri(target);
if (_uri == null) {
+ Log.d(TAG, "getAudioUri() file not found in system, trying bundle");
+ _uri = getRingtoneUriFromBundle(type);
+ if (_uri != null) {
+ return _uri;
+ }
+
Log.d(TAG, "getAudioUri() using user default");
return getDefaultUserUri(uriDefault);
} else {
diff --git a/node_modules/react-native-incall-manager/index.d.ts b/node_modules/react-native-incall-manager/index.d.ts
index c8ebe9d..5f2ab9e 100644
--- a/node_modules/react-native-incall-manager/index.d.ts
+++ b/node_modules/react-native-incall-manager/index.d.ts
@@ -37,9 +37,9 @@ declare class InCallManager {
vibrate_pattern: number | number[],
ios_category: string,
seconds: number
- ): void;
+ ): Promise<void>;
- stopRingtone(): void;
+ stopRingtone(): Promise<void>;
startProximitySensor(): void;
diff --git a/node_modules/react-native-incall-manager/index.js b/node_modules/react-native-incall-manager/index.js
index ac5cafb..6887150 100644
--- a/node_modules/react-native-incall-manager/index.js
+++ b/node_modules/react-native-incall-manager/index.js
@@ -73,14 +73,14 @@ class InCallManager {
_InCallManager.setMicrophoneMute(enable);
}
- startRingtone(ringtone, vibrate_pattern, ios_category, seconds) {
+ async startRingtone(ringtone, vibrate_pattern, ios_category, seconds) {
ringtone = (typeof ringtone === 'string') ? ringtone : "_DEFAULT_";
this.vibrate = (Array.isArray(vibrate_pattern)) ? true : false;
ios_category = (ios_category === 'playback') ? 'playback' : "default";
seconds = (typeof seconds === 'number' && seconds > 0) ? parseInt(seconds) : -1; // --- android only, default looping
if (Platform.OS === 'android') {
- _InCallManager.startRingtone(ringtone, seconds);
+ await _InCallManager.startRingtone(ringtone, seconds);
} else {
_InCallManager.startRingtone(ringtone, ios_category);
}
@@ -91,11 +91,11 @@ class InCallManager {
}
}
- stopRingtone() {
+ async stopRingtone() {
if (this.vibrate) {
Vibration.cancel();
}
- _InCallManager.stopRingtone();
+ await _InCallManager.stopRingtone();
}
startProximitySensor() {
diff --git a/node_modules/react-native-incall-manager/ios/RNInCallManager/RNInCallManager.m b/node_modules/react-native-incall-manager/ios/RNInCallManager/RNInCallManager.m
index 7c54f6e..f861a0f 100644
--- a/node_modules/react-native-incall-manager/ios/RNInCallManager/RNInCallManager.m
+++ b/node_modules/react-native-incall-manager/ios/RNInCallManager/RNInCallManager.m
@@ -1126,6 +1126,18 @@ - (NSURL *)getRingtoneUri:(NSString *)_type
return uri;
}
+
+- (NSURL *)getRingtoneUriFromBundle:(NSString *)filename
+{
+ NSString *fileBundleExt = @"mp3";
+ NSLog(@"RNInCallManager.getRingtoneUriFromBundle(): trying to get from bundle: %@.%@", filename, fileBundleExt);
+ NSURL *uriBundle = [[NSBundle mainBundle] URLForResource:filename withExtension:fileBundleExt];
+ if (uriBundle == nil) {
+ NSLog(@"RNInCallManager.getRingtoneUriFromBundle(): not found in bundle: %@.%@", filename, fileBundleExt);
+ }
+ return uriBundle;
+}
+
- (NSURL *)getAudioUri:(NSString *)_type
fileBundle:(NSString *)fileBundle
fileBundleExt:(NSString *)fileBundleExt
@@ -1149,11 +1161,15 @@ - (NSURL *)getAudioUri:(NSString *)_type
}
}
- if (*uriDefault == nil) {
- NSString *target = [NSString stringWithFormat:@"%@/%@", fileSysPath, type];
- *uriDefault = [self getSysFileUri:target];
+ // --- Check file every time in case user deleted.
+ NSString *target = [NSString stringWithFormat:@"%@/%@", fileSysPath, type];
+ NSURL *uri = [self getSysFileUri:target];
+
+ if (uri == nil) {
+ uri = [self getRingtoneUriFromBundle:type];
}
- return *uriDefault;
+
+ return uri;
}
- (NSURL *)getSysFileUri:(NSString *)target