Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Twitter/ファンアート表示機能仮対応 #742

Merged
merged 2 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,15 @@
"file": "donations.html",
"width": 6,
"headerColor": "#00BEBE",
"workspace": "3-donations"
"workspace": "3-reactions"
},
{
"name": "twitter",
"title": "Twitter投稿/ファンアート",
"file": "twitter.html",
"width": 6,
"headerColor": "#00BEBE",
"workspace": "3-reactions"
},
{
"name": "video-control",
Expand Down
16 changes: 16 additions & 0 deletions schemas/tweets-temp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://json-schema.org/draft-04/schema",

"type": "array",
"items": {
"type": "object",
"properties": {
"text": {"type": "string"},
"name": {"type": "string"},
"image": {"type": "string"}
},
"additionalProperties": false,
"required": ["text", "name"]
},
"default": []
}
63 changes: 63 additions & 0 deletions src/browser/dashboard/components/twitter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import styled from "styled-components";
import List from "@mui/material/List";
import {TweetAdd} from "./tweet-add";
import {TweetItem} from "./tweet-item";
import {useReplicant} from "../../../use-replicant";

const Container = styled.div``;

const tweetsTempRep = nodecg.Replicant("tweets-temp");

export const Twitter = () => {
const tweets = useReplicant("tweets-temp");

return (
<Container>
<List>
<TweetAdd
onSubmit={(tweets, onSuccess) => {
if (tweetsTempRep.value && tweets.text && tweets.name) {
tweetsTempRep.value.push(tweets);
onSuccess();
}
}}
/>
{tweets?.map((tweet, index) => (
<TweetItem
key={index}
tweet={tweet}
onSubmit={(tweet, onSuccess) => {
if (tweetsTempRep.value) {
tweetsTempRep.value = [
...tweets.slice(0, index),
...tweets.slice(index + 1),
];
nodecg.sendMessage("showTweet", tweet);
onSuccess();
}
}}
onSubmitFanArt={(tweet, onSuccess) => {
if (tweetsTempRep.value) {
tweetsTempRep.value = [
...tweets.slice(0, index),
...tweets.slice(index + 1),
];
nodecg.sendMessage("showFanArtTweet", tweet);
onSuccess();
}
}}
onDelete={(onSuccess) => {
if (tweetsTempRep.value) {
tweetsTempRep.value = [
...tweets.slice(0, index),
...tweets.slice(index + 1),
];
onSuccess();
}
}}
/>
))}
</List>
</Container>
);
};
97 changes: 97 additions & 0 deletions src/browser/dashboard/components/twitter/tweet-add.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import IconButton, {IconButtonProps} from "@mui/material/IconButton";
import ListItem from "@mui/material/ListItem";
import ListItemSecondaryAction from "@mui/material/ListItemSecondaryAction";
import ListItemText from "@mui/material/ListItemText";
import AddIcon from "@mui/icons-material/Add";
import {useState} from "react";
import {TweetsTemp} from "../../../../nodecg/generated";

type Tweet = TweetsTemp[number];

type Props = {
onSubmit: (tweet: Tweet, onSuccess: () => void) => void;
};

type ButtonProps = Pick<IconButtonProps, "onClick">;

const AddButton = (props: ButtonProps) => {
return (
<IconButton {...props}>
<AddIcon />
</IconButton>
);
};

export const TweetAdd = ({onSubmit}: Props) => {
const [tweet, setTweet] = useState<Tweet>({
text: "",
name: "",
image: "",
});

const clearInputs = () => {
setTweet({
text: "",
name: "",
image: "",
});
};

return (
<ListItem>
<ListItemText
primary={
<>
<input
value={tweet.name}
onChange={({currentTarget: {value}}) => {
setTweet((tweet) => ({
...tweet,
name: value,
}));
}}
placeholder='ユーザー名'
style={{
marginRight: "10px",
}}
/>
<input
value={tweet.image}
onChange={({currentTarget: {value}}) => {
setTweet((tweet) => ({
...tweet,
image: value,
}));
}}
size={50}
placeholder='画像URL(ファンアートを表示したい場合入力してください)'
/>
</>
}
secondary={
<textarea
value={tweet.text}
onChange={({currentTarget: {value}}) => {
setTweet((tweet) => ({
...tweet,
text: value,
}));
}}
placeholder='本文'
cols={100}
rows={4}
/>
}
/>
<ListItemSecondaryAction>
<AddButton
onClick={() => {
onSubmit(tweet, () => {
clearInputs();
});
}}
/>
</ListItemSecondaryAction>
</ListItem>
);
};
104 changes: 104 additions & 0 deletions src/browser/dashboard/components/twitter/tweet-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import IconButton, {IconButtonProps} from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import ListItem from "@mui/material/ListItem";
import ListItemSecondaryAction from "@mui/material/ListItemSecondaryAction";
import ListItemText from "@mui/material/ListItemText";
import Typography from "@mui/material/Typography";
import CheckIcon from "@mui/icons-material/Check";
import DeleteIcon from "@mui/icons-material/Delete";
import {useEffect, useState} from "react";
import {TweetsTemp} from "../../../../nodecg/generated";

type Tweet = TweetsTemp[number];

type Props = {
tweet: Tweet;
onSubmit: (tweet: Tweet, onSuccess: () => void) => void;
onSubmitFanArt: (tweet: Tweet, onSuccess: () => void) => void;
onDelete: (onSuccess: () => void) => void;
};

type ButtonProps = Pick<IconButtonProps, "onClick">;

const DeleteButton = (props: ButtonProps) => {
return (
<Tooltip title='ツイートを削除'>
<IconButton {...props}>
<DeleteIcon />
</IconButton>
</Tooltip>
);
};

const SubmitButton = (props: ButtonProps) => {
return (
<Tooltip title='ツイート表示/ファンアート表示を実行'>
<IconButton {...props}>
<CheckIcon />
</IconButton>
</Tooltip>
);
};

export const TweetItem = ({
tweet: propTweet,
onSubmit,
onSubmitFanArt,
onDelete,
}: Props) => {
const [tweet, setTweet] = useState<Tweet>(propTweet);

useEffect(() => {
setTweet(propTweet);
}, [propTweet]);

return (
<ListItem>
<ListItemText
primary={tweet.name}
secondary={
<>
<Typography
variant='body2'
style={{
maxWidth: "500px",
}}
>
{tweet.text}
</Typography>
{tweet.image && (
<a href={tweet.image} target='_blank'>
<img
src={tweet.image}
style={{
maxWidth: "300px",
maxHeight: "100px",
}}
/>
</a>
)}
</>
}
/>
<ListItemSecondaryAction>
(
<>
<SubmitButton
onClick={() => {
tweet.image
? onSubmitFanArt(tweet, () => {})
: onSubmit(tweet, () => {});
}}
/>
/
<DeleteButton
onClick={() => {
onDelete(() => {});
}}
/>
</>
)
</ListItemSecondaryAction>
</ListItem>
);
};
22 changes: 22 additions & 0 deletions src/browser/dashboard/views/twitter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import "../styles/global";

import createTheme from "@mui/material/styles/createTheme";
import ThemeProvider from "@mui/material/styles/ThemeProvider";
import {Twitter} from "../components/twitter";
import {render} from "../../render";

const theme = createTheme();

const App = () => {
return (
<ThemeProvider theme={theme}>
<Twitter />
</ThemeProvider>
);
};

render(
<>
<App />
</>,
);
Loading