Vitalik
8 months ago
38 changed files with 528 additions and 277 deletions
@ -1,7 +1,3 @@
@@ -1,7 +1,3 @@
|
||||
# API_URL=https://taskme-api.work-jetup.site |
||||
# SOCKET_URL=https://taskme-api.work-jetup.site |
||||
# ONE_SIGNAL_KEY=8b9066f5-8c3f-49f7-bef4-c5ab621f9d27 |
||||
|
||||
API_URL=http://localhost:3000 |
||||
SOCKET_URL=http://localhost:3000 |
||||
ONE_SIGNAL_KEY=8b9066f5-8c3f-49f7-bef4-c5ab621f9d27 |
||||
API_URL=https://taskme-api.work-jetup.site |
||||
SOCKET_URL=https://taskme-api.work-jetup.site |
||||
ONE_SIGNAL_KEY=8b9066f5-8c3f-49f7-bef4-c5ab621f9d27 |
||||
|
@ -1,4 +1,5 @@
@@ -1,4 +1,5 @@
|
||||
export enum CallTypesEnum { |
||||
INCOMING = 'incoming', |
||||
OUTGOING = 'outgoing', |
||||
SKIP = 'skipped', |
||||
} |
||||
|
@ -1,2 +1,4 @@
@@ -1,2 +1,4 @@
|
||||
export * from './use-call-data.hook' |
||||
export * from './use-call-from.hook' |
||||
export * from './use-call-streams.hook' |
||||
export * from './use-calls-history.hook' |
||||
|
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
import { MediaStream, mediaDevices } from 'react-native-webrtc' |
||||
import { create } from 'zustand' |
||||
import { callDataStoreHelper } from './use-call-data.hook' |
||||
|
||||
export interface ICallStreamsStore { |
||||
localStream: MediaStream |
||||
remoteStream: MediaStream |
||||
|
||||
setLocalStream: (localStream: MediaStream) => void |
||||
setRemoteStream: (remoteStream: MediaStream) => void |
||||
} |
||||
|
||||
const callsStreamStore = create<ICallStreamsStore>()(set => ({ |
||||
localStream: null, |
||||
remoteStream: null, |
||||
|
||||
setLocalStream(localStream) { |
||||
set({ localStream }) |
||||
}, |
||||
|
||||
setRemoteStream(remoteStream) { |
||||
set({ remoteStream }) |
||||
}, |
||||
})) |
||||
|
||||
export const useCallsStream = callsStreamStore |
||||
|
||||
export const callsStreamsCtr = () => callsStreamStore.getState() |
||||
|
||||
export const initCallsMediaDevices = async (peerConnection: any) => { |
||||
try { |
||||
const stream = await mediaDevices.getUserMedia({ |
||||
audio: true, |
||||
video: { |
||||
frameRate: 30, |
||||
facingMode: 'user', |
||||
}, |
||||
}) |
||||
|
||||
callsStreamsCtr().setLocalStream(stream) |
||||
stream.getTracks().forEach(track => { |
||||
peerConnection.addTrack(track as any, stream as any) |
||||
}) |
||||
} catch (e) { |
||||
console.log('eerror') |
||||
} |
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
import { getCallsListReq } from '@/api/calls/requests' |
||||
import { CallStatus, ICall, IUser, useFlatList } from '@/shared' |
||||
import store from '@/store' |
||||
import { selectId } from '@/store/account' |
||||
import moment from 'moment' |
||||
import { CallTypesEnum } from '../enums' |
||||
|
||||
export interface ICallListItem { |
||||
callId: number |
||||
date: string |
||||
title: string |
||||
avatarUrl?: string |
||||
type: CallTypesEnum |
||||
isMissed: boolean |
||||
targetUserId: number |
||||
} |
||||
|
||||
export const useCallHistory = () => { |
||||
const list = useFlatList<ICallListItem>({ |
||||
fetchItems: getCallsListReq, |
||||
needInit: false, |
||||
limit: 10, |
||||
serrializatorItems: transformItems, |
||||
clearWhenReload: false, |
||||
}) |
||||
|
||||
function transformItems(items: ICall[]) { |
||||
const result: ICallListItem[] = [] |
||||
const userId = selectId(store.getState()) |
||||
|
||||
items.map((it, i) => { |
||||
result[i] = transformItem(it, userId) |
||||
}) |
||||
|
||||
return result |
||||
} |
||||
|
||||
function transformItem(it: ICall, userId: number): ICallListItem { |
||||
const targetUser = it.users.find(it => it.id !== userId) |
||||
const info = targetUser.info |
||||
return { |
||||
callId: it.id, |
||||
title: `${info.firstName} ${info.lastName}`, |
||||
date: moment(new Date(it.startAt)).format('DD.MM.YY'), |
||||
avatarUrl: info.avatarUrl, |
||||
isMissed: it.status !== CallStatus.Finished, |
||||
targetUserId: targetUser.id, |
||||
type: getType(it, userId), |
||||
} |
||||
} |
||||
|
||||
function getType(it: ICall, userId: number) { |
||||
if (it.status !== CallStatus.Finished) { |
||||
if (userId !== it.initiatorUserId) { |
||||
return CallTypesEnum.SKIP |
||||
} |
||||
} |
||||
|
||||
return userId === it.initiatorUserId |
||||
? CallTypesEnum.INCOMING |
||||
: CallTypesEnum.OUTGOING |
||||
} |
||||
|
||||
return { |
||||
list, |
||||
} |
||||
} |
@ -1,64 +1,91 @@
@@ -1,64 +1,91 @@
|
||||
import { $size, Txt } from '@/shared' |
||||
import { $size, Loading, NotFound, Txt } from '@/shared' |
||||
import { SearchForm } from '@/shared/components/forms' |
||||
import { useTheme } from '@/shared/hooks/use-theme.hook' |
||||
import { PartialTheme } from '@/shared/themes/interfaces' |
||||
import React, { FC, useState } from 'react' |
||||
import { ScrollView, StyleSheet } from 'react-native' |
||||
import { FlatList } from 'react-native-gesture-handler' |
||||
import React, { FC, useCallback, useEffect, useRef, useState } from 'react' |
||||
import { StyleSheet, FlatList } from 'react-native' |
||||
import { CallSwipableRowCardSmart } from '.' |
||||
import { getCallsConfig } from '../configs/calls.config' |
||||
import { ICallListItem, useCallHistory } from '../hooks' |
||||
|
||||
export const CallSmartList: FC = () => { |
||||
const { styles, theme } = useTheme(createStyles) |
||||
|
||||
const { styles } = useTheme(createStyles) |
||||
const [searchString, setSearchString] = useState<string>() |
||||
const { list } = useCallHistory() |
||||
const { isLoading, isLoadingNext } = list |
||||
const timmer = useRef(null) |
||||
|
||||
useEffect(() => { |
||||
if (searchString !== undefined) { |
||||
clearTimeout(timmer.current) |
||||
|
||||
const callsData = getCallsConfig() |
||||
timmer.current = setTimeout(() => { |
||||
list.setLoadParams({ searchString }) |
||||
}, 400) |
||||
|
||||
const itemToRender = ({ item }) => ( |
||||
return () => { |
||||
clearTimeout(timmer.current) |
||||
} |
||||
} |
||||
}, [searchString]) |
||||
|
||||
const itemToRender = ({ item }: { item: ICallListItem }) => ( |
||||
<CallSwipableRowCardSmart |
||||
id={item.id} |
||||
callStatus={item.callType} |
||||
imageUrl={null} |
||||
callerFullName={`${item.firstName} ${item.lastName}`} |
||||
dateTime={item.dateTime} |
||||
id={item.callId} |
||||
callStatus={item.type} |
||||
imageUrl={item.avatarUrl} |
||||
callerFullName={item.title} |
||||
dateTime={item.date} |
||||
isMissed={item.isMissed} |
||||
onDelete={() => {}} |
||||
onPressCard={() => {}} |
||||
onPressCall={() => {}} |
||||
onDeleted={list.resetFlatList} |
||||
targetUserId={item.targetUserId} |
||||
/> |
||||
) |
||||
const keyExtractor = useCallback( |
||||
(item: ICallListItem) => String(item.callId), |
||||
[], |
||||
) |
||||
|
||||
return ( |
||||
<ScrollView> |
||||
<Txt |
||||
style={{ |
||||
color: theme.$textPrimary, |
||||
textAlign: 'center', |
||||
fontWeight: '500', |
||||
alignSelf: 'center', |
||||
}}> |
||||
Буде реалізовано в наступній версії додатку. |
||||
</Txt> |
||||
|
||||
{/* <SearchForm |
||||
placeholder="Знайти виклик" |
||||
searchValue={searchString} |
||||
onChange={setSearchString} |
||||
/> |
||||
|
||||
<FlatList |
||||
style={styles.listContainer} |
||||
data={callsData} |
||||
renderItem={itemToRender} |
||||
/> */} |
||||
</ScrollView> |
||||
<FlatList |
||||
style={styles.listContainer} |
||||
contentContainerStyle={styles.containerInner} |
||||
data={list.items} |
||||
renderItem={itemToRender} |
||||
showsVerticalScrollIndicator={false} |
||||
showsHorizontalScrollIndicator={false} |
||||
initialNumToRender={10} |
||||
onEndReached={list.loadMore} |
||||
keyExtractor={keyExtractor} |
||||
refreshing={!searchString && list.isLoading} |
||||
onRefresh={list.resetFlatList} |
||||
ListFooterComponent={() => { |
||||
if (!isLoading && isLoadingNext) { |
||||
return <Loading /> |
||||
} |
||||
if (isLoading) { |
||||
return null |
||||
} |
||||
if (list.isEmpty) { |
||||
return <NotFound text="Виклики не знайдені" /> |
||||
} |
||||
}} |
||||
ListHeaderComponent={ |
||||
<SearchForm |
||||
placeholder="Знайти виклик" |
||||
searchValue={searchString} |
||||
onChange={setSearchString} |
||||
/> |
||||
} |
||||
/> |
||||
) |
||||
} |
||||
|
||||
const createStyles = (theme: PartialTheme) => |
||||
const createStyles = () => |
||||
StyleSheet.create({ |
||||
listContainer: { |
||||
marginBottom: $size(25, 23), |
||||
// marginBottom: $size(25, 23),
|
||||
flex: 1, |
||||
}, |
||||
containerInner: { |
||||
paddingBottom: 20, |
||||
}, |
||||
}) |
||||
|
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
export enum CallStatus { |
||||
New = 'n', |
||||
InProccess = 'i', |
||||
Canceled = 'c', |
||||
Finished = 'f', |
||||
} |
@ -1,18 +1,19 @@
@@ -1,18 +1,19 @@
|
||||
export * from './route-key.enum' |
||||
export * from './navigation-module-key.enum' |
||||
export * from './exception-keys.enum' |
||||
export * from './storage-keys.enum' |
||||
export * from './user.enum' |
||||
export * from './taxonomies.enum' |
||||
export * from './task-status.enum' |
||||
export * from './task-actions.enum' |
||||
export * from './actions-queue-type.enum' |
||||
export * from './btns-type.enum' |
||||
export * from './call-status.enum' |
||||
export * from './chat-bg.enum' |
||||
export * from './task-events.enum' |
||||
export * from './notification.enum' |
||||
export * from './chat.enums' |
||||
export * from './btns-type.enum' |
||||
export * from './actions-queue-type.enum' |
||||
export * from './entity-type.enum' |
||||
export * from './permissions.enum' |
||||
export * from './error-message.enum' |
||||
export * from './file-type.enum' |
||||
export * from './exception-keys.enum' |
||||
export * from './file-type.enum' |
||||
export * from './navigation-module-key.enum' |
||||
export * from './notification.enum' |
||||
export * from './permissions.enum' |
||||
export * from './route-key.enum' |
||||
export * from './storage-keys.enum' |
||||
export * from './task-actions.enum' |
||||
export * from './task-events.enum' |
||||
export * from './task-status.enum' |
||||
export * from './taxonomies.enum' |
||||
export * from './user.enum' |
||||
|
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
import { CallStatus } from '../enums' |
||||
import { IUser } from './user.interfaces' |
||||
|
||||
export interface ICall { |
||||
id: number |
||||
usersIds: number[] |
||||
initiatorUserId: number |
||||
finishedAt: string |
||||
startAt: string |
||||
|
||||
status: CallStatus |
||||
|
||||
createdAt: string |
||||
updatedAt: string |
||||
|
||||
users?: IUser[] |
||||
} |
@ -1,15 +1,18 @@
@@ -1,15 +1,18 @@
|
||||
export * from './routing.interfaces' |
||||
export * from './token-pair.interfaces' |
||||
export * from './user.interfaces' |
||||
export * from './styles.interfaces' |
||||
export * from './taxonomy.interfaces' |
||||
export * from './contact.interfaces' |
||||
export * from './pagination.interfaces' |
||||
export * from './tasks.interfaces' |
||||
export * from './call.inteface' |
||||
export * from './chats.interfaces' |
||||
export * from './comments.interfaces' |
||||
export * from './configs.interfaces' |
||||
export * from './contact.interfaces' |
||||
export * from './drawer.interface' |
||||
export * from './entities' |
||||
export * from './factories.interfaces' |
||||
export * from './options.interfaces' |
||||
export * from './notification.interfaces' |
||||
export * from './chats.interfaces' |
||||
export * from './media.interfaces' |
||||
export * from './configs.interfaces' |
||||
export * from './notification.interfaces' |
||||
export * from './options.interfaces' |
||||
export * from './pagination.interfaces' |
||||
export * from './routing.interfaces' |
||||
export * from './styles.interfaces' |
||||
export * from './tasks.interfaces' |
||||
export * from './taxonomy.interfaces' |
||||
export * from './token-pair.interfaces' |
||||
export * from './user.interfaces' |
||||
|
Loading…
Reference in new issue