From 6cd30d893a0df249de5f75db152f888f3cc3f7a7 Mon Sep 17 00:00:00 2001 From: Hampus Date: Mon, 24 Aug 2026 12:51:25 +0200 Subject: [PATCH] feat(app): let the pinned messages popout be resized (#1948) --- .../popouts/ChannelPinsPopout.module.css | 14 ++-- .../components/popouts/ChannelPinsPopout.tsx | 76 ++++++++++++++++++- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.module.css b/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.module.css index 5853bdada..767c2450d 100644 --- a/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.module.css +++ b/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.module.css @@ -1,14 +1,11 @@ /* SPDX-License-Identifier: AGPL-3.0-or-later */ .container { - --pins-popout-max-height: min(calc(100vh - 7.5rem), 45rem); --pins-popout-header-height: 4.25rem; position: relative; display: flex; - width: 30rem; flex-direction: column; - min-height: 12.5rem; - max-height: var(--pins-popout-max-height); + box-sizing: border-box; overflow: hidden; border-radius: 0.5rem; border: 0.0625rem solid var(--background-modifier-accent); @@ -28,10 +25,8 @@ flex: 1 1 0%; display: flex; flex-direction: column; - height: 100%; min-height: 0; overflow: hidden; - max-height: calc(var(--pins-popout-max-height) - var(--pins-popout-header-height)); } .title { @@ -46,3 +41,10 @@ width: 1.5rem; color: var(--text-primary-muted); } + +:global(html.channel-pins-popout-resizing), +:global(html.channel-pins-popout-resizing) * { + cursor: var(--channel-pins-popout-resize-cursor, nwse-resize) !important; + user-select: none !important; + -webkit-user-select: none !important; +} diff --git a/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.tsx b/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.tsx index 929e6e546..3b8a7f6b1 100644 --- a/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.tsx +++ b/fluxer_app/src/features/channel/components/popouts/ChannelPinsPopout.tsx @@ -3,19 +3,88 @@ import {ChannelPinsContent} from '@app/features/app/components/shared/ChannelPinsContent'; import styles from '@app/features/channel/components/popouts/ChannelPinsPopout.module.css'; import type {Channel} from '@app/features/channel/models/Channel'; +import {remFromPx} from '@app/features/theme/layout/RemFromPx'; +import {RESIZABLE_PANE_DEFAULT_VIEWPORT_PADDING, useResizablePane} from '@app/features/ui/hooks/useResizablePane'; +import { + type ResizablePaneHandleLabels, + ResizablePaneHandles, +} from '@app/features/ui/resizable_pane/ResizablePaneHandles'; import {msg} from '@lingui/core/macro'; import {useLingui} from '@lingui/react/macro'; import {PushPinIcon} from '@phosphor-icons/react'; import {observer} from 'mobx-react-lite'; +import {useRef} from 'react'; const PINNED_MESSAGES_DESCRIPTOR = msg({ message: 'Pinned messages', comment: 'Button or menu action label in the channel pins popout. Keep it concise.', }); +const RESIZE_PINS_TOP_DESCRIPTOR = msg({ + message: 'Resize pinned messages from the top edge', + comment: 'Accessible label for the top resize handle on the channel pins popout.', +}); +const RESIZE_PINS_BOTTOM_DESCRIPTOR = msg({ + message: 'Resize pinned messages from the bottom edge', + comment: 'Accessible label for the bottom resize handle on the channel pins popout.', +}); +const RESIZE_PINS_LEFT_DESCRIPTOR = msg({ + message: 'Resize pinned messages from the left edge', + comment: 'Accessible label for the left resize handle on the channel pins popout.', +}); +const RESIZE_PINS_RIGHT_DESCRIPTOR = msg({ + message: 'Resize pinned messages from the right edge', + comment: 'Accessible label for the right resize handle on the channel pins popout.', +}); +const RESIZE_PINS_TOP_LEFT_DESCRIPTOR = msg({ + message: 'Resize pinned messages from top left', + comment: 'Accessible label for the top-left resize handle on the channel pins popout.', +}); +const RESIZE_PINS_TOP_RIGHT_DESCRIPTOR = msg({ + message: 'Resize pinned messages from top right', + comment: 'Accessible label for the top-right resize handle on the channel pins popout.', +}); +const RESIZE_PINS_BOTTOM_LEFT_DESCRIPTOR = msg({ + message: 'Resize pinned messages from bottom left', + comment: 'Accessible label for the bottom-left resize handle on the channel pins popout.', +}); +const RESIZE_PINS_BOTTOM_RIGHT_DESCRIPTOR = msg({ + message: 'Resize pinned messages from bottom right', + comment: 'Accessible label for the bottom-right resize handle on the channel pins popout.', +}); + +const CHANNEL_PINS_POPOUT_DEFAULT_SIZE = {width: 480, height: 640}; +const CHANNEL_PINS_POPOUT_MIN_SIZE = {width: 320, height: 200}; +const CHANNEL_PINS_POPOUT_RESIZING_CLASS = 'channel-pins-popout-resizing'; +const CHANNEL_PINS_POPOUT_RESIZE_CURSOR_PROPERTY = '--channel-pins-popout-resize-cursor'; +const CHANNEL_PINS_RESIZE_HANDLE_LABELS: ResizablePaneHandleLabels = { + top: RESIZE_PINS_TOP_DESCRIPTOR, + bottom: RESIZE_PINS_BOTTOM_DESCRIPTOR, + left: RESIZE_PINS_LEFT_DESCRIPTOR, + right: RESIZE_PINS_RIGHT_DESCRIPTOR, + 'top-left': RESIZE_PINS_TOP_LEFT_DESCRIPTOR, + 'top-right': RESIZE_PINS_TOP_RIGHT_DESCRIPTOR, + 'bottom-left': RESIZE_PINS_BOTTOM_LEFT_DESCRIPTOR, + 'bottom-right': RESIZE_PINS_BOTTOM_RIGHT_DESCRIPTOR, +}; + export const ChannelPinsPopout = observer(({channel, onClose}: {channel: Channel; onClose?: () => void}) => { const {i18n} = useLingui(); + const containerRef = useRef(null); + const {size, getHandleProps} = useResizablePane(containerRef, { + storageKey: 'fluxer:ui:channel-pins-popout-size', + defaultSize: CHANNEL_PINS_POPOUT_DEFAULT_SIZE, + minSize: CHANNEL_PINS_POPOUT_MIN_SIZE, + viewportPadding: RESIZABLE_PANE_DEFAULT_VIEWPORT_PADDING, + resizingClassName: CHANNEL_PINS_POPOUT_RESIZING_CLASS, + cursorProperty: CHANNEL_PINS_POPOUT_RESIZE_CURSOR_PROPERTY, + }); return ( -
+

@@ -29,6 +98,11 @@ export const ChannelPinsPopout = observer(({channel, onClose}: {channel: Channel data-flx="channel.channel-pins-popout.channel-pins-content" />

+
); });