Compare commits

...

2 Commits

Author SHA1 Message Date
Denis Kurmansky 1eca952c98 fix | conflict 3 years ago
Denis Kurmansky 039f44a065 fix | voice msg 3 years ago
  1. BIN
      android/app/src/main/assets/fonts/fontello.ttf
  2. 3
      android/app/src/main/java/com/taskme/MainApplication.java
  3. 2
      android/build.gradle
  4. 4
      android/settings.gradle
  5. 4
      ios/Podfile
  6. 19
      ios/Podfile.lock
  7. 138
      ios/taskme.xcodeproj/project.pbxproj
  8. 16
      package-lock.json
  9. 1
      package.json
  10. 7
      src/api/chat-messages/requests.ts
  11. 9
      src/modules/media/consts/record-audio-modal.consts.ts
  12. 380
      src/modules/media/smart-components/record-audio-modal.smart-component.tsx
  13. 14
      src/services/domain/chat-messages.service.ts
  14. 20
      src/services/system/file-convert.service.ts
  15. 7
      src/services/system/fs.service.ts
  16. 3
      src/services/system/index.ts
  17. 5
      src/services/system/media-permissions.service.ts
  18. 81
      src/services/system/media.service.ts
  19. 33
      src/shared/components/plugins/chat/chat-item-audio.component.tsx
  20. 17
      src/shared/helpers/fs.helpers.ts
  21. 5
      yarn.lock

BIN
android/app/src/main/assets/fonts/fontello.ttf

Binary file not shown.

3
android/app/src/main/java/com/taskme/MainApplication.java

@ -4,6 +4,7 @@ import android.app.Application; @@ -4,6 +4,7 @@ import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.punarinta.RNSoundLevel.RNSoundLevel;
import com.rnfs.RNFSPackage;
import org.devio.rn.splashscreen.SplashScreenReactPackage;
import com.facebook.react.ReactInstanceManager;
@ -14,7 +15,7 @@ import java.lang.reflect.InvocationTargetException; @@ -14,7 +15,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.wonday.orientation.OrientationActivityLifecycle;
import com.brentvatne.react.ReactVideoPackage;
import com.dooboolab.audiorecorderplayer.RNAudioRecorderPlayerPackage;
import com.facebook.react.bridge.JSIModulePackage;
import com.swmansion.reanimated.ReanimatedJSIModulePackage;

2
android/build.gradle

