mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
Reworked mobile UI for some components
This commit is contained in:
parent
37ad329072
commit
efbe6907ac
@ -65,9 +65,9 @@ export default function ChatContainer(props: Props) {
|
|||||||
|
|
||||||
const MessagesTable = useMemo(
|
const MessagesTable = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<>
|
<div style={{ height: '100%' }}>
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
style={{ height: isMobile ? 500 : '77vh', width: 'auto' }}
|
style={{ height: '100%', width: 'auto' }}
|
||||||
ref={chatContainerRef}
|
ref={chatContainerRef}
|
||||||
initialTopMostItemIndex={messages.length - 1} // Force alignment to bottom
|
initialTopMostItemIndex={messages.length - 1} // Force alignment to bottom
|
||||||
data={messages}
|
data={messages}
|
||||||
@ -92,7 +92,7 @@ export default function ChatContainer(props: Props) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
),
|
),
|
||||||
[messages, usernameToHighlight, chatUserId, isModerator, atBottom, isMobile],
|
[messages, usernameToHighlight, chatUserId, isModerator, atBottom, isMobile],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
interface Props {}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
export default function ChatTextField(props: Props) {
|
|
||||||
const [value, setValue] = useState('');
|
|
||||||
const [showEmojis, setShowEmojis] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={value}
|
|
||||||
onChange={e => setValue(e.target.value)}
|
|
||||||
placeholder="Type a message here then hit ENTER"
|
|
||||||
/>
|
|
||||||
<button type="button" onClick={() => setShowEmojis(!showEmojis)}>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
className="icon"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="2"
|
|
||||||
d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -7,48 +7,62 @@
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
div[role=textbox] {
|
div[role=textbox] {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
border-radius: .2rem;
|
||||||
padding: .6rem;
|
padding: .6rem;
|
||||||
padding-right: calc(0.6rem + 44px);
|
padding-right: calc(0.6rem + 44px);
|
||||||
border-radius: .35rem;
|
|
||||||
background-color: var(--color-owncast-gray-700);
|
background-color: var(--color-owncast-gray-700);
|
||||||
|
box-shadow: 0;
|
||||||
|
transition: box-shadow 50ms ease-in-out;
|
||||||
|
&:focus {
|
||||||
|
box-shadow: inset 0px 0px 0x 1px var(--color-owncast-purple-700);
|
||||||
|
outline: 1px solid var(--color-owncast-gray-500) !important;
|
||||||
|
}
|
||||||
& > p {
|
& > p {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inputWrapper {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
margin-right: .3rem;
|
||||||
|
border-radius: .2rem;
|
||||||
|
& > div {
|
||||||
|
transition: box-shadow .2s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.emojiButton {
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 1rem;
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
svg {
|
||||||
|
fill: var(--color-owncast-gray-300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.submitButtonWrapper {
|
||||||
|
display: flex;
|
||||||
|
padding: 6px 0;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputWrapper {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
.mobile {
|
||||||
border-radius: var(--theme-rounded-corners);
|
&.root {
|
||||||
outline: 1px solid var(--color-owncast-gray-500);
|
display: flex;
|
||||||
&:hover {
|
.inputWrapper {
|
||||||
box-shadow: 0 0 1px 1px var(--color-owncast-gray-300);
|
flex: 1;
|
||||||
}
|
}
|
||||||
& > div {
|
.submitButtonWrapper {
|
||||||
transition: box-shadow .2s ease-in-out;
|
padding: 0px;
|
||||||
&:focus {
|
|
||||||
// box-shadow: 0 0 1px 1px var(--color-owncast-gray-300);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.emojiButton {
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0 1rem;
|
|
||||||
position: absolute;
|
|
||||||
right: 0px;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
svg {
|
|
||||||
fill: var(--color-owncast-gray-300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.submitButtonWrapper {
|
|
||||||
display: flex;
|
|
||||||
padding: 6px 0;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -4,9 +4,10 @@ import React, { useState } from 'react';
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Transforms, createEditor, BaseEditor, Text } from 'slate';
|
import { Transforms, createEditor, BaseEditor, Text } from 'slate';
|
||||||
import { Slate, Editable, withReact, ReactEditor } from 'slate-react';
|
import { Slate, Editable, withReact, ReactEditor } from 'slate-react';
|
||||||
|
import cn from 'classnames';
|
||||||
import EmojiPicker from './EmojiPicker';
|
import EmojiPicker from './EmojiPicker';
|
||||||
import WebsocketService from '../../../services/websocket-service';
|
import WebsocketService from '../../../services/websocket-service';
|
||||||
import { websocketServiceAtom } from '../../stores/ClientConfigStore';
|
import { isMobileAtom, websocketServiceAtom } from '../../stores/ClientConfigStore';
|
||||||
import { MessageType } from '../../../interfaces/socket-events';
|
import { MessageType } from '../../../interfaces/socket-events';
|
||||||
import s from './ChatTextField.module.scss';
|
import s from './ChatTextField.module.scss';
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ export default function ChatTextField(props: Props) {
|
|||||||
// const { value: originalValue } = props;
|
// const { value: originalValue } = props;
|
||||||
const [showEmojis, setShowEmojis] = useState(false);
|
const [showEmojis, setShowEmojis] = useState(false);
|
||||||
const websocketService = useRecoilValue<WebsocketService>(websocketServiceAtom);
|
const websocketService = useRecoilValue<WebsocketService>(websocketServiceAtom);
|
||||||
|
const isMobile = useRecoilValue<boolean>(isMobileAtom);
|
||||||
const [editor] = useState(() => withImages(withReact(createEditor())));
|
const [editor] = useState(() => withImages(withReact(createEditor())));
|
||||||
|
|
||||||
const sendMessage = () => {
|
const sendMessage = () => {
|
||||||
@ -120,7 +122,7 @@ export default function ChatTextField(props: Props) {
|
|||||||
|
|
||||||
const handleChange = () => {};
|
const handleChange = () => {};
|
||||||
|
|
||||||
const handleEmojiSelect = e => {
|
const handleEmojiSelect = (e: any) => {
|
||||||
ReactEditor.focus(editor);
|
ReactEditor.focus(editor);
|
||||||
|
|
||||||
if (e.url) {
|
if (e.url) {
|
||||||
@ -134,7 +136,7 @@ export default function ChatTextField(props: Props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onKeyDown = e => {
|
const onKeyDown = (e: React.KeyboardEvent) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
sendMessage();
|
sendMessage();
|
||||||
@ -142,7 +144,11 @@ export default function ChatTextField(props: Props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={s.root}>
|
<div
|
||||||
|
className={cn(s.root, {
|
||||||
|
[s.mobile]: isMobile,
|
||||||
|
})}
|
||||||
|
>
|
||||||
<div className={s.inputWrapper}>
|
<div className={s.inputWrapper}>
|
||||||
<Slate
|
<Slate
|
||||||
editor={editor}
|
editor={editor}
|
||||||
@ -167,9 +173,13 @@ export default function ChatTextField(props: Props) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className={s.submitButtonWrapper}>
|
<div className={s.submitButtonWrapper}>
|
||||||
<Button size="middle" type="primary" icon={<SendOutlined />} onClick={sendMessage}>
|
{isMobile ? (
|
||||||
Send
|
<Button size="large" type="ghost" icon={<SendOutlined />} onClick={sendMessage} />
|
||||||
</Button>
|
) : (
|
||||||
|
<Button type="primary" icon={<SendOutlined />} onClick={sendMessage}>
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Popover
|
<Popover
|
||||||
content={<EmojiPicker onEmojiSelect={handleEmojiSelect} />}
|
content={<EmojiPicker onEmojiSelect={handleEmojiSelect} />}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
.streamInfo {
|
.root {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
@ -34,3 +34,44 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile {
|
||||||
|
&.root {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
padding: 0 .3rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
.mobileInfo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mobileStatus {
|
||||||
|
display: flex;
|
||||||
|
font-weight: 600;
|
||||||
|
.viewerCount {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.liveStatus {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: .5rem;
|
||||||
|
font-size: .8rem;
|
||||||
|
gap: 4px;
|
||||||
|
.liveCircle {
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: red;
|
||||||
|
width: .5rem;
|
||||||
|
height: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,56 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import cn from 'classnames';
|
||||||
|
import { EyeFilled } from '@ant-design/icons';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { ClientConfig } from '../../../interfaces/client-config.model';
|
import { ClientConfig } from '../../../interfaces/client-config.model';
|
||||||
import { clientConfigStateAtom } from '../../stores/ClientConfigStore';
|
import {
|
||||||
|
clientConfigStateAtom,
|
||||||
|
isOnlineSelector,
|
||||||
|
serverStatusState,
|
||||||
|
} from '../../stores/ClientConfigStore';
|
||||||
import { ServerLogo } from '../../ui';
|
import { ServerLogo } from '../../ui';
|
||||||
|
import StatusBar from '../../ui/Statusbar';
|
||||||
import CategoryIcon from '../../ui/CategoryIcon/CategoryIcon';
|
import CategoryIcon from '../../ui/CategoryIcon/CategoryIcon';
|
||||||
import SocialLinks from '../../ui/SocialLinks/SocialLinks';
|
import SocialLinks from '../../ui/SocialLinks/SocialLinks';
|
||||||
import s from './StreamInfo.module.scss';
|
import s from './StreamInfo.module.scss';
|
||||||
|
import { ServerStatus } from '../../../interfaces/server-status.model';
|
||||||
|
|
||||||
export default function StreamInfo() {
|
interface Props {
|
||||||
|
isMobile: boolean;
|
||||||
|
}
|
||||||
|
export default function StreamInfo({ isMobile }: Props) {
|
||||||
const { socialHandles, name, title, tags } = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
const { socialHandles, name, title, tags } = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||||
|
const { viewerCount, lastConnectTime, lastDisconnectTime } =
|
||||||
|
useRecoilValue<ServerStatus>(serverStatusState);
|
||||||
|
const online = useRecoilValue<boolean>(isOnlineSelector);
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<div className={s.streamInfo}>
|
console.log({ online });
|
||||||
|
}, [online]);
|
||||||
|
|
||||||
|
return isMobile ? (
|
||||||
|
<div className={cn(s.root, s.mobile)}>
|
||||||
|
<div className={s.mobileInfo}>
|
||||||
|
<ServerLogo src="/logo" />
|
||||||
|
<div className={s.title}>{name}</div>
|
||||||
|
</div>
|
||||||
|
<div className={s.mobileStatus}>
|
||||||
|
<div className={s.viewerCount}>
|
||||||
|
{online && (
|
||||||
|
<>
|
||||||
|
<span>{viewerCount}</span>
|
||||||
|
<EyeFilled />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={s.liveStatus}>
|
||||||
|
{online && <div className={s.liveCircle} />}
|
||||||
|
<span>{online ? 'LIVE' : 'OFFLINE'}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className={s.root}>
|
||||||
<div className={s.logoTitleSection}>
|
<div className={s.logoTitleSection}>
|
||||||
<ServerLogo src="/logo" />
|
<ServerLogo src="/logo" />
|
||||||
<div className={s.titleSection}>
|
<div className={s.titleSection}>
|
||||||
@ -23,6 +63,12 @@ export default function StreamInfo() {
|
|||||||
<SocialLinks links={socialHandles} />
|
<SocialLinks links={socialHandles} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<StatusBar
|
||||||
|
online={online}
|
||||||
|
lastConnectTime={lastConnectTime}
|
||||||
|
lastDisconnectTime={lastDisconnectTime}
|
||||||
|
viewerCount={viewerCount}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,32 +1,8 @@
|
|||||||
.root {
|
.root {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
&.mobile {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: calc(100vh - 64px);
|
|
||||||
overflow-y: hidden;
|
|
||||||
.topHalf {
|
|
||||||
border: 1px dashed white;
|
|
||||||
height: calc(40vh - 64px);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.lowerHalf {
|
|
||||||
border: 1px dashed red;
|
|
||||||
height: 60vh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobileChat {
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
// top: 0px;
|
|
||||||
width: 100%;
|
|
||||||
[data-virtuoso-scroller] {
|
|
||||||
height: 500px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.leftCol {
|
.leftCol {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -40,3 +16,26 @@
|
|||||||
z-index: 999999;
|
z-index: 999999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile {
|
||||||
|
&.root {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: calc(100vh - 64px);
|
||||||
|
overflow: hidden;
|
||||||
|
.topHalf {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 30vh 5vh 5vh;
|
||||||
|
height: 40vh;
|
||||||
|
// overflow: hidden;
|
||||||
|
}
|
||||||
|
.lowerHalf {
|
||||||
|
height: 60vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mobileChat {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import {
|
|||||||
chatDisplayNameAtom,
|
chatDisplayNameAtom,
|
||||||
chatUserIdAtom,
|
chatUserIdAtom,
|
||||||
isChatVisibleSelector,
|
isChatVisibleSelector,
|
||||||
serverStatusState,
|
|
||||||
appStateAtom,
|
appStateAtom,
|
||||||
isOnlineSelector,
|
isOnlineSelector,
|
||||||
isMobileAtom,
|
isMobileAtom,
|
||||||
@ -28,8 +27,6 @@ import { ChatMessage } from '../../../interfaces/chat-message.model';
|
|||||||
import ChatTextField from '../../chat/ChatTextField/ChatTextField';
|
import ChatTextField from '../../chat/ChatTextField/ChatTextField';
|
||||||
import ActionButtonRow from '../../action-buttons/ActionButtonRow';
|
import ActionButtonRow from '../../action-buttons/ActionButtonRow';
|
||||||
import ActionButton from '../../action-buttons/ActionButton';
|
import ActionButton from '../../action-buttons/ActionButton';
|
||||||
import Statusbar from '../Statusbar/Statusbar';
|
|
||||||
import { ServerStatus } from '../../../interfaces/server-status.model';
|
|
||||||
import { Follower } from '../../../interfaces/follower';
|
import { Follower } from '../../../interfaces/follower';
|
||||||
import NotifyReminderPopup from '../NotifyReminderPopup/NotifyReminderPopup';
|
import NotifyReminderPopup from '../NotifyReminderPopup/NotifyReminderPopup';
|
||||||
import OfflineBanner from '../OfflineBanner/OfflineBanner';
|
import OfflineBanner from '../OfflineBanner/OfflineBanner';
|
||||||
@ -38,13 +35,13 @@ import FollowButton from '../../action-buttons/FollowButton';
|
|||||||
import NotifyButton from '../../action-buttons/NotifyButton';
|
import NotifyButton from '../../action-buttons/NotifyButton';
|
||||||
import Modal from '../Modal/Modal';
|
import Modal from '../Modal/Modal';
|
||||||
import BrowserNotifyModal from '../../modals/BrowserNotify/BrowserNotifyModal';
|
import BrowserNotifyModal from '../../modals/BrowserNotify/BrowserNotifyModal';
|
||||||
|
import StreamInfo from '../../common/StreamInfo';
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
const { Content } = Layout;
|
const { Content } = Layout;
|
||||||
|
|
||||||
export default function ContentComponent() {
|
export default function ContentComponent() {
|
||||||
const appState = useRecoilValue<AppStateOptions>(appStateAtom);
|
const appState = useRecoilValue<AppStateOptions>(appStateAtom);
|
||||||
const status = useRecoilValue<ServerStatus>(serverStatusState);
|
|
||||||
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||||
const isChatVisible = useRecoilValue<boolean>(isChatVisibleSelector);
|
const isChatVisible = useRecoilValue<boolean>(isChatVisibleSelector);
|
||||||
const [isMobile, setIsMobile] = useRecoilState<boolean | undefined>(isMobileAtom);
|
const [isMobile, setIsMobile] = useRecoilState<boolean | undefined>(isMobileAtom);
|
||||||
@ -54,7 +51,6 @@ export default function ContentComponent() {
|
|||||||
const chatUserId = useRecoilValue<string>(chatUserIdAtom);
|
const chatUserId = useRecoilValue<string>(chatUserIdAtom);
|
||||||
|
|
||||||
const { extraPageContent, version, name, summary } = clientConfig;
|
const { extraPageContent, version, name, summary } = clientConfig;
|
||||||
const { viewerCount, lastConnectTime, lastDisconnectTime } = status;
|
|
||||||
const [showNotifyReminder, setShowNotifyReminder] = useState(false);
|
const [showNotifyReminder, setShowNotifyReminder] = useState(false);
|
||||||
const [showNotifyPopup, setShowNotifyPopup] = useState(false);
|
const [showNotifyPopup, setShowNotifyPopup] = useState(false);
|
||||||
|
|
||||||
@ -129,13 +125,6 @@ export default function ContentComponent() {
|
|||||||
text="Stream is offline text goes here. Will create a new form to set it in the Admin."
|
text="Stream is offline text goes here. Will create a new form to set it in the Admin."
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Statusbar
|
|
||||||
online={online}
|
|
||||||
lastConnectTime={lastConnectTime}
|
|
||||||
lastDisconnectTime={lastDisconnectTime}
|
|
||||||
viewerCount={viewerCount}
|
|
||||||
/>
|
|
||||||
<div className={s.buttonsLogoTitleSection}>
|
<div className={s.buttonsLogoTitleSection}>
|
||||||
<ActionButtonRow>
|
<ActionButtonRow>
|
||||||
{externalActionButtons}
|
{externalActionButtons}
|
||||||
@ -158,12 +147,18 @@ export default function ContentComponent() {
|
|||||||
<BrowserNotifyModal />
|
<BrowserNotifyModal />
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
<StreamInfo isMobile={isMobile} />
|
||||||
</div>
|
</div>
|
||||||
<div className={s.lowerHalf}>
|
<div className={s.lowerHalf}>
|
||||||
<Tabs defaultActiveKey="0">
|
<Tabs defaultActiveKey="0">
|
||||||
{isChatVisible && isMobile && (
|
{isChatVisible && isMobile && (
|
||||||
<TabPane tab="Chat" key="0" className={s.pageContentSection}>
|
<TabPane
|
||||||
<div style={{ position: 'relative' }}>
|
tab="Chat"
|
||||||
|
key="0"
|
||||||
|
className={s.pageContentSection}
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
>
|
||||||
|
<div style={{ position: 'relative', height: '100%' }}>
|
||||||
<div className={s.mobileChat}>
|
<div className={s.mobileChat}>
|
||||||
<ChatContainer
|
<ChatContainer
|
||||||
messages={messages}
|
messages={messages}
|
||||||
@ -173,8 +168,8 @@ export default function ContentComponent() {
|
|||||||
isModerator={false}
|
isModerator={false}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
/>
|
/>
|
||||||
|
<ChatTextField />
|
||||||
</div>
|
</div>
|
||||||
<ChatTextField />
|
|
||||||
</div>
|
</div>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
)}
|
)}
|
||||||
@ -186,7 +181,7 @@ export default function ContentComponent() {
|
|||||||
<FollowerCollection total={total} followers={followers} />
|
<FollowerCollection total={total} followers={followers} />
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<Footer version={version} />
|
{!isMobile && <Footer version={version} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isChatVisible && !isMobile && <Sidebar />}
|
{isChatVisible && !isMobile && <Sidebar />}
|
||||||
|
|||||||
@ -5,15 +5,22 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.4rem .7rem;
|
||||||
background-color: var(--default-bg-color);
|
background-color: var(--default-bg-color);
|
||||||
.logo {
|
.logo {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
span {
|
span {
|
||||||
margin-left: 1rem;
|
margin-left: .5rem;
|
||||||
font-size: 1.7rem;
|
font-size: 1.5rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.header {
|
||||||
|
line-height: 5vh;
|
||||||
|
height: 5vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -4,8 +4,9 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: clamp(4rem, 10vw, 120px);
|
margin-right: .5rem;
|
||||||
height: clamp(4rem, 10vw, 120px);
|
width: clamp(2.5vh, 9vw, 120px);
|
||||||
|
height: clamp(2.5vh, 9vw, 120px);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
@ -27,3 +28,4 @@
|
|||||||
background-position: center;
|
background-position: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,9 +7,8 @@
|
|||||||
width: clamp(200px, 100%, 300px);
|
width: clamp(200px, 100%, 300px);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
;
|
|
||||||
background-color: var(--theme-background-secondary);
|
background-color: var(--theme-background-secondary);
|
||||||
margin: auto;
|
margin: 1rem auto;
|
||||||
border-radius: var(--theme-rounded-corners);
|
border-radius: var(--theme-rounded-corners);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|||||||
1
web/components/ui/Statusbar/index.ts
Normal file
1
web/components/ui/Statusbar/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './Statusbar';
|
||||||
@ -4,3 +4,4 @@ export { default as Footer } from './Footer/index';
|
|||||||
export { default as Content } from './Content/index';
|
export { default as Content } from './Content/index';
|
||||||
export { default as ModIcon } from './ModIcon';
|
export { default as ModIcon } from './ModIcon';
|
||||||
export { default as ServerLogo } from './Logo';
|
export { default as ServerLogo } from './Logo';
|
||||||
|
export { default as StatusBar } from './Statusbar';
|
||||||
|
|||||||
@ -10,3 +10,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.player {
|
||||||
|
height: 30vh !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -9,11 +9,17 @@ body {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: var(--theme-font-family), var(--theme-header-font-family), sans-serif;
|
font-family: var(--theme-font-family), var(--theme-header-font-family), sans-serif;
|
||||||
font-size: clamp(14px, 1.5vw, 17px);
|
font-size: clamp(14px, 1vw, 17px);
|
||||||
background-color: var(--default-bg-color);
|
background-color: var(--default-bg-color);
|
||||||
color: var(--default-text-color);
|
color: var(--default-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// a {
|
// a {
|
||||||
// color: inherit;
|
// color: inherit;
|
||||||
// text-decoration: none;
|
// text-decoration: none;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user