mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 02:08:57 +00:00
Add pinned message notifications
This commit is contained in:
@@ -3408,6 +3408,14 @@
|
|||||||
"messageformat": "You donated for {recipient}",
|
"messageformat": "You donated for {recipient}",
|
||||||
"description": "Shown to label a donation badge you've sent in notifications and the left pane"
|
"description": "Shown to label a donation badge you've sent in notifications and the left pane"
|
||||||
},
|
},
|
||||||
|
"icu:message--pinned--preview--received": {
|
||||||
|
"messageformat": "{sender} pinned a message",
|
||||||
|
"description": "Shown to label pinned message notification in notifications and the left pane."
|
||||||
|
},
|
||||||
|
"icu:message--pinned--preview--sent": {
|
||||||
|
"messageformat": "You pinned a message",
|
||||||
|
"description": "Shown to label pinned message notification in notifications and the left pane."
|
||||||
|
},
|
||||||
"icu:message--donation": {
|
"icu:message--donation": {
|
||||||
"messageformat": "Donation",
|
"messageformat": "Donation",
|
||||||
"description": "Shown to label the donation badge you've redeemed on another device."
|
"description": "Shown to label the donation badge you've redeemed on another device."
|
||||||
|
|||||||
@@ -232,26 +232,27 @@ function TabTrigger(props: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Content = forwardRef(function Content(
|
type ContentProps = Readonly<{
|
||||||
props: {
|
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
pin: Pin;
|
pin: Pin;
|
||||||
onPinGoTo: (messageId: string) => void;
|
onPinGoTo: (messageId: string) => void;
|
||||||
onPinRemove: (messageId: string) => void;
|
onPinRemove: (messageId: string) => void;
|
||||||
onPinsShowAll: () => void;
|
onPinsShowAll: () => void;
|
||||||
canPinMessages: boolean;
|
canPinMessages: boolean;
|
||||||
},
|
}>;
|
||||||
ref: ForwardedRef<HTMLDivElement>
|
|
||||||
): JSX.Element {
|
const Content = forwardRef(function Content(
|
||||||
const {
|
{
|
||||||
i18n,
|
i18n,
|
||||||
pin,
|
pin,
|
||||||
onPinGoTo,
|
onPinGoTo,
|
||||||
onPinRemove,
|
onPinRemove,
|
||||||
onPinsShowAll,
|
onPinsShowAll,
|
||||||
|
canPinMessages,
|
||||||
...forwardedProps
|
...forwardedProps
|
||||||
} = props;
|
}: ContentProps,
|
||||||
|
ref: ForwardedRef<HTMLDivElement>
|
||||||
|
): JSX.Element {
|
||||||
const handlePinGoTo = useCallback(() => {
|
const handlePinGoTo = useCallback(() => {
|
||||||
onPinGoTo(pin.message.id);
|
onPinGoTo(pin.message.id);
|
||||||
}, [onPinGoTo, pin.message.id]);
|
}, [onPinGoTo, pin.message.id]);
|
||||||
@@ -277,10 +278,10 @@ const Content = forwardRef(function Content(
|
|||||||
{thumbnailUrl != null && <ImageThumbnail url={thumbnailUrl} />}
|
{thumbnailUrl != null && <ImageThumbnail url={thumbnailUrl} />}
|
||||||
<div className={tw('min-w-0 flex-1')}>
|
<div className={tw('min-w-0 flex-1')}>
|
||||||
<h1 className={tw('type-body-small font-semibold text-label-primary')}>
|
<h1 className={tw('type-body-small font-semibold text-label-primary')}>
|
||||||
<UserText text={props.pin.sender.title} />
|
<UserText text={pin.sender.title} />
|
||||||
</h1>
|
</h1>
|
||||||
<p className={tw('me-2 truncate type-body-medium text-label-primary')}>
|
<p className={tw('me-2 truncate type-body-medium text-label-primary')}>
|
||||||
<MessagePreview i18n={i18n} message={props.pin.message} />
|
<MessagePreview i18n={i18n} message={pin.message} />
|
||||||
</p>
|
</p>
|
||||||
<AriaClickable.HiddenTrigger
|
<AriaClickable.HiddenTrigger
|
||||||
aria-label={i18n(
|
aria-label={i18n(
|
||||||
@@ -302,7 +303,7 @@ const Content = forwardRef(function Content(
|
|||||||
/>
|
/>
|
||||||
</AxoDropdownMenu.Trigger>
|
</AxoDropdownMenu.Trigger>
|
||||||
<AxoDropdownMenu.Content>
|
<AxoDropdownMenu.Content>
|
||||||
{props.canPinMessages && (
|
{canPinMessages && (
|
||||||
<AxoDropdownMenu.Item
|
<AxoDropdownMenu.Item
|
||||||
symbol="pin-slash"
|
symbol="pin-slash"
|
||||||
onSelect={handlePinRemove}
|
onSelect={handlePinRemove}
|
||||||
|
|||||||
@@ -93,6 +93,13 @@ export async function onPinnedMessageAdd(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.change?.inserted) {
|
||||||
|
await targetConversation.addNotification('pinned-message-notification', {
|
||||||
|
pinnedMessageId: targetMessage.id,
|
||||||
|
sourceServiceId: props.pinnedByAci,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
window.reduxActions.pinnedMessages.onPinnedMessagesChanged(
|
window.reduxActions.pinnedMessages.onPinnedMessagesChanged(
|
||||||
targetConversation.id
|
targetConversation.id
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1933,7 +1933,8 @@ export class BackupExportStream extends Readable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPinnedMessageNotification(message)) {
|
if (isPinnedMessageNotification(message)) {
|
||||||
throw new Error('unimplemented');
|
// TODO(jamie): Implement backups for pinned messages
|
||||||
|
return { kind: NonBubbleResultKind.Drop };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isProfileChange(message)) {
|
if (isProfileChange(message)) {
|
||||||
|
|||||||
@@ -134,6 +134,11 @@ function onPinnedMessageAdd(
|
|||||||
): StateThunk {
|
): StateThunk {
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
const target = await getPinnedMessageTarget(targetMessageId);
|
const target = await getPinnedMessageTarget(targetMessageId);
|
||||||
|
const targetConversation = window.ConversationController.get(
|
||||||
|
target.conversationId
|
||||||
|
);
|
||||||
|
strictAssert(targetConversation != null, 'Missing target conversation');
|
||||||
|
|
||||||
await conversationJobQueue.add({
|
await conversationJobQueue.add({
|
||||||
type: conversationQueueJobEnum.enum.PinMessage,
|
type: conversationQueueJobEnum.enum.PinMessage,
|
||||||
...target,
|
...target,
|
||||||
@@ -152,6 +157,11 @@ function onPinnedMessageAdd(
|
|||||||
pinnedAt,
|
pinnedAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await targetConversation.addNotification('pinned-message-notification', {
|
||||||
|
pinnedMessageId: targetMessageId,
|
||||||
|
sourceServiceId: itemStorage.user.getCheckedAci(),
|
||||||
|
});
|
||||||
|
|
||||||
dispatch(onPinnedMessagesChanged(target.conversationId));
|
dispatch(onPinnedMessagesChanged(target.conversationId));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -512,7 +512,21 @@ export function getNotificationDataForMessage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPinnedMessageNotification(attributes)) {
|
if (isPinnedMessageNotification(attributes)) {
|
||||||
throw new Error('unimplemented');
|
const fromContact = getAuthor(attributes);
|
||||||
|
const ourAci = itemStorage.user.getCheckedAci();
|
||||||
|
|
||||||
|
let text: string;
|
||||||
|
if (fromContact?.getAci() === ourAci) {
|
||||||
|
text = i18n('icu:message--pinned--preview--sent');
|
||||||
|
} else {
|
||||||
|
const sender = fromContact?.getTitle() ?? i18n('icu:unknownContact');
|
||||||
|
text = i18n('icu:message--pinned--preview--received', { sender });
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
emoji: '📌',
|
||||||
|
text,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { poll } = attributes;
|
const { poll } = attributes;
|
||||||
|
|||||||
Reference in New Issue
Block a user