mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-10 01:03:36 -05:00
Add editing role name / colour.
Animate avatars on message hover. Switch to 24-hour time format by default.
This commit is contained in:
parent
6f6020c474
commit
7374591458
9 changed files with 122 additions and 44 deletions
2
external/lang
vendored
2
external/lang
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 3931bf87e94264d92556a2f3ee96c6051be75b02
|
Subproject commit 9f72b064aad85293f332c3f7ce3f4fe5965def37
|
|
@ -94,7 +94,7 @@
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scroll": "^1.8.2",
|
"react-scroll": "^1.8.2",
|
||||||
"redux": "^4.1.0",
|
"redux": "^4.1.0",
|
||||||
"revolt.js": "4.3.3-alpha.14",
|
"revolt.js": "4.3.3-alpha.15",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
"shade-blend-color": "^1.0.0",
|
"shade-blend-color": "^1.0.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { attachContextMenu } from "preact-context-menu";
|
import { attachContextMenu } from "preact-context-menu";
|
||||||
import { memo } from "preact/compat";
|
import { memo } from "preact/compat";
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext, useState } from "preact/hooks";
|
||||||
|
|
||||||
import { QueuedMessage } from "../../../redux/reducers/queue";
|
import { QueuedMessage } from "../../../redux/reducers/queue";
|
||||||
|
|
||||||
|
@ -64,6 +64,9 @@ function Message({
|
||||||
const openProfile = () =>
|
const openProfile = () =>
|
||||||
openScreen({ id: "profile", user_id: message.author });
|
openScreen({ id: "profile", user_id: message.author });
|
||||||
|
|
||||||
|
// ! FIXME: animate on hover
|
||||||
|
const [animate, setAnimate] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id={message._id}>
|
<div id={message._id}>
|
||||||
{message.replies?.map((message_id, index) => (
|
{message.replies?.map((message_id, index) => (
|
||||||
|
@ -88,7 +91,9 @@ function Message({
|
||||||
queued,
|
queued,
|
||||||
})
|
})
|
||||||
: undefined
|
: undefined
|
||||||
}>
|
}
|
||||||
|
onMouseEnter={() => setAnimate(true)}
|
||||||
|
onMouseLeave={() => setAnimate(false)}>
|
||||||
<MessageInfo>
|
<MessageInfo>
|
||||||
{head ? (
|
{head ? (
|
||||||
<UserIcon
|
<UserIcon
|
||||||
|
@ -96,6 +101,7 @@ function Message({
|
||||||
size={36}
|
size={36}
|
||||||
onContextMenu={userContext}
|
onContextMenu={userContext}
|
||||||
onClick={openProfile}
|
onClick={openProfile}
|
||||||
|
animate={animate}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<MessageDetail message={message} position="left" />
|
<MessageDetail message={message} position="left" />
|
||||||
|
|
|
@ -150,7 +150,10 @@ function Locale({ children, locale }: Props) {
|
||||||
const dayjs = obj.dayjs;
|
const dayjs = obj.dayjs;
|
||||||
const defaults = dayjs.defaults;
|
const defaults = dayjs.defaults;
|
||||||
|
|
||||||
const twelvehour = defaults?.twelvehour === "yes" || true;
|
const twelvehour = defaults?.twelvehour
|
||||||
|
? defaults.twelvehour === "yes"
|
||||||
|
: false;
|
||||||
|
|
||||||
const separator: string = defaults?.date_separator ?? "/";
|
const separator: string = defaults?.date_separator ?? "/";
|
||||||
const date: "traditional" | "simplified" | "ISO8601" =
|
const date: "traditional" | "simplified" | "ISO8601" =
|
||||||
defaults?.date_format ?? "traditional";
|
defaults?.date_format ?? "traditional";
|
||||||
|
|
|
@ -141,7 +141,7 @@ export function UserProfile({ user_id, onClose, dummy, dummyProfile }: Props) {
|
||||||
`linear-gradient( rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7) ), url('${backgroundURL}')`,
|
`linear-gradient( rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7) ), url('${backgroundURL}')`,
|
||||||
}}>
|
}}>
|
||||||
<div className={styles.profile}>
|
<div className={styles.profile}>
|
||||||
<UserIcon size={80} target={user} status />
|
<UserIcon size={80} target={user} status animate />
|
||||||
<div className={styles.details}>
|
<div className={styles.details}>
|
||||||
<Localizer>
|
<Localizer>
|
||||||
<span
|
<span
|
||||||
|
|
|
@ -1,24 +1,41 @@
|
||||||
@keyframes open {
|
@keyframes open {
|
||||||
0% {transform: scale(1.2);};
|
0% {
|
||||||
100% {transform: scale(1);};
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes close {
|
@keyframes close {
|
||||||
0% {transform: scale(1); opacity: 1;};
|
0% {
|
||||||
100% {transform: scale(1.2); opacity: 0;};
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1.2);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes opacity {
|
@keyframes opacity {
|
||||||
0% {opacity: 0;};
|
0% {
|
||||||
20% {opacity: .5;}
|
opacity: 0;
|
||||||
50% {opacity: 1;}
|
}
|
||||||
|
20% {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings[data-mobile="true"] {
|
.settings[data-mobile="true"] {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background: var(--primary-header);
|
background: var(--primary-header);
|
||||||
|
|
||||||
.sidebar, .content {
|
.sidebar,
|
||||||
|
.content {
|
||||||
background: var(--primary-background);
|
background: var(--primary-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +53,6 @@
|
||||||
|
|
||||||
.version {
|
.version {
|
||||||
place-items: center;
|
place-items: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +68,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
animation: open .18s ease-out,
|
animation: open 0.18s ease-out, opacity 0.18s;
|
||||||
opacity .18s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings {
|
.settings {
|
||||||
|
@ -177,8 +192,8 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
width: 40px;
|
width: 40px;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
font-size: .75em;
|
font-size: 0.75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.closeButton {
|
.closeButton {
|
||||||
|
@ -208,6 +223,10 @@
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader {
|
.loader {
|
||||||
|
|
|
@ -39,7 +39,8 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
background: var(--secondary-background);
|
background: var(--secondary-background);
|
||||||
|
|
||||||
code, span {
|
code,
|
||||||
|
span {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,10 +96,6 @@
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
|
||||||
section {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@ -107,7 +104,8 @@
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
h1, h2 {
|
h1,
|
||||||
|
h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||||
|
|
||||||
import Button from "../../../components/ui/Button";
|
import Button from "../../../components/ui/Button";
|
||||||
import Checkbox from "../../../components/ui/Checkbox";
|
import Checkbox from "../../../components/ui/Checkbox";
|
||||||
|
import ColourSwatches from "../../../components/ui/ColourSwatches";
|
||||||
import IconButton from "../../../components/ui/IconButton";
|
import IconButton from "../../../components/ui/IconButton";
|
||||||
import InputBox from "../../../components/ui/InputBox";
|
import InputBox from "../../../components/ui/InputBox";
|
||||||
import Overline from "../../../components/ui/Overline";
|
import Overline from "../../../components/ui/Overline";
|
||||||
|
@ -40,21 +41,46 @@ export function Roles({ server }: Props) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const v = (id: string) =>
|
function getPermissions(id: string) {
|
||||||
I32ToU32(
|
return I32ToU32(
|
||||||
id === "default"
|
id === "default"
|
||||||
? server.default_permissions
|
? server.default_permissions
|
||||||
: roles[id].permissions,
|
: roles[id].permissions,
|
||||||
);
|
);
|
||||||
const [perm, setPerm] = useState(v(role));
|
}
|
||||||
useEffect(() => setPerm(v(role)), [role, roles[role]?.permissions]);
|
|
||||||
|
|
||||||
const modified = !isEqual(perm, v(role));
|
const { name: roleName, colour: roleColour } = roles[role] ?? {};
|
||||||
const save = () =>
|
|
||||||
|
const [perm, setPerm] = useState(getPermissions(role));
|
||||||
|
const [name, setName] = useState(roleName);
|
||||||
|
const [colour, setColour] = useState(roleColour);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => setPerm(getPermissions(role)),
|
||||||
|
[role, roles[role]?.permissions],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => setName(roleName), [role, roleName]);
|
||||||
|
useEffect(() => setColour(roleColour), [role, roleColour]);
|
||||||
|
|
||||||
|
const modified =
|
||||||
|
!isEqual(perm, getPermissions(role)) ||
|
||||||
|
!isEqual(name, roleName) ||
|
||||||
|
!isEqual(colour, roleColour);
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
if (!isEqual(perm, getPermissions(role))) {
|
||||||
client.servers.setPermissions(server._id, role, {
|
client.servers.setPermissions(server._id, role, {
|
||||||
server: perm[0],
|
server: perm[0],
|
||||||
channel: perm[1],
|
channel: perm[1],
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEqual(name, roleName) || !isEqual(colour, roleColour)) {
|
||||||
|
client.servers.editRole(server._id, role, { name, colour });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const deleteRole = () => {
|
const deleteRole = () => {
|
||||||
setRole("default");
|
setRole("default");
|
||||||
client.servers.deleteRole(server._id, role);
|
client.servers.deleteRole(server._id, role);
|
||||||
|
@ -92,7 +118,8 @@ export function Roles({ server }: Props) {
|
||||||
return (
|
return (
|
||||||
<ButtonItem
|
<ButtonItem
|
||||||
active={role === id}
|
active={role === id}
|
||||||
onClick={() => setRole(id)}>
|
onClick={() => setRole(id)}
|
||||||
|
style={{ color: roles[id].colour }}>
|
||||||
{roles[id].name}
|
{roles[id].name}
|
||||||
</ButtonItem>
|
</ButtonItem>
|
||||||
);
|
);
|
||||||
|
@ -111,6 +138,31 @@ export function Roles({ server }: Props) {
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
{role !== "default" && (
|
||||||
|
<>
|
||||||
|
<section>
|
||||||
|
<Overline type="subtle">Role Name</Overline>
|
||||||
|
<p>
|
||||||
|
<InputBox
|
||||||
|
value={name}
|
||||||
|
onChange={(e) =>
|
||||||
|
setName(e.currentTarget.value)
|
||||||
|
}
|
||||||
|
contrast
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<Overline type="subtle">Role Colour</Overline>
|
||||||
|
<p>
|
||||||
|
<ColourSwatches
|
||||||
|
value={colour ?? "gray"}
|
||||||
|
onChange={(value) => setColour(value)}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<section>
|
<section>
|
||||||
<Overline type="subtle">
|
<Overline type="subtle">
|
||||||
<Text id="app.settings.permissions.server" />
|
<Text id="app.settings.permissions.server" />
|
||||||
|
|
|
@ -3563,10 +3563,10 @@ reusify@^1.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||||
|
|
||||||
revolt.js@4.3.3-alpha.14:
|
revolt.js@4.3.3-alpha.15:
|
||||||
version "4.3.3-alpha.14"
|
version "4.3.3-alpha.15"
|
||||||
resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.14.tgz#f4912ee25725de6e43ba1d4fd8ab84c711678271"
|
resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.15.tgz#e511ad500a20f658b15b7bad0fdb9e2a5465d1b1"
|
||||||
integrity sha512-4p3DhEu+GUKZxczCPXR2JM04fzGlFfZdwHYjgkgU48NgPXgzxQrSv4x0FjpyIIv3xNpuO59z35mYRMLxAnBXsQ==
|
integrity sha512-24hIQEO+FIRIAQXITBH2qVvWH6LA1MeJW2/3lj6cqBgJz7lnb3ZNIXZBu5sHbUEJpIDtJiHcOEeaeh3sE2RwxA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/mutable" "1.1.0"
|
"@insertish/mutable" "1.1.0"
|
||||||
axios "^0.19.2"
|
axios "^0.19.2"
|
||||||
|
|
Loading…
Reference in a new issue