diff --git a/_locales/en/messages.json b/_locales/en/messages.json index cbc2489a9..4aaad9806 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1302,6 +1302,22 @@ "message": "Typing Indicators", "description": "Title of the typing indicators setting" }, + "multiDeviceDisabledTemporary": { + "message": "MultiDevice disabled temporarily", + "description": "Description of why multi device is disabled" + }, + "multiDeviceDisabledTemporaryTitle": { + "message": "Changes to Multi-device", + "description": "Description of why multi device is disabled on app start" + }, + "multiDeviceDisabledTemporaryDescriptionPrimary": { + "message": "You’re seeing this because you have a secondary device linked to your Session ID. To improve reliability and stability, we’ve decided to temporarily disable Session’s multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on August 6th.

To read more about this change, visit the Session FAQ at getsession.org/faq.", + "description": "Description of why multi device is disabled on app start for a primary device" + }, + "multiDeviceDisabledTemporaryDescriptionSecondary": { + "message": "You’re seeing this because this is a secondary device in a multi-device setup. To improve reliability and stability, we’ve decided to temporarily disable Session’s multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on August 6th.

To read more about this change, visit the Session FAQ at getsession.org/faq.", + "description": "Description of why multi device is disabled on app start for a secondary device" + }, "messageTTL": { "message": "Message TTL", "description": "Title of the Message TTL setting" diff --git a/js/views/inbox_view.js b/js/views/inbox_view.js index 8ec8e024b..9d702b620 100644 --- a/js/views/inbox_view.js +++ b/js/views/inbox_view.js @@ -90,12 +90,21 @@ type: 'success', }); }, - showConfirmationDialog({ title, message, onOk, onCancel }) { + showConfirmationDialog({ + title, + message, + messageSub, + onOk, + onCancel, + hideCancel, + }) { window.confirmationDialog({ title, message, resolve: onOk, reject: onCancel, + hideCancel, + messageSub, }); }, }); diff --git a/stylesheets/_theme_dark.scss b/stylesheets/_theme_dark.scss index 36cf6d68a..aa1d61477 100644 --- a/stylesheets/_theme_dark.scss +++ b/stylesheets/_theme_dark.scss @@ -242,7 +242,7 @@ body.dark-theme { } a { - color: $blue; + color: $session-color-green; } .file-input { @@ -410,7 +410,7 @@ body.dark-theme { } } a.link { - color: #2090ea; + color: $session-color-green; } .progress { diff --git a/ts/components/session/ActionsPanel.tsx b/ts/components/session/ActionsPanel.tsx index 2664b6ba0..484a3b89f 100644 --- a/ts/components/session/ActionsPanel.tsx +++ b/ts/components/session/ActionsPanel.tsx @@ -2,6 +2,9 @@ import React from 'react'; import { SessionIconButton, SessionIconSize, SessionIconType } from './icon'; import { Avatar } from '../Avatar'; import { PropsData as ConversationListItemPropsType } from '../ConversationListItem'; +import { MultiDeviceProtocol } from '../../session/protocols'; +import { UserUtil } from '../../util'; +import { createOrUpdateItem, getItemById } from '../../../js/modules/data'; export enum SectionType { Profile, @@ -56,6 +59,48 @@ export class ActionsPanel extends React.Component { }, 'refreshAvatarCallback' ); + setTimeout(async () => { + const disabledMultiDeviceCountDb = await getItemById( + 'disabledMultiDeviceCount' + ); + const disabledMultiDeviceCount = + Number(disabledMultiDeviceCountDb?.value) || 0; + const data = { + id: 'disabledMultiDeviceCount', + value: String(disabledMultiDeviceCount + 1), + }; + await createOrUpdateItem(data); + if (disabledMultiDeviceCount % 5 !== 0) { + return; + } + const currentDevice = await UserUtil.getCurrentDevicePubKey(); + if (!currentDevice) { + return; + } + const secondaryDevices = await MultiDeviceProtocol.getSecondaryDevices( + currentDevice + ); + const isSecondary = + secondaryDevices.find(s => s.key === currentDevice) || + !!window.textsecure.storage.get('isSecondaryDevice'); + + const hasMultipleDevices = + (await MultiDeviceProtocol.getOurDevices()).length > 1; + const primaryWithSecondary = !isSecondary && hasMultipleDevices; + + if (!primaryWithSecondary && !isSecondary) { + return; + } + + const opts = { + hideCancel: true, + title: window.i18n('multiDeviceDisabledTemporaryTitle'), + message: primaryWithSecondary + ? window.i18n('multiDeviceDisabledTemporaryDescriptionPrimary') + : window.i18n('multiDeviceDisabledTemporaryDescriptionSecondary'), + }; + window.Whisper.events.trigger('showConfirmationDialog', opts); + }, 1000); } ); } diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index be7d733ea..4690a3d34 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -557,8 +557,9 @@ export class RegistrationTabs extends React.Component<{}, State> { SessionButtonType.BrandOutline, SessionButtonColor.Green )} -

{or}

- {this.renderLinkDeviceToExistingAccountButton()} + {/*

{or}

*/} + {/* FIXME enable back to allow linking of device + this.renderLinkDeviceToExistingAccountButton() */} ); } @@ -583,8 +584,9 @@ export class RegistrationTabs extends React.Component<{}, State> { return (
{this.renderContinueYourSessionButton()} -

{or}

- {this.renderLinkDeviceToExistingAccountButton()} + {/*

{or}

*/} + {/* FIXME enable back to allow linking of device + this.renderLinkDeviceToExistingAccountButton()*/}
); } diff --git a/ts/components/session/SessionConfirm.tsx b/ts/components/session/SessionConfirm.tsx index 859e856c8..ed8914c4a 100644 --- a/ts/components/session/SessionConfirm.tsx +++ b/ts/components/session/SessionConfirm.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { SessionModal } from './SessionModal'; import { SessionButton, SessionButtonColor } from './SessionButton'; +import { SessionHtmlRenderer } from './SessionHTMLRenderer'; interface Props { message: string; @@ -61,7 +62,11 @@ export class SessionConfirm extends React.Component { {!showHeader &&
}
- {message} + {messageSub && ( {messageSub} diff --git a/ts/components/session/SessionHTMLRenderer.tsx b/ts/components/session/SessionHTMLRenderer.tsx index f7f493b7b..438213be5 100644 --- a/ts/components/session/SessionHTMLRenderer.tsx +++ b/ts/components/session/SessionHTMLRenderer.tsx @@ -5,6 +5,7 @@ interface ReceivedProps { html: string; tag?: string; key?: any; + className?: string; } // Needed because of https://github.com/microsoft/tslint-microsoft-contrib/issues/339 @@ -14,14 +15,16 @@ export const SessionHtmlRenderer: React.SFC = ({ tag = 'div', key, html, + className, }) => { const clean = DOMPurify.sanitize(html, { USE_PROFILES: { html: true }, - FORBID_ATTR: ['style', 'script'], + FORBID_ATTR: ['script'], }); return React.createElement(tag, { key, + className, dangerouslySetInnerHTML: { __html: clean }, }); }; diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index 3b4076da0..f60459ea8 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -644,7 +644,7 @@ export class SettingsView extends React.Component { id: 'no-linked-device', title: noPairedDeviceText, type: undefined, - description: '', + description: window.i18n('multiDeviceDisabledTemporary'), category: SessionSettingCategory.Devices, content: {}, comparisonValue: undefined, diff --git a/ts/components/session/settings/SessionSettingsHeader.tsx b/ts/components/session/settings/SessionSettingsHeader.tsx index 21e663e96..b1e33393a 100644 --- a/ts/components/session/settings/SessionSettingsHeader.tsx +++ b/ts/components/session/settings/SessionSettingsHeader.tsx @@ -74,9 +74,12 @@ export class SettingsHeader extends React.Component { ? `${categoryTitlePrefix.slice(0, -1)} Settings` : `${categoryTitlePrefix} Settings`; const showSearch = false; - const showAddDevice = + const showAddDevice = false; + /* FIXME enable back to allow linking of device + const showAddDevice = category === SessionSettingCategory.Devices && this.props.showLinkDeviceButton; + */ return (