@ -8,7 +8,7 @@ buildscript { @@ -8,7 +8,7 @@ buildscript {
targetSdkVersion = 29
kotlinVersion = '1.5.0'
ndkVersion = "22.0.7026061"
ffmpegKitPackage = "audio"
}
repositories {
google()

4
android/settings.gradle

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@
rootProject.name = 'taskme'
include ':react-native-sound-level'
project(':react-native-sound-level').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sound-level/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
include ':react-native-fs'
@ -9,6 +11,8 @@ include ':react-native-splash-screen' @@ -9,6 +11,8 @@ include ':react-native-splash-screen'
project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android')
include ':react-native-splash-screen'
project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android')
include ':react-native-audio-recorder-player'
project(':react-native-audio-recorder-player').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-audio-recorder-player/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android')
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

4
ios/Podfile

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
platform :ios, '11.0'
platform :ios, '12.1'
target 'taskme' do
config = use_native_modules!
@ -24,6 +24,8 @@ target 'taskme' do @@ -24,6 +24,8 @@ target 'taskme' do
:path => '../node_modules/rn-fetch-blob'
pod 'RNSoundLevel', :path => '../node_modules/react-native-sound-level'
target 'taskmeTests' do
inherit! :complete
# Pods for testing

19
ios/Podfile.lock

@ -9,6 +9,13 @@ PODS: @@ -9,6 +9,13 @@ PODS:
- React-Core (= 0.64.3)
- React-jsi (= 0.64.3)
- ReactCommon/turbomodule/core (= 0.64.3)
- ffmpeg-kit-ios-https (4.5.1)
- ffmpeg-kit-react-native (4.5.2):
- ffmpeg-kit-react-native/https (= 4.5.2)
- React-Core
- ffmpeg-kit-react-native/https (4.5.2):
- ffmpeg-kit-ios-https (= 4.5.1)
- React-Core
- glog (0.3.5)
- libwebp (1.2.1):
- libwebp/demux (= 1.2.1)
@ -412,6 +419,7 @@ DEPENDENCIES: @@ -412,6 +419,7 @@ DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- ffmpeg-kit-react-native (from `../node_modules/ffmpeg-kit-react-native`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- OneSignal (< 4.0, >= 3.0)
- Permission-Camera (from `../node_modules/react-native-permissions/ios/Camera`)
@ -480,6 +488,7 @@ DEPENDENCIES: @@ -480,6 +488,7 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- boost-for-react-native
- ffmpeg-kit-ios-https
- libwebp
- OneSignal
- OneSignalXCFramework
@ -494,6 +503,8 @@ EXTERNAL SOURCES: @@ -494,6 +503,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/FBLazyVector"
FBReactNativeSpec:
:path: "../node_modules/react-native/React/FBReactNativeSpec"
ffmpeg-kit-react-native:
:path: "../node_modules/ffmpeg-kit-react-native"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
Permission-Camera:
@ -621,7 +632,9 @@ SPEC CHECKSUMS: @@ -621,7 +632,9 @@ SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
FBLazyVector: c71c5917ec0ad2de41d5d06a5855f6d5eda06971
FBReactNativeSpec: 50ac84ed135478e1b20e25b4c165cd57b2ce1988
FBReactNativeSpec: 1b104089c962a23178ab10f7d072921d46a48d43
ffmpeg-kit-ios-https: cec24d405b511e4f274980d8a9c751d384f89558
ffmpeg-kit-react-native: bc3c900af9f761b6fe30906ee1bd98000c79f9c9
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
OneSignal: 60902887c93f91e9b5599583e7df5f55b2144755
@ -681,8 +694,8 @@ SPEC CHECKSUMS: @@ -681,8 +694,8 @@ SPEC CHECKSUMS:
RNPermissions: bf844d392fe0ecbfbd2e4ae2b88cc32f2f09b369
RNReanimated: 58e7b950e0172235ff8296dd39ec145f9577e301
RNScreens: eb0dfb2d6b21d2d7f980ad46b14eb306d2f1062e
RNSoundLevel: 3dd5d2f6431e47f806233600936deb636a0d9800
RNShare: 2074af48908436c310847c6c47ebb6129db1dc89
RNSoundLevel: a02f3bfbb81aeec256de4e41d7fc967b32e3faf1
RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f
RNVectorIcons: f67a1abce2ec73e62fe4606e8110e95a832bc859
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
@ -690,6 +703,6 @@ SPEC CHECKSUMS: @@ -690,6 +703,6 @@ SPEC CHECKSUMS:
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
Yoga: e6ecf3fa25af9d4c87e94ad7d5d292eedef49749
PODFILE CHECKSUM: 08b7d007885579803f4a8533ea82622e0abf9ea0
PODFILE CHECKSUM: 794df2878aa835db0bc03a96f2f040b5ffad064c
COCOAPODS: 1.11.3

138
ios/taskme.xcodeproj/project.pbxproj

@ -13,16 +13,16 @@ @@ -13,16 +13,16 @@
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
15A240E2A6D8A43F0ED0FB1D /* libPods-taskme-taskmeTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B98C6B3676786E12016A3B65 /* libPods-taskme-taskmeTests.a */; };
1CEA5DFB26FCA6F700BCC3E1 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CEA5DFA26FCA6F700BCC3E1 /* File.swift */; };
2987B7362760E7DD00D6426B /* Gilroy-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2987B7322760E7DD00D6426B /* Gilroy-Bold.ttf */; };
2987B7372760E7DD00D6426B /* Gilroy-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2987B7332760E7DD00D6426B /* Gilroy-Regular.ttf */; };
2987B7382760E7DD00D6426B /* Gilroy-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2987B7342760E7DD00D6426B /* Gilroy-Medium.ttf */; };
2987B7392760E7DD00D6426B /* Gilroy-Semibold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2987B7352760E7DD00D6426B /* Gilroy-Semibold.ttf */; };
5244945D26B7EA27006A5FAB /* fontello.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5244945C26B7EA27006A5FAB /* fontello.ttf */; };
6BACE8E4315CC96D239C790C /* libPods-taskme-taskmeTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F7B7289FDDFDA96CFD39C2F5 /* libPods-taskme-taskmeTests.a */; };
80515EE004B778197656D916 /* libPods-taskme.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 86A5942ED43616B459FA26D2 /* libPods-taskme.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
E1A9811C9E140ECC9EE00615 /* libPods-taskme.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A67EF2793DF34630DF8428E /* libPods-taskme.a */; };
F7524E431D1FCB68DF75F11A /* libPods-OneSignalNotificationServiceExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1875C61D4A5C25FC075EDF51 /* libPods-OneSignalNotificationServiceExtension.a */; };
A30533557E53E524448F251D /* libPods-OneSignalNotificationServiceExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CFB5E9E55206DFB36EF62435 /* libPods-OneSignalNotificationServiceExtension.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -57,10 +57,10 @@ @@ -57,10 +57,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
002266F6E63A359C134149B0 /* Pods-taskme-taskmeTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme-taskmeTests.debug.xcconfig"; path = "Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests.debug.xcconfig"; sourceTree = "<group>"; };
00E356EE1AD99517003FC87E /* taskmeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = taskmeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* taskmeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = taskmeTests.m; sourceTree = "<group>"; };
03BCF765BD982E47BB5B8AAF /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneSignalNotificationServiceExtension.release.xcconfig"; path = "Target Support Files/Pods-OneSignalNotificationServiceExtension/Pods-OneSignalNotificationServiceExtension.release.xcconfig"; sourceTree = "<group>"; };
04340E26B5C146E0AAF5497A /* FontAwesome5_Brands.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Brands.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf"; sourceTree = "<group>"; };
0480F71D27CBC33D0039631F /* taskme.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = taskme.entitlements; path = taskme/taskme.entitlements; sourceTree = "<group>"; };
0480F72227CBC3D10039631F /* OneSignalNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OneSignalNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@ -76,35 +76,35 @@ @@ -76,35 +76,35 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = taskme/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = taskme/main.m; sourceTree = "<group>"; };
14C92B86EBCC43CBA49665B8 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; };
1875C61D4A5C25FC075EDF51 /* libPods-OneSignalNotificationServiceExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OneSignalNotificationServiceExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; };
1CEA5DF926FCA6F600BCC3E1 /* taskme-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "taskme-Bridging-Header.h"; sourceTree = "<group>"; };
1CEA5DFA26FCA6F700BCC3E1 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
1DFD6A1EFFF3CB839B88D336 /* Pods-taskme-taskmeTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme-taskmeTests.release.xcconfig"; path = "Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests.release.xcconfig"; sourceTree = "<group>"; };
1F5EF60061E54FB0AF25C308 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; };
26D9C4DB7C57AD8DF41BBF0C /* Pods-taskme.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme.release.xcconfig"; path = "Target Support Files/Pods-taskme/Pods-taskme.release.xcconfig"; sourceTree = "<group>"; };
2929AE903C2818917F4F8BD3 /* Pods-taskme.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme.debug.xcconfig"; path = "Target Support Files/Pods-taskme/Pods-taskme.debug.xcconfig"; sourceTree = "<group>"; };
2987B7322760E7DD00D6426B /* Gilroy-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Gilroy-Bold.ttf"; path = "../src/assets/fonts/Gilroy-Bold.ttf"; sourceTree = "<group>"; };
2987B7332760E7DD00D6426B /* Gilroy-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Gilroy-Regular.ttf"; path = "../src/assets/fonts/Gilroy-Regular.ttf"; sourceTree = "<group>"; };
2987B7342760E7DD00D6426B /* Gilroy-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Gilroy-Medium.ttf"; path = "../src/assets/fonts/Gilroy-Medium.ttf"; sourceTree = "<group>"; };
2987B7352760E7DD00D6426B /* Gilroy-Semibold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Gilroy-Semibold.ttf"; path = "../src/assets/fonts/Gilroy-Semibold.ttf"; sourceTree = "<group>"; };
37D9710EF24F0880F098FE22 /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneSignalNotificationServiceExtension.release.xcconfig"; path = "Target Support Files/Pods-OneSignalNotificationServiceExtension/Pods-OneSignalNotificationServiceExtension.release.xcconfig"; sourceTree = "<group>"; };
317F6A85CB26B26FA7EF94B8 /* Pods-taskme-taskmeTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme-taskmeTests.debug.xcconfig"; path = "Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests.debug.xcconfig"; sourceTree = "<group>"; };
3E0132E085B040ECBA70742C /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = "<group>"; };
4D4A3C52CD04EF7DE81F26E9 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneSignalNotificationServiceExtension.debug.xcconfig"; path = "Target Support Files/Pods-OneSignalNotificationServiceExtension/Pods-OneSignalNotificationServiceExtension.debug.xcconfig"; sourceTree = "<group>"; };
5244945C26B7EA27006A5FAB /* fontello.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = fontello.ttf; path = ../src/assets/fonts/fontello.ttf; sourceTree = "<group>"; };
5F7AB8195E5548089203A788 /* Fontisto.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Fontisto.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf"; sourceTree = "<group>"; };
60AB903BA8B3443CB0797A7E /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; };
6268C41675EF4A2BB24E4DDE /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = taskme/LaunchScreen.storyboard; sourceTree = "<group>"; };
8A67EF2793DF34630DF8428E /* libPods-taskme.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-taskme.a"; sourceTree = BUILT_PRODUCTS_DIR; };
8C051622AF0774A320C586E0 /* Pods-taskme-taskmeTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme-taskmeTests.release.xcconfig"; path = "Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests.release.xcconfig"; sourceTree = "<group>"; };
86A5942ED43616B459FA26D2 /* libPods-taskme.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-taskme.a"; sourceTree = BUILT_PRODUCTS_DIR; };
918F5914B4544E6F9A0FB6C4 /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = "<group>"; };
A00A5743695C40A480A9D8CD /* AntDesign.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = AntDesign.ttf; path = "../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf"; sourceTree = "<group>"; };
AAC5712FBCC645558F9D6659 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; };
B98C6B3676786E12016A3B65 /* libPods-taskme-taskmeTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-taskme-taskmeTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
AB5CF4C2395C817E1EA4D407 /* Pods-taskme.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme.debug.xcconfig"; path = "Target Support Files/Pods-taskme/Pods-taskme.debug.xcconfig"; sourceTree = "<group>"; };
B02FD8E8B7408BE3460BA4E0 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneSignalNotificationServiceExtension.debug.xcconfig"; path = "Target Support Files/Pods-OneSignalNotificationServiceExtension/Pods-OneSignalNotificationServiceExtension.debug.xcconfig"; sourceTree = "<group>"; };
CA195349B72A48B4A46E3330 /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; };
CFB5E9E55206DFB36EF62435 /* libPods-OneSignalNotificationServiceExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OneSignalNotificationServiceExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DE06A1D2EC694C6CAB3459FA /* FontAwesome5_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Solid.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf"; sourceTree = "<group>"; };
E3A1F8EB6AEC40E899F663AD /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = "<group>"; };
E8EC73AD21F192967C9C8C5D /* Pods-taskme.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-taskme.release.xcconfig"; path = "Target Support Files/Pods-taskme/Pods-taskme.release.xcconfig"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
F0A3EAEF5BF94A2580145235 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = "<group>"; };
F7B7289FDDFDA96CFD39C2F5 /* libPods-taskme-taskmeTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-taskme-taskmeTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -112,7 +112,7 @@ @@ -112,7 +112,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
15A240E2A6D8A43F0ED0FB1D /* libPods-taskme-taskmeTests.a in Frameworks */,
6BACE8E4315CC96D239C790C /* libPods-taskme-taskmeTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -120,7 +120,7 @@ @@ -120,7 +120,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F7524E431D1FCB68DF75F11A /* libPods-OneSignalNotificationServiceExtension.a in Frameworks */,
A30533557E53E524448F251D /* libPods-OneSignalNotificationServiceExtension.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -128,7 +128,7 @@ @@ -128,7 +128,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E1A9811C9E140ECC9EE00615 /* libPods-taskme.a in Frameworks */,
80515EE004B778197656D916 /* libPods-taskme.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -182,9 +182,9 @@ @@ -182,9 +182,9 @@
isa = PBXGroup;
children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
1875C61D4A5C25FC075EDF51 /* libPods-OneSignalNotificationServiceExtension.a */,
8A67EF2793DF34630DF8428E /* libPods-taskme.a */,
B98C6B3676786E12016A3B65 /* libPods-taskme-taskmeTests.a */,
CFB5E9E55206DFB36EF62435 /* libPods-OneSignalNotificationServiceExtension.a */,
86A5942ED43616B459FA26D2 /* libPods-taskme.a */,
F7B7289FDDFDA96CFD39C2F5 /* libPods-taskme-taskmeTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
@ -254,12 +254,12 @@ @@ -254,12 +254,12 @@
B362F9321C4BC54C6EBF6F61 /* Pods */ = {
isa = PBXGroup;
children = (
4D4A3C52CD04EF7DE81F26E9 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */,
37D9710EF24F0880F098FE22 /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */,
2929AE903C2818917F4F8BD3 /* Pods-taskme.debug.xcconfig */,
26D9C4DB7C57AD8DF41BBF0C /* Pods-taskme.release.xcconfig */,
002266F6E63A359C134149B0 /* Pods-taskme-taskmeTests.debug.xcconfig */,
8C051622AF0774A320C586E0 /* Pods-taskme-taskmeTests.release.xcconfig */,
B02FD8E8B7408BE3460BA4E0 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */,
03BCF765BD982E47BB5B8AAF /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */,
AB5CF4C2395C817E1EA4D407 /* Pods-taskme.debug.xcconfig */,
E8EC73AD21F192967C9C8C5D /* Pods-taskme.release.xcconfig */,
317F6A85CB26B26FA7EF94B8 /* Pods-taskme-taskmeTests.debug.xcconfig */,
1DFD6A1EFFF3CB839B88D336 /* Pods-taskme-taskmeTests.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -271,12 +271,12 @@ @@ -271,12 +271,12 @@
isa = PBXNativeTarget;
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "taskmeTests" */;
buildPhases = (
05A63358E397D0C7F23A716D /* [CP] Check Pods Manifest.lock */,
C8804C3FD52E5B594CB3960B /* [CP] Check Pods Manifest.lock */,
00E356EA1AD99517003FC87E /* Sources */,
00E356EB1AD99517003FC87E /* Frameworks */,
00E356EC1AD99517003FC87E /* Resources */,
81AFD8B4B669B76565FC34DB /* [CP] Embed Pods Frameworks */,
C7F1A036CDBAB8D78CEF801C /* [CP] Copy Pods Resources */,
72054CECC87E3569C719C194 /* [CP] Embed Pods Frameworks */,
85CE6B7FF2C265C566098C42 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -292,7 +292,7 @@ @@ -292,7 +292,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 0480F72A27CBC3D10039631F /* Build configuration list for PBXNativeTarget "OneSignalNotificationServiceExtension" */;
buildPhases = (
203325252E357358819A84A8 /* [CP] Check Pods Manifest.lock */,
D605104B049CD82325F55389 /* [CP] Check Pods Manifest.lock */,
0480F71E27CBC3D10039631F /* Sources */,
0480F71F27CBC3D10039631F /* Frameworks */,
0480F72027CBC3D10039631F /* Resources */,
@ -310,15 +310,15 @@ @@ -310,15 +310,15 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "taskme" */;
buildPhases = (
F7944BC36807E9149D112EEE /* [CP] Check Pods Manifest.lock */,
198E5588489B15126261B13B /* [CP] Check Pods Manifest.lock */,
FD10A7F022414F080027D42C /* Start Packager */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
0480F72D27CBC3D10039631F /* Embed App Extensions */,
47FE39BEBA6C7E1BC744F8EA /* [CP] Embed Pods Frameworks */,
6D6EE9CE83351AABBA201734 /* [CP] Copy Pods Resources */,
CD6C5861975985BA6B46DA71 /* [CP] Embed Pods Frameworks */,
54D4F6C940C70151ED1A515B /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -421,7 +421,7 @@ @@ -421,7 +421,7 @@
shellPath = /bin/sh;
shellScript = "set -e\n\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
};
05A63358E397D0C7F23A716D /* [CP] Check Pods Manifest.lock */ = {
198E5588489B15126261B13B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -436,104 +436,104 @@ @@ -436,104 +436,104 @@
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-taskme-taskmeTests-checkManifestLockResult.txt",
"$(DERIVED_FILE_DIR)/Pods-taskme-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
203325252E357358819A84A8 /* [CP] Check Pods Manifest.lock */ = {
54D4F6C940C70151ED1A515B /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-OneSignalNotificationServiceExtension-checkManifestLockResult.txt",
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-resources.sh\"\n";
showEnvVarsInLog = 0;
};
47FE39BEBA6C7E1BC744F8EA /* [CP] Embed Pods Frameworks */ = {
72054CECC87E3569C719C194 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-frameworks-${CONFIGURATION}-input-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-frameworks-${CONFIGURATION}-output-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-frameworks.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
6D6EE9CE83351AABBA201734 /* [CP] Copy Pods Resources */ = {
85CE6B7FF2C265C566098C42 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-resources-${CONFIGURATION}-input-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-resources-${CONFIGURATION}-output-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-resources.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
81AFD8B4B669B76565FC34DB /* [CP] Embed Pods Frameworks */ = {
C8804C3FD52E5B594CB3960B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-taskme-taskmeTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-frameworks.sh\"\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
C7F1A036CDBAB8D78CEF801C /* [CP] Copy Pods Resources */ = {
CD6C5861975985BA6B46DA71 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-resources-${CONFIGURATION}-input-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-resources-${CONFIGURATION}-output-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme-taskmeTests/Pods-taskme-taskmeTests-resources.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-taskme/Pods-taskme-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
F7944BC36807E9149D112EEE /* [CP] Check Pods Manifest.lock */ = {
D605104B049CD82325F55389 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -548,7 +548,7 @@ @@ -548,7 +548,7 @@
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-taskme-checkManifestLockResult.txt",
"$(DERIVED_FILE_DIR)/Pods-OneSignalNotificationServiceExtension-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -621,7 +621,7 @@ @@ -621,7 +621,7 @@
/* Begin XCBuildConfiguration section */
00E356F61AD99517003FC87E /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 002266F6E63A359C134149B0 /* Pods-taskme-taskmeTests.debug.xcconfig */;
baseConfigurationReference = 317F6A85CB26B26FA7EF94B8 /* Pods-taskme-taskmeTests.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
@ -649,7 +649,7 @@ @@ -649,7 +649,7 @@
};
00E356F71AD99517003FC87E /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 8C051622AF0774A320C586E0 /* Pods-taskme-taskmeTests.release.xcconfig */;
baseConfigurationReference = 1DFD6A1EFFF3CB839B88D336 /* Pods-taskme-taskmeTests.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
@ -674,7 +674,7 @@ @@ -674,7 +674,7 @@
};
0480F72B27CBC3D10039631F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4D4A3C52CD04EF7DE81F26E9 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */;
baseConfigurationReference = B02FD8E8B7408BE3460BA4E0 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
@ -715,7 +715,7 @@ @@ -715,7 +715,7 @@
};
0480F72C27CBC3D10039631F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 37D9710EF24F0880F098FE22 /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */;
baseConfigurationReference = 03BCF765BD982E47BB5B8AAF /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
@ -756,7 +756,7 @@ @@ -756,7 +756,7 @@
};
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2929AE903C2818917F4F8BD3 /* Pods-taskme.debug.xcconfig */;
baseConfigurationReference = AB5CF4C2395C817E1EA4D407 /* Pods-taskme.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@ -794,7 +794,7 @@ @@ -794,7 +794,7 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 26D9C4DB7C57AD8DF41BBF0C /* Pods-taskme.release.xcconfig */;
baseConfigurationReference = E8EC73AD21F192967C9C8C5D /* Pods-taskme.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;

16
package-lock.json generated

@ -27,6 +27,7 @@ @@ -27,6 +27,7 @@
"axios": "^0.21.1",
"cachios": "^3.0.0",
"events": "^3.3.0",
"ffmpeg-kit-react-native": "^4.5.2",
"jet-tools": "^1.1.0",
"lodash": "^4.17.21",
"mime": "^3.0.0",
@ -6991,6 +6992,15 @@ @@ -6991,6 +6992,15 @@
"asap": "~2.0.3"
}
},
"node_modules/ffmpeg-kit-react-native": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/ffmpeg-kit-react-native/-/ffmpeg-kit-react-native-4.5.2.tgz",
"integrity": "sha512-eB0rvBtkSnwpCL9wh/gzv2HU/RA1SKsBQn8gwnWEuVPLiPxFayTI72n7apKeTyvM+OpNnIERhmhqzZxEq9ulCg==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/file-entry-cache": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
@ -20891,6 +20901,12 @@ @@ -20891,6 +20901,12 @@
"resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz",
"integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="
},
"ffmpeg-kit-react-native": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/ffmpeg-kit-react-native/-/ffmpeg-kit-react-native-4.5.2.tgz",
"integrity": "sha512-eB0rvBtkSnwpCL9wh/gzv2HU/RA1SKsBQn8gwnWEuVPLiPxFayTI72n7apKeTyvM+OpNnIERhmhqzZxEq9ulCg==",
"requires": {}
},
"file-entry-cache": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",

1
package.json

@ -32,6 +32,7 @@ @@ -32,6 +32,7 @@
"axios": "^0.21.1",
"cachios": "^3.0.0",
"events": "^3.3.0",
"ffmpeg-kit-react-native": "^4.5.2",
"jet-tools": "^1.1.0",
"lodash": "^4.17.21",
"mime": "^3.0.0",

7
src/api/chat-messages/requests.ts

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
import { prepareFormData } from './../../shared/helpers/fs.helpers'
import { ApiResponse } from '../http.types'
import * as req from './requests.interfaces'
import * as res from './responses.interfaces'
import http from '../http.service'
import { convertToFormData } from '@/shared/helpers/api.helpers'
import { prepareFormData } from '@/shared/helpers'
export const getChatMessagesListReq = (params: {
params: req.IFetchChatMessages
@ -103,7 +103,10 @@ export const forwardMessageReq = (data: req.IForwardMessage) => { @@ -103,7 +103,10 @@ export const forwardMessageReq = (data: req.IForwardMessage) => {
const createFormData = (data: req.ISendFileMessages) => {
const formData = new FormData()
formData.append('chatId', data.chatId.toString())
formData.append('replyToId', data.replyToId.toString())
if (data?.replyToId) {
formData.append('replyToId', data?.replyToId?.toString())
}
data.files.map(it => prepareFormData(it, formData))

9
src/modules/media/consts/record-audio-modal.consts.ts

@ -1,6 +1,9 @@ @@ -1,6 +1,9 @@
import { $size } from "@/shared"
import { Platform } from 'react-native'
import { $size } from '@/shared'
export const DEF_DB_LVL = -65
export const DEF_VOLUME_INDICATOR_SIZE = $size(65)
export const MAX_VOLUME_INDICATOR_SIZE = DEF_VOLUME_INDICATOR_SIZE + 35
export const INITIAL_PLAY_TIME = '00:00:00'
export const MAX_VOLUME_INDICATOR_SIZE =
DEF_VOLUME_INDICATOR_SIZE +
Platform.select({ ios: $size(35), android: $size(25) })
export const INITIAL_PLAY_TIME = '00:00'

380
src/modules/media/smart-components/record-audio-modal.smart-component.tsx

@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
import {
$size,
BottomModal,
IconComponent,
Txt,
useEventsListener,
useTheme,
$size,
BottomModal,
IconComponent,
Txt,
useEventsListener,
useTheme,
} from '@/shared'
import { PartialTheme } from '@/shared/themes/interfaces'
import React, { FC, useEffect, useMemo, useRef, useState } from 'react'
import { StyleSheet, TouchableOpacity, View } from 'react-native'
import React, { FC, useMemo, useRef, useState } from 'react'
import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native'
import Svg, { Path } from 'react-native-svg'
import RBSheet from 'react-native-raw-bottom-sheet'
import RNSoundLevel from 'react-native-sound-level'
@ -16,176 +16,206 @@ import Animated, * as RNReanimated from 'react-native-reanimated' @@ -16,176 +16,206 @@ import Animated, * as RNReanimated from 'react-native-reanimated'
import { mediaService } from '@/services/system'
import { RecordAudioModalSettings } from '../interfaces'
import {
DEF_DB_LVL,
DEF_VOLUME_INDICATOR_SIZE,
INITIAL_PLAY_TIME,
MAX_VOLUME_INDICATOR_SIZE,
DEF_DB_LVL,
DEF_VOLUME_INDICATOR_SIZE,
INITIAL_PLAY_TIME,
MAX_VOLUME_INDICATOR_SIZE,
} from '../consts'
export const RecordAudioModalSmart: FC = () => {
const { styles, theme } = useTheme(createStyles)
const [isRecording, setRecord] = useState<boolean>(false)
const [playTime, setPlayTime] = useState<string>(INITIAL_PLAY_TIME)
const [recordFilPath, setRecordFilePath] = useState<string>('')
const animationVal = RNReanimated.useSharedValue(DEF_DB_LVL)
const sheetRef = useRef<RBSheet | null>()
const settingsRef = useRef<RecordAudioModalSettings>({
send: null,
}).current
const animatedStyles = RNReanimated.useAnimatedStyle(() => {
const size = RNReanimated.interpolate(
animationVal.value,
[DEF_DB_LVL, 0],
[DEF_VOLUME_INDICATOR_SIZE, MAX_VOLUME_INDICATOR_SIZE],
)
return {
width: size,
height: size,
borderRadius: size / 2,
}
})
useEventsListener(
'openRecordVoiceModal',
data => {
sheetRef.current.open()
settingsRef.send = data.send
},
[sheetRef.current, settingsRef],
)
const onStartRecord = async () => {
setRecord(true)
RNSoundLevel.start()
await mediaService.onStartRecord()
mediaService.addRecordBackListener(({ currentPosition }) =>
setPlayTime(mediaService.formatRecordPlayTime(currentPosition)),
)
RNSoundLevel.onNewFrame = data => {
animationVal.value = RNReanimated.withSpring(data.value)
}
}
const onStopRecord = async () => {
setRecord(false)
RNReanimated.cancelAnimation(animationVal)
animationVal.value = RNReanimated.withSpring(DEF_DB_LVL)
RNSoundLevel.stop()
const path = await mediaService.onStopRecord()
setRecordFilePath(path)
}
const onClose = () => {
setPlayTime(INITIAL_PLAY_TIME)
onStopRecord()
}
const onCancel = () => {
setPlayTime(INITIAL_PLAY_TIME)
setRecordFilePath('')
}
const onConfirm = () => {
settingsRef?.send(recordFilPath)
sheetRef.current.close()
}
const timer = useMemo(() => <Txt>{playTime}</Txt>, [playTime])
return (
<BottomModal
sheetRef={ref => (sheetRef.current = ref)}
height={$size(200, 190)}
onClose={onClose}
containerStyle={styles.container}>
<Txt style={styles.title}>Запис повідомлення</Txt>
<View style={styles.actionsContainer}>
<TouchableOpacity disabled={isRecording} onPress={onCancel}>
<IconComponent
name="xcircle-1"
size={$size(23)}
color={theme?.chats?.message?.$btnSend}
/>
</TouchableOpacity>
<TouchableOpacity
style={styles.micContainer}
onPress={() =>
!isRecording ? onStartRecord() : onStopRecord()
}>
<View style={styles.micBtn}>
<IconComponent
name="microphone-1"
size={$size(23)}
color={theme?.chats?.message?.$btnSend}
/>
</View>
<Animated.View
style={[styles.micVolumeCircle, animatedStyles]}
/>
</TouchableOpacity>
<TouchableOpacity
disabled={!recordFilPath || isRecording}
onPress={onConfirm}>
<Svg width={$size(20)} height={$size(25)} fill="none">
<Path
d="M20.581 11.346 4.745 2.478a.75.75 0 0 0-1.072.906l2.987 8.364a.75.75 0 0 1 0 .504l-2.987 8.364a.75.75 0 0 0 1.072.907l15.836-8.868a.75.75 0 0 0 0-1.31v0ZM6.75 12h6"
stroke={theme?.chats?.message?.$btnSend}
strokeWidth={1.7}
strokeLinecap="round"
strokeLinejoin="round"
transform={`translate(${$size(1, 2)}, ${$size(
0.5,
1.5,
)}), scale(${$size(0.7, 0.85)})`}
/>
</Svg>
</TouchableOpacity>
</View>
<View>{timer}</View>
</BottomModal>
)
const { styles, theme } = useTheme(createStyles)
const [isRecording, setRecord] = useState<boolean>(false)
const [playTime, setPlayTime] = useState<string>(INITIAL_PLAY_TIME)
const [recordFilPath, setRecordFilePath] = useState<string>('')
const animationVal = RNReanimated.useSharedValue(DEF_DB_LVL)
const sheetRef = useRef<RBSheet>()
const settingsRef = useRef<RecordAudioModalSettings>({
send: null,
}).current
const animatedStyles = RNReanimated.useAnimatedStyle(() => {
const size = RNReanimated.interpolate(
animationVal.value,
[DEF_DB_LVL, 0],
[DEF_VOLUME_INDICATOR_SIZE, MAX_VOLUME_INDICATOR_SIZE],
)
return {
width: size,
height: size,
borderRadius: size / 2,
}
})
useEventsListener(
'openRecordVoiceModal',
data => {
sheetRef.current.open()
settingsRef.send = data.send
},
[sheetRef.current, settingsRef],
)
const iosRecordAnim = () =>
RNSoundLevel.onNewFrame = data => {
animationVal.value = RNReanimated.withSpring(data.value)
}
const androidRecordAnim = () => {
const animation = (toVal: number = MAX_VOLUME_INDICATOR_SIZE / 4) =>
RNReanimated.withTiming(toVal, {
duration: 1000,
}, (finish) => (finish && isRecording) && animation(DEF_VOLUME_INDICATOR_SIZE))
animationVal.value = RNReanimated.withRepeat(
animation(),
10000,
true,
)
}
const animationOnRecord = () =>
Platform.select({
ios: iosRecordAnim,
android: androidRecordAnim,
})()
const onStartRecord = async () => {
setRecord(true)
RNSoundLevel.start()
await mediaService.onStartRecord()
mediaService.addRecordBackListener(({ currentPosition }) => {
setPlayTime(
mediaService
.formatRecordPlayTime(currentPosition)
.slice(0, '00:00:00'.length - 3),
)
})
animationOnRecord()
}
const onStopRecord = async () => {
setRecord(false)
RNReanimated.cancelAnimation(animationVal)
animationVal.value = RNReanimated.withSpring(DEF_DB_LVL)
if (Platform.OS === 'ios') RNSoundLevel.stop()
const path = await mediaService.onStopRecord()
setRecordFilePath(path)
}
const onClose = () => {
setPlayTime(INITIAL_PLAY_TIME)
onStopRecord()
}
const onCancel = () => {
setPlayTime(INITIAL_PLAY_TIME)
setRecordFilePath('')
}
const onConfirm = () => {
settingsRef?.send(recordFilPath)
sheetRef.current.close()
}
const timer = useMemo(() => <Txt>{playTime}</Txt>, [playTime])
return (
<BottomModal
sheetRef={ref => (sheetRef.current = ref)}
height={$size(200, 190)}
onClose={onClose}
containerStyle={styles.container}>
<Txt style={styles.title}>Запис повідомлення</Txt>
<View style={styles.actionsContainer}>
<TouchableOpacity disabled={isRecording} onPress={onCancel}>
<IconComponent
name="xcircle-1"
size={$size(23)}
color={theme?.chats?.message?.$btnSend}
/>
</TouchableOpacity>
<TouchableOpacity
style={styles.micContainer}
onPress={() =>
!isRecording ? onStartRecord() : onStopRecord()
}>
<View style={styles.micBtn}>
<IconComponent
name="microphone-1"
size={$size(23)}
color={theme?.chats?.message?.$btnSend}
/>
</View>
<Animated.View
style={[styles.micVolumeCircle, animatedStyles]}
/>
</TouchableOpacity>
<TouchableOpacity
disabled={!recordFilPath || isRecording}
onPress={onConfirm}>
<Svg
width={$size(25)}
height={$size(25)}
fill="none"
viewBox={`0 0 ${$size(25)} ${$size(30)}`}>
<Path
d="M20.581 11.346 4.745 2.478a.75.75 0 0 0-1.072.906l2.987 8.364a.75.75 0 0 1 0 .504l-2.987 8.364a.75.75 0 0 0 1.072.907l15.836-8.868a.75.75 0 0 0 0-1.31v0ZM6.75 12h6"
stroke={theme?.chats?.message?.$btnSend}
strokeWidth={1.7}
strokeLinecap="round"
strokeLinejoin="round"
transform={`translate(${$size(1, 2)}, ${$size(
0.5,
1.5,
)}), scale(${$size(1, 0.85)})`}
/>
</Svg>
</TouchableOpacity>
</View>
<View>{timer}</View>
</BottomModal>
)
}
const createStyles = ({ chats: { sendVoiceMsg } }: PartialTheme) =>
StyleSheet.create({
container: {
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
title: {
top: $size(-35),
},
actionsContainer: {
width: '60%',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: $size(25),
},
micContainer: {
alignItems: 'center',
justifyContent: 'center',
},
micBtn: {
alignItems: 'center',
justifyContent: 'center',
zIndex: 1,
width: $size(52),
height: $size(52),
backgroundColor: sendVoiceMsg.micBtn.$bg,
borderRadius: $size(62) / 2,
},
micVolumeCircle: {
position: 'absolute',
backgroundColor: sendVoiceMsg.micBtn.$border,
},
})
StyleSheet.create({
container: {
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
title: {
top: $size(-35),
},
actionsContainer: {
width: '60%',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: $size(25),
},
micContainer: {
alignItems: 'center',
justifyContent: 'center',
},
micBtn: {
alignItems: 'center',
justifyContent: 'center',
zIndex: 1,
width: $size(52),
height: $size(52),
backgroundColor: sendVoiceMsg.micBtn.$bg,
borderRadius: $size(62) / 2,
},
micVolumeCircle: {
position: 'absolute',
backgroundColor: sendVoiceMsg.micBtn.$border,
},
})

14
src/services/domain/chat-messages.service.ts

@ -24,8 +24,8 @@ import { appEvents, IChatMessage } from '@/shared' @@ -24,8 +24,8 @@ import { appEvents, IChatMessage } from '@/shared'
import { runActionByType } from '@/shared/helpers'
import { SetUnreadMessagesCount } from '@/store/chats'
import { simpleDispatch } from '@/store/store-helpers'
import { Alert } from 'react-native'
import { fsService } from '../system'
import { Alert, Platform } from 'react-native'
import { fileConvertService, fsService } from '../system'
const fetchMessages = async (
params: { params: IFetchChatMessages },
@ -66,7 +66,15 @@ const sendImageMessage = async (data: ISendFileMessages) => { @@ -66,7 +66,15 @@ const sendImageMessage = async (data: ISendFileMessages) => {
const sendVoiceMsg = async (chatId: number, filePath: string) => {
try {
const record = await fsService.getFileStat(filePath)
const record = await fsService.getFileStat(Platform.select({
ios: await fileConvertService.convertM4aToMp4(filePath),
android: filePath
}))
record.type = `audio/${record.type}`
console.log({ record })
await sendAudioMessageReq({ chatId, files: [record] })
} catch (err) {

20
src/services/system/file-convert.service.ts

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
import { getDownloadDirectoryPath } from "@/shared/helpers";
import { FFmpegKit } from "ffmpeg-kit-react-native"
const convertM4aToMp4 = async (audioUri: string): Promise<string> => {
const outputName = 'record.mp3'
const directory = getDownloadDirectoryPath()
const outputUri = `file://${directory}/${outputName}`
try {
await FFmpegKit.execute(`-i ${audioUri} -c:a libmp3lame -q:a 8 ${outputUri}`)
} catch (err) {
console.log('convertM4aToMp4 ERR: ', err);
}
return outputUri;
}
export const fileConvertService = {
convertM4aToMp4
}

7
src/services/system/fs.service.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import { IFile } from '@/shared'
import {
getDownloadDirectoryPath,
createUniqueFileName,
getFileExtension,
getFileName,
@ -11,6 +12,7 @@ import RNFS from 'react-native-fs' @@ -11,6 +12,7 @@ import RNFS from 'react-native-fs'
import { Alert, Platform } from 'react-native'
import RNFetchBlob from 'rn-fetch-blob'
interface IWriteFileData {
content: string
fileName: string
@ -44,10 +46,7 @@ const getFileStat = async (filePath: string): Promise<IFile> => { @@ -44,10 +46,7 @@ const getFileStat = async (filePath: string): Promise<IFile> => {
const writeFile = (data: IWriteFileData) => {
return new Promise<string>((resolve, reject) => {
const directory = isAndroid(
RNFS.DownloadDirectoryPath,
RNFS.LibraryDirectoryPath,
)
const directory = getDownloadDirectoryPath()
const path = directory + `/${data.fileName}`
RNFS.writeFile(path, data.content, 'utf8')

3
src/services/system/index.ts

@ -5,4 +5,5 @@ export * from './storage.service' @@ -5,4 +5,5 @@ export * from './storage.service'
export * from './device-info.service'
export * from './real-time.service'
export * from './media.service'
export * from './fs.service'
export * from './fs.service'
export * from './file-convert.service'

5
src/services/system/media-permissions.service.ts

@ -81,6 +81,8 @@ const requestAudioRecordAndroidPermissions = async () => { @@ -81,6 +81,8 @@ const requestAudioRecordAndroidPermissions = async () => {
throw err
}
}
return true
}
const requestWriteExternalStorageAndroidPermissions = async () => {
@ -106,7 +108,7 @@ const requestWriteExternalStorageAndroidPermissions = async () => { @@ -106,7 +108,7 @@ const requestWriteExternalStorageAndroidPermissions = async () => {
}
const needMediaPermissions = () => {
return new Promise((resolve, reject) => {
return new Promise((_, reject) => {
Alert.alert(
'Доступ відсутній',
'Для використання цієї функції ви повинні надати дозвіл',
@ -123,7 +125,6 @@ const needMediaPermissions = () => { @@ -123,7 +125,6 @@ const needMediaPermissions = () => {
})
}
export const mediaPermissionsService = {
checkCameraPermissions,
requestAudioRecordAndroidPermissions,

81
src/services/system/media.service.ts

@ -1,14 +1,11 @@ @@ -1,14 +1,11 @@
import { Platform } from 'react-native'
import ImagePicker, { Options } from 'react-native-image-crop-picker'
import {
launchImageLibrary,
CameraOptions,
} from 'react-native-image-picker'
import { launchImageLibrary, CameraOptions } from 'react-native-image-picker'
import { PERMISSIONS } from 'react-native-permissions'
import { mediaPermissionsService } from './media-permissions.service'
import DocumentPicker from 'react-native-document-picker'
import { prepareFile, prepareFiles } from '@/shared/helpers'
import AudioRecorderPlayer from 'react-native-audio-recorder-player';
import AudioRecorderPlayer from 'react-native-audio-recorder-player'
interface IPickerProps {
width: number
@ -16,7 +13,7 @@ interface IPickerProps { @@ -16,7 +13,7 @@ interface IPickerProps {
cropperCircleOverlay?: boolean
}
const audioRecorderPlayer = new AudioRecorderPlayer();
const audioRecorderPlayer = new AudioRecorderPlayer()
const permissions = Platform.select({
ios: {
@ -134,38 +131,68 @@ const openGalleryPicker = async () => { @@ -134,38 +131,68 @@ const openGalleryPicker = async () => {
}
const onStartRecord = async () => {
await mediaPermissionsService.requestAudioRecordAndroidPermissions()
const uri = await audioRecorderPlayer.startRecorder();
try {
const hasPermissions = await mediaPermissionsService.requestAudioRecordAndroidPermissions()
if (!hasPermissions) return
return uri
};
const uri = await audioRecorderPlayer.startRecorder()
return uri
} catch (err) {
console.log('onStartRecord ERR: ', err)
}
}
const onStopRecord = async () => {
const result = await audioRecorderPlayer.stopRecorder();
audioRecorderPlayer.removeRecordBackListener();
return result
};
try {
const result = await audioRecorderPlayer.stopRecorder()
audioRecorderPlayer.removeRecordBackListener()
return result
} catch (err) {
console.log('onStopRecord ERR: ', err)
}
}
const onStartPlay = async (uri: string) => {
await audioRecorderPlayer.startPlayer(uri);
};
try {
await audioRecorderPlayer.startPlayer(uri)
} catch (err) {
console.log('onStartPlay ERR: ', err)
}
}
const onResumePlay = async () => {
await audioRecorderPlayer.resumePlayer()
try {
await audioRecorderPlayer.resumePlayer()
} catch (err) {
console.log('onResumePlay ERR: ', err)
}
}
const onPausePlay = async () => {
await audioRecorderPlayer.pausePlayer();
};
try {
await audioRecorderPlayer.pausePlayer()
} catch (err) {
console.log('onPausePlay ERR: ', err)
}
}
const seekToPlayer = async (position: number) => {
await audioRecorderPlayer.seekToPlayer(position)
try {
await audioRecorderPlayer.seekToPlayer(position)
} catch (err) {
console.log('seekToPlayer ERR: ', err)
}
}
const onStopPlay = async () => {
audioRecorderPlayer.stopPlayer();
audioRecorderPlayer.removePlayBackListener();
};
try {
await audioRecorderPlayer.stopPlayer()
audioRecorderPlayer.removePlayBackListener()
} catch (err) {
console.log('onStopPlay ERR: ', err)
}
}
export const mediaService = {
openCamera,
@ -175,7 +202,7 @@ export const mediaService = { @@ -175,7 +202,7 @@ export const mediaService = {
openFilesPicker,
launchDeviceCamera,
// Audio ====
// Audio ====
onStartRecord,
onStopRecord,
onStartPlay,
@ -185,5 +212,9 @@ export const mediaService = { @@ -185,5 +212,9 @@ export const mediaService = {
onStopPlay,
addRecordBackListener: audioRecorderPlayer.addRecordBackListener,
addPlayBackListener: audioRecorderPlayer.addPlayBackListener,
formatRecordPlayTime: audioRecorderPlayer.mmssss
/**
* @returns time record time in format '00:00:00'
*/
formatRecordPlayTime: audioRecorderPlayer.mmssss,
}

33
src/shared/components/plugins/chat/chat-item-audio.component.tsx

@ -1,13 +1,13 @@ @@ -1,13 +1,13 @@
import { $size } from '@/shared/helpers'
import { $size, getFileExtension, getFileName } from '@/shared/helpers'
import { useTheme } from '@/shared/hooks'
import { PartialTheme } from '@/shared/themes/interfaces'
import React, { FC, useEffect, useState } from 'react'
import { StyleSheet, TouchableOpacity, View } from 'react-native'
import { IconComponent } from '../../elements'
import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native'
import { ChatItem } from './chat-item.component'
import { IChatMessage } from './interfaces'
import { Slider } from '@miblanchard/react-native-slider'
import { mediaService } from '@/services/system'
import { fileConvertService, mediaService } from '@/services/system'
import { IconComponent } from '@/shared'
interface ChatItemAudioProps extends IChatMessage {
onLongPress?: () => void
@ -17,6 +17,7 @@ interface ChatItemAudioProps extends IChatMessage { @@ -17,6 +17,7 @@ interface ChatItemAudioProps extends IChatMessage {
export const ChatItemAudio: FC<ChatItemAudioProps> = props => {
const [currentPosition, setCurrentPosition] = useState<number>(0)
const [fileUri, setFileUri] = useState<string>('')
const [audioDuration, setDuration] = useState<number>(0)
const [isPlaying, setIsPlying] = useState<boolean>(false)
const [isPause, setIsPause] = useState<boolean>(false)
@ -26,12 +27,21 @@ export const ChatItemAudio: FC<ChatItemAudioProps> = props => { @@ -26,12 +27,21 @@ export const ChatItemAudio: FC<ChatItemAudioProps> = props => {
theme: { chats },
} = useTheme(createStyles)
const prepareFileUriToAndroid = async () => {
const fileExt = getFileExtension(getFileName({ path: props.content.fileUrl }))
if (fileExt === 'm4a') {
const preparedFileUri = await fileConvertService.convertM4aToMp4(props.content.fileUrl)
setFileUri(preparedFileUri)
}
}
const onPlay = async () => {
setIsPlying(true)
await mediaService.onStartPlay(props.content.fileUrl)
await mediaService.onStartPlay(fileUri)
mediaService.addPlayBackListener(e => {
setDuration(e.duration)
setCurrentPosition(e.currentPosition)
setDuration(Math.abs(e.duration))
setCurrentPosition(Math.abs(e.currentPosition))
if (e.currentPosition === e.duration) {
setIsPlying(false)
@ -68,6 +78,15 @@ export const ChatItemAudio: FC<ChatItemAudioProps> = props => { @@ -68,6 +78,15 @@ export const ChatItemAudio: FC<ChatItemAudioProps> = props => {
}
}, [currentPosition, audioDuration])
useEffect(() => {
if (Platform.OS === 'android') {
prepareFileUriToAndroid()
return
}
setFileUri(props.content.fileUrl)
}, [props.content.fileUrl])
return (
<ChatItem
{...props}

17
src/shared/helpers/fs.helpers.ts

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
import { Alert, Platform } from 'react-native'
import { DownloadDirectoryPath, LibraryDirectoryPath } from 'react-native-fs'
import { IFile } from '../interfaces'
import { isAndroid } from './platform.helper'
export const MAX_FILE_SIZE = 50000000
export const MAX_VIDEO_SIZE = 100000000
@ -17,11 +19,12 @@ export const getFileName = (file: any) => { @@ -17,11 +19,12 @@ export const getFileName = (file: any) => {
export const getFileExtension = (uri: string) => uri.split('.').pop()
export const getFileUri = (file: any) => {
return Platform.OS === 'android'
? file.path
: file.path.replace('file://', '')
}
export const getFileUri = (file: any): string =>
Platform.select<string>({
ios: file.path.replace('file://', ''),
android: file.path
})
export const prepareFile = (data: any): IFile => {
return {
@ -97,6 +100,10 @@ export const alertFileSizeExceeded = (files: IFile[]) => { @@ -97,6 +100,10 @@ export const alertFileSizeExceeded = (files: IFile[]) => {
Alert.alert(`Не вдалось віправити ${filesText}`, message)
}
export const getDownloadDirectoryPath = () => Platform.select({
ios: LibraryDirectoryPath,
android: DownloadDirectoryPath
})
export const createUniqueFileName = (fileName: string) => {
const arrFromName = fileName.split('.')
const ext = arrFromName[arrFromName.length - 1]

5
yarn.lock

@ -3877,6 +3877,11 @@ @@ -3877,6 +3877,11 @@
"setimmediate" "^1.0.5"
"ua-parser-js" "^0.7.18"
"ffmpeg-kit-react-native@^4.5.2":
"integrity" "sha512-eB0rvBtkSnwpCL9wh/gzv2HU/RA1SKsBQn8gwnWEuVPLiPxFayTI72n7apKeTyvM+OpNnIERhmhqzZxEq9ulCg=="
"resolved" "https://registry.npmjs.org/ffmpeg-kit-react-native/-/ffmpeg-kit-react-native-4.5.2.tgz"
"version" "4.5.2"
"file-entry-cache@^5.0.1":
"integrity" "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g=="
"resolved" "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz"

Loading…
Cancel
Save