Skip to content

Commit

Permalink
Merge pull request #88 from amanojs/develop
Browse files Browse the repository at this point in the history
Release(2.0.0): Streaming!!
  • Loading branch information
amanojs authored May 24, 2021
2 parents 431141a + 368dc5e commit f1e21dc
Show file tree
Hide file tree
Showing 30 changed files with 1,004 additions and 220 deletions.
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"axios": "^0.21.1",
"hotkeys-js": "^3.8.5",
"js-cookie": "^2.2.1",
"notistack": "^1.0.5",
"react": "^17.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/components/AddForm/Presenter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const Presenter: React.FC<PresenterProps> = (props: PresenterProps) => {
style={{ height: '100%' }}
disableElevation
>
変更
ADD
</Button>
</Grid>
</Grid>
Expand Down
2 changes: 1 addition & 1 deletion src/components/AddForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const AddForm: React.FC<AddFormProps> = (props: AddFormProps) => {

const addMovieHandler = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
socket.emit('youtube_add_movie', videoId);
socket.emit('playlist_add', { video_url: videoId });
setVideoId('');
};

Expand Down
70 changes: 70 additions & 0 deletions src/components/Chat/Presenter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import * as React from 'react';
import { Grid, TextField, IconButton } from '@material-ui/core';
import './main.css';
import { Send } from '@material-ui/icons';
import { ChatItem } from '.';

interface PresenterProps {
chatList: ChatItem[];
chat: string;
userName: string;
onInput: (msg: string) => void;
onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void;
postChat: () => void;
isOpen: boolean;
smartphone?: boolean;
}

export const Presenter: React.FC<PresenterProps> = (props: PresenterProps) => {
return (
<React.Fragment>
<div className="chatList" style={{ height: props.isOpen ? '200px' : '0px' }}>
{props.chatList.map((chat, index) => {
return (
<Grid container className="chats" key={index}>
<Grid item xs={12} className="commentUser">
{chat.name}
</Grid>
<Grid item xs={12} className="commentText">
{chat.msg}
</Grid>
</Grid>
);
})}
</div>
<div className="chatActions">
<form style={{ width: '100%' }}>
<Grid container justify="center" alignItems="center" spacing={0}>
<Grid item xs={9} sm={10} md={10} lg={9} xl={9}>
<TextField
multiline
fullWidth
rowsMax={2}
color="secondary"
variant="standard"
size="small"
className="chatInput"
value={props.chat}
onKeyPress={(e) => props.onKeyDown(e)}
onChange={(e) => props.onInput(e.target.value)}
placeholder={props.userName + 'としてチャットを送信'}
/>
</Grid>
<Grid item xs={1} md={1} lg={1} xl={1}>
<IconButton type="button" size="medium" color="secondary" onClick={props.postChat}>
<Send fontSize="small" />
</IconButton>
</Grid>
{props.smartphone ? (
false
) : (
<Grid item xs={12}>
<div className="assist_key">Ctrl + Enterで送信</div>
</Grid>
)}
</Grid>
</form>
</div>
</React.Fragment>
);
};
67 changes: 67 additions & 0 deletions src/components/Chat/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from 'react';
import { useSelector } from 'react-redux';
import { State } from '../../store/store';
import { Presenter } from './Presenter';

interface ChatProps {
socket: SocketIOClient.Socket;
chatList: ChatItem[];
setChatList: React.Dispatch<React.SetStateAction<ChatItem[]>>;
smartphone?: boolean;
isOpen: boolean;
}

export interface ChatItem {
name: string;
id: string;
msg: string;
}

export const Chat: React.FC<ChatProps> = (props: ChatProps) => {
const socket: SocketIOClient.Socket = props.socket;
const [chat, setChat] = React.useState<string>('');
const userName: string = useSelector((state: State) => state.room.userName);
const maxNameLength = 6;
const userNameSlice = userName.length <= maxNameLength ? userName : userName.slice(0, maxNameLength) + '..';

React.useEffect(() => {
const elements = document.getElementsByClassName('chatList');
for (let i = 0; i < elements.length; i++) {
const bottom = elements[i].scrollHeight - elements[i].clientHeight;
elements[i].scroll(0, bottom);
}
}, [props.chatList]);

const onInput = (msg: string) => {
setChat(msg);
};

const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
if (e.ctrlKey && e.code === 'Enter') {
postChat();
}
};

/** チャット送信時の処理 */
const postChat = () => {
const postData = chat.replace('\n', '');
console.log('saf');
if (postData !== '') {
socket.emit('post_chat', postData);
setChat('');
}
};

