mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-10 01:03:36 -05:00
feat(rbd): transform rbd types to Preact from React
This commit is contained in:
parent
c208064d2c
commit
f97925073a
2 changed files with 227 additions and 192 deletions
56
src/lib/dnd.ts
Normal file
56
src/lib/dnd.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import {
|
||||||
|
Draggable as rbdDraggable,
|
||||||
|
DraggableProps as rbdDraggableProps,
|
||||||
|
DraggableProvided as rbdDraggableProvided,
|
||||||
|
DraggableProvidedDraggableProps as rbdDraggableProvidedDraggableProps,
|
||||||
|
DraggableProvidedDragHandleProps as rbdDraggableProvidedDragHandleProps,
|
||||||
|
DraggableRubric,
|
||||||
|
DraggableStateSnapshot,
|
||||||
|
Droppable as rbdDroppable,
|
||||||
|
DroppableProps,
|
||||||
|
DroppableProvided,
|
||||||
|
DroppableStateSnapshot,
|
||||||
|
} from "react-beautiful-dnd";
|
||||||
|
|
||||||
|
export type DraggableProvidedDraggableProps = Omit<
|
||||||
|
rbdDraggableProvidedDraggableProps,
|
||||||
|
"style" | "onTransitionEnd"
|
||||||
|
> & {
|
||||||
|
style?: string;
|
||||||
|
onTransitionEnd?: JSX.TransitionEventHandler<HTMLElement>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DraggableProvidedDragHandleProps = Omit<
|
||||||
|
rbdDraggableProvidedDragHandleProps,
|
||||||
|
"onDragStart"
|
||||||
|
> & {
|
||||||
|
onDragStart?: JSX.DragEventHandler<HTMLElement>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DraggableProvided = rbdDraggableProvided & {
|
||||||
|
draggableProps: DraggableProvidedDraggableProps;
|
||||||
|
dragHandleProps?: DraggableProvidedDragHandleProps | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DraggableChildrenFn = (
|
||||||
|
provided: DraggableProvided,
|
||||||
|
snapshot: DraggableStateSnapshot,
|
||||||
|
rubric: DraggableRubric,
|
||||||
|
) => JSX.Element;
|
||||||
|
|
||||||
|
export type DraggableProps = Omit<rbdDraggableProps, "children"> & {
|
||||||
|
children: DraggableChildrenFn;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Draggable = rbdDraggable as unknown as (
|
||||||
|
props: DraggableProps,
|
||||||
|
) => JSX.Element;
|
||||||
|
|
||||||
|
export const Droppable = rbdDroppable as unknown as (
|
||||||
|
props: Omit<DroppableProps, "children"> & {
|
||||||
|
children(
|
||||||
|
provided: DroppableProvided,
|
||||||
|
snapshot: DroppableStateSnapshot,
|
||||||
|
): JSX.Element;
|
||||||
|
},
|
||||||
|
) => JSX.Element;
|
|
@ -1,7 +1,6 @@
|
||||||
import { Filter, Plus, X } from "@styled-icons/boxicons-regular";
|
import { Plus, X } from "@styled-icons/boxicons-regular";
|
||||||
import isEqual from "lodash.isequal";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
|
import { DragDropContext } from "react-beautiful-dnd";
|
||||||
import { TextChannel, VoiceChannel } from "revolt-api/types/Channels";
|
import { TextChannel, VoiceChannel } from "revolt-api/types/Channels";
|
||||||
import { Category } from "revolt-api/types/Servers";
|
import { Category } from "revolt-api/types/Servers";
|
||||||
import { Server } from "revolt.js/dist/maps/Servers";
|
import { Server } from "revolt.js/dist/maps/Servers";
|
||||||
|
@ -12,16 +11,13 @@ import { Text } from "preact-i18n";
|
||||||
import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
|
import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { useAutosave } from "../../../lib/debounce";
|
import { useAutosave } from "../../../lib/debounce";
|
||||||
|
import { Draggable, Droppable } from "../../../lib/dnd";
|
||||||
import { noop } from "../../../lib/js";
|
import { noop } from "../../../lib/js";
|
||||||
|
|
||||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||||
|
|
||||||
import ChannelIcon from "../../../components/common/ChannelIcon";
|
import ChannelIcon from "../../../components/common/ChannelIcon";
|
||||||
import Button from "../../../components/ui/Button";
|
|
||||||
import ComboBox from "../../../components/ui/ComboBox";
|
|
||||||
import InputBox from "../../../components/ui/InputBox";
|
|
||||||
import SaveStatus, { EditStatus } from "../../../components/ui/SaveStatus";
|
import SaveStatus, { EditStatus } from "../../../components/ui/SaveStatus";
|
||||||
import Tip from "../../../components/ui/Tip";
|
|
||||||
|
|
||||||
const KanbanEntry = styled.div`
|
const KanbanEntry = styled.div`
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
|
@ -234,86 +230,83 @@ export const Categories = observer(({ server }: Props) => {
|
||||||
droppableId="categories"
|
droppableId="categories"
|
||||||
direction="horizontal"
|
direction="horizontal"
|
||||||
type="column">
|
type="column">
|
||||||
{(provided) =>
|
{(provided) => (
|
||||||
(
|
<div
|
||||||
<div
|
ref={provided.innerRef}
|
||||||
ref={provided.innerRef}
|
{...provided.droppableProps}>
|
||||||
{...provided.droppableProps}>
|
<KanbanBoard>
|
||||||
<KanbanBoard>
|
<ListElement
|
||||||
|
category={defaultCategory}
|
||||||
|
server={server}
|
||||||
|
index={0}
|
||||||
|
addChannel={noop}
|
||||||
|
/>
|
||||||
|
{categories.map((category, index) => (
|
||||||
<ListElement
|
<ListElement
|
||||||
category={defaultCategory}
|
draggable
|
||||||
|
category={category}
|
||||||
server={server}
|
server={server}
|
||||||
index={0}
|
index={index + 1}
|
||||||
addChannel={noop}
|
key={category.id}
|
||||||
|
setTitle={(title) => {
|
||||||
|
setCategories(
|
||||||
|
categories.map((x) =>
|
||||||
|
x.id === category.id
|
||||||
|
? {
|
||||||
|
...x,
|
||||||
|
title,
|
||||||
|
}
|
||||||
|
: x,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
deleteSelf={() =>
|
||||||
|
setCategories(
|
||||||
|
categories.filter(
|
||||||
|
(x) =>
|
||||||
|
x.id !==
|
||||||
|
category.id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
addChannel={(channel) => {
|
||||||
|
setCategories(
|
||||||
|
categories.map((x) =>
|
||||||
|
x.id === category.id
|
||||||
|
? {
|
||||||
|
...x,
|
||||||
|
channels: [
|
||||||
|
...x.channels,
|
||||||
|
channel._id,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: x,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{categories.map((category, index) => (
|
))}
|
||||||
<ListElement
|
<KanbanList last>
|
||||||
draggable
|
<div class="inner">
|
||||||
category={category}
|
<KanbanListHeader
|
||||||
server={server}
|
onClick={() =>
|
||||||
index={index + 1}
|
setCategories([
|
||||||
key={category.id}
|
...categories,
|
||||||
setTitle={(title) => {
|
{
|
||||||
setCategories(
|
id: ulid(),
|
||||||
categories.map((x) =>
|
title: "New Category",
|
||||||
x.id === category.id
|
channels: [],
|
||||||
? {
|
},
|
||||||
...x,
|
])
|
||||||
title,
|
}>
|
||||||
}
|
<Plus size={24} />
|
||||||
: x,
|
</KanbanListHeader>
|
||||||
),
|
</div>
|
||||||
);
|
</KanbanList>
|
||||||
}}
|
{provided.placeholder}
|
||||||
deleteSelf={() =>
|
</KanbanBoard>
|
||||||
setCategories(
|
</div>
|
||||||
categories.filter(
|
)}
|
||||||
(x) =>
|
|
||||||
x.id !==
|
|
||||||
category.id,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
addChannel={(channel) => {
|
|
||||||
setCategories(
|
|
||||||
categories.map((x) =>
|
|
||||||
x.id === category.id
|
|
||||||
? {
|
|
||||||
...x,
|
|
||||||
channels:
|
|
||||||
[
|
|
||||||
...x.channels,
|
|
||||||
channel._id,
|
|
||||||
],
|
|
||||||
}
|
|
||||||
: x,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
<KanbanList last>
|
|
||||||
<div class="inner">
|
|
||||||
<KanbanListHeader
|
|
||||||
onClick={() =>
|
|
||||||
setCategories([
|
|
||||||
...categories,
|
|
||||||
{
|
|
||||||
id: ulid(),
|
|
||||||
title: "New Category",
|
|
||||||
channels: [],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
}>
|
|
||||||
<Plus size={24} />
|
|
||||||
</KanbanListHeader>
|
|
||||||
</div>
|
|
||||||
</KanbanList>
|
|
||||||
{provided.placeholder}
|
|
||||||
</KanbanBoard>
|
|
||||||
</div>
|
|
||||||
) as any
|
|
||||||
}
|
|
||||||
</Droppable>
|
</Droppable>
|
||||||
</FullSize>
|
</FullSize>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
|
@ -366,116 +359,102 @@ function ListElement({
|
||||||
key={category.id}
|
key={category.id}
|
||||||
draggableId={category.id}
|
draggableId={category.id}
|
||||||
index={index}>
|
index={index}>
|
||||||
{(provided) =>
|
{(provided) => (
|
||||||
(
|
<div {...provided.draggableProps} ref={provided.innerRef}>
|
||||||
<div
|
<KanbanList last={false} key={category.id}>
|
||||||
{...(provided.draggableProps as any)}
|
<div class="inner">
|
||||||
ref={provided.innerRef}>
|
<Row>
|
||||||
<KanbanList last={false} key={category.id}>
|
<KanbanListHeader {...provided.dragHandleProps}>
|
||||||
<div class="inner">
|
{editing ? (
|
||||||
<Row>
|
<input
|
||||||
<KanbanListHeader
|
value={editing}
|
||||||
{...(provided.dragHandleProps as any)}>
|
onChange={(e) =>
|
||||||
{editing ? (
|
setEditing(
|
||||||
<input
|
e.currentTarget.value,
|
||||||
value={editing}
|
)
|
||||||
onChange={(e) =>
|
}
|
||||||
setEditing(
|
onKeyDown={(e) =>
|
||||||
e.currentTarget.value,
|
e.key === "Enter" && save()
|
||||||
)
|
}
|
||||||
}
|
id={category.id}
|
||||||
onKeyDown={(e) =>
|
/>
|
||||||
e.key === "Enter" && save()
|
) : (
|
||||||
}
|
<span onClick={startEditing}>
|
||||||
id={category.id}
|
{category.title}
|
||||||
/>
|
</span>
|
||||||
) : (
|
|
||||||
<span onClick={startEditing}>
|
|
||||||
{category.title}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</KanbanListHeader>
|
|
||||||
{deleteSelf && (
|
|
||||||
<KanbanListHeader onClick={deleteSelf}>
|
|
||||||
<X size={24} />
|
|
||||||
</KanbanListHeader>
|
|
||||||
)}
|
)}
|
||||||
</Row>
|
|
||||||
<Droppable
|
|
||||||
droppableId={category.id}
|
|
||||||
key={category.id}>
|
|
||||||
{(provided) =>
|
|
||||||
(
|
|
||||||
<div
|
|
||||||
ref={provided.innerRef}
|
|
||||||
{...provided.droppableProps}>
|
|
||||||
{category.channels.map(
|
|
||||||
(x, index) => {
|
|
||||||
const channel =
|
|
||||||
server.client.channels.get(
|
|
||||||
x,
|
|
||||||
);
|
|
||||||
if (!channel)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Draggable
|
|
||||||
key={x}
|
|
||||||
draggableId={x}
|
|
||||||
index={index}>
|
|
||||||
{(provided) =>
|
|
||||||
(
|
|
||||||
<div
|
|
||||||
{...(provided.draggableProps as any)}
|
|
||||||
{...provided.dragHandleProps}
|
|
||||||
ref={
|
|
||||||
provided.innerRef
|
|
||||||
}>
|
|
||||||
<KanbanEntry>
|
|
||||||
<div class="inner">
|
|
||||||
<ChannelIcon
|
|
||||||
target={
|
|
||||||
channel
|
|
||||||
}
|
|
||||||
size={
|
|
||||||
24
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<span>
|
|
||||||
{
|
|
||||||
channel.name
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</KanbanEntry>
|
|
||||||
</div>
|
|
||||||
) as any
|
|
||||||
}
|
|
||||||
</Draggable>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
{provided.placeholder}
|
|
||||||
</div>
|
|
||||||
) as any
|
|
||||||
}
|
|
||||||
</Droppable>
|
|
||||||
<KanbanListHeader
|
|
||||||
onClick={() =>
|
|
||||||
openScreen({
|
|
||||||
id: "special_prompt",
|
|
||||||
type: "create_channel",
|
|
||||||
target: server,
|
|
||||||
cb: addChannel,
|
|
||||||
})
|
|
||||||
}>
|
|
||||||
<Plus size={24} />
|
|
||||||
</KanbanListHeader>
|
</KanbanListHeader>
|
||||||
</div>
|
{deleteSelf && (
|
||||||
</KanbanList>
|
<KanbanListHeader onClick={deleteSelf}>
|
||||||
</div>
|
<X size={24} />
|
||||||
) as any
|
</KanbanListHeader>
|
||||||
}
|
)}
|
||||||
|
</Row>
|
||||||
|
<Droppable
|
||||||
|
droppableId={category.id}
|
||||||
|
key={category.id}>
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.droppableProps}>
|
||||||
|
{category.channels.map((x, index) => {
|
||||||
|
const channel =
|
||||||
|
server.client.channels.get(x);
|
||||||
|
if (!channel) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Draggable
|
||||||
|
key={x}
|
||||||
|
draggableId={x}
|
||||||
|
index={index}>
|
||||||
|
{(provided) => (
|
||||||
|
<div
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
ref={
|
||||||
|
provided.innerRef
|
||||||
|
}>
|
||||||
|
<KanbanEntry>
|
||||||
|
<div class="inner">
|
||||||
|
<ChannelIcon
|
||||||
|
target={
|
||||||
|
channel
|
||||||
|
}
|
||||||
|
size={
|
||||||
|
24
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
{
|
||||||
|
channel.name
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</KanbanEntry>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
<KanbanListHeader
|
||||||
|
onClick={() =>
|
||||||
|
openScreen({
|
||||||
|
id: "special_prompt",
|
||||||
|
type: "create_channel",
|
||||||
|
target: server,
|
||||||
|
cb: addChannel,
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
<Plus size={24} />
|
||||||
|
</KanbanListHeader>
|
||||||
|
</div>
|
||||||
|
</KanbanList>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Draggable>
|
</Draggable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue