From 20c91921dd4d15b895d541ed2298fd94fdf6b63f Mon Sep 17 00:00:00 2001 From: amanojs Date: Fri, 2 Apr 2021 05:09:52 +0900 Subject: [PATCH 01/84] =?UTF-8?q?feat(src/createForm,=20src/InputText):=20?= =?UTF-8?q?=E3=83=AB=E3=83=BC=E3=83=A0=E4=BD=9C=E6=88=90=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=83=A0=E3=81=AE=E3=83=91=E3=83=BC=E3=83=84=E3=83=87?= =?UTF-8?q?=E3=82=B6=E3=82=A4=E3=83=B3=20ver0.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Input + labelのAtomsを切り出しました。 --- .../CreateForm/CreateForm.stories.tsx | 15 +++++++++++++ src/components/CreateForm/Presenter.tsx | 22 +++++++++++++++++++ src/components/CreateForm/index.tsx | 10 +++++++++ .../InputText/InputText.stories.tsx | 19 ++++++++++++++++ src/components/InputText/Presenter.tsx | 19 ++++++++++++++++ src/components/InputText/index.tsx | 15 +++++++++++++ 6 files changed, 100 insertions(+) create mode 100644 src/components/CreateForm/CreateForm.stories.tsx create mode 100644 src/components/CreateForm/Presenter.tsx create mode 100644 src/components/CreateForm/index.tsx create mode 100644 src/components/InputText/InputText.stories.tsx create mode 100644 src/components/InputText/Presenter.tsx create mode 100644 src/components/InputText/index.tsx diff --git a/src/components/CreateForm/CreateForm.stories.tsx b/src/components/CreateForm/CreateForm.stories.tsx new file mode 100644 index 0000000..d1347e4 --- /dev/null +++ b/src/components/CreateForm/CreateForm.stories.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Story, Meta } from '@storybook/react/types-6-0'; +import { CreateForm, ContainerProps } from './index'; + +export default { + title: 'Block/CreateForm', + component: CreateForm +} as Meta; + +const Template: Story = (props: ContainerProps) => ; + +export const NoValue = Template.bind({}); +NoValue.args = { + width: '100px' +}; diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx new file mode 100644 index 0000000..f931674 --- /dev/null +++ b/src/components/CreateForm/Presenter.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { Card, Input } from '@material-ui/core'; + +interface PresenterProps { + width: string; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + const useStyles = makeStyles({ + form_card: { + width: props.width, + padding: '10px' + } + }); + const classes = useStyles(); + return ( + + + + ); +}; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx new file mode 100644 index 0000000..51bb62a --- /dev/null +++ b/src/components/CreateForm/index.tsx @@ -0,0 +1,10 @@ +import * as React from 'react'; +import { Presenter } from './Presenter'; + +export interface ContainerProps { + width: string; +} + +export const CreateForm: React.FC = (props: ContainerProps) => { + return ; +}; diff --git a/src/components/InputText/InputText.stories.tsx b/src/components/InputText/InputText.stories.tsx new file mode 100644 index 0000000..e7aa714 --- /dev/null +++ b/src/components/InputText/InputText.stories.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Story, Meta } from '@storybook/react/types-6-0'; +import { InputText, ContainerProps } from './index'; + +export default { + title: 'Atom/InputText', + component: InputText +} as Meta; + +const Template: Story = (props: ContainerProps) => ; + +export const Test = Template.bind({}); +Test.args = { + label: '名前', + placeholder: 'super man', + value: '', + // eslint-disable-next-line @typescript-eslint/no-empty-function + onChange: () => {} +}; diff --git a/src/components/InputText/Presenter.tsx b/src/components/InputText/Presenter.tsx new file mode 100644 index 0000000..1b9746c --- /dev/null +++ b/src/components/InputText/Presenter.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import { Input } from '@material-ui/core'; + +interface PresenterProps { + label: string; + placeholder?: string; + value?: string; + onChange: (e: React.ChangeEvent) => void; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + return ( +
+ + +
+ ); +}; diff --git a/src/components/InputText/index.tsx b/src/components/InputText/index.tsx new file mode 100644 index 0000000..0f95564 --- /dev/null +++ b/src/components/InputText/index.tsx @@ -0,0 +1,15 @@ +import * as React from 'react'; +import { Presenter } from './Presenter'; + +export interface ContainerProps { + label: string; + placeholder?: string; + value?: string; + onChange: (e: React.ChangeEvent) => void; +} + +export const InputText: React.FC = (props: ContainerProps) => { + return ( + + ); +}; From 544af06a2248e7ed4c0ac7ebe9f800af769008f7 Mon Sep 17 00:00:00 2001 From: amanojs Date: Fri, 2 Apr 2021 23:14:57 +0900 Subject: [PATCH 02/84] =?UTF-8?q?feat(src/components/CreateForm):=20Input?= =?UTF-8?q?=E3=81=AE=E7=AE=A1=E7=90=86=E3=82=92Container=E5=81=B4=E3=81=AB?= =?UTF-8?q?=E6=8C=81=E3=81=9F=E3=81=9B=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Presenter側ではmapを使って展開。 --- .../CreateForm/CreateForm.stories.tsx | 4 +--- src/components/CreateForm/Presenter.tsx | 23 +++++++++++++++++-- src/components/CreateForm/index.tsx | 17 ++++++++++++-- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/components/CreateForm/CreateForm.stories.tsx b/src/components/CreateForm/CreateForm.stories.tsx index d1347e4..70edf34 100644 --- a/src/components/CreateForm/CreateForm.stories.tsx +++ b/src/components/CreateForm/CreateForm.stories.tsx @@ -10,6 +10,4 @@ export default { const Template: Story = (props: ContainerProps) => ; export const NoValue = Template.bind({}); -NoValue.args = { - width: '100px' -}; +NoValue.args = {}; diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index f931674..d09d72e 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -1,9 +1,18 @@ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Card, Input } from '@material-ui/core'; +import { Card } from '@material-ui/core'; +import { InputText } from '../InputText'; interface PresenterProps { width: string; + inputs: Input[]; +} + +export interface Input { + label: string; + placeholder: string; + value: string; + onChange: (e: React.ChangeEvent) => void; } export const Presenter: React.FC = (props: PresenterProps) => { @@ -16,7 +25,17 @@ export const Presenter: React.FC = (props: PresenterProps) => { const classes = useStyles(); return ( - + {props.inputs.map((input) => { + return ( + + ); + })} ); }; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 51bb62a..c644192 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -1,10 +1,23 @@ import * as React from 'react'; -import { Presenter } from './Presenter'; +import { Presenter, Input } from './Presenter'; export interface ContainerProps { width: string; + onChange: (e: React.ChangeEvent) => void; } export const CreateForm: React.FC = (props: ContainerProps) => { - return ; + const [userName, setUserName] = React.useState(''); + const inputs: Input[] = [ + { + label: 'ユーザネーム', + placeholder: 'superman', + value: userName, + onChange: (e) => setUserName(e.target.value) + } + ]; + return ; +}; +CreateForm.defaultProps = { + width: '100%' }; From 976c060f57c6ddc7d7f2ee9f762435d36f7ca0b4 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Sat, 3 Apr 2021 05:20:51 +0900 Subject: [PATCH 03/84] =?UTF-8?q?feat(src/components/CreateForm,=20src/com?= =?UTF-8?q?ponents/InputText):=20=E3=83=AB=E3=83=BC=E3=83=A0=E4=BD=9C?= =?UTF-8?q?=E6=88=90=E3=83=95=E3=82=A9=E3=83=BC=E3=83=A0=E3=81=AE=E3=83=91?= =?UTF-8?q?=E3=83=BC=E3=83=84=E3=83=87=E3=82=B6=E3=82=A4=E3=83=B3=20ver1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CreateForm/CreateForm.stories.tsx | 4 +- src/components/CreateForm/Presenter.tsx | 46 ++++++++++--------- src/components/CreateForm/index.tsx | 12 +++-- src/components/InputText/Presenter.tsx | 12 +++-- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/components/CreateForm/CreateForm.stories.tsx b/src/components/CreateForm/CreateForm.stories.tsx index 70edf34..2a83add 100644 --- a/src/components/CreateForm/CreateForm.stories.tsx +++ b/src/components/CreateForm/CreateForm.stories.tsx @@ -10,4 +10,6 @@ export default { const Template: Story = (props: ContainerProps) => ; export const NoValue = Template.bind({}); -NoValue.args = {}; +NoValue.args = { + width: '400px' +}; diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index d09d72e..bee86cd 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -1,41 +1,43 @@ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Card } from '@material-ui/core'; -import { InputText } from '../InputText'; +import { Grid, Card, Button } from '@material-ui/core'; +import { InputText, ContainerProps as Input } from '../InputText'; -interface PresenterProps { +export interface PresenterProps { width: string; inputs: Input[]; -} - -export interface Input { - label: string; - placeholder: string; - value: string; - onChange: (e: React.ChangeEvent) => void; + submitEvent: () => void; } export const Presenter: React.FC = (props: PresenterProps) => { const useStyles = makeStyles({ form_card: { width: props.width, - padding: '10px' + padding: '30px 0' } }); const classes = useStyles(); return ( - {props.inputs.map((input) => { - return ( - - ); - })} + + {props.inputs.map((input) => { + return ( + + + + ); + })} + + + + ); }; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index c644192..97f9033 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -1,22 +1,24 @@ import * as React from 'react'; -import { Presenter, Input } from './Presenter'; +import { Presenter, PresenterProps } from './Presenter'; export interface ContainerProps { width: string; - onChange: (e: React.ChangeEvent) => void; } export const CreateForm: React.FC = (props: ContainerProps) => { const [userName, setUserName] = React.useState(''); - const inputs: Input[] = [ + const inputs: PresenterProps['inputs'] = [ { label: 'ユーザネーム', - placeholder: 'superman', + placeholder: '須鳥武 太郎', value: userName, onChange: (e) => setUserName(e.target.value) } ]; - return ; + const submitEvent = () => { + console.log('submit'); + }; + return ; }; CreateForm.defaultProps = { width: '100%' diff --git a/src/components/InputText/Presenter.tsx b/src/components/InputText/Presenter.tsx index 1b9746c..1d4fffa 100644 --- a/src/components/InputText/Presenter.tsx +++ b/src/components/InputText/Presenter.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Input } from '@material-ui/core'; +import { TextField } from '@material-ui/core'; interface PresenterProps { label: string; @@ -12,8 +12,14 @@ interface PresenterProps { export const Presenter: React.FC = (props: PresenterProps) => { return (
- - +
{props.label}
+
); }; From 04e15b34ffece414315a3bac91336c317df372a5 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Sat, 3 Apr 2021 09:30:33 +0900 Subject: [PATCH 04/84] =?UTF-8?q?feat(src/components/CreateForm,=20src/com?= =?UTF-8?q?ponents/InputText):=20=E3=83=90=E3=83=AA=E3=83=87=E3=83=BC?= =?UTF-8?q?=E3=82=B7=E3=83=A7=E3=83=B3=E5=87=A6=E7=90=86=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit リアルタイムバリデーションとサブミットバリデーションを追加。それに伴ってinputsの型にはInputTextから継承した新たな型の配列を使用。 re #1 --- src/components/CreateForm/Presenter.tsx | 9 ++-- src/components/CreateForm/index.tsx | 61 ++++++++++++++++++++++--- src/components/InputText/Presenter.tsx | 6 ++- src/components/InputText/index.tsx | 13 +++++- 4 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index bee86cd..c1cdaad 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; import { Grid, Card, Button } from '@material-ui/core'; -import { InputText, ContainerProps as Input } from '../InputText'; +import { InputText } from '../InputText'; +import { InputSub } from './index'; export interface PresenterProps { width: string; - inputs: Input[]; + inputs: InputSub[]; submitEvent: () => void; } @@ -20,11 +21,13 @@ export const Presenter: React.FC = (props: PresenterProps) => { return ( - {props.inputs.map((input) => { + {props.inputs.map((input: InputSub) => { return ( { error: boolean; msg: string }; + setter: React.Dispatch< + React.SetStateAction<{ + value: string; + error: boolean; + msg: string; + }> + >; +} + export const CreateForm: React.FC = (props: ContainerProps) => { - const [userName, setUserName] = React.useState(''); - const inputs: PresenterProps['inputs'] = [ + const [userName, setUserName] = React.useState({ value: '', error: false, msg: '' }); + + const inputs: InputSub[] = [ { - label: 'ユーザネーム', + label: 'ユーザネーム*', placeholder: '須鳥武 太郎', - value: userName, - onChange: (e) => setUserName(e.target.value) + value: userName.value, + error: userName.error, + msg: userName.msg, + onChange: function (e) { + const { error, msg } = this.validate(e.target.value); + this.setter({ value: e.target.value, error, msg }); + }, + validate: (val) => { + const response = { error: false, msg: '' }; + if (val === '') { + response.error = true; + response.msg = 'ユーザネームを入力してください'; + } else if (val.length > 13) { + response.error = true; + response.msg = '12文字以内で入力してください'; + } + return response; + }, + setter: setUserName } ]; + + for (const input of inputs) { + input.onChange = input.onChange.bind(input); + } + + const validateAll = () => { + let errorFlag = false; + for (const input of inputs) { + const response = input.validate(input.value); + if (response.error) errorFlag = true; + input.setter({ value: input.value, error: response.error, msg: response.msg }); + } + return errorFlag; + }; + const submitEvent = () => { + if (validateAll()) { + return alert('エラー項目があります'); + } console.log('submit'); }; + return ; }; CreateForm.defaultProps = { diff --git a/src/components/InputText/Presenter.tsx b/src/components/InputText/Presenter.tsx index 1d4fffa..73e253e 100644 --- a/src/components/InputText/Presenter.tsx +++ b/src/components/InputText/Presenter.tsx @@ -5,7 +5,9 @@ import { TextField } from '@material-ui/core'; interface PresenterProps { label: string; placeholder?: string; - value?: string; + value: string; + error: boolean; + msg: string; onChange: (e: React.ChangeEvent) => void; } @@ -15,6 +17,8 @@ export const Presenter: React.FC = (props: PresenterProps) => {
{props.label}
) => void; } export const InputText: React.FC = (props: ContainerProps) => { return ( - + ); }; From 90d4046dd88ef80477d0a85c7c2377f36e222ae5 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 3 Apr 2021 15:14:34 +0900 Subject: [PATCH 05/84] =?UTF-8?q?feat(src/pages/Home):=20Home=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=83=87=E3=82=B6=E3=82=A4=E3=83=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home/Home.stories.tsx | 12 +++++++++ src/pages/Home/Presenter.tsx | 41 +++++++++++++++++++++++++++++++ src/pages/Home/index.tsx | 6 +++++ src/pages/Home/main.css | 43 +++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 src/pages/Home/Home.stories.tsx create mode 100644 src/pages/Home/Presenter.tsx create mode 100644 src/pages/Home/index.tsx create mode 100644 src/pages/Home/main.css diff --git a/src/pages/Home/Home.stories.tsx b/src/pages/Home/Home.stories.tsx new file mode 100644 index 0000000..b84a683 --- /dev/null +++ b/src/pages/Home/Home.stories.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Story, Meta } from '@storybook/react/types-6-0'; +import { Home } from '.'; + +export default { + title: 'Page/Home', + component: Home +} as Meta; + +const Template: Story = () => ; + +export const Default = Template.bind({}); diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx new file mode 100644 index 0000000..0a2fd73 --- /dev/null +++ b/src/pages/Home/Presenter.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import { Box, Grid } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import './main.css'; + +export const Presenter: React.FC = () => { + const useStyles = makeStyles({ + baseGrid: { + height: '100%' + } + }); + const classes = useStyles(); + return ( +
+ + Streaming + + + + +
+ + + + + +
+
+ ); +}; diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx new file mode 100644 index 0000000..3713b5e --- /dev/null +++ b/src/pages/Home/index.tsx @@ -0,0 +1,6 @@ +import * as React from 'react'; +import { Presenter } from './Presenter'; + +export const Home: React.FC = () => { + return ; +}; diff --git a/src/pages/Home/main.css b/src/pages/Home/main.css new file mode 100644 index 0000000..e96c4de --- /dev/null +++ b/src/pages/Home/main.css @@ -0,0 +1,43 @@ +.base { + position: relative; + width: 100%; + height: 100vh; + background: rgb(255,108,200); + background: linear-gradient(107deg, rgba(255,108,200,1) 0%, rgba(255,111,0,1) 100%); +} + +.logo{ + position: absolute; + top: 20px; + left: 20px; + font-size: 35px; + font-weight: bold; + text-shadow: 2px 2px 10px #777; + color: #fff; +} +.logo > span{ + font-size: 47px; + text-shadow: 1px 1px 5px #666; +} + +.custom-shape-divider-bottom-1617426966 { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + overflow: hidden; + line-height: 0; + transform: rotate(180deg); +} + +.custom-shape-divider-bottom-1617426966 svg { + position: relative; + display: block; + width: calc(100% + 1.3px); + height: 308px; + transform: rotateY(180deg); +} + +.custom-shape-divider-bottom-1617426966 .shape-fill { + fill: #FFFFFF; +} \ No newline at end of file From edb284c39ee723b3d7f694e1e4dd805dc844f0b1 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 3 Apr 2021 21:09:17 +0900 Subject: [PATCH 06/84] =?UTF-8?q?feat(src/App.tsx,=20src/components,=20src?= =?UTF-8?q?/pages):=20Home=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=8D=E3=83=B3?= =?UTF-8?q?=E3=83=88,CreateForm=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=8D?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=82=92=E7=B5=90=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 全体のバランスをみながらリデザインしました。 re #4 --- src/App.tsx | 13 +----- src/components/CreateForm/Presenter.tsx | 55 ++++++++++++++++--------- src/components/CreateForm/index.tsx | 2 +- src/components/InputText/Presenter.tsx | 3 +- src/config/theme.ts | 9 +++- src/pages/Home/Presenter.tsx | 17 +++++--- src/pages/Home/main.css | 51 ++++++++++++++++------- 7 files changed, 94 insertions(+), 56 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index d7213a6..05934d5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,21 +3,12 @@ import logo from './logo.svg'; import './App.css'; import { ThemeProvider } from '@material-ui/styles'; import { theme } from './config/theme'; +import { Home } from './pages/Home'; function App() { return ( -
-
- logo -

- Edit src/App.tsx and save to reload. -

- - Learn React - -
-
+
); } diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index c1cdaad..fb083af 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Grid, Card, Button } from '@material-ui/core'; +import { Grid, Card, Button, Box } from '@material-ui/core'; +import { Home, PlayArrow } from '@material-ui/icons'; import { InputText } from '../InputText'; import { InputSub } from './index'; @@ -14,31 +15,45 @@ export const Presenter: React.FC = (props: PresenterProps) => { const useStyles = makeStyles({ form_card: { width: props.width, - padding: '30px 0' + padding: '55px 0' } }); const classes = useStyles(); return ( - {props.inputs.map((input: InputSub) => { - return ( - - - - ); - })} - - + + + + ルーム作成 + + + {props.inputs.map((input: InputSub) => { + return ( + + + + ); + })} + + + diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 5dcd8a7..95eadba 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -62,7 +62,7 @@ export const CreateForm: React.FC = (props: ContainerProps) => { const submitEvent = () => { if (validateAll()) { - return alert('エラー項目があります'); + return; } console.log('submit'); }; diff --git a/src/components/InputText/Presenter.tsx b/src/components/InputText/Presenter.tsx index 73e253e..03e6351 100644 --- a/src/components/InputText/Presenter.tsx +++ b/src/components/InputText/Presenter.tsx @@ -14,7 +14,7 @@ interface PresenterProps { export const Presenter: React.FC = (props: PresenterProps) => { return (
-
{props.label}
+
{props.label}
= (props: PresenterProps) => { variant="outlined" value={props.value} onChange={props.onChange} + color="secondary" placeholder={props.placeholder} />
diff --git a/src/config/theme.ts b/src/config/theme.ts index d8ce0e6..fdee416 100644 --- a/src/config/theme.ts +++ b/src/config/theme.ts @@ -3,10 +3,15 @@ import { createMuiTheme } from '@material-ui/core/styles'; export const theme = createMuiTheme({ palette: { primary: { - main: '#1976d2' + main: '#FF6F26', + contrastText: '#fff' }, secondary: { - main: '#dc004e' + main: '#1dd1a1', + contrastText: '#fefefe' + }, + info: { + main: '#1289A7' }, background: { default: '#fffafa' diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index 0a2fd73..e4f8d73 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -1,24 +1,29 @@ import * as React from 'react'; import { Box, Grid } from '@material-ui/core'; +import { CreateForm } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; import './main.css'; export const Presenter: React.FC = () => { const useStyles = makeStyles({ baseGrid: { - height: '100%' + position: 'relative', + height: '100%', + zIndex: 2 } }); const classes = useStyles(); return (
- - Streaming - - + + + Streaming!! + + + -
+
span{ - font-size: 47px; - text-shadow: 1px 1px 5px #666; + font-size: 80px; + color: #55E6C1; +} + +.create_room_head{ + text-shadow:1px 0 0 #666,0 1px 0 #666,-1px 0 0 #666,0 -1px 0 #666; + font-size: 20px; + font-weight: bold; + line-height: 0px; + color: #fff; } -.custom-shape-divider-bottom-1617426966 { +.custom-shape { position: absolute; bottom: 0; left: 0; width: 100%; overflow: hidden; line-height: 0; - transform: rotate(180deg); + transform: rotate(180deg) translate3d(0,0,0); + z-index: 1; } -.custom-shape-divider-bottom-1617426966 svg { +.custom-shape svg { position: relative; - display: block; width: calc(100% + 1.3px); - height: 308px; + height: 250px; transform: rotateY(180deg); + z-index: 1; } -.custom-shape-divider-bottom-1617426966 .shape-fill { +.custom-shape .shape-fill { fill: #FFFFFF; } \ No newline at end of file From 99e97e08cad13bddc84d93fcf67327c231722ced Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 4 Apr 2021 02:45:50 +0900 Subject: [PATCH 07/84] =?UTF-8?q?feat(src/config/route.tsx):=20Routing?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A(=E9=81=85=E5=BB=B6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeSplitingしたルーティングを実装しました。 --- src/App.css | 38 ---------------------- src/App.tsx | 6 ++-- src/components/Loading/Loading.stories.tsx | 11 +++++++ src/components/Loading/index.tsx | 16 +++++++++ src/config/route.tsx | 36 ++++++++++++++++++++ src/index.css | 30 +++++++++-------- src/logo.svg | 1 - src/pages/Home/Home.stories.tsx | 2 +- src/pages/Home/index.tsx | 4 ++- src/pages/Home/main.css | 18 ++++++++-- 10 files changed, 101 insertions(+), 61 deletions(-) delete mode 100644 src/App.css create mode 100644 src/components/Loading/Loading.stories.tsx create mode 100644 src/components/Loading/index.tsx create mode 100644 src/config/route.tsx delete mode 100644 src/logo.svg diff --git a/src/App.css b/src/App.css deleted file mode 100644 index 74b5e05..0000000 --- a/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/App.tsx b/src/App.tsx index 05934d5..60d6422 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,14 +1,12 @@ import React from 'react'; -import logo from './logo.svg'; -import './App.css'; import { ThemeProvider } from '@material-ui/styles'; import { theme } from './config/theme'; -import { Home } from './pages/Home'; +import { Routes } from './config/route'; function App() { return ( - + ); } diff --git a/src/components/Loading/Loading.stories.tsx b/src/components/Loading/Loading.stories.tsx new file mode 100644 index 0000000..8e41c7d --- /dev/null +++ b/src/components/Loading/Loading.stories.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { Story, Meta } from '@storybook/react/types-6-0'; +import { Loading } from './'; + +export default { + title: 'Page/Loading', + component: Loading +} as Meta; + +const Template: Story = () => ; +export const Default = Template.bind({}); diff --git a/src/components/Loading/index.tsx b/src/components/Loading/index.tsx new file mode 100644 index 0000000..580833f --- /dev/null +++ b/src/components/Loading/index.tsx @@ -0,0 +1,16 @@ +import * as React from 'react'; +import { Box, CircularProgress } from '@material-ui/core'; + +export const Loading: React.FC = () => { + return ( + + + + ); +}; diff --git a/src/config/route.tsx b/src/config/route.tsx new file mode 100644 index 0000000..f73a3f9 --- /dev/null +++ b/src/config/route.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; +import { Loading } from '../components/Loading'; + +const Home = React.lazy(() => { + return Promise.all([import('../pages/Home'), new Promise((resolve) => setTimeout(resolve, 1000))]).then( + ([moduleExports]) => moduleExports + ); +}); + +interface RouteBase { + path: string; + exact: boolean; + name: string; + component: React.LazyExoticComponent | React.FC; +} + +const routebases: Array = [{ path: '/', exact: true, name: 'Home', component: Home }]; + +export const Routes: React.FC = () => { + const makeRoute = (routebase: RouteBase) => { + return ( + + + + ); + }; + + return ( + + }> + {routebases.map((routebase: RouteBase) => makeRoute(routebase))} + + + ); +}; diff --git a/src/index.css b/src/index.css index ec2585e..e3c40f7 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,17 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} +body{ + margin: 0; + padding: 0; + font-family: 'Noto Sans JP', + 'Lato', + '游ゴシック Medium', + '游ゴシック体', + 'Yu Gothic Medium', + 'YuGothic', + 'ヒラギノ角ゴ ProN', + 'Hiragino Kaku Gothic ProN', + 'メイリオ', + 'Meiryo', + 'MS Pゴシック', + 'MS PGothic', + 'sans-serif'; +} \ No newline at end of file diff --git a/src/logo.svg b/src/logo.svg deleted file mode 100644 index 9dfc1c0..0000000 --- a/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/pages/Home/Home.stories.tsx b/src/pages/Home/Home.stories.tsx index b84a683..80a2d7f 100644 --- a/src/pages/Home/Home.stories.tsx +++ b/src/pages/Home/Home.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; -import { Home } from '.'; +import Home from './'; export default { title: 'Page/Home', diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 3713b5e..fc6e88d 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,6 +1,8 @@ import * as React from 'react'; import { Presenter } from './Presenter'; -export const Home: React.FC = () => { +const Home: React.FC = () => { return ; }; + +export default Home; diff --git a/src/pages/Home/main.css b/src/pages/Home/main.css index d9c67fb..704b14b 100644 --- a/src/pages/Home/main.css +++ b/src/pages/Home/main.css @@ -1,9 +1,10 @@ - +@import url('https://fonts.googleapis.com/css2?family=Fredoka+One&display=swap'); .base { position: relative; width: 100%; height: 100vh; - animation: gradient 12s ease infinite; + opacity: 1; + animation: gradient 12s ease infinite , fadein 1.4s ease; background: linear-gradient(45deg, #23d5ab,#23a6d5,#ee7752 ); background-size: 190% 190%; } @@ -19,10 +20,21 @@ } } +@keyframes fadein { +0% { + opacity: 0; +} +100% { + opacity: 1; +} +} + .logo{ + font-family: 'Fredoka One', cursive; + font-weight: bold; + letter-spacing: 3px; position: relative; font-size: 60px; - font-weight: bold; color: #fff; z-index: 2; text-align: center; From 8201c7c42ca95139c0e1fc9541dfa2d9e8e772c3 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 4 Apr 2021 14:05:01 +0900 Subject: [PATCH 08/84] =?UTF-8?q?feat(src/pages/Home):=20Home=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=AEwave=E3=82=92=E5=8B=95=E3=81=8F?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cssアニメーション --- src/assets/wave.png | Bin 0 -> 6104 bytes src/pages/Home/Presenter.tsx | 19 +----------- src/pages/Home/main.css | 55 ++++++++++++++++++++++++++--------- 3 files changed, 42 insertions(+), 32 deletions(-) create mode 100644 src/assets/wave.png diff --git a/src/assets/wave.png b/src/assets/wave.png new file mode 100644 index 0000000000000000000000000000000000000000..7987492d7bdde87ec0ee3e64d64361e61b284339 GIT binary patch literal 6104 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 L+f^S8`RacFjG<$k literal 0 HcmV?d00001 diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index e4f8d73..6109d41 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -23,24 +23,7 @@ export const Presenter: React.FC = () => { -
- - - - - -
+
); }; diff --git a/src/pages/Home/main.css b/src/pages/Home/main.css index 704b14b..75cbbdc 100644 --- a/src/pages/Home/main.css +++ b/src/pages/Home/main.css @@ -52,25 +52,52 @@ color: #fff; } -.custom-shape { +.wave { position: absolute; bottom: 0; left: 0; width: 100%; - overflow: hidden; - line-height: 0; - transform: rotate(180deg) translate3d(0,0,0); - z-index: 1; + height: 143px; + background: url(../../assets/wave.png); + animation: wave 10s linear infinite; +} +.wave::before { + content: ''; + position: absolute; + top: 0; + left: 0; + opacity: 0.6; + width: 100%; + height: 143px; + background: url(../../assets/wave.png); + animation: wave-reverse 10s linear infinite; +} +.wave::after { + content: ''; + position: absolute; + top: 0; + left: 0; + opacity: 0.4; + width: 100%; + height: 143px; + background: url(../../assets/wave.png); + animation-delay: -5s; + animation: wave 20s linear infinite; +} +@keyframes wave { +0% { + background-position: 0; +} +100% { + background-position: 1360px; } - -.custom-shape svg { - position: relative; - width: calc(100% + 1.3px); - height: 250px; - transform: rotateY(180deg); - z-index: 1; } -.custom-shape .shape-fill { - fill: #FFFFFF; +@keyframes wave-reverse { +0% { + background-position: 1360px; +} +100% { + background-position: 0; +} } \ No newline at end of file From f8a07adcdf99d489dd0e10b37949e8befe64d4df Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 4 Apr 2021 22:12:08 +0900 Subject: [PATCH 09/84] =?UTF-8?q?feat(src/pages/Room,=20router):=20Room?= =?UTF-8?q?=E3=83=9A=E3=83=BC=E3=82=B8=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC?= =?UTF-8?q?=E3=83=8D=E3=83=B3=E3=83=88=E3=81=B2=E3=81=AA=E5=BD=A2=E4=BD=9C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit socket-io-client 2.4 インストール。Roomコンテナでwebsocketサーバーに接続。 --- package-lock.json | 199 ++++++++++++++++++++++++++++++++ package.json | 2 + src/config/route.tsx | 12 +- src/pages/Home/Presenter.tsx | 2 +- src/pages/Room/Presenter.tsx | 14 +++ src/pages/Room/Room.stories.tsx | 1 + src/pages/Room/index.tsx | 28 +++++ src/pages/Room/main.css | 0 8 files changed, 255 insertions(+), 3 deletions(-) create mode 100644 src/pages/Room/Presenter.tsx create mode 100644 src/pages/Room/Room.stories.tsx create mode 100644 src/pages/Room/index.tsx create mode 100644 src/pages/Room/main.css diff --git a/package-lock.json b/package-lock.json index 96f6be5..b2d8407 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5658,6 +5658,12 @@ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" }, + "@types/socket.io-client": { + "version": "1.4.36", + "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz", + "integrity": "sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag==", + "dev": true + }, "@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -6053,6 +6059,11 @@ "regex-parser": "^2.2.11" } }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" + }, "agent-base": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", @@ -6382,6 +6393,11 @@ "is-string": "^1.0.5" } }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -7090,6 +7106,11 @@ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, "bail": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", @@ -7151,6 +7172,11 @@ } } }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -7205,6 +7231,11 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -8064,11 +8095,21 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" + }, "compose-function": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", @@ -9707,6 +9748,51 @@ "objectorarray": "^1.0.4" } }, + "engine.io-client": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.1.tgz", + "integrity": "sha512-oVu9kBkGbcggulyVF0kz6BV3ganqUeqXvD79WOFKa+11oK692w1NyFkuEj4xrkFRpZhn92QOqTk4RQq5LiBXbQ==", + "requires": { + "component-emitter": "~1.3.0", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~7.4.2", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "engine.io-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", + "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.4", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, "enhanced-resolve": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", @@ -11880,6 +11966,26 @@ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -12602,6 +12708,11 @@ "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -16762,6 +16873,16 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -21141,6 +21262,69 @@ } } }, + "socket.io-client": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz", + "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==", + "requires": { + "backo2": "1.0.2", + "component-bind": "1.0.0", + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "engine.io-client": "~3.5.0", + "has-binary2": "~1.0.2", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "socket.io-parser": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", + "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", + "requires": { + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "sockjs": { "version": "0.3.21", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", @@ -22131,6 +22315,11 @@ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -24574,6 +24763,11 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -24638,6 +24832,11 @@ "fd-slicer": "~1.1.0" } }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index fac3216..0e28098 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "react-dom": "^17.0.2", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", + "socket.io-client": "^2.4.0", "typescript": "^4.2.3", "web-vitals": "^1.1.1" }, @@ -64,6 +65,7 @@ "@storybook/react": "^6.2.1", "@types/material-ui": "^0.21.8", "@types/react-router-dom": "^5.1.7", + "@types/socket.io-client": "^1.4.36", "@typescript-eslint/eslint-plugin": "^4.20.0", "@typescript-eslint/parser": "^4.20.0", "eslint": "^7.23.0", diff --git a/src/config/route.tsx b/src/config/route.tsx index f73a3f9..44bf546 100644 --- a/src/config/route.tsx +++ b/src/config/route.tsx @@ -7,15 +7,23 @@ const Home = React.lazy(() => { ([moduleExports]) => moduleExports ); }); +const Room = React.lazy(() => { + return Promise.all([import('../pages/Room'), new Promise((resolve) => setTimeout(resolve, 1000))]).then( + ([moduleExports]) => moduleExports + ); +}); interface RouteBase { path: string; exact: boolean; name: string; - component: React.LazyExoticComponent | React.FC; + component: React.LazyExoticComponent | React.FC | typeof Room; } -const routebases: Array = [{ path: '/', exact: true, name: 'Home', component: Home }]; +const routebases: Array = [ + { path: '/', exact: true, name: 'Home', component: Home }, + { path: '/room', exact: true, name: 'Room', component: Room } +]; export const Routes: React.FC = () => { const makeRoute = (routebase: RouteBase) => { diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index 6109d41..816a7c2 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Box, Grid } from '@material-ui/core'; +import { Grid } from '@material-ui/core'; import { CreateForm } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; import './main.css'; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx new file mode 100644 index 0000000..f708595 --- /dev/null +++ b/src/pages/Room/Presenter.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; +import { Box } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; + +export const Presenter: React.FC = () => { + return ( + +
+
header
+
+ +
+ ); +}; diff --git a/src/pages/Room/Room.stories.tsx b/src/pages/Room/Room.stories.tsx new file mode 100644 index 0000000..aaf4046 --- /dev/null +++ b/src/pages/Room/Room.stories.tsx @@ -0,0 +1 @@ +import React from 'react'; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx new file mode 100644 index 0000000..341b7fe --- /dev/null +++ b/src/pages/Room/index.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import io from 'socket.io-client'; +import { Presenter } from './Presenter'; + +export default class Room extends React.Component { + state: { socket: null | SocketIOClient.Socket } = { + socket: null + }; + + componentDidMount(): void { + if (!this.state.socket) { + this.setState({ socket: io.connect(process.env.REACT_APP_API_URL as string) }); + } + } + + componentDidUpdate(): void { + console.log(this.state); + if (this.state.socket) { + this.state.socket?.on('connect', () => { + console.log('WebSocketサーバーに接続しました。'); + }); + } + } + + render(): JSX.Element { + return ; + } +} diff --git a/src/pages/Room/main.css b/src/pages/Room/main.css new file mode 100644 index 0000000..e69de29 From 9751090385273ba1ddfc27ceff135b7f76b3a2fb Mon Sep 17 00:00:00 2001 From: amanojs Date: Mon, 5 Apr 2021 07:56:03 +0900 Subject: [PATCH 10/84] =?UTF-8?q?feat(src/store,=20src/pages/Room):=20Redu?= =?UTF-8?q?x=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Redux Toolkitを使用してReduxを組み込みました。 re #8 --- package-lock.json | 88 ++++++++++++++++++++++++++++++++- package.json | 5 ++ src/config/route.tsx | 2 +- src/index.tsx | 8 ++- src/pages/Room/index.tsx | 39 +++++++-------- src/store/modules/roomModule.ts | 25 ++++++++++ src/store/store.ts | 21 ++++++++ 7 files changed, 164 insertions(+), 24 deletions(-) create mode 100644 src/store/modules/roomModule.ts create mode 100644 src/store/store.ts diff --git a/package-lock.json b/package-lock.json index b2d8407..b5f1b4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2224,6 +2224,17 @@ "react-lifecycles-compat": "^3.0.4" } }, + "@reduxjs/toolkit": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.5.1.tgz", + "integrity": "sha512-PngZKuwVZsd+mimnmhiOQzoD0FiMjqVks6ituO1//Ft5UEX5Ca9of13NEjo//pU22Jk7z/mdXVsmDfgsig1osA==", + "requires": { + "immer": "^8.0.1", + "redux": "^4.0.0", + "redux-thunk": "^2.3.0", + "reselect": "^4.0.0" + } + }, "@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -5389,6 +5400,15 @@ "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==", "dev": true }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", @@ -5607,6 +5627,17 @@ "@types/react": "*" } }, + "@types/react-redux": { + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.16.tgz", + "integrity": "sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/react-router": { "version": "5.1.13", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.13.tgz", @@ -5645,6 +5676,15 @@ "@types/react": "*" } }, + "@types/redux-logger": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/redux-logger/-/redux-logger-3.0.8.tgz", + "integrity": "sha512-zM+cxiSw6nZtRbxpVp9SE3x/X77Z7e7YAfHD1NkxJyJbAGSXJGF0E9aqajZfPOa/sTYnuwutmlCldveExuCeLw==", + "dev": true, + "requires": { + "redux": "^4.0.0" + } + }, "@types/resolve": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", @@ -9135,6 +9175,11 @@ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" }, + "deep-diff": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", + "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=" + }, "deep-equal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", @@ -19574,6 +19619,19 @@ "react-popper": "^2.2.4" } }, + "react-redux": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.3.tgz", + "integrity": "sha512-ZhAmQ1lrK+Pyi0ZXNMUZuYxYAZd59wFuVDGUt536kSGdD0ya9Q7BfsE95E3TsFLE3kOSFp5m6G5qbatE+Ic1+w==", + "requires": { + "@babel/runtime": "^7.12.1", + "@types/react-redux": "^7.1.16", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.13.1" + } + }, "react-refresh": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", @@ -19881,6 +19939,28 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "redux-logger": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", + "integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=", + "requires": { + "deep-diff": "^0.3.5" + } + }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "refractor": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.3.1.tgz", @@ -20287,6 +20367,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + }, "resolve": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", @@ -23040,8 +23125,7 @@ "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "optional": true + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "uuid-browser": { "version": "3.1.0", diff --git a/package.json b/package.json index 0e28098..d0a7ad5 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "dependencies": { "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", + "@reduxjs/toolkit": "^1.5.1", "@testing-library/jest-dom": "^5.11.10", "@testing-library/react": "^11.2.6", "@testing-library/user-event": "^12.8.3", @@ -14,10 +15,13 @@ "@types/react-dom": "^17.0.3", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-redux": "^7.2.3", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", + "redux-logger": "^3.0.6", "socket.io-client": "^2.4.0", "typescript": "^4.2.3", + "uuid": "^8.3.2", "web-vitals": "^1.1.1" }, "scripts": { @@ -65,6 +69,7 @@ "@storybook/react": "^6.2.1", "@types/material-ui": "^0.21.8", "@types/react-router-dom": "^5.1.7", + "@types/redux-logger": "^3.0.8", "@types/socket.io-client": "^1.4.36", "@typescript-eslint/eslint-plugin": "^4.20.0", "@typescript-eslint/parser": "^4.20.0", diff --git a/src/config/route.tsx b/src/config/route.tsx index 44bf546..76de98f 100644 --- a/src/config/route.tsx +++ b/src/config/route.tsx @@ -17,7 +17,7 @@ interface RouteBase { path: string; exact: boolean; name: string; - component: React.LazyExoticComponent | React.FC | typeof Room; + component: React.LazyExoticComponent | React.FC; } const routebases: Array = [ diff --git a/src/index.tsx b/src/index.tsx index ef2edf8..e85e3c5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,12 +1,18 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { Provider } from 'react-redux'; +import { setUpStore } from './store/store'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; +const store = setUpStore(); + ReactDOM.render( - + + + , document.getElementById('root') ); diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 341b7fe..ec1d252 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -1,28 +1,27 @@ import * as React from 'react'; import io from 'socket.io-client'; +import { useSelector, useDispatch } from 'react-redux'; +import roomModule, { RoomState } from '../../store/modules/roomModule'; +import { State } from '../../store/store'; import { Presenter } from './Presenter'; -export default class Room extends React.Component { - state: { socket: null | SocketIOClient.Socket } = { - socket: null - }; +const Room: React.FC = () => { + const [mount, mountKeeper] = React.useState(null); + const room = useSelector((state: State) => state.room); + const dispach = useDispatch(); + console.log(room); - componentDidMount(): void { - if (!this.state.socket) { - this.setState({ socket: io.connect(process.env.REACT_APP_API_URL as string) }); - } - } - - componentDidUpdate(): void { - console.log(this.state); - if (this.state.socket) { - this.state.socket?.on('connect', () => { - console.log('WebSocketサーバーに接続しました。'); + React.useEffect(() => { + if (!room.roomId) { + const socket = io.connect(process.env.REACT_APP_API_URL as string); + socket.on('connect', () => { + console.log('connected'); + dispach(roomModule.actions.setRoom({ roomId: 'iii' })); }); } - } + }, [mountKeeper]); + + return ; +}; - render(): JSX.Element { - return ; - } -} +export default Room; diff --git a/src/store/modules/roomModule.ts b/src/store/modules/roomModule.ts new file mode 100644 index 0000000..c03fbf3 --- /dev/null +++ b/src/store/modules/roomModule.ts @@ -0,0 +1,25 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; + +export interface RoomState { + roomId: string; +} + +const roomInitialState: RoomState = { + roomId: '' +}; + +// createSliceメソッドを使ってactionsとreducersを生成 +const socketsModule = createSlice({ + name: 'room', + initialState: roomInitialState, + reducers: { + setRoom: (state, action: PayloadAction) => { + Object.assign(state, action.payload); + }, + unsetRoom: (state, action: PayloadAction) => { + Object.assign(state, roomInitialState); + } + } +}); + +export default socketsModule; diff --git a/src/store/store.ts b/src/store/store.ts new file mode 100644 index 0000000..5993f68 --- /dev/null +++ b/src/store/store.ts @@ -0,0 +1,21 @@ +import { combineReducers, configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'; +import logger from 'redux-logger'; + +import roomModule, { RoomState } from './modules/roomModule'; + +export interface State { + room: RoomState; +} + +const rootReducer = combineReducers({ + room: roomModule.reducer +}); + +export const setUpStore = () => { + const middlewares = [...getDefaultMiddleware(), logger]; + const store = configureStore({ + reducer: rootReducer, + middleware: middlewares + }); + return store; +}; From 514afaa8d441935f53f24184d95b24fa715fb2d8 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 5 Apr 2021 21:16:50 +0900 Subject: [PATCH 11/84] =?UTF-8?q?feat(src/App,=20src/pages/Home):=20Websoc?= =?UTF-8?q?ket=E3=81=AERoom=E3=81=AB=E6=8E=A5=E7=B6=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Appにsocket clientを返却するgetSocket関数を実装。Promise型で非同期に扱える。 --- package-lock.json | 33 ++++++++++++++- src/App.tsx | 40 +++++++++++++++++-- src/components/CreateForm/index.tsx | 12 +++++- src/config/route.tsx | 7 ++-- .../{Home.stories.tsx => Home.*stories.tsx} | 6 +-- src/pages/Home/Presenter.tsx | 5 ++- src/pages/Home/index.tsx | 5 ++- src/pages/Room/index.tsx | 4 +- 8 files changed, 93 insertions(+), 19 deletions(-) rename src/pages/Home/{Home.stories.tsx => Home.*stories.tsx} (58%) diff --git a/package-lock.json b/package-lock.json index b5f1b4f..5a2757d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7271,6 +7271,15 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", @@ -11197,6 +11206,12 @@ } } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "filesize": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", @@ -16168,6 +16183,12 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "optional": true + }, "nanoid": { "version": "3.1.22", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz", @@ -23419,7 +23440,11 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } }, "glob-parent": { "version": "3.1.0", @@ -24024,7 +24049,11 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } }, "glob-parent": { "version": "3.1.0", diff --git a/src/App.tsx b/src/App.tsx index 60d6422..51d71f7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,14 +1,48 @@ import React from 'react'; +import io from 'socket.io-client'; import { ThemeProvider } from '@material-ui/styles'; import { theme } from './config/theme'; import { Routes } from './config/route'; +import { resolve } from 'node:path'; + +interface AppState { + socket: SocketIOClient.Socket | null; +} + +export interface PageProps { + getSocket(): Promise; +} + +const App: React.FC = () => { + const [socket, setSocket] = React.useState(null); + + // websocketに接続し、socket clientを返却 + const getSocket = (): Promise => { + console.log('getSocket'); + return new Promise((resolve) => { + if (!socket) { + // 接続開始 + const client = io.connect(process.env.REACT_APP_API_URL as string); + client.on('connect', () => { + console.log('connected'); + // 別ページからも参照できるようにstateにセット + setSocket(client); + // 接続が接続が成功した際にsocket clientを返却 + return resolve(client); + }); + } else { + console.log('接続済み'); + // 接続済みだった場合stateのsocket clietnを返却 + return resolve(socket); + } + }); + }; -function App() { return ( - + ); -} +}; export default App; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 95eadba..603e35f 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -4,6 +4,7 @@ import { ContainerProps as Input } from '../InputText'; export interface ContainerProps { width: string; + setSocketHandler(): Promise; } export interface InputSub extends Input { @@ -60,9 +61,16 @@ export const CreateForm: React.FC = (props: ContainerProps) => { return errorFlag; }; - const submitEvent = () => { + const submitEvent = async () => { if (validateAll()) { - return; + return console.log('aaa'); + } + const socket = await props.setSocketHandler(); + console.log(socket); + if (socket) { + socket.emit('create_room', 'takashi', (res: any) => { + console.log(res); + }); } console.log('submit'); }; diff --git a/src/config/route.tsx b/src/config/route.tsx index 76de98f..cec0450 100644 --- a/src/config/route.tsx +++ b/src/config/route.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import { Loading } from '../components/Loading'; +import { PageProps } from '../App'; const Home = React.lazy(() => { return Promise.all([import('../pages/Home'), new Promise((resolve) => setTimeout(resolve, 1000))]).then( @@ -17,7 +18,7 @@ interface RouteBase { path: string; exact: boolean; name: string; - component: React.LazyExoticComponent | React.FC; + component: React.LazyExoticComponent> | React.FC; } const routebases: Array = [ @@ -25,11 +26,11 @@ const routebases: Array = [ { path: '/room', exact: true, name: 'Room', component: Room } ]; -export const Routes: React.FC = () => { +export const Routes: React.FC = (props) => { const makeRoute = (routebase: RouteBase) => { return ( - + ); }; diff --git a/src/pages/Home/Home.stories.tsx b/src/pages/Home/Home.*stories.tsx similarity index 58% rename from src/pages/Home/Home.stories.tsx rename to src/pages/Home/Home.*stories.tsx index 80a2d7f..bed9ec2 100644 --- a/src/pages/Home/Home.stories.tsx +++ b/src/pages/Home/Home.*stories.tsx @@ -1,12 +1,12 @@ import React from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; -import Home from './'; +import Home from '.'; export default { title: 'Page/Home', component: Home } as Meta; -const Template: Story = () => ; +/* const Template: Story = () => ; -export const Default = Template.bind({}); +export const Default = Template.bind({}); */ diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index 816a7c2..75a5507 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -3,8 +3,9 @@ import { Grid } from '@material-ui/core'; import { CreateForm } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; import './main.css'; +import { PageProps } from '../../App'; -export const Presenter: React.FC = () => { +export const Presenter: React.FC = (props: PageProps) => { const useStyles = makeStyles({ baseGrid: { position: 'relative', @@ -20,7 +21,7 @@ export const Presenter: React.FC = () => { Streaming!! - +
diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index fc6e88d..c7f0cda 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,8 +1,9 @@ import * as React from 'react'; import { Presenter } from './Presenter'; +import { PageProps } from '../../App'; -const Home: React.FC = () => { - return ; +const Home: React.FC = (props: PageProps) => { + return ; }; export default Home; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index ec1d252..0106ffb 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; -import io from 'socket.io-client'; import { useSelector, useDispatch } from 'react-redux'; import roomModule, { RoomState } from '../../store/modules/roomModule'; import { State } from '../../store/store'; import { Presenter } from './Presenter'; +import { PageProps } from '../../App'; -const Room: React.FC = () => { +const Room: React.FC = (props: PageProps) => { const [mount, mountKeeper] = React.useState(null); const room = useSelector((state: State) => state.room); const dispach = useDispatch(); From 79e0b1e5f8771842b80634a37a1cec910b6c5d45 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 5 Apr 2021 22:06:40 +0900 Subject: [PATCH 12/84] =?UTF-8?q?fix(Home/Home.stories):=20=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E5=90=8D=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home/{Home.*stories.tsx => Home.stories.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/pages/Home/{Home.*stories.tsx => Home.stories.tsx} (100%) diff --git a/src/pages/Home/Home.*stories.tsx b/src/pages/Home/Home.stories.tsx similarity index 100% rename from src/pages/Home/Home.*stories.tsx rename to src/pages/Home/Home.stories.tsx From 49c7a41dcbcd367ba9c2114317ffc207b6232acd Mon Sep 17 00:00:00 2001 From: amanojs Date: Mon, 5 Apr 2021 22:29:55 +0900 Subject: [PATCH 13/84] =?UTF-8?q?perf(src/App):=20useStateWithCallback?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97=E3=81=A6setState=E3=81=AB?= =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=AB=E3=83=90=E3=83=83=E3=82=AF=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参照: https://www.npmjs.com/package/use-state-with-callback --- package-lock.json | 5 +++++ package.json | 1 + src/App.tsx | 11 ++++++----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a2757d..eca94d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23102,6 +23102,11 @@ "use-isomorphic-layout-effect": "^1.0.0" } }, + "use-state-with-callback": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/use-state-with-callback/-/use-state-with-callback-2.0.3.tgz", + "integrity": "sha512-bJXNAtJZW0xz16GIW54aDbYxRkZa2c8RdoKGQnJqE7GmRdVkZkKQBTR/9vH6T5tZX/7yCIhywE09NyeTQ9EJJQ==" + }, "util": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", diff --git a/package.json b/package.json index d0a7ad5..60a149d 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "redux-logger": "^3.0.6", "socket.io-client": "^2.4.0", "typescript": "^4.2.3", + "use-state-with-callback": "^2.0.3", "uuid": "^8.3.2", "web-vitals": "^1.1.1" }, diff --git a/src/App.tsx b/src/App.tsx index 51d71f7..f417fa8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import io from 'socket.io-client'; import { ThemeProvider } from '@material-ui/styles'; import { theme } from './config/theme'; import { Routes } from './config/route'; -import { resolve } from 'node:path'; +import { useStateWithCallbackLazy } from 'use-state-with-callback'; interface AppState { socket: SocketIOClient.Socket | null; @@ -14,7 +14,7 @@ export interface PageProps { } const App: React.FC = () => { - const [socket, setSocket] = React.useState(null); + const [socket, setSocket] = useStateWithCallbackLazy(null); // websocketに接続し、socket clientを返却 const getSocket = (): Promise => { @@ -26,9 +26,10 @@ const App: React.FC = () => { client.on('connect', () => { console.log('connected'); // 別ページからも参照できるようにstateにセット - setSocket(client); - // 接続が接続が成功した際にsocket clientを返却 - return resolve(client); + setSocket(client, () => { + // 接続が接続が成功した際にsocket clientを返却 + return resolve(client); + }); }); } else { console.log('接続済み'); From 665404dfc65739f8580ba6eec75150c4afa6c0b9 Mon Sep 17 00:00:00 2001 From: amanojs Date: Mon, 5 Apr 2021 23:54:05 +0900 Subject: [PATCH 14/84] =?UTF-8?q?feat(pages/Home,=20pages/Room,=20CreateFo?= =?UTF-8?q?rm):=20=E3=83=AB=E3=83=BC=E3=83=A0=E4=BD=9C=E6=88=90=E3=80=81?= =?UTF-8?q?=E3=83=AB=E3=83=BC=E3=83=A0=E5=8F=82=E5=8A=A0=E5=87=A6=E7=90=86?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Roomページのparamをもとにルームに参加。stateを参照して部屋制作者と参加者で処理を分ける。 --- src/App.tsx | 14 +++++++--- src/components/CreateForm/index.tsx | 13 +++++++-- src/pages/Home/index.tsx | 7 ++++- src/pages/Room/index.tsx | 41 +++++++++++++++++++++++------ 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index f417fa8..341f096 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,7 @@ interface AppState { export interface PageProps { getSocket(): Promise; + clearSocket(): void; } const App: React.FC = () => { @@ -26,22 +27,27 @@ const App: React.FC = () => { client.on('connect', () => { console.log('connected'); // 別ページからも参照できるようにstateにセット - setSocket(client, () => { + setSocket(client, function () { // 接続が接続が成功した際にsocket clientを返却 - return resolve(client); + resolve(client); }); }); } else { console.log('接続済み'); - // 接続済みだった場合stateのsocket clietnを返却 + // 接続済みだった場合stateのsocket clientを返却 return resolve(socket); } }); }; + const clearSocket = (): void => { + setSocket(null, () => { + console.log('clear socket'); + }); + }; return ( - + ); }; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 603e35f..03baf38 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -1,4 +1,8 @@ import * as React from 'react'; +import { useHistory } from 'react-router-dom'; +import { useSelector, useDispatch } from 'react-redux'; +import roomModule from '../../store/modules/roomModule'; +import { State } from '../../store/store'; import { Presenter } from './Presenter'; import { ContainerProps as Input } from '../InputText'; @@ -20,6 +24,8 @@ export interface InputSub extends Input { export const CreateForm: React.FC = (props: ContainerProps) => { const [userName, setUserName] = React.useState({ value: '', error: false, msg: '' }); + const dispach = useDispatch(); + const history = useHistory(); const inputs: InputSub[] = [ { @@ -68,11 +74,14 @@ export const CreateForm: React.FC = (props: ContainerProps) => { const socket = await props.setSocketHandler(); console.log(socket); if (socket) { - socket.emit('create_room', 'takashi', (res: any) => { + socket.emit('create_room', userName, (res: { result: boolean; room_id: string }) => { console.log(res); + if (res.result) { + dispach(roomModule.actions.setRoom({ roomId: res.room_id })); + history.push('/room' + '?room_id=' + res.room_id); + } }); } - console.log('submit'); }; return ; diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index c7f0cda..9f0777a 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -3,7 +3,12 @@ import { Presenter } from './Presenter'; import { PageProps } from '../../App'; const Home: React.FC = (props: PageProps) => { - return ; + const [mout, mountkeeper] = React.useState(); + + React.useEffect(() => { + props.clearSocket(); + }, [mountkeeper]); + return ; }; export default Home; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 0106ffb..7e31883 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; +import { useHistory } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; -import roomModule, { RoomState } from '../../store/modules/roomModule'; +import roomModule from '../../store/modules/roomModule'; import { State } from '../../store/store'; import { Presenter } from './Presenter'; import { PageProps } from '../../App'; @@ -8,19 +9,43 @@ import { PageProps } from '../../App'; const Room: React.FC = (props: PageProps) => { const [mount, mountKeeper] = React.useState(null); const room = useSelector((state: State) => state.room); + const history = useHistory(); const dispach = useDispatch(); console.log(room); React.useEffect(() => { - if (!room.roomId) { - const socket = io.connect(process.env.REACT_APP_API_URL as string); - socket.on('connect', () => { - console.log('connected'); - dispach(roomModule.actions.setRoom({ roomId: 'iii' })); - }); - } + props.getSocket().then((socket) => { + // ルーム作成ではない場合 + if (!room.roomId) { + // パラメータからroom_idを取得 + const roomId = getParamValue('room_id'); + if (roomId) { + // ルーム入出処理 + // 後でユーザネーム登録処理と一緒に切り離す + joinRoom(socket, { roomId }); + } + } + }); }, [mountKeeper]); + const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { + socket.emit('join_room', option.roomId, (res: boolean) => { + console.log('入出', res); + if (res) { + dispach(roomModule.actions.setRoom({ roomId: option.roomId })); + } /* else { + alert('入出に失敗しました'); + history.push('/'); + } */ + }); + }; + + const getParamValue = (key: string): string | null => { + const params = new URLSearchParams(window.location.search); + const value = params.get(key); + return value; + }; + return ; }; From 81686e82b60d15813acf13f3999c18b4001850f9 Mon Sep 17 00:00:00 2001 From: amanojs Date: Tue, 6 Apr 2021 06:43:47 +0900 Subject: [PATCH 15/84] =?UTF-8?q?refactor(src/App,=20pages/Room):=20socket?= =?UTF-8?q?=20client=E3=82=92Context=E3=81=A7=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Appのstateのsocket clientをContextに設定し、参照できるようにしました。 --- src/App.tsx | 9 +++++++-- src/components/CreateForm/index.tsx | 9 ++++----- .../YoutubeController/Presenter.tsx | 9 +++++++++ .../YoutubeController.stories.tsx | 8 ++++++++ src/components/YoutubeController/index.tsx | 20 +++++++++++++++++++ src/pages/Home/Presenter.tsx | 2 +- src/pages/Home/index.tsx | 2 +- src/pages/Room/Presenter.tsx | 5 ++++- src/pages/Room/index.tsx | 3 +++ 9 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 src/components/YoutubeController/Presenter.tsx create mode 100644 src/components/YoutubeController/YoutubeController.stories.tsx create mode 100644 src/components/YoutubeController/index.tsx diff --git a/src/App.tsx b/src/App.tsx index 341f096..6cf0585 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,8 @@ export interface PageProps { clearSocket(): void; } +export const SocketContext = React.createContext(null); + const App: React.FC = () => { const [socket, setSocket] = useStateWithCallbackLazy(null); @@ -33,7 +35,6 @@ const App: React.FC = () => { }); }); } else { - console.log('接続済み'); // 接続済みだった場合stateのsocket clientを返却 return resolve(socket); } @@ -41,13 +42,17 @@ const App: React.FC = () => { }; const clearSocket = (): void => { + socket?.disconnect(); setSocket(null, () => { console.log('clear socket'); }); }; + return ( - + + + ); }; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 03baf38..4847799 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -1,14 +1,13 @@ import * as React from 'react'; import { useHistory } from 'react-router-dom'; -import { useSelector, useDispatch } from 'react-redux'; +import { useDispatch } from 'react-redux'; import roomModule from '../../store/modules/roomModule'; -import { State } from '../../store/store'; import { Presenter } from './Presenter'; import { ContainerProps as Input } from '../InputText'; export interface ContainerProps { width: string; - setSocketHandler(): Promise; + getSocket(): Promise; } export interface InputSub extends Input { @@ -69,9 +68,9 @@ export const CreateForm: React.FC = (props: ContainerProps) => { const submitEvent = async () => { if (validateAll()) { - return console.log('aaa'); + return console.log('未入力の内容があります'); } - const socket = await props.setSocketHandler(); + const socket = await props.getSocket(); console.log(socket); if (socket) { socket.emit('create_room', userName, (res: { result: boolean; room_id: string }) => { diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx new file mode 100644 index 0000000..a14451a --- /dev/null +++ b/src/components/YoutubeController/Presenter.tsx @@ -0,0 +1,9 @@ +import * as React from 'react'; + +export const Presenter: React.FC = () => { + return ( + +
youtube
+
+ ); +}; diff --git a/src/components/YoutubeController/YoutubeController.stories.tsx b/src/components/YoutubeController/YoutubeController.stories.tsx new file mode 100644 index 0000000..5172168 --- /dev/null +++ b/src/components/YoutubeController/YoutubeController.stories.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import { Story, Meta } from '@storybook/react/types-6-0'; +import { Presenter } from './Presenter'; + +export default { + title: 'Box/YoutubeController', + component: Presenter +}; diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx new file mode 100644 index 0000000..eb9c610 --- /dev/null +++ b/src/components/YoutubeController/index.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import { Presenter } from './Presenter'; +import { SocketContext } from '../../App'; + +export const YoutubeController: React.FC = () => { + const [mount, mountKeeper] = React.useState(); + const socket = React.useContext(SocketContext); + + React.useEffect(() => { + console.log('youtube', socket); + onPause(); + }, [mountKeeper]); + + const onPause = () => { + if (!socket) return; + socket.emit('youtube_pause', 120); + }; + + return ; +}; diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index 75a5507..8092d90 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -21,7 +21,7 @@ export const Presenter: React.FC = (props: PageProps) => { Streaming!! - +
diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 9f0777a..f10fcf6 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -6,7 +6,7 @@ const Home: React.FC = (props: PageProps) => { const [mout, mountkeeper] = React.useState(); React.useEffect(() => { - props.clearSocket(); + //props.clearSocket(); }, [mountkeeper]); return ; }; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index f708595..bbf9aa5 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { Box } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; +import { YoutubeController } from '../../components/YoutubeController'; export const Presenter: React.FC = () => { return ( @@ -8,7 +9,9 @@ export const Presenter: React.FC = () => {
header
- + + + ); }; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 7e31883..9dc8f47 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -26,6 +26,9 @@ const Room: React.FC = (props: PageProps) => { } } }); + return () => { + props.clearSocket(); + }; }, [mountKeeper]); const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { From c89ce078b0dbd062a727e260016144b3d28ade2c Mon Sep 17 00:00:00 2001 From: amanojs Date: Tue, 6 Apr 2021 07:29:01 +0900 Subject: [PATCH 16/84] =?UTF-8?q?feat(YoutubeController,=20pages/Room):=20?= =?UTF-8?q?Room=E3=81=AESocketListenner=E3=81=A8Youtube=E3=81=AESocketHand?= =?UTF-8?q?ler=E3=82=92=E8=A8=AD=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeController/index.tsx | 14 ++++++++++---- src/pages/Room/index.tsx | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index eb9c610..9ca96ef 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -3,18 +3,24 @@ import { Presenter } from './Presenter'; import { SocketContext } from '../../App'; export const YoutubeController: React.FC = () => { - const [mount, mountKeeper] = React.useState(); const socket = React.useContext(SocketContext); React.useEffect(() => { - console.log('youtube', socket); - onPause(); - }, [mountKeeper]); + if (socket) { + onPause(); + onPlay(); + } + }, [socket]); const onPause = () => { if (!socket) return; socket.emit('youtube_pause', 120); }; + const onPlay = () => { + if (!socket) return; + socket.emit('youtube_play', 120); + }; + return ; }; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 9dc8f47..7708275 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -15,6 +15,7 @@ const Room: React.FC = (props: PageProps) => { React.useEffect(() => { props.getSocket().then((socket) => { + // 後でここにルーム存在確認処理を追加 // ルーム作成ではない場合 if (!room.roomId) { // パラメータからroom_idを取得 @@ -24,6 +25,8 @@ const Room: React.FC = (props: PageProps) => { // 後でユーザネーム登録処理と一緒に切り離す joinRoom(socket, { roomId }); } + } else { + setUpSocketListenner(socket); } }); return () => { @@ -36,6 +39,7 @@ const Room: React.FC = (props: PageProps) => { console.log('入出', res); if (res) { dispach(roomModule.actions.setRoom({ roomId: option.roomId })); + setUpSocketListenner(socket); } /* else { alert('入出に失敗しました'); history.push('/'); @@ -43,6 +47,16 @@ const Room: React.FC = (props: PageProps) => { }); }; + const setUpSocketListenner = (socket: SocketIOClient.Socket) => { + socket.on('youtube_pause', (timer: number) => { + console.log('listen!pause!', timer); + }); + + socket.on('youtube_play', (time: number) => { + console.log(time); + }); + }; + const getParamValue = (key: string): string | null => { const params = new URLSearchParams(window.location.search); const value = params.get(key); From b91e8ccd811677b5fb5099460fa74bb658fc51d5 Mon Sep 17 00:00:00 2001 From: amanojs Date: Tue, 6 Apr 2021 23:25:35 +0900 Subject: [PATCH 17/84] =?UTF-8?q?feat(component/YoutubeController):=20Yout?= =?UTF-8?q?ube=E5=90=8C=E6=9C=9F=E5=86=8D=E7=94=9F,=E5=81=9C=E6=AD=A2?= =?UTF-8?q?=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit react-youtube追加。socketListennerをYoutubeControllerコンポーネントに依存させた。 re #10 --- package-lock.json | 51 +++++++++++ package.json | 2 + .../YoutubeController/Presenter.tsx | 16 +++- src/components/YoutubeController/index.tsx | 84 +++++++++++++++++-- src/pages/Room/index.tsx | 13 --- 5 files changed, 143 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index eca94d8..30378ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5804,6 +5804,12 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" }, + "@types/youtube-player": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@types/youtube-player/-/youtube-player-5.5.3.tgz", + "integrity": "sha512-G9k9Q8fyOwzX4A8DI90WB2viYlpxDazoLZDe37GY9+82JL2OOFhEzz6yUIKEt4klACdx/UUuY0BesD68BVR7SA==", + "dev": true + }, "@typescript-eslint/eslint-plugin": { "version": "4.20.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.20.0.tgz", @@ -15465,6 +15471,11 @@ } } }, + "load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=" + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -19817,6 +19828,16 @@ "prop-types": "^15.6.2" } }, + "react-youtube": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-7.13.1.tgz", + "integrity": "sha512-b++TLHmHDpd0ZBS1wcbYabbuchU+W4jtx5A2MUQX0BINNKKsaIQX29sn/aLvZ9v5luwAoceia3VGtyz9blaB9w==", + "requires": { + "fast-deep-equal": "3.1.3", + "prop-types": "15.7.2", + "youtube-player": "5.5.2" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -21215,6 +21236,11 @@ } } }, + "sister": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sister/-/sister-3.0.2.tgz", + "integrity": "sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA==" + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -24960,6 +24986,31 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" }, + "youtube-player": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz", + "integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==", + "requires": { + "debug": "^2.6.6", + "load-script": "^1.0.0", + "sister": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "zwitch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", diff --git a/package.json b/package.json index 60a149d..09622b6 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "react-redux": "^7.2.3", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", + "react-youtube": "^7.13.1", "redux-logger": "^3.0.6", "socket.io-client": "^2.4.0", "typescript": "^4.2.3", @@ -72,6 +73,7 @@ "@types/react-router-dom": "^5.1.7", "@types/redux-logger": "^3.0.8", "@types/socket.io-client": "^1.4.36", + "@types/youtube-player": "^5.5.3", "@typescript-eslint/eslint-plugin": "^4.20.0", "@typescript-eslint/parser": "^4.20.0", "eslint": "^7.23.0", diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx index a14451a..74b6cb5 100644 --- a/src/components/YoutubeController/Presenter.tsx +++ b/src/components/YoutubeController/Presenter.tsx @@ -1,9 +1,23 @@ import * as React from 'react'; +import YouTube from 'react-youtube'; +import { YouTubePlayer } from 'youtube-player/dist/types'; -export const Presenter: React.FC = () => { +export interface PresenterProps { + player: { + ref: React.RefObject; + videoId: string; + onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => void; + onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => void; + onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => void; + onReady: (event: { target: YouTubePlayer }) => void; + }; +} + +export const Presenter: React.FC = (props: PresenterProps) => { return (
youtube
+
); }; diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index 9ca96ef..65a1fb6 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -1,26 +1,92 @@ import * as React from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import { State } from '../../store/store'; import { Presenter } from './Presenter'; import { SocketContext } from '../../App'; +import YouTube from 'react-youtube'; +import { YouTubePlayer } from 'youtube-player/dist/types'; +import { PresenterProps } from './Presenter'; export const YoutubeController: React.FC = () => { + const [videoId, setVideoId] = React.useState('M1UuHL6U7Zk'); + const youtubeRef = React.createRef(); const socket = React.useContext(SocketContext); + const room = useSelector((state: State) => state.room); React.useEffect(() => { if (socket) { - onPause(); - onPlay(); + // socketに接続した時の処理 + if (room.roomId) { + // roomIdがセットされているときListennerをセット + setUpSocketListenner(); + // youtubeSync(socket); + } } - }, [socket]); + }, [socket, room.roomId]); - const onPause = () => { + /* const youtubeSync = (socket: SocketIOClient.Socket): void => { + socket.emit('youtube_sync', (res: { video_id: string; time: number }) => { + //getPlayer()?.cueVideoByUrl(res.video_id); + console.log(videoId); + setVideoId(videoId); + const playTime = res.time + 5; + getPlayer()?.seekTo(playTime, true); + window.setTimeout(() => { + getPlayer()?.playVideo(); + }, 5000); + }); + }; */ + + // socket client Listennerを設定 + const setUpSocketListenner = () => { if (!socket) return; - socket.emit('youtube_pause', 120); + socket.on('youtube_pause', (time: number) => { + getPlayer()?.pauseVideo(); + getPlayer()?.seekTo(time, true); + console.log('listen!pause!', time, getPlayer()); + }); + + socket.on('youtube_play', (time: number) => { + getPlayer()?.playVideo(); + console.log('listen!play!', time, youtubeRef); + }); }; - const onPlay = () => { - if (!socket) return; - socket.emit('youtube_play', 120); + const getPlayer = (): YouTubePlayer | undefined => { + return youtubeRef.current?.getInternalPlayer(); + }; + + // react-youtubeコンポーネントの設定 + const player: PresenterProps['player'] = { + ref: youtubeRef, + videoId: videoId, + onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { + if (!socket) return; + socket.emit('youtube_play', target.getCurrentTime()); + }, + onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => { + if (!socket) return; + socket.emit('youtube_pause', target.getCurrentTime()); + }, + onReady: (event: { target: YouTubePlayer }) => { + event.target.getOptions(); + event.target.playVideo(); + window.setTimeout( + (target: YouTubePlayer) => { + target.pauseVideo(); + target.seekTo(0, true); + }, + 200, + event.target + ); + }, + onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { + console.log('onStateChange'); + console.log(target.getCurrentTime()); + // target.set + console.log(data); + } }; - return ; + return ; }; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 7708275..36077d9 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -25,8 +25,6 @@ const Room: React.FC = (props: PageProps) => { // 後でユーザネーム登録処理と一緒に切り離す joinRoom(socket, { roomId }); } - } else { - setUpSocketListenner(socket); } }); return () => { @@ -39,7 +37,6 @@ const Room: React.FC = (props: PageProps) => { console.log('入出', res); if (res) { dispach(roomModule.actions.setRoom({ roomId: option.roomId })); - setUpSocketListenner(socket); } /* else { alert('入出に失敗しました'); history.push('/'); @@ -47,16 +44,6 @@ const Room: React.FC = (props: PageProps) => { }); }; - const setUpSocketListenner = (socket: SocketIOClient.Socket) => { - socket.on('youtube_pause', (timer: number) => { - console.log('listen!pause!', timer); - }); - - socket.on('youtube_play', (time: number) => { - console.log(time); - }); - }; - const getParamValue = (key: string): string | null => { const params = new URLSearchParams(window.location.search); const value = params.get(key); From d581bf5c0cc60e5324c75c1ed7058703e301ad11 Mon Sep 17 00:00:00 2001 From: amanojs Date: Wed, 7 Apr 2021 06:24:40 +0900 Subject: [PATCH 18/84] =?UTF-8?q?fix(YoutubeController):=20=E3=82=A8?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=A7=E3=83=B3=E3=83=88=E3=81=8CFireFox?= =?UTF-8?q?=E3=81=AE=E5=A0=B4=E5=90=88=E5=8B=95=E7=94=BB=E3=82=92mute?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FireFoxはmute状態でないと動画の自動再生をうけつけない --- src/components/YoutubeController/index.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index 65a1fb6..a7afc95 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -8,7 +8,7 @@ import { YouTubePlayer } from 'youtube-player/dist/types'; import { PresenterProps } from './Presenter'; export const YoutubeController: React.FC = () => { - const [videoId, setVideoId] = React.useState('M1UuHL6U7Zk'); + const [videoId, setVideoId] = React.useState('b6-2P8RgT0A'); const youtubeRef = React.createRef(); const socket = React.useContext(SocketContext); const room = useSelector((state: State) => state.room); @@ -69,14 +69,20 @@ export const YoutubeController: React.FC = () => { socket.emit('youtube_pause', target.getCurrentTime()); }, onReady: (event: { target: YouTubePlayer }) => { + event.target.mute(); event.target.getOptions(); event.target.playVideo(); window.setTimeout( (target: YouTubePlayer) => { target.pauseVideo(); target.seekTo(0, true); + // FireFoxの場合 + const agent = window.navigator.userAgent.toLowerCase(); + if (!agent.match('firefox')) { + event.target.unMute(); + } }, - 200, + 500, event.target ); }, From 9f7982802c5074f388fb3764501f8c41ff8102ff Mon Sep 17 00:00:00 2001 From: amanojs Date: Wed, 7 Apr 2021 08:45:53 +0900 Subject: [PATCH 19/84] =?UTF-8?q?refactor(Player=E9=96=A2=E9=80=A3):=20You?= =?UTF-8?q?tube=E3=81=AE=E3=83=87=E3=82=A3=E3=82=B9=E3=83=97=E3=83=AC?= =?UTF-8?q?=E3=82=A4=E3=81=A8=E3=82=B3=E3=83=B3=E3=83=88=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=A9=E3=82=92=E5=88=86=E5=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ユーザの細かい操作も同期できるようにYoutubeの動画再生ディスプレイと操作コントローラを分割。 --- .../YoutubeController/Presenter.tsx | 17 +-- src/components/YoutubeController/index.tsx | 90 +-------------- src/components/YoutubeWrap/Presenter.tsx | 31 ++++++ src/components/YoutubeWrap/index.tsx | 104 ++++++++++++++++++ src/pages/Room/Presenter.tsx | 4 +- 5 files changed, 143 insertions(+), 103 deletions(-) create mode 100644 src/components/YoutubeWrap/Presenter.tsx create mode 100644 src/components/YoutubeWrap/index.tsx diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx index 74b6cb5..3843bf6 100644 --- a/src/components/YoutubeController/Presenter.tsx +++ b/src/components/YoutubeController/Presenter.tsx @@ -2,22 +2,13 @@ import * as React from 'react'; import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; -export interface PresenterProps { - player: { - ref: React.RefObject; - videoId: string; - onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => void; - onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => void; - onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => void; - onReady: (event: { target: YouTubePlayer }) => void; - }; -} +/* export interface PresenterProps { +} */ -export const Presenter: React.FC = (props: PresenterProps) => { +export const Presenter: React.FC = () => { return ( -
youtube
- +
controller
); }; diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index a7afc95..d2a2302 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -5,94 +5,8 @@ import { Presenter } from './Presenter'; import { SocketContext } from '../../App'; import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; -import { PresenterProps } from './Presenter'; +//import { PresenterProps } from './Presenter'; export const YoutubeController: React.FC = () => { - const [videoId, setVideoId] = React.useState('b6-2P8RgT0A'); - const youtubeRef = React.createRef(); - const socket = React.useContext(SocketContext); - const room = useSelector((state: State) => state.room); - - React.useEffect(() => { - if (socket) { - // socketに接続した時の処理 - if (room.roomId) { - // roomIdがセットされているときListennerをセット - setUpSocketListenner(); - // youtubeSync(socket); - } - } - }, [socket, room.roomId]); - - /* const youtubeSync = (socket: SocketIOClient.Socket): void => { - socket.emit('youtube_sync', (res: { video_id: string; time: number }) => { - //getPlayer()?.cueVideoByUrl(res.video_id); - console.log(videoId); - setVideoId(videoId); - const playTime = res.time + 5; - getPlayer()?.seekTo(playTime, true); - window.setTimeout(() => { - getPlayer()?.playVideo(); - }, 5000); - }); - }; */ - - // socket client Listennerを設定 - const setUpSocketListenner = () => { - if (!socket) return; - socket.on('youtube_pause', (time: number) => { - getPlayer()?.pauseVideo(); - getPlayer()?.seekTo(time, true); - console.log('listen!pause!', time, getPlayer()); - }); - - socket.on('youtube_play', (time: number) => { - getPlayer()?.playVideo(); - console.log('listen!play!', time, youtubeRef); - }); - }; - - const getPlayer = (): YouTubePlayer | undefined => { - return youtubeRef.current?.getInternalPlayer(); - }; - - // react-youtubeコンポーネントの設定 - const player: PresenterProps['player'] = { - ref: youtubeRef, - videoId: videoId, - onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { - if (!socket) return; - socket.emit('youtube_play', target.getCurrentTime()); - }, - onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => { - if (!socket) return; - socket.emit('youtube_pause', target.getCurrentTime()); - }, - onReady: (event: { target: YouTubePlayer }) => { - event.target.mute(); - event.target.getOptions(); - event.target.playVideo(); - window.setTimeout( - (target: YouTubePlayer) => { - target.pauseVideo(); - target.seekTo(0, true); - // FireFoxの場合 - const agent = window.navigator.userAgent.toLowerCase(); - if (!agent.match('firefox')) { - event.target.unMute(); - } - }, - 500, - event.target - ); - }, - onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { - console.log('onStateChange'); - console.log(target.getCurrentTime()); - // target.set - console.log(data); - } - }; - - return ; + return ; }; diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx new file mode 100644 index 0000000..40da574 --- /dev/null +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; +import YouTube from 'react-youtube'; +import { YouTubePlayer } from 'youtube-player/dist/types'; +import { YoutubeController } from '../YoutubeController'; + +export interface PresenterProps { + player: { + ref: React.RefObject; + videoId: string; + onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => void; + onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => void; + onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => void; + onReady: (event: { target: YouTubePlayer }) => void; + opts: { + width?: string; + height?: string; + playerVars: { + [params: string]: string | number; + }; + }; + }; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + return ( + + + + + ); +}; diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx new file mode 100644 index 0000000..989e383 --- /dev/null +++ b/src/components/YoutubeWrap/index.tsx @@ -0,0 +1,104 @@ +import * as React from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import { State } from '../../store/store'; +import { SocketContext } from '../../App'; +import YouTube from 'react-youtube'; +import { YouTubePlayer } from 'youtube-player/dist/types'; +import { Presenter, PresenterProps } from './Presenter'; + +export const YoutubeWrap: React.FC = () => { + const [videoId, setVideoId] = React.useState('b6-2P8RgT0A'); + const youtubeRef = React.createRef(); + const socket = React.useContext(SocketContext); + const room = useSelector((state: State) => state.room); + + React.useEffect(() => { + if (socket) { + // socketに接続した時の処理 + if (room.roomId) { + // roomIdがセットされているときListennerをセット + setUpSocketListenner(); + // youtubeSync(socket); + } + } + }, [socket, room.roomId]); + + /* const youtubeSync = (socket: SocketIOClient.Socket): void => { + socket.emit('youtube_sync', (res: { video_id: string; time: number }) => { + //getPlayer()?.cueVideoByUrl(res.video_id); + console.log(videoId); + setVideoId(videoId); + const playTime = res.time + 5; + getPlayer()?.seekTo(playTime, true); + window.setTimeout(() => { + getPlayer()?.playVideo(); + }, 5000); + }); + }; */ + + // socket client Listennerを設定 + const setUpSocketListenner = () => { + if (!socket) return; + socket.on('youtube_pause', (time: number) => { + getPlayer()?.pauseVideo(); + getPlayer()?.seekTo(time, true); + console.log('listen!pause!', time, getPlayer()); + }); + + socket.on('youtube_play', (time: number) => { + getPlayer()?.playVideo(); + console.log('listen!play!', time, youtubeRef); + }); + }; + + const getPlayer = (): YouTubePlayer | undefined => { + return youtubeRef.current?.getInternalPlayer(); + }; + + // react-youtubeコンポーネントの設定 + const player: PresenterProps['player'] = { + ref: youtubeRef, + videoId: videoId, + onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { + if (!socket) return; + socket.emit('youtube_play', target.getCurrentTime()); + }, + onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => { + if (!socket) return; + socket.emit('youtube_pause', target.getCurrentTime()); + }, + onReady: (event: { target: YouTubePlayer }) => { + event.target.mute(); + event.target.getOptions(); + event.target.playVideo(); + window.setTimeout( + (target: YouTubePlayer) => { + target.pauseVideo(); + target.seekTo(0, true); + // FireFoxの場合 + const agent = window.navigator.userAgent.toLowerCase(); + if (!agent.match('firefox')) { + event.target.unMute(); + } + }, + 500, + event.target + ); + }, + onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { + console.log('onStateChange'); + console.log(target.getCurrentTime()); + // target.set + console.log(data); + }, + opts: { + playerVars: { + controls: 0, + rel: 0, + playsinline: 1 + } + } + }; + + return ; +}; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index bbf9aa5..2a8754f 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Box } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; -import { YoutubeController } from '../../components/YoutubeController'; +import { YoutubeWrap } from '../../components/YoutubeWrap'; export const Presenter: React.FC = () => { return ( @@ -10,7 +10,7 @@ export const Presenter: React.FC = () => {
header
- + ); From 6189e90e02882dd0e2d794018b859e9f0d2bd501 Mon Sep 17 00:00:00 2001 From: amanojs Date: Wed, 7 Apr 2021 23:40:44 +0900 Subject: [PATCH 20/84] =?UTF-8?q?feat(YoutubeController):=20Youtube?= =?UTF-8?q?=E3=82=B3=E3=83=B3=E3=83=88=E3=83=AD=E3=83=BC=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E3=83=AC=E3=82=A4=E3=82=A2=E3=82=A6=E3=83=88=E4=BD=9C?= =?UTF-8?q?=E6=88=90=E3=81=A8=E6=93=8D=E4=BD=9C=E5=87=A6=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit react-youtubeのイベントに頼るとイベントの種類が乏しくなり、サーバーへのemit実行タイミングも制御できないので自前のYoutubeコントローラを作成した。 --- .../YoutubeController/Presenter.tsx | 95 +++++++++++++++++- src/components/YoutubeController/index.tsx | 98 ++++++++++++++++++- src/components/YoutubeWrap/Presenter.tsx | 17 +++- src/components/YoutubeWrap/index.tsx | 21 +++- src/pages/Room/Presenter.tsx | 14 ++- src/pages/Room/index.tsx | 1 + src/pages/Room/main.css | 3 + 7 files changed, 230 insertions(+), 19 deletions(-) diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx index 3843bf6..15ea483 100644 --- a/src/components/YoutubeController/Presenter.tsx +++ b/src/components/YoutubeController/Presenter.tsx @@ -1,14 +1,101 @@ import * as React from 'react'; import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; +import { withStyles } from '@material-ui/core/styles'; +import { Grid, Slider, IconButton } from '@material-ui/core'; +import { PlayArrow, Pause } from '@material-ui/icons'; -/* export interface PresenterProps { -} */ +export interface PresenterProps { + statusIcon: 'play' | 'pause'; + timed: number; + duratioin: number; + sliderOnChange: (e: any, value: any) => void; + valueLabelFormat: (value: number) => string; + playOrPause: () => void; +} -export const Presenter: React.FC = () => { +const PrettoSlider = withStyles({ + root: { + color: '#1dd1a1', + paddingTop: 0 + }, + thumb: { + height: 10, + width: 10, + backgroundColor: 'currentColor', + marginTop: -1, + marginLeft: -1, + border: '2px solid currentColor', + '&:hover': { + boxShadow: '2px 2px 8px currentColor', + height: 16, + width: 16, + marginTop: -6, + marginLeft: -10, + backgroundColor: 'currentColor' + }, + '&:focus': { + boxShadow: '2px 2px 8px currentColor' + } + }, + active: {}, + valueLabel: { + left: 'calc(-80%)', + '& *': { + paddingRight: 5, + background: 'transparent', + color: '#fff', + fontWeight: 'bold', + textShadow: '2px 2px 4px #222' + } + }, + track: { + height: 8, + borderRadius: 0 + }, + rail: { + height: 8, + borderRadius: 0 + } +})(Slider); + +export const Presenter: React.FC = (props: PresenterProps) => { return ( -
controller
+ + + + + + + {props.valueLabelFormat(props.timed)}/{props.valueLabelFormat(props.duratioin)} + + + + + + {props.statusIcon === 'play' ? ( + + ) : ( + + )} + + + + + +
); }; diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index d2a2302..47f6f7a 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -7,6 +7,100 @@ import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; //import { PresenterProps } from './Presenter'; -export const YoutubeController: React.FC = () => { - return ; +export interface YoutubeControllerProps { + youtubeDisp: YouTubePlayer | undefined; + videoStatus: number; +} + +export const YoutubeController: React.FC = (props: YoutubeControllerProps) => { + const [timed, setTimed] = React.useState(0); + const [duration, setDuration] = React.useState(0); + const [statusIcon, setStatusIcon] = React.useState<'play' | 'pause'>('pause'); + let checkTimer: NodeJS.Timeout | null = null; + + React.useEffect(() => { + if (props.youtubeDisp) { + setDuration(props.youtubeDisp.getDuration()); + checkTimer = setInterval( + (props) => { + setTimed(props.youtubeDisp.getCurrentTime()); + }, + 50, + props + ); + } + return () => { + if (checkTimer) { + clearInterval(checkTimer); + } + }; + }, [props.youtubeDisp]); + + React.useEffect(() => { + statusCheck(props.videoStatus); + }, [props.videoStatus]); + + const sliderOnChange = (changedtime: MouseEvent, value: number | number[]) => { + if (props.youtubeDisp) { + props.youtubeDisp.seekTo(Number(value), true); + setTimed(Number(value)); + } + }; + + const valueLabelFormat = (value: number): string => { + const floorValue = Math.floor(value); + const timeH = Math.floor((floorValue % (24 * 60 * 60)) / (60 * 60)); + const timeM = Math.floor(((floorValue % (24 * 60 * 60)) % (60 * 60)) / 60); + const timeS = ((floorValue % (24 * 60 * 60)) % (60 * 60)) % 60; + if (timeH === 0) { + return String(timeM).padStart(2, '0') + ':' + String(timeS).padStart(2, '0'); + } else { + return ( + String(timeH).padStart(2, '0') + ':' + String(timeM).padStart(2, '0') + ':' + String(timeS).padStart(2, '0') + ); + } + }; + + const statusCheck = (status: number) => { + // https://developers.google.com/youtube/iframe_api_reference?hl=ja#Adding_event_listener 参照 + switch (status) { + case -1: // 未開始 + setStatusIcon('play'); + break; + case 0: // 終了 + setStatusIcon('play'); + break; + case 1: // 再生中 + setStatusIcon('pause'); + break; + case 2: // 停止 + setStatusIcon('play'); + break; + case 3: // バッファリング中 + setStatusIcon('play'); + break; + case 5: // 頭出し済み + setStatusIcon('play'); + break; + } + }; + + const playOrPause = () => { + if (statusIcon === 'play') { + props.youtubeDisp?.playVideo(); + } else { + props.youtubeDisp?.pauseVideo(); + } + }; + + return ( + + ); }; diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index 40da574..92e8bc7 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -2,10 +2,12 @@ import * as React from 'react'; import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; import { YoutubeController } from '../YoutubeController'; +import { YoutubeControllerProps } from '../YoutubeController'; +import { Box, Grid } from '@material-ui/core'; export interface PresenterProps { + youtubeRef: React.RefObject; player: { - ref: React.RefObject; videoId: string; onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => void; onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => void; @@ -19,13 +21,22 @@ export interface PresenterProps { }; }; }; + videoStatus: YoutubeControllerProps['videoStatus']; + youtubeDisp: YoutubeControllerProps['youtubeDisp']; } export const Presenter: React.FC = (props: PresenterProps) => { return ( - - + + {/* 最大化の場合は↓を変更 */} + + + + + + + ); }; diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 989e383..1fccc08 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -8,6 +8,9 @@ import { Presenter, PresenterProps } from './Presenter'; export const YoutubeWrap: React.FC = () => { const [videoId, setVideoId] = React.useState('b6-2P8RgT0A'); + const [youtubeDisp, setDisp] = React.useState(undefined); + const [videoStatus, setVideoStatus] = React.useState(-1); + const youtubeRef = React.createRef(); const socket = React.useContext(SocketContext); const room = useSelector((state: State) => state.room); @@ -21,7 +24,7 @@ export const YoutubeWrap: React.FC = () => { // youtubeSync(socket); } } - }, [socket, room.roomId]); + }, [socket, room.roomId, youtubeRef]); /* const youtubeSync = (socket: SocketIOClient.Socket): void => { socket.emit('youtube_sync', (res: { video_id: string; time: number }) => { @@ -57,7 +60,6 @@ export const YoutubeWrap: React.FC = () => { // react-youtubeコンポーネントの設定 const player: PresenterProps['player'] = { - ref: youtubeRef, videoId: videoId, onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { if (!socket) return; @@ -71,6 +73,7 @@ export const YoutubeWrap: React.FC = () => { event.target.mute(); event.target.getOptions(); event.target.playVideo(); + setDisp(event.target); window.setTimeout( (target: YouTubePlayer) => { target.pauseVideo(); @@ -87,18 +90,26 @@ export const YoutubeWrap: React.FC = () => { }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { console.log('onStateChange'); - console.log(target.getCurrentTime()); // target.set console.log(data); + setVideoStatus(data); }, + // https://developers.google.com/youtube/player_parameters?hl=ja ここ参照してる opts: { + width: '100%', + height: '700px', playerVars: { controls: 0, rel: 0, - playsinline: 1 + playsinline: 1, + fs: 0, + disablekb: 1, + modestbranding: 1 } } }; - return ; + // コントローラメソッド + + return ; }; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index 2a8754f..dd862e7 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -1,17 +1,21 @@ import * as React from 'react'; -import { Box } from '@material-ui/core'; +import { Box, Grid } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import { YoutubeWrap } from '../../components/YoutubeWrap'; export const Presenter: React.FC = () => { return ( -
+
header
- - - + + + + + + + ); }; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 36077d9..0de548b 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -5,6 +5,7 @@ import roomModule from '../../store/modules/roomModule'; import { State } from '../../store/store'; import { Presenter } from './Presenter'; import { PageProps } from '../../App'; +import './main.css'; const Room: React.FC = (props: PageProps) => { const [mount, mountKeeper] = React.useState(null); diff --git a/src/pages/Room/main.css b/src/pages/Room/main.css index e69de29..6291dff 100644 --- a/src/pages/Room/main.css +++ b/src/pages/Room/main.css @@ -0,0 +1,3 @@ +body{ + background-color: #F9F9F9; +} \ No newline at end of file From 44b9a87b093c00793a6dfe559b720c7de7e03c56 Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 8 Apr 2021 02:58:58 +0900 Subject: [PATCH 21/84] =?UTF-8?q?feat(YoutubeWrap):=20=E6=96=B0=E8=A6=8F?= =?UTF-8?q?=E3=83=A6=E3=83=BC=E3=82=B6=E5=8F=82=E5=8A=A0=E6=99=82=E3=81=AE?= =?UTF-8?q?Socket=E3=83=AA=E3=82=B9=E3=83=8A=E3=83=BC=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CreateForm/index.tsx | 2 +- src/components/YoutubeWrap/index.tsx | 46 ++++++++++++++++++++++++++++ src/pages/Room/index.tsx | 4 +-- src/store/modules/roomModule.ts | 4 ++- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 4847799..184063b 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -76,7 +76,7 @@ export const CreateForm: React.FC = (props: ContainerProps) => { socket.emit('create_room', userName, (res: { result: boolean; room_id: string }) => { console.log(res); if (res.result) { - dispach(roomModule.actions.setRoom({ roomId: res.room_id })); + dispach(roomModule.actions.setRoom({ roomId: res.room_id, isOwner: true })); history.push('/room' + '?room_id=' + res.room_id); } }); diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 1fccc08..ded2a08 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -52,12 +52,58 @@ export const YoutubeWrap: React.FC = () => { getPlayer()?.playVideo(); console.log('listen!play!', time, youtubeRef); }); + + /* socket.on('request_playing_data', (participant_id: string) => { + console.log('request_playing_data', participant_id); + const playingData: { movie_id?: string; time: number; isPlaying: boolean } = { + time: getPlayer()?.getCurrentTime() || 0.0, + isPlaying: statusCheck(videoStatus) + }; + if (videoId) { + playingData.movie_id = videoId; + } + const payload = { + socket_id: participant_id, + playingData: playingData + }; + socket.emit('send_playing_data', payload); + }); + + socket.on('new_playing_data', (res: any) => { + console.log('newplayingData', res); + }); */ }; const getPlayer = (): YouTubePlayer | undefined => { return youtubeRef.current?.getInternalPlayer(); }; + const statusCheck = (status: number): boolean => { + // https://developers.google.com/youtube/iframe_api_reference?hl=ja#Adding_event_listener 参照 + let isPlaying = false; + switch (status) { + case -1: // 未開始 + isPlaying = false; + break; + case 0: // 終了 + isPlaying = false; + break; + case 1: // 再生中 + isPlaying = true; + break; + case 2: // 停止 + isPlaying = false; + break; + case 3: // バッファリング中 + isPlaying = false; + break; + case 5: // 頭出し済み + isPlaying = false; + break; + } + return isPlaying; + }; + // react-youtubeコンポーネントの設定 const player: PresenterProps['player'] = { videoId: videoId, diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 0de548b..283331d 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -34,10 +34,10 @@ const Room: React.FC = (props: PageProps) => { }, [mountKeeper]); const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { - socket.emit('join_room', option.roomId, (res: boolean) => { + socket.emit('join_room', { room_id: option.roomId, username: 'guest' }, (res: boolean) => { console.log('入出', res); if (res) { - dispach(roomModule.actions.setRoom({ roomId: option.roomId })); + dispach(roomModule.actions.setRoom({ roomId: option.roomId, isOwner: false })); } /* else { alert('入出に失敗しました'); history.push('/'); diff --git a/src/store/modules/roomModule.ts b/src/store/modules/roomModule.ts index c03fbf3..8b8af56 100644 --- a/src/store/modules/roomModule.ts +++ b/src/store/modules/roomModule.ts @@ -2,10 +2,12 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; export interface RoomState { roomId: string; + isOwner: boolean; } const roomInitialState: RoomState = { - roomId: '' + roomId: '', + isOwner: false }; // createSliceメソッドを使ってactionsとreducersを生成 From 6ac04cf049fbfff52270312b65b831b2fdf67d9b Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 8 Apr 2021 06:03:44 +0900 Subject: [PATCH 22/84] =?UTF-8?q?feat(Wrap,Controller):=20=E3=83=AB?= =?UTF-8?q?=E3=83=BC=E3=83=A0=E5=8F=82=E5=8A=A0=E6=99=82=E3=81=AB=E3=83=AB?= =?UTF-8?q?=E3=83=BC=E3=83=A0=E3=81=AE=E5=86=8D=E7=94=9F=E6=99=82=E9=96=93?= =?UTF-8?q?=E3=82=84=E3=82=B9=E3=83=86=E3=83=BC=E3=82=BF=E3=82=B9=E3=82=92?= =?UTF-8?q?=E5=8F=96=E5=BE=97=E3=81=97=E5=90=8C=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ルーム参加をサーバが検知 => マスターに問い合わせをして最新情報を入手 => 新規参加者に送信。今後遅延をより少なくするためこのロジックを変えていく必要がありそう。 --- src/components/YoutubeController/index.tsx | 3 + src/components/YoutubeWrap/index.tsx | 69 +++++++++++++--------- src/pages/Room/index.tsx | 2 +- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index 47f6f7a..a2310a1 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -37,6 +37,9 @@ export const YoutubeController: React.FC = (props: Youtu }, [props.youtubeDisp]); React.useEffect(() => { + if (props.youtubeDisp) { + setDuration(props.youtubeDisp?.getDuration()); + } statusCheck(props.videoStatus); }, [props.videoStatus]); diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index ded2a08..1be707c 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -7,9 +7,14 @@ import { YouTubePlayer } from 'youtube-player/dist/types'; import { Presenter, PresenterProps } from './Presenter'; export const YoutubeWrap: React.FC = () => { - const [videoId, setVideoId] = React.useState('b6-2P8RgT0A'); + const [videoId, setVideoId] = React.useState(''); const [youtubeDisp, setDisp] = React.useState(undefined); const [videoStatus, setVideoStatus] = React.useState(-1); + const [playingData, setPlayingData] = React.useState<{ movie_id?: string; time: number; isPlaying: boolean }>({ + time: 0, + isPlaying: false + }); + const [candidateId, setCandidate] = React.useState(''); const youtubeRef = React.createRef(); const socket = React.useContext(SocketContext); @@ -26,22 +31,13 @@ export const YoutubeWrap: React.FC = () => { } }, [socket, room.roomId, youtubeRef]); - /* const youtubeSync = (socket: SocketIOClient.Socket): void => { - socket.emit('youtube_sync', (res: { video_id: string; time: number }) => { - //getPlayer()?.cueVideoByUrl(res.video_id); - console.log(videoId); - setVideoId(videoId); - const playTime = res.time + 5; - getPlayer()?.seekTo(playTime, true); - window.setTimeout(() => { - getPlayer()?.playVideo(); - }, 5000); - }); - }; */ - // socket client Listennerを設定 const setUpSocketListenner = () => { if (!socket) return; + const events = ['youtube_pause', 'youtube_play', 'request_playing_data', 'new_playing_data']; + for (const event of events) { + socket.off(event); + } socket.on('youtube_pause', (time: number) => { getPlayer()?.pauseVideo(); getPlayer()?.seekTo(time, true); @@ -53,10 +49,10 @@ export const YoutubeWrap: React.FC = () => { console.log('listen!play!', time, youtubeRef); }); - /* socket.on('request_playing_data', (participant_id: string) => { - console.log('request_playing_data', participant_id); + socket.on('request_playing_data', async (participant_id: string) => { + const time = await getPlayer()?.getCurrentTime(); const playingData: { movie_id?: string; time: number; isPlaying: boolean } = { - time: getPlayer()?.getCurrentTime() || 0.0, + time: time || 0.0, isPlaying: statusCheck(videoStatus) }; if (videoId) { @@ -69,9 +65,13 @@ export const YoutubeWrap: React.FC = () => { socket.emit('send_playing_data', payload); }); - socket.on('new_playing_data', (res: any) => { + socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { console.log('newplayingData', res); - }); */ + if (res.movie_id) { + setVideoId(res.movie_id); + } + setPlayingData(res); + }); }; const getPlayer = (): YouTubePlayer | undefined => { @@ -118,21 +118,26 @@ export const YoutubeWrap: React.FC = () => { onReady: (event: { target: YouTubePlayer }) => { event.target.mute(); event.target.getOptions(); - event.target.playVideo(); setDisp(event.target); + event.target.cueVideoById('b6-2P8RgT0A'); + event.target.playVideo(); window.setTimeout( (target: YouTubePlayer) => { - target.pauseVideo(); - target.seekTo(0, true); - // FireFoxの場合 - const agent = window.navigator.userAgent.toLowerCase(); - if (!agent.match('firefox')) { - event.target.unMute(); + event.target.seekTo(playingData.time, true); + if (playingData.isPlaying) { + event.target.playVideo(); + } else { + event.target.pauseVideo(); } }, 500, event.target ); + // FireFoxの場合 + const agent = window.navigator.userAgent.toLowerCase(); + if (!agent.match('firefox')) { + event.target.unMute(); + } }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { console.log('onStateChange'); @@ -155,7 +160,15 @@ export const YoutubeWrap: React.FC = () => { } }; - // コントローラメソッド + const handler = () => { + youtubeDisp?.loadVideoById(candidateId); + }; - return ; + return ( + + setCandidate(e.target.value)} /> + + + + ); }; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 283331d..0c34396 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -34,7 +34,7 @@ const Room: React.FC = (props: PageProps) => { }, [mountKeeper]); const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { - socket.emit('join_room', { room_id: option.roomId, username: 'guest' }, (res: boolean) => { + socket.emit('join_room', { room_id: option.roomId, user_name: 'guest' }, (res: boolean) => { console.log('入出', res); if (res) { dispach(roomModule.actions.setRoom({ roomId: option.roomId, isOwner: false })); From a0ceed72f29240b7d4c5c7f1b5efe9cd2a5c492d Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 8 Apr 2021 15:50:07 +0900 Subject: [PATCH 23/84] =?UTF-8?q?feat(Wrap,Controller):=20=E5=86=8D?= =?UTF-8?q?=E7=94=9F=E3=83=90=E3=83=BC=E3=81=AE=E6=93=8D=E4=BD=9C(?= =?UTF-8?q?=E3=82=B7=E3=83=BC=E3=82=AF)=E3=82=92=E5=90=8C=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit seekToイベントをルームと同期させました。 --- src/components/YoutubeController/index.tsx | 3 +++ src/components/YoutubeWrap/index.tsx | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index a2310a1..e586f5d 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -16,6 +16,8 @@ export const YoutubeController: React.FC = (props: Youtu const [timed, setTimed] = React.useState(0); const [duration, setDuration] = React.useState(0); const [statusIcon, setStatusIcon] = React.useState<'play' | 'pause'>('pause'); + + const socket = React.useContext(SocketContext); let checkTimer: NodeJS.Timeout | null = null; React.useEffect(() => { @@ -45,6 +47,7 @@ export const YoutubeController: React.FC = (props: Youtu const sliderOnChange = (changedtime: MouseEvent, value: number | number[]) => { if (props.youtubeDisp) { + socket?.emit('youtube_seek', value); props.youtubeDisp.seekTo(Number(value), true); setTimed(Number(value)); } diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 1be707c..eb3be3f 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -34,7 +34,7 @@ export const YoutubeWrap: React.FC = () => { // socket client Listennerを設定 const setUpSocketListenner = () => { if (!socket) return; - const events = ['youtube_pause', 'youtube_play', 'request_playing_data', 'new_playing_data']; + const events = ['youtube_pause', 'youtube_play', 'youtube_seek', 'request_playing_data', 'new_playing_data']; for (const event of events) { socket.off(event); } @@ -49,6 +49,10 @@ export const YoutubeWrap: React.FC = () => { console.log('listen!play!', time, youtubeRef); }); + socket.on('youtube_seek', (time: number) => { + getPlayer()?.seekTo(time, true); + }); + socket.on('request_playing_data', async (participant_id: string) => { const time = await getPlayer()?.getCurrentTime(); const playingData: { movie_id?: string; time: number; isPlaying: boolean } = { From e6acff21ff7e7f8d1630f954742a0d4a1aceacee Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 8 Apr 2021 18:42:57 +0900 Subject: [PATCH 24/84] =?UTF-8?q?fix(Wrap):=20=E3=83=AB=E3=83=BC=E3=83=A0?= =?UTF-8?q?=E5=8F=82=E5=8A=A0=E6=99=82=E3=81=AE=E5=88=9D=E6=9C=9F=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=89=E5=86=8D=E7=94=9F=E3=82=92emit=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 初期マウント時のonPlayとonPauseでのemitを行わないように変更しました。 --- src/components/YoutubeWrap/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index eb3be3f..1ecfa46 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -15,6 +15,7 @@ export const YoutubeWrap: React.FC = () => { isPlaying: false }); const [candidateId, setCandidate] = React.useState(''); + const [isFirst, setIsFirst] = React.useState(true); const youtubeRef = React.createRef(); const socket = React.useContext(SocketContext); @@ -112,11 +113,11 @@ export const YoutubeWrap: React.FC = () => { const player: PresenterProps['player'] = { videoId: videoId, onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { - if (!socket) return; + if (!socket || isFirst) return; socket.emit('youtube_play', target.getCurrentTime()); }, onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => { - if (!socket) return; + if (!socket || isFirst) return; socket.emit('youtube_pause', target.getCurrentTime()); }, onReady: (event: { target: YouTubePlayer }) => { @@ -133,6 +134,7 @@ export const YoutubeWrap: React.FC = () => { } else { event.target.pauseVideo(); } + setIsFirst(false); }, 500, event.target From edff005b2ff05221c69a1c0cc9a535af0e532e2b Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 8 Apr 2021 21:06:52 +0900 Subject: [PATCH 25/84] =?UTF-8?q?style(Wrap):=20Wrap=E3=82=B3=E3=83=B3?= =?UTF-8?q?=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E3=81=AE=E3=82=B3?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeWrap/index.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 1ecfa46..220d9f2 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -8,13 +8,22 @@ import { Presenter, PresenterProps } from './Presenter'; export const YoutubeWrap: React.FC = () => { const [videoId, setVideoId] = React.useState(''); + + // YoutubeControllerに渡すYoutubeイベント const [youtubeDisp, setDisp] = React.useState(undefined); + + // YouTubeコンポーネントのステータスが変更された時に変更される const [videoStatus, setVideoStatus] = React.useState(-1); + const [playingData, setPlayingData] = React.useState<{ movie_id?: string; time: number; isPlaying: boolean }>({ time: 0, isPlaying: false }); + + // 動画URL入力フォームの値 const [candidateId, setCandidate] = React.useState(''); + + // 参加時かどうかのフラグ const [isFirst, setIsFirst] = React.useState(true); const youtubeRef = React.createRef(); @@ -42,12 +51,12 @@ export const YoutubeWrap: React.FC = () => { socket.on('youtube_pause', (time: number) => { getPlayer()?.pauseVideo(); getPlayer()?.seekTo(time, true); - console.log('listen!pause!', time, getPlayer()); + // console.log('listen!pause!', time, getPlayer()); }); socket.on('youtube_play', (time: number) => { getPlayer()?.playVideo(); - console.log('listen!play!', time, youtubeRef); + // console.log('listen!play!', time, youtubeRef); }); socket.on('youtube_seek', (time: number) => { @@ -83,6 +92,7 @@ export const YoutubeWrap: React.FC = () => { return youtubeRef.current?.getInternalPlayer(); }; + // ステータスナンバーから再生中か停止中かを返す const statusCheck = (status: number): boolean => { // https://developers.google.com/youtube/iframe_api_reference?hl=ja#Adding_event_listener 参照 let isPlaying = false; @@ -147,7 +157,6 @@ export const YoutubeWrap: React.FC = () => { }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { console.log('onStateChange'); - // target.set console.log(data); setVideoStatus(data); }, From 6fc2d3e64f1aa5e2fda4d0de0b7bf83720b81a66 Mon Sep 17 00:00:00 2001 From: amanojs Date: Fri, 9 Apr 2021 07:02:27 +0900 Subject: [PATCH 26/84] =?UTF-8?q?refactor(Wrap,Room):=20Context=E3=82=92?= =?UTF-8?q?=E5=89=8A=E9=99=A4=E3=81=97=E7=95=B0=E3=81=AA=E3=82=8B=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E3=81=A7Socket=E3=82=92=E5=85=B1=E6=9C=89/=E3=81=9D?= =?UTF-8?q?=E3=81=AE=E4=BB=96=E7=B4=B0=E3=81=8B=E3=81=84=E3=83=AA=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=AF=E3=82=BF=E3=83=AA=E3=83=B3=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参加時、YouTubeコンポネントのonReadyのタイミングで同期を開始する処理の修正前リファクタリング。 --- src/App.tsx | 6 +- src/components/YoutubeController/index.tsx | 8 +- src/components/YoutubeWrap/Presenter.tsx | 6 +- src/components/YoutubeWrap/index.tsx | 133 +++++++++------------ src/pages/Room/Presenter.tsx | 10 +- src/pages/Room/index.tsx | 14 ++- 6 files changed, 78 insertions(+), 99 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 6cf0585..98edc61 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,8 +14,6 @@ export interface PageProps { clearSocket(): void; } -export const SocketContext = React.createContext(null); - const App: React.FC = () => { const [socket, setSocket] = useStateWithCallbackLazy(null); @@ -50,9 +48,7 @@ const App: React.FC = () => { return ( - - - + ); }; diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index e586f5d..c38e9a5 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -2,12 +2,12 @@ import * as React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { State } from '../../store/store'; import { Presenter } from './Presenter'; -import { SocketContext } from '../../App'; import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; //import { PresenterProps } from './Presenter'; export interface YoutubeControllerProps { + socket: SocketIOClient.Socket; youtubeDisp: YouTubePlayer | undefined; videoStatus: number; } @@ -16,8 +16,6 @@ export const YoutubeController: React.FC = (props: Youtu const [timed, setTimed] = React.useState(0); const [duration, setDuration] = React.useState(0); const [statusIcon, setStatusIcon] = React.useState<'play' | 'pause'>('pause'); - - const socket = React.useContext(SocketContext); let checkTimer: NodeJS.Timeout | null = null; React.useEffect(() => { @@ -27,7 +25,7 @@ export const YoutubeController: React.FC = (props: Youtu (props) => { setTimed(props.youtubeDisp.getCurrentTime()); }, - 50, + 150, props ); } @@ -47,7 +45,7 @@ export const YoutubeController: React.FC = (props: Youtu const sliderOnChange = (changedtime: MouseEvent, value: number | number[]) => { if (props.youtubeDisp) { - socket?.emit('youtube_seek', value); + props.socket?.emit('youtube_seek', value); props.youtubeDisp.seekTo(Number(value), true); setTimed(Number(value)); } diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index 92e8bc7..dfd785c 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -6,7 +6,7 @@ import { YoutubeControllerProps } from '../YoutubeController'; import { Box, Grid } from '@material-ui/core'; export interface PresenterProps { - youtubeRef: React.RefObject; + socket: SocketIOClient.Socket; player: { videoId: string; onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => void; @@ -32,8 +32,8 @@ export const Presenter: React.FC = (props: PresenterProps) => { {/* 最大化の場合は↓を変更 */} - - + + diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 220d9f2..da76bf0 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -1,74 +1,70 @@ import * as React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { State } from '../../store/store'; -import { SocketContext } from '../../App'; -import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; import { Presenter, PresenterProps } from './Presenter'; -export const YoutubeWrap: React.FC = () => { - const [videoId, setVideoId] = React.useState(''); - - // YoutubeControllerに渡すYoutubeイベント - const [youtubeDisp, setDisp] = React.useState(undefined); - - // YouTubeコンポーネントのステータスが変更された時に変更される - const [videoStatus, setVideoStatus] = React.useState(-1); +interface YoutubeWrapProps { + socket: SocketIOClient.Socket; +} +export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) => { + const [videoId, setVideoId] = React.useState(''); + const socket = props.socket; + const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target + const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される const [playingData, setPlayingData] = React.useState<{ movie_id?: string; time: number; isPlaying: boolean }>({ time: 0, isPlaying: false }); - - // 動画URL入力フォームの値 - const [candidateId, setCandidate] = React.useState(''); - - // 参加時かどうかのフラグ - const [isFirst, setIsFirst] = React.useState(true); - - const youtubeRef = React.createRef(); - const socket = React.useContext(SocketContext); - const room = useSelector((state: State) => state.room); + const [candidateId, setCandidate] = React.useState(''); // 動画URL入力フォームの値 + const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ + // const room = useSelector((state: State) => state.room); React.useEffect(() => { - if (socket) { - // socketに接続した時の処理 - if (room.roomId) { - // roomIdがセットされているときListennerをセット - setUpSocketListenner(); - // youtubeSync(socket); + socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { + console.log('newplayingData', res); + if (res.movie_id) { + setVideoId(res.movie_id); } - } - }, [socket, room.roomId, youtubeRef]); + setPlayingData(res); + }); + }, []); + + React.useEffect(() => { + setUpSocketListenner(); + }, [youtubeDisp]); // socket client Listennerを設定 const setUpSocketListenner = () => { if (!socket) return; - const events = ['youtube_pause', 'youtube_play', 'youtube_seek', 'request_playing_data', 'new_playing_data']; + const events = ['youtube_pause', 'youtube_play', 'youtube_seek', 'request_playing_data']; for (const event of events) { socket.off(event); } socket.on('youtube_pause', (time: number) => { - getPlayer()?.pauseVideo(); - getPlayer()?.seekTo(time, true); - // console.log('listen!pause!', time, getPlayer()); + youtubeDisp?.pauseVideo(); + youtubeDisp?.seekTo(time, true); + //console.log('listen!pause!', time, youtubeDisp); }); socket.on('youtube_play', (time: number) => { - getPlayer()?.playVideo(); - // console.log('listen!play!', time, youtubeRef); + youtubeDisp?.playVideo(); + //console.log('listen!play!', time, youtubeDisp); }); socket.on('youtube_seek', (time: number) => { - getPlayer()?.seekTo(time, true); + youtubeDisp?.seekTo(time, true); }); socket.on('request_playing_data', async (participant_id: string) => { - const time = await getPlayer()?.getCurrentTime(); + const status = youtubeDisp?.getPlayerState(); + const time = youtubeDisp?.getCurrentTime(); const playingData: { movie_id?: string; time: number; isPlaying: boolean } = { time: time || 0.0, - isPlaying: statusCheck(videoStatus) + isPlaying: status ? statusCheck(status) : false }; + // console.log('プレイングデータをemitします', playingData); if (videoId) { playingData.movie_id = videoId; } @@ -78,25 +74,13 @@ export const YoutubeWrap: React.FC = () => { }; socket.emit('send_playing_data', payload); }); - - socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { - console.log('newplayingData', res); - if (res.movie_id) { - setVideoId(res.movie_id); - } - setPlayingData(res); - }); - }; - - const getPlayer = (): YouTubePlayer | undefined => { - return youtubeRef.current?.getInternalPlayer(); }; // ステータスナンバーから再生中か停止中かを返す - const statusCheck = (status: number): boolean => { + const statusCheck = (value: number): boolean => { // https://developers.google.com/youtube/iframe_api_reference?hl=ja#Adding_event_listener 参照 let isPlaying = false; - switch (status) { + switch (value) { case -1: // 未開始 isPlaying = false; break; @@ -131,33 +115,30 @@ export const YoutubeWrap: React.FC = () => { socket.emit('youtube_pause', target.getCurrentTime()); }, onReady: (event: { target: YouTubePlayer }) => { - event.target.mute(); - event.target.getOptions(); - setDisp(event.target); - event.target.cueVideoById('b6-2P8RgT0A'); - event.target.playVideo(); - window.setTimeout( - (target: YouTubePlayer) => { - event.target.seekTo(playingData.time, true); - if (playingData.isPlaying) { - event.target.playVideo(); - } else { - event.target.pauseVideo(); - } + const { target } = event; + target.mute(); + target.getOptions(); + setDisp(target); + target.cueVideoById('b6-2P8RgT0A'); + target.playVideo(); + window.setTimeout(() => { + target.pauseVideo(); + target.seekTo(playingData.time, true); + // エージェントごとの処理 + const agent = window.navigator.userAgent.toLowerCase(); + if (!agent.match('firefox')) { + target.unMute(); + } + if (playingData.isPlaying) { + target.playVideo(); + } + window.setTimeout(() => { setIsFirst(false); - }, - 500, - event.target - ); - // FireFoxの場合 - const agent = window.navigator.userAgent.toLowerCase(); - if (!agent.match('firefox')) { - event.target.unMute(); - } + }, 200); + }, 1000); }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { - console.log('onStateChange'); - console.log(data); + // console.log('onStateChange', data); setVideoStatus(data); }, // https://developers.google.com/youtube/player_parameters?hl=ja ここ参照してる @@ -183,7 +164,7 @@ export const YoutubeWrap: React.FC = () => { setCandidate(e.target.value)} /> - + ); }; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index dd862e7..3218a8e 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -3,7 +3,11 @@ import { Box, Grid } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import { YoutubeWrap } from '../../components/YoutubeWrap'; -export const Presenter: React.FC = () => { +interface PresenterProps { + socket: SocketIOClient.Socket | null; +} + +export const Presenter: React.FC = (props: PresenterProps) => { return (
@@ -11,9 +15,7 @@ export const Presenter: React.FC = () => {
- - - + {props.socket && }
diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 0c34396..47f8192 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -8,14 +8,15 @@ import { PageProps } from '../../App'; import './main.css'; const Room: React.FC = (props: PageProps) => { + const [socket, setSocket] = React.useState(null); const [mount, mountKeeper] = React.useState(null); const room = useSelector((state: State) => state.room); const history = useHistory(); const dispach = useDispatch(); - console.log(room); React.useEffect(() => { - props.getSocket().then((socket) => { + props.getSocket().then((rec_socket) => { + setSocket(rec_socket); // 後でここにルーム存在確認処理を追加 // ルーム作成ではない場合 if (!room.roomId) { @@ -24,7 +25,7 @@ const Room: React.FC = (props: PageProps) => { if (roomId) { // ルーム入出処理 // 後でユーザネーム登録処理と一緒に切り離す - joinRoom(socket, { roomId }); + joinRoom(rec_socket, { roomId }); } } }); @@ -33,8 +34,9 @@ const Room: React.FC = (props: PageProps) => { }; }, [mountKeeper]); - const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { - socket.emit('join_room', { room_id: option.roomId, user_name: 'guest' }, (res: boolean) => { + const joinRoom = (socket_rec: SocketIOClient.Socket, option: { roomId: string }) => { + if (!socket_rec) return console.log('room :', 'socketがnullだよ', socket_rec); + socket_rec.emit('join_room', { room_id: option.roomId, user_name: 'guest' }, (res: boolean) => { console.log('入出', res); if (res) { dispach(roomModule.actions.setRoom({ roomId: option.roomId, isOwner: false })); @@ -51,7 +53,7 @@ const Room: React.FC = (props: PageProps) => { return value; }; - return ; + return ; }; export default Room; From 7149efcadf6aac08b489b4e698a7c120d521f3ae Mon Sep 17 00:00:00 2001 From: amanojs Date: Fri, 9 Apr 2021 07:49:09 +0900 Subject: [PATCH 27/84] =?UTF-8?q?fix(Wrap):=20=E5=8F=82=E5=8A=A0=E6=99=82?= =?UTF-8?q?=E3=80=81=E5=8B=95=E7=94=BB=E5=88=9D=E6=9C=9F=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=81=8C=E7=B5=82=E3=82=8F=E3=81=A3=E3=81=9F=E6=99=82?= =?UTF-8?q?=E7=82=B9=E3=81=A7=E3=83=AB=E3=83=BC=E3=83=A0=E3=81=A8=E5=86=8D?= =?UTF-8?q?=E7=94=9F=E7=8A=B6=E6=B3=81=E3=82=92=E5=90=8C=E6=9C=9F=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit YouTubeコンポーネントのonReady関数ないで youtube_sync に emitする。 --- src/components/YoutubeWrap/index.tsx | 35 ++++++++++++---------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index da76bf0..9efbba9 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -13,32 +13,18 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) const socket = props.socket; const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される - const [playingData, setPlayingData] = React.useState<{ movie_id?: string; time: number; isPlaying: boolean }>({ - time: 0, - isPlaying: false - }); const [candidateId, setCandidate] = React.useState(''); // 動画URL入力フォームの値 const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ // const room = useSelector((state: State) => state.room); - React.useEffect(() => { - socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { - console.log('newplayingData', res); - if (res.movie_id) { - setVideoId(res.movie_id); - } - setPlayingData(res); - }); - }, []); - React.useEffect(() => { setUpSocketListenner(); }, [youtubeDisp]); // socket client Listennerを設定 const setUpSocketListenner = () => { - if (!socket) return; - const events = ['youtube_pause', 'youtube_play', 'youtube_seek', 'request_playing_data']; + if (!youtubeDisp) return; + const events = ['youtube_pause', 'youtube_play', 'youtube_seek', 'request_playing_data', 'new_playing_data']; for (const event of events) { socket.off(event); } @@ -74,6 +60,17 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) }; socket.emit('send_playing_data', payload); }); + + socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { + console.log('newplayingData', res); + if (res.movie_id) { + setVideoId(res.movie_id); + } + if (res.isPlaying) { + youtubeDisp.playVideo(); + } + youtubeDisp.seekTo(res.time, true); + }); }; // ステータスナンバーから再生中か停止中かを返す @@ -123,15 +120,13 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) target.playVideo(); window.setTimeout(() => { target.pauseVideo(); - target.seekTo(playingData.time, true); + target.seekTo(0, true); + socket.emit('youtube_sync'); // エージェントごとの処理 const agent = window.navigator.userAgent.toLowerCase(); if (!agent.match('firefox')) { target.unMute(); } - if (playingData.isPlaying) { - target.playVideo(); - } window.setTimeout(() => { setIsFirst(false); }, 200); From 9a90ca532c4dae05eb890b6a2d9ca005c5c95352 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 10 Apr 2021 03:19:07 +0900 Subject: [PATCH 28/84] =?UTF-8?q?feat(App,Room):=20=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E3=81=AB=E5=8B=95=E7=9A=84=E3=81=AA=E9=80=9A=E7=9F=A5=E3=82=92?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B=E9=96=A2=E6=95=B0=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sendNotifiction関数に通知内容とカラーを渡すと画面上部中央に通知することができます。 --- package-lock.json | 9 +++++++++ package.json | 1 + src/App.tsx | 5 ++++- src/pages/Room/index.tsx | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 30378ac..32e59f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16438,6 +16438,15 @@ "sort-keys": "^1.0.0" } }, + "notistack": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/notistack/-/notistack-1.0.5.tgz", + "integrity": "sha512-xCMG0OhzEdczmDs2lDABEiphKQMZUavdOIRAJhfIcyJkCA4UqBDANL3YCLt+mz8VbAPCeKTn76kbCmYQIqksnA==", + "requires": { + "clsx": "^1.1.0", + "hoist-non-react-statics": "^3.3.0" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", diff --git a/package.json b/package.json index 09622b6..6d270a9 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@types/node": "^12.20.7", "@types/react": "^17.0.3", "@types/react-dom": "^17.0.3", + "notistack": "^1.0.5", "react": "^17.0.2", "react-dom": "^17.0.2", "react-redux": "^7.2.3", diff --git a/src/App.tsx b/src/App.tsx index 98edc61..82350e5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { ThemeProvider } from '@material-ui/styles'; import { theme } from './config/theme'; import { Routes } from './config/route'; import { useStateWithCallbackLazy } from 'use-state-with-callback'; +import { SnackbarProvider } from 'notistack'; interface AppState { socket: SocketIOClient.Socket | null; @@ -48,7 +49,9 @@ const App: React.FC = () => { return ( - + + + ); }; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 47f8192..b5bc904 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { useHistory } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; +import { VariantType, useSnackbar } from 'notistack'; import roomModule from '../../store/modules/roomModule'; import { State } from '../../store/store'; import { Presenter } from './Presenter'; @@ -10,10 +11,13 @@ import './main.css'; const Room: React.FC = (props: PageProps) => { const [socket, setSocket] = React.useState(null); const [mount, mountKeeper] = React.useState(null); + const room = useSelector((state: State) => state.room); const history = useHistory(); const dispach = useDispatch(); + const { enqueueSnackbar } = useSnackbar(); + React.useEffect(() => { props.getSocket().then((rec_socket) => { setSocket(rec_socket); @@ -53,6 +57,16 @@ const Room: React.FC = (props: PageProps) => { return value; }; + // sendNotifiction('○○○○が退出しました', 'error'); + const sendNotifiction = (message: string, variant: VariantType) => { + if (screen.width < 600) return; + enqueueSnackbar(message, { + variant, + anchorOrigin: { horizontal: 'center', vertical: 'top' }, + autoHideDuration: 2000 + }); + }; + return ; }; From c8b322da9b270cbe6f32a47881f9a31ae8fcedc3 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 10 Apr 2021 04:10:43 +0900 Subject: [PATCH 29/84] =?UTF-8?q?feat(Room):=20=E5=85=A5=E5=87=BA=E8=80=85?= =?UTF-8?q?=E3=80=81=E9=80=80=E5=87=BA=E8=80=85=E3=81=8C=E5=87=BA=E3=81=9F?= =?UTF-8?q?=E5=A0=B4=E5=90=88=E7=94=BB=E9=9D=A2=E4=B8=8A=E9=83=A8=E4=B8=AD?= =?UTF-8?q?=E5=A4=AE=E3=81=AB=E9=80=9A=E7=9F=A5=E3=82=92=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Room/index.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index b5bc904..4ef5ebd 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -38,6 +38,16 @@ const Room: React.FC = (props: PageProps) => { }; }, [mountKeeper]); + React.useEffect(() => { + if (!socket) return; + socket.on('user_joined', (user: { id: string; name: string }) => { + sendNotifiction(user.name + 'が入出しました', 'success'); + }); + socket.on('user_left', (user: { id: string; name: string }) => { + sendNotifiction(user.name + 'が退出しました', 'error'); + }); + }, [socket]); + const joinRoom = (socket_rec: SocketIOClient.Socket, option: { roomId: string }) => { if (!socket_rec) return console.log('room :', 'socketがnullだよ', socket_rec); socket_rec.emit('join_room', { room_id: option.roomId, user_name: 'guest' }, (res: boolean) => { @@ -57,7 +67,6 @@ const Room: React.FC = (props: PageProps) => { return value; }; - // sendNotifiction('○○○○が退出しました', 'error'); const sendNotifiction = (message: string, variant: VariantType) => { if (screen.width < 600) return; enqueueSnackbar(message, { From 2fe9c7e6821f87e3dcb861208b61b7de1e398b69 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 10 Apr 2021 06:43:37 +0900 Subject: [PATCH 30/84] =?UTF-8?q?fix(Wrap):=20=E5=8F=82=E5=8A=A0=E6=99=82?= =?UTF-8?q?=E3=81=AF=E5=8B=95=E7=94=BB=E3=82=92=E3=83=9F=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=83=88=E7=8A=B6=E6=85=8B=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ミュート状態でない動画の自動再生は数回訪れたドメインでないと行われないのでMicrosoft edge以外はミュートを設定しました。後ほど策を打つかもしれません。 --- src/components/YoutubeWrap/index.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 9efbba9..f35b704 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -15,7 +15,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される const [candidateId, setCandidate] = React.useState(''); // 動画URL入力フォームの値 const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ - // const room = useSelector((state: State) => state.room); + const room = useSelector((state: State) => state.room); React.useEffect(() => { setUpSocketListenner(); @@ -36,7 +36,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) socket.on('youtube_play', (time: number) => { youtubeDisp?.playVideo(); - //console.log('listen!play!', time, youtubeDisp); + // console.log('listen!play!', time, youtubeDisp); }); socket.on('youtube_seek', (time: number) => { @@ -66,10 +66,10 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) if (res.movie_id) { setVideoId(res.movie_id); } + youtubeDisp.seekTo(res.time, true); if (res.isPlaying) { youtubeDisp.playVideo(); } - youtubeDisp.seekTo(res.time, true); }); }; @@ -114,6 +114,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) onReady: (event: { target: YouTubePlayer }) => { const { target } = event; target.mute(); + target.setVolume(30); target.getOptions(); setDisp(target); target.cueVideoById('b6-2P8RgT0A'); @@ -121,14 +122,16 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) window.setTimeout(() => { target.pauseVideo(); target.seekTo(0, true); - socket.emit('youtube_sync'); // エージェントごとの処理 const agent = window.navigator.userAgent.toLowerCase(); - if (!agent.match('firefox')) { + if (agent.match('edg')) { target.unMute(); } window.setTimeout(() => { setIsFirst(false); + if (!room.isOwner) { + socket.emit('youtube_sync'); + } }, 200); }, 1000); }, From f85b1ed71c7feb394bef06bb36a570357865dcb6 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 10 Apr 2021 09:56:02 +0900 Subject: [PATCH 31/84] =?UTF-8?q?feat(Room):=20=E6=8B=9B=E5=BE=85URL?= =?UTF-8?q?=E3=81=8B=E3=82=89=E6=9D=A5=E3=81=9F=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=81=AE=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=8D=E3=83=BC=E3=83=A0?= =?UTF-8?q?=E7=99=BB=E9=8C=B2=E5=87=A6=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 招待URLから来たユーザはフォームからネームを登録することで入出ができる。 BREAKING CHANGE: 再利用が可能そうなコンポーネントを最適化しました --- .../CreateForm/CreateForm.stories.tsx | 4 +- src/components/CreateForm/Presenter.tsx | 10 ++- src/components/CreateForm/index.tsx | 71 ++++------------ src/components/CreateForm/main.css | 7 ++ .../InputText/InputText.stories.tsx | 4 +- src/components/InputText/index.tsx | 4 +- src/components/YoutubeWrap/index.tsx | 17 ++-- src/pages/Home/Presenter.tsx | 14 +++- src/pages/Home/index.tsx | 52 +++++++++++- src/pages/Home/main.css | 19 ----- src/pages/Room/Presenter.tsx | 25 ++++-- src/pages/Room/index.tsx | 70 +++++++++++++--- src/pages/Room/main.css | 80 +++++++++++++++++++ src/store/modules/roomModule.ts | 2 + 14 files changed, 262 insertions(+), 117 deletions(-) create mode 100644 src/components/CreateForm/main.css diff --git a/src/components/CreateForm/CreateForm.stories.tsx b/src/components/CreateForm/CreateForm.stories.tsx index 2a83add..09d5776 100644 --- a/src/components/CreateForm/CreateForm.stories.tsx +++ b/src/components/CreateForm/CreateForm.stories.tsx @@ -1,13 +1,13 @@ import React from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; -import { CreateForm, ContainerProps } from './index'; +import { CreateForm, CreateFormProps } from './index'; export default { title: 'Block/CreateForm', component: CreateForm } as Meta; -const Template: Story = (props: ContainerProps) => ; +const Template: Story = (props: CreateFormProps) => ; export const NoValue = Template.bind({}); NoValue.args = { diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index fb083af..3714b7e 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -1,14 +1,16 @@ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; import { Grid, Card, Button, Box } from '@material-ui/core'; -import { Home, PlayArrow } from '@material-ui/icons'; import { InputText } from '../InputText'; import { InputSub } from './index'; +import './main.css'; export interface PresenterProps { width: string; + head: string; + btn: string; inputs: InputSub[]; - submitEvent: () => void; + submitEvent: () => any; } export const Presenter: React.FC = (props: PresenterProps) => { @@ -32,7 +34,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { lineHeight="0px" marginBottom="30px" > - ルーム作成 + {props.head} {props.inputs.map((input: InputSub) => { @@ -51,7 +53,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { })} diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 184063b..2f33f5d 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -1,16 +1,8 @@ import * as React from 'react'; -import { useHistory } from 'react-router-dom'; -import { useDispatch } from 'react-redux'; -import roomModule from '../../store/modules/roomModule'; import { Presenter } from './Presenter'; -import { ContainerProps as Input } from '../InputText'; +import { InputTextProps } from '../InputText'; -export interface ContainerProps { - width: string; - getSocket(): Promise; -} - -export interface InputSub extends Input { +export interface InputSub extends InputTextProps { validate: (val: string) => { error: boolean; msg: string }; setter: React.Dispatch< React.SetStateAction<{ @@ -21,44 +13,21 @@ export interface InputSub extends Input { >; } -export const CreateForm: React.FC = (props: ContainerProps) => { - const [userName, setUserName] = React.useState({ value: '', error: false, msg: '' }); - const dispach = useDispatch(); - const history = useHistory(); - - const inputs: InputSub[] = [ - { - label: 'ユーザネーム*', - placeholder: '須鳥武 太郎', - value: userName.value, - error: userName.error, - msg: userName.msg, - onChange: function (e) { - const { error, msg } = this.validate(e.target.value); - this.setter({ value: e.target.value, error, msg }); - }, - validate: (val) => { - const response = { error: false, msg: '' }; - if (val === '') { - response.error = true; - response.msg = 'ユーザネームを入力してください'; - } else if (val.length > 13) { - response.error = true; - response.msg = '12文字以内で入力してください'; - } - return response; - }, - setter: setUserName - } - ]; +export interface CreateFormProps { + width: string; + head: string; + btn: string; + inputs: InputSub[]; + onSubmit: () => any; +} - for (const input of inputs) { +export const CreateForm: React.FC = (props: CreateFormProps) => { + for (const input of props.inputs) { input.onChange = input.onChange.bind(input); } - const validateAll = () => { let errorFlag = false; - for (const input of inputs) { + for (const input of props.inputs) { const response = input.validate(input.value); if (response.error) errorFlag = true; input.setter({ value: input.value, error: response.error, msg: response.msg }); @@ -70,20 +39,12 @@ export const CreateForm: React.FC = (props: ContainerProps) => { if (validateAll()) { return console.log('未入力の内容があります'); } - const socket = await props.getSocket(); - console.log(socket); - if (socket) { - socket.emit('create_room', userName, (res: { result: boolean; room_id: string }) => { - console.log(res); - if (res.result) { - dispach(roomModule.actions.setRoom({ roomId: res.room_id, isOwner: true })); - history.push('/room' + '?room_id=' + res.room_id); - } - }); - } + props.onSubmit(); }; - return ; + return ( + + ); }; CreateForm.defaultProps = { width: '100%' diff --git a/src/components/CreateForm/main.css b/src/components/CreateForm/main.css new file mode 100644 index 0000000..fc0ddfd --- /dev/null +++ b/src/components/CreateForm/main.css @@ -0,0 +1,7 @@ +.create_room_head{ + text-shadow:1px 0 0 #666,0 1px 0 #666,-1px 0 0 #666,0 -1px 0 #666; + font-size: 20px; + font-weight: bold; + line-height: 0px; + color: #fff; +} \ No newline at end of file diff --git a/src/components/InputText/InputText.stories.tsx b/src/components/InputText/InputText.stories.tsx index e7aa714..e44ef7f 100644 --- a/src/components/InputText/InputText.stories.tsx +++ b/src/components/InputText/InputText.stories.tsx @@ -1,13 +1,13 @@ import React from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; -import { InputText, ContainerProps } from './index'; +import { InputText, InputTextProps } from './index'; export default { title: 'Atom/InputText', component: InputText } as Meta; -const Template: Story = (props: ContainerProps) => ; +const Template: Story = (props: InputTextProps) => ; export const Test = Template.bind({}); Test.args = { diff --git a/src/components/InputText/index.tsx b/src/components/InputText/index.tsx index 758cffa..1210385 100644 --- a/src/components/InputText/index.tsx +++ b/src/components/InputText/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { Presenter } from './Presenter'; -export interface ContainerProps { +export interface InputTextProps { label: string; placeholder?: string; value: string; @@ -10,7 +10,7 @@ export interface ContainerProps { onChange: (e: React.ChangeEvent) => void; } -export const InputText: React.FC = (props: ContainerProps) => { +export const InputText: React.FC = (props: InputTextProps) => { return ( = (props: YoutubeWrapProps) if (res.movie_id) { setVideoId(res.movie_id); } - youtubeDisp.seekTo(res.time, true); if (res.isPlaying) { + youtubeDisp.seekTo(res.time + 0.2, true); youtubeDisp.playVideo(); + } else { + youtubeDisp.seekTo(res.time, true); } }); }; @@ -114,7 +116,6 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) onReady: (event: { target: YouTubePlayer }) => { const { target } = event; target.mute(); - target.setVolume(30); target.getOptions(); setDisp(target); target.cueVideoById('b6-2P8RgT0A'); @@ -122,17 +123,13 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) window.setTimeout(() => { target.pauseVideo(); target.seekTo(0, true); - // エージェントごとの処理 - const agent = window.navigator.userAgent.toLowerCase(); - if (agent.match('edg')) { - target.unMute(); + target.unMute(); + if (!room.isOwner) { + socket.emit('youtube_sync'); } window.setTimeout(() => { setIsFirst(false); - if (!room.isOwner) { - socket.emit('youtube_sync'); - } - }, 200); + }, 500); }, 1000); }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index 8092d90..13d5914 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -1,11 +1,17 @@ import * as React from 'react'; import { Grid } from '@material-ui/core'; -import { CreateForm } from '../../components/CreateForm'; +import { CreateForm, CreateFormProps } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; import './main.css'; -import { PageProps } from '../../App'; -export const Presenter: React.FC = (props: PageProps) => { +interface PresenterProps { + createForm: { + inputs: CreateFormProps['inputs']; + onSubmit: CreateFormProps['onSubmit']; + }; +} + +export const Presenter: React.FC = (props: PresenterProps) => { const useStyles = makeStyles({ baseGrid: { position: 'relative', @@ -21,7 +27,7 @@ export const Presenter: React.FC = (props: PageProps) => { Streaming!! - +
diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index f10fcf6..e855ddb 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,14 +1,62 @@ import * as React from 'react'; +import { useHistory } from 'react-router-dom'; +import { useDispatch } from 'react-redux'; +import roomModule from '../../store/modules/roomModule'; import { Presenter } from './Presenter'; import { PageProps } from '../../App'; +import { InputSub } from '../../components/CreateForm'; const Home: React.FC = (props: PageProps) => { const [mout, mountkeeper] = React.useState(); + const [userName, setUserName] = React.useState({ value: '', error: false, msg: '' }); + + const dispach = useDispatch(); + const history = useHistory(); + + const inputs: InputSub[] = [ + { + label: 'ユーザネーム*', + placeholder: '須鳥武 太郎', + value: userName.value, + error: userName.error, + msg: userName.msg, + onChange: function (e) { + const { error, msg } = this.validate(e.target.value); + this.setter({ value: e.target.value, error, msg }); + }, + validate: (val) => { + const response = { error: false, msg: '' }; + if (val === '') { + response.error = true; + response.msg = 'ユーザネームを入力してください'; + } else if (val.length > 13) { + response.error = true; + response.msg = '12文字以内で入力してください'; + } + return response; + }, + setter: setUserName + } + ]; React.useEffect(() => { - //props.clearSocket(); + props.clearSocket(); }, [mountkeeper]); - return ; + + const createRoomHandler = async () => { + const socket = await props.getSocket(); + console.log(socket); + if (socket) { + socket.emit('create_room', userName, (res: { result: boolean; room_id: string }) => { + console.log(res); + if (res.result) { + dispach(roomModule.actions.setRoom({ roomId: res.room_id, userName: userName.value, isOwner: true })); + history.push('/room' + '?room_id=' + res.room_id); + } + }); + } + }; + return ; }; export default Home; diff --git a/src/pages/Home/main.css b/src/pages/Home/main.css index 75cbbdc..9157e58 100644 --- a/src/pages/Home/main.css +++ b/src/pages/Home/main.css @@ -8,17 +8,6 @@ background: linear-gradient(45deg, #23d5ab,#23a6d5,#ee7752 ); background-size: 190% 190%; } -@keyframes gradient { -0% { - background-position: 0% 50%; -} -50% { - background-position: 100% 50%; -} -100% { - background-position: 0% 50%; -} -} @keyframes fadein { 0% { @@ -44,14 +33,6 @@ color: #55E6C1; } -.create_room_head{ - text-shadow:1px 0 0 #666,0 1px 0 #666,-1px 0 0 #666,0 -1px 0 #666; - font-size: 20px; - font-weight: bold; - line-height: 0px; - color: #fff; -} - .wave { position: absolute; bottom: 0; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index 3218a8e..b02faaf 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -1,23 +1,38 @@ import * as React from 'react'; -import { Box, Grid } from '@material-ui/core'; +import { Box, Grid, Dialog } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import { YoutubeWrap } from '../../components/YoutubeWrap'; +import './main.css'; +import { CreateForm, CreateFormProps } from '../../components/CreateForm'; interface PresenterProps { socket: SocketIOClient.Socket | null; + roomId: string; + nameDialog: boolean; + createForm: { + inputs: CreateFormProps['inputs']; + onSubmit: CreateFormProps['onSubmit']; + }; } export const Presenter: React.FC = (props: PresenterProps) => { return ( -
-
header
-
- {props.socket && } + {props.roomId && {props.socket && }} + {props.roomId ? ( + false + ) : ( +
+
+
+ )} + + +
); }; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 4ef5ebd..3378b24 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -6,16 +6,15 @@ import roomModule from '../../store/modules/roomModule'; import { State } from '../../store/store'; import { Presenter } from './Presenter'; import { PageProps } from '../../App'; -import './main.css'; +import { InputSub } from '../../components/CreateForm'; const Room: React.FC = (props: PageProps) => { const [socket, setSocket] = React.useState(null); - const [mount, mountKeeper] = React.useState(null); - + const [nameDialog, setNameDialog] = React.useState(false); + const [enterId, setEnterId] = React.useState(''); const room = useSelector((state: State) => state.room); const history = useHistory(); const dispach = useDispatch(); - const { enqueueSnackbar } = useSnackbar(); React.useEffect(() => { @@ -28,15 +27,15 @@ const Room: React.FC = (props: PageProps) => { const roomId = getParamValue('room_id'); if (roomId) { // ルーム入出処理 - // 後でユーザネーム登録処理と一緒に切り離す - joinRoom(rec_socket, { roomId }); + setEnterId(roomId); + setNameDialog(true); } } }); return () => { props.clearSocket(); }; - }, [mountKeeper]); + }, []); React.useEffect(() => { if (!socket) return; @@ -48,12 +47,13 @@ const Room: React.FC = (props: PageProps) => { }); }, [socket]); - const joinRoom = (socket_rec: SocketIOClient.Socket, option: { roomId: string }) => { - if (!socket_rec) return console.log('room :', 'socketがnullだよ', socket_rec); - socket_rec.emit('join_room', { room_id: option.roomId, user_name: 'guest' }, (res: boolean) => { + const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { + if (!socket) return console.log('room :', 'socketがnullだよ', socket); + socket.emit('join_room', { room_id: option.roomId, user_name: userName.value }, (res: boolean) => { console.log('入出', res); if (res) { - dispach(roomModule.actions.setRoom({ roomId: option.roomId, isOwner: false })); + dispach(roomModule.actions.setRoom({ roomId: option.roomId, userName: userName.value, isOwner: false })); + setNameDialog(false); } /* else { alert('入出に失敗しました'); history.push('/'); @@ -76,7 +76,53 @@ const Room: React.FC = (props: PageProps) => { }); }; - return ; + // ユーザネーム入力に参照するstate + const [userName, setUserName] = React.useState({ + value: 'Guest', + error: false, + msg: '' + }); + + const inputs: InputSub[] = [ + { + label: '', + placeholder: '須鳥武 太郎', + value: userName.value, + error: userName.error, + msg: userName.msg, + onChange: function (e) { + const { error, msg } = this.validate(e.target.value); + this.setter({ value: e.target.value, error, msg }); + }, + validate: (val) => { + const response = { error: false, msg: '' }; + if (val === '') { + response.error = true; + response.msg = 'ユーザネームを入力してください'; + } else if (val.length > 13) { + response.error = true; + response.msg = '12文字以内で入力してください'; + } + return response; + }, + setter: setUserName + } + ]; + + const enterSubmitHandler = () => { + if (!socket) return; + console.log('enterSubmitHandler', socket, enterId); + joinRoom(socket, { roomId: enterId }); + }; + + return ( + + ); }; export default Room; diff --git a/src/pages/Room/main.css b/src/pages/Room/main.css index 6291dff..eff8f12 100644 --- a/src/pages/Room/main.css +++ b/src/pages/Room/main.css @@ -1,3 +1,83 @@ body{ background-color: #F9F9F9; +} + +.base { + position: relative; + width: 100%; + height: 100vh; + opacity: 1; + animation: gradient 12s ease infinite , fadein 1.4s ease; + background: linear-gradient(45deg, #23d5ab,#23a6d5,#ee7752 ); + background-size: 190% 190%; +} +@keyframes gradient { +0% { + background-position: 0% 50%; +} +50% { + background-position: 100% 50%; +} +100% { + background-position: 0% 50%; +} +} + +@keyframes fadein { +0% { + opacity: 0; +} +100% { + opacity: 1; +} +} + +.wave { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 143px; + background: url(../../assets/wave.png); + animation: wave 10s linear infinite; +} +.wave::before { + content: ''; + position: absolute; + top: 0; + left: 0; + opacity: 0.6; + width: 100%; + height: 143px; + background: url(../../assets/wave.png); + animation: wave-reverse 10s linear infinite; +} +.wave::after { + content: ''; + position: absolute; + top: 0; + left: 0; + opacity: 0.4; + width: 100%; + height: 143px; + background: url(../../assets/wave.png); + animation-delay: -5s; + animation: wave 20s linear infinite; +} +@keyframes wave { +0% { + background-position: 0; +} +100% { + background-position: 1360px; +} +} + +@keyframes wave-reverse { +0% { + background-position: 1360px; +} +100% { + background-position: 0; +} } \ No newline at end of file diff --git a/src/store/modules/roomModule.ts b/src/store/modules/roomModule.ts index 8b8af56..b049b2b 100644 --- a/src/store/modules/roomModule.ts +++ b/src/store/modules/roomModule.ts @@ -2,11 +2,13 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; export interface RoomState { roomId: string; + userName: string; isOwner: boolean; } const roomInitialState: RoomState = { roomId: '', + userName: '', isOwner: false }; From 2bd7f4fd3158f216fb85518c5e721c9bafd81fc3 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 10 Apr 2021 18:35:20 +0900 Subject: [PATCH 32/84] =?UTF-8?q?refactor(CreateForm):=20InputSub=E5=9E=8B?= =?UTF-8?q?=E3=82=92=E3=82=88=E3=82=8A=E5=88=86=E3=81=8B=E3=82=8A=E3=82=84?= =?UTF-8?q?=E3=81=99=E3=81=8F=E3=82=B7=E3=83=B3=E3=83=97=E3=83=AB=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 必要なものを見直し、修正しました。 --- src/components/CreateForm/index.tsx | 14 ++++---------- src/components/InputText/Presenter.tsx | 4 ++-- src/components/InputText/index.tsx | 2 +- src/pages/Home/index.tsx | 11 +++++------ src/pages/Room/index.tsx | 11 +++++------ 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 2f33f5d..0ad3004 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -4,13 +4,6 @@ import { InputTextProps } from '../InputText'; export interface InputSub extends InputTextProps { validate: (val: string) => { error: boolean; msg: string }; - setter: React.Dispatch< - React.SetStateAction<{ - value: string; - error: boolean; - msg: string; - }> - >; } export interface CreateFormProps { @@ -25,12 +18,13 @@ export const CreateForm: React.FC = (props: CreateFormProps) => for (const input of props.inputs) { input.onChange = input.onChange.bind(input); } + const validateAll = () => { let errorFlag = false; for (const input of props.inputs) { - const response = input.validate(input.value); - if (response.error) errorFlag = true; - input.setter({ value: input.value, error: response.error, msg: response.msg }); + input.onChange(input.value); + const { error } = input.validate(input.value); + if (error) errorFlag = true; } return errorFlag; }; diff --git a/src/components/InputText/Presenter.tsx b/src/components/InputText/Presenter.tsx index 03e6351..d6374f2 100644 --- a/src/components/InputText/Presenter.tsx +++ b/src/components/InputText/Presenter.tsx @@ -8,7 +8,7 @@ interface PresenterProps { value: string; error: boolean; msg: string; - onChange: (e: React.ChangeEvent) => void; + onChange: (value: string) => void; } export const Presenter: React.FC = (props: PresenterProps) => { @@ -21,7 +21,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { helperText={props.msg} variant="outlined" value={props.value} - onChange={props.onChange} + onChange={(e) => props.onChange(e.target.value)} color="secondary" placeholder={props.placeholder} /> diff --git a/src/components/InputText/index.tsx b/src/components/InputText/index.tsx index 1210385..c84e3d5 100644 --- a/src/components/InputText/index.tsx +++ b/src/components/InputText/index.tsx @@ -7,7 +7,7 @@ export interface InputTextProps { value: string; error: boolean; msg: string; - onChange: (e: React.ChangeEvent) => void; + onChange: (value: string) => void; } export const InputText: React.FC = (props: InputTextProps) => { diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index e855ddb..2d3a898 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -20,11 +20,11 @@ const Home: React.FC = (props: PageProps) => { value: userName.value, error: userName.error, msg: userName.msg, - onChange: function (e) { - const { error, msg } = this.validate(e.target.value); - this.setter({ value: e.target.value, error, msg }); + onChange: function (value: string) { + const { error, msg } = this.validate(value); + setUserName({ value: value, error, msg }); }, - validate: (val) => { + validate: (val: string) => { const response = { error: false, msg: '' }; if (val === '') { response.error = true; @@ -34,8 +34,7 @@ const Home: React.FC = (props: PageProps) => { response.msg = '12文字以内で入力してください'; } return response; - }, - setter: setUserName + } } ]; diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 3378b24..1f88bd1 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -90,11 +90,11 @@ const Room: React.FC = (props: PageProps) => { value: userName.value, error: userName.error, msg: userName.msg, - onChange: function (e) { - const { error, msg } = this.validate(e.target.value); - this.setter({ value: e.target.value, error, msg }); + onChange: function (value: string) { + const { error, msg } = this.validate(value); + setUserName({ value, error, msg }); }, - validate: (val) => { + validate: (val: string) => { const response = { error: false, msg: '' }; if (val === '') { response.error = true; @@ -104,8 +104,7 @@ const Room: React.FC = (props: PageProps) => { response.msg = '12文字以内で入力してください'; } return response; - }, - setter: setUserName + } } ]; From a0b9b738665447dcc7893e3c29eabbcb84007474 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 10 Apr 2021 20:27:42 +0900 Subject: [PATCH 33/84] =?UTF-8?q?refactor(Wrap):=20react-youtube=E3=81=AB?= =?UTF-8?q?=E7=94=A8=E6=84=8F=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84=E3=81=9F?= =?UTF-8?q?=E5=9E=8B=E3=82=92player=E3=81=AB=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 6 +---- src/components/InputText/Presenter.tsx | 30 ------------------------ src/components/InputText/index.tsx | 23 +++++++++++------- src/components/YoutubeWrap/Presenter.tsx | 26 ++++++-------------- src/components/YoutubeWrap/index.tsx | 11 +++++---- src/pages/Home/Presenter.tsx | 6 ++--- src/pages/Room/Presenter.tsx | 6 ++--- 7 files changed, 34 insertions(+), 74 deletions(-) delete mode 100644 src/components/InputText/Presenter.tsx diff --git a/src/App.tsx b/src/App.tsx index 82350e5..b9f0e53 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,17 +6,13 @@ import { Routes } from './config/route'; import { useStateWithCallbackLazy } from 'use-state-with-callback'; import { SnackbarProvider } from 'notistack'; -interface AppState { - socket: SocketIOClient.Socket | null; -} - export interface PageProps { getSocket(): Promise; clearSocket(): void; } const App: React.FC = () => { - const [socket, setSocket] = useStateWithCallbackLazy(null); + const [socket, setSocket] = useStateWithCallbackLazy(null); // websocketに接続し、socket clientを返却 const getSocket = (): Promise => { diff --git a/src/components/InputText/Presenter.tsx b/src/components/InputText/Presenter.tsx deleted file mode 100644 index d6374f2..0000000 --- a/src/components/InputText/Presenter.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import { TextField } from '@material-ui/core'; - -interface PresenterProps { - label: string; - placeholder?: string; - value: string; - error: boolean; - msg: string; - onChange: (value: string) => void; -} - -export const Presenter: React.FC = (props: PresenterProps) => { - return ( -
-
{props.label}
- props.onChange(e.target.value)} - color="secondary" - placeholder={props.placeholder} - /> -
- ); -}; diff --git a/src/components/InputText/index.tsx b/src/components/InputText/index.tsx index c84e3d5..261fb0a 100644 --- a/src/components/InputText/index.tsx +++ b/src/components/InputText/index.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Presenter } from './Presenter'; +import { TextField } from '@material-ui/core'; export interface InputTextProps { label: string; @@ -12,13 +12,18 @@ export interface InputTextProps { export const InputText: React.FC = (props: InputTextProps) => { return ( - +
+
{props.label}
+ props.onChange(e.target.value)} + color="secondary" + placeholder={props.placeholder} + /> +
); }; diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index dfd785c..f5983ba 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -1,28 +1,16 @@ import * as React from 'react'; -import YouTube from 'react-youtube'; +import YouTube, { YouTubeProps } from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; import { YoutubeController } from '../YoutubeController'; -import { YoutubeControllerProps } from '../YoutubeController'; import { Box, Grid } from '@material-ui/core'; export interface PresenterProps { - socket: SocketIOClient.Socket; - player: { - videoId: string; - onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => void; - onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => void; - onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => void; - onReady: (event: { target: YouTubePlayer }) => void; - opts: { - width?: string; - height?: string; - playerVars: { - [params: string]: string | number; - }; - }; + player: YouTubeProps; + controller: { + socket: SocketIOClient.Socket; + youtubeDisp: YouTubePlayer | undefined; + videoStatus: number; }; - videoStatus: YoutubeControllerProps['videoStatus']; - youtubeDisp: YoutubeControllerProps['youtubeDisp']; } export const Presenter: React.FC = (props: PresenterProps) => { @@ -33,7 +21,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { - + diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index e62171f..3f131ce 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -1,8 +1,9 @@ import * as React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector } from 'react-redux'; import { State } from '../../store/store'; import { YouTubePlayer } from 'youtube-player/dist/types'; -import { Presenter, PresenterProps } from './Presenter'; +import { Presenter } from './Presenter'; +import { YouTubeProps } from 'react-youtube'; interface YoutubeWrapProps { socket: SocketIOClient.Socket; @@ -11,7 +12,7 @@ interface YoutubeWrapProps { export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) => { const [videoId, setVideoId] = React.useState(''); const socket = props.socket; - const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target + const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される const [candidateId, setCandidate] = React.useState(''); // 動画URL入力フォームの値 const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ @@ -103,7 +104,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) }; // react-youtubeコンポーネントの設定 - const player: PresenterProps['player'] = { + const player: YouTubeProps = { videoId: videoId, onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { if (!socket || isFirst) return; @@ -159,7 +160,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) setCandidate(e.target.value)} /> - + ); }; diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index 13d5914..a7d7633 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -1,13 +1,13 @@ import * as React from 'react'; import { Grid } from '@material-ui/core'; -import { CreateForm, CreateFormProps } from '../../components/CreateForm'; +import { CreateForm, InputSub } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; import './main.css'; interface PresenterProps { createForm: { - inputs: CreateFormProps['inputs']; - onSubmit: CreateFormProps['onSubmit']; + inputs: InputSub[]; + onSubmit: () => any; }; } diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index b02faaf..6c2d7a4 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -3,15 +3,15 @@ import { Box, Grid, Dialog } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import { YoutubeWrap } from '../../components/YoutubeWrap'; import './main.css'; -import { CreateForm, CreateFormProps } from '../../components/CreateForm'; +import { CreateForm, CreateFormProps, InputSub } from '../../components/CreateForm'; interface PresenterProps { socket: SocketIOClient.Socket | null; roomId: string; nameDialog: boolean; createForm: { - inputs: CreateFormProps['inputs']; - onSubmit: CreateFormProps['onSubmit']; + inputs: InputSub[]; + onSubmit: () => void; }; } From 73a9fb7dbc9caf8d6f71642c8e264f163f6b7ae5 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Sat, 10 Apr 2021 21:16:22 +0900 Subject: [PATCH 34/84] =?UTF-8?q?CopyRoomIdButton=E3=82=B3=E3=83=B3?= =?UTF-8?q?=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CopyRoomIdButton/index.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/components/CopyRoomIdButton/index.tsx diff --git a/src/components/CopyRoomIdButton/index.tsx b/src/components/CopyRoomIdButton/index.tsx new file mode 100644 index 0000000..8885ca1 --- /dev/null +++ b/src/components/CopyRoomIdButton/index.tsx @@ -0,0 +1,9 @@ +import { Button } from '@material-ui/core'; +import * as React from 'react'; + +export const CopyRoomIdButton: React.FC = () => { + const onClick = () => { + console.log('押したよ!'); + }; + return ; +}; From 3200b252581e8130ac98a292eeefec8cdb4fcdc8 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Sat, 10 Apr 2021 21:20:27 +0900 Subject: [PATCH 35/84] =?UTF-8?q?fix=20payload=E3=81=A8response=E3=81=AE?= =?UTF-8?q?=E5=9E=8B=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home/index.tsx | 2 +- src/pages/Room/index.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 2d3a898..ba95b23 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -46,7 +46,7 @@ const Home: React.FC = (props: PageProps) => { const socket = await props.getSocket(); console.log(socket); if (socket) { - socket.emit('create_room', userName, (res: { result: boolean; room_id: string }) => { + socket.emit('create_room', userName.value, (res: { result: boolean; room_id: string }) => { console.log(res); if (res.result) { dispach(roomModule.actions.setRoom({ roomId: res.room_id, userName: userName.value, isOwner: true })); diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 1f88bd1..049210e 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -39,11 +39,11 @@ const Room: React.FC = (props: PageProps) => { React.useEffect(() => { if (!socket) return; - socket.on('user_joined', (user: { id: string; name: string }) => { - sendNotifiction(user.name + 'が入出しました', 'success'); + socket.on('user_joined', (res: { user: { id: string; name: string } }) => { + sendNotifiction(res.user.name + 'が入出しました', 'success'); }); - socket.on('user_left', (user: { id: string; name: string }) => { - sendNotifiction(user.name + 'が退出しました', 'error'); + socket.on('user_left', (res: { user: { id: string; name: string } }) => { + sendNotifiction(res.user.name + 'が退出しました', 'error'); }); }, [socket]); From 62611ff559ef336624aa3f592aaf106ff4d1d474 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Sat, 10 Apr 2021 22:39:49 +0900 Subject: [PATCH 36/84] =?UTF-8?q?feat(CopyRoomIdButton):=20=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E9=83=A8=E5=88=86=E5=AE=8C=E6=88=90=20=E3=82=AF?= =?UTF-8?q?=E3=83=AA=E3=83=83=E3=82=AF=E3=81=97=E3=81=9F=E3=82=89URL?= =?UTF-8?q?=E3=81=8C=E3=82=B3=E3=83=94=E3=83=BC=E3=81=95=E3=82=8C=E3=81=A6?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E3=81=8C=E5=87=BA=E3=81=BE=E3=81=99=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CopyRoomIdButton/Presenter.tsx | 22 +++++++++++++++ src/components/CopyRoomIdButton/index.tsx | 28 ++++++++++++++++--- src/pages/Home/Presenter.tsx | 2 ++ 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 src/components/CopyRoomIdButton/Presenter.tsx diff --git a/src/components/CopyRoomIdButton/Presenter.tsx b/src/components/CopyRoomIdButton/Presenter.tsx new file mode 100644 index 0000000..5ce245d --- /dev/null +++ b/src/components/CopyRoomIdButton/Presenter.tsx @@ -0,0 +1,22 @@ +import { Button } from '@material-ui/core'; +import * as React from 'react'; + +interface PresenterProps { + onClick: () => void; + inputRef: React.RefObject; + url: string; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + return ( + + + + + ); +}; diff --git a/src/components/CopyRoomIdButton/index.tsx b/src/components/CopyRoomIdButton/index.tsx index 8885ca1..43f7b92 100644 --- a/src/components/CopyRoomIdButton/index.tsx +++ b/src/components/CopyRoomIdButton/index.tsx @@ -1,9 +1,29 @@ -import { Button } from '@material-ui/core'; import * as React from 'react'; +import { useSnackbar } from 'notistack'; +import { Presenter } from './Presenter'; +/** + * URLをクリップボードにコピーするボタン + */ export const CopyRoomIdButton: React.FC = () => { - const onClick = () => { - console.log('押したよ!'); + const [url] = React.useState(window.location.href); + const urlInputRef = React.useRef(null); + const { enqueueSnackbar } = useSnackbar(); + + const onClick = (): void => { + // 選択 + console.log(!!urlInputRef.current); + urlInputRef.current?.select(); + + // クリップボードにコピー + document.execCommand('copy'); + + // 通知 + enqueueSnackbar('招待URLをコピーしました。', { + variant: 'info', + anchorOrigin: { horizontal: 'center', vertical: 'top' }, + autoHideDuration: 2000 + }); }; - return ; + return ; }; diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index 13d5914..d5272c4 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -3,6 +3,7 @@ import { Grid } from '@material-ui/core'; import { CreateForm, CreateFormProps } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; import './main.css'; +import { CopyRoomIdButton } from '../../components/CopyRoomIdButton'; interface PresenterProps { createForm: { @@ -27,6 +28,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { Streaming!! + From 8f6bfe2eeb2a327ffccb9aef9de4e2294b588d54 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Sat, 10 Apr 2021 22:56:00 +0900 Subject: [PATCH 37/84] =?UTF-8?q?feat(CopyRoomIdButton):=20=E3=83=87?= =?UTF-8?q?=E3=82=B6=E3=82=A4=E3=83=B3=E5=AE=8C=E6=88=90=20flat=E3=81=A7ro?= =?UTF-8?q?unded=E3=81=AA=E6=84=9F=E3=81=98=E3=81=AB=E3=81=97=E3=81=BE?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CopyRoomIdButton/Presenter.tsx | 7 ++++++- src/pages/Home/Presenter.tsx | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/CopyRoomIdButton/Presenter.tsx b/src/components/CopyRoomIdButton/Presenter.tsx index 5ce245d..e1b4af6 100644 --- a/src/components/CopyRoomIdButton/Presenter.tsx +++ b/src/components/CopyRoomIdButton/Presenter.tsx @@ -16,7 +16,12 @@ export const Presenter: React.FC = (props: PresenterProps) => { ref={props.inputRef} style={{ opacity: 0, height: 1, width: 1, marginLeft: -1, padding: 0, border: 'none' }} /> - + ); }; diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index d5272c4..13d5914 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -3,7 +3,6 @@ import { Grid } from '@material-ui/core'; import { CreateForm, CreateFormProps } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; import './main.css'; -import { CopyRoomIdButton } from '../../components/CopyRoomIdButton'; interface PresenterProps { createForm: { @@ -28,7 +27,6 @@ export const Presenter: React.FC = (props: PresenterProps) => { Streaming!! - From 477280423341342f2a57e61eba880e752044b933 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Sun, 11 Apr 2021 04:24:19 +0900 Subject: [PATCH 38/84] =?UTF-8?q?feat(Volume):=20=E3=83=9C=E3=83=AA?= =?UTF-8?q?=E3=83=A5=E3=83=BC=E3=83=A0=E8=AA=BF=E6=95=B4=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=81=AE=E5=AE=9F=E8=A3=85=20BREAKING=20CHANGE:=20onReady?= =?UTF-8?q?=E6=99=82=E3=81=AE=E5=87=A6=E7=90=86=E3=82=92=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F=20BREAKING=20CHANGE:=20You?= =?UTF-8?q?tubeWrap=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F=20BREAKING=20CHANGE:=20YoutubeController=E3=82=92?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Volume/index.tsx | 28 +++++++++++ .../YoutubeController/Presenter.tsx | 13 ++++++ src/components/YoutubeController/index.tsx | 28 +++++++++++ src/components/YoutubeWrap/Presenter.tsx | 5 ++ src/components/YoutubeWrap/index.tsx | 46 +++++++++++++++++-- 5 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 src/components/Volume/index.tsx diff --git a/src/components/Volume/index.tsx b/src/components/Volume/index.tsx new file mode 100644 index 0000000..9b066d5 --- /dev/null +++ b/src/components/Volume/index.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { Grid, Slider, IconButton, withStyles } from '@material-ui/core'; +import { VolumeOff, VolumeDown, VolumeUp } from '@material-ui/icons'; + +export interface VolumeProps { + isMute: boolean; + volume: number; + onChange: (e: React.ChangeEvent, value: number | number[]) => any; + onClick: () => any; +} + +export const Volume: React.FC = (props: VolumeProps) => { + return ( + + {props.isMute ? : } + + + ); +}; + +const VolumeSlider = withStyles({})(Slider); diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx index 15ea483..6cd7ebc 100644 --- a/src/components/YoutubeController/Presenter.tsx +++ b/src/components/YoutubeController/Presenter.tsx @@ -4,6 +4,7 @@ import { YouTubePlayer } from 'youtube-player/dist/types'; import { withStyles } from '@material-ui/core/styles'; import { Grid, Slider, IconButton } from '@material-ui/core'; import { PlayArrow, Pause } from '@material-ui/icons'; +import { Volume } from '../Volume'; export interface PresenterProps { statusIcon: 'play' | 'pause'; @@ -12,6 +13,10 @@ export interface PresenterProps { sliderOnChange: (e: any, value: any) => void; valueLabelFormat: (value: number) => string; playOrPause: () => void; + isMute: boolean; + volumeOnClick: () => any; + volumeSliderOnChange: (e: React.ChangeEvent, value: number | number[]) => any; + volume: number; } const PrettoSlider = withStyles({ @@ -83,6 +88,14 @@ export const Presenter: React.FC = (props: PresenterProps) => { + + + {props.statusIcon === 'play' ? ( diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index c38e9a5..c756224 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -10,17 +10,24 @@ export interface YoutubeControllerProps { socket: SocketIOClient.Socket; youtubeDisp: YouTubePlayer | undefined; videoStatus: number; + volume: number; + isMuted: boolean; + mute: () => void; + unMute: () => void; + changeVolume: (num: number) => void; } export const YoutubeController: React.FC = (props: YoutubeControllerProps) => { const [timed, setTimed] = React.useState(0); const [duration, setDuration] = React.useState(0); const [statusIcon, setStatusIcon] = React.useState<'play' | 'pause'>('pause'); + let checkTimer: NodeJS.Timeout | null = null; React.useEffect(() => { if (props.youtubeDisp) { setDuration(props.youtubeDisp.getDuration()); + checkTimer = setInterval( (props) => { setTimed(props.youtubeDisp.getCurrentTime()); @@ -97,6 +104,23 @@ export const YoutubeController: React.FC = (props: Youtu } }; + /** + * ミュート状態の切り替え + */ + const volumeOnClick = () => { + props.isMuted ? props.unMute() : props.mute(); + }; + + const volumeSliderOnChange = (e: React.ChangeEvent, value: number | number[]) => { + const num = Number(value); + + // ボリュームを変更 + props.changeVolume(num); + + // ボリュームの値を参照しミュート状態を切り替え + num < 1 ? props.mute() : props.isMuted ? props.unMute() : false; + }; + return ( = (props: Youtu duratioin={duration} valueLabelFormat={valueLabelFormat} playOrPause={playOrPause} + volume={props.volume} + volumeOnClick={volumeOnClick} + volumeSliderOnChange={volumeSliderOnChange} + isMute={props.isMuted} /> ); }; diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index f5983ba..9735496 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -10,6 +10,11 @@ export interface PresenterProps { socket: SocketIOClient.Socket; youtubeDisp: YouTubePlayer | undefined; videoStatus: number; + volume: number; + isMuted: boolean; + changeVolume: (num: number) => void; + mute: () => void; + unMute: () => void; }; } diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 3f131ce..262418a 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -10,14 +10,18 @@ interface YoutubeWrapProps { } export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) => { - const [videoId, setVideoId] = React.useState(''); const socket = props.socket; + const room = useSelector((state: State) => state.room); const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target + const [videoId, setVideoId] = React.useState(''); const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される const [candidateId, setCandidate] = React.useState(''); // 動画URL入力フォームの値 const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ - const room = useSelector((state: State) => state.room); + const [volume, setVolume] = React.useState(0); // ボリューム + const [volumeLog, setVolumeLog] = React.useState(0); // 変更前のボリューム + const [isMuted, setIsMuted] = React.useState(true); // ミュートフラグ + // onReady React.useEffect(() => { setUpSocketListenner(); }, [youtubeDisp]); @@ -74,6 +78,11 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) youtubeDisp.seekTo(res.time, true); } }); + + // ボリューム情報のセット + const defaultVolume = youtubeDisp.getVolume(); + changeVolume(defaultVolume); // ボリュームを取得 + setVolumeLog(defaultVolume); // ボリュームを保存 }; // ステータスナンバーから再生中か停止中かを返す @@ -116,15 +125,16 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) }, onReady: (event: { target: YouTubePlayer }) => { const { target } = event; - target.mute(); - target.getOptions(); setDisp(target); + target.mute(); + mute(); target.cueVideoById('b6-2P8RgT0A'); target.playVideo(); window.setTimeout(() => { target.pauseVideo(); target.seekTo(0, true); target.unMute(); + unMute(); if (!room.isOwner) { socket.emit('youtube_sync'); } @@ -156,11 +166,37 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) youtubeDisp?.loadVideoById(candidateId); }; + /** ボリュームを変更する */ + const changeVolume = (value: number) => { + youtubeDisp?.setVolume(value); + setVolume(value); + console.log(value); + }; + + /** ミュート時の処理 */ + const mute = () => { + setIsMuted(true); + changeVolume(0); + setVolumeLog(volume); + console.log('youtubeDisp', !!youtubeDisp); + youtubeDisp?.mute(); + }; + + /** アンミュート時の処理 */ + const unMute = () => { + setIsMuted(false); + youtubeDisp?.unMute(); + volumeLog > 30 ? changeVolume(volumeLog) : changeVolume(30); + }; + return ( setCandidate(e.target.value)} /> - + ); }; From 4166ae17c8892b6b345900f71fcf51d6749a01b3 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Sun, 11 Apr 2021 04:56:09 +0900 Subject: [PATCH 39/84] =?UTF-8?q?feat(Volume):=20=E3=83=87=E3=82=B6?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E5=A4=89=E6=9B=B4=20=E3=82=B9=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=80=E3=83=BC=E3=81=AE=E3=83=87=E3=82=B6=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Volume/Presenter.tsx | 76 ++++++++++++++++++++++++++++ src/components/Volume/index.tsx | 21 ++------ src/components/YoutubeWrap/index.tsx | 2 - 3 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 src/components/Volume/Presenter.tsx diff --git a/src/components/Volume/Presenter.tsx b/src/components/Volume/Presenter.tsx new file mode 100644 index 0000000..f45d03c --- /dev/null +++ b/src/components/Volume/Presenter.tsx @@ -0,0 +1,76 @@ +import * as React from 'react'; +import { Slider, IconButton, withStyles } from '@material-ui/core'; +import { VolumeOff, VolumeDown, VolumeUp } from '@material-ui/icons'; + +interface PresenterProps { + isMute: boolean; + volume: number; + onChange: (e: React.ChangeEvent, value: number | number[]) => void; + onClick: () => void; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + return ( +
+ {props.isMute ? : } + +
+ ); +}; + +const VolumeSlider = withStyles({ + root: { + color: '#1dd1a1', + paddingTop: 0, + marginBottom: 0, + padding: 0 + }, + thumb: { + height: 14, + width: 14, + backgroundColor: 'currentColor', + border: '2px solid currentColor', + '&:hover': { + height: 14, + width: 14, + backgroundColor: 'currentColor', + boxShadow: 'none' + }, + '&:focus': { + boxShadow: 'none' + }, + '&:active': { + boxShadow: 'none' + } + }, + active: {}, + valueLabel: { + left: 'calc(-80%)', + '& *': { + paddingRight: 5, + background: 'transparent', + color: '#fff', + fontWeight: 'bold', + textShadow: '2px 2px 4px #222' + } + }, + track: { + height: 4, + borderRadius: 0 + }, + rail: { + height: 4, + borderRadius: 0 + } +})(Slider); diff --git a/src/components/Volume/index.tsx b/src/components/Volume/index.tsx index 9b066d5..d975031 100644 --- a/src/components/Volume/index.tsx +++ b/src/components/Volume/index.tsx @@ -1,28 +1,15 @@ import * as React from 'react'; +import { Presenter } from './Presenter'; import { Grid, Slider, IconButton, withStyles } from '@material-ui/core'; import { VolumeOff, VolumeDown, VolumeUp } from '@material-ui/icons'; export interface VolumeProps { isMute: boolean; volume: number; - onChange: (e: React.ChangeEvent, value: number | number[]) => any; - onClick: () => any; + onChange: (e: React.ChangeEvent, value: number | number[]) => void; + onClick: () => void; } export const Volume: React.FC = (props: VolumeProps) => { - return ( - - {props.isMute ? : } - - - ); + return ; }; - -const VolumeSlider = withStyles({})(Slider); diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 262418a..1df8758 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -170,7 +170,6 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) const changeVolume = (value: number) => { youtubeDisp?.setVolume(value); setVolume(value); - console.log(value); }; /** ミュート時の処理 */ @@ -178,7 +177,6 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) setIsMuted(true); changeVolume(0); setVolumeLog(volume); - console.log('youtubeDisp', !!youtubeDisp); youtubeDisp?.mute(); }; From 6c2572ddc3f1200a81f9ab69b623640ba47b3dcf Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 11 Apr 2021 04:58:02 +0900 Subject: [PATCH 40/84] =?UTF-8?q?fix(*.stories):=20Storybook=E3=81=A7Box?= =?UTF-8?q?=E4=BB=A5=E4=B8=8B=E3=81=AE=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC?= =?UTF-8?q?=E3=83=8D=E3=83=B3=E3=83=88=E3=82=92=E8=A1=A8=E7=A4=BA=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit *.storiesファイルを最適化。 --- .../CopyRoomIdButton.stories.tsx | 21 +++++ .../CreateForm/CreateForm.stories.tsx | 80 ++++++++++++++++++- src/components/CreateForm/index.tsx | 6 ++ .../InputText/InputText.stories.tsx | 23 +++++- src/components/InputText/index.tsx | 7 ++ src/components/Loading/index.tsx | 1 + .../YoutubeController.stories.tsx | 25 +++++- src/pages/Home/Home.stories.tsx | 12 --- src/pages/Room/Room.stories.tsx | 1 - 9 files changed, 154 insertions(+), 22 deletions(-) create mode 100644 src/components/CopyRoomIdButton/CopyRoomIdButton.stories.tsx delete mode 100644 src/pages/Home/Home.stories.tsx delete mode 100644 src/pages/Room/Room.stories.tsx diff --git a/src/components/CopyRoomIdButton/CopyRoomIdButton.stories.tsx b/src/components/CopyRoomIdButton/CopyRoomIdButton.stories.tsx new file mode 100644 index 0000000..3aade2a --- /dev/null +++ b/src/components/CopyRoomIdButton/CopyRoomIdButton.stories.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import { Story, Meta } from '@storybook/react/types-6-0'; +import { CopyRoomIdButton } from './index'; +import { ThemeProvider } from '@material-ui/styles'; +import { theme } from '../../config/theme'; +import { SnackbarProvider } from 'notistack'; + +export default { + title: 'Atom/CopyRoomIdButton', + component: CopyRoomIdButton +} as Meta; + +const Template: Story = () => ( + + + + + +); + +export const Default = Template.bind({}); diff --git a/src/components/CreateForm/CreateForm.stories.tsx b/src/components/CreateForm/CreateForm.stories.tsx index 09d5776..b14c736 100644 --- a/src/components/CreateForm/CreateForm.stories.tsx +++ b/src/components/CreateForm/CreateForm.stories.tsx @@ -1,15 +1,87 @@ import React from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; import { CreateForm, CreateFormProps } from './index'; +import { ThemeProvider } from '@material-ui/styles'; +import { theme } from '../../config/theme'; export default { title: 'Block/CreateForm', component: CreateForm } as Meta; -const Template: Story = (props: CreateFormProps) => ; +const Template: Story = (props: CreateFormProps) => ( + + + +); -export const NoValue = Template.bind({}); -NoValue.args = { - width: '400px' +const DefaultProps: CreateFormProps = { + width: '400px', + head: 'ヘッドタイトル', + btn: '送信', + inputs: [ + { + label: 'ユーザネーム', + placeholder: 'テストユーザ', + value: '', + error: false, + msg: '', + onChange: function (val) { + console.log('onChange'); + }, + validate: (val) => { + console.log('validate'); + return { error: true, msg: 'エラーメッセージ' }; + } + } + ], + onSubmit: () => { + console.log('onSubmit'); + } }; + +export const Default = Template.bind({}); +Default.args = DefaultProps; + +export const Error = Template.bind({}); +const ErrorProps: CreateFormProps = { ...DefaultProps }; +ErrorProps.inputs = [ + { + label: 'ユーザネーム', + placeholder: 'テストユーザ', + value: '', + error: true, + msg: '入力値が誤っています', + onChange: function (val) { + console.log('onChange'); + }, + validate: (val) => { + console.log('validate'); + return { error: true, msg: 'エラーメッセージ' }; + } + } +]; +Error.args = ErrorProps; + +export const MultiInput = Template.bind({}); +const MultiInputProps: CreateFormProps = { ...DefaultProps }; +MultiInputProps.inputs = [ + ...MultiInputProps.inputs, + { + label: 'メールアドレス', + placeholder: 'streaming@steream.com', + value: '', + error: false, + msg: '', + onChange: function (val) { + console.log('onChange'); + }, + validate: (val) => { + console.log('validate'); + return { error: true, msg: 'エラーメッセージ' }; + } + } +]; +console.log(MultiInputProps); + +MultiInput.args = MultiInputProps; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 0ad3004..f3211fe 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -7,13 +7,19 @@ export interface InputSub extends InputTextProps { } export interface CreateFormProps { + /** 横幅 px や % で指定 */ width: string; + /** フォームタイトル*/ head: string; + /** フォームのサブミットボタンのタイトル */ btn: string; + /** InputText型にバリデーション処理を加えたインプットの配列 */ inputs: InputSub[]; + /** サブミット処理(オールバリデーション処理の後に実行されます) */ onSubmit: () => any; } +/** タイトルとインプットテキストとサブミットボタンのシンプルなフォーム */ export const CreateForm: React.FC = (props: CreateFormProps) => { for (const input of props.inputs) { input.onChange = input.onChange.bind(input); diff --git a/src/components/InputText/InputText.stories.tsx b/src/components/InputText/InputText.stories.tsx index e44ef7f..8304a8a 100644 --- a/src/components/InputText/InputText.stories.tsx +++ b/src/components/InputText/InputText.stories.tsx @@ -1,19 +1,36 @@ import React from 'react'; import { Story, Meta } from '@storybook/react/types-6-0'; import { InputText, InputTextProps } from './index'; +import { ThemeProvider } from '@material-ui/styles'; +import { theme } from '../../config/theme'; export default { title: 'Atom/InputText', component: InputText } as Meta; -const Template: Story = (props: InputTextProps) => ; +const Template: Story = (props: InputTextProps) => ( + + + +); -export const Test = Template.bind({}); -Test.args = { +export const Default = Template.bind({}); +Default.args = { label: '名前', placeholder: 'super man', value: '', // eslint-disable-next-line @typescript-eslint/no-empty-function onChange: () => {} }; + +export const Error = Template.bind({}); +Error.args = { + label: '名前', + placeholder: 'super man', + value: '', + error: true, + msg: '入力値が誤っています', + // eslint-disable-next-line @typescript-eslint/no-empty-function + onChange: () => {} +}; diff --git a/src/components/InputText/index.tsx b/src/components/InputText/index.tsx index 261fb0a..c995399 100644 --- a/src/components/InputText/index.tsx +++ b/src/components/InputText/index.tsx @@ -2,14 +2,21 @@ import * as React from 'react'; import { TextField } from '@material-ui/core'; export interface InputTextProps { + /** ラベル */ label: string; + /**プレースホルダ */ placeholder?: string; + /** インプットテキストの値 */ value: string; + /** エラー状態 */ error: boolean; + /** エラー時に表示するメッセージ */ msg: string; + /** インプットテキストの値が変更されるたびに実行される処理 */ onChange: (value: string) => void; } +/** ラベル付きのインプットテキスト */ export const InputText: React.FC = (props: InputTextProps) => { return (
diff --git a/src/components/Loading/index.tsx b/src/components/Loading/index.tsx index 580833f..1e70016 100644 --- a/src/components/Loading/index.tsx +++ b/src/components/Loading/index.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { Box, CircularProgress } from '@material-ui/core'; +/** ローディング画面 */ export const Loading: React.FC = () => { return ( = (props) => ( + +
+ +
+); + +export const Play = Template.bind({}); +Play.args = { + youtubeDisp: undefined, + videoStatus: 1 +}; + +export const Stop = Template.bind({}); +Play.args = { + youtubeDisp: undefined, + videoStatus: 0 }; diff --git a/src/pages/Home/Home.stories.tsx b/src/pages/Home/Home.stories.tsx deleted file mode 100644 index bed9ec2..0000000 --- a/src/pages/Home/Home.stories.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { Story, Meta } from '@storybook/react/types-6-0'; -import Home from '.'; - -export default { - title: 'Page/Home', - component: Home -} as Meta; - -/* const Template: Story = () => ; - -export const Default = Template.bind({}); */ diff --git a/src/pages/Room/Room.stories.tsx b/src/pages/Room/Room.stories.tsx deleted file mode 100644 index aaf4046..0000000 --- a/src/pages/Room/Room.stories.tsx +++ /dev/null @@ -1 +0,0 @@ -import React from 'react'; From a19d4c495271e8a978b4a89b496113080df29e35 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 11 Apr 2021 06:11:49 +0900 Subject: [PATCH 41/84] =?UTF-8?q?feat(Wrap):=20Youtube=E3=82=B3=E3=83=B3?= =?UTF-8?q?=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E3=81=AE=E3=83=AC?= =?UTF-8?q?=E3=82=B9=E3=83=9D=E3=83=B3=E3=82=B7=E3=83=96=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ウィンドウの幅に応じて高さを変更するようにしました。 --- src/components/Volume/Presenter.tsx | 10 +++--- .../YoutubeController/Presenter.tsx | 34 ++++++++++++------- src/components/YoutubeWrap/Presenter.tsx | 5 +-- src/components/YoutubeWrap/main.css | 23 +++++++++++++ 4 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 src/components/YoutubeWrap/main.css diff --git a/src/components/Volume/Presenter.tsx b/src/components/Volume/Presenter.tsx index f45d03c..b7fb930 100644 --- a/src/components/Volume/Presenter.tsx +++ b/src/components/Volume/Presenter.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { Slider, IconButton, withStyles } from '@material-ui/core'; -import { VolumeOff, VolumeDown, VolumeUp } from '@material-ui/icons'; +import { VolumeOff, VolumeUp } from '@material-ui/icons'; interface PresenterProps { isMute: boolean; @@ -11,8 +11,10 @@ interface PresenterProps { export const Presenter: React.FC = (props: PresenterProps) => { return ( -
- {props.isMute ? : } +
+ + {props.isMute ? : } + = (props: PresenterProps) => { onChange={props.onChange} style={{ width: '100%', - marginLeft: '10px' + marginLeft: '1px' }} >
diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx index 6cd7ebc..aeb80c9 100644 --- a/src/components/YoutubeController/Presenter.tsx +++ b/src/components/YoutubeController/Presenter.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; import { withStyles } from '@material-ui/core/styles'; -import { Grid, Slider, IconButton } from '@material-ui/core'; +import { Grid, Slider, IconButton, Hidden } from '@material-ui/core'; import { PlayArrow, Pause } from '@material-ui/icons'; import { Volume } from '../Volume'; @@ -83,19 +83,28 @@ export const Presenter: React.FC = (props: PresenterProps) => { /> - - {props.valueLabelFormat(props.timed)}/{props.valueLabelFormat(props.duratioin)} + + + + + {props.valueLabelFormat(props.timed)}/ + {props.valueLabelFormat(props.duratioin)} + + + + + + + + - + - - - {props.statusIcon === 'play' ? ( @@ -107,6 +116,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { + diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index 9735496..0250c48 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -3,6 +3,7 @@ import YouTube, { YouTubeProps } from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; import { YoutubeController } from '../YoutubeController'; import { Box, Grid } from '@material-ui/core'; +import './main.css'; export interface PresenterProps { player: YouTubeProps; @@ -23,9 +24,9 @@ export const Presenter: React.FC = (props: PresenterProps) => { {/* 最大化の場合は↓を変更 */} - + - + diff --git a/src/components/YoutubeWrap/main.css b/src/components/YoutubeWrap/main.css new file mode 100644 index 0000000..7111f93 --- /dev/null +++ b/src/components/YoutubeWrap/main.css @@ -0,0 +1,23 @@ +@media screen and (max-width: 600px){ + .youtube_display{ + height: 250px; + } +} + +@media screen and (min-width: 601px){ + .youtube_display{ + height: 500px; + } +} + +@media screen and (min-width: 1500px){ + .youtube_display{ + height: 650px; + } +} + +@media screen and (min-width: 1920px){ + .youtube_display{ + height: 750px; + } +} \ No newline at end of file From e30d85fed3ea22171d9ba1e3e03a9a7980793d0b Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 11 Apr 2021 07:08:33 +0900 Subject: [PATCH 42/84] =?UTF-8?q?feat(Header,route):=20Header=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前に戻るボタンとCopyRoomIdButtonを配置しました。 --- src/components/Header/Presenter.tsx | 27 +++++++++++++++++++++++++++ src/components/Header/index.tsx | 12 ++++++++++++ src/components/Header/main.css | 18 ++++++++++++++++++ src/config/route.tsx | 2 ++ src/config/theme.ts | 4 ++-- 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/components/Header/Presenter.tsx create mode 100644 src/components/Header/index.tsx create mode 100644 src/components/Header/main.css diff --git a/src/components/Header/Presenter.tsx b/src/components/Header/Presenter.tsx new file mode 100644 index 0000000..3aae09c --- /dev/null +++ b/src/components/Header/Presenter.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import { AppBar, Toolbar, IconButton, Typography, Button } from '@material-ui/core'; +import { CopyRoomIdButton } from '../CopyRoomIdButton'; +import { ArrowLeftRounded } from '@material-ui/icons'; +import './main.css'; + +interface PresenterProps { + backClick: () => void; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + return ( +
+ + + + + +

+ Streaming!! +

+ +
+
+
+ ); +}; diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx new file mode 100644 index 0000000..f4784e8 --- /dev/null +++ b/src/components/Header/index.tsx @@ -0,0 +1,12 @@ +import * as React from 'react'; +import { useHistory } from 'react-router'; +import { Presenter } from './Presenter'; + +export const Header: React.FC = () => { + const history = useHistory(); + + const backClick = () => { + history.goBack(); + }; + return ; +}; diff --git a/src/components/Header/main.css b/src/components/Header/main.css new file mode 100644 index 0000000..707c1f7 --- /dev/null +++ b/src/components/Header/main.css @@ -0,0 +1,18 @@ +@import url('https://fonts.googleapis.com/css2?family=Fredoka+One&display=swap'); + +.header_logo{ + font-family: 'Fredoka One', cursive; + font-weight: bold; + font-size: 25px; + letter-spacing: 1px; + position: relative; + color: #55E6C1; + z-index: 2; + user-select: none; + box-sizing: border-box; + padding-left: 2px; +} +.header_logo > span{ + font-size: 28px; + color: #55E6C1; +} \ No newline at end of file diff --git a/src/config/route.tsx b/src/config/route.tsx index cec0450..ae719eb 100644 --- a/src/config/route.tsx +++ b/src/config/route.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import { Loading } from '../components/Loading'; import { PageProps } from '../App'; +import { Header } from '../components/Header'; const Home = React.lazy(() => { return Promise.all([import('../pages/Home'), new Promise((resolve) => setTimeout(resolve, 1000))]).then( @@ -30,6 +31,7 @@ export const Routes: React.FC = (props) => { const makeRoute = (routebase: RouteBase) => { return ( + {routebase.path !== '/' ?
: false} ); diff --git a/src/config/theme.ts b/src/config/theme.ts index fdee416..f22c1f9 100644 --- a/src/config/theme.ts +++ b/src/config/theme.ts @@ -3,8 +3,8 @@ import { createMuiTheme } from '@material-ui/core/styles'; export const theme = createMuiTheme({ palette: { primary: { - main: '#FF6F26', - contrastText: '#fff' + main: '#fff', + contrastText: '#555' }, secondary: { main: '#1dd1a1', From e46864621b4ac5cc22e22cec367e2be4e3281d1e Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 11 Apr 2021 07:18:18 +0900 Subject: [PATCH 43/84] =?UTF-8?q?refactor(Header):=20=E3=83=98=E3=83=83?= =?UTF-8?q?=E3=83=80=E3=83=BC=E3=83=AD=E3=82=B4=E3=81=AE=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=82=B5=E3=82=A4=E3=82=BA=E3=82=92=E8=AA=BF?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Header/main.css | 4 +--- src/components/YoutubeWrap/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/Header/main.css b/src/components/Header/main.css index 707c1f7..cbf09d2 100644 --- a/src/components/Header/main.css +++ b/src/components/Header/main.css @@ -3,7 +3,6 @@ .header_logo{ font-family: 'Fredoka One', cursive; font-weight: bold; - font-size: 25px; letter-spacing: 1px; position: relative; color: #55E6C1; @@ -13,6 +12,5 @@ padding-left: 2px; } .header_logo > span{ - font-size: 28px; - color: #55E6C1; + text-shadow: 2px 2px 3px #eee; } \ No newline at end of file diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 1df8758..76964d3 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -189,12 +189,12 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) return ( - setCandidate(e.target.value)} /> - + setCandidate(e.target.value)} /> + ); }; From da990ef155481212594b8c43dd7a0451e6f7fd4f Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 11 Apr 2021 07:34:49 +0900 Subject: [PATCH 44/84] =?UTF-8?q?fix(CopyRoomIdButton):=20=E3=83=91?= =?UTF-8?q?=E3=83=A9=E3=83=A1=E3=83=BC=E3=82=BF=E3=81=BE=E3=81=A7=E3=81=99?= =?UTF-8?q?=E3=81=B9=E3=81=A6=E3=82=AF=E3=83=AA=E3=83=83=E3=83=97=E3=83=9C?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=81=AB=E3=82=B3=E3=83=94=E3=83=BC=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=81=A6=E3=81=84=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F?= =?UTF-8?q?=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit window.location.href => location.href に変更しました。 --- src/components/CopyRoomIdButton/index.tsx | 2 +- src/pages/Room/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/CopyRoomIdButton/index.tsx b/src/components/CopyRoomIdButton/index.tsx index 43f7b92..4cad38a 100644 --- a/src/components/CopyRoomIdButton/index.tsx +++ b/src/components/CopyRoomIdButton/index.tsx @@ -6,7 +6,7 @@ import { Presenter } from './Presenter'; * URLをクリップボードにコピーするボタン */ export const CopyRoomIdButton: React.FC = () => { - const [url] = React.useState(window.location.href); + const [url] = React.useState(location.href); const urlInputRef = React.useRef(null); const { enqueueSnackbar } = useSnackbar(); diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 049210e..4018ef4 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -71,7 +71,7 @@ const Room: React.FC = (props: PageProps) => { if (screen.width < 600) return; enqueueSnackbar(message, { variant, - anchorOrigin: { horizontal: 'center', vertical: 'top' }, + anchorOrigin: { horizontal: 'left', vertical: 'bottom' }, autoHideDuration: 2000 }); }; From 005b991cd9261ec6e55ed58f354a0cbd11bdc3a7 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Sun, 11 Apr 2021 21:08:51 +0900 Subject: [PATCH 45/84] =?UTF-8?q?feat(Wrap):=20=E5=8B=95=E7=94=BB=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=82=AD=E3=83=A5=E3=83=BC=E3=81=AE=E5=90=8C=E6=9C=9F?= =?UTF-8?q?=E6=A9=9F=E8=83=BD=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit すごく苦戦しました。YouTubeコンポーネントのmovieIdプロパティに依存せず動画の変更は全てtarget.cueVideoByIdで行い、データとしての値はvideoIdステートに保存するようにしました。 --- src/components/YoutubeController/index.tsx | 9 +- src/components/YoutubeWrap/index.tsx | 95 ++++++++++++++-------- 2 files changed, 70 insertions(+), 34 deletions(-) diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index c756224..b6f4992 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -30,7 +30,8 @@ export const YoutubeController: React.FC = (props: Youtu checkTimer = setInterval( (props) => { - setTimed(props.youtubeDisp.getCurrentTime()); + const currentTime = props.youtubeDisp.getCurrentTime(); + setTimed(currentTime); }, 150, props @@ -45,7 +46,8 @@ export const YoutubeController: React.FC = (props: Youtu React.useEffect(() => { if (props.youtubeDisp) { - setDuration(props.youtubeDisp?.getDuration()); + const duration = props.youtubeDisp.getDuration(); + setDuration(duration); } statusCheck(props.videoStatus); }, [props.videoStatus]); @@ -59,6 +61,9 @@ export const YoutubeController: React.FC = (props: Youtu }; const valueLabelFormat = (value: number): string => { + if (!value) { + return '00:00'; + } const floorValue = Math.floor(value); const timeH = Math.floor((floorValue % (24 * 60 * 60)) / (60 * 60)); const timeM = Math.floor(((floorValue % (24 * 60 * 60)) % (60 * 60)) / 60); diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 76964d3..ab14c88 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -15,7 +15,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target const [videoId, setVideoId] = React.useState(''); const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される - const [candidateId, setCandidate] = React.useState(''); // 動画URL入力フォームの値 + const [candidateURL, setCandidate] = React.useState(''); // 動画URL入力フォームの値 const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ const [volume, setVolume] = React.useState(0); // ボリューム const [volumeLog, setVolumeLog] = React.useState(0); // 変更前のボリューム @@ -24,15 +24,32 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) // onReady React.useEffect(() => { setUpSocketListenner(); - }, [youtubeDisp]); + }, [youtubeDisp, videoId]); - // socket client Listennerを設定 + /** socket client Listennerを設定 */ const setUpSocketListenner = () => { if (!youtubeDisp) return; - const events = ['youtube_pause', 'youtube_play', 'youtube_seek', 'request_playing_data', 'new_playing_data']; - for (const event of events) { - socket.off(event); + const listenners = [ + 'youtube_add_movie', + 'youtube_pause', + 'youtube_play', + 'youtube_seek', + 'request_playing_data', + 'new_playing_data' + ]; + for (const listenner of listenners) { + socket.off(listenner); } + + socket.on('youtube_add_movie', (movie_id: string) => { + console.log('movieId', movie_id); + setVideoId(movie_id); + youtubeDisp.cueVideoById(movie_id); + setUpBuffer(youtubeDisp).then(() => { + youtubeDisp.playVideo(); + }); + }); + socket.on('youtube_pause', (time: number) => { youtubeDisp?.pauseVideo(); youtubeDisp?.seekTo(time, true); @@ -69,14 +86,17 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { console.log('newplayingData', res); if (res.movie_id) { + youtubeDisp.cueVideoById(res.movie_id); setVideoId(res.movie_id); } - if (res.isPlaying) { - youtubeDisp.seekTo(res.time + 0.2, true); - youtubeDisp.playVideo(); - } else { - youtubeDisp.seekTo(res.time, true); - } + setUpBuffer(youtubeDisp).then(() => { + if (res.isPlaying) { + youtubeDisp.seekTo(res.time + 1.2, true); + youtubeDisp.playVideo(); + } else { + youtubeDisp.seekTo(res.time, true); + } + }); }); // ボリューム情報のセット @@ -85,7 +105,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) setVolumeLog(defaultVolume); // ボリュームを保存 }; - // ステータスナンバーから再生中か停止中かを返す + /** ステータスナンバーから再生中か停止中かを返す */ const statusCheck = (value: number): boolean => { // https://developers.google.com/youtube/iframe_api_reference?hl=ja#Adding_event_listener 参照 let isPlaying = false; @@ -112,9 +132,8 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) return isPlaying; }; - // react-youtubeコンポーネントの設定 + /** react-youtubeコンポーネントの設定 */ const player: YouTubeProps = { - videoId: videoId, onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { if (!socket || isFirst) return; socket.emit('youtube_play', target.getCurrentTime()); @@ -126,22 +145,18 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) onReady: (event: { target: YouTubePlayer }) => { const { target } = event; setDisp(target); - target.mute(); - mute(); - target.cueVideoById('b6-2P8RgT0A'); - target.playVideo(); + if (room.isOwner) { + target.cueVideoById('b6-2P8RgT0A'); + setVideoId('b6-2P8RgT0A'); + setUpBuffer(target).then(() => { + console.log('Buffer完了'); + }); + } else { + socket.emit('youtube_sync'); + } window.setTimeout(() => { - target.pauseVideo(); - target.seekTo(0, true); - target.unMute(); - unMute(); - if (!room.isOwner) { - socket.emit('youtube_sync'); - } - window.setTimeout(() => { - setIsFirst(false); - }, 500); - }, 1000); + setIsFirst(false); + }, 2000); }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { // console.log('onStateChange', data); @@ -162,8 +177,24 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) } }; + /** ミュート状態で1秒間再生し、元に戻して一時停止する初期バッファーを読み込むための関数です */ + const setUpBuffer = (target: YouTubePlayer) => { + return new Promise((resolve) => { + target.mute(); + mute(); + target.playVideo(); + window.setTimeout(() => { + target.pauseVideo(); + target.seekTo(0, true); + target.unMute(); + unMute(); + resolve(true); + }, 1000); + }); + }; + const handler = () => { - youtubeDisp?.loadVideoById(candidateId); + socket.emit('youtube_add_movie', candidateURL); }; /** ボリュームを変更する */ @@ -193,7 +224,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) player={player} controller={{ socket, youtubeDisp, videoStatus, volume, isMuted, mute, unMute, changeVolume }} /> - setCandidate(e.target.value)} /> + setCandidate(e.target.value)} /> ); From 70d6469de28ca80d607b23008d9d38a730efa288 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 12 Apr 2021 06:49:37 +0900 Subject: [PATCH 46/84] =?UTF-8?q?feat(AddForm,Wrap,):=20=E5=8B=95=E7=94=BB?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=82=AD=E3=83=A5=E3=83=BC=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=83=A0=E3=82=B9=E3=82=BF=E3=82=A4=E3=83=AA=E3=83=B3?= =?UTF-8?q?=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit レスポンシブ対応済みです。 --- src/components/AddForm/Presenter.tsx | 37 ++++++++++++++++++++++++++++ src/components/AddForm/index.tsx | 22 +++++++++++++++++ src/components/YoutubeWrap/index.tsx | 9 +------ src/pages/Room/Presenter.tsx | 20 ++++++++++++--- src/pages/Room/main.css | 2 +- 5 files changed, 77 insertions(+), 13 deletions(-) create mode 100644 src/components/AddForm/Presenter.tsx create mode 100644 src/components/AddForm/index.tsx diff --git a/src/components/AddForm/Presenter.tsx b/src/components/AddForm/Presenter.tsx new file mode 100644 index 0000000..27ad953 --- /dev/null +++ b/src/components/AddForm/Presenter.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { Button, Grid, TextField } from '@material-ui/core'; + +interface PresenterProps { + videoId: string; + onChange: (value: string) => void; + addMovieHandler: () => void; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + return ( + + + props.onChange(e.target.value)} + > + + + + + + ); +}; diff --git a/src/components/AddForm/index.tsx b/src/components/AddForm/index.tsx new file mode 100644 index 0000000..7c1f1de --- /dev/null +++ b/src/components/AddForm/index.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import { Presenter } from './Presenter'; + +interface AddFormProps { + socket: SocketIOClient.Socket; +} + +export const AddForm: React.FC = (props: AddFormProps) => { + const socket = props.socket; + const [videoId, setVideoId] = React.useState(''); + + const onChange = (value: string) => { + setVideoId(value); + }; + + const addMovieHandler = () => { + socket.emit('youtube_add_movie', videoId); + setVideoId(''); + }; + + return ; +}; diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index ab14c88..12b1199 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -15,7 +15,6 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target const [videoId, setVideoId] = React.useState(''); const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される - const [candidateURL, setCandidate] = React.useState(''); // 動画URL入力フォームの値 const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ const [volume, setVolume] = React.useState(0); // ボリューム const [volumeLog, setVolumeLog] = React.useState(0); // 変更前のボリューム @@ -91,7 +90,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) } setUpBuffer(youtubeDisp).then(() => { if (res.isPlaying) { - youtubeDisp.seekTo(res.time + 1.2, true); + youtubeDisp.seekTo(res.time + 1.5, true); youtubeDisp.playVideo(); } else { youtubeDisp.seekTo(res.time, true); @@ -193,10 +192,6 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) }); }; - const handler = () => { - socket.emit('youtube_add_movie', candidateURL); - }; - /** ボリュームを変更する */ const changeVolume = (value: number) => { youtubeDisp?.setVolume(value); @@ -224,8 +219,6 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) player={player} controller={{ socket, youtubeDisp, videoStatus, volume, isMuted, mute, unMute, changeVolume }} /> - setCandidate(e.target.value)} /> - ); }; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index 6c2d7a4..43ba532 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -4,6 +4,7 @@ import { makeStyles } from '@material-ui/core/styles'; import { YoutubeWrap } from '../../components/YoutubeWrap'; import './main.css'; import { CreateForm, CreateFormProps, InputSub } from '../../components/CreateForm'; +import { AddForm } from '../../components/AddForm'; interface PresenterProps { socket: SocketIOClient.Socket | null; @@ -18,11 +19,22 @@ interface PresenterProps { export const Presenter: React.FC = (props: PresenterProps) => { return ( - - - {props.roomId && {props.socket && }} + {props.roomId && props.socket ? ( + + + + + + + + + + + - + ) : ( + false + )} {props.roomId ? ( false ) : ( diff --git a/src/pages/Room/main.css b/src/pages/Room/main.css index eff8f12..a0b8e75 100644 --- a/src/pages/Room/main.css +++ b/src/pages/Room/main.css @@ -1,5 +1,5 @@ body{ - background-color: #F9F9F9; + background-color: #373739; } .base { From 186a53376ced6ad6a785af1fde752547991420b3 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 12 Apr 2021 07:31:14 +0900 Subject: [PATCH 47/84] =?UTF-8?q?fix(Wrap):=20=E9=9F=B3=E9=87=8F=E8=AA=BF?= =?UTF-8?q?=E6=95=B4=E3=82=B3=E3=83=B3=E3=83=88=E3=83=AD=E3=83=BC=E3=83=A9?= =?UTF-8?q?=E3=81=AE=E3=83=90=E3=82=B0=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 音量調整コントローラの初期値が実数値と違っていたバグ、動画変更あとに音量が100になってしまうバグの修正。 re #28 --- src/components/YoutubeWrap/index.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 12b1199..826ad46 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -97,11 +97,6 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) } }); }); - - // ボリューム情報のセット - const defaultVolume = youtubeDisp.getVolume(); - changeVolume(defaultVolume); // ボリュームを取得 - setVolumeLog(defaultVolume); // ボリュームを保存 }; /** ステータスナンバーから再生中か停止中かを返す */ @@ -144,11 +139,16 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) onReady: (event: { target: YouTubePlayer }) => { const { target } = event; setDisp(target); + target.setVolume(30); if (room.isOwner) { target.cueVideoById('b6-2P8RgT0A'); setVideoId('b6-2P8RgT0A'); setUpBuffer(target).then(() => { console.log('Buffer完了'); + // ボリューム情報のセット + const defaultVolume = target.getVolume(); + changeVolume(defaultVolume); // ボリュームを取得 + setVolumeLog(defaultVolume); // ボリュームを保存 }); } else { socket.emit('youtube_sync'); @@ -179,13 +179,11 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) /** ミュート状態で1秒間再生し、元に戻して一時停止する初期バッファーを読み込むための関数です */ const setUpBuffer = (target: YouTubePlayer) => { return new Promise((resolve) => { - target.mute(); mute(); target.playVideo(); window.setTimeout(() => { target.pauseVideo(); target.seekTo(0, true); - target.unMute(); unMute(); resolve(true); }, 1000); From 500d7d81e84a51c653c2b851344c783605a4c1b5 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 12 Apr 2021 10:30:50 +0900 Subject: [PATCH 48/84] =?UTF-8?q?feat(env.base,PlayingBoard,Wrap):=20?= =?UTF-8?q?=E5=86=8D=E7=94=9F=E4=B8=AD=E3=81=AE=E5=8B=95=E7=94=BB=E3=82=BF?= =?UTF-8?q?=E3=82=A4=E3=83=88=E3=83=AB=E3=82=92=E3=82=A2=E3=83=8B=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=A7=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 再生中の動画タイトルを videoId を元に YouTube Data API から取得し、アニメーションと共に表示する機能、スタイルングを実装。 BREAKING CHANGE: YouTubeDataAPIを利用しているので.env.baseを参考に.envファイルを各自編集してください。 --- .env.base | 3 +- package-lock.json | 17 ++++++++ package.json | 2 + src/components/PlayingBoard/Presenter.tsx | 30 +++++++++++++ src/components/PlayingBoard/index.tsx | 30 +++++++++++++ src/components/PlayingBoard/main.css | 52 +++++++++++++++++++++++ src/components/YoutubeWrap/Presenter.tsx | 17 ++++++-- src/components/YoutubeWrap/index.tsx | 1 + 8 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 src/components/PlayingBoard/Presenter.tsx create mode 100644 src/components/PlayingBoard/index.tsx create mode 100644 src/components/PlayingBoard/main.css diff --git a/.env.base b/.env.base index 4452883..908abdb 100644 --- a/.env.base +++ b/.env.base @@ -1 +1,2 @@ -REACT_APP_API_URL= \ No newline at end of file +REACT_APP_API_URL= +REACT_APP_YOUTUBE_KEY= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 32e59f9..b494f74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5284,6 +5284,15 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.1.tgz", "integrity": "sha512-S6oPal772qJZHoRZLFc/XoZW2gFvwXusYUmXPXkgxJLuEk2vOt7jc4Yo6z/vtI0EBkbPBVrJJ0B+prLIKiWqHg==" }, + "@types/axios": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz", + "integrity": "sha1-7CMA++fX3d1+udOr+HmZlkyvzkY=", + "dev": true, + "requires": { + "axios": "*" + } + }, "@types/babel__core": { "version": "7.1.14", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz", @@ -6592,6 +6601,14 @@ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.1.3.tgz", "integrity": "sha512-vwPpH4Aj4122EW38mxO/fxhGKtwWTMLDIJfZ1He0Edbtjcfna/R3YB67yVhezUMzqc3Jr3+Ii50KRntlENL4xQ==" }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", diff --git a/package.json b/package.json index 6d270a9..d226d37 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@types/node": "^12.20.7", "@types/react": "^17.0.3", "@types/react-dom": "^17.0.3", + "axios": "^0.21.1", "notistack": "^1.0.5", "react": "^17.0.2", "react-dom": "^17.0.2", @@ -70,6 +71,7 @@ "@storybook/node-logger": "^6.2.1", "@storybook/preset-create-react-app": "^3.1.7", "@storybook/react": "^6.2.1", + "@types/axios": "^0.14.0", "@types/material-ui": "^0.21.8", "@types/react-router-dom": "^5.1.7", "@types/redux-logger": "^3.0.8", diff --git a/src/components/PlayingBoard/Presenter.tsx b/src/components/PlayingBoard/Presenter.tsx new file mode 100644 index 0000000..783c187 --- /dev/null +++ b/src/components/PlayingBoard/Presenter.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { Grid, Box } from '@material-ui/core'; + +interface PresenterProps { + title: string; +} + +export const Presenter: React.FC = (props: PresenterProps) => { + return ( + + + + + + + + + + + + + + + +

{props.title}

+
+
+
+ ); +}; diff --git a/src/components/PlayingBoard/index.tsx b/src/components/PlayingBoard/index.tsx new file mode 100644 index 0000000..4ea1e73 --- /dev/null +++ b/src/components/PlayingBoard/index.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import axios from 'axios'; +import { Presenter } from './Presenter'; +import './main.css'; + +interface PlayingBoardProps { + videoId: string; +} + +export const PlayingBoard: React.FC = (props: PlayingBoardProps) => { + const [title, setTitle] = React.useState(''); + const APIKEY: string = process.env.REACT_APP_YOUTUBE_KEY as string; + React.useEffect(() => { + if (!props.videoId) return; + getTitle(); + }, [props.videoId]); + const getTitle = () => { + axios + .get(`https://www.googleapis.com/youtube/v3/search?key=${APIKEY}&part=id,snippet`, { + params: { q: props.videoId } + }) + .then(({ data, status }) => { + if (status === 200) { + const title = data.items[0].snippet.title; + setTitle(title); + } + }); + }; + return ; +}; diff --git a/src/components/PlayingBoard/main.css b/src/components/PlayingBoard/main.css new file mode 100644 index 0000000..0b7f5e5 --- /dev/null +++ b/src/components/PlayingBoard/main.css @@ -0,0 +1,52 @@ + .PlayingBoard{ + padding: 5px 0px; + font-size: 12px; + box-sizing: border-box; + } + + svg#icon-audio-disc { + margin: auto; + width: 80%; + stroke: #fff; + } + + @media screen and (min-width: 1270px) { + svg#icon-audio-disc { + width: 60%; + } + } + + svg#icon-audio-disc path{ + color: #fff; + } + + #icon-audio-disc { + -webkit-transform-origin: center; + transform-origin: center; + -webkit-animation: spinning 3s linear alternate infinite; + animation: spinning 3s linear alternate infinite; + } + + @keyframes spinning { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + .title { + overflow : hidden; + } + .title p{ + color: rgba(255,255,255,0.7); + margin: 0; + display : inline-block; + padding-left: 2px; + white-space : nowrap; + animation : scrolltitle 15s linear infinite; + } \ No newline at end of file diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index 0250c48..5153e1b 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -4,9 +4,11 @@ import { YouTubePlayer } from 'youtube-player/dist/types'; import { YoutubeController } from '../YoutubeController'; import { Box, Grid } from '@material-ui/core'; import './main.css'; +import { PlayingBoard } from '../PlayingBoard'; export interface PresenterProps { player: YouTubeProps; + videoId: string; controller: { socket: SocketIOClient.Socket; youtubeDisp: YouTubePlayer | undefined; @@ -25,9 +27,18 @@ export const Presenter: React.FC = (props: PresenterProps) => { {/* 最大化の場合は↓を変更 */} - - - + + + + + + + + + + + + diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 826ad46..5c38abc 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -215,6 +215,7 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) From f3369d3acd4de77a9155563976980bdf4bb61bd5 Mon Sep 17 00:00:00 2001 From: amanojs Date: Mon, 12 Apr 2021 22:02:16 +0900 Subject: [PATCH 49/84] =?UTF-8?q?fix(Wrap,Room):=20YoutubeWrap=E3=82=B3?= =?UTF-8?q?=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E3=82=92?= =?UTF-8?q?=E3=82=AF=E3=83=A9=E3=82=B9=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC?= =?UTF-8?q?=E3=83=8D=E3=83=B3=E3=83=88=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit タイムリーな処理が多いYoutubeWrapコンポーネントでsetStateのコールバックが使用できないことが多くのバグを生み出す原因となっていたのでファンクションコンポーネントからクラスコンポーネントに変更しました。 BREAKING CHANGE: YoutubeWrapコンポーネントをクラスコンポーネントに変更しました。 --- src/components/PlayingBoard/index.tsx | 10 +- src/components/YoutubeWrap/index.tsx | 206 +++++++++++++++----------- src/pages/Room/Presenter.tsx | 9 +- src/pages/Room/index.tsx | 2 +- 4 files changed, 136 insertions(+), 91 deletions(-) diff --git a/src/components/PlayingBoard/index.tsx b/src/components/PlayingBoard/index.tsx index 4ea1e73..bf96c91 100644 --- a/src/components/PlayingBoard/index.tsx +++ b/src/components/PlayingBoard/index.tsx @@ -15,14 +15,20 @@ export const PlayingBoard: React.FC = (props: PlayingBoardPro getTitle(); }, [props.videoId]); const getTitle = () => { + console.log('youtube videoId', props.videoId); axios .get(`https://www.googleapis.com/youtube/v3/search?key=${APIKEY}&part=id,snippet`, { params: { q: props.videoId } }) .then(({ data, status }) => { if (status === 200) { - const title = data.items[0].snippet.title; - setTitle(title); + // console.log('title data', data); + try { + const title = data.items[0].snippet.title; + setTitle(title); + } catch { + setTitle('動画タイトルを取得できませんでした'); + } } }); }; diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 5c38abc..d4a2ec0 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -4,30 +4,51 @@ import { State } from '../../store/store'; import { YouTubePlayer } from 'youtube-player/dist/types'; import { Presenter } from './Presenter'; import { YouTubeProps } from 'react-youtube'; +import { RoomState } from '../../store/modules/roomModule'; interface YoutubeWrapProps { socket: SocketIOClient.Socket; + room: RoomState; } -export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) => { - const socket = props.socket; - const room = useSelector((state: State) => state.room); - const [youtubeDisp, setDisp] = React.useState(undefined); // youtube target - const [videoId, setVideoId] = React.useState(''); - const [videoStatus, setVideoStatus] = React.useState(-1); // YouTubeコンポーネントのステータスが変更された時に変更される - const [isFirst, setIsFirst] = React.useState(true); // 参加時かどうかのフラグ - const [volume, setVolume] = React.useState(0); // ボリューム - const [volumeLog, setVolumeLog] = React.useState(0); // 変更前のボリューム - const [isMuted, setIsMuted] = React.useState(true); // ミュートフラグ - - // onReady - React.useEffect(() => { - setUpSocketListenner(); - }, [youtubeDisp, videoId]); +interface YoutubeWrapState { + youtubeDisp: YouTubePlayer | undefined; + videoId: string; + videoStatus: number; + isFirst: boolean; + volume: number; + volumeLog: number; + isMuted: boolean; +} + +export class YoutubeWrap extends React.Component { + constructor(props: YoutubeWrapProps) { + super(props); + this.state = { + youtubeDisp: undefined, // youtube target + videoId: '', + videoStatus: -1, // YouTubeコンポーネントのステータスが変更された時に変更される + isFirst: true, // 参加時かどうかのフラグ + volume: 0, // ボリューム + volumeLog: 0, // 変更前のボリューム + isMuted: true // ミュートフラグ + }; + this.mute = this.mute.bind(this); + this.unMute = this.unMute.bind(this); + this.changeVolume = this.changeVolume.bind(this); + } + + socket = this.props.socket; + + componentDidUpdate() { + console.log('componentDidUpdate', this.state.videoId); + if (this.state.youtubeDisp) { + this.setUpSocketListenner(); + } + } /** socket client Listennerを設定 */ - const setUpSocketListenner = () => { - if (!youtubeDisp) return; + setUpSocketListenner = () => { const listenners = [ 'youtube_add_movie', 'youtube_pause', @@ -37,70 +58,76 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) 'new_playing_data' ]; for (const listenner of listenners) { - socket.off(listenner); + this.socket.off(listenner); } - socket.on('youtube_add_movie', (movie_id: string) => { + this.socket.on('youtube_add_movie', (movie_id: string) => { + if (!this.state.youtubeDisp) return; console.log('movieId', movie_id); - setVideoId(movie_id); - youtubeDisp.cueVideoById(movie_id); - setUpBuffer(youtubeDisp).then(() => { - youtubeDisp.playVideo(); + this.setState({ videoId: movie_id }); + this.state.youtubeDisp.cueVideoById(movie_id); + this.setUpBuffer(this.state.youtubeDisp).then(() => { + this.state.youtubeDisp?.playVideo(); }); }); - socket.on('youtube_pause', (time: number) => { - youtubeDisp?.pauseVideo(); - youtubeDisp?.seekTo(time, true); + this.socket.on('youtube_pause', (time: number) => { + if (!this.state.youtubeDisp) return; + this.state.youtubeDisp.pauseVideo(); + this.state.youtubeDisp.seekTo(time, true); //console.log('listen!pause!', time, youtubeDisp); }); - socket.on('youtube_play', (time: number) => { - youtubeDisp?.playVideo(); + this.socket.on('youtube_play', (time: number) => { + if (!this.state.youtubeDisp) return; + this.state.youtubeDisp.playVideo(); // console.log('listen!play!', time, youtubeDisp); }); - socket.on('youtube_seek', (time: number) => { - youtubeDisp?.seekTo(time, true); + this.socket.on('youtube_seek', (time: number) => { + if (!this.state.youtubeDisp) return; + this.state.youtubeDisp.seekTo(time, true); }); - socket.on('request_playing_data', async (participant_id: string) => { - const status = youtubeDisp?.getPlayerState(); - const time = youtubeDisp?.getCurrentTime(); + this.socket.on('request_playing_data', async (participant_id: string) => { + if (!this.state.youtubeDisp) return; + const status = this.state.youtubeDisp.getPlayerState(); + const time = this.state.youtubeDisp.getCurrentTime(); const playingData: { movie_id?: string; time: number; isPlaying: boolean } = { time: time || 0.0, - isPlaying: status ? statusCheck(status) : false + isPlaying: status ? this.statusCheck(status) : false }; // console.log('プレイングデータをemitします', playingData); - if (videoId) { - playingData.movie_id = videoId; + if (this.state.videoId) { + playingData.movie_id = this.state.videoId; } const payload = { socket_id: participant_id, playingData: playingData }; - socket.emit('send_playing_data', payload); + this.socket.emit('send_playing_data', payload); }); - socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { + this.socket.on('new_playing_data', (res: { movie_id?: string; time: number; isPlaying: boolean }) => { + if (!this.state.youtubeDisp) return; console.log('newplayingData', res); if (res.movie_id) { - youtubeDisp.cueVideoById(res.movie_id); - setVideoId(res.movie_id); + this.state.youtubeDisp.cueVideoById(res.movie_id); + this.setState({ videoId: res.movie_id }); } - setUpBuffer(youtubeDisp).then(() => { + this.setUpBuffer(this.state.youtubeDisp).then(() => { if (res.isPlaying) { - youtubeDisp.seekTo(res.time + 1.5, true); - youtubeDisp.playVideo(); + this.state.youtubeDisp?.seekTo(res.time + 1.5, true); + this.state.youtubeDisp?.playVideo(); } else { - youtubeDisp.seekTo(res.time, true); + this.state.youtubeDisp?.seekTo(res.time, true); } }); }); }; /** ステータスナンバーから再生中か停止中かを返す */ - const statusCheck = (value: number): boolean => { + statusCheck = (value: number): boolean => { // https://developers.google.com/youtube/iframe_api_reference?hl=ja#Adding_event_listener 参照 let isPlaying = false; switch (value) { @@ -127,39 +154,39 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) }; /** react-youtubeコンポーネントの設定 */ - const player: YouTubeProps = { + player: YouTubeProps = { onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { - if (!socket || isFirst) return; - socket.emit('youtube_play', target.getCurrentTime()); + if (this.state.isFirst) return; + this.socket.emit('youtube_play', target.getCurrentTime()); }, onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => { - if (!socket || isFirst) return; - socket.emit('youtube_pause', target.getCurrentTime()); + if (this.state.isFirst) return; + this.socket.emit('youtube_pause', target.getCurrentTime()); }, onReady: (event: { target: YouTubePlayer }) => { const { target } = event; - setDisp(target); + this.setState({ youtubeDisp: target }); target.setVolume(30); - if (room.isOwner) { + if (this.props.room.isOwner) { target.cueVideoById('b6-2P8RgT0A'); - setVideoId('b6-2P8RgT0A'); - setUpBuffer(target).then(() => { + this.setState({ videoId: 'b6-2P8RgT0A' }); + this.setUpBuffer(target).then(() => { console.log('Buffer完了'); // ボリューム情報のセット const defaultVolume = target.getVolume(); - changeVolume(defaultVolume); // ボリュームを取得 - setVolumeLog(defaultVolume); // ボリュームを保存 + this.changeVolume(defaultVolume); // ボリュームを取得 + this.setState({ volumeLog: defaultVolume }); // ボリュームを保存 }); } else { - socket.emit('youtube_sync'); + this.socket.emit('youtube_sync'); } window.setTimeout(() => { - setIsFirst(false); + this.setState({ isFirst: false }); }, 2000); }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { // console.log('onStateChange', data); - setVideoStatus(data); + this.setState({ videoStatus: data }); }, // https://developers.google.com/youtube/player_parameters?hl=ja ここ参照してる opts: { @@ -177,47 +204,58 @@ export const YoutubeWrap: React.FC = (props: YoutubeWrapProps) }; /** ミュート状態で1秒間再生し、元に戻して一時停止する初期バッファーを読み込むための関数です */ - const setUpBuffer = (target: YouTubePlayer) => { + setUpBuffer = (target: YouTubePlayer) => { return new Promise((resolve) => { - mute(); + this.mute(); target.playVideo(); window.setTimeout(() => { target.pauseVideo(); target.seekTo(0, true); - unMute(); + this.unMute(); resolve(true); }, 1000); }); }; /** ボリュームを変更する */ - const changeVolume = (value: number) => { - youtubeDisp?.setVolume(value); - setVolume(value); + changeVolume = (value: number) => { + this.state.youtubeDisp?.setVolume(value); + this.setState({ volume: value }); }; /** ミュート時の処理 */ - const mute = () => { - setIsMuted(true); - changeVolume(0); - setVolumeLog(volume); - youtubeDisp?.mute(); + mute = () => { + this.setState({ isMuted: true }); + this.changeVolume(0); + this.setState({ volumeLog: this.state.volume }); + this.state.youtubeDisp?.mute(); }; /** アンミュート時の処理 */ - const unMute = () => { - setIsMuted(false); - youtubeDisp?.unMute(); - volumeLog > 30 ? changeVolume(volumeLog) : changeVolume(30); + unMute = () => { + this.setState({ isMuted: false }); + this.state.youtubeDisp?.unMute(); + this.state.volumeLog > 30 ? this.changeVolume(this.state.volumeLog) : this.changeVolume(30); }; - return ( - - - - ); -}; + render() { + return ( + + + + ); + } +} diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index 43ba532..16b4f0d 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -5,10 +5,11 @@ import { YoutubeWrap } from '../../components/YoutubeWrap'; import './main.css'; import { CreateForm, CreateFormProps, InputSub } from '../../components/CreateForm'; import { AddForm } from '../../components/AddForm'; +import { RoomState } from '../../store/modules/roomModule'; interface PresenterProps { socket: SocketIOClient.Socket | null; - roomId: string; + room: RoomState; nameDialog: boolean; createForm: { inputs: InputSub[]; @@ -19,11 +20,11 @@ interface PresenterProps { export const Presenter: React.FC = (props: PresenterProps) => { return ( - {props.roomId && props.socket ? ( + {props.room.roomId && props.socket ? ( - + @@ -35,7 +36,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { ) : ( false )} - {props.roomId ? ( + {props.room.roomId ? ( false ) : (
diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 4018ef4..2626765 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -117,7 +117,7 @@ const Room: React.FC = (props: PageProps) => { return ( From 9a35ddc1c31ceb90c70d2c5bc7af8d5b5cb4c501 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Tue, 13 Apr 2021 00:12:29 +0900 Subject: [PATCH 50/84] =?UTF-8?q?feature(Volume):=20YouTube=E3=81=AE?= =?UTF-8?q?=E3=83=87=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E9=9F=B3=E9=87=8F?= =?UTF-8?q?=E3=81=AE=E5=8F=96=E5=BE=97=E6=A9=9F=E8=83=BD=E5=AE=9F=E8=A3=85?= =?UTF-8?q?=20BREAKING=20CHANGE:=20YouTube=E3=82=B3=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=A9=E3=82=92=E4=B8=80=E6=97=A6=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA=E3=81=97=E3=81=A6=E3=81=9D=E3=81=AE=E5=BE=8C=E9=9D=9E?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=AB=E3=81=97=E3=81=A6=E3=81=84=E3=81=BE?= =?UTF-8?q?=E3=81=99=E3=80=82=20YouTube=E9=83=A8=E5=88=86=E3=81=AE?= =?UTF-8?q?=E8=83=8C=E6=99=AF=E8=89=B2=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeWrap/Presenter.tsx | 5 +- src/components/YoutubeWrap/index.tsx | 127 +++++++++++++++-------- 2 files changed, 87 insertions(+), 45 deletions(-) diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index 5153e1b..c2026fe 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -19,6 +19,7 @@ export interface PresenterProps { mute: () => void; unMute: () => void; }; + opts: YouTubeProps['opts']; } export const Presenter: React.FC = (props: PresenterProps) => { @@ -32,8 +33,8 @@ export const Presenter: React.FC = (props: PresenterProps) => { - - + + diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index d4a2ec0..b6a534b 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -19,8 +19,22 @@ interface YoutubeWrapState { volume: number; volumeLog: number; isMuted: boolean; + opts: YouTubeProps['opts']; } +const defaultOpts: YouTubeProps['opts'] = { + width: '100%', + height: '700px', + playerVars: { + controls: 1, + rel: 0, + playsinline: 1, + fs: 0, + disablekb: 1, + modestbranding: 1 + } +}; + export class YoutubeWrap extends React.Component { constructor(props: YoutubeWrapProps) { super(props); @@ -31,8 +45,10 @@ export class YoutubeWrap extends React.Component { + setUpSocketListenner = (): void => { const listenners = [ 'youtube_add_movie', 'youtube_pause', @@ -166,45 +182,62 @@ export class YoutubeWrap extends React.Component { const { target } = event; this.setState({ youtubeDisp: target }); - target.setVolume(30); - if (this.props.room.isOwner) { - target.cueVideoById('b6-2P8RgT0A'); - this.setState({ videoId: 'b6-2P8RgT0A' }); - this.setUpBuffer(target).then(() => { - console.log('Buffer完了'); - // ボリューム情報のセット - const defaultVolume = target.getVolume(); - this.changeVolume(defaultVolume); // ボリュームを取得 - this.setState({ volumeLog: defaultVolume }); // ボリュームを保存 - }); - } else { - this.socket.emit('youtube_sync'); - } - window.setTimeout(() => { - this.setState({ isFirst: false }); - }, 2000); + // ボリューム情報のセット + const defaultVolume = target.getVolume(); + let prev_flag: number | undefined = 0; + this.setState( + (prev) => { + // コントローラ表示時のみボリュームログに保存 + prev_flag = prev.opts?.playerVars?.controls; + if (prev.opts?.playerVars?.controls === 1) { + return { ...prev, volumeLog: defaultVolume }; + } else { + return { ...prev }; + } + }, + () => { + // コントローラを非表示にする + this.setState( + (prev) => ({ + opts: { + ...prev.opts, + playerVars: { + ...prev.opts?.playerVars, + controls: 0 + } + } + }), + () => { + target.setVolume(0); + if (this.props.room.isOwner) { + if (prev_flag === 0) { + target.cueVideoById('b6-2P8RgT0A'); + this.setState({ videoId: 'b6-2P8RgT0A' }, () => { + this.setUpBuffer(target).then(() => { + console.log('Buffer完了'); + }); + }); + } + } else { + this.socket.emit('youtube_sync'); + } + window.setTimeout(() => { + this.setState({ isFirst: false }); + }, 2000); + } + ); + } + ); }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { // console.log('onStateChange', data); this.setState({ videoStatus: data }); - }, - // https://developers.google.com/youtube/player_parameters?hl=ja ここ参照してる - opts: { - width: '100%', - height: '700px', - playerVars: { - controls: 0, - rel: 0, - playsinline: 1, - fs: 0, - disablekb: 1, - modestbranding: 1 - } } + // https://developers.google.com/youtube/player_parameters?hl=ja ここ参照してる }; /** ミュート状態で1秒間再生し、元に戻して一時停止する初期バッファーを読み込むための関数です */ - setUpBuffer = (target: YouTubePlayer) => { + setUpBuffer = (target: YouTubePlayer): Promise => { return new Promise((resolve) => { this.mute(); target.playVideo(); @@ -218,31 +251,39 @@ export class YoutubeWrap extends React.Component { + changeVolume = (value: number): void => { this.state.youtubeDisp?.setVolume(value); this.setState({ volume: value }); }; /** ミュート時の処理 */ - mute = () => { - this.setState({ isMuted: true }); - this.changeVolume(0); - this.setState({ volumeLog: this.state.volume }); - this.state.youtubeDisp?.mute(); + mute = (): void => { + this.setState({ isMuted: true }, () => { + this.setState((prev) => { + if (prev.volume > 0) { + return { volumeLog: this.state.volume }; + } else { + return { ...prev }; + } + }); + this.changeVolume(0); + this.state.youtubeDisp?.mute(); + }); }; /** アンミュート時の処理 */ - unMute = () => { + unMute = (): void => { this.setState({ isMuted: false }); this.state.youtubeDisp?.unMute(); - this.state.volumeLog > 30 ? this.changeVolume(this.state.volumeLog) : this.changeVolume(30); + this.state.volumeLog > 1 ? this.changeVolume(this.state.volumeLog) : this.changeVolume(30); }; - render() { + render(): JSX.Element { return ( Date: Tue, 13 Apr 2021 00:52:22 +0900 Subject: [PATCH 51/84] =?UTF-8?q?fix(Wrap):=201=E4=BA=BA=E3=81=8C=E5=86=8D?= =?UTF-8?q?=E7=94=9F=E3=80=81=E5=81=9C=E6=AD=A2=E3=81=99=E3=82=8B=E3=81=A8?= =?UTF-8?q?=E5=85=A8=E3=81=A6=E3=81=AE=E3=82=AF=E3=83=A9=E3=82=A4=E3=82=A2?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=81=8B=E3=82=89emit=E3=81=99=E3=82=8B?= =?UTF-8?q?=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=97?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeWrap/index.tsx | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index b6a534b..713abbe 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -15,6 +15,7 @@ interface YoutubeWrapState { youtubeDisp: YouTubePlayer | undefined; videoId: string; videoStatus: number; + getAction: boolean; isFirst: boolean; volume: number; volumeLog: number; @@ -42,6 +43,7 @@ export class YoutubeWrap extends React.Component { if (!this.state.youtubeDisp) return; - this.state.youtubeDisp.pauseVideo(); - this.state.youtubeDisp.seekTo(time, true); - //console.log('listen!pause!', time, youtubeDisp); + // console.log('listen!pause!', time); + this.setState({ getAction: true }, () => { + this.state.youtubeDisp?.pauseVideo(); + this.state.youtubeDisp?.seekTo(time, true); + }); }); this.socket.on('youtube_play', (time: number) => { if (!this.state.youtubeDisp) return; - this.state.youtubeDisp.playVideo(); - // console.log('listen!play!', time, youtubeDisp); + // console.log('listen!play!', time); + this.setState({ getAction: true }, () => { + this.state.youtubeDisp?.playVideo(); + }); }); this.socket.on('youtube_seek', (time: number) => { @@ -173,10 +178,18 @@ export class YoutubeWrap extends React.Component { if (this.state.isFirst) return; + if (this.state.getAction) { + this.setState({ getAction: false }); + return; + } this.socket.emit('youtube_play', target.getCurrentTime()); }, onPause: ({ target, data }: { target: YouTubePlayer; data: number }) => { if (this.state.isFirst) return; + if (this.state.getAction) { + this.setState({ getAction: false }); + return; + } this.socket.emit('youtube_pause', target.getCurrentTime()); }, onReady: (event: { target: YouTubePlayer }) => { From da72a9216eeb74a4ea82daaa77a3cc08d61bcc27 Mon Sep 17 00:00:00 2001 From: amanojs Date: Tue, 13 Apr 2021 08:11:10 +0900 Subject: [PATCH 52/84] =?UTF-8?q?refactor(Wrap):=20=E3=83=AB=E3=83=BC?= =?UTF-8?q?=E3=83=A0=E3=83=9E=E3=82=B9=E3=82=BF=E3=83=BC=E3=81=8B=E3=82=89?= =?UTF-8?q?=E3=83=87=E3=83=BC=E3=82=BF=E3=82=92=E3=82=82=E3=82=89=E3=81=84?= =?UTF-8?q?=E5=90=8C=E6=9C=9F=E5=87=A6=E7=90=86=E3=82=92=E3=81=8A=E3=81=93?= =?UTF-8?q?=E3=81=AA=E3=81=A3=E3=81=A6=E3=81=8B=E3=82=89isFirst=E3=82=92fa?= =?UTF-8?q?lse=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit クライアントの処理性能に依存しにくいコードにしました。 --- src/components/YoutubeWrap/index.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 713abbe..aae3e56 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -90,7 +90,7 @@ export class YoutubeWrap extends React.Component { if (!this.state.youtubeDisp) return; - // console.log('listen!pause!', time); + console.log('listen!pause!', time); this.setState({ getAction: true }, () => { this.state.youtubeDisp?.pauseVideo(); this.state.youtubeDisp?.seekTo(time, true); @@ -99,7 +99,7 @@ export class YoutubeWrap extends React.Component { if (!this.state.youtubeDisp) return; - // console.log('listen!play!', time); + console.log('listen!play!', time); this.setState({ getAction: true }, () => { this.state.youtubeDisp?.playVideo(); }); @@ -143,6 +143,9 @@ export class YoutubeWrap extends React.Component { + this.setState({ isFirst: false }); + }, 500); }); }); }; @@ -228,15 +231,13 @@ export class YoutubeWrap extends React.Component { this.setUpBuffer(target).then(() => { console.log('Buffer完了'); + this.setState({ isFirst: false }); }); }); } } else { this.socket.emit('youtube_sync'); } - window.setTimeout(() => { - this.setState({ isFirst: false }); - }, 2000); } ); } From e889fa2e84faab2c82622d37cb51c923c71191b3 Mon Sep 17 00:00:00 2001 From: amanojs Date: Wed, 14 Apr 2021 22:24:05 +0900 Subject: [PATCH 53/84] =?UTF-8?q?feat(Room):=20=E3=83=AB=E3=83=BC=E3=83=A0?= =?UTF-8?q?=E5=85=A5=E5=87=BA=E5=A4=B1=E6=95=97=E5=87=A6=E7=90=86=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 参加する瞬間にルームが削除された時の入出失敗処理。 --- src/pages/Room/index.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 2626765..7ae7fde 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -48,16 +48,16 @@ const Room: React.FC = (props: PageProps) => { }, [socket]); const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { - if (!socket) return console.log('room :', 'socketがnullだよ', socket); + if (!socket) return sendNotifiction('入出に失敗しました', 'error', { horizontal: 'center', vertical: 'top' }); socket.emit('join_room', { room_id: option.roomId, user_name: userName.value }, (res: boolean) => { console.log('入出', res); if (res) { dispach(roomModule.actions.setRoom({ roomId: option.roomId, userName: userName.value, isOwner: false })); setNameDialog(false); - } /* else { - alert('入出に失敗しました'); + } else { + sendNotifiction('入出に失敗しました', 'error', { horizontal: 'center', vertical: 'top' }); history.push('/'); - } */ + } }); }; @@ -67,11 +67,18 @@ const Room: React.FC = (props: PageProps) => { return value; }; - const sendNotifiction = (message: string, variant: VariantType) => { + const sendNotifiction = ( + message: string, + variant: VariantType, + position: { horizontal: 'left' | 'center' | 'right'; vertical: 'top' | 'bottom' } = { + horizontal: 'left', + vertical: 'bottom' + } + ) => { if (screen.width < 600) return; enqueueSnackbar(message, { variant, - anchorOrigin: { horizontal: 'left', vertical: 'bottom' }, + anchorOrigin: { horizontal: position.horizontal, vertical: position.vertical }, autoHideDuration: 2000 }); }; From 83aa42c4ab7d3c1256d25bc427de11370d5ac5b8 Mon Sep 17 00:00:00 2001 From: amanojs Date: Wed, 14 Apr 2021 22:58:58 +0900 Subject: [PATCH 54/84] =?UTF-8?q?feat(Room):=20=E3=83=AB=E3=83=BC=E3=83=A0?= =?UTF-8?q?=E3=81=8C=E5=AD=98=E5=9C=A8=E3=81=97=E3=81=AA=E3=81=8B=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E5=A0=B4=E5=90=88=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E5=87=A6=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Socketサーバーにcheck_roomをemitする。 --- src/pages/Room/index.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 7ae7fde..214c54a 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -26,9 +26,16 @@ const Room: React.FC = (props: PageProps) => { // パラメータからroom_idを取得 const roomId = getParamValue('room_id'); if (roomId) { - // ルーム入出処理 - setEnterId(roomId); - setNameDialog(true); + rec_socket.emit('check_room', roomId, (res: boolean) => { + if (res) { + // ルーム入出処理 + setEnterId(roomId); + setNameDialog(true); + } else { + sendNotifiction('ルームが存在しませんでした', 'error', { horizontal: 'center', vertical: 'top' }); + history.push('/'); + } + }); } } }); From ec3cd6c966bcbfb2881ec293b0d33dd8e7924913 Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 15 Apr 2021 17:20:45 +0900 Subject: [PATCH 55/84] =?UTF-8?q?feat(Controller):=2015=E7=A7=92=E3=82=B9?= =?UTF-8?q?=E3=82=AD=E3=83=83=E3=83=97=E3=80=8115=E7=A7=92=E5=B7=BB?= =?UTF-8?q?=E3=81=8D=E6=88=BB=E3=81=97=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=AE?= =?UTF-8?q?=E3=83=87=E3=82=B6=E3=82=A4=E3=83=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YoutubeController/Presenter.tsx | 17 ++++++++++++++--- src/components/YoutubeController/index.tsx | 19 ++++++++++++++++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx index aeb80c9..1b8c572 100644 --- a/src/components/YoutubeController/Presenter.tsx +++ b/src/components/YoutubeController/Presenter.tsx @@ -3,7 +3,7 @@ import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; import { withStyles } from '@material-ui/core/styles'; import { Grid, Slider, IconButton, Hidden } from '@material-ui/core'; -import { PlayArrow, Pause } from '@material-ui/icons'; +import { PlayArrow, Pause, FastForward, FastRewind } from '@material-ui/icons'; import { Volume } from '../Volume'; export interface PresenterProps { @@ -11,6 +11,7 @@ export interface PresenterProps { timed: number; duratioin: number; sliderOnChange: (e: any, value: any) => void; + fastTimed: (value: number) => void; valueLabelFormat: (value: number) => string; playOrPause: () => void; isMute: boolean; @@ -103,8 +104,13 @@ export const Presenter: React.FC = (props: PresenterProps) => { - - + + + + props.fastTimed(-15)}> + + + {props.statusIcon === 'play' ? ( @@ -114,6 +120,11 @@ export const Presenter: React.FC = (props: PresenterProps) => { )} + + props.fastTimed(15)}> + + + diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index b6f4992..637e794 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -54,12 +54,28 @@ export const YoutubeController: React.FC = (props: Youtu const sliderOnChange = (changedtime: MouseEvent, value: number | number[]) => { if (props.youtubeDisp) { - props.socket?.emit('youtube_seek', value); + props.socket.emit('youtube_seek', value); props.youtubeDisp.seekTo(Number(value), true); setTimed(Number(value)); } }; + const fastTimed = (value: number) => { + if (props.youtubeDisp) { + let targetTime = timed + value; + if (duration <= targetTime) { + targetTime = duration - 0.2; + setTimed(targetTime); + props.youtubeDisp.pauseVideo(); + window.setTimeout(() => { + props.youtubeDisp?.playVideo(); + }, 200); + } + props.youtubeDisp.seekTo(targetTime, true); + props.socket.emit('youtube_seek', targetTime); + } + }; + const valueLabelFormat = (value: number): string => { if (!value) { return '00:00'; @@ -131,6 +147,7 @@ export const YoutubeController: React.FC = (props: Youtu statusIcon={statusIcon} timed={timed} sliderOnChange={sliderOnChange} + fastTimed={fastTimed} duratioin={duration} valueLabelFormat={valueLabelFormat} playOrPause={playOrPause} From 46790c5222d39537191b8f33b4c1a8790666cca6 Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 15 Apr 2021 17:49:32 +0900 Subject: [PATCH 56/84] =?UTF-8?q?feat(Controller):=2015=E7=A7=92=E3=82=B9?= =?UTF-8?q?=E3=82=AD=E3=83=83=E3=83=97=E3=80=8115=E7=A7=92=E5=B7=BB?= =?UTF-8?q?=E3=81=8D=E6=88=BB=E3=81=97=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=AE?= =?UTF-8?q?=E6=A9=9F=E8=83=BD=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ルームにスキップ同期も同時に実装済みです。 --- src/components/YoutubeController/index.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index 637e794..bcca395 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -1,8 +1,5 @@ import * as React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { State } from '../../store/store'; import { Presenter } from './Presenter'; -import YouTube from 'react-youtube'; import { YouTubePlayer } from 'youtube-player/dist/types'; //import { PresenterProps } from './Presenter'; @@ -52,6 +49,7 @@ export const YoutubeController: React.FC = (props: Youtu statusCheck(props.videoStatus); }, [props.videoStatus]); + /** 再生バー処理 */ const sliderOnChange = (changedtime: MouseEvent, value: number | number[]) => { if (props.youtubeDisp) { props.socket.emit('youtube_seek', value); @@ -60,6 +58,7 @@ export const YoutubeController: React.FC = (props: Youtu } }; + /** 引数の秒数分動画をスキップする */ const fastTimed = (value: number) => { if (props.youtubeDisp) { let targetTime = timed + value; @@ -76,6 +75,7 @@ export const YoutubeController: React.FC = (props: Youtu } }; + /** 少数で渡された秒数を hh:mm:ss のフォーマットで返す */ const valueLabelFormat = (value: number): string => { if (!value) { return '00:00'; @@ -93,6 +93,7 @@ export const YoutubeController: React.FC = (props: Youtu } }; + /** 動画再生状況をセット */ const statusCheck = (status: number) => { // https://developers.google.com/youtube/iframe_api_reference?hl=ja#Adding_event_listener 参照 switch (status) { @@ -117,6 +118,7 @@ export const YoutubeController: React.FC = (props: Youtu } }; + /** 再生、停止ボタンクリック処理 */ const playOrPause = () => { if (statusIcon === 'play') { props.youtubeDisp?.playVideo(); @@ -125,19 +127,16 @@ export const YoutubeController: React.FC = (props: Youtu } }; - /** - * ミュート状態の切り替え - */ + /** ミュート状態の切り替え */ const volumeOnClick = () => { props.isMuted ? props.unMute() : props.mute(); }; + /** ボリューム変更処理 */ const volumeSliderOnChange = (e: React.ChangeEvent, value: number | number[]) => { const num = Number(value); - // ボリュームを変更 props.changeVolume(num); - // ボリュームの値を参照しミュート状態を切り替え num < 1 ? props.mute() : props.isMuted ? props.unMute() : false; }; From dd8ef46c30c9e27a5839a3ef61d956e868d5bf7e Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Thu, 15 Apr 2021 22:28:56 +0900 Subject: [PATCH 57/84] =?UTF-8?q?fix(Volume):=20=E9=9F=B3=E9=87=8F?= =?UTF-8?q?=E3=83=90=E3=83=BC=E3=81=AE=E4=B8=8D=E5=85=B7=E5=90=88=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20=E9=9F=B3=E9=87=8F=E3=83=90=E3=83=BC=E3=81=AE?= =?UTF-8?q?=E3=83=87=E3=82=B6=E3=82=A4=E3=83=B3=E5=BE=AE=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Volume/Presenter.tsx | 4 ++-- src/components/Volume/index.tsx | 2 -- src/components/YoutubeController/index.tsx | 15 +++++++++++++++ src/components/YoutubeWrap/Presenter.tsx | 1 + src/components/YoutubeWrap/index.tsx | 14 ++++++++++++-- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/components/Volume/Presenter.tsx b/src/components/Volume/Presenter.tsx index b7fb930..c5e13c5 100644 --- a/src/components/Volume/Presenter.tsx +++ b/src/components/Volume/Presenter.tsx @@ -12,7 +12,7 @@ interface PresenterProps { export const Presenter: React.FC = (props: PresenterProps) => { return (
- + {props.isMute ? : } = (props: PresenterProps) => { onChange={props.onChange} style={{ width: '100%', - marginLeft: '1px' + marginLeft: '12px' }} >
diff --git a/src/components/Volume/index.tsx b/src/components/Volume/index.tsx index d975031..ee391e3 100644 --- a/src/components/Volume/index.tsx +++ b/src/components/Volume/index.tsx @@ -1,7 +1,5 @@ import * as React from 'react'; import { Presenter } from './Presenter'; -import { Grid, Slider, IconButton, withStyles } from '@material-ui/core'; -import { VolumeOff, VolumeDown, VolumeUp } from '@material-ui/icons'; export interface VolumeProps { isMute: boolean; diff --git a/src/components/YoutubeController/index.tsx b/src/components/YoutubeController/index.tsx index bcca395..e20b1cd 100644 --- a/src/components/YoutubeController/index.tsx +++ b/src/components/YoutubeController/index.tsx @@ -12,6 +12,7 @@ export interface YoutubeControllerProps { mute: () => void; unMute: () => void; changeVolume: (num: number) => void; + setVolumeLog: (num: number) => void; } export const YoutubeController: React.FC = (props: YoutubeControllerProps) => { @@ -135,6 +136,20 @@ export const YoutubeController: React.FC = (props: Youtu /** ボリューム変更処理 */ const volumeSliderOnChange = (e: React.ChangeEvent, value: number | number[]) => { const num = Number(value); + + switch (e.type) { + case 'mousemove': + break; + case 'mousedown': + // クリック時の処理 + if (num > 5) { + props.setVolumeLog(num); + } + break; + default: + // デフォルト処理 + } + // ボリュームを変更 props.changeVolume(num); // ボリュームの値を参照しミュート状態を切り替え diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index c2026fe..5b02d91 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -16,6 +16,7 @@ export interface PresenterProps { volume: number; isMuted: boolean; changeVolume: (num: number) => void; + setVolumeLog: (num: number) => void; mute: () => void; unMute: () => void; }; diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index aae3e56..45ea6e7 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -270,11 +270,19 @@ export class YoutubeWrap extends React.Component { + console.log(value); + if (value > 5 && value <= 100) { + this.setState({ volumeLog: value }); + } + }; + /** ミュート時の処理 */ mute = (): void => { this.setState({ isMuted: true }, () => { this.setState((prev) => { - if (prev.volume > 0) { + if (prev.volume > 5) { return { volumeLog: this.state.volume }; } else { return { ...prev }; @@ -295,6 +303,7 @@ export class YoutubeWrap extends React.Component +
{this.state.volumeLog}
From bd66cf2daf34149e5b21beaf29811c9cb5715b14 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Thu, 15 Apr 2021 22:39:04 +0900 Subject: [PATCH 58/84] =?UTF-8?q?fix(Volume):=20=E3=81=93=E3=81=A3?= =?UTF-8?q?=E3=81=9D=E3=82=8A=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeWrap/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 45ea6e7..d6a986e 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -272,7 +272,6 @@ export class YoutubeWrap extends React.Component { - console.log(value); if (value > 5 && value <= 100) { this.setState({ volumeLog: value }); } @@ -303,7 +302,6 @@ export class YoutubeWrap extends React.Component -
{this.state.volumeLog}
Date: Thu, 15 Apr 2021 22:56:34 +0900 Subject: [PATCH 59/84] =?UTF-8?q?feat(Wrap):=20Chrome=E4=BB=A5=E5=A4=96?= =?UTF-8?q?=E3=81=AE=E3=82=A8=E3=83=BC=E3=82=B8=E3=82=A7=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=AE=E5=A0=B4=E5=90=88=E5=89=8D=E5=9B=9E=E3=81=AE=E3=83=9C?= =?UTF-8?q?=E3=83=AA=E3=83=A5=E3=83=BC=E3=83=A0=E3=82=92=E3=83=87=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=AB=E3=83=88=E3=83=9C=E3=83=AA=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=83=A0=E3=81=AB=E8=A8=AD=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前回のアクセスのボリュームを参考にデフォルトボリュームを設定する。 --- package-lock.json | 11 +++++++++++ package.json | 2 ++ src/components/YoutubeWrap/index.tsx | 18 +++++++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index b494f74..0867478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5459,6 +5459,12 @@ "pretty-format": "^26.0.0" } }, + "@types/js-cookie": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.6.tgz", + "integrity": "sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw==", + "dev": true + }, "@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", @@ -14952,6 +14958,11 @@ } } }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", diff --git a/package.json b/package.json index d226d37..1fb9b3f 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@types/react": "^17.0.3", "@types/react-dom": "^17.0.3", "axios": "^0.21.1", + "js-cookie": "^2.2.1", "notistack": "^1.0.5", "react": "^17.0.2", "react-dom": "^17.0.2", @@ -72,6 +73,7 @@ "@storybook/preset-create-react-app": "^3.1.7", "@storybook/react": "^6.2.1", "@types/axios": "^0.14.0", + "@types/js-cookie": "^2.2.6", "@types/material-ui": "^0.21.8", "@types/react-router-dom": "^5.1.7", "@types/redux-logger": "^3.0.8", diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index aae3e56..d6b4a2e 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -5,6 +5,7 @@ import { YouTubePlayer } from 'youtube-player/dist/types'; import { Presenter } from './Presenter'; import { YouTubeProps } from 'react-youtube'; import { RoomState } from '../../store/modules/roomModule'; +import Cookie from 'js-cookie'; interface YoutubeWrapProps { socket: SocketIOClient.Socket; @@ -64,6 +65,10 @@ export class YoutubeWrap extends React.Component { const listenners = [ @@ -199,7 +204,18 @@ export class YoutubeWrap extends React.Component { From 9976cba7bf959638a3dfd13df5bd26236bab5f29 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Fri, 16 Apr 2021 15:16:29 +0900 Subject: [PATCH 60/84] =?UTF-8?q?fix(AddForm,Room):=20Room=E3=81=AE?= =?UTF-8?q?=E3=83=AC=E3=82=B9=E3=83=9D=E3=83=B3=E3=82=B7=E3=83=96=E3=83=87?= =?UTF-8?q?=E3=82=B6=E3=82=A4=E3=83=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 動画部分とフォーム部分が1画面にできるだけ映るように調整。 --- src/components/AddForm/Presenter.tsx | 4 ++-- src/components/PlayingBoard/main.css | 1 + src/components/YoutubeWrap/Presenter.tsx | 4 ++-- src/components/YoutubeWrap/main.css | 6 +++--- src/pages/Room/Presenter.tsx | 6 +++--- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/components/AddForm/Presenter.tsx b/src/components/AddForm/Presenter.tsx index 27ad953..87cb4d4 100644 --- a/src/components/AddForm/Presenter.tsx +++ b/src/components/AddForm/Presenter.tsx @@ -15,7 +15,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { fullWidth variant="outlined" placeholder="YouTube Movie URL" - style={{ borderRadius: 'none', background: '#f9f9f9' }} + style={{ borderRadius: 'none', background: '#f9f9f9', height: '100%' }} value={props.videoId} onChange={(e) => props.onChange(e.target.value)} > @@ -25,8 +25,8 @@ export const Presenter: React.FC = (props: PresenterProps) => { fullWidth color="secondary" variant="contained" - disableElevation style={{ height: '100%' }} + disableElevation onClick={props.addMovieHandler} > 変更 diff --git a/src/components/PlayingBoard/main.css b/src/components/PlayingBoard/main.css index 0b7f5e5..52742bf 100644 --- a/src/components/PlayingBoard/main.css +++ b/src/components/PlayingBoard/main.css @@ -5,6 +5,7 @@ } svg#icon-audio-disc { + display: none; margin: auto; width: 80%; stroke: #fff; diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index 5b02d91..7f833bc 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -28,7 +28,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { {/* 最大化の場合は↓を変更 */} - + @@ -37,7 +37,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { - + diff --git a/src/components/YoutubeWrap/main.css b/src/components/YoutubeWrap/main.css index 7111f93..4a12e18 100644 --- a/src/components/YoutubeWrap/main.css +++ b/src/components/YoutubeWrap/main.css @@ -1,12 +1,12 @@ @media screen and (max-width: 600px){ .youtube_display{ - height: 250px; + height: 300px; } } @media screen and (min-width: 601px){ .youtube_display{ - height: 500px; + height: 420px; } } @@ -18,6 +18,6 @@ @media screen and (min-width: 1920px){ .youtube_display{ - height: 750px; + height: 700px; } } \ No newline at end of file diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index 16b4f0d..34b70a1 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -22,13 +22,13 @@ export const Presenter: React.FC = (props: PresenterProps) => { {props.room.roomId && props.socket ? ( - + - - + + From 6cc1e3943e7dd2db546f1fd0e6840cac1d2a9c3a Mon Sep 17 00:00:00 2001 From: takashiVue Date: Fri, 16 Apr 2021 16:43:02 +0900 Subject: [PATCH 61/84] =?UTF-8?q?fix(CopyRoomIdButton):=20=E3=82=B9?= =?UTF-8?q?=E3=83=9E=E3=83=9B=E3=81=A7CopyRoomIdButton=E3=82=92=E6=8A=BC?= =?UTF-8?q?=E3=81=97=E3=81=9F=E6=99=82=E3=81=AE=E6=84=8F=E5=9B=B3=E3=81=97?= =?UTF-8?q?=E3=81=AA=E3=81=84=E6=8C=99=E5=8B=95=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit スマホでCopyRoomIdButtonを押すとテキスト入力フォームが開いてしまう挙動を修正。 --- src/components/CopyRoomIdButton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CopyRoomIdButton/index.tsx b/src/components/CopyRoomIdButton/index.tsx index 4cad38a..5bdab8e 100644 --- a/src/components/CopyRoomIdButton/index.tsx +++ b/src/components/CopyRoomIdButton/index.tsx @@ -17,7 +17,7 @@ export const CopyRoomIdButton: React.FC = () => { // クリップボードにコピー document.execCommand('copy'); - + urlInputRef.current?.blur(); // 通知 enqueueSnackbar('招待URLをコピーしました。', { variant: 'info', From b6d508c20052beafd3f5a9a77cc95a8fc7f952a9 Mon Sep 17 00:00:00 2001 From: amanojs Date: Fri, 16 Apr 2021 22:01:23 +0900 Subject: [PATCH 62/84] =?UTF-8?q?fix(Wrap):=20=E3=83=87=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=88=E3=83=83=E3=83=97=E3=82=B5=E3=82=A4=E3=82=BA=E6=99=82?= =?UTF-8?q?=E3=80=81=E7=AB=8B=E5=B9=85=E3=81=8C=E9=95=B7=E3=81=99=E3=81=8E?= =?UTF-8?q?=E3=81=9F=E3=82=B9=E3=82=BF=E3=82=A4=E3=83=AB=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CopyRoomIdButton/Presenter.tsx | 2 +- src/components/YoutubeWrap/main.css | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/CopyRoomIdButton/Presenter.tsx b/src/components/CopyRoomIdButton/Presenter.tsx index e1b4af6..eef89e2 100644 --- a/src/components/CopyRoomIdButton/Presenter.tsx +++ b/src/components/CopyRoomIdButton/Presenter.tsx @@ -20,7 +20,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { {...{ onClick: props.onClick, disableElevation: true, variant: 'contained', color: 'secondary' }} style={{ borderRadius: '1000px' }} > - Copy URL + INVITE ROOM ); diff --git a/src/components/YoutubeWrap/main.css b/src/components/YoutubeWrap/main.css index 4a12e18..b0fc14c 100644 --- a/src/components/YoutubeWrap/main.css +++ b/src/components/YoutubeWrap/main.css @@ -12,12 +12,12 @@ @media screen and (min-width: 1500px){ .youtube_display{ - height: 650px; + height: 500px; } } @media screen and (min-width: 1920px){ .youtube_display{ - height: 700px; + height: 640px; } } \ No newline at end of file From 746be344a3475bb9c8b853c09498369275d0d353 Mon Sep 17 00:00:00 2001 From: amanojs Date: Fri, 16 Apr 2021 23:01:46 +0900 Subject: [PATCH 63/84] =?UTF-8?q?feat(Hoom,Room):=20=E5=89=8D=E5=9B=9E?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E3=81=97=E3=81=9F=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=8D=E3=83=BC=E3=83=A0=E3=82=92=E3=82=A4=E3=83=B3=E3=83=97?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88=E3=81=AB?= =?UTF-8?q?=E3=81=82=E3=82=89=E3=81=8B=E3=81=98=E3=82=81=E5=85=A5=E5=8A=9B?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ルーム作成時や参加時のユーザ名を入力するインプットテキストに、前回使用したユーザ名をデフォルト値として設定するようにしました。 --- src/pages/Home/index.tsx | 7 +++++++ src/pages/Room/index.tsx | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index ba95b23..b58971b 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -5,6 +5,7 @@ import roomModule from '../../store/modules/roomModule'; import { Presenter } from './Presenter'; import { PageProps } from '../../App'; import { InputSub } from '../../components/CreateForm'; +import Cookie from 'js-cookie'; const Home: React.FC = (props: PageProps) => { const [mout, mountkeeper] = React.useState(); @@ -40,12 +41,18 @@ const Home: React.FC = (props: PageProps) => { React.useEffect(() => { props.clearSocket(); + // Cookie存在時ユーザネームセット処理 + const cookieName = Cookie.get('streaming_name'); + if (cookieName) { + setUserName({ value: cookieName, error: false, msg: '' }); + } }, [mountkeeper]); const createRoomHandler = async () => { const socket = await props.getSocket(); console.log(socket); if (socket) { + Cookie.set('streaming_name', userName.value); socket.emit('create_room', userName.value, (res: { result: boolean; room_id: string }) => { console.log(res); if (res.result) { diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 214c54a..6153a1e 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -7,6 +7,7 @@ import { State } from '../../store/store'; import { Presenter } from './Presenter'; import { PageProps } from '../../App'; import { InputSub } from '../../components/CreateForm'; +import Cookie from 'js-cookie'; const Room: React.FC = (props: PageProps) => { const [socket, setSocket] = React.useState(null); @@ -28,6 +29,11 @@ const Room: React.FC = (props: PageProps) => { if (roomId) { rec_socket.emit('check_room', roomId, (res: boolean) => { if (res) { + // Cookie存在時ユーザネームセット処理 + const cookieName = Cookie.get('streaming_name'); + if (cookieName) { + setUserName({ value: cookieName, error: false, msg: '' }); + } // ルーム入出処理 setEnterId(roomId); setNameDialog(true); @@ -125,6 +131,7 @@ const Room: React.FC = (props: PageProps) => { const enterSubmitHandler = () => { if (!socket) return; console.log('enterSubmitHandler', socket, enterId); + Cookie.set('streaming_name', userName.value); joinRoom(socket, { roomId: enterId }); }; From 8921a3bd54ed83e28352b9a398b4bf9ccfc97d68 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 17 Apr 2021 02:22:01 +0900 Subject: [PATCH 64/84] =?UTF-8?q?fix(Room):=20=E9=80=9A=E7=9F=A5=E3=81=AE?= =?UTF-8?q?=E8=AA=A4=E5=AD=97=E3=82=92=E4=BF=AE=E6=AD=A3=E3=81=97=E3=81=BE?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Room/index.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 6153a1e..dc886bf 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -34,7 +34,7 @@ const Room: React.FC = (props: PageProps) => { if (cookieName) { setUserName({ value: cookieName, error: false, msg: '' }); } - // ルーム入出処理 + // ルーム入室処理 setEnterId(roomId); setNameDialog(true); } else { @@ -53,7 +53,7 @@ const Room: React.FC = (props: PageProps) => { React.useEffect(() => { if (!socket) return; socket.on('user_joined', (res: { user: { id: string; name: string } }) => { - sendNotifiction(res.user.name + 'が入出しました', 'success'); + sendNotifiction(res.user.name + 'が入室しました', 'success'); }); socket.on('user_left', (res: { user: { id: string; name: string } }) => { sendNotifiction(res.user.name + 'が退出しました', 'error'); @@ -61,14 +61,13 @@ const Room: React.FC = (props: PageProps) => { }, [socket]); const joinRoom = (socket: SocketIOClient.Socket, option: { roomId: string }) => { - if (!socket) return sendNotifiction('入出に失敗しました', 'error', { horizontal: 'center', vertical: 'top' }); + if (!socket) return sendNotifiction('入室に失敗しました', 'error', { horizontal: 'center', vertical: 'top' }); socket.emit('join_room', { room_id: option.roomId, user_name: userName.value }, (res: boolean) => { - console.log('入出', res); if (res) { dispach(roomModule.actions.setRoom({ roomId: option.roomId, userName: userName.value, isOwner: false })); setNameDialog(false); } else { - sendNotifiction('入出に失敗しました', 'error', { horizontal: 'center', vertical: 'top' }); + sendNotifiction('入室に失敗しました', 'error', { horizontal: 'center', vertical: 'top' }); history.push('/'); } }); From f9c52c425b3b2fab19ebbdd05176a0013b46a72b Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 17 Apr 2021 04:13:41 +0900 Subject: [PATCH 65/84] =?UTF-8?q?feat(Wrap):=20=E3=82=B9=E3=83=9E=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=83=95=E3=82=A9=E3=83=B3=E3=81=8BPC=E3=81=8B?= =?UTF-8?q?=E3=81=AE=E5=88=A4=E5=88=A5=E3=82=92=E3=81=99=E3=82=8B=E3=83=A1?= =?UTF-8?q?=E3=82=BD=E3=83=83=E3=83=89=E3=81=AE=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeWrap/index.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index b8dd2c3..fd959b8 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -182,6 +182,15 @@ export class YoutubeWrap extends React.Component { + if (navigator.userAgent.match(/iPhone|Android.+Mobile/)) { + return true; + } else { + return false; + } + }; + /** react-youtubeコンポーネントの設定 */ player: YouTubeProps = { onPlay: ({ target, data }: { target: YouTubePlayer; data: number }) => { From d94ed19fe7f03d7f96e12b22e1823b0818c53627 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 17 Apr 2021 21:35:14 +0900 Subject: [PATCH 66/84] =?UTF-8?q?feat(Volume):=20(=E3=82=B9=E3=83=9E?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=83=95=E3=82=A9=E3=83=B3)=E3=83=9C?= =?UTF-8?q?=E3=83=AA=E3=83=A5=E3=83=BC=E3=83=A0=E3=83=90=E3=83=BC=E3=82=92?= =?UTF-8?q?=E3=81=AA=E3=81=8F=E3=81=97=E3=81=A6=E3=83=9F=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E3=83=88(=E3=83=9F=E3=83=A5=E3=83=BC=E3=83=88=E8=A7=A3?= =?UTF-8?q?=E9=99=A4)=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=A0=E3=81=91?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit スマートフォンではボリューム調整の概念がなく、ミュートかミュート解除かの2つの状態だけなのでレイアウトを変更しました。 --- src/components/Volume/Presenter.tsx | 31 +++++++++++-------- src/components/Volume/index.tsx | 18 ++++++++++- .../YoutubeController/Presenter.tsx | 24 +++++++------- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/components/Volume/Presenter.tsx b/src/components/Volume/Presenter.tsx index c5e13c5..698f389 100644 --- a/src/components/Volume/Presenter.tsx +++ b/src/components/Volume/Presenter.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { Slider, IconButton, withStyles } from '@material-ui/core'; +import { Slider, IconButton, withStyles, Hidden } from '@material-ui/core'; import { VolumeOff, VolumeUp } from '@material-ui/icons'; interface PresenterProps { @@ -7,6 +7,7 @@ interface PresenterProps { volume: number; onChange: (e: React.ChangeEvent, value: number | number[]) => void; onClick: () => void; + isSmartPhone: () => boolean; } export const Presenter: React.FC = (props: PresenterProps) => { @@ -15,18 +16,22 @@ export const Presenter: React.FC = (props: PresenterProps) => { {props.isMute ? : } - + + {!props.isSmartPhone() && ( + + )} +
); }; diff --git a/src/components/Volume/index.tsx b/src/components/Volume/index.tsx index ee391e3..7555c2e 100644 --- a/src/components/Volume/index.tsx +++ b/src/components/Volume/index.tsx @@ -9,5 +9,21 @@ export interface VolumeProps { } export const Volume: React.FC = (props: VolumeProps) => { - return ; + /** スマートフォンからのアクセスかどうかの判定 */ + const isSmartPhone = (): boolean => { + if (navigator.userAgent.match(/iPhone|Android.+Mobile/)) { + return true; + } else { + return false; + } + }; + return ( + + ); }; diff --git a/src/components/YoutubeController/Presenter.tsx b/src/components/YoutubeController/Presenter.tsx index 1b8c572..7222b82 100644 --- a/src/components/YoutubeController/Presenter.tsx +++ b/src/components/YoutubeController/Presenter.tsx @@ -84,7 +84,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { />
- + @@ -92,19 +92,17 @@ export const Presenter: React.FC = (props: PresenterProps) => { {props.valueLabelFormat(props.duratioin)} - - - - - + + + - + props.fastTimed(-15)}> @@ -127,7 +125,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { - +
From aa6316c2a54c80927421ee488ee2c1a2c810397b Mon Sep 17 00:00:00 2001 From: amanojs Date: Sat, 17 Apr 2021 21:46:19 +0900 Subject: [PATCH 67/84] =?UTF-8?q?fix(Header):=20=E6=8B=9B=E5=BE=85URL?= =?UTF-8?q?=E3=81=A7=E3=83=AB=E3=83=BC=E3=83=A0=E3=81=AB=E5=85=A5=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E3=83=A6=E3=83=BC=E3=82=B6=E3=81=8C=E6=88=BB=E3=82=8B?= =?UTF-8?q?=E3=83=9C=E3=82=BF=E3=83=B3=E3=82=92=E3=82=AF=E3=83=AA=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=81=97=E3=81=A6=E3=82=82=E3=81=AA=E3=81=AB=E3=82=82?= =?UTF-8?q?=E8=B5=B7=E3=81=8D=E3=81=AA=E3=81=84=E7=8F=BE=E8=B1=A1=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit historyインスタンスで使用していたメソッドをbackからpushに変更しました。 --- src/components/Header/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index f4784e8..0c9884f 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -6,7 +6,7 @@ export const Header: React.FC = () => { const history = useHistory(); const backClick = () => { - history.goBack(); + history.push('/'); }; return ; }; From 2a87787608c594ebc5bbc4160bfdd80ea2dfa9a4 Mon Sep 17 00:00:00 2001 From: tanabe1422 <1422hal@gmail.com> Date: Sat, 17 Apr 2021 22:36:36 +0900 Subject: [PATCH 68/84] =?UTF-8?q?fix(YoutubeWrap):=20=E3=82=B9=E3=83=9E?= =?UTF-8?q?=E3=83=9B=E3=81=A7=E3=81=AEonReady=E6=99=82=E3=81=AE=E6=8C=99?= =?UTF-8?q?=E5=8B=95=E3=82=92=E5=A4=89=E6=9B=B4=20*=20=E3=82=B9=E3=83=9E?= =?UTF-8?q?=E3=83=9B=E3=81=AE=E5=A0=B4=E5=90=88=E3=81=AFyoutube=E3=81=AE?= =?UTF-8?q?=E3=82=B3=E3=83=B3=E3=83=88=E3=83=AD=E3=83=BC=E3=83=A9=E3=82=92?= =?UTF-8?q?=E3=81=AF=E3=81=98=E3=82=81=E3=81=8B=E3=82=89=E8=A1=A8=E7=A4=BA?= =?UTF-8?q?=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E3=81=97?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F=E3=80=82=20*=20=E3=82=B9=E3=83=9E?= =?UTF-8?q?=E3=83=9B=E3=81=AE=E5=A0=B4=E5=90=88=E3=81=AF=E3=82=A2=E3=83=B3?= =?UTF-8?q?=E3=83=9F=E3=83=A5=E3=83=BC=E3=83=88=E3=82=92=E3=81=97=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeWrap/index.tsx | 148 ++++++++++++++++----------- 1 file changed, 88 insertions(+), 60 deletions(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index fd959b8..2e2e5f4 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -24,19 +24,6 @@ interface YoutubeWrapState { opts: YouTubeProps['opts']; } -const defaultOpts: YouTubeProps['opts'] = { - width: '100%', - height: '700px', - playerVars: { - controls: 1, - rel: 0, - playsinline: 1, - fs: 0, - disablekb: 1, - modestbranding: 1 - } -}; - export class YoutubeWrap extends React.Component { constructor(props: YoutubeWrapProps) { super(props); @@ -49,7 +36,7 @@ export class YoutubeWrap extends React.Component ({ + width: '100%', + height: '700px', + playerVars: { + controls: isSmartPhone ? 0 : 1, + rel: 0, + playsinline: 1, + fs: 0, + disablekb: 1, + modestbranding: 1 + } + }); + componentDidUpdate(): void { if (this.state.youtubeDisp) { this.setUpSocketListenner(); @@ -214,59 +214,85 @@ export class YoutubeWrap extends React.Component { + this.setUpBuffer(target).then(() => { + console.log('Buffer完了'); + this.setState({ isFirst: false }); + }); + }); } else { - defaultVolume = 20; + this.socket.emit('youtube_sync'); } - } - let prev_flag: number | undefined = 0; - this.setState( - (prev) => { - // コントローラ表示時のみボリュームログに保存 - prev_flag = prev.opts?.playerVars?.controls; - if (prev.opts?.playerVars?.controls === 1) { - return { ...prev, volumeLog: defaultVolume }; + } else { + // それ以外の場合 + let defaultVolume = 0; + + // デフォルトボリュームの取得 + if (agent.match('chrome') && !agent.match('edg')) { + defaultVolume = target.getVolume(); + } else { + const cookieVolume = Cookie.get('streaming_volume'); + if (cookieVolume) { + defaultVolume = Number(cookieVolume); } else { - return { ...prev }; + defaultVolume = 20; } - }, - () => { - // コントローラを非表示にする - this.setState( - (prev) => ({ - opts: { - ...prev.opts, - playerVars: { - ...prev.opts?.playerVars, - controls: 0 + } + + /** コントローラのが表示されているかどうか */ + let prev_flag: number | undefined = 0; + + this.setState( + (prev) => { + // コントローラ表示時のみボリュームログに保存 + prev_flag = prev.opts?.playerVars?.controls; + + if (prev.opts?.playerVars?.controls === 1) { + return { ...prev, volumeLog: defaultVolume }; + } else { + return { ...prev }; + } + }, + () => { + // コントローラを非表示にする + this.setState( + (prev) => ({ + opts: { + ...prev.opts, + playerVars: { + ...prev.opts?.playerVars, + controls: 0 + } } - } - }), - () => { - target.setVolume(0); - if (this.props.room.isOwner) { - if (prev_flag === 0) { - target.cueVideoById('b6-2P8RgT0A'); - this.setState({ videoId: 'b6-2P8RgT0A' }, () => { - this.setUpBuffer(target).then(() => { - console.log('Buffer完了'); - this.setState({ isFirst: false }); + }), + () => { + target.setVolume(0); + if (this.props.room.isOwner) { + if (prev_flag === 0) { + target.cueVideoById('b6-2P8RgT0A'); + this.setState({ videoId: 'b6-2P8RgT0A' }, () => { + this.setUpBuffer(target).then(() => { + console.log('Buffer完了'); + this.setState({ isFirst: false }); + }); }); - }); + } + } else { + this.socket.emit('youtube_sync'); } - } else { - this.socket.emit('youtube_sync'); } - } - ); - } - ); + ); + } + ); + } }, onStateChange: ({ target, data }: { target: YouTubePlayer; data: number }) => { // console.log('onStateChange', data); @@ -283,7 +309,9 @@ export class YoutubeWrap extends React.Component { target.pauseVideo(); target.seekTo(0, true); - this.unMute(); + if (!this.isSmartPhone) { + this.unMute(); + } resolve(true); }, 1000); }); From 85f4f227096bb0e686fbecd7e044fbbd5318c078 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 18 Apr 2021 00:57:59 +0900 Subject: [PATCH 69/84] =?UTF-8?q?fix(Wrap):=20PC=E3=81=A7=E3=82=82?= =?UTF-8?q?=E3=83=87=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E3=81=8C=E3=83=9F?= =?UTF-8?q?=E3=83=A5=E3=83=BC=E3=83=88=E7=8A=B6=E6=85=8B=E3=81=AB=E3=81=AA?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E4=B8=8D=E5=85=B7=E5=90=88?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/YoutubeWrap/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 2e2e5f4..8d03d44 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -309,7 +309,7 @@ export class YoutubeWrap extends React.Component { target.pauseVideo(); target.seekTo(0, true); - if (!this.isSmartPhone) { + if (!this.isSmartPhone()) { this.unMute(); } resolve(true); From cba436106edc10aae31df5d92ab18e72e4264278 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 18 Apr 2021 03:58:14 +0900 Subject: [PATCH 70/84] =?UTF-8?q?fix(Home):=20=E3=82=B9=E3=83=9E=E3=83=9B?= =?UTF-8?q?=E3=82=B5=E3=82=A4=E3=82=BA=E3=81=AEHOME=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E3=83=AC=E3=82=A4=E3=82=A2=E3=82=A6=E3=83=88=E3=82=92=E6=95=B4?= =?UTF-8?q?=E3=81=88=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ロゴのフォントサイズを変更。 --- src/pages/Home/Presenter.tsx | 6 ++++-- src/pages/Home/main.css | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index a7d7633..f8d6aaf 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -23,11 +23,13 @@ export const Presenter: React.FC = (props: PresenterProps) => { return (
- + Streaming!! - + + +
diff --git a/src/pages/Home/main.css b/src/pages/Home/main.css index 9157e58..7e7477b 100644 --- a/src/pages/Home/main.css +++ b/src/pages/Home/main.css @@ -33,6 +33,33 @@ color: #55E6C1; } +@media screen and (max-width: 600px) { + .logo{ + font-size: 50px; + } + .logo > span{ + font-size: 70px; + } +} + +@media screen and (max-width: 450px) { + .logo{ + font-size: 40px; + } + .logo > span{ + font-size: 60px; + } +} + +@media screen and (max-width: 350px) { + .logo{ + font-size: 30px; + } + .logo > span{ + font-size: 40px; + } +} + .wave { position: absolute; bottom: 0; From d180828364ce038250db26470f642253e7861d47 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 18 Apr 2021 06:01:04 +0900 Subject: [PATCH 71/84] =?UTF-8?q?fix(Presenter,css):=20=E5=85=A8=E4=BD=93?= =?UTF-8?q?=E3=81=AE=E3=83=AC=E3=82=A4=E3=82=A2=E3=82=A6=E3=83=88=E8=AA=BF?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.0リリースに向けてレスポンシブを含めたレイアウト調整を行いました。 --- src/components/AddForm/Presenter.tsx | 1 + src/components/CopyRoomIdButton/Presenter.tsx | 26 ++++++-- src/components/CreateForm/Presenter.tsx | 64 ++++++++++--------- src/components/Header/main.css | 2 +- src/components/Loading/index.tsx | 3 +- src/components/Loading/main.css | 10 +++ src/components/YoutubeWrap/Presenter.tsx | 2 +- src/config/route.tsx | 2 +- src/pages/Home/Presenter.tsx | 14 ++-- src/pages/Home/main.css | 20 +++++- src/pages/Room/Presenter.tsx | 6 +- src/pages/Room/main.css | 20 +++++- 12 files changed, 115 insertions(+), 55 deletions(-) create mode 100644 src/components/Loading/main.css diff --git a/src/components/AddForm/Presenter.tsx b/src/components/AddForm/Presenter.tsx index 87cb4d4..aa95535 100644 --- a/src/components/AddForm/Presenter.tsx +++ b/src/components/AddForm/Presenter.tsx @@ -15,6 +15,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { fullWidth variant="outlined" placeholder="YouTube Movie URL" + color="secondary" style={{ borderRadius: 'none', background: '#f9f9f9', height: '100%' }} value={props.videoId} onChange={(e) => props.onChange(e.target.value)} diff --git a/src/components/CopyRoomIdButton/Presenter.tsx b/src/components/CopyRoomIdButton/Presenter.tsx index eef89e2..be1b03e 100644 --- a/src/components/CopyRoomIdButton/Presenter.tsx +++ b/src/components/CopyRoomIdButton/Presenter.tsx @@ -1,5 +1,6 @@ -import { Button } from '@material-ui/core'; import * as React from 'react'; +import { Button, Hidden, IconButton } from '@material-ui/core'; +import { Share } from '@material-ui/icons'; interface PresenterProps { onClick: () => void; @@ -13,15 +14,26 @@ export const Presenter: React.FC = (props: PresenterProps) => { { + /* valueを設定しているとonChangeを設定しないといけないので */ + }} ref={props.inputRef} style={{ opacity: 0, height: 1, width: 1, marginLeft: -1, padding: 0, border: 'none' }} /> - + + + + + + + + ); }; diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index 3714b7e..8c362af 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -24,37 +24,39 @@ export const Presenter: React.FC = (props: PresenterProps) => { return ( - - - - {props.head} - - - {props.inputs.map((input: InputSub) => { - return ( - - - - ); - })} - - + + + + + {props.head} + + + {props.inputs.map((input: InputSub) => { + return ( + + + + ); + })} + + + diff --git a/src/components/Header/main.css b/src/components/Header/main.css index cbf09d2..9caa4ea 100644 --- a/src/components/Header/main.css +++ b/src/components/Header/main.css @@ -9,7 +9,7 @@ z-index: 2; user-select: none; box-sizing: border-box; - padding-left: 2px; + padding-left: 8px; } .header_logo > span{ text-shadow: 2px 2px 3px #eee; diff --git a/src/components/Loading/index.tsx b/src/components/Loading/index.tsx index 1e70016..1eac13a 100644 --- a/src/components/Loading/index.tsx +++ b/src/components/Loading/index.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { Box, CircularProgress } from '@material-ui/core'; +import './main.css'; /** ローディング画面 */ export const Loading: React.FC = () => { @@ -8,7 +9,7 @@ export const Loading: React.FC = () => { display="flex" justifyContent="center" alignItems="center" - height="100vh" + className="loadBox" style={{ background: 'linear-gradient(45deg, #23d5ab,#23a6d5,#ee7752)' }} > diff --git a/src/components/Loading/main.css b/src/components/Loading/main.css new file mode 100644 index 0000000..05f5d8f --- /dev/null +++ b/src/components/Loading/main.css @@ -0,0 +1,10 @@ +.loadBox{ + height: 100vh; +} + +@supports (-webkit-touch-callout: none) { + .loadBox { + /* Safari用のハック */ + height: -webkit-fill-available; + } +} \ No newline at end of file diff --git a/src/components/YoutubeWrap/Presenter.tsx b/src/components/YoutubeWrap/Presenter.tsx index 7f833bc..12557fa 100644 --- a/src/components/YoutubeWrap/Presenter.tsx +++ b/src/components/YoutubeWrap/Presenter.tsx @@ -29,7 +29,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { {/* 最大化の場合は↓を変更 */} - + diff --git a/src/config/route.tsx b/src/config/route.tsx index ae719eb..d945f9b 100644 --- a/src/config/route.tsx +++ b/src/config/route.tsx @@ -30,7 +30,7 @@ const routebases: Array = [ export const Routes: React.FC = (props) => { const makeRoute = (routebase: RouteBase) => { return ( - + {routebase.path !== '/' ?
: false} diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index f8d6aaf..b23ac18 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -23,12 +23,14 @@ export const Presenter: React.FC = (props: PresenterProps) => { return (
- - - Streaming!! - - - + + + + Streaming!! + + + + diff --git a/src/pages/Home/main.css b/src/pages/Home/main.css index 7e7477b..59c27e3 100644 --- a/src/pages/Home/main.css +++ b/src/pages/Home/main.css @@ -1,14 +1,28 @@ @import url('https://fonts.googleapis.com/css2?family=Fredoka+One&display=swap'); -.base { + +body{ position: relative; - width: 100%; height: 100vh; +} + +.base { + position: absolute; + top: 0; + width: 100%; + height: 100%; opacity: 1; animation: gradient 12s ease infinite , fadein 1.4s ease; background: linear-gradient(45deg, #23d5ab,#23a6d5,#ee7752 ); background-size: 190% 190%; } +@supports (-webkit-touch-callout: none) { + body { + /* Safari用のハック */ + height: -webkit-fill-available; + } +} + @keyframes fadein { 0% { opacity: 0; @@ -25,6 +39,7 @@ position: relative; font-size: 60px; color: #fff; + user-select: none; z-index: 2; text-align: center; } @@ -45,6 +60,7 @@ @media screen and (max-width: 450px) { .logo{ font-size: 40px; + letter-spacing: 0px; } .logo > span{ font-size: 60px; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index 34b70a1..88d093f 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -21,13 +21,13 @@ export const Presenter: React.FC = (props: PresenterProps) => { return ( {props.room.roomId && props.socket ? ( - - + + - + diff --git a/src/pages/Room/main.css b/src/pages/Room/main.css index a0b8e75..7f78b91 100644 --- a/src/pages/Room/main.css +++ b/src/pages/Room/main.css @@ -1,9 +1,9 @@ body{ - background-color: #373739; + background-color: #1f1f1f; } .base { - position: relative; + position: absolute; width: 100%; height: 100vh; opacity: 1; @@ -11,6 +11,22 @@ body{ background: linear-gradient(45deg, #23d5ab,#23a6d5,#ee7752 ); background-size: 190% 190%; } + +@supports (-webkit-touch-callout: none) { + body{ + height: -webkit-fill-available; + } + .base { + /* Safari用のハック */ + height: -webkit-fill-available; + } +} + +.RoomContainer{ + padding-bottom: '10px'; + box-sizing: 'border-box'; +} + @keyframes gradient { 0% { background-position: 0% 50%; From b343ffbdda8f540954343d1ee74925d9ec3e1956 Mon Sep 17 00:00:00 2001 From: amanojs Date: Sun, 18 Apr 2021 17:05:16 +0900 Subject: [PATCH 72/84] =?UTF-8?q?feat(public):=20=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=88=E3=83=AB=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=81=BE?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit manifest.json index.html デフォルトのロゴの削除 --- public/favicon.ico | Bin 3870 -> 0 bytes public/index.html | 48 +++++++++++++++++++++---------------------- public/logo192.png | Bin 5347 -> 0 bytes public/logo512.png | Bin 9664 -> 0 bytes public/manifest.json | 4 ++-- 5 files changed, 26 insertions(+), 26 deletions(-) delete mode 100644 public/favicon.ico delete mode 100644 public/logo192.png delete mode 100644 public/logo512.png diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/index.html b/public/index.html index 8773e46..392a3cf 100644 --- a/public/index.html +++ b/public/index.html @@ -1,24 +1,22 @@ - - - - - - - - - - - - - - React App - - - -
- - - + + + \ No newline at end of file diff --git a/public/logo192.png b/public/logo192.png deleted file mode 100644 index fc44b0a3796c0e0a64c3d858ca038bd4570465d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5347 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN diff --git a/public/manifest.json b/public/manifest.json index 080d6c7..60c50d7 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "Streaming!!", + "name": "Streaming!!", "icons": [ { "src": "favicon.ico", From ba38ae49da412587233bf0ab31696fea3c1f84bf Mon Sep 17 00:00:00 2001 From: takashiVue Date: Sun, 18 Apr 2021 23:15:01 +0900 Subject: [PATCH 73/84] =?UTF-8?q?feat(Public,Home):=20=E3=82=A2=E3=83=97?= =?UTF-8?q?=E3=83=AA=E3=82=B1=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=AE?= =?UTF-8?q?=E3=83=AD=E3=82=B4=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=80=81?= =?UTF-8?q?favicon=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Illustratorで作成したロゴをfaviconやホーム画面、ヘッダーに追加しました。 --- public/favicon.ico | Bin 0 -> 2845 bytes src/assets/Streaming-logo.png | Bin 0 -> 2845 bytes src/components/Header/Presenter.tsx | 4 +++- src/pages/Home/Presenter.tsx | 14 +++++++++++--- src/pages/Home/main.css | 2 +- 5 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 public/favicon.ico create mode 100644 src/assets/Streaming-logo.png diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9bf01011097342802a70df8c4caab37325867923 GIT binary patch literal 2845 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 = (props: PresenterProps) => { -

+

+ Streaming!!

diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index b23ac18..b29aeb5 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { Grid } from '@material-ui/core'; import { CreateForm, InputSub } from '../../components/CreateForm'; import { makeStyles } from '@material-ui/core/styles'; +import Logo from '../../assets/Streaming-logo.png'; import './main.css'; interface PresenterProps { @@ -23,10 +24,17 @@ export const Presenter: React.FC = (props: PresenterProps) => { return (
- - + + - Streaming!! + + + Logo + + + Streaming!! + + diff --git a/src/pages/Home/main.css b/src/pages/Home/main.css index 59c27e3..0844790 100644 --- a/src/pages/Home/main.css +++ b/src/pages/Home/main.css @@ -43,7 +43,7 @@ body{ z-index: 2; text-align: center; } -.logo > span{ +.logo span{ font-size: 80px; color: #55E6C1; } From 95201bbde31f4e5299ade4efd9ee2161ee7b6a84 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 19 Apr 2021 04:24:26 +0900 Subject: [PATCH 74/84] =?UTF-8?q?fix(Header,Home):=20=E3=82=B9=E3=83=9E?= =?UTF-8?q?=E3=83=9B=E3=81=AE=E3=83=AC=E3=82=A4=E3=82=A2=E3=82=A6=E3=83=88?= =?UTF-8?q?=E3=82=92=E8=80=83=E3=81=88=E3=80=81=E3=83=AD=E3=82=B4=E3=81=AE?= =?UTF-8?q?=E9=AB=98=E3=81=95=E3=82=92=E6=98=8E=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/Streaming-logo2.png | Bin 0 -> 2848 bytes src/components/Header/Presenter.tsx | 6 +++--- src/components/Header/main.css | 2 +- src/pages/Home/Presenter.tsx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 src/assets/Streaming-logo2.png diff --git a/src/assets/Streaming-logo2.png b/src/assets/Streaming-logo2.png new file mode 100644 index 0000000000000000000000000000000000000000..03a3be0d4372fd0bcedd5b6e76b903f2b1cb7d44 GIT binary patch literal 2848 zcmd5;c~lc=5|0iM2%><52ciS42nxY?Ookl|S2kRN5rl*g21tNtUsT``E0Q)Wc8NL=+0s* zLN-wSCHT)O^THx(IN^PUxXIBvH|9?Fn;l9@-@4lJeKkvBj8PLbn}Ytb>c6s>uZYl?w>W_b9l6g5AD9kdfzUNhg{GxP+^QA z3JjjPrj9BT9N95gMD~*yi36l2PK_j()UsQKePMs_ ziy8t&_sKbq%tG80h5Q0XByY8^K=s%k?Tb6cpG(RLN~Gl;x*~0*bi9%GbbQ)OKTT_+ z6D+jEUOg7xlg8OGxY-=U7_t*=1eR7}OcXU8*2$v^lBg^=jz>jQ z$3}mM@l|MiA5e}6&#y#gC0IpeRc2bSDOu275{pT1=K`0@ckXh zm*k&a13U+H*Elr_2I!-KT{-K7CSCyotQ&*d60LB^nMj9yczmXcCYsj&Xj7rr$(T98 zDN+z|-bR&nL>p^nCe$RN>JHG(*^l23O>z|&P{vJev`*JxByx^Nn^l>JS~T}3cQl@S>`+xwKcO?g zBf5CNlfcJm%EQ1yCl85r6Yl&f&*L+BwCmEf2ZbN%765${@%iYYy>%7*1Yusc8oVPa z2Li2TU;}<)3qz03aq$${ZCM6#L3SjGrZvL!gldjHpW}HNY3{dYa5pmcG&^VpEMs@= z?vGrxY{@-6Ch4sFPV9V%Yqug}n=T+qhJI5%B(~Q1Sg9YfthHXN3y>5;wP?C0qullP zQWal|DP9W^lSViNRgX8tSAEtv<#4rHr!|oBKzZHAAJZwb+Yj3^K=B1%A-bXc(_j0h z)E*ClUvg%dM%p;025Yul{Nbd_P<{g^9h1dDEJTko60I4KBJSs5fl=AOGt<-iy~705 zP{~|m(}1zKC_3rhSlK&eYqhA|I3(U!3!*5X%B^A|%V8p#1Up~=t98&}iK02bEW}q(!Q^!}Npp{EPN{mI0V4~hddqeFV6$8# z*3++Lb&$0eC6KfN8s#|MOu72l%+w+`>JJRk)5HqjW|jCRh!bgoN$~uWabs(*5{_U<_>Dr(%CUS zDQ97t&y`Js9B<2C-_+B7(HTtw)`vPzd57GIPp-TN@<)Z$tA=(>KT8R+27zEMWFGj~ zH8TIVN2YqpGa%(yk|^WZt!MzTMfXvG{1jW^f5Hf-I<}(tpd26HMObLlX6ntCMppgy zB?ocoe8}qP-ffL0PQ@oj=*j*PvT~HUsjPyn0Qi+{T{iQ!|3$IA&4fnCJKWGwol^jH zdtENGt8}>ys4DZ#svg-HIc}F7UBJ%5<}P{Dw(h7H2@PGs9Cx_*Y^pyiXo+@4qXs&% zGRWHhuUMRFPQTNlHA>4s9GT{N@jzGV7ubK2} zV^A)_?K_WBisd~MFG~8bTqF)&$daTLr`N735b8i*IrnUFAsOw83GRgV9ljcmFUCgY2jvy8 z&gK*Ww~x%bzQYT4lR_qakA-ce0$D*$Qof#|oNg9Qm*{v-%1_or%2V}1&# z6k3B0s~W3uNTC&huHI58{9|uC5V@g$c?r6sbjfIB+Nbpv=y^M;vQqoyj#Gpw9E6mI zBzyb>hWHSe&gmj~XVp#OdG#40W0kvD3gm{{)0LDStOzQX0T0zlw>`*5i=p5a%fX|lEOOMl~(F7~8o*JGGMmN-^ z^@whdKOsfDK#xQd5;7}PyCWkXlpn7j)=wS(guiQR3U%OD=Um4`W&4q&4l~n-x=T^H z#(X;3JT{bO&}ag^swTWAQkQ`hsXB?Ejth0FEUz-@wuDmm&U8NdA}j1rwv{{R_=!kl z10aEbdg(kf?nau;k`$o9Qh=^Vr7L%iPcqK+nnanisIIL$eetr2*IwH0%QIUNAmLgM zhRXl`ZCk6|^JCx}Mzg$L0+kV%ihnYRe-D{=Sk_fV*v;r*clr*UEzFnX!`A107Yjnc z&&?}u(7g7niR@t+%TjEKv=|X*Ir{6!Hxcllvb= CQuT=d literal 0 HcmV?d00001 diff --git a/src/components/Header/Presenter.tsx b/src/components/Header/Presenter.tsx index 1299f5e..7881899 100644 --- a/src/components/Header/Presenter.tsx +++ b/src/components/Header/Presenter.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { AppBar, Toolbar, IconButton, Typography, Button } from '@material-ui/core'; import { CopyRoomIdButton } from '../CopyRoomIdButton'; import { ArrowLeftRounded } from '@material-ui/icons'; -import Logo from '../../assets/Streaming-logo.png'; +import Logo2 from '../../assets/Streaming-logo2.png'; import './main.css'; interface PresenterProps { @@ -17,8 +17,8 @@ export const Presenter: React.FC = (props: PresenterProps) => { -

- +

+ Streaming!!

diff --git a/src/components/Header/main.css b/src/components/Header/main.css index 9caa4ea..cb540b0 100644 --- a/src/components/Header/main.css +++ b/src/components/Header/main.css @@ -12,5 +12,5 @@ padding-left: 8px; } .header_logo > span{ - text-shadow: 2px 2px 3px #eee; + /* text-shadow: 2px 2px 3px #eee; */ } \ No newline at end of file diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index b29aeb5..c68760a 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -29,7 +29,7 @@ export const Presenter: React.FC = (props: PresenterProps) => { - Logo + Logo Streaming!! From 929c2db914f55bded11df061be2f5cd11805ae8b Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 19 Apr 2021 05:02:02 +0900 Subject: [PATCH 75/84] =?UTF-8?q?feat(CreateForm,AddForm):=20Submit?= =?UTF-8?q?=E3=81=A7=E3=82=A4=E3=83=99=E3=83=B3=E3=83=88=E3=81=8C=E7=99=BA?= =?UTF-8?q?=E7=81=AB=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CreateFormコンポーネントとAddFormコンポーネントのイベントをEnterキーで発火するようにしました。 --- src/components/AddForm/Presenter.tsx | 52 +++++++++--------- src/components/AddForm/index.tsx | 3 +- src/components/CreateForm/Presenter.tsx | 73 +++++++++++++------------ src/components/CreateForm/index.tsx | 3 +- 4 files changed, 69 insertions(+), 62 deletions(-) diff --git a/src/components/AddForm/Presenter.tsx b/src/components/AddForm/Presenter.tsx index aa95535..7a9aed4 100644 --- a/src/components/AddForm/Presenter.tsx +++ b/src/components/AddForm/Presenter.tsx @@ -4,35 +4,37 @@ import { Button, Grid, TextField } from '@material-ui/core'; interface PresenterProps { videoId: string; onChange: (value: string) => void; - addMovieHandler: () => void; + addMovieHandler: (e: React.FormEvent) => void; } export const Presenter: React.FC = (props: PresenterProps) => { return ( - - - props.onChange(e.target.value)} - > +
+ + + props.onChange(e.target.value)} + > + + + + - - - - +
); }; diff --git a/src/components/AddForm/index.tsx b/src/components/AddForm/index.tsx index 7c1f1de..bced877 100644 --- a/src/components/AddForm/index.tsx +++ b/src/components/AddForm/index.tsx @@ -13,7 +13,8 @@ export const AddForm: React.FC = (props: AddFormProps) => { setVideoId(value); }; - const addMovieHandler = () => { + const addMovieHandler = (e: React.FormEvent) => { + e.preventDefault(); socket.emit('youtube_add_movie', videoId); setVideoId(''); }; diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index 8c362af..5c6c4dd 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -10,7 +10,7 @@ export interface PresenterProps { head: string; btn: string; inputs: InputSub[]; - submitEvent: () => any; + submitEvent: (e: React.FormEvent) => void; } export const Presenter: React.FC = (props: PresenterProps) => { @@ -23,43 +23,46 @@ export const Presenter: React.FC = (props: PresenterProps) => { const classes = useStyles(); return ( - - - - - - {props.head} - - - {props.inputs.map((input: InputSub) => { - return ( - - - - ); - })} - - +
+ + + + + + {props.head} + + + + {props.inputs.map((input: InputSub) => { + return ( + + + + ); + })} + + + - +
); }; diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index f3211fe..240c5c2 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -35,7 +35,8 @@ export const CreateForm: React.FC = (props: CreateFormProps) => return errorFlag; }; - const submitEvent = async () => { + const submitEvent = async (e: React.FormEvent) => { + e.preventDefault(); if (validateAll()) { return console.log('未入力の内容があります'); } From 2e5e82056f8af7140204dc39d72b1e1b6750aff5 Mon Sep 17 00:00:00 2001 From: takashiVue Date: Mon, 19 Apr 2021 05:44:28 +0900 Subject: [PATCH 76/84] =?UTF-8?q?feat(CreateForm,Home,Room):=20=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=BC=E3=83=A0=E3=81=AB=E3=83=AD=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=83=97=E3=83=AD=E3=83=91=E3=83=86=E3=82=A3=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ルーム作成やルーム入室などのサブミット処理中にボタンを処理をロックし、ロードアニメーションを表示するようにしました。 --- src/components/CreateForm/CreateForm.stories.tsx | 1 + src/components/CreateForm/Presenter.tsx | 14 +++++++++++--- src/components/CreateForm/index.tsx | 15 ++++++++++++--- src/pages/Home/Presenter.tsx | 1 + src/pages/Home/index.tsx | 7 ++++++- src/pages/Room/Presenter.tsx | 1 + src/pages/Room/index.tsx | 5 ++++- 7 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/components/CreateForm/CreateForm.stories.tsx b/src/components/CreateForm/CreateForm.stories.tsx index b14c736..dcd0dc2 100644 --- a/src/components/CreateForm/CreateForm.stories.tsx +++ b/src/components/CreateForm/CreateForm.stories.tsx @@ -19,6 +19,7 @@ const DefaultProps: CreateFormProps = { width: '400px', head: 'ヘッドタイトル', btn: '送信', + load: false, inputs: [ { label: 'ユーザネーム', diff --git a/src/components/CreateForm/Presenter.tsx b/src/components/CreateForm/Presenter.tsx index 5c6c4dd..51e1a82 100644 --- a/src/components/CreateForm/Presenter.tsx +++ b/src/components/CreateForm/Presenter.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Grid, Card, Button, Box } from '@material-ui/core'; +import { Grid, Card, Button, Box, CircularProgress } from '@material-ui/core'; import { InputText } from '../InputText'; import { InputSub } from './index'; import './main.css'; @@ -10,6 +10,7 @@ export interface PresenterProps { head: string; btn: string; inputs: InputSub[]; + load: boolean; submitEvent: (e: React.FormEvent) => void; } @@ -55,8 +56,15 @@ export const Presenter: React.FC = (props: PresenterProps) => { ); })} -
diff --git a/src/components/CreateForm/index.tsx b/src/components/CreateForm/index.tsx index 240c5c2..3997b7c 100644 --- a/src/components/CreateForm/index.tsx +++ b/src/components/CreateForm/index.tsx @@ -13,6 +13,8 @@ export interface CreateFormProps { head: string; /** フォームのサブミットボタンのタイトル */ btn: string; + /** ロード中か */ + load: boolean; /** InputText型にバリデーション処理を加えたインプットの配列 */ inputs: InputSub[]; /** サブミット処理(オールバリデーション処理の後に実行されます) */ @@ -38,13 +40,20 @@ export const CreateForm: React.FC = (props: CreateFormProps) => const submitEvent = async (e: React.FormEvent) => { e.preventDefault(); if (validateAll()) { - return console.log('未入力の内容があります'); + return; } - props.onSubmit(); + await props.onSubmit(); }; return ( - + ); }; CreateForm.defaultProps = { diff --git a/src/pages/Home/Presenter.tsx b/src/pages/Home/Presenter.tsx index c68760a..99bfbeb 100644 --- a/src/pages/Home/Presenter.tsx +++ b/src/pages/Home/Presenter.tsx @@ -8,6 +8,7 @@ import './main.css'; interface PresenterProps { createForm: { inputs: InputSub[]; + load: boolean; onSubmit: () => any; }; } diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index b58971b..85ce073 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -10,6 +10,7 @@ import Cookie from 'js-cookie'; const Home: React.FC = (props: PageProps) => { const [mout, mountkeeper] = React.useState(); const [userName, setUserName] = React.useState({ value: '', error: false, msg: '' }); + const [load, setLoad] = React.useState(false); const dispach = useDispatch(); const history = useHistory(); @@ -49,6 +50,7 @@ const Home: React.FC = (props: PageProps) => { }, [mountkeeper]); const createRoomHandler = async () => { + setLoad(true); const socket = await props.getSocket(); console.log(socket); if (socket) { @@ -59,10 +61,13 @@ const Home: React.FC = (props: PageProps) => { dispach(roomModule.actions.setRoom({ roomId: res.room_id, userName: userName.value, isOwner: true })); history.push('/room' + '?room_id=' + res.room_id); } + setLoad(false); }); + } else { + setLoad(false); } }; - return ; + return ; }; export default Home; diff --git a/src/pages/Room/Presenter.tsx b/src/pages/Room/Presenter.tsx index 88d093f..47f3696 100644 --- a/src/pages/Room/Presenter.tsx +++ b/src/pages/Room/Presenter.tsx @@ -13,6 +13,7 @@ interface PresenterProps { nameDialog: boolean; createForm: { inputs: InputSub[]; + load: boolean; onSubmit: () => void; }; } diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index dc886bf..e07199e 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -13,6 +13,7 @@ const Room: React.FC = (props: PageProps) => { const [socket, setSocket] = React.useState(null); const [nameDialog, setNameDialog] = React.useState(false); const [enterId, setEnterId] = React.useState(''); + const [load, setLoad] = React.useState(false); const room = useSelector((state: State) => state.room); const history = useHistory(); const dispach = useDispatch(); @@ -70,6 +71,7 @@ const Room: React.FC = (props: PageProps) => { sendNotifiction('入室に失敗しました', 'error', { horizontal: 'center', vertical: 'top' }); history.push('/'); } + setLoad(false); }); }; @@ -129,6 +131,7 @@ const Room: React.FC = (props: PageProps) => { const enterSubmitHandler = () => { if (!socket) return; + setLoad(true); console.log('enterSubmitHandler', socket, enterId); Cookie.set('streaming_name', userName.value); joinRoom(socket, { roomId: enterId }); @@ -139,7 +142,7 @@ const Room: React.FC = (props: PageProps) => { socket={socket} room={room} nameDialog={nameDialog} - createForm={{ inputs, onSubmit: enterSubmitHandler }} + createForm={{ inputs, load, onSubmit: enterSubmitHandler }} /> ); }; From fbb71709cac1f30912138d72427cf773ea5835ba Mon Sep 17 00:00:00 2001 From: amanojs Date: Tue, 20 Apr 2021 20:46:04 +0900 Subject: [PATCH 77/84] =?UTF-8?q?refactor(.env.base,html-base):=20?= =?UTF-8?q?=E3=83=93=E3=83=AB=E3=83=89=E8=A8=AD=E5=AE=9A=E3=82=92=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit インラインスクリプトをなくし、ビルドベースのHTMLをミニファイしないようにしました。 --- .env.base | 3 ++- public/index.html | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.env.base b/.env.base index 908abdb..84c82bf 100644 --- a/.env.base +++ b/.env.base @@ -1,2 +1,3 @@ REACT_APP_API_URL= -REACT_APP_YOUTUBE_KEY= \ No newline at end of file +REACT_APP_YOUTUBE_KEY= +INLINE_RUNTIME_CHUNK=false \ No newline at end of file diff --git a/public/index.html b/public/index.html index 392a3cf..c9e77e2 100644 --- a/public/index.html +++ b/public/index.html @@ -1,5 +1,6 @@ + @@ -42,5 +43,6 @@ To create a production bundle, use `npm run build` or `yarn build`. --> + \ No newline at end of file From 78ce384c0a36f630b19eb85d5e587979a9f8d02a Mon Sep 17 00:00:00 2001 From: takashiVue Date: Wed, 21 Apr 2021 17:10:14 +0900 Subject: [PATCH 78/84] =?UTF-8?q?fix(Room):=20=E3=83=AB=E3=83=BC=E3=83=A0I?= =?UTF-8?q?D=E3=81=8C=E5=8F=96=E5=BE=97=E3=81=A7=E3=81=8D=E3=81=AA?= =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=9F=E9=9A=9B=E3=81=AB=E3=80=81=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E9=80=9A=E7=9F=A5=E3=82=92=E9=80=81=E4=BF=A1?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Room/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index e07199e..88557b5 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -43,6 +43,9 @@ const Room: React.FC = (props: PageProps) => { history.push('/'); } }); + } else { + sendNotifiction('ルームが存在しませんでした', 'error', { horizontal: 'center', vertical: 'top' }); + history.push('/'); } } }); From 6435b38939891d6cc137d05a6339f62210cf4e63 Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 22 Apr 2021 19:28:26 +0900 Subject: [PATCH 79/84] =?UTF-8?q?docs(public):=20PWA=E7=94=A8=E3=81=AE?= =?UTF-8?q?=E3=82=A2=E3=83=97=E3=83=AA=E3=82=B1=E3=83=BC=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=82=A2=E3=82=A4=E3=82=B3=E3=83=B3=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/logo192.png | Bin 0 -> 5198 bytes public/logo512.png | Bin 0 -> 22013 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/logo192.png create mode 100644 public/logo512.png diff --git a/public/logo192.png b/public/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..94629a58fcea6a2d9972364d376775ca7f253df1 GIT binary patch literal 5198 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 literal 0 HcmV?d00001 From 57b8a7ebca926e1424b12563df7e7b295bb3915c Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 22 Apr 2021 19:53:07 +0900 Subject: [PATCH 80/84] =?UTF-8?q?style(*):=20console.log=E3=82=92=E3=82=B3?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=82=A2=E3=82=A6=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 6 +++--- src/components/CopyRoomIdButton/index.tsx | 1 - src/components/CreateForm/CreateForm.stories.tsx | 16 ++++++++-------- src/components/PlayingBoard/index.tsx | 5 ++--- src/components/YoutubeWrap/index.tsx | 12 ++++++------ src/pages/Home/index.tsx | 4 ++-- src/pages/Room/index.tsx | 2 +- src/store/store.ts | 2 +- 8 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b9f0e53..2112ca4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,13 +16,13 @@ const App: React.FC = () => { // websocketに接続し、socket clientを返却 const getSocket = (): Promise => { - console.log('getSocket'); + // console.log('getSocket'); return new Promise((resolve) => { if (!socket) { // 接続開始 const client = io.connect(process.env.REACT_APP_API_URL as string); client.on('connect', () => { - console.log('connected'); + // console.log('connected'); // 別ページからも参照できるようにstateにセット setSocket(client, function () { // 接続が接続が成功した際にsocket clientを返却 @@ -39,7 +39,7 @@ const App: React.FC = () => { const clearSocket = (): void => { socket?.disconnect(); setSocket(null, () => { - console.log('clear socket'); + // console.log('clear socket'); }); }; diff --git a/src/components/CopyRoomIdButton/index.tsx b/src/components/CopyRoomIdButton/index.tsx index 5bdab8e..ce74b05 100644 --- a/src/components/CopyRoomIdButton/index.tsx +++ b/src/components/CopyRoomIdButton/index.tsx @@ -12,7 +12,6 @@ export const CopyRoomIdButton: React.FC = () => { const onClick = (): void => { // 選択 - console.log(!!urlInputRef.current); urlInputRef.current?.select(); // クリップボードにコピー diff --git a/src/components/CreateForm/CreateForm.stories.tsx b/src/components/CreateForm/CreateForm.stories.tsx index dcd0dc2..1c91bb9 100644 --- a/src/components/CreateForm/CreateForm.stories.tsx +++ b/src/components/CreateForm/CreateForm.stories.tsx @@ -28,16 +28,16 @@ const DefaultProps: CreateFormProps = { error: false, msg: '', onChange: function (val) { - console.log('onChange'); + // console.log('onChange'); }, validate: (val) => { - console.log('validate'); + // console.log('validate'); return { error: true, msg: 'エラーメッセージ' }; } } ], onSubmit: () => { - console.log('onSubmit'); + // console.log('onSubmit'); } }; @@ -54,10 +54,10 @@ ErrorProps.inputs = [ error: true, msg: '入力値が誤っています', onChange: function (val) { - console.log('onChange'); + // console.log('onChange'); }, validate: (val) => { - console.log('validate'); + // console.log('validate'); return { error: true, msg: 'エラーメッセージ' }; } } @@ -75,14 +75,14 @@ MultiInputProps.inputs = [ error: false, msg: '', onChange: function (val) { - console.log('onChange'); + // console.log('onChange'); }, validate: (val) => { - console.log('validate'); + // console.log('validate'); return { error: true, msg: 'エラーメッセージ' }; } } ]; -console.log(MultiInputProps); +// console.log(MultiInputProps); MultiInput.args = MultiInputProps; diff --git a/src/components/PlayingBoard/index.tsx b/src/components/PlayingBoard/index.tsx index bf96c91..a98061d 100644 --- a/src/components/PlayingBoard/index.tsx +++ b/src/components/PlayingBoard/index.tsx @@ -15,8 +15,7 @@ export const PlayingBoard: React.FC = (props: PlayingBoardPro getTitle(); }, [props.videoId]); const getTitle = () => { - console.log('youtube videoId', props.videoId); - axios + /* axios .get(`https://www.googleapis.com/youtube/v3/search?key=${APIKEY}&part=id,snippet`, { params: { q: props.videoId } }) @@ -30,7 +29,7 @@ export const PlayingBoard: React.FC = (props: PlayingBoardPro setTitle('動画タイトルを取得できませんでした'); } } - }); + }); */ }; return ; }; diff --git a/src/components/YoutubeWrap/index.tsx b/src/components/YoutubeWrap/index.tsx index 8d03d44..e94e38e 100644 --- a/src/components/YoutubeWrap/index.tsx +++ b/src/components/YoutubeWrap/index.tsx @@ -85,7 +85,7 @@ export class YoutubeWrap extends React.Component { if (!this.state.youtubeDisp) return; - console.log('movieId', movie_id); + // console.log('movieId', movie_id); this.setState({ videoId: movie_id }); this.state.youtubeDisp.cueVideoById(movie_id); this.setUpBuffer(this.state.youtubeDisp).then(() => { @@ -95,7 +95,7 @@ export class YoutubeWrap extends React.Component { if (!this.state.youtubeDisp) return; - console.log('listen!pause!', time); + // console.log('listen!pause!', time); this.setState({ getAction: true }, () => { this.state.youtubeDisp?.pauseVideo(); this.state.youtubeDisp?.seekTo(time, true); @@ -104,7 +104,7 @@ export class YoutubeWrap extends React.Component { if (!this.state.youtubeDisp) return; - console.log('listen!play!', time); + // console.log('listen!play!', time); this.setState({ getAction: true }, () => { this.state.youtubeDisp?.playVideo(); }); @@ -136,7 +136,7 @@ export class YoutubeWrap extends React.Component { if (!this.state.youtubeDisp) return; - console.log('newplayingData', res); + // console.log('newplayingData', res); if (res.movie_id) { this.state.youtubeDisp.cueVideoById(res.movie_id); this.setState({ videoId: res.movie_id }); @@ -224,7 +224,7 @@ export class YoutubeWrap extends React.Component { this.setUpBuffer(target).then(() => { - console.log('Buffer完了'); + // console.log('Buffer完了'); this.setState({ isFirst: false }); }); }); @@ -280,7 +280,7 @@ export class YoutubeWrap extends React.Component { this.setUpBuffer(target).then(() => { - console.log('Buffer完了'); + // console.log('Buffer完了'); this.setState({ isFirst: false }); }); }); diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 85ce073..ca74a6e 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -52,11 +52,11 @@ const Home: React.FC = (props: PageProps) => { const createRoomHandler = async () => { setLoad(true); const socket = await props.getSocket(); - console.log(socket); + // console.log(socket); if (socket) { Cookie.set('streaming_name', userName.value); socket.emit('create_room', userName.value, (res: { result: boolean; room_id: string }) => { - console.log(res); + // console.log(res); if (res.result) { dispach(roomModule.actions.setRoom({ roomId: res.room_id, userName: userName.value, isOwner: true })); history.push('/room' + '?room_id=' + res.room_id); diff --git a/src/pages/Room/index.tsx b/src/pages/Room/index.tsx index 88557b5..73a9cea 100644 --- a/src/pages/Room/index.tsx +++ b/src/pages/Room/index.tsx @@ -135,7 +135,7 @@ const Room: React.FC = (props: PageProps) => { const enterSubmitHandler = () => { if (!socket) return; setLoad(true); - console.log('enterSubmitHandler', socket, enterId); + // console.log('enterSubmitHandler', socket, enterId); Cookie.set('streaming_name', userName.value); joinRoom(socket, { roomId: enterId }); }; diff --git a/src/store/store.ts b/src/store/store.ts index 5993f68..14208ef 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -12,7 +12,7 @@ const rootReducer = combineReducers({ }); export const setUpStore = () => { - const middlewares = [...getDefaultMiddleware(), logger]; + const middlewares = [...getDefaultMiddleware() /* , logger */]; const store = configureStore({ reducer: rootReducer, middleware: middlewares From 1f21066a8b20d1fb671ff1946c76e721ae5d6192 Mon Sep 17 00:00:00 2001 From: amanojs Date: Thu, 22 Apr 2021 20:35:14 +0900 Subject: [PATCH 81/84] =?UTF-8?q?perf(*):=20=E3=82=B3=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=82=B9=E3=83=97=E3=83=AA=E3=83=83=E3=83=86=E3=82=A3=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=81=AE=E8=A6=8B=E7=9B=B4=E3=81=97=E3=80=81=E3=83=96?= =?UTF-8?q?=E3=83=AD=E3=83=83=E3=82=AD=E3=83=B3=E3=82=B0=E3=82=92=E8=A7=A3?= =?UTF-8?q?=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit routeコンポーネントのコードスプリッティングを見直し、変更しました。不要なフォントを削除しました。 --- public/index.html | 7 +++-- src/components/Header/index.tsx | 2 ++ src/components/Header/main.css | 2 -- src/components/InputText/index.tsx | 12 ++++++++- src/config/route.tsx | 43 ++++++++++++------------------ src/config/theme.ts | 16 +---------- src/index.css | 9 ------- src/pages/Home/main.css | 2 -- src/stories/button.css | 2 +- src/stories/header.css | 2 +- src/stories/page.css | 2 +- 11 files changed, 37 insertions(+), 62 deletions(-) diff --git a/public/index.html b/public/index.html index c9e77e2..4bccec3 100644 --- a/public/index.html +++ b/public/index.html @@ -7,16 +7,15 @@ - + - - - + +