Move link notification to the conversation hero

This commit is contained in:
Josh Perez 2022-04-25 17:03:24 -04:00 committed by GitHub
parent 5f3a62cbb6
commit 2f44e33c9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 174 additions and 350 deletions

View file

@ -2132,103 +2132,6 @@ button.ConversationDetails__action-button {
color: $color-gray-45;
}
// Module: Conversation Hero
.module-conversation-hero {
padding: 32px 0 28px 0;
text-align: center;
&__avatar {
margin-bottom: 12px;
}
&__profile-name {
@include font-title-2;
margin-bottom: 2px;
@include light-theme {
color: $color-gray-90;
}
@include dark-theme {
color: $color-gray-05;
}
}
&__with {
@include font-body-2;
margin: 0 auto;
margin-bottom: 16px;
max-width: 500px;
@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
}
&__membership {
@include font-body-2;
padding: 0 16px;
@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
&__name {
@include font-body-2-bold;
}
}
&__message-request-warning {
@include font-body-2;
&__message {
display: flex;
margin-bottom: 12px;
align-items: center;
justify-content: center;
user-select: none;
@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
&::before {
content: '';
display: block;
height: 14px;
margin-right: 8px;
width: 14px;
@include light-theme {
@include color-svg(
'../images/icons/v2/info-outline-24.svg',
$color-gray-60
);
}
@include dark-theme {
@include color-svg(
'../images/icons/v2/info-solid-24.svg',
$color-gray-25
);
}
}
}
}
}
// Module: Message Request Actions
.module-message-request-actions {

View file

@ -0,0 +1,125 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
.module-conversation-hero {
padding: 32px 0 28px 0;
text-align: center;
&__avatar {
margin-bottom: 12px;
}
&__profile-name {
@include font-title-2;
margin-bottom: 2px;
@include light-theme {
color: $color-gray-90;
}
@include dark-theme {
color: $color-gray-05;
}
}
&__with {
@include font-body-2;
margin: 0 auto;
margin-bottom: 16px;
max-width: 500px;
@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
}
&__membership {
@include font-body-2;
padding: 0 16px;
@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
&__name {
@include font-body-2-bold;
}
}
&__message-request-warning {
@include font-body-2;
&__message {
display: flex;
margin-bottom: 12px;
align-items: center;
justify-content: center;
user-select: none;
@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
&::before {
content: '';
display: block;
height: 14px;
margin-right: 8px;
width: 14px;
@include light-theme {
@include color-svg(
'../images/icons/v2/info-outline-24.svg',
$color-gray-60
);
}
@include dark-theme {
@include color-svg(
'../images/icons/v2/info-solid-24.svg',
$color-gray-25
);
}
}
}
}
&__linkNotification {
@include font-body-2;
text-align: center;
user-select: none;
&::before {
content: '';
display: inline-block;
height: 16px;
margin-right: 8px;
vertical-align: middle;
width: 16px;
@include light-theme {
@include color-svg(
'../images/icons/v2/info-outline-24.svg',
$color-gray-60
);
}
@include dark-theme {
@include color-svg(
'../images/icons/v2/info-solid-24.svg',
$color-gray-25
);
}
}
}
}

View file

@ -219,13 +219,6 @@
);
}
&--icon-unsynced::before {
@include system-message-icon(
'../images/icons/v2/info-outline-24.svg',
'../images/icons/v2/info-solid-24.svg'
);
}
&--icon-verified::before {
@include system-message-icon(
'../images/icons/v2/check-24.svg',

View file

@ -57,6 +57,7 @@
@import './components/ContextMenu.scss';
@import './components/ConversationDetails.scss';
@import './components/ConversationHeader.scss';
@import './components/ConversationHero.scss';
@import './components/ConversationView.scss';
@import './components/CustomColorEditor.scss';
@import './components/CustomizingPreferredReactionsModal.scss';

View file

@ -2178,9 +2178,6 @@ export async function startApp(): Promise<void> {
);
}
log.info('firstRun: disabling post link experience');
window.Signal.Util.postLinkExperience.stop();
// Switch to inbox view even if contact sync is still running
if (
window.reduxStore.getState().app.appView === AppViewType.Installer
@ -2647,13 +2644,6 @@ export async function startApp(): Promise<void> {
}
);
}
if (window.Signal.Util.postLinkExperience.isActive()) {
log.info(
'onContactReceived: Adding the message history disclaimer on link'
);
await conversation.addMessageHistoryDisclaimer();
}
} catch (error) {
log.error('onContactReceived error:', Errors.toLogFormat(error));
}
@ -2722,12 +2712,6 @@ export async function startApp(): Promise<void> {
window.Signal.Data.updateConversation(conversation.attributes);
if (window.Signal.Util.postLinkExperience.isActive()) {
log.info(
'onGroupReceived: Adding the message history disclaimer on link'
);
await conversation.addMessageHistoryDisclaimer();
}
const { expireTimer } = details;
const isValidExpireTimer = typeof expireTimer === 'number';
if (!isValidExpireTimer) {

View file

@ -204,6 +204,9 @@ export const ConversationHero = ({
phoneNumber,
sharedGroupNames,
})}
<div className="module-conversation-hero__linkNotification">
{i18n('messageHistoryUnsynced')}
</div>
</div>
{isShowingMessageRequestWarning && (
<ConfirmationDialog

View file

@ -1,16 +0,0 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { setupI18n } from '../../util/setupI18n';
import enMessages from '../../../_locales/en/messages.json';
import { LinkNotification } from './LinkNotification';
const story = storiesOf('Components/Conversation/LinkNotification', module);
const i18n = setupI18n('en', enMessages);
story.add('Default', () => <LinkNotification i18n={i18n} />);

View file

@ -1,13 +0,0 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { SystemMessage } from './SystemMessage';
import type { LocalizerType } from '../../types/Util';
export const LinkNotification = ({
i18n,
}: Readonly<{ i18n: LocalizerType }>): JSX.Element => (
<SystemMessage icon="unsynced" contents={i18n('messageHistoryUnsynced')} />
);

View file

@ -337,11 +337,6 @@ const items: Record<string, TimelineItemType> = {
},
timestamp: Date.now(),
},
'id-15': {
type: 'linkNotification',
data: null,
timestamp: Date.now(),
},
};
const actions = () => ({

View file

@ -417,10 +417,6 @@ storiesOf('Components/Conversation/TimelineItem', module)
startedTime: Date.now(),
},
},
{
type: 'linkNotification',
data: null,
},
{
type: 'profileChange',
data: {

View file

@ -23,7 +23,6 @@ import type {
PropsDataType as DeliveryIssueProps,
} from './DeliveryIssueNotification';
import { DeliveryIssueNotification } from './DeliveryIssueNotification';
import { LinkNotification } from './LinkNotification';
import type { PropsData as ChangeNumberNotificationProps } from './ChangeNumberNotification';
import { ChangeNumberNotification } from './ChangeNumberNotification';
import type { CallingNotificationType } from '../../util/callingNotification';
@ -69,10 +68,6 @@ type DeliveryIssueType = {
type: 'deliveryIssue';
data: DeliveryIssueProps;
};
type LinkNotificationType = {
type: 'linkNotification';
data: null;
};
type MessageType = {
type: 'message';
data: Omit<MessageProps, 'renderingContext'>;
@ -129,7 +124,6 @@ export type TimelineItemType = (
| GroupNotificationType
| GroupV1MigrationType
| GroupV2ChangeType
| LinkNotificationType
| MessageType
| ProfileChangeNotificationType
| ResetSessionNotificationType
@ -261,8 +255,6 @@ export class TimelineItem extends React.PureComponent<PropsType> {
i18n={i18n}
/>
);
} else if (item.type === 'linkNotification') {
notification = <LinkNotification i18n={i18n} />;
} else if (item.type === 'timerNotification') {
notification = (
<TimerNotification {...this.props} {...item.data} i18n={i18n} />

1
ts/model-types.d.ts vendored
View file

@ -171,7 +171,6 @@ export type MessageAttributesType = {
| 'group-v2-change'
| 'incoming'
| 'keychange'
| 'message-history-unsynced'
| 'outgoing'
| 'profile-change'
| 'story'

View file

@ -219,8 +219,6 @@ export class ConversationModel extends window.Backbone
private isFetchingUUID?: boolean;
private hasAddedHistoryDisclaimer?: boolean;
private lastIsTyping?: boolean;
private muteTimer?: NodeJS.Timer;
@ -4578,38 +4576,6 @@ export class ConversationModel extends window.Backbone
return message;
}
async addMessageHistoryDisclaimer(): Promise<void> {
const timestamp = Date.now();
if (this.hasAddedHistoryDisclaimer) {
log.warn(
`addMessageHistoryDisclaimer/${this.idForLogging()}: Refusing to add another this session`
);
return;
}
this.hasAddedHistoryDisclaimer = true;
const model = new window.Whisper.Message({
type: 'message-history-unsynced',
readStatus: ReadStatus.Read,
seenStatus: SeenStatus.NotApplicable,
conversationId: this.id,
sent_at: timestamp,
received_at: window.Signal.Util.incrementMessageCounter(),
received_at_ms: timestamp,
// TODO: DESKTOP-722
} as unknown as MessageAttributesType);
const id = await window.Signal.Data.saveMessage(model.attributes, {
ourUuid: window.textsecure.storage.user.getCheckedUuid().toString(),
});
model.set({ id });
const message = window.MessageController.register(id, model);
this.addSingleMessage(message);
}
isSearchable(): boolean {
return !this.get('left');
}

View file

@ -91,7 +91,6 @@ import {
isGroupV2Change,
isIncoming,
isKeyChange,
isMessageHistoryUnsynced,
isOutgoing,
isStory,
isProfileChange,
@ -295,7 +294,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
!isGroupV2Change(attributes) &&
!isGroupV1Migration(attributes) &&
!isKeyChange(attributes) &&
!isMessageHistoryUnsynced(attributes) &&
!isProfileChange(attributes) &&
!isUniversalTimerNotification(attributes) &&
!isUnsupportedMessage(attributes) &&
@ -1056,7 +1054,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
// Locally-generated notifications
const isKeyChangeValue = isKeyChange(attributes);
const isMessageHistoryUnsyncedValue = isMessageHistoryUnsynced(attributes);
const isProfileChangeValue = isProfileChange(attributes);
const isUniversalTimerNotificationValue =
isUniversalTimerNotification(attributes);
@ -1085,7 +1082,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
hasErrorsValue ||
// Locally-generated notifications
isKeyChangeValue ||
isMessageHistoryUnsyncedValue ||
isProfileChangeValue ||
isUniversalTimerNotificationValue;

View file

@ -1111,16 +1111,6 @@ export async function mergeAccountRecord(
remotelyPinnedConversations.forEach(conversation => {
conversation.set({ isPinned: true, isArchived: false });
if (
window.Signal.Util.postLinkExperience.isActive() &&
isGroupV2(conversation.attributes)
) {
log.info(
'mergeAccountRecord: Adding the message history disclaimer on link'
);
conversation.addMessageHistoryDisclaimer();
}
updatedConversations.push(conversation);
});

View file

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Database } from 'better-sqlite3';

View file

@ -0,0 +1,29 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Database } from 'better-sqlite3';
import type { LoggerType } from '../../types/Logging';
export default function updateToSchemaVersion57(
currentVersion: number,
db: Database,
logger: LoggerType
): void {
if (currentVersion >= 57) {
return;
}
db.transaction(() => {
db.exec(
`
DELETE FROM messages
WHERE type IS 'message-history-unsynced';
`
);
db.pragma('user_version = 57');
})();
logger.info('updateToSchemaVersion57: success!');
}

View file

@ -32,6 +32,7 @@ import updateToSchemaVersion53 from './53-gv2-banned-members';
import updateToSchemaVersion54 from './54-unprocessed-received-at-counter';
import updateToSchemaVersion55 from './55-report-message-aci';
import updateToSchemaVersion56 from './56-add-unseen-to-message';
import updateToSchemaVersion57 from './57-rm-message-history-unsynced';
function updateToSchemaVersion1(
currentVersion: number,
@ -1927,6 +1928,7 @@ export const SCHEMA_VERSIONS = [
updateToSchemaVersion54,
updateToSchemaVersion55,
updateToSchemaVersion56,
updateToSchemaVersion57,
];
export function updateSchema(db: Database, logger: LoggerType): void {

View file

@ -785,13 +785,6 @@ export function getPropsForBubble(
timestamp,
};
}
if (isMessageHistoryUnsynced(message)) {
return {
type: 'linkNotification',
data: null,
timestamp,
};
}
if (isExpirationTimerUpdate(message)) {
return {
type: 'timerNotification',
@ -984,14 +977,6 @@ function getPropsForGroupV1Migration(
};
}
// Message History Unsynced
export function isMessageHistoryUnsynced(
message: MessageWithUIFieldsType
): boolean {
return message.type === 'message-history-unsynced';
}
// Note: props are null!
// Expiration Timer Update

View file

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { ComponentProps, ReactElement } from 'react';
@ -193,8 +193,6 @@ export function SmartInstallScreen(): ReactElement {
throw new Error('Cannot confirm number; the component was unmounted');
}
window.Signal.Util.postLinkExperience.start();
return result;
};

View file

@ -40,24 +40,6 @@ describe('<Timeline> utilities', () => {
assert.isFalse(areMessagesInSameGroup(undefined, false, defaultNewer));
});
it('returns false if either item is not a message', () => {
const linkNotification = {
type: 'linkNotification' as const,
data: null,
timestamp: Date.now(),
};
assert.isFalse(
areMessagesInSameGroup(defaultNewer, false, linkNotification)
);
assert.isFalse(
areMessagesInSameGroup(linkNotification, false, defaultNewer)
);
assert.isFalse(
areMessagesInSameGroup(linkNotification, false, linkNotification)
);
});
it("returns false if authors don't match", () => {
const older = {
...defaultOlder,
@ -155,18 +137,6 @@ describe('<Timeline> utilities', () => {
);
});
it('returns false if newer item is not a message', () => {
const linkNotification = {
type: 'linkNotification' as const,
data: null,
timestamp: Date.now(),
};
assert.isFalse(
shouldCurrentMessageHideMetadata(true, defaultCurrent, linkNotification)
);
});
it('returns false if newer is deletedForEveryone', () => {
const newer = {
...defaultNewer,

View file

@ -1,4 +1,4 @@
// Copyright 2021 Signal Messenger, LLC
// Copyright 2021-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
@ -166,15 +166,6 @@ describe('sql/conversationSummary', () => {
timestamp: now + 3,
};
const message4: MessageAttributesType = {
id: getUuid(),
body: 'message 4',
type: 'message-history-unsynced',
conversationId,
sent_at: now + 4,
received_at: now + 4,
timestamp: now + 4,
};
const message5: MessageAttributesType = {
id: getUuid(),
body: 'message 5',
type: 'profile-change',
@ -183,7 +174,7 @@ describe('sql/conversationSummary', () => {
received_at: now + 5,
timestamp: now + 5,
};
const message6: MessageAttributesType = {
const message5: MessageAttributesType = {
id: getUuid(),
body: 'message 6',
type: 'story',
@ -192,7 +183,7 @@ describe('sql/conversationSummary', () => {
received_at: now + 6,
timestamp: now + 6,
};
const message7: MessageAttributesType = {
const message6: MessageAttributesType = {
id: getUuid(),
body: 'message 7',
type: 'universal-timer-notification',
@ -201,7 +192,7 @@ describe('sql/conversationSummary', () => {
received_at: now + 7,
timestamp: now + 7,
};
const message8: MessageAttributesType = {
const message7: MessageAttributesType = {
id: getUuid(),
body: 'message 8',
type: 'verified-change',
@ -212,23 +203,14 @@ describe('sql/conversationSummary', () => {
};
await saveMessages(
[
message1,
message2,
message3,
message4,
message5,
message6,
message7,
message8,
],
[message1, message2, message3, message4, message5, message6, message7],
{
forceSave: true,
ourUuid,
}
);
assert.lengthOf(await _getAllMessages(), 8);
assert.lengthOf(await _getAllMessages(), 7);
const messages = await getConversationMessageStats({
conversationId,
@ -282,15 +264,6 @@ describe('sql/conversationSummary', () => {
timestamp: now + 4,
};
const message5: MessageAttributesType = {
id: getUuid(),
body: 'message 5',
type: 'message-history-unsynced',
conversationId,
sent_at: now + 5,
received_at: now + 5,
timestamp: now + 5,
};
const message6: MessageAttributesType = {
id: getUuid(),
body: 'message 6',
type: 'profile-change',
@ -299,7 +272,7 @@ describe('sql/conversationSummary', () => {
received_at: now + 6,
timestamp: now + 6,
};
const message7: MessageAttributesType = {
const message6: MessageAttributesType = {
id: getUuid(),
body: 'message 7',
type: 'story',
@ -308,7 +281,7 @@ describe('sql/conversationSummary', () => {
received_at: now + 7,
timestamp: now + 7,
};
const message8: MessageAttributesType = {
const message7: MessageAttributesType = {
id: getUuid(),
body: 'message 8',
type: 'universal-timer-notification',
@ -317,7 +290,7 @@ describe('sql/conversationSummary', () => {
received_at: now + 8,
timestamp: now + 8,
};
const message9: MessageAttributesType = {
const message8: MessageAttributesType = {
id: getUuid(),
body: 'message 9',
type: 'verified-change',
@ -337,7 +310,6 @@ describe('sql/conversationSummary', () => {
message6,
message7,
message8,
message9,
],
{
forceSave: true,
@ -345,7 +317,7 @@ describe('sql/conversationSummary', () => {
}
);
assert.lengthOf(await _getAllMessages(), 9);
assert.lengthOf(await _getAllMessages(), 8);
const messages = await getConversationMessageStats({
conversationId,

View file

@ -1,4 +1,4 @@
// Copyright 2018-2021 Signal Messenger, LLC
// Copyright 2018-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable camelcase */
@ -10,7 +10,6 @@ import type { IndexableBoolean, IndexablePresence } from './IndexedDB';
export type Message = (
| UserMessage
| VerifiedChangeMessage
| MessageHistoryUnsyncedMessage
| ProfileChangeNotificationMessage
) & { deletedForEveryone?: boolean };
export type UserMessage = IncomingMessage | OutgoingMessage;
@ -68,14 +67,6 @@ export type VerifiedChangeMessage = Readonly<
ExpirationTimerUpdate
>;
export type MessageHistoryUnsyncedMessage = Readonly<
{
type: 'message-history-unsynced';
} & SharedMessageProperties &
MessageSchemaVersion5 &
ExpirationTimerUpdate
>;
export type ProfileChangeNotificationMessage = Readonly<
{
type: 'profile-change';

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as Attachment from '../Attachment';
@ -19,9 +19,6 @@ export const initializeAttachmentMetadata = async (
if (message.type === 'verified-change') {
return message;
}
if (message.type === 'message-history-unsynced') {
return message;
}
if (message.type === 'profile-change') {
return message;
}

View file

@ -38,7 +38,6 @@ import {
} from './sessionTranslation';
import * as zkgroup from './zkgroup';
import { StartupQueue } from './StartupQueue';
import { postLinkExperience } from './postLinkExperience';
import { sendToGroup, sendContentMessageToGroup } from './sendToGroup';
import { RetryPlaceholders } from './retryPlaceholders';
import * as expirationTimer from './expirationTimer';
@ -70,7 +69,6 @@ export {
MessageController,
missingCaseError,
parseRemoteClientExpiration,
postLinkExperience,
queueUpdateMessage,
RetryPlaceholders,
saveNewMessageBatcher,

View file

@ -1,32 +0,0 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { MINUTE } from './durations';
class PostLinkExperience {
private hasNotFinishedSync: boolean;
constructor() {
this.hasNotFinishedSync = false;
}
start() {
this.hasNotFinishedSync = true;
// timeout "post link" after 10 minutes in case the syncs don't complete
// in time or are never called.
setTimeout(() => {
this.stop();
}, 10 * MINUTE);
}
stop() {
this.hasNotFinishedSync = false;
}
isActive(): boolean {
return this.hasNotFinishedSync === true;
}
}
export const postLinkExperience = new PostLinkExperience();