diff --git a/renderer/app.css b/renderer/app.css index 3aae1c6a..1cd32788 100644 --- a/renderer/app.css +++ b/renderer/app.css @@ -3,6 +3,7 @@ @tailwind utilities; .emojione { + display: inline-block; width: 1.2rem; height: 1.2rem; } diff --git a/renderer/components/timelines/Timeline.tsx b/renderer/components/timelines/Timeline.tsx index cee7d5f5..9869c70f 100644 --- a/renderer/components/timelines/Timeline.tsx +++ b/renderer/components/timelines/Timeline.tsx @@ -45,6 +45,23 @@ export default function Timeline(props: Props) { } } + const updateStatus = (current: Array, status: Entity.Status) => { + const renew = current.map(s => { + if (s.id === status.id) { + return status + } else if (s.reblog && s.reblog.id === status.id) { + return Object.assign({}, s, { reblog: status }) + } else if (status.reblog && s.id === status.reblog.id) { + return status.reblog + } else if (status.reblog && s.reblog && s.reblog.id === status.reblog.id) { + return Object.assign({}, s, { reblog: status.reblog }) + } else { + return s + } + }) + return renew + } + return (
@@ -59,7 +76,14 @@ export default function Timeline(props: Props) { } + itemContent={(_, status) => ( + setStatuses(current => updateStatus(current, status))} + /> + )} />
diff --git a/renderer/components/timelines/status/Poll.tsx b/renderer/components/timelines/status/Poll.tsx new file mode 100644 index 00000000..dd4b9175 --- /dev/null +++ b/renderer/components/timelines/status/Poll.tsx @@ -0,0 +1,124 @@ +import dayjs from 'dayjs' +import { Progress, Button, Radio, Label, Checkbox } from 'flowbite-react' +import { Entity, MegalodonInterface } from 'megalodon' + +type Props = { + poll: Entity.Poll + client: MegalodonInterface + onRefresh: () => void +} +export default function Poll(props: Props) { + if (props.poll.voted || props.poll.expired) { + return + } else if (props.poll.multiple) { + return + } else { + return + } +} + +function SimplePoll(props: Props) { + const vote = async () => { + const elements = document.getElementsByName(props.poll.id) + let checked: number | null = null + elements.forEach((element, index) => { + if ((element as HTMLInputElement).checked) { + checked = index + } + }) + if (checked !== null) { + await props.client.votePoll(props.poll.id, [checked]) + props.onRefresh() + } + } + return ( +
+ {props.poll.options.map((option, index) => ( +
+ + +
+ ))} +
+ +
{props.poll.votes_count} people
+
+ +
+
+
+ ) +} + +function MultiplePoll(props: Props) { + const vote = async () => { + let checked: Array = [] + props.poll.options.forEach((value, index) => { + const element = document.getElementById(value.title) as HTMLInputElement + if (element.checked) { + checked = [...checked, index] + } + }) + if (checked.length > 0) { + await props.client.votePoll(props.poll.id, checked) + props.onRefresh() + } + } + + return ( +
+ {props.poll.options.map((option, index) => ( +
+ + +
+ ))} +
+ +
{props.poll.votes_count} people
+
+ +
+
+
+ ) +} + +function PollResult(props: Props) { + return ( +
+ {props.poll.options.map((option, index) => ( +
+ {percent(option.votes_count ?? 0, props.poll.votes_count)}% + {option.title} + +
+ ))} +
+ +
{props.poll.votes_count} people
+ {props.poll.expired ? ( +
Closed
+ ) : ( +
+ +
+ )} +
+
+ ) +} + +const percent = (votes: number, all: number) => { + if (all > 0) { + return Math.round((votes * 100) / all) + } else { + return 0 + } +} diff --git a/renderer/components/timelines/status/Status.tsx b/renderer/components/timelines/status/Status.tsx index 04438959..9fa6fb02 100644 --- a/renderer/components/timelines/status/Status.tsx +++ b/renderer/components/timelines/status/Status.tsx @@ -5,15 +5,22 @@ import Body from './Body' import Media from './Media' import emojify from '@/utils/emojify' import Card from './Card' +import Poll from './Poll' type Props = { status: Entity.Status client: MegalodonInterface + onRefresh: (status: Entity.Status) => void } export default function Status(props: Props) { const status = originalStatus(props.status) + const onRefresh = async () => { + const res = await props.client.getStatus(status.id) + props.onRefresh(res.data) + } + return (
{rebloggedHeader(props.status)} @@ -35,6 +42,7 @@ export default function Status(props: Props) {
+ {status.poll && } {status.card && }