From d8e23aea129974ac0bcc7dfbf4c3961019f9d346 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 2 Jul 2021 18:00:17 +0100 Subject: [PATCH] Add pending requests menu. --- src/context/intermediate/Intermediate.tsx | 3 +- src/context/intermediate/Popovers.tsx | 3 ++ .../intermediate/popovers/PendingRequests.tsx | 26 +++++++++ src/lib/ContextMenus.tsx | 3 +- src/pages/friends/Friend.module.scss | 54 ++++++++++++++++--- src/pages/friends/Friend.tsx | 6 ++- src/pages/friends/Friends.tsx | 26 +++++++-- src/styles/_context-menu.scss | 2 +- 8 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 src/context/intermediate/popovers/PendingRequests.tsx diff --git a/src/context/intermediate/Intermediate.tsx b/src/context/intermediate/Intermediate.tsx index 7cb97202..89298064 100644 --- a/src/context/intermediate/Intermediate.tsx +++ b/src/context/intermediate/Intermediate.tsx @@ -53,6 +53,7 @@ export type Screen = | { id: "modify_account"; field: "username" | "email" | "password" } | { id: "profile"; user_id: string } | { id: "channel_info"; channel_id: string } +| { id: "pending_requests"; users: string[] } | { id: "user_picker"; omit?: string[]; @@ -119,7 +120,7 @@ export default function Intermediate(props: Props) { } /** By specifying a key, we reset state whenever switching screen. */ /> { if (action === 'POP') { openScreen({ id: 'none' }); diff --git a/src/context/intermediate/Popovers.tsx b/src/context/intermediate/Popovers.tsx index 73d2337e..d0ee4305 100644 --- a/src/context/intermediate/Popovers.tsx +++ b/src/context/intermediate/Popovers.tsx @@ -7,6 +7,7 @@ import { SpecialPromptModal } from "./modals/Prompt"; import { UserProfile } from "./popovers/UserProfile"; import { ImageViewer } from "./popovers/ImageViewer"; import { ChannelInfo } from "./popovers/ChannelInfo"; +import { PendingRequests } from "./popovers/PendingRequests"; import { ModifyAccountModal } from "./popovers/ModifyAccount"; export default function Popovers() { @@ -24,6 +25,8 @@ export default function Popovers() { return ; case "channel_info": return ; + case "pending_requests": + return ; case "modify_account": return ; case "special_prompt": diff --git a/src/context/intermediate/popovers/PendingRequests.tsx b/src/context/intermediate/popovers/PendingRequests.tsx new file mode 100644 index 00000000..710cb6b2 --- /dev/null +++ b/src/context/intermediate/popovers/PendingRequests.tsx @@ -0,0 +1,26 @@ +import styles from "./UserPicker.module.scss"; +import { useUsers } from "../../revoltjs/hooks"; +import Modal from "../../../components/ui/Modal"; +import { Friend } from "../../../pages/friends/Friend"; + +interface Props { + users: string[]; + onClose: () => void; +} + +export function PendingRequests({ users: ids, onClose }: Props) { + const users = useUsers(ids); + + return ( + +
+ { users + .filter(x => typeof x !== 'undefined') + .map(x => ) } +
+
+ ); +} diff --git a/src/lib/ContextMenus.tsx b/src/lib/ContextMenus.tsx index 97e28529..7252d8ba 100644 --- a/src/lib/ContextMenus.tsx +++ b/src/lib/ContextMenus.tsx @@ -23,7 +23,6 @@ import { At, Bell, BellOff, Check, CheckSquare, ChevronRight, Block, Square, Lef import { Cog } from "@styled-icons/boxicons-solid"; import { getNotificationState, Notifications, NotificationState } from "../redux/reducers/notifications"; import UserStatus from "../components/common/user/UserStatus"; -import { Link } from "react-router-dom"; import IconButton from "../components/ui/IconButton"; interface ContextMenuData { @@ -438,7 +437,7 @@ function ContextMenus(props: Props) { ]; break; case Users.Relationship.Incoming: - actions = ["add_friend", "block_user"]; + actions = ["add_friend", "cancel_friend", "block_user"]; break; case Users.Relationship.Outgoing: actions = ["cancel_friend", "block_user"]; diff --git a/src/pages/friends/Friend.module.scss b/src/pages/friends/Friend.module.scss index 450abee1..61cd612b 100644 --- a/src/pages/friends/Friend.module.scss +++ b/src/pages/friends/Friend.module.scss @@ -122,6 +122,53 @@ background: var(--primary-background); } +.title { + flex-grow: 1; +} + +.pending { + gap: 12px; + padding: 1em; + display: flex; + cursor: pointer; + margin-top: 1em; + align-items: center; + flex-direction: row; + background: var(--secondary-background); + + .avatars { + display: flex; + } + + .details { + flex-grow: 1; + display: flex; + flex-direction: column; + + > div { + font-size: 1.4em; + font-weight: 800; + + span { + width: 1.5em; + height: 1.5em; + font-size: 0.8em; + + border-radius: 50%; + align-items: center; + display: inline-flex; + justify-content: center; + background: var(--error); + } + } + + > span { + font-weight: 600; + color: var(--tertiary-foreground); + } + } +} + @media only screen and (max-width: 768px) { .list { padding: 0 8px 8px 8px; @@ -131,10 +178,3 @@ display: none; } } - -//! FIXME: Move this to the Header component, do this: -// 1. Check if header has topic, if yes, flex-grow: 0 on the title. -// 2. If header has no topic (example: friends page), flex-grow 1 on the header title. -.title { - flex-grow: 1; -} \ No newline at end of file diff --git a/src/pages/friends/Friend.tsx b/src/pages/friends/Friend.tsx index d50198cc..3dd598b5 100644 --- a/src/pages/friends/Friend.tsx +++ b/src/pages/friends/Friend.tsx @@ -70,7 +70,11 @@ export function Friend({ user }: Props) { actions.push( stopPropagation(ev, openScreen({ id: 'special_prompt', type: 'unfriend_user', target: user }))}> + onClick={ev => stopPropagation(ev, + user.relationship === Users.Relationship.Friend ? + openScreen({ id: 'special_prompt', type: 'unfriend_user', target: user }) + : client.users.removeFriend(user._id) + )}> ); diff --git a/src/pages/friends/Friends.tsx b/src/pages/friends/Friends.tsx index 7ff2a462..83eba1ac 100644 --- a/src/pages/friends/Friends.tsx +++ b/src/pages/friends/Friends.tsx @@ -1,16 +1,17 @@ import { Friend } from "./Friend"; import { Text } from "preact-i18n"; import styles from "./Friend.module.scss"; -import Tooltip from "../../components/common/Tooltip"; import Header from "../../components/ui/Header"; import Overline from "../../components/ui/Overline"; +import Tooltip from "../../components/common/Tooltip"; import IconButton from "../../components/ui/IconButton"; import { useUsers } from "../../context/revoltjs/hooks"; import { User, Users } from "revolt.js/dist/api/objects"; +import UserIcon from "../../components/common/user/UserIcon"; import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice"; import { useIntermediate } from "../../context/intermediate/Intermediate"; import { ChevronDown, ChevronRight } from "@styled-icons/boxicons-regular"; -import { UserDetail, Conversation, UserPlus, TennisBall } from "@styled-icons/boxicons-solid"; +import { UserDetail, Conversation, UserPlus } from "@styled-icons/boxicons-solid"; export default function Friends() { const { openScreen } = useIntermediate(); @@ -22,7 +23,9 @@ export default function Friends() { const lists = [ [ 'app.special.friends.pending', users.filter(x => - x.relationship === Users.Relationship.Incoming || + x.relationship === Users.Relationship.Incoming + ) ], + [ 'app.special.friends.pending', users.filter(x => x.relationship === Users.Relationship.Outgoing ) ], [ 'app.status.online', friends.filter(x => @@ -70,8 +73,23 @@ export default function Friends() { )} + + { lists[0][1].length > 0 &&
openScreen({ id: 'pending_requests', users: lists[0][1].map(x => x._id) })}> +
+ { lists[0][1].map((x, i) => i < 3 && ) } +
+
+ {/* ! FIXME: i18n */} +
Pending requests { lists[0][1].length }
+ From { lists[0][1].map(x => x.username).join(', ') } +
+ +
} + { - lists.map(([i18n, list]) => { + lists.map(([i18n, list], index) => { + if (index === 0) return; if (list.length === 0) return; return ( diff --git a/src/styles/_context-menu.scss b/src/styles/_context-menu.scss index 66df1348..8f33978b 100644 --- a/src/styles/_context-menu.scss +++ b/src/styles/_context-menu.scss @@ -1,5 +1,5 @@ .preact-context-menu .context-menu { - z-index: 100; + z-index: 10000; min-width: 190px; padding: 6px 8px; user-select: none;