Shared Media: Add Voice tab (#1437)
This commit is contained in:
parent
364f2d9930
commit
d677200ec0
@ -288,7 +288,7 @@ export type ApiReplyKeyboard = {
|
|||||||
[K in 'inlineButtons' | 'keyboardButtons']?: ApiKeyboardButtons;
|
[K in 'inlineButtons' | 'keyboardButtons']?: ApiKeyboardButtons;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ApiMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'profilePhoto';
|
export type ApiMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'voice' | 'profilePhoto';
|
||||||
export type ApiGlobalMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
export type ApiGlobalMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
|
|
||||||
export type ApiReportReason = 'spam' | 'violence' | 'pornography' | 'childAbuse'
|
export type ApiReportReason = 'spam' | 'violence' | 'pornography' | 'childAbuse'
|
||||||
|
|||||||
@ -279,7 +279,7 @@ const Audio: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const contentClassName = buildClassName('content', withSeekline && 'with-seekline');
|
const contentClassName = buildClassName('content', withSeekline && 'with-seekline');
|
||||||
|
|
||||||
function renderSearchResult() {
|
function renderWithTitle() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={contentClassName}>
|
<div className={contentClassName}>
|
||||||
@ -355,12 +355,13 @@ const Audio: FC<OwnProps> = ({
|
|||||||
<i className={isDownloadStarted ? 'icon-close' : 'icon-arrow-down'} />
|
<i className={isDownloadStarted ? 'icon-close' : 'icon-arrow-down'} />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{origin === AudioOrigin.Search && renderSearchResult()}
|
{origin === AudioOrigin.Search && renderWithTitle()}
|
||||||
{origin !== AudioOrigin.Search && audio && renderAudio(
|
{origin !== AudioOrigin.Search && audio && renderAudio(
|
||||||
lang, audio, duration, isPlaying, playProgress, bufferedProgress, seekerRef, (isDownloadStarted || isUploading),
|
lang, audio, duration, isPlaying, playProgress, bufferedProgress, seekerRef, (isDownloadStarted || isUploading),
|
||||||
date, transferProgress, onDateClick ? handleDateClick : undefined,
|
date, transferProgress, onDateClick ? handleDateClick : undefined,
|
||||||
)}
|
)}
|
||||||
{origin !== AudioOrigin.Search && voice && renderVoice(voice, renderedWaveform, playProgress, isMediaUnread)}
|
{origin === AudioOrigin.SharedMedia && voice && renderWithTitle()}
|
||||||
|
{origin === AudioOrigin.Inline && voice && renderVoice(voice, renderedWaveform, playProgress, isMediaUnread)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -57,7 +57,7 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
.Tab {
|
.Tab {
|
||||||
padding: 1rem .25rem;
|
padding: 1rem .75rem;
|
||||||
i {
|
i {
|
||||||
bottom: -1rem;
|
bottom: -1rem;
|
||||||
}
|
}
|
||||||
@ -105,7 +105,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.audio-list {
|
&.audio-list,
|
||||||
|
&.voice-list {
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
|
|
||||||
& .Audio {
|
& .Audio {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
ApiMessage,
|
ApiMessage,
|
||||||
ApiChatMember,
|
ApiChatMember,
|
||||||
ApiUser,
|
ApiUser,
|
||||||
MAIN_THREAD_ID,
|
MAIN_THREAD_ID, ApiChat,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import { GlobalActions } from '../../global/types';
|
import { GlobalActions } from '../../global/types';
|
||||||
import {
|
import {
|
||||||
@ -33,6 +33,7 @@ import {
|
|||||||
} from '../../modules/selectors';
|
} from '../../modules/selectors';
|
||||||
import { pick } from '../../util/iteratees';
|
import { pick } from '../../util/iteratees';
|
||||||
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
import { captureEvents, SwipeDirection } from '../../util/captureEvents';
|
||||||
|
import { getSenderName } from '../left/search/helpers/getSenderName';
|
||||||
import useCacheBuster from '../../hooks/useCacheBuster';
|
import useCacheBuster from '../../hooks/useCacheBuster';
|
||||||
import useProfileViewportIds from './hooks/useProfileViewportIds';
|
import useProfileViewportIds from './hooks/useProfileViewportIds';
|
||||||
import useProfileState from './hooks/useProfileState';
|
import useProfileState from './hooks/useProfileState';
|
||||||
@ -78,7 +79,8 @@ type StateProps = {
|
|||||||
canAddMembers?: boolean;
|
canAddMembers?: boolean;
|
||||||
canDeleteMembers?: boolean;
|
canDeleteMembers?: boolean;
|
||||||
members?: ApiChatMember[];
|
members?: ApiChatMember[];
|
||||||
usersById?: Record<number, ApiUser>;
|
chatsById: Record<number, ApiChat>;
|
||||||
|
usersById: Record<number, ApiUser>;
|
||||||
isRightColumnShown: boolean;
|
isRightColumnShown: boolean;
|
||||||
isRestricted?: boolean;
|
isRestricted?: boolean;
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
@ -95,6 +97,7 @@ const TABS = [
|
|||||||
{ type: 'documents', title: 'SharedFilesTab2' },
|
{ type: 'documents', title: 'SharedFilesTab2' },
|
||||||
{ type: 'links', title: 'SharedLinksTab2' },
|
{ type: 'links', title: 'SharedLinksTab2' },
|
||||||
{ type: 'audio', title: 'SharedMusicTab2' },
|
{ type: 'audio', title: 'SharedMusicTab2' },
|
||||||
|
{ type: 'voice', title: 'SharedVoiceTab2' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const HIDDEN_RENDER_DELAY = 1000;
|
const HIDDEN_RENDER_DELAY = 1000;
|
||||||
@ -116,6 +119,7 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
canDeleteMembers,
|
canDeleteMembers,
|
||||||
members,
|
members,
|
||||||
usersById,
|
usersById,
|
||||||
|
chatsById,
|
||||||
isRightColumnShown,
|
isRightColumnShown,
|
||||||
isRestricted,
|
isRestricted,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
@ -272,6 +276,7 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
case 'links':
|
case 'links':
|
||||||
text = lang('lng_media_link_empty_search');
|
text = lang('lng_media_link_empty_search');
|
||||||
break;
|
break;
|
||||||
|
case 'voice':
|
||||||
case 'audio':
|
case 'audio':
|
||||||
text = lang('lng_media_song_empty_search');
|
text = lang('lng_media_song_empty_search');
|
||||||
break;
|
break;
|
||||||
@ -333,6 +338,21 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
onDateClick={handleMessageFocus}
|
onDateClick={handleMessageFocus}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
) : resultType === 'voice' ? (
|
||||||
|
viewportIds!.map((id) => chatMessages[id] && (
|
||||||
|
<Audio
|
||||||
|
key={id}
|
||||||
|
theme={theme}
|
||||||
|
message={chatMessages[id]}
|
||||||
|
senderTitle={getSenderName(lang, chatMessages[id], chatsById, usersById)}
|
||||||
|
origin={AudioOrigin.SharedMedia}
|
||||||
|
date={chatMessages[id].date}
|
||||||
|
lastSyncTime={lastSyncTime}
|
||||||
|
className="scroll-item"
|
||||||
|
onPlay={handlePlayAudio}
|
||||||
|
onDateClick={handleMessageFocus}
|
||||||
|
/>
|
||||||
|
))
|
||||||
) : resultType === 'members' ? (
|
) : resultType === 'members' ? (
|
||||||
viewportIds!.map((id, i) => (
|
viewportIds!.map((id, i) => (
|
||||||
<ListItem
|
<ListItem
|
||||||
@ -383,7 +403,6 @@ const Profile: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
{renderSharedMedia}
|
{renderSharedMedia}
|
||||||
</Transition>
|
</Transition>
|
||||||
<TabList big activeTab={activeTab} tabs={tabs} onSwitchTab={setActiveTab} />
|
<TabList big activeTab={activeTab} tabs={tabs} onSwitchTab={setActiveTab} />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -434,6 +453,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const { foundIds } = (resultsByType && mediaSearchType && resultsByType[mediaSearchType]) || {};
|
const { foundIds } = (resultsByType && mediaSearchType && resultsByType[mediaSearchType]) || {};
|
||||||
|
|
||||||
const { byId: usersById } = global.users;
|
const { byId: usersById } = global.users;
|
||||||
|
const { byId: chatsById } = global.chats;
|
||||||
|
|
||||||
const isGroup = chat && isChatGroup(chat);
|
const isGroup = chat && isChatGroup(chat);
|
||||||
const isChannel = chat && isChatChannel(chat);
|
const isChannel = chat && isChatChannel(chat);
|
||||||
@ -466,10 +486,9 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
isRestricted: chat?.isRestricted,
|
isRestricted: chat?.isRestricted,
|
||||||
lastSyncTime: global.lastSyncTime,
|
lastSyncTime: global.lastSyncTime,
|
||||||
serverTimeOffset: global.serverTimeOffset,
|
serverTimeOffset: global.serverTimeOffset,
|
||||||
...(hasMembersTab && members && {
|
usersById,
|
||||||
members,
|
chatsById,
|
||||||
usersById,
|
...(hasMembersTab && members && { members }),
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
(setGlobal, actions): DispatchProps => pick(actions, [
|
(setGlobal, actions): DispatchProps => pick(actions, [
|
||||||
|
|||||||
@ -52,6 +52,10 @@ export default function useProfileViewportIds(
|
|||||||
'audio', resultType, searchMessages, lastSyncTime, chatMessages, foundIds,
|
'audio', resultType, searchMessages, lastSyncTime, chatMessages, foundIds,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [voiceViewportIds, getMoreVoices, noProfileInfoForVoices] = useInfiniteScrollForSharedMedia(
|
||||||
|
'voice', resultType, searchMessages, lastSyncTime, chatMessages, foundIds,
|
||||||
|
);
|
||||||
|
|
||||||
let viewportIds: number[] | undefined;
|
let viewportIds: number[] | undefined;
|
||||||
let getMore: AnyToVoidFunction | undefined;
|
let getMore: AnyToVoidFunction | undefined;
|
||||||
let noProfileInfo = false;
|
let noProfileInfo = false;
|
||||||
@ -82,6 +86,11 @@ export default function useProfileViewportIds(
|
|||||||
getMore = getMoreAudio;
|
getMore = getMoreAudio;
|
||||||
noProfileInfo = noProfileInfoForAudio;
|
noProfileInfo = noProfileInfoForAudio;
|
||||||
break;
|
break;
|
||||||
|
case 'voice':
|
||||||
|
viewportIds = voiceViewportIds;
|
||||||
|
getMore = getMoreVoices;
|
||||||
|
noProfileInfo = noProfileInfoForVoices;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [resultType, viewportIds, getMore, noProfileInfo] as const;
|
return [resultType, viewportIds, getMore, noProfileInfo] as const;
|
||||||
|
|||||||
@ -365,6 +365,10 @@ export function getMessageContentIds(
|
|||||||
validator = getMessageAudio;
|
validator = getMessageAudio;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'voice':
|
||||||
|
validator = getMessageVoice;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'inlineMedia':
|
case 'inlineMedia':
|
||||||
validator = (message: ApiMessage) => {
|
validator = (message: ApiMessage) => {
|
||||||
const video = getMessageVideo(message);
|
const video = getMessageVideo(message);
|
||||||
|
|||||||
@ -270,8 +270,8 @@ export enum NewChatMembersProgress {
|
|||||||
Loading,
|
Loading,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProfileTabType = 'members' | 'media' | 'documents' | 'links' | 'audio';
|
export type ProfileTabType = 'members' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio';
|
export type SharedMediaType = 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
export type ApiPrivacyKey = 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'forwards' | 'chatInvite';
|
export type ApiPrivacyKey = 'phoneNumber' | 'lastSeen' | 'profilePhoto' | 'forwards' | 'chatInvite';
|
||||||
export type PrivacyVisibility = 'everybody' | 'contacts' | 'nonContacts' | 'nobody';
|
export type PrivacyVisibility = 'everybody' | 'contacts' | 'nonContacts' | 'nobody';
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user