return (
<Presenter
chatList={props.chatList}
chat={chat}
userName={userNameSlice}
onInput={onInput}
onKeyDown={onKeyDown}
postChat={postChat}
isOpen={props.isOpen}
smartphone={props.smartphone}
/>
);
};
41 changes: 41 additions & 0 deletions src/components/Chat/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.chatList{
flex-grow: 1;
background: #F9F9F9;
box-sizing: border-box;
overflow-y: scroll;
overflow-x: hidden;
word-wrap: break-word;
transition: 0.5s;
}
.chats{
padding: 10px 15px 10px 15px;
}
.commentUser{
color: #1DD1A1;
font-family: Noto Sans JP;
font-size: 14px;
}
.commentText{
color: #777;
font-family: Noto Sans JP;
}
.chatActions{
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid #eee;
height: 70px;
padding: 5px 0;
background: #fff;
}
.chatInput ::placeholder{
font-size: 14px;
}
.assist_key{
text-align: end;
box-sizing: border-box;
padding: 0 60px;
font-size: 12px;
color: #777;
font-family: Noto Sans JP;
}
6 changes: 4 additions & 2 deletions src/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import * as React from 'react';
import { useSelector } from 'react-redux';
import { useHistory } from 'react-router';
import { State } from '../../store/store';
import { Presenter } from './Presenter';

export const Header: React.FC = () => {
const history = useHistory();

const header = useSelector((state: State) => state.app.header);
const backClick = () => {
history.push('/');
};
return <Presenter backClick={backClick} />;
return header ? <Presenter backClick={backClick} /> : <React.Fragment></React.Fragment>;
};

export default Header;
115 changes: 115 additions & 0 deletions src/components/PlayList/Presenter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import * as React from 'react';
import { Grid, IconButton } from '@material-ui/core';
import './main.css';
import { SkipNext, Delete } from '@material-ui/icons';
import { PlayListItem } from '.';

interface PresenterProps {
socket: SocketIOClient.Socket;
nowPlaying: PlayListItem;
skipPlayList: () => void;
deletePlayListItem: (index: number) => void;
deletePlayList: () => void;
playList: PlayListItem[];
isOpen: boolean;
smartphone?: boolean;
}

export const Presenter: React.FC<PresenterProps> = (props: PresenterProps) => {
const playList = props.playList;
const nowPlaying = props.nowPlaying;
return (
<React.Fragment>
<Grid className="listControll" container spacing={1}>
<Grid item>
<IconButton size="small" onClick={props.skipPlayList}>
<SkipNext fontSize="small" />
</IconButton>
</Grid>
<Grid item>
<IconButton size="small" onClick={props.deletePlayList}>
<Delete fontSize="small" />
</IconButton>
</Grid>
</Grid>
<div className="movieDetail">
<div style={{ color: '#999', fontSize: '14px', paddingBottom: '4px' }}>now playing...</div>
<Grid container spacing={1}>
<Grid item xs={4}>
<img
src={nowPlaying.thumbnail}
width="100%"
alt="samune"
style={{ objectFit: 'cover', verticalAlign: 'bottom' }}
/>
</Grid>
<Grid item xs={8}>
<h4
style={{
margin: '0px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
fontSize: '14px'
}}
>
{nowPlaying.title}
</h4>
<p style={{ margin: '0px', fontSize: '14px', color: '#8f8f8f' }}>{nowPlaying.requester} がリクエスト</p>
</Grid>
</Grid>
</div>
<div className="movieList" style={{ height: props.isOpen ? '200px' : '0px' }}>
{playList.map((movie, index) => {
return (
<Grid
container
className="movies"
alignItems="center"
style={{ background: '#fff', borderBottom: '1px solid #eee' }}
key={index}
>
<Grid item xs={4} style={{ position: 'relative' }}>
<div
style={{
position: 'absolute',
top: 0,
left: 0,
padding: '0 5px',
fontSize: '13px',
fontFamily: 'Noto Sans JP',
color: '#fff',
background: 'rgba(0,0,0,0.3)'
}}
>
{index + 1}
</div>
<img
src={movie.thumbnail}
width="100%"
alt="samu"
style={{ objectFit: 'cover', verticalAlign: 'bottom' }}
/>
</Grid>
<Grid item xs={8} style={{ padding: '0px 10px 0 10px' }}>
<h4
style={{
margin: '0px',
fontSize: '14px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
color: '#3f3f3f'
}}
>
{movie.title}
</h4>
<p style={{ margin: '0px', fontSize: '14px', color: '#8f8f8f' }}>{movie.requester} がリクエスト</p>
</Grid>
</Grid>
);
})}
</div>
</React.Fragment>
);
};
35 changes: 35 additions & 0 deletions src/components/PlayList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from 'react';
import { Presenter } from './Presenter';

interface PlayListProps {
socket: SocketIOClient.Socket;
nowPlaying: PlayListItem;
playList: PlayListItem[];
skipPlayList: () => void;
deletePlayListItem: (index: number) => void;
deletePlayList: () => void;
isOpen: boolean;
smartphone?: boolean;
}

export interface PlayListItem {
videoId: string;
thumbnail: string;
title: string;
requester: string;
}

export const PlayList: React.FC<PlayListProps> = (props: PlayListProps) => {
return (
<Presenter
socket={props.socket}
nowPlaying={props.nowPlaying}
playList={props.playList}
skipPlayList={props.skipPlayList}
deletePlayListItem={props.deletePlayListItem}
deletePlayList={props.deletePlayList}
isOpen={props.isOpen}
smartphone={props.smartphone}
/>
);
};
Loading

0 comments on commit f1e21dc

Please sign in to comment.