mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 02:08:57 +00:00
Make unpin all button work
Co-authored-by: Jamie <113370520+jamiebuilds-signal@users.noreply.github.com>
This commit is contained in:
@@ -1750,6 +1750,22 @@
|
|||||||
"messageformat": "Unpin all messages",
|
"messageformat": "Unpin all messages",
|
||||||
"description": "Conversation > Pinned messages panel (view all) > Unpin all messages button"
|
"description": "Conversation > Pinned messages panel (view all) > Unpin all messages button"
|
||||||
},
|
},
|
||||||
|
"icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Title": {
|
||||||
|
"messageformat": "Unpin all messages?",
|
||||||
|
"description": "Conversation > Pinned messages panel (view all) > Unpin all messages button > Confirm Dialog > Title"
|
||||||
|
},
|
||||||
|
"icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Description--Group": {
|
||||||
|
"messageformat": "Messages will be unpinned for all group members.",
|
||||||
|
"description": "Conversation > Pinned messages panel (view all) > Unpin all messages button > Confirm Dialog > Description (in group)"
|
||||||
|
},
|
||||||
|
"icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Cancel": {
|
||||||
|
"messageformat": "Cancel",
|
||||||
|
"description": "Conversation > Pinned messages panel (view all) > Unpin all messages button > Confirm Dialog > Cancel"
|
||||||
|
},
|
||||||
|
"icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Unpin": {
|
||||||
|
"messageformat": "Unpin",
|
||||||
|
"description": "Conversation > Pinned messages panel (view all) > Unpin all messages button > Confirm Dialog > Unpin"
|
||||||
|
},
|
||||||
"icu:sessionEnded": {
|
"icu:sessionEnded": {
|
||||||
"messageformat": "Secure session reset",
|
"messageformat": "Secure session reset",
|
||||||
"description": "This is a past tense, informational message. In other words, your secure session has been reset."
|
"description": "This is a past tense, informational message. In other words, your secure session has been reset."
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import React, {
|
|||||||
forwardRef,
|
forwardRef,
|
||||||
Fragment,
|
Fragment,
|
||||||
memo,
|
memo,
|
||||||
|
useCallback,
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
@@ -26,12 +27,14 @@ import { useSizeObserver } from '../../../hooks/useSizeObserver.dom.js';
|
|||||||
import { MessageInteractivity } from '../Message.dom.js';
|
import { MessageInteractivity } from '../Message.dom.js';
|
||||||
import { tw } from '../../../axo/tw.dom.js';
|
import { tw } from '../../../axo/tw.dom.js';
|
||||||
import { AxoButton } from '../../../axo/AxoButton.dom.js';
|
import { AxoButton } from '../../../axo/AxoButton.dom.js';
|
||||||
|
import { AxoAlertDialog } from '../../../axo/AxoAlertDialog.dom.js';
|
||||||
|
|
||||||
export type PinnedMessagesPanelProps = Readonly<{
|
export type PinnedMessagesPanelProps = Readonly<{
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
conversation: ConversationType;
|
conversation: ConversationType;
|
||||||
pinnedMessages: ReadonlyArray<PinnedMessageRenderData>;
|
pinnedMessages: ReadonlyArray<PinnedMessageRenderData>;
|
||||||
canPinMessages: boolean;
|
canPinMessages: boolean;
|
||||||
|
onPinnedMessageRemoveAll: () => void;
|
||||||
renderTimelineItem: (props: SmartTimelineItemProps) => JSX.Element;
|
renderTimelineItem: (props: SmartTimelineItemProps) => JSX.Element;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
@@ -44,6 +47,13 @@ export const PinnedMessagesPanel = memo(function PinnedMessagesPanel(
|
|||||||
WidthBreakpoint.Wide
|
WidthBreakpoint.Wide
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [confirmUnpinAllDialogOpen, setConfirmUnpinAllDialogOpen] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
|
const handleClickUnpinAll = useCallback(() => {
|
||||||
|
setConfirmUnpinAllDialogOpen(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
strictAssert(containerElementRef.current, 'Missing container ref');
|
strictAssert(containerElementRef.current, 'Missing container ref');
|
||||||
const container = containerElementRef.current;
|
const container = containerElementRef.current;
|
||||||
@@ -81,11 +91,49 @@ export const PinnedMessagesPanel = memo(function PinnedMessagesPanel(
|
|||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
{props.canPinMessages && (
|
{props.canPinMessages && (
|
||||||
<div className={tw('flex items-center justify-center p-2.5')}>
|
<div className={tw('flex items-center justify-center p-2.5')}>
|
||||||
<AxoButton.Root variant="borderless-primary" size="lg">
|
<AxoButton.Root
|
||||||
|
variant="borderless-primary"
|
||||||
|
size="lg"
|
||||||
|
onClick={handleClickUnpinAll}
|
||||||
|
>
|
||||||
{i18n('icu:PinnedMessagesPanel__UnpinAllMessages')}
|
{i18n('icu:PinnedMessagesPanel__UnpinAllMessages')}
|
||||||
</AxoButton.Root>
|
</AxoButton.Root>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<AxoAlertDialog.Root
|
||||||
|
open={confirmUnpinAllDialogOpen}
|
||||||
|
onOpenChange={setConfirmUnpinAllDialogOpen}
|
||||||
|
>
|
||||||
|
<AxoAlertDialog.Content escape="cancel-is-noop">
|
||||||
|
<AxoAlertDialog.Body>
|
||||||
|
<AxoAlertDialog.Title>
|
||||||
|
{i18n(
|
||||||
|
'icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Title'
|
||||||
|
)}
|
||||||
|
</AxoAlertDialog.Title>
|
||||||
|
<AxoAlertDialog.Description>
|
||||||
|
{i18n(
|
||||||
|
'icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Description--Group'
|
||||||
|
)}
|
||||||
|
</AxoAlertDialog.Description>
|
||||||
|
</AxoAlertDialog.Body>
|
||||||
|
<AxoAlertDialog.Footer>
|
||||||
|
<AxoAlertDialog.Cancel>
|
||||||
|
{i18n(
|
||||||
|
'icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Cancel'
|
||||||
|
)}
|
||||||
|
</AxoAlertDialog.Cancel>
|
||||||
|
<AxoAlertDialog.Action
|
||||||
|
variant="primary"
|
||||||
|
onClick={props.onPinnedMessageRemoveAll}
|
||||||
|
>
|
||||||
|
{i18n(
|
||||||
|
'icu:PinnedMessagesPanel__UnpinAllMessages__ConfirmDialog__Unpin'
|
||||||
|
)}
|
||||||
|
</AxoAlertDialog.Action>
|
||||||
|
</AxoAlertDialog.Footer>
|
||||||
|
</AxoAlertDialog.Content>
|
||||||
|
</AxoAlertDialog.Root>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2025 Signal Messenger, LLC
|
// Copyright 2025 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { memo } from 'react';
|
import React, { memo, useCallback } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { getIntl } from '../selectors/user.std.js';
|
import { getIntl } from '../selectors/user.std.js';
|
||||||
import { getConversationByIdSelector } from '../selectors/conversations.dom.js';
|
import { getConversationByIdSelector } from '../selectors/conversations.dom.js';
|
||||||
@@ -11,6 +11,8 @@ import type { SmartTimelineItemProps } from './TimelineItem.preload.js';
|
|||||||
import { SmartTimelineItem } from './TimelineItem.preload.js';
|
import { SmartTimelineItem } from './TimelineItem.preload.js';
|
||||||
import { getPinnedMessages } from '../selectors/pinnedMessages.dom.js';
|
import { getPinnedMessages } from '../selectors/pinnedMessages.dom.js';
|
||||||
import { canPinMessages as getCanPinMessages } from '../selectors/message.preload.js';
|
import { canPinMessages as getCanPinMessages } from '../selectors/message.preload.js';
|
||||||
|
import { usePinnedMessagesActions } from '../ducks/pinnedMessages.preload.js';
|
||||||
|
import { useConversationsActions } from '../ducks/conversations.preload.js';
|
||||||
|
|
||||||
export type SmartPinnedMessagesPanelProps = Readonly<{
|
export type SmartPinnedMessagesPanelProps = Readonly<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
@@ -26,6 +28,7 @@ export const SmartPinnedMessagesPanel = memo(function SmartPinnedMessagesPanel(
|
|||||||
const i18n = useSelector(getIntl);
|
const i18n = useSelector(getIntl);
|
||||||
const conversationSelector = useSelector(getConversationByIdSelector);
|
const conversationSelector = useSelector(getConversationByIdSelector);
|
||||||
const conversation = conversationSelector(props.conversationId);
|
const conversation = conversationSelector(props.conversationId);
|
||||||
|
const { popPanelForConversation } = useConversationsActions();
|
||||||
|
|
||||||
strictAssert(
|
strictAssert(
|
||||||
conversation,
|
conversation,
|
||||||
@@ -35,6 +38,15 @@ export const SmartPinnedMessagesPanel = memo(function SmartPinnedMessagesPanel(
|
|||||||
const pinnedMessages = useSelector(getPinnedMessages);
|
const pinnedMessages = useSelector(getPinnedMessages);
|
||||||
const canPinMessages = getCanPinMessages(conversation);
|
const canPinMessages = getCanPinMessages(conversation);
|
||||||
|
|
||||||
|
const { onPinnedMessageRemove } = usePinnedMessagesActions();
|
||||||
|
|
||||||
|
const handlePinnedMessageRemoveAll = useCallback(() => {
|
||||||
|
popPanelForConversation();
|
||||||
|
for (const { pinnedMessage } of pinnedMessages) {
|
||||||
|
onPinnedMessageRemove(pinnedMessage.messageId);
|
||||||
|
}
|
||||||
|
}, [popPanelForConversation, pinnedMessages, onPinnedMessageRemove]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PinnedMessagesPanel
|
<PinnedMessagesPanel
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
@@ -42,6 +54,7 @@ export const SmartPinnedMessagesPanel = memo(function SmartPinnedMessagesPanel(
|
|||||||
pinnedMessages={pinnedMessages}
|
pinnedMessages={pinnedMessages}
|
||||||
renderTimelineItem={renderTimelineItem}
|
renderTimelineItem={renderTimelineItem}
|
||||||
canPinMessages={canPinMessages}
|
canPinMessages={canPinMessages}
|
||||||
|
onPinnedMessageRemoveAll={handlePinnedMessageRemoveAll}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user