Browse Source

fix | calls bugs

master
Vitalik 7 months ago
parent
commit
85ef54330f
  1. 12
      .env.production
  2. 2
      android/app/build.gradle
  3. 28
      ios/taskme2.xcodeproj/project.pbxproj
  4. 6
      src/api/auth/requests.ts
  5. 7
      src/api/calls/requests.ts
  6. 11
      src/modules/calls/core/stop-call.ts
  7. 2
      src/modules/calls/screens/call/index.tsx
  8. 20
      src/modules/calls/services/call.service.ts
  9. 21
      src/modules/calls/services/callkeep/callkeep-root.service.ts
  10. 4
      src/modules/calls/services/calls-events.service.ts
  11. 4
      src/modules/calls/smart-components/call-swipable-row-card.smart-component.tsx
  12. 2
      src/modules/root/index.tsx
  13. 6
      src/services/domain/auth.service.ts
  14. 3
      src/services/system/real-time.service.ts
  15. 1
      src/shared/dto/account.dtos.ts
  16. 1
      src/shared/events/index.ts

12
.env.production

@ -1,7 +1,7 @@
# API_URL=https://tasks-api.rwsbank.com.ua API_URL=https://tasks-api.rwsbank.com.ua
# SOCKET_URL=https://tasks-api.rwsbank.com.ua SOCKET_URL=https://tasks-api.rwsbank.com.ua
# ONE_SIGNAL_KEY=5e1a5e18-33e5-4ed3-8423-45b1abc354c6 ONE_SIGNAL_KEY=5e1a5e18-33e5-4ed3-8423-45b1abc354c6
API_URL=https://taskme-api.work-jetup.site # API_URL=https://taskme-api.work-jetup.site
SOCKET_URL=https://taskme-api.work-jetup.site # SOCKET_URL=https://taskme-api.work-jetup.site
ONE_SIGNAL_KEY=8b9066f5-8c3f-49f7-bef4-c5ab621f9d27 # ONE_SIGNAL_KEY=8b9066f5-8c3f-49f7-bef4-c5ab621f9d27

2
android/app/build.gradle

@ -26,7 +26,7 @@ android {
applicationId "com.app.task_me" applicationId "com.app.task_me"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 228 versionCode 229
versionName "2.3" versionName "2.3"
resValue "string", "build_config_package", "com.app.task_me" resValue "string", "build_config_package", "com.app.task_me"
} }

28
ios/taskme2.xcodeproj/project.pbxproj

@ -753,7 +753,10 @@
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
); );
OTHER_LDFLAGS = "$(inherited) "; OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
}; };
@ -768,7 +771,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = taskme2/taskme2Stage.Debug.entitlements; CODE_SIGN_ENTITLEMENTS = taskme2/taskme2Stage.Debug.entitlements;
CURRENT_PROJECT_VERSION = 28; CURRENT_PROJECT_VERSION = 29;
DEVELOPMENT_TEAM = HQ3J3TDPR2; DEVELOPMENT_TEAM = HQ3J3TDPR2;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
@ -1036,7 +1039,10 @@
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
); );
OTHER_LDFLAGS = "$(inherited) "; OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
@ -1052,7 +1058,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = taskme2/taskme2Stage.Release.entitlements; CODE_SIGN_ENTITLEMENTS = taskme2/taskme2Stage.Release.entitlements;
CURRENT_PROJECT_VERSION = 28; CURRENT_PROJECT_VERSION = 29;
DEVELOPMENT_TEAM = HQ3J3TDPR2; DEVELOPMENT_TEAM = HQ3J3TDPR2;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -1332,7 +1338,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = taskme2/taskme2.entitlements; CODE_SIGN_ENTITLEMENTS = taskme2/taskme2.entitlements;
CURRENT_PROJECT_VERSION = 28; CURRENT_PROJECT_VERSION = 29;
DEVELOPMENT_TEAM = HQ3J3TDPR2; DEVELOPMENT_TEAM = HQ3J3TDPR2;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
@ -1470,7 +1476,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = taskme2/taskme2.entitlements; CODE_SIGN_ENTITLEMENTS = taskme2/taskme2.entitlements;
CURRENT_PROJECT_VERSION = 28; CURRENT_PROJECT_VERSION = 29;
DEVELOPMENT_TEAM = HQ3J3TDPR2; DEVELOPMENT_TEAM = HQ3J3TDPR2;
HEADER_SEARCH_PATHS = ( HEADER_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -1674,7 +1680,10 @@
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
); );
OTHER_LDFLAGS = "$(inherited) "; OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
}; };
@ -1752,7 +1761,10 @@
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
); );
OTHER_LDFLAGS = "$(inherited) "; OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;

