diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 973f047eb..90191839b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1577,6 +1577,9 @@ "unblockUser": { "message": "Unblock contact" }, + "unblocked": { + "message": "Unblocked" + }, "blockedSettingsTitle": { "message": "Blocked contacts", "description": "Shown in the settings page as the heading for the blocked user settings" diff --git a/ts/components/DevicePairingDialog.tsx b/ts/components/DevicePairingDialog.tsx index c15604d88..e8c25dd36 100644 --- a/ts/components/DevicePairingDialog.tsx +++ b/ts/components/DevicePairingDialog.tsx @@ -4,6 +4,7 @@ import { QRCode } from 'react-qr-svg'; import { SessionModal } from './session/SessionModal'; import { SessionButton, SessionButtonColor } from './session/SessionButton'; import { SessionSpinner } from './session/SessionSpinner'; +import { ToastUtils } from '../session/utils'; interface Props { onClose: any; @@ -280,7 +281,7 @@ export class DevicePairingDialog extends React.Component { errors: null, }); this.closeDialog(); - window.pushToast({ + ToastUtils.push({ title: window.i18n('devicePairedSuccessfully'), type: 'success', }); @@ -365,7 +366,7 @@ export class DevicePairingDialog extends React.Component { private triggerUnpairDevice() { const deviceUnpaired = () => { - window.pushToast({ + ToastUtils.push({ title: window.i18n('deviceUnpaired'), }); this.closeDialog(); diff --git a/ts/components/EditProfileDialog.tsx b/ts/components/EditProfileDialog.tsx index 888794fbf..d9d9d9c28 100644 --- a/ts/components/EditProfileDialog.tsx +++ b/ts/components/EditProfileDialog.tsx @@ -17,6 +17,7 @@ import { } from './session/icon'; import { SessionModal } from './session/SessionModal'; import { PillDivider } from './session/PillDivider'; +import { ToastUtils } from '../session/utils'; declare global { interface Window { @@ -304,7 +305,7 @@ export class EditProfileDialog extends React.Component { private copySessionID(sessionID: string) { window.clipboard.writeText(sessionID); - window.pushToast({ + ToastUtils.push({ title: window.i18n('copiedToClipboard'), type: 'success', id: 'copiedToClipboard', diff --git a/ts/components/MainViewController.tsx b/ts/components/MainViewController.tsx index b8e120380..46f34762e 100644 --- a/ts/components/MainViewController.tsx +++ b/ts/components/MainViewController.tsx @@ -15,6 +15,7 @@ export const MainViewController = { }; import { ContactType } from './session/SessionMemberListItem'; +import { ToastUtils } from '../session/utils'; export class MessageView extends React.Component { public render() { @@ -49,7 +50,7 @@ async function createClosedGroup( ) { // Validate groupName and groupMembers length if (groupName.length === 0) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('invalidGroupNameTooShort'), type: 'error', id: 'invalidGroupName', @@ -57,7 +58,7 @@ async function createClosedGroup( return; } else if (groupName.length > window.CONSTANTS.MAX_GROUP_NAME_LENGTH) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('invalidGroupNameTooLong'), type: 'error', id: 'invalidGroupName', @@ -70,7 +71,7 @@ async function createClosedGroup( // the same is valid with groups count <= 1 if (groupMembers.length <= 1) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('pickClosedGroupMember'), type: 'error', id: 'pickClosedGroupMember', @@ -78,7 +79,7 @@ async function createClosedGroup( return; } else if (groupMembers.length >= window.CONSTANTS.SMALL_GROUP_SIZE_LIMIT) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('closedGroupMaxSize'), type: 'error', id: 'closedGroupMaxSize', diff --git a/ts/components/session/LeftPaneContactSection.tsx b/ts/components/session/LeftPaneContactSection.tsx index 68de97471..440c4e4a8 100644 --- a/ts/components/session/LeftPaneContactSection.tsx +++ b/ts/components/session/LeftPaneContactSection.tsx @@ -22,6 +22,7 @@ import { SessionClosableOverlayType, } from './SessionClosableOverlay'; import { MainViewController } from '../MainViewController'; +import { ToastUtils } from '../../session/utils'; export interface Props { searchTerm: string; @@ -192,7 +193,7 @@ export class LeftPaneContactSection extends React.Component { const error = validateNumber(sessionID, window.i18n); if (error) { - window.pushToast({ + ToastUtils.push({ title: error, type: 'error', id: 'addContact', diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index c73a3de29..560597d5e 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -30,6 +30,7 @@ import { SessionButtonType, } from './SessionButton'; import { OpenGroup } from '../../session/types'; +import { ToastUtils } from '../../session/utils'; export interface Props { searchTerm: string; @@ -416,7 +417,7 @@ export class LeftPaneMessageSection extends React.Component { const { openConversationInternal } = this.props; if (!this.state.valuePasted && !this.props.searchTerm) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('invalidNumberError'), type: 'error', id: 'invalidPubKey', @@ -432,7 +433,7 @@ export class LeftPaneMessageSection extends React.Component { if (!error) { openConversationInternal(pubkey); } else { - window.pushToast({ + ToastUtils.push({ title: error, type: 'error', id: 'invalidPubKey', @@ -449,7 +450,7 @@ export class LeftPaneMessageSection extends React.Component { // Server URL valid? if (serverUrl.length === 0 || !OpenGroup.validate(serverUrl)) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('invalidOpenGroupUrl'), id: 'connectToServer', type: 'error', @@ -460,7 +461,7 @@ export class LeftPaneMessageSection extends React.Component { // Already connected? if (Boolean(await OpenGroup.getConversation(serverUrl))) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('publicChatExists'), id: 'publicChatExists', type: 'error', @@ -471,14 +472,14 @@ export class LeftPaneMessageSection extends React.Component { // Connect to server try { - window.pushToast({ + ToastUtils.push({ title: window.i18n('connectingToServer'), id: 'connectToServer', type: 'success', }); await OpenGroup.join(serverUrl, async () => { if (await OpenGroup.serverExists(serverUrl)) { - window.pushToast({ + ToastUtils.push({ title: window.i18n('connectToServerSuccess'), id: 'connectToServer', type: 'success', @@ -502,7 +503,7 @@ export class LeftPaneMessageSection extends React.Component { } } catch (e) { window.console.error('Failed to connect to server:', e); - window.pushToast({ + ToastUtils.push({ title: window.i18n('connectToServerFail'), id: 'connectToServer', type: 'error', @@ -527,7 +528,7 @@ export class LeftPaneMessageSection extends React.Component { () => { this.handleToggleOverlay(undefined); - window.pushToast({ + ToastUtils.push({ title: window.i18n('closedGroupCreatedToastTitle'), type: 'success', }); diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index 71fa3aac7..52c6f4b21 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -11,7 +11,7 @@ import { trigger } from '../../shims/events'; import { SessionHtmlRenderer } from './SessionHTMLRenderer'; import { SessionIdEditable } from './SessionIdEditable'; import { SessionSpinner } from './SessionSpinner'; -import { StringUtils } from '../../session/utils'; +import { StringUtils, ToastUtils } from '../../session/utils'; enum SignInMode { Default, @@ -803,7 +803,7 @@ export class RegistrationTabs extends React.Component<{}, State> { if (!trimName) { window.log.warn('invalid trimmed name for registration'); - window.pushToast({ + ToastUtils.push({ title: window.i18n('displayNameEmpty'), type: 'error', id: 'invalidDisplayName', @@ -814,7 +814,7 @@ export class RegistrationTabs extends React.Component<{}, State> { if (passwordErrorString) { window.log.warn('invalid password for registration'); - window.pushToast({ + ToastUtils.push({ title: window.i18n('invalidPassword'), type: 'error', id: 'invalidPassword', @@ -826,7 +826,7 @@ export class RegistrationTabs extends React.Component<{}, State> { if (!!password && !passwordFieldsMatch) { window.log.warn('passwords does not match for registration'); - window.pushToast({ + ToastUtils.push({ title: window.i18n('passwordsDoNotMatch'), type: 'error', id: 'invalidPassword', @@ -864,7 +864,7 @@ export class RegistrationTabs extends React.Component<{}, State> { ); trigger('openInbox'); } catch (e) { - window.pushToast({ + ToastUtils.push({ title: `Error: ${e.message || 'Something went wrong'}`, type: 'error', id: 'registrationError', @@ -895,7 +895,7 @@ export class RegistrationTabs extends React.Component<{}, State> { // tslint:disable-next-line: no-backbone-get-set-outside-model if (window.textsecure.storage.get('secondaryDeviceStatus') === 'ongoing') { window.log.warn('registering secondary device already ongoing'); - window.pushToast({ + ToastUtils.push({ title: window.i18n('pairingOngoing'), type: 'error', id: 'pairingOngoing', @@ -938,7 +938,7 @@ export class RegistrationTabs extends React.Component<{}, State> { const validationError = c.validateNumber(); if (validationError) { onError('Invalid public key').ignore(); - window.pushToast({ + ToastUtils.push({ title: window.i18n('invalidNumberError'), type: 'error', id: 'invalidNumberError', diff --git a/ts/components/session/SessionPasswordModal.tsx b/ts/components/session/SessionPasswordModal.tsx index 9e9d4b19f..99a5b485f 100644 --- a/ts/components/session/SessionPasswordModal.tsx +++ b/ts/components/session/SessionPasswordModal.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { SessionModal } from './SessionModal'; import { SessionButton, SessionButtonColor } from './SessionButton'; import { PasswordUtil } from '../../util/'; +import { ToastUtils } from '../../session/utils'; export enum PasswordAction { Set = 'set', Change = 'change', @@ -232,16 +233,12 @@ export class SessionPasswordModal extends React.Component { throw new Error(`Invalid action ${action}`); } - const toastParams = { + ToastUtils.push({ + id: 'set-password-success-toast', + type: action !== Remove ? 'success' : 'warning', title: title, description: description, - type: action !== Remove ? 'success' : 'warning', icon: action !== Remove ? 'lock' : undefined, - }; - - window.pushToast({ - id: 'set-password-success-toast', - ...toastParams, }); onSuccess(this.props.action); @@ -265,7 +262,7 @@ export class SessionPasswordModal extends React.Component { ) ); - window.pushToast({ + ToastUtils.push({ title, type: 'warning', }); diff --git a/ts/components/session/SessionSeedModal.tsx b/ts/components/session/SessionSeedModal.tsx index c2730fac3..1f60bd174 100644 --- a/ts/components/session/SessionSeedModal.tsx +++ b/ts/components/session/SessionSeedModal.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { SessionModal } from './SessionModal'; import { SessionButton } from './SessionButton'; +import { ToastUtils } from '../../session/utils'; interface Props { onClose: any; @@ -212,7 +213,7 @@ export class SessionSeedModal extends React.Component { private copySeed(seed: string) { window.clipboard.writeText(seed); - window.pushToast({ + ToastUtils.push({ title: window.i18n('copiedToClipboard'), type: 'success', id: 'copySeedToast', diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index e9f859cf3..043dcd6dd 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -10,7 +10,7 @@ import { import { BlockedNumberController, UserUtil } from '../../../util'; import { MultiDeviceProtocol } from '../../../session/protocols'; import { PubKey } from '../../../session/types'; -import { NumberUtils } from '../../../session/utils'; +import { NumberUtils, ToastUtils } from '../../../session/utils'; export enum SessionSettingCategory { Appearance = 'appearance', @@ -600,21 +600,20 @@ export class SettingsView extends React.Component { const blockedNumbers = BlockedNumberController.getBlockedNumbers(); for (const blockedNumber of blockedNumbers) { - let displayName = `User (...${blockedNumber.substr(-6)})`; + let title: string; const currentModel = window.ConversationController.get(blockedNumber); - if ( - currentModel && - currentModel.attributes.profile && - currentModel.attributes.profile.displayName - ) { - displayName = currentModel.attributes.profile.displayName; - } + title = + currentModel.getProfileName() || + currentModel.getName() || + window.i18n('anonymous'); + + title = `${title} ${window.shortenPubkey(blockedNumber)}`; results.push({ id: blockedNumber, - title: displayName, - description: blockedNumber, + title, + description: '', type: SessionSettingType.Button, category: SessionSettingCategory.Blocked, content: { @@ -623,7 +622,11 @@ export class SettingsView extends React.Component { }, comparisonValue: undefined, setFn: async () => { - await BlockedNumberController.unblock(blockedNumber); + await currentModel.unblock(); + ToastUtils.push({ + title: window.i18n('unblocked'), + id: 'unblocked', + }); }, hidden: false, onClick: undefined, diff --git a/ts/session/utils/Toast.ts b/ts/session/utils/Toast.ts new file mode 100644 index 000000000..bf2edb945 --- /dev/null +++ b/ts/session/utils/Toast.ts @@ -0,0 +1,10 @@ +export function push(options: { + title: string; + id?: string; + description?: string; + type?: 'success' | 'info' | 'warning' | 'error'; + icon?: string; + shouldFade?: boolean; +}) { + window.pushToast(options); +} diff --git a/ts/session/utils/index.ts b/ts/session/utils/index.ts index b38705d0e..bf9e1f969 100644 --- a/ts/session/utils/index.ts +++ b/ts/session/utils/index.ts @@ -6,6 +6,7 @@ import * as NumberUtils from './Number'; import * as PromiseUtils from './Promise'; import * as ProtobufUtils from './Protobuf'; import * as MenuUtils from './Menu'; +import * as ToastUtils from './Toast'; export * from './Attachments'; export * from './TypedEmitter'; @@ -20,4 +21,5 @@ export { PromiseUtils, ProtobufUtils, MenuUtils, + ToastUtils, };