Mark conversation as unread
Co-authored-by: Sidney Keese <sidney@carbonfive.com>
This commit is contained in:
parent
184f7e1bf3
commit
c408072576
20 changed files with 169 additions and 62 deletions
|
@ -210,11 +210,15 @@
|
||||||
"description": "Shown at the top of the archived conversations list in the left pane"
|
"description": "Shown at the top of the archived conversations list in the left pane"
|
||||||
},
|
},
|
||||||
"archiveConversation": {
|
"archiveConversation": {
|
||||||
"message": "Archive Conversation",
|
"message": "Archive",
|
||||||
"description": "Shown in menu for conversation, and moves conversation out of main conversation list"
|
"description": "Shown in menu for conversation, and moves conversation out of main conversation list"
|
||||||
},
|
},
|
||||||
|
"markUnread": {
|
||||||
|
"message": "Mark as unread",
|
||||||
|
"description": "Shown in menu for conversation, and marks conversation as unread"
|
||||||
|
},
|
||||||
"moveConversationToInbox": {
|
"moveConversationToInbox": {
|
||||||
"message": "Move Conversation to Inbox",
|
"message": "Unarchive",
|
||||||
"description": "Undoes Archive Conversation action, and moves archived conversation back to the main conversation list"
|
"description": "Undoes Archive Conversation action, and moves archived conversation back to the main conversation list"
|
||||||
},
|
},
|
||||||
"pinConversation": {
|
"pinConversation": {
|
||||||
|
@ -1039,7 +1043,7 @@
|
||||||
"description": "Shown on the drop-down menu for an individual message, deletes single message for everyone"
|
"description": "Shown on the drop-down menu for an individual message, deletes single message for everyone"
|
||||||
},
|
},
|
||||||
"deleteMessages": {
|
"deleteMessages": {
|
||||||
"message": "Delete messages",
|
"message": "Delete",
|
||||||
"description": "Menu item for deleting messages, title case."
|
"description": "Menu item for deleting messages, title case."
|
||||||
},
|
},
|
||||||
"deleteConversationConfirmation": {
|
"deleteConversationConfirmation": {
|
||||||
|
@ -2361,6 +2365,10 @@
|
||||||
"message": "Conversation returned to inbox",
|
"message": "Conversation returned to inbox",
|
||||||
"description": "A toast that shows up when the user unarchives a conversation"
|
"description": "A toast that shows up when the user unarchives a conversation"
|
||||||
},
|
},
|
||||||
|
"conversationMarkedUnread": {
|
||||||
|
"message": "Conversation marked unread",
|
||||||
|
"description": "A toast that shows up when user marks a conversation as unread"
|
||||||
|
},
|
||||||
"StickerCreator--title": {
|
"StickerCreator--title": {
|
||||||
"message": "Sticker pack creator",
|
"message": "Sticker pack creator",
|
||||||
"description": "The title of the Sticker Pack Creator window"
|
"description": "The title of the Sticker Pack Creator window"
|
||||||
|
|
|
@ -205,6 +205,8 @@
|
||||||
'private'
|
'private'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
conversation.setMarkedUnread(false);
|
||||||
|
|
||||||
const { openConversationExternal } = window.reduxActions.conversations;
|
const { openConversationExternal } = window.reduxActions.conversations;
|
||||||
if (openConversationExternal) {
|
if (openConversationExternal) {
|
||||||
openConversationExternal(id, messageId);
|
openConversationExternal(id, messageId);
|
||||||
|
|
|
@ -73,20 +73,23 @@ message ContactRecord {
|
||||||
optional bool blocked = 9;
|
optional bool blocked = 9;
|
||||||
optional bool whitelisted = 10;
|
optional bool whitelisted = 10;
|
||||||
optional bool archived = 11;
|
optional bool archived = 11;
|
||||||
|
optional bool markedUnread = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupV1Record {
|
message GroupV1Record {
|
||||||
optional bytes id = 1;
|
optional bytes id = 1;
|
||||||
optional bool blocked = 2;
|
optional bool blocked = 2;
|
||||||
optional bool whitelisted = 3;
|
optional bool whitelisted = 3;
|
||||||
optional bool archived = 4;
|
optional bool archived = 4;
|
||||||
|
optional bool markedUnread = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupV2Record {
|
message GroupV2Record {
|
||||||
optional bytes masterKey = 1;
|
optional bytes masterKey = 1;
|
||||||
optional bool blocked = 2;
|
optional bool blocked = 2;
|
||||||
optional bool whitelisted = 3;
|
optional bool whitelisted = 3;
|
||||||
optional bool archived = 4;
|
optional bool archived = 4;
|
||||||
|
optional bool markedUnread = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AccountRecord {
|
message AccountRecord {
|
||||||
|
@ -112,7 +115,7 @@ message AccountRecord {
|
||||||
optional bool sealedSenderIndicators = 7;
|
optional bool sealedSenderIndicators = 7;
|
||||||
optional bool typingIndicators = 8;
|
optional bool typingIndicators = 8;
|
||||||
optional bool proxiedLinkPreviews = 9;
|
optional bool proxiedLinkPreviews = 9;
|
||||||
optional bool noteToSelfUnread = 10;
|
optional bool noteToSelfMarkedUnread = 10;
|
||||||
optional bool linkPreviews = 11;
|
optional bool linkPreviews = 11;
|
||||||
repeated PinnedConversation pinnedConversations = 14;
|
repeated PinnedConversation pinnedConversations = 14;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
name: overrideProps.name || 'Some Person',
|
name: overrideProps.name || 'Some Person',
|
||||||
type: overrideProps.type || 'direct',
|
type: overrideProps.type || 'direct',
|
||||||
onClick: action('onClick'),
|
onClick: action('onClick'),
|
||||||
|
markedUnread: boolean('markedUnread', overrideProps.markedUnread || false),
|
||||||
lastMessage: overrideProps.lastMessage || {
|
lastMessage: overrideProps.lastMessage || {
|
||||||
text: text('lastMessage.text', 'Hi there!'),
|
text: text('lastMessage.text', 'Hi there!'),
|
||||||
status: select(
|
status: select(
|
||||||
|
@ -137,18 +138,32 @@ story.add('Message Request', () => {
|
||||||
|
|
||||||
story.add('Unread', () => {
|
story.add('Unread', () => {
|
||||||
const counts = [4, 10, 250];
|
const counts = [4, 10, 250];
|
||||||
|
const defaultProps = createProps({
|
||||||
|
lastMessage: {
|
||||||
|
text: 'Hey there!',
|
||||||
|
status: 'delivered',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return counts.map(unreadCount => {
|
const items = counts.map(unreadCount => {
|
||||||
const props = createProps({
|
const props = {
|
||||||
lastMessage: {
|
...defaultProps,
|
||||||
text: 'Hey there!',
|
|
||||||
status: 'delivered',
|
|
||||||
},
|
|
||||||
unreadCount,
|
unreadCount,
|
||||||
});
|
};
|
||||||
|
|
||||||
return <ConversationListItem key={unreadCount} {...props} />;
|
return <ConversationListItem key={unreadCount} {...props} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const markedUnreadProps = {
|
||||||
|
...defaultProps,
|
||||||
|
markedUnread: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const markedUnreadItem = [
|
||||||
|
<ConversationListItem key={5} {...markedUnreadProps} />,
|
||||||
|
];
|
||||||
|
|
||||||
|
return [...items, ...markedUnreadItem];
|
||||||
});
|
});
|
||||||
|
|
||||||
story.add('Selected', () => {
|
story.add('Selected', () => {
|
||||||
|
|
|
@ -37,6 +37,7 @@ export type PropsData = {
|
||||||
|
|
||||||
lastUpdated: number;
|
lastUpdated: number;
|
||||||
unreadCount?: number;
|
unreadCount?: number;
|
||||||
|
markedUnread: boolean;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
|
|
||||||
acceptedMessageRequest?: boolean;
|
acceptedMessageRequest?: boolean;
|
||||||
|
@ -93,13 +94,19 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isUnread(): boolean {
|
||||||
|
const { markedUnread, unreadCount } = this.props;
|
||||||
|
|
||||||
|
return (isNumber(unreadCount) && unreadCount > 0) || markedUnread;
|
||||||
|
}
|
||||||
|
|
||||||
public renderUnread(): JSX.Element | null {
|
public renderUnread(): JSX.Element | null {
|
||||||
const { unreadCount } = this.props;
|
const { unreadCount } = this.props;
|
||||||
|
|
||||||
if (isNumber(unreadCount) && unreadCount > 0) {
|
if (this.isUnread()) {
|
||||||
return (
|
return (
|
||||||
<div className="module-conversation-list-item__unread-count">
|
<div className="module-conversation-list-item__unread-count">
|
||||||
{unreadCount}
|
{unreadCount || ''}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -109,7 +116,6 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
|
|
||||||
public renderHeader(): JSX.Element {
|
public renderHeader(): JSX.Element {
|
||||||
const {
|
const {
|
||||||
unreadCount,
|
|
||||||
i18n,
|
i18n,
|
||||||
isMe,
|
isMe,
|
||||||
lastUpdated,
|
lastUpdated,
|
||||||
|
@ -119,14 +125,12 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
title,
|
title,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const withUnread = isNumber(unreadCount) && unreadCount > 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-conversation-list-item__header">
|
<div className="module-conversation-list-item__header">
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'module-conversation-list-item__header__name',
|
'module-conversation-list-item__header__name',
|
||||||
withUnread
|
this.isUnread()
|
||||||
? 'module-conversation-list-item__header__name--with-unread'
|
? 'module-conversation-list-item__header__name--with-unread'
|
||||||
: null
|
: null
|
||||||
)}
|
)}
|
||||||
|
@ -146,7 +150,7 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'module-conversation-list-item__header__date',
|
'module-conversation-list-item__header__date',
|
||||||
withUnread
|
this.isUnread()
|
||||||
? 'module-conversation-list-item__header__date--has-unread'
|
? 'module-conversation-list-item__header__date--has-unread'
|
||||||
: null
|
: null
|
||||||
)}
|
)}
|
||||||
|
@ -155,7 +159,7 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
timestamp={lastUpdated}
|
timestamp={lastUpdated}
|
||||||
extended={false}
|
extended={false}
|
||||||
module="module-conversation-list-item__header__timestamp"
|
module="module-conversation-list-item__header__timestamp"
|
||||||
withUnread={withUnread}
|
withUnread={this.isUnread()}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -172,14 +176,12 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
muteExpiresAt,
|
muteExpiresAt,
|
||||||
shouldShowDraft,
|
shouldShowDraft,
|
||||||
typingContact,
|
typingContact,
|
||||||
unreadCount,
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
if (!lastMessage && !typingContact) {
|
if (!lastMessage && !typingContact) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageBody = lastMessage ? lastMessage.text : '';
|
const messageBody = lastMessage ? lastMessage.text : '';
|
||||||
const withUnread = isNumber(unreadCount) && unreadCount > 0;
|
|
||||||
const showingDraft = shouldShowDraft && draftPreview;
|
const showingDraft = shouldShowDraft && draftPreview;
|
||||||
const deletedForEveryone = Boolean(
|
const deletedForEveryone = Boolean(
|
||||||
lastMessage && lastMessage.deletedForEveryone
|
lastMessage && lastMessage.deletedForEveryone
|
||||||
|
@ -192,7 +194,7 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
dir="auto"
|
dir="auto"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'module-conversation-list-item__message__text',
|
'module-conversation-list-item__message__text',
|
||||||
withUnread
|
this.isUnread()
|
||||||
? 'module-conversation-list-item__message__text--has-unread'
|
? 'module-conversation-list-item__message__text--has-unread'
|
||||||
: null
|
: null
|
||||||
)}
|
)}
|
||||||
|
@ -249,8 +251,7 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
/* eslint-enable no-nested-ternary */
|
/* eslint-enable no-nested-ternary */
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
const { unreadCount, onClick, id, isSelected, style } = this.props;
|
const { id, isSelected, onClick, style } = this.props;
|
||||||
const withUnread = isNumber(unreadCount) && unreadCount > 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
@ -263,7 +264,7 @@ export class ConversationListItem extends React.PureComponent<Props> {
|
||||||
style={style}
|
style={style}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'module-conversation-list-item',
|
'module-conversation-list-item',
|
||||||
withUnread ? 'module-conversation-list-item--has-unread' : null,
|
this.isUnread() ? 'module-conversation-list-item--has-unread' : null,
|
||||||
isSelected ? 'module-conversation-list-item--is-selected' : null
|
isSelected ? 'module-conversation-list-item--is-selected' : null
|
||||||
)}
|
)}
|
||||||
data-id={cleanId(id)}
|
data-id={cleanId(id)}
|
||||||
|
|
|
@ -18,6 +18,7 @@ const defaultConversations: Array<PropsData> = [
|
||||||
id: 'fred-convo',
|
id: 'fred-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Fred Willard',
|
title: 'Fred Willard',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -25,6 +26,7 @@ const defaultConversations: Array<PropsData> = [
|
||||||
id: 'marc-convo',
|
id: 'marc-convo',
|
||||||
isSelected: true,
|
isSelected: true,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Marc Barraca',
|
title: 'Marc Barraca',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -35,6 +37,7 @@ const defaultArchivedConversations: Array<PropsData> = [
|
||||||
id: 'michelle-archive-convo',
|
id: 'michelle-archive-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Michelle Mercure',
|
title: 'Michelle Mercure',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -46,6 +49,7 @@ const pinnedConversations: Array<PropsData> = [
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Philip Glass',
|
title: 'Philip Glass',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -54,6 +58,7 @@ const pinnedConversations: Array<PropsData> = [
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Robert Moog',
|
title: 'Robert Moog',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -129,6 +134,7 @@ story.add('Search Results', () => {
|
||||||
id: 'fred-convo',
|
id: 'fred-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'People Named Fred',
|
title: 'People Named Fred',
|
||||||
type: 'group',
|
type: 'group',
|
||||||
},
|
},
|
||||||
|
@ -147,6 +153,7 @@ story.add('Search Results', () => {
|
||||||
id: 'fred-contact',
|
id: 'fred-contact',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Fred Willard',
|
title: 'Fred Willard',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
|
|
@ -157,6 +157,7 @@ const conversations = [
|
||||||
text: 'The rabbit hopped silently in the night.',
|
text: 'The rabbit hopped silently in the night.',
|
||||||
status: SENT,
|
status: SENT,
|
||||||
},
|
},
|
||||||
|
markedUnread: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -177,6 +178,7 @@ const conversations = [
|
||||||
text: "What's going on?",
|
text: "What's going on?",
|
||||||
status: SENT,
|
status: SENT,
|
||||||
},
|
},
|
||||||
|
markedUnread: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -196,6 +198,7 @@ const contacts = [
|
||||||
lastUpdated: Date.now() - 10 * 60 * 1000,
|
lastUpdated: Date.now() - 10 * 60 * 1000,
|
||||||
unreadCount: 0,
|
unreadCount: 0,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
|
markedUnread: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -211,6 +214,7 @@ const contacts = [
|
||||||
lastUpdated: Date.now() - 11 * 60 * 1000,
|
lastUpdated: Date.now() - 11 * 60 * 1000,
|
||||||
unreadCount: 0,
|
unreadCount: 0,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
|
markedUnread: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -44,6 +44,7 @@ const actionProps: PropsActionsType = {
|
||||||
onGoBack: action('onGoBack'),
|
onGoBack: action('onGoBack'),
|
||||||
|
|
||||||
onArchive: action('onArchive'),
|
onArchive: action('onArchive'),
|
||||||
|
onMarkUnread: action('onMarkUnread'),
|
||||||
onMoveToInbox: action('onMoveToInbox'),
|
onMoveToInbox: action('onMoveToInbox'),
|
||||||
onSetPin: action('onSetPin'),
|
onSetPin: action('onSetPin'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,6 +36,7 @@ export interface PropsDataType {
|
||||||
isMe?: boolean;
|
isMe?: boolean;
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
isPinned?: boolean;
|
isPinned?: boolean;
|
||||||
|
markedUnread?: boolean;
|
||||||
|
|
||||||
disableTimerChanges?: boolean;
|
disableTimerChanges?: boolean;
|
||||||
expirationSettingName?: string;
|
expirationSettingName?: string;
|
||||||
|
@ -60,6 +61,7 @@ export interface PropsActionsType {
|
||||||
onGoBack: () => void;
|
onGoBack: () => void;
|
||||||
|
|
||||||
onArchive: () => void;
|
onArchive: () => void;
|
||||||
|
onMarkUnread: () => void;
|
||||||
onMoveToInbox: () => void;
|
onMoveToInbox: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +312,7 @@ export class ConversationHeader extends React.Component<PropsType> {
|
||||||
isPinned,
|
isPinned,
|
||||||
type,
|
type,
|
||||||
isArchived,
|
isArchived,
|
||||||
|
markedUnread,
|
||||||
muteExpirationLabel,
|
muteExpirationLabel,
|
||||||
onDeleteMessages,
|
onDeleteMessages,
|
||||||
onResetSession,
|
onResetSession,
|
||||||
|
@ -319,6 +322,7 @@ export class ConversationHeader extends React.Component<PropsType> {
|
||||||
onShowGroupMembers,
|
onShowGroupMembers,
|
||||||
onShowSafetyNumber,
|
onShowSafetyNumber,
|
||||||
onArchive,
|
onArchive,
|
||||||
|
onMarkUnread,
|
||||||
onSetPin,
|
onSetPin,
|
||||||
onMoveToInbox,
|
onMoveToInbox,
|
||||||
timerOptions,
|
timerOptions,
|
||||||
|
@ -350,28 +354,6 @@ export class ConversationHeader extends React.Component<PropsType> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu id={triggerId}>
|
<ContextMenu id={triggerId}>
|
||||||
<SubMenu title={muteTitle}>
|
|
||||||
{muteOptions.map(item => (
|
|
||||||
<MenuItem
|
|
||||||
key={item.name}
|
|
||||||
disabled={item.disabled}
|
|
||||||
onClick={() => {
|
|
||||||
onSetMuteNotifications(item.value);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</SubMenu>
|
|
||||||
{isPinned ? (
|
|
||||||
<MenuItem onClick={() => onSetPin(false)}>
|
|
||||||
{i18n('unpinConversation')}
|
|
||||||
</MenuItem>
|
|
||||||
) : (
|
|
||||||
<MenuItem onClick={() => onSetPin(true)}>
|
|
||||||
{i18n('pinConversation')}
|
|
||||||
</MenuItem>
|
|
||||||
)}
|
|
||||||
{disableTimerChanges ? null : (
|
{disableTimerChanges ? null : (
|
||||||
<SubMenu title={disappearingTitle}>
|
<SubMenu title={disappearingTitle}>
|
||||||
{(timerOptions || []).map(item => (
|
{(timerOptions || []).map(item => (
|
||||||
|
@ -386,21 +368,37 @@ export class ConversationHeader extends React.Component<PropsType> {
|
||||||
))}
|
))}
|
||||||
</SubMenu>
|
</SubMenu>
|
||||||
)}
|
)}
|
||||||
<MenuItem onClick={onShowAllMedia}>{i18n('viewRecentMedia')}</MenuItem>
|
<SubMenu title={muteTitle}>
|
||||||
|
{muteOptions.map(item => (
|
||||||
|
<MenuItem
|
||||||
|
key={item.name}
|
||||||
|
disabled={item.disabled}
|
||||||
|
onClick={() => {
|
||||||
|
onSetMuteNotifications(item.value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</SubMenu>
|
||||||
{isGroup ? (
|
{isGroup ? (
|
||||||
<MenuItem onClick={onShowGroupMembers}>
|
<MenuItem onClick={onShowGroupMembers}>
|
||||||
{i18n('showMembers')}
|
{i18n('showMembers')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
) : null}
|
) : null}
|
||||||
|
<MenuItem onClick={onShowAllMedia}>{i18n('viewRecentMedia')}</MenuItem>
|
||||||
{!isGroup && !isMe ? (
|
{!isGroup && !isMe ? (
|
||||||
<MenuItem onClick={onShowSafetyNumber}>
|
<MenuItem onClick={onShowSafetyNumber}>
|
||||||
{i18n('showSafetyNumber')}
|
{i18n('showSafetyNumber')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
) : null}
|
) : null}
|
||||||
<MenuItem divider />
|
|
||||||
{!isGroup && acceptedMessageRequest ? (
|
{!isGroup && acceptedMessageRequest ? (
|
||||||
<MenuItem onClick={onResetSession}>{i18n('resetSession')}</MenuItem>
|
<MenuItem onClick={onResetSession}>{i18n('resetSession')}</MenuItem>
|
||||||
) : null}
|
) : null}
|
||||||
|
<MenuItem divider />
|
||||||
|
{!markedUnread ? (
|
||||||
|
<MenuItem onClick={onMarkUnread}>{i18n('markUnread')}</MenuItem>
|
||||||
|
) : null}
|
||||||
{isArchived ? (
|
{isArchived ? (
|
||||||
<MenuItem onClick={onMoveToInbox}>
|
<MenuItem onClick={onMoveToInbox}>
|
||||||
{i18n('moveConversationToInbox')}
|
{i18n('moveConversationToInbox')}
|
||||||
|
@ -409,6 +407,15 @@ export class ConversationHeader extends React.Component<PropsType> {
|
||||||
<MenuItem onClick={onArchive}>{i18n('archiveConversation')}</MenuItem>
|
<MenuItem onClick={onArchive}>{i18n('archiveConversation')}</MenuItem>
|
||||||
)}
|
)}
|
||||||
<MenuItem onClick={onDeleteMessages}>{i18n('deleteMessages')}</MenuItem>
|
<MenuItem onClick={onDeleteMessages}>{i18n('deleteMessages')}</MenuItem>
|
||||||
|
{isPinned ? (
|
||||||
|
<MenuItem onClick={() => onSetPin(false)}>
|
||||||
|
{i18n('unpinConversation')}
|
||||||
|
</MenuItem>
|
||||||
|
) : (
|
||||||
|
<MenuItem onClick={() => onSetPin(true)}>
|
||||||
|
{i18n('pinConversation')}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ storiesOf('Components/Conversation/ProfileChangeNotification', module)
|
||||||
title: 'Mr. Fire 🔥',
|
title: 'Mr. Fire 🔥',
|
||||||
name: 'Mr. Fire 🔥',
|
name: 'Mr. Fire 🔥',
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
}}
|
}}
|
||||||
change={{
|
change={{
|
||||||
type: 'name',
|
type: 'name',
|
||||||
|
@ -37,6 +38,7 @@ storiesOf('Components/Conversation/ProfileChangeNotification', module)
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
title: 'Mr. Fire 🔥',
|
title: 'Mr. Fire 🔥',
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
}}
|
}}
|
||||||
change={{
|
change={{
|
||||||
type: 'name',
|
type: 'name',
|
||||||
|
|
1
ts/model-types.d.ts
vendored
1
ts/model-types.d.ts
vendored
|
@ -149,6 +149,7 @@ export type ConversationAttributesType = {
|
||||||
isPinned: boolean;
|
isPinned: boolean;
|
||||||
lastMessageDeletedForEveryone: boolean;
|
lastMessageDeletedForEveryone: boolean;
|
||||||
lastMessageStatus: LastMessageStatus | null;
|
lastMessageStatus: LastMessageStatus | null;
|
||||||
|
markedUnread: boolean;
|
||||||
messageCount: number;
|
messageCount: number;
|
||||||
messageCountBeforeMessageRequests: number;
|
messageCountBeforeMessageRequests: number;
|
||||||
messageRequestResponseType: number;
|
messageRequestResponseType: number;
|
||||||
|
|
|
@ -1137,7 +1137,7 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
deletedForEveryone: this.get('lastMessageDeletedForEveryone')!,
|
deletedForEveryone: this.get('lastMessageDeletedForEveryone')!,
|
||||||
},
|
},
|
||||||
lastUpdated: this.get('timestamp')!,
|
lastUpdated: this.get('timestamp')!,
|
||||||
|
markedUnread: this.get('markedUnread')!,
|
||||||
membersCount: this.isPrivate()
|
membersCount: this.isPrivate()
|
||||||
? undefined
|
? undefined
|
||||||
: (this.get('membersV2')! || this.get('members')! || []).length,
|
: (this.get('membersV2')! || this.get('members')! || []).length,
|
||||||
|
@ -3019,6 +3019,12 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMarkedUnread(markedUnread: boolean): void {
|
||||||
|
this.set({ markedUnread });
|
||||||
|
window.Signal.Data.updateConversation(this.attributes);
|
||||||
|
this.captureChange('markedUnread');
|
||||||
|
}
|
||||||
|
|
||||||
async updateExpirationTimer(
|
async updateExpirationTimer(
|
||||||
providedExpireTimer: number | undefined,
|
providedExpireTimer: number | undefined,
|
||||||
providedSource: unknown,
|
providedSource: unknown,
|
||||||
|
@ -3998,6 +4004,7 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
// [X] blocked
|
// [X] blocked
|
||||||
// [X] whitelisted
|
// [X] whitelisted
|
||||||
// [X] archived
|
// [X] archived
|
||||||
|
// [X] markedUnread
|
||||||
captureChange(property: string): void {
|
captureChange(property: string): void {
|
||||||
if (!window.Signal.RemoteConfig.isEnabled('desktop.storageWrite')) {
|
if (!window.Signal.RemoteConfig.isEnabled('desktop.storageWrite')) {
|
||||||
window.log.info(
|
window.log.info(
|
||||||
|
|
|
@ -113,6 +113,7 @@ export async function toContactRecord(
|
||||||
contactRecord.blocked = conversation.isBlocked();
|
contactRecord.blocked = conversation.isBlocked();
|
||||||
contactRecord.whitelisted = Boolean(conversation.get('profileSharing'));
|
contactRecord.whitelisted = Boolean(conversation.get('profileSharing'));
|
||||||
contactRecord.archived = Boolean(conversation.get('isArchived'));
|
contactRecord.archived = Boolean(conversation.get('isArchived'));
|
||||||
|
contactRecord.markedUnread = Boolean(conversation.get('markedUnread'));
|
||||||
|
|
||||||
applyUnknownFields(contactRecord, conversation);
|
applyUnknownFields(contactRecord, conversation);
|
||||||
|
|
||||||
|
@ -137,6 +138,9 @@ export async function toAccountRecord(
|
||||||
}
|
}
|
||||||
accountRecord.avatarUrl = window.storage.get('avatarUrl') || '';
|
accountRecord.avatarUrl = window.storage.get('avatarUrl') || '';
|
||||||
accountRecord.noteToSelfArchived = Boolean(conversation.get('isArchived'));
|
accountRecord.noteToSelfArchived = Boolean(conversation.get('isArchived'));
|
||||||
|
accountRecord.noteToSelfMarkedUnread = Boolean(
|
||||||
|
conversation.get('markedUnread')
|
||||||
|
);
|
||||||
accountRecord.readReceipts = Boolean(
|
accountRecord.readReceipts = Boolean(
|
||||||
window.storage.get('read-receipt-setting')
|
window.storage.get('read-receipt-setting')
|
||||||
);
|
);
|
||||||
|
@ -218,6 +222,7 @@ export async function toGroupV1Record(
|
||||||
groupV1Record.blocked = conversation.isBlocked();
|
groupV1Record.blocked = conversation.isBlocked();
|
||||||
groupV1Record.whitelisted = Boolean(conversation.get('profileSharing'));
|
groupV1Record.whitelisted = Boolean(conversation.get('profileSharing'));
|
||||||
groupV1Record.archived = Boolean(conversation.get('isArchived'));
|
groupV1Record.archived = Boolean(conversation.get('isArchived'));
|
||||||
|
groupV1Record.markedUnread = Boolean(conversation.get('markedUnread'));
|
||||||
|
|
||||||
applyUnknownFields(groupV1Record, conversation);
|
applyUnknownFields(groupV1Record, conversation);
|
||||||
|
|
||||||
|
@ -236,6 +241,7 @@ export async function toGroupV2Record(
|
||||||
groupV2Record.blocked = conversation.isBlocked();
|
groupV2Record.blocked = conversation.isBlocked();
|
||||||
groupV2Record.whitelisted = Boolean(conversation.get('profileSharing'));
|
groupV2Record.whitelisted = Boolean(conversation.get('profileSharing'));
|
||||||
groupV2Record.archived = Boolean(conversation.get('isArchived'));
|
groupV2Record.archived = Boolean(conversation.get('isArchived'));
|
||||||
|
groupV2Record.markedUnread = Boolean(conversation.get('markedUnread'));
|
||||||
|
|
||||||
applyUnknownFields(groupV2Record, conversation);
|
applyUnknownFields(groupV2Record, conversation);
|
||||||
|
|
||||||
|
@ -386,6 +392,7 @@ export async function mergeGroupV1Record(
|
||||||
|
|
||||||
conversation.set({
|
conversation.set({
|
||||||
isArchived: Boolean(groupV1Record.archived),
|
isArchived: Boolean(groupV1Record.archived),
|
||||||
|
markedUnread: Boolean(groupV1Record.markedUnread),
|
||||||
storageID,
|
storageID,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -446,6 +453,7 @@ export async function mergeGroupV2Record(
|
||||||
|
|
||||||
conversation.set({
|
conversation.set({
|
||||||
isArchived: Boolean(groupV2Record.archived),
|
isArchived: Boolean(groupV2Record.archived),
|
||||||
|
markedUnread: Boolean(groupV2Record.markedUnread),
|
||||||
storageID,
|
storageID,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -537,6 +545,7 @@ export async function mergeContactRecord(
|
||||||
|
|
||||||
conversation.set({
|
conversation.set({
|
||||||
isArchived: Boolean(contactRecord.archived),
|
isArchived: Boolean(contactRecord.archived),
|
||||||
|
markedUnread: Boolean(contactRecord.markedUnread),
|
||||||
storageID,
|
storageID,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -559,6 +568,7 @@ export async function mergeAccountRecord(
|
||||||
avatarUrl,
|
avatarUrl,
|
||||||
linkPreviews,
|
linkPreviews,
|
||||||
noteToSelfArchived,
|
noteToSelfArchived,
|
||||||
|
noteToSelfMarkedUnread,
|
||||||
pinnedConversations: remotelyPinnedConversationClasses,
|
pinnedConversations: remotelyPinnedConversationClasses,
|
||||||
profileKey,
|
profileKey,
|
||||||
readReceipts,
|
readReceipts,
|
||||||
|
@ -734,6 +744,7 @@ export async function mergeAccountRecord(
|
||||||
|
|
||||||
conversation.set({
|
conversation.set({
|
||||||
isArchived: Boolean(noteToSelfArchived),
|
isArchived: Boolean(noteToSelfArchived),
|
||||||
|
markedUnread: Boolean(noteToSelfMarkedUnread),
|
||||||
storageID,
|
storageID,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ export type ConversationType = {
|
||||||
text: string;
|
text: string;
|
||||||
deletedForEveryone?: boolean;
|
deletedForEveryone?: boolean;
|
||||||
};
|
};
|
||||||
|
markedUnread: boolean;
|
||||||
phoneNumber?: string;
|
phoneNumber?: string;
|
||||||
membersCount?: number;
|
membersCount?: number;
|
||||||
muteExpiresAt?: number;
|
muteExpiresAt?: number;
|
||||||
|
|
|
@ -36,6 +36,7 @@ describe('LeftPane', () => {
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Philip Glass',
|
title: 'Philip Glass',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -44,6 +45,7 @@ describe('LeftPane', () => {
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Robert Moog',
|
title: 'Robert Moog',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -70,6 +72,7 @@ describe('LeftPane', () => {
|
||||||
id: 'fred-convo',
|
id: 'fred-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Fred Willard',
|
title: 'Fred Willard',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -78,6 +81,7 @@ describe('LeftPane', () => {
|
||||||
isPinned: false,
|
isPinned: false,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Robert Moog',
|
title: 'Robert Moog',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -104,6 +108,7 @@ describe('LeftPane', () => {
|
||||||
id: 'fred-convo',
|
id: 'fred-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Fred Willard',
|
title: 'Fred Willard',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -114,6 +119,7 @@ describe('LeftPane', () => {
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Philip Glass',
|
title: 'Philip Glass',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -148,6 +154,7 @@ describe('LeftPane', () => {
|
||||||
id: 'jerry-convo',
|
id: 'jerry-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Jerry Jordan',
|
title: 'Jerry Jordan',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -157,6 +164,7 @@ describe('LeftPane', () => {
|
||||||
id: 'fred-convo',
|
id: 'fred-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Fred Willard',
|
title: 'Fred Willard',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
@ -179,6 +187,7 @@ describe('LeftPane', () => {
|
||||||
id: 'fred-convo',
|
id: 'fred-convo',
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
lastUpdated: Date.now(),
|
lastUpdated: Date.now(),
|
||||||
|
markedUnread: false,
|
||||||
title: 'Fred Willard',
|
title: 'Fred Willard',
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,6 +41,7 @@ describe('state/selectors/conversations', () => {
|
||||||
inboxPosition: 0,
|
inboxPosition: 0,
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
@ -65,6 +66,7 @@ describe('state/selectors/conversations', () => {
|
||||||
inboxPosition: 21,
|
inboxPosition: 21,
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
@ -89,6 +91,7 @@ describe('state/selectors/conversations', () => {
|
||||||
inboxPosition: 22,
|
inboxPosition: 22,
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
@ -113,6 +116,7 @@ describe('state/selectors/conversations', () => {
|
||||||
inboxPosition: 20,
|
inboxPosition: 20,
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
@ -137,6 +141,7 @@ describe('state/selectors/conversations', () => {
|
||||||
inboxPosition: 30,
|
inboxPosition: 30,
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
@ -185,6 +190,7 @@ describe('state/selectors/conversations', () => {
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
@ -210,6 +216,7 @@ describe('state/selectors/conversations', () => {
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
@ -235,6 +242,7 @@ describe('state/selectors/conversations', () => {
|
||||||
phoneNumber: 'notused',
|
phoneNumber: 'notused',
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isPinned: true,
|
isPinned: true,
|
||||||
|
markedUnread: false,
|
||||||
|
|
||||||
type: 'direct',
|
type: 'direct',
|
||||||
isMe: false,
|
isMe: false,
|
||||||
|
|
4
ts/textsecure.d.ts
vendored
4
ts/textsecure.d.ts
vendored
|
@ -929,6 +929,7 @@ export declare class ContactRecordClass {
|
||||||
blocked?: boolean | null;
|
blocked?: boolean | null;
|
||||||
whitelisted?: boolean | null;
|
whitelisted?: boolean | null;
|
||||||
archived?: boolean | null;
|
archived?: boolean | null;
|
||||||
|
markedUnread?: boolean;
|
||||||
|
|
||||||
__unknownFields?: ArrayBuffer;
|
__unknownFields?: ArrayBuffer;
|
||||||
}
|
}
|
||||||
|
@ -944,6 +945,7 @@ export declare class GroupV1RecordClass {
|
||||||
blocked?: boolean | null;
|
blocked?: boolean | null;
|
||||||
whitelisted?: boolean | null;
|
whitelisted?: boolean | null;
|
||||||
archived?: boolean | null;
|
archived?: boolean | null;
|
||||||
|
markedUnread?: boolean;
|
||||||
|
|
||||||
__unknownFields?: ArrayBuffer;
|
__unknownFields?: ArrayBuffer;
|
||||||
}
|
}
|
||||||
|
@ -959,6 +961,7 @@ export declare class GroupV2RecordClass {
|
||||||
blocked?: boolean | null;
|
blocked?: boolean | null;
|
||||||
whitelisted?: boolean | null;
|
whitelisted?: boolean | null;
|
||||||
archived?: boolean | null;
|
archived?: boolean | null;
|
||||||
|
markedUnread?: boolean;
|
||||||
|
|
||||||
__unknownFields?: ArrayBuffer;
|
__unknownFields?: ArrayBuffer;
|
||||||
}
|
}
|
||||||
|
@ -995,6 +998,7 @@ export declare class AccountRecordClass {
|
||||||
typingIndicators?: boolean | null;
|
typingIndicators?: boolean | null;
|
||||||
linkPreviews?: boolean | null;
|
linkPreviews?: boolean | null;
|
||||||
pinnedConversations?: PinnedConversationClass[];
|
pinnedConversations?: PinnedConversationClass[];
|
||||||
|
noteToSelfMarkedUnread?: boolean;
|
||||||
|
|
||||||
__unknownFields?: ArrayBuffer;
|
__unknownFields?: ArrayBuffer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -631,7 +631,7 @@
|
||||||
"rule": "jQuery-$(",
|
"rule": "jQuery-$(",
|
||||||
"path": "js/views/inbox_view.js",
|
"path": "js/views/inbox_view.js",
|
||||||
"line": " if (e && this.$(e.target).closest('.capture-audio').length > 0) {",
|
"line": " if (e && this.$(e.target).closest('.capture-audio').length > 0) {",
|
||||||
"lineNumber": 217,
|
"lineNumber": 219,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2020-05-29T18:29:18.234Z",
|
"updated": "2020-05-29T18:29:18.234Z",
|
||||||
"reasonDetail": "Known DOM elements"
|
"reasonDetail": "Known DOM elements"
|
||||||
|
@ -640,7 +640,7 @@
|
||||||
"rule": "jQuery-$(",
|
"rule": "jQuery-$(",
|
||||||
"path": "js/views/inbox_view.js",
|
"path": "js/views/inbox_view.js",
|
||||||
"line": " this.$('.conversation:first .recorder').trigger('close');",
|
"line": " this.$('.conversation:first .recorder').trigger('close');",
|
||||||
"lineNumber": 220,
|
"lineNumber": 222,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2020-05-29T18:29:18.234Z",
|
"updated": "2020-05-29T18:29:18.234Z",
|
||||||
"reasonDetail": "Hardcoded selector"
|
"reasonDetail": "Hardcoded selector"
|
||||||
|
@ -14703,7 +14703,7 @@
|
||||||
"rule": "React-createRef",
|
"rule": "React-createRef",
|
||||||
"path": "ts/components/conversation/ConversationHeader.tsx",
|
"path": "ts/components/conversation/ConversationHeader.tsx",
|
||||||
"line": " this.menuTriggerRef = React.createRef();",
|
"line": " this.menuTriggerRef = React.createRef();",
|
||||||
"lineNumber": 84,
|
"lineNumber": 86,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2020-05-20T20:10:43.540Z",
|
"updated": "2020-05-20T20:10:43.540Z",
|
||||||
"reasonDetail": "Used to reference popup menu"
|
"reasonDetail": "Used to reference popup menu"
|
||||||
|
@ -15116,4 +15116,4 @@
|
||||||
"reasonCategory": "falseMatch",
|
"reasonCategory": "falseMatch",
|
||||||
"updated": "2020-09-08T23:07:22.682Z"
|
"updated": "2020-09-08T23:07:22.682Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -115,6 +115,12 @@ Whisper.ConversationUnarchivedToast = Whisper.ToastView.extend({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Whisper.ConversationMarkedUnreadToast = Whisper.ToastView.extend({
|
||||||
|
render_attributes() {
|
||||||
|
return { toastMessage: window.i18n('conversationMarkedUnread') };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
Whisper.TapToViewExpiredIncomingToast = Whisper.ToastView.extend({
|
Whisper.TapToViewExpiredIncomingToast = Whisper.ToastView.extend({
|
||||||
render_attributes() {
|
render_attributes() {
|
||||||
return {
|
return {
|
||||||
|
@ -544,6 +550,14 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
document.body
|
document.body
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
onMarkUnread: () => {
|
||||||
|
this.model.setMarkedUnread(true);
|
||||||
|
|
||||||
|
Whisper.ToastView.show(
|
||||||
|
Whisper.ConversationMarkedUnreadToast,
|
||||||
|
document.body
|
||||||
|
);
|
||||||
|
},
|
||||||
onMoveToInbox: () => {
|
onMoveToInbox: () => {
|
||||||
this.model.setArchived(false);
|
this.model.setArchived(false);
|
||||||
|
|
||||||
|
@ -3057,6 +3071,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
);
|
);
|
||||||
|
|
||||||
this.compositionApi.current.reset();
|
this.compositionApi.current.reset();
|
||||||
|
this.model.setMarkedUnread(false);
|
||||||
this.setQuoteMessage(null);
|
this.setQuoteMessage(null);
|
||||||
this.resetLinkPreview();
|
this.resetLinkPreview();
|
||||||
this.clearAttachments();
|
this.clearAttachments();
|
||||||
|
|
1
ts/window.d.ts
vendored
1
ts/window.d.ts
vendored
|
@ -545,6 +545,7 @@ export type WhisperType = {
|
||||||
};
|
};
|
||||||
ConversationArchivedToast: WhatIsThis;
|
ConversationArchivedToast: WhatIsThis;
|
||||||
ConversationUnarchivedToast: WhatIsThis;
|
ConversationUnarchivedToast: WhatIsThis;
|
||||||
|
ConversationMarkedUnreadToast: WhatIsThis;
|
||||||
AppView: WhatIsThis;
|
AppView: WhatIsThis;
|
||||||
WallClockListener: WhatIsThis;
|
WallClockListener: WhatIsThis;
|
||||||
MessageRequests: WhatIsThis;
|
MessageRequests: WhatIsThis;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue