Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions scripts/index_d_ts
Original file line number Diff line number Diff line change
Expand Up @@ -1864,6 +1864,7 @@ declare module '@sendbird/uikit-react/ui/Dropdown' {
declare module '@sendbird/uikit-react/ui/EmojiReactions' {
import type { EmojiCategory } from '@sendbird/chat';
import type { FileMessage, UserMessage } from '@sendbird/chat/message';
import type { GroupChannel } from '@sendbird/chat/groupChannel';

interface EmojiContainer {
emojiCategories: Array<EmojiCategory>;
Expand All @@ -1873,6 +1874,7 @@ declare module '@sendbird/uikit-react/ui/EmojiReactions' {
className?: string | Array<string>;
userId: string;
message: UserMessage | FileMessage;
channel: GroupChannel;
emojiContainer: EmojiContainer;
memberNicknamesMap: Map<string, string>;
spaceFromTrigger?: Record<string, unknown>;
Expand Down
9 changes: 7 additions & 2 deletions src/hooks/VoiceRecorder/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
import {
BROWSER_SUPPORT_MIME_TYPE_LIST,
VOICE_MESSAGE_FILE_NAME,
VOICE_MESSAGE_MIME_TYPE,
VOICE_RECORDER_AUDIO_BITS,
VOICE_RECORDER_MIME_TYPE,
} from '../../utils/consts';
import useSendbirdStateContext from '../useSendbirdStateContext';

Expand Down Expand Up @@ -37,6 +37,11 @@ export const VoiceRecorderProvider = (props: VoiceRecorderProps): React.ReactEle
const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder>(null);
const [isRecordable, setIsRecordable] = useState<boolean>(false);

const browserSupportMimeType = BROWSER_SUPPORT_MIME_TYPE_LIST.find((mimeType) => MediaRecorder.isTypeSupported(mimeType)) ?? '';
if (!browserSupportMimeType) {
logger.error('VoiceRecorder: Browser does not support mimeType', { mimmeTypes: BROWSER_SUPPORT_MIME_TYPE_LIST });
}

const [webAudioUtils, setWebAudioUtils] = useState(null);
useEffect(() => {
if (isVoiceMessageEnabled && !webAudioUtils) {
Expand All @@ -62,7 +67,7 @@ export const VoiceRecorderProvider = (props: VoiceRecorderProps): React.ReactEle
logger.info('VoiceRecorder: Succeeded getting media stream.', stream);
setIsRecordable(true);
const mediaRecorder = new MediaRecorder(stream, {
mimeType: VOICE_RECORDER_MIME_TYPE,
mimeType: browserSupportMimeType,
audioBitsPerSecond: VOICE_RECORDER_AUDIO_BITS,
});
mediaRecorder.ondataavailable = (e) => { // when recording stops
Expand Down
7 changes: 6 additions & 1 deletion src/hooks/useLongPress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ interface PressHandlers<T> {
interface Options {
delay?: number;
shouldPreventDefault?: boolean;
shouldStopPropagation?: boolean;
}

interface UseLongPressType<T> {
Expand All @@ -67,6 +68,7 @@ export default function useLongPress<T>({
}: PressHandlers<T>, {
delay = DEFAULT_DURATION,
shouldPreventDefault = true,
shouldStopPropagation = false,
}: Options = {}): UseLongPressType<T> {
const { isMobile } = useMediaQueryContext();
const [longPressTriggered, setLongPressTriggered] = useState(false);
Expand All @@ -81,6 +83,9 @@ export default function useLongPress<T>({
...e,
};
setDragTriggered(false);
if (shouldStopPropagation) {
e.stopPropagation();
}
if (shouldPreventDefault && e.target) {
e.target.addEventListener(
'touchend',
Expand All @@ -96,7 +101,7 @@ export default function useLongPress<T>({
onLongPress(clonedEvent);
setLongPressTriggered(true);
}, delay);
}, [onLongPress, delay, shouldPreventDefault, isMobile]);
}, [onLongPress, delay, shouldPreventDefault, shouldStopPropagation, isMobile]);

const clear = useCallback((
e: React.MouseEvent<T> | React.TouchEvent<T>,
Expand Down
11 changes: 6 additions & 5 deletions src/lib/MediaQueryContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useEffect, useState } from 'react';
import type { Logger } from './SendbirdState';

const DEFAULT_MOBILE = '0px';
const DEFAULT_MOBILE = false;
// const DEFAULT_MOBILE = '768px';
const MOBILE_CLASSNAME = 'sendbird--mobile-mode';

const MediaQueryContext = React.createContext({
Expand All @@ -18,7 +19,7 @@ export interface MediaQueryProviderProps {
const addClassNameToBody = () => {
try {
const body = document.querySelector('body');
body.classList.add(MOBILE_CLASSNAME);
body?.classList.add(MOBILE_CLASSNAME);
} catch {
// noop
}
Expand All @@ -27,7 +28,7 @@ const addClassNameToBody = () => {
const removeClassNameFromBody = () => {
try {
const body = document.querySelector('body');
body.classList.remove(MOBILE_CLASSNAME);
body?.classList.remove(MOBILE_CLASSNAME);
} catch {
// noop
}
Expand Down Expand Up @@ -67,10 +68,10 @@ const MediaQueryProvider = (props: MediaQueryProviderProps): React.ReactElement
};
updateSize();
window.addEventListener('resize', updateSize);
logger?.info?.('MediaQueryProvider: addEventListener', updateSize);
logger?.info?.('MediaQueryProvider: addEventListener', { updateSize });
return () => {
window.removeEventListener('resize', updateSize);
logger?.info?.('MediaQueryProvider: removeEventListener', updateSize);
logger?.info?.('MediaQueryProvider: removeEventListener', { updateSize });
};
}, [mediaQueryBreakPoint]);
return (
Expand Down
8 changes: 5 additions & 3 deletions src/modules/App/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ export const AppLayout: React.FC<AppLayoutProps> = (
setCurrentChannel,
} = props;
const [showThread, setShowThread] = useState(false);
const [threadTargetMessage, setThreadTargetMessage] = useState<UserMessage | FileMessage>(null);
const [threadTargetMessage, setThreadTargetMessage] = useState<UserMessage | FileMessage | null>(null);
const [showSettings, setShowSettings] = useState(false);
const [showSearch, setShowSearch] = useState(false);
const [highlightedMessage, setHighlightedMessage] = useState<number>(null);
const [startingPoint, setStartingPoint] = useState<number>(null);
const [highlightedMessage, setHighlightedMessage] = useState<number | null>(null);
const [startingPoint, setStartingPoint] = useState<number | null>(null);
const { isMobile } = useMediaQueryContext();
return (
<>
Expand All @@ -46,6 +46,8 @@ export const AppLayout: React.FC<AppLayoutProps> = (
setHighlightedMessage={setHighlightedMessage}
startingPoint={startingPoint}
setStartingPoint={setStartingPoint}
threadTargetMessage={threadTargetMessage}
setThreadTargetMessage={setThreadTargetMessage}
/>
)
: (
Expand Down
18 changes: 9 additions & 9 deletions src/modules/App/DesktopLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const DesktopLayout: React.FC<DesktopLayoutProps> = (
threadTargetMessage,
setThreadTargetMessage,
} = props;
const [animatedMessageId, setAnimatedMessageId] = useState(null);
const [animatedMessageId, setAnimatedMessageId] = useState<number | null>(null);
return (
<div className="sendbird-app__wrap">
<div className="sendbird-app__channellist-wrap">
Expand All @@ -44,8 +44,8 @@ export const DesktopLayout: React.FC<DesktopLayoutProps> = (
onProfileEditSuccess={onProfileEditSuccess}
disableAutoSelect={disableAutoSelect}
onChannelSelect={(channel) => {
setStartingPoint(null);
setHighlightedMessage(null);
setStartingPoint?.(null);
setHighlightedMessage?.(null);
if (channel) {
setCurrentChannel(channel);
} else {
Expand Down Expand Up @@ -93,7 +93,7 @@ export const DesktopLayout: React.FC<DesktopLayoutProps> = (
setAnimatedMessageId(null);
}}
onMessageHighlighted={() => {
setHighlightedMessage(null);
setHighlightedMessage?.(null);
}}
showSearchIcon={showSearchIcon}
startingPoint={startingPoint}
Expand Down Expand Up @@ -121,13 +121,13 @@ export const DesktopLayout: React.FC<DesktopLayoutProps> = (
channelUrl={currentChannel?.url || ''}
onResultClick={(message) => {
if (message.messageId === highlightedMessage) {
setHighlightedMessage(null);
setHighlightedMessage?.(null);
setTimeout(() => {
setHighlightedMessage(message.messageId);
setHighlightedMessage?.(message.messageId);
});
} else {
setStartingPoint(message.createdAt);
setHighlightedMessage(message.messageId);
setStartingPoint?.(message.createdAt);
setHighlightedMessage?.(message.messageId);
}
}}
onCloseClick={() => {
Expand All @@ -149,7 +149,7 @@ export const DesktopLayout: React.FC<DesktopLayoutProps> = (
setCurrentChannel(channel);
}
if (message?.messageId !== animatedMessageId) {
setStartingPoint(message?.createdAt);
setStartingPoint?.(message?.createdAt);
}
setTimeout(() => {
setAnimatedMessageId(message?.messageId);
Expand Down
56 changes: 51 additions & 5 deletions src/modules/App/MobileLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ChannelList from '../ChannelList';
import Channel from '../Channel';
import ChannelSettings from '../ChannelSettings';
import MessageSearch from '../MessageSearch';
import Thread from '../Thread';
import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import uuidv4 from '../../utils/uuid';

Expand All @@ -19,6 +20,7 @@ enum PANELS {
CHANNEL = 'CHANNEL',
CHANNEL_SETTINGS = 'CHANNEL_SETTINGS',
MESSAGE_SEARCH = 'MESSAGE_SEARCH',
THREAD = 'THREAD',
}

export const MobileLayout: React.FC<MobileLayoutProps> = (
Expand All @@ -37,18 +39,21 @@ export const MobileLayout: React.FC<MobileLayoutProps> = (
setHighlightedMessage,
startingPoint,
setStartingPoint,
threadTargetMessage,
setThreadTargetMessage,
} = props;
const [panel, setPanel] = useState(PANELS?.CHANNEL_LIST);
const [animatedMessageId, setAnimatedMessageId] = useState<number | null>(null);

const store = useSendbirdStateContext();
const sdk = store?.stores?.sdkStore?.sdk as SendbirdGroupChat;
const userId = store?.config?.userId;

const goToMessage = (message?: BaseMessage | null) => {
setStartingPoint(message?.createdAt);
const goToMessage = (message?: BaseMessage | null, timeoutCb?: (msgId: number | null) => void) => {
setStartingPoint?.(message?.createdAt || null);
setTimeout(() => {
setHighlightedMessage(message?.messageId);
});
timeoutCb?.(message?.messageId || null);
}, 500);
};

useEffect(() => {
Expand Down Expand Up @@ -118,10 +123,23 @@ export const MobileLayout: React.FC<MobileLayoutProps> = (
showSearchIcon={showSearchIcon}
isMessageGroupingEnabled={isMessageGroupingEnabled}
startingPoint={startingPoint}
animatedMessage={animatedMessageId}
highlightedMessage={highlightedMessage}
onChatHeaderActionClick={() => {
setPanel(PANELS.CHANNEL_SETTINGS);
}}
onReplyInThread={({ message }) => {
if (replyType === 'THREAD') {
setPanel(PANELS.THREAD);
setThreadTargetMessage(message);
}
}}
onQuoteMessageClick={({ message }) => { // thread message
if (replyType === 'THREAD') {
setThreadTargetMessage(message);
setPanel(PANELS.THREAD);
}
}}
/>
</div>
)
Expand Down Expand Up @@ -151,7 +169,35 @@ export const MobileLayout: React.FC<MobileLayoutProps> = (
}}
onResultClick={(message) => {
setPanel(PANELS.CHANNEL);
goToMessage(message);
goToMessage(message, (messageId) => {
setHighlightedMessage?.(messageId);
});
}}
/>
</div>
)
}
{
panel === PANELS?.THREAD && (
<div className='sb_mobile__panelwrap'>
<Thread
channelUrl={currentChannel?.url || ''}
message={threadTargetMessage}
onHeaderActionClick={() => {
setPanel(PANELS.CHANNEL);
}}
onMoveToParentMessage={({ message, channel }) => {
if (channel?.url !== currentChannel?.url) {
setPanel(PANELS.CHANNEL);
}
if (message?.messageId !== animatedMessageId) {
goToMessage(message, (messageId) => {
setAnimatedMessageId(messageId);
});
}
setTimeout(() => {
setAnimatedMessageId(message?.messageId);
}, 500);
}}
/>
</div>
Expand Down
11 changes: 11 additions & 0 deletions src/modules/App/mobile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,14 @@
.sb-show-main {
padding: 0 !important;
}

.sb_mobile__panelwrap .sendbird-thread {
width: 100%;
height: 100%;
& .sendbird-thread-ui {
max-width: 100%;
& .sendbird-thread-ui__header {
width: 100%;
}
}
}
38 changes: 35 additions & 3 deletions src/modules/App/stories/integrated-app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@
height: 120px;
justify-content: center;
align-items: center;
@include mobile() {
height: 80px;
}
}

.sendbird-integrated-sample-app__moderations {
position: relative;
padding: 18px;
display: flex;
flex-direction: column;
margin-left: calc((100% - 520px) / 2);
margin-right: calc((100% - 520px) / 2);
align-items: center;
@include themed() {
background-color: t(bg-1);
}
Expand All @@ -48,19 +50,49 @@
@include themed() {
border-bottom: 1px solid t(on-bg-1);
}
@include mobile() {
flex-direction: column;
flex-wrap: wrap;
align-items: center;
}
}
.sendbird-integrated-sample-app__moderations__option--toggle {
@include mobile() {
flex-direction: row;
flex-wrap: wrap;
width: 100%;
justify-content: space-between
}
.sendbird-integrated-sample-app__moderations__option__name,
.sendbird-integrated-sample-app__moderations__option__input {
@include mobile() {
width: auto;
}
}
.sendbird-integrated-sample-app-toggle-button {
text-align: right;
}
}
.sendbird-integrated-sample-app__moderations__option__name {
width: 140px;
@include mobile() {
width: 100%;
}
}
.sendbird-integrated-sample-app__moderations__option__input {
margin-left: 20px;
@include mobile() {
width: 100%;
margin-left: 0px;
}
}

.sendbird-integrated-app-submit-area {
display: flex;
width: 100%;
justify-content: center;
gap: 10px
gap: 10px;
margin: 16px 0px;
}

// text input
Expand Down
Loading