6
src/api/auth/requests.ts

@ -26,8 +26,6 @@ export const resetSessionReq = (
return axiosInstance.post('/app/auth/refresh-token', params) return axiosInstance.post('/app/auth/refresh-token', params)
} }
export const signOut = ( export const signOut = (params: ILogoutPayload): ApiResponse<void> => {
params: ILogoutPayload, return http.post<void>('auth/logout', params)
): ApiResponse<IAuthSuccessResponse> => {
return http.post<IAuthSuccessResponse>('auth/logout', params)
} }

7
src/api/calls/requests.ts

@ -23,6 +23,11 @@ export const iceCandidateReq = (payload: IIceCandidatePayload) => {
export const cancelCallReq = (payload: ICancelCallPayload) => { export const cancelCallReq = (payload: ICancelCallPayload) => {
return api.post('calls/cancel', payload, {}, '') return api.post('calls/cancel', payload, {}, '')
} }
export const rejectCallReq = (payload: ICancelCallPayload) => {
return api.post('calls/reject', payload, {}, '')
}
export const finishCallReq = (payload: IFinishCallPayload) => { export const finishCallReq = (payload: IFinishCallPayload) => {
return api.post('calls/finish', payload, {}, '') return api.post('calls/finish', payload, {}, '')
} }
@ -31,7 +36,7 @@ export const getCallsListReq = (params: any) => {
return api.get('calls', params, '') return api.get('calls', params, '')
} }
export const deleteCallHistoryReq = (callId: number) => { export const deleteCallHistoryReq = (callId: string) => {
return api.delete(`calls/history/${callId}`, null, '') return api.delete(`calls/history/${callId}`, null, '')
} }

11
src/modules/calls/core/stop-call.ts

