forked from NotNet/gluestick
add back hold-to-unlink
This commit is contained in:
parent
3e24c99db4
commit
1340bf531a
5 changed files with 56 additions and 46 deletions
|
@ -58,29 +58,6 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
/* the !importants here piss me off but it wouldn't accept the property otherwise */
|
||||
.progress {
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
var(--fg-darker) 50%,
|
||||
var(--bg-dark) 50%
|
||||
) !important;
|
||||
background-size: 200% 100% !important;
|
||||
background-position: right bottom !important;
|
||||
transition: all 0s linear !important;
|
||||
|
||||
border: 0;
|
||||
border-radius: 0.15rem;
|
||||
cursor: pointer;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
/* when clicked */
|
||||
.progress:active {
|
||||
transition: all 3s linear !important;
|
||||
background-position: left bottom !important;
|
||||
}
|
||||
|
||||
.multiButtons {
|
||||
margin: 1rem 0;
|
||||
white-space: nowrap;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { UserInfo } from "@/ldap";
|
|||
import React from "react";
|
||||
import styles from "./AboutMe.module.css";
|
||||
import AvatarChanger from "@/components/AvatarChanger";
|
||||
import Input, { Label } from "@/components/Input";
|
||||
import Input, { Hint, Label } from "@/components/Input";
|
||||
import { Form, Formik, FormikHelpers } from "formik";
|
||||
import {
|
||||
AboutMeFormValues,
|
||||
|
@ -204,6 +204,8 @@ export default function AboutMe({
|
|||
|
||||
<div className={styles.connections}>
|
||||
<Label>Connections</Label>
|
||||
<Hint>Click to link, hold to unlink.</Hint>
|
||||
|
||||
<Connection
|
||||
service="Discord"
|
||||
authState={discordState}
|
||||
|
|
|
@ -55,3 +55,21 @@
|
|||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* the !importants here piss me off but it wouldn't accept the property otherwise */
|
||||
.progress {
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
var(--fg-darker) 50%,
|
||||
var(--bg-dark) 50%
|
||||
) !important;
|
||||
background-size: 200% 100% !important;
|
||||
background-position: right bottom !important;
|
||||
transition: all 0s linear !important;
|
||||
}
|
||||
|
||||
/* when clicked */
|
||||
.progress:active {
|
||||
transition: all 3s linear !important;
|
||||
background-position: left bottom !important;
|
||||
}
|
||||
|
|
|
@ -18,39 +18,41 @@ export default function Connection({
|
|||
icon?: () => JSX.Element;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [changing, setChanging] = React.useState(false);
|
||||
|
||||
// TODO: Reimplement hold-to-unlink.
|
||||
const holdTime = authState?.connected ? 3000 : 0;
|
||||
const interval = React.useRef<NodeJS.Timeout | null>();
|
||||
|
||||
async function handleClick(event: React.MouseEvent<HTMLButtonElement>) {
|
||||
event.preventDefault();
|
||||
|
||||
if (unavailable) return;
|
||||
|
||||
const provider = service.toLowerCase();
|
||||
if (authState?.connected === false) {
|
||||
setChanging(true);
|
||||
router.push(`/oauth/${provider}/login`);
|
||||
const execute = async () => {
|
||||
const name = authState?.name.toLowerCase();
|
||||
if (!authState?.connected) {
|
||||
router.push(`/oauth/${name}/login`);
|
||||
} else {
|
||||
setChanging(true);
|
||||
if (confirm(`Unlink your ${service} account?`)) {
|
||||
await fetch(`/api/unlink?provider=${provider}`, { method: "POST" });
|
||||
window.location.reload();
|
||||
} else {
|
||||
setChanging(false);
|
||||
}
|
||||
await fetch(`/api/unlink?provider=${name}`, { method: "POST" });
|
||||
router.refresh();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mouseDown = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
interval.current = setTimeout(execute, holdTime);
|
||||
};
|
||||
|
||||
const mouseUp = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
if (interval.current) clearTimeout(interval.current);
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={classnames(
|
||||
styles.connection,
|
||||
unavailable ? styles.unavailable : null,
|
||||
!authState?.connected ? styles.disconnected : null
|
||||
!authState?.connected ? styles.disconnected : styles.progress
|
||||
)}
|
||||
onClick={handleClick}
|
||||
disabled={changing}
|
||||
disabled={unavailable}
|
||||
onMouseDown={mouseDown}
|
||||
onMouseUp={mouseUp}
|
||||
>
|
||||
<div className={styles.iconContainer}>
|
||||
{icon ? icon() : <span className={styles.dot}></span>}
|
||||
|
|
|
@ -23,6 +23,17 @@ export function Label({
|
|||
);
|
||||
}
|
||||
|
||||
export function Hint({
|
||||
children,
|
||||
...props
|
||||
}: LabelHTMLAttributes<HTMLLabelElement>) {
|
||||
return (
|
||||
<label className={classnames(styles.hint, props.className)} {...props}>
|
||||
{children}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Input<T>(
|
||||
props: CustomInputProps<T> &
|
||||
FieldAttributes<{ hint?: string; label?: string; disabled?: boolean }>
|
||||
|
|
Loading…
Reference in a new issue