@ -1,6 +1,7 @@
import { finishCallReq } from '@/api/calls/requests' import { finishCallReq } from '@/api/calls/requests'
import { CallDataStore, ICallStreamsStore } from '../hooks' import { CallDataStore, ICallStreamsStore } from '../hooks'
import { MediaStream } from 'react-native-webrtc' import { MediaStream } from 'react-native-webrtc'
import inCallManager from 'react-native-incall-manager'
export class StopCall { export class StopCall {
constructor( constructor(
@ -20,9 +21,17 @@ export class StopCall {
await finishCallReq({ await finishCallReq({
callId: this.callDataStore.callId, callId: this.callDataStore.callId,
}).catch(console.log) }).catch(console.log)
// inCallManager.stop()
this.peerConnection.close() this.peerConnection.close()
this.stopStreams() this.stopStreams()
try {
inCallManager.stopRingback()
inCallManager.stopRingtone()
inCallManager.stop()
} catch (e) {
console.log('incallmeneger', e)
}
} }
private stopStreams() { private stopStreams() {

2
src/modules/calls/screens/call/index.tsx

@ -93,7 +93,7 @@ export const CallScreen = () => {
), ),
[CallMod.Finished]: ( [CallMod.Finished]: (
<CallBackground <CallBackground
title={'Звінок завершенно'} title={'Виклик завершенно'}
avatarImageUrl={avatarImageUrl} avatarImageUrl={avatarImageUrl}
needOverlay={false} needOverlay={false}
showAvatar={false}> showAvatar={false}>

20
src/modules/calls/services/call.service.ts

@ -8,7 +8,14 @@ import { StopCall } from '../core/stop-call'
import { cancelCallReq } from '@/api/calls/requests' import { cancelCallReq } from '@/api/calls/requests'
import { RTCSessionDescription } from 'react-native-webrtc' import { RTCSessionDescription } from 'react-native-webrtc'
import { callKeepService } from './callkeep' import { callKeepService } from './callkeep'
import inCallManager from 'react-native-incall-manager'
class CallService extends CallRoot { class CallService extends CallRoot {
constructor() {
super()
inCallManager.stopRingback()
}
public async proccesIncome(data: any) { public async proccesIncome(data: any) {
const peerConnection = await peerConnectionService.createIns() const peerConnection = await peerConnectionService.createIns()
@ -32,6 +39,7 @@ class CallService extends CallRoot {
public async processStart(targetUserId: number) { public async processStart(targetUserId: number) {
try { try {
inCallManager.start({ media: 'audio', ringback: '_BUNDLE_' })
const peerConnection = await peerConnectionService.createIns() const peerConnection = await peerConnectionService.createIns()
useCallDataStore.getState().startCall(targetUserId, peerConnection) useCallDataStore.getState().startCall(targetUserId, peerConnection)
NavigationService.navigate(RouteKey.Call, {}) NavigationService.navigate(RouteKey.Call, {})
@ -53,15 +61,27 @@ class CallService extends CallRoot {
public async finishCall() { public async finishCall() {
useCallDataStore.setState(useCallDataStore.getInitialState()) useCallDataStore.setState(useCallDataStore.getInitialState())
NavigationService.goBack() NavigationService.goBack()
callKeepService.stop()
} }
public async cancel() { public async cancel() {
try {
inCallManager.stopRingback()
} catch (e) {}
await cancelCallReq({ await cancelCallReq({
callId: useCallDataStore.getState().callId, callId: useCallDataStore.getState().callId,
}).catch(console.log) }).catch(console.log)
new StopCall(useCallDataStore.getState, callsStreamsCtr).stop() new StopCall(useCallDataStore.getState, callsStreamsCtr).stop()
useCallDataStore.setState(useCallDataStore.getInitialState()) useCallDataStore.setState(useCallDataStore.getInitialState())
callKeepService.stop()
NavigationService.goBack()
}
public async onRejectedByAnotherUser() {
inCallManager.stopRingback()
useCallDataStore.setState(useCallDataStore.getInitialState())
callKeepService.stop()
NavigationService.goBack() NavigationService.goBack()
} }
} }

21
src/modules/calls/services/callkeep/callkeep-root.service.ts

@ -1,9 +1,14 @@
import { getCallReq, getIncomeDataReq } from '@/api/calls/requests' import {
getCallReq,
getIncomeDataReq,
rejectCallReq,
} from '@/api/calls/requests'
import RNCallKeep from 'react-native-callkeep' import RNCallKeep from 'react-native-callkeep'
import { CallStatus, appEvents } from '@/shared' import { CallStatus, appEvents } from '@/shared'
import { DeviceInfoService } from '@/services/system' import { DeviceInfoService } from '@/services/system'
import { CallRoot } from '../call-root.service' import { CallRoot } from '../call-root.service'
import { useLocalStream } from '../../hooks' import { useLocalStream } from '../../hooks'
import { callService } from '../call.service'
export class CallKeepRootService extends CallRoot { export class CallKeepRootService extends CallRoot {
protected accountInited = false protected accountInited = false
@ -86,7 +91,7 @@ export class CallKeepRootService extends CallRoot {
const { data: call } = await getCallReq(data.callUUID) const { data: call } = await getCallReq(data.callUUID)
if (call.status !== CallStatus.New) { if (call.status !== CallStatus.New) {
appEvents.emit('openInfoModal', { appEvents.emit('openInfoModal', {
title: 'Звінок вже завершився', title: 'Дзвінок вже завершився',
message: message:
'Ініціатор скасував виклик або виклик був прийнятий на іншому девайсі', 'Ініціатор скасував виклик або виклик був прийнятий на іншому девайсі',
}) })
@ -111,8 +116,12 @@ export class CallKeepRootService extends CallRoot {
await getIncomeDataReq(payload.callUUID, id) await getIncomeDataReq(payload.callUUID, id)
} }
protected async onEnd() { protected async onEnd({ callUUID }) {
console.log('onend') if (!this.store.callId) {
await rejectCallReq({
callId: callUUID,
})
}
} }
protected async changeMuted({ muted }) { protected async changeMuted({ muted }) {
@ -135,7 +144,9 @@ export class CallKeepRootService extends CallRoot {
} }
public async stop() { public async stop() {
RNCallKeep.endCall(this.store.callId) if (this.store.callId) {
RNCallKeep.endCall(this.store.callId)
}
RNCallKeep.endAllCalls() RNCallKeep.endAllCalls()
} }

4
src/modules/calls/services/calls-events.service.ts

@ -35,12 +35,14 @@ class CallsEventsService extends CallRoot {
}) })
socketEvents.on('calls/answered-by-another-device', async data => { socketEvents.on('calls/answered-by-another-device', async data => {
console.log('calls/answered-by-another-device', data)
const deviceId = await DeviceInfoService.getDeviceUniqueId() const deviceId = await DeviceInfoService.getDeviceUniqueId()
if (deviceId !== data.deviceUuid) { if (deviceId !== data.deviceUuid) {
RNCallKeep.endAllCalls() RNCallKeep.endAllCalls()
} }
}) })
socketEvents.on('calls/rejected', async () => {
callService.onRejectedByAnotherUser()
})
} }
private proccessIceCandidates() { private proccessIceCandidates() {

4
src/modules/calls/smart-components/call-swipable-row-card.smart-component.tsx

@ -10,7 +10,7 @@ import { deleteCallHistoryReq } from '@/api/calls/requests'
import { callService } from '../services' import { callService } from '../services'
interface IProps { interface IProps {
id: number id: string
callerFullName: string callerFullName: string
imageUrl?: string imageUrl?: string
callStatus: CallTypesEnum callStatus: CallTypesEnum
@ -32,7 +32,7 @@ export const CallSwipableRowCardSmart: FC<IProps> = props => {
} }
const handlePressCard = () => { const handlePressCard = () => {
nav.navigate(RouteKey.ContactDetail, { contactId: props.id }) nav.navigate(RouteKey.ContactDetail, { contactId: props.targetUserId })
} }
const handlePressCall = () => { const handlePressCall = () => {

2
src/modules/root/index.tsx

@ -39,8 +39,6 @@ import { StyleSheet } from 'react-native'
import { PartialTheme } from '@/shared/themes/interfaces' import { PartialTheme } from '@/shared/themes/interfaces'
import { useAppBadge, useAppSocketListener, useNetConnect } from './hooks' import { useAppBadge, useAppSocketListener, useNetConnect } from './hooks'
import { PreviewFileModal, LoaderModal } from '@/shared/components/modals' import { PreviewFileModal, LoaderModal } from '@/shared/components/modals'
import { IncomingCallWidget } from '../calls/widgets'
import '@/modules/calls/core/call-events-listener'
export const Navigation: FC = () => { export const Navigation: FC = () => {
const activeModule = useSelector(selectActiveNavigationModule) const activeModule = useSelector(selectActiveNavigationModule)

6
src/services/domain/auth.service.ts

@ -142,7 +142,11 @@ const logout = async (refreshToken: string) => {
try { try {
const isSignedOutOnline = await accManager.signOutOnline.bind( const isSignedOutOnline = await accManager.signOutOnline.bind(
accManager, accManager,
)({ refreshToken }) {
refreshToken,
deviceUuid: await DeviceInfoService.getDeviceUniqueId(),
},
)()
await onLogout() await onLogout()
if (!isSignedOutOnline) if (!isSignedOutOnline)

3
src/services/system/real-time.service.ts

@ -19,8 +19,6 @@ export class SocketIo {
secure: true, secure: true,
reconnectionAttempts: 10, reconnectionAttempts: 10,
auth(cb) { auth(cb) {
const token = store()?.getState()?.auth?.accessToken
console.log('token', token)
cb({ accessToken: store()?.getState()?.auth?.accessToken }) cb({ accessToken: store()?.getState()?.auth?.accessToken })
}, },
}) })
@ -125,6 +123,7 @@ export class SocketIo {
this._onSocketSendEvent('call/ICEcandidate') this._onSocketSendEvent('call/ICEcandidate')
this._onSocketSendEvent('call/canceled') this._onSocketSendEvent('call/canceled')
this._onSocketSendEvent('calls/answered-by-another-device') this._onSocketSendEvent('calls/answered-by-another-device')
this._onSocketSendEvent('calls/rejected')
this._on('error/join-user', async () => { this._on('error/join-user', async () => {
await authService.refreshSession() await authService.refreshSession()

1
src/shared/dto/account.dtos.ts

@ -24,4 +24,5 @@ export class UpdateAccountPayloadDto {
export class SignOutPayloadDto { export class SignOutPayloadDto {
refreshToken: string refreshToken: string
deviceUuid?: string
} }

1
src/shared/events/index.ts

@ -254,6 +254,7 @@ export type SocketEvents = {
'calls/answered-by-another-device': { 'calls/answered-by-another-device': {
deviceUuid: string deviceUuid: string
} }
'calls/rejected': {}
} }
export const appEvents = new Events<AppEvents>() export const appEvents = new Events<AppEvents>()

Loading…
Cancel
Save