Move confirmation_dialog_view to ts and React
* Moves confirmation_dialog_view to ts and React * showConfirmationDialog API
This commit is contained in:
parent
031a1fcc3d
commit
2529e208c1
16 changed files with 154 additions and 254 deletions
|
@ -114,18 +114,6 @@
|
||||||
<button class='finish' tabIndex='1'><span class='icon'></span></button>
|
<button class='finish' tabIndex='1'><span class='icon'></span></button>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type='text/x-tmpl-mustache' id='confirmation-dialog'>
|
|
||||||
<div class="content">
|
|
||||||
<div class='message'>{{ message }}</div>
|
|
||||||
<div class='buttons'>
|
|
||||||
<button class='ok' tabindex='2'>{{ ok }}</button>
|
|
||||||
{{ #showCancel }}
|
|
||||||
<button class='cancel' tabindex='1'>{{ cancel }}</button>
|
|
||||||
{{ /showCancel }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type='text/x-tmpl-mustache' id='safety-number-change-dialog'>
|
<script type='text/x-tmpl-mustache' id='safety-number-change-dialog'>
|
||||||
<div class='safety-number-change-dialog-wrapper'></div>
|
<div class='safety-number-change-dialog-wrapper'></div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -361,7 +349,7 @@
|
||||||
<script type='text/javascript' src='js/views/recorder_view.js'></script>
|
<script type='text/javascript' src='js/views/recorder_view.js'></script>
|
||||||
<script type='text/javascript' src='ts/views/conversation_view.js'></script>
|
<script type='text/javascript' src='ts/views/conversation_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/inbox_view.js'></script>
|
<script type='text/javascript' src='js/views/inbox_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/confirmation_dialog_view.js'></script>
|
<script type='text/javascript' src='ts/shims/showConfirmationDialog.js'></script>
|
||||||
<script type='text/javascript' src='js/views/identicon_svg_view.js'></script>
|
<script type='text/javascript' src='js/views/identicon_svg_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/install_view.js'></script>
|
<script type='text/javascript' src='js/views/install_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/banner_view.js'></script>
|
<script type='text/javascript' src='js/views/banner_view.js'></script>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2018-2020 Signal Messenger, LLC
|
// Copyright 2018-2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global $, Whisper, i18n */
|
/* global $, i18n */
|
||||||
|
|
||||||
$(document).on('keydown', e => {
|
$(document).on('keydown', e => {
|
||||||
if (e.keyCode === 27) {
|
if (e.keyCode === 27) {
|
||||||
|
@ -35,7 +35,8 @@ if (window.forCalling) {
|
||||||
message = i18n('audioPermissionNeeded');
|
message = i18n('audioPermissionNeeded');
|
||||||
}
|
}
|
||||||
|
|
||||||
window.view = new Whisper.ConfirmationDialogView({
|
window.showConfirmationDialog({
|
||||||
|
confirmStyle: 'affirmative',
|
||||||
message,
|
message,
|
||||||
okText: i18n('allowAccess'),
|
okText: i18n('allowAccess'),
|
||||||
resolve: () => {
|
resolve: () => {
|
||||||
|
@ -48,5 +49,3 @@ window.view = new Whisper.ConfirmationDialogView({
|
||||||
},
|
},
|
||||||
reject: window.closePermissionsPopup,
|
reject: window.closePermissionsPopup,
|
||||||
});
|
});
|
||||||
|
|
||||||
window.view.$el.appendTo($body);
|
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
// Copyright 2015-2020 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
/* global Backbone, Whisper, i18n */
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
|
||||||
(function () {
|
|
||||||
window.Whisper = window.Whisper || {};
|
|
||||||
|
|
||||||
Whisper.ConfirmationDialogView = Whisper.View.extend({
|
|
||||||
className: 'confirmation-dialog modal',
|
|
||||||
templateName: 'confirmation-dialog',
|
|
||||||
initialize(options) {
|
|
||||||
this.previousFocus = document.activeElement;
|
|
||||||
|
|
||||||
this.message = options.message;
|
|
||||||
this.hideCancel = options.hideCancel;
|
|
||||||
|
|
||||||
this.resolve = options.resolve;
|
|
||||||
this.okText = options.okText || i18n('ok');
|
|
||||||
|
|
||||||
this.reject = options.reject;
|
|
||||||
this.cancelText = options.cancelText || i18n('cancel');
|
|
||||||
|
|
||||||
if (Whisper.activeConfirmationView) {
|
|
||||||
Whisper.activeConfirmationView.remove();
|
|
||||||
Whisper.activeConfirmationView = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Whisper.activeConfirmationView = this;
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
events: {
|
|
||||||
keydown: 'onKeydown',
|
|
||||||
'click .ok': 'ok',
|
|
||||||
'click .cancel': 'cancel',
|
|
||||||
},
|
|
||||||
remove() {
|
|
||||||
if (this.previousFocus && this.previousFocus.focus) {
|
|
||||||
this.previousFocus.focus();
|
|
||||||
}
|
|
||||||
Backbone.View.prototype.remove.call(this);
|
|
||||||
},
|
|
||||||
render_attributes() {
|
|
||||||
return {
|
|
||||||
message: this.message,
|
|
||||||
showCancel: !this.hideCancel,
|
|
||||||
cancel: this.cancelText,
|
|
||||||
ok: this.okText,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
ok() {
|
|
||||||
this.remove();
|
|
||||||
if (this.resolve) {
|
|
||||||
this.resolve();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cancel() {
|
|
||||||
this.remove();
|
|
||||||
if (this.reject) {
|
|
||||||
this.reject(new Error('User clicked cancel button'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onKeydown(event) {
|
|
||||||
if (event.key === 'Escape' || event.key === 'Esc') {
|
|
||||||
this.cancel();
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
focusCancel() {
|
|
||||||
// We delay this call because we might be called inside click handlers
|
|
||||||
// which would set focus to themselves afterwards!
|
|
||||||
setTimeout(() => this.$('.cancel').focus(), 1);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})();
|
|
|
@ -54,14 +54,12 @@
|
||||||
},
|
},
|
||||||
confirm(message, okText) {
|
confirm(message, okText) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const dialog = new Whisper.ConfirmationDialogView({
|
window.showConfirmationDialog({
|
||||||
message,
|
message,
|
||||||
okText,
|
okText,
|
||||||
resolve,
|
resolve,
|
||||||
reject,
|
reject,
|
||||||
});
|
});
|
||||||
this.$el.append(dialog.el);
|
|
||||||
dialog.focusCancel();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,20 +23,9 @@
|
||||||
</head>
|
</head>
|
||||||
<body class='permissions-popup'>
|
<body class='permissions-popup'>
|
||||||
</body>
|
</body>
|
||||||
<script type='text/x-tmpl-mustache' id='confirmation-dialog'>
|
|
||||||
<div class="content">
|
|
||||||
<div class='message'>{{ message }}</div>
|
|
||||||
<div class='buttons'>
|
|
||||||
{{ #showCancel }}
|
|
||||||
<button class='cancel' tabindex='2'>{{ cancel }}</button>
|
|
||||||
{{ /showCancel }}
|
|
||||||
<button class='ok' tabindex='1'>{{ ok }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
<script type='text/javascript' src='js/components.js'></script>
|
<script type='text/javascript' src='js/components.js'></script>
|
||||||
<script type='text/javascript' src='ts/backboneJquery.js'></script>
|
<script type='text/javascript' src='ts/backboneJquery.js'></script>
|
||||||
<script type='text/javascript' src='js/views/whisper_view.js'></script>
|
<script type='text/javascript' src='js/views/whisper_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/confirmation_dialog_view.js'></script>
|
<script type='text/javascript' src='ts/shims/showConfirmationDialog.js'></script>
|
||||||
<script type='text/javascript' src='js/permissions_popup_start.js'></script>
|
<script type='text/javascript' src='js/permissions_popup_start.js'></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -3,9 +3,13 @@
|
||||||
|
|
||||||
/* global window */
|
/* global window */
|
||||||
|
|
||||||
|
window.React = require('react');
|
||||||
|
window.ReactDOM = require('react-dom');
|
||||||
|
|
||||||
const { ipcRenderer, remote } = require('electron');
|
const { ipcRenderer, remote } = require('electron');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const i18n = require('./js/modules/i18n');
|
const i18n = require('./js/modules/i18n');
|
||||||
|
const { ConfirmationModal } = require('./ts/components/ConfirmationModal');
|
||||||
const { makeGetter, makeSetter } = require('./preload_utils');
|
const { makeGetter, makeSetter } = require('./preload_utils');
|
||||||
|
|
||||||
const { nativeTheme } = remote.require('electron');
|
const { nativeTheme } = remote.require('electron');
|
||||||
|
@ -20,6 +24,11 @@ window.theme = config.theme;
|
||||||
window.i18n = i18n.setup(locale, localeMessages);
|
window.i18n = i18n.setup(locale, localeMessages);
|
||||||
window.forCalling = config.forCalling === 'true';
|
window.forCalling = config.forCalling === 'true';
|
||||||
window.forCamera = config.forCamera === 'true';
|
window.forCamera = config.forCamera === 'true';
|
||||||
|
window.Signal = {
|
||||||
|
Components: {
|
||||||
|
ConfirmationModal,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
function setSystemTheme() {
|
function setSystemTheme() {
|
||||||
window.systemTheme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
|
window.systemTheme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
|
||||||
|
|
|
@ -292,79 +292,10 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirmation-dialog {
|
|
||||||
.content {
|
|
||||||
max-width: 350px;
|
|
||||||
margin: 100px auto;
|
|
||||||
padding: 1em;
|
|
||||||
|
|
||||||
border-radius: 5px;
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
background: $color-white;
|
|
||||||
box-shadow: 0px 0px 15px 0px $color-black-alpha-20;
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
background: $color-black;
|
|
||||||
color: $color-gray-02;
|
|
||||||
box-shadow: 0px 0px 15px 0px $color-white-alpha-20;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
margin-top: 10px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
float: right;
|
|
||||||
margin-left: 10px;
|
|
||||||
padding: 5px 8px;
|
|
||||||
border-radius: 5px;
|
|
||||||
|
|
||||||
outline: none;
|
|
||||||
@include keyboard-mode {
|
|
||||||
&:focus {
|
|
||||||
outline: -webkit-focus-ring-color auto 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
background-color: $color-gray-02;
|
|
||||||
border: 1px solid $color-gray-15;
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
background-color: $color-gray-90;
|
|
||||||
border: 1px solid $color-gray-45;
|
|
||||||
color: $color-gray-02;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
@include light-theme {
|
|
||||||
background-color: $color-gray-15;
|
|
||||||
border-color: $color-gray-25;
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
background-color: $color-gray-75;
|
|
||||||
border-color: $color-gray-45;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.permissions-popup,
|
.permissions-popup,
|
||||||
.debug-log-window {
|
.debug-log-window {
|
||||||
.modal {
|
.modal {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirmation-dialog .content {
|
|
||||||
box-shadow: 0px 0px 0px 0px;
|
|
||||||
max-width: 1000px;
|
|
||||||
margin: 0;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8308,7 +8308,8 @@ button.module-image__border-overlay:focus {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
z-index: 5;
|
// THIS Z-INDEX IS OVER NINE THOUSAND. OVER NINE THOUSAND?! THAT CAN'T BE!
|
||||||
|
z-index: 9001;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
|
|
|
@ -125,16 +125,8 @@
|
||||||
<button class='close'><span class='icon'></span></button>
|
<button class='close'><span class='icon'></span></button>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type='text/x-tmpl-mustache' id='confirmation-dialog'>
|
<script type='text/x-tmpl-mustache' id='safety-number-change-dialog'>
|
||||||
<div class="content">
|
<div class='safety-number-change-dialog-wrapper'></div>
|
||||||
<div class='message'>{{ message }}</div>
|
|
||||||
<div class='buttons'>
|
|
||||||
{{ #showCancel }}
|
|
||||||
<button class='cancel' tabindex='2'>{{ cancel }}</button>
|
|
||||||
{{ /showCancel }}
|
|
||||||
<button class='ok' tabindex='1'>{{ ok }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type='text/x-tmpl-mustache' id='identicon-svg'>
|
<script type='text/x-tmpl-mustache' id='identicon-svg'>
|
||||||
|
|
|
@ -241,15 +241,14 @@ type WhatIsThis = import('./window.d').WhatIsThis;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
const dialog = new window.Whisper.ConfirmationDialogView({
|
window.showConfirmationDialog({
|
||||||
|
cancelText: window.i18n('quit'),
|
||||||
|
confirmStyle: 'negative',
|
||||||
message: window.i18n('deleteOldIndexedDBData'),
|
message: window.i18n('deleteOldIndexedDBData'),
|
||||||
okText: window.i18n('deleteOldData'),
|
okText: window.i18n('deleteOldData'),
|
||||||
cancelText: window.i18n('quit'),
|
reject: () => reject(),
|
||||||
resolve,
|
resolve: () => resolve(),
|
||||||
reject,
|
|
||||||
});
|
});
|
||||||
document.body.append(dialog.el);
|
|
||||||
dialog.focusCancel();
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
window.log.info(
|
window.log.info(
|
||||||
|
|
|
@ -12,9 +12,8 @@ import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
storiesOf('Components/ConfirmationDialog', module).add(
|
storiesOf('Components/ConfirmationDialog', module)
|
||||||
'ConfirmationDialog',
|
.add('ConfirmationDialog', () => {
|
||||||
() => {
|
|
||||||
return (
|
return (
|
||||||
<ConfirmationDialog
|
<ConfirmationDialog
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
|
@ -36,5 +35,23 @@ storiesOf('Components/ConfirmationDialog', module).add(
|
||||||
{text('Child text', 'asdf blip')}
|
{text('Child text', 'asdf blip')}
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
);
|
.add('Custom cancel text', () => {
|
||||||
|
return (
|
||||||
|
<ConfirmationDialog
|
||||||
|
cancelText="Nah"
|
||||||
|
i18n={i18n}
|
||||||
|
onClose={action('onClose')}
|
||||||
|
title={text('Title', 'Foo bar banana baz?')}
|
||||||
|
actions={[
|
||||||
|
{
|
||||||
|
text: 'Maybe',
|
||||||
|
style: 'affirmative',
|
||||||
|
action: action('affirmative'),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{text('Child text', 'asdf blip')}
|
||||||
|
</ConfirmationDialog>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
|
@ -12,11 +12,12 @@ export type ActionSpec = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
readonly i18n: LocalizerType;
|
|
||||||
readonly children: React.ReactNode;
|
|
||||||
readonly title?: string | React.ReactNode;
|
|
||||||
readonly actions: Array<ActionSpec>;
|
readonly actions: Array<ActionSpec>;
|
||||||
|
readonly cancelText?: string;
|
||||||
|
readonly children?: React.ReactNode;
|
||||||
|
readonly i18n: LocalizerType;
|
||||||
readonly onClose: () => unknown;
|
readonly onClose: () => unknown;
|
||||||
|
readonly title?: string | React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Props = OwnProps;
|
export type Props = OwnProps;
|
||||||
|
@ -28,7 +29,7 @@ function focusRef(el: HTMLElement | null) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConfirmationDialog = React.memo(
|
export const ConfirmationDialog = React.memo(
|
||||||
({ i18n, onClose, children, title, actions }: Props) => {
|
({ i18n, onClose, cancelText, children, title, actions }: Props) => {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const handler = ({ key }: KeyboardEvent) => {
|
const handler = ({ key }: KeyboardEvent) => {
|
||||||
if (key === 'Escape') {
|
if (key === 'Escape') {
|
||||||
|
@ -81,7 +82,7 @@ export const ConfirmationDialog = React.memo(
|
||||||
ref={focusRef}
|
ref={focusRef}
|
||||||
className="module-confirmation-dialog__container__buttons__button"
|
className="module-confirmation-dialog__container__buttons__button"
|
||||||
>
|
>
|
||||||
{i18n('confirmation-dialog--Cancel')}
|
{cancelText || i18n('confirmation-dialog--Cancel')}
|
||||||
</button>
|
</button>
|
||||||
{actions.map((action, i) => (
|
{actions.map((action, i) => (
|
||||||
<button
|
<button
|
||||||
|
|
77
ts/shims/showConfirmationDialog.tsx
Normal file
77
ts/shims/showConfirmationDialog.tsx
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2015-2020 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
// This file is here temporarily while we're switching off of Backbone into
|
||||||
|
// React. In the future, and in React-land, please just import and use
|
||||||
|
// ConfirmationModal directly. This is the thin API layer to bridge the gap
|
||||||
|
// while we convert things over. Please delete this file once all usages are
|
||||||
|
// ported over. Note: this file cannot have any imports/exports since it is
|
||||||
|
// being included in a <script /> tag.
|
||||||
|
|
||||||
|
type ConfirmationDialogViewProps = {
|
||||||
|
cancelText?: string;
|
||||||
|
confirmStyle?: 'affirmative' | 'negative';
|
||||||
|
message: string;
|
||||||
|
okText: string;
|
||||||
|
reject?: () => void;
|
||||||
|
resolve: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
let confirmationDialogViewNode: HTMLElement | null = null;
|
||||||
|
let confirmationDialogPreviousFocus: HTMLElement | null = null;
|
||||||
|
|
||||||
|
function removeConfirmationDialog() {
|
||||||
|
if (!confirmationDialogViewNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.ReactDOM.unmountComponentAtNode(confirmationDialogViewNode);
|
||||||
|
document.body.removeChild(confirmationDialogViewNode);
|
||||||
|
|
||||||
|
if (
|
||||||
|
confirmationDialogPreviousFocus &&
|
||||||
|
typeof confirmationDialogPreviousFocus.focus === 'function'
|
||||||
|
) {
|
||||||
|
confirmationDialogPreviousFocus.focus();
|
||||||
|
}
|
||||||
|
confirmationDialogViewNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showConfirmationDialog(options: ConfirmationDialogViewProps) {
|
||||||
|
if (confirmationDialogViewNode) {
|
||||||
|
removeConfirmationDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmationDialogViewNode = document.createElement('div');
|
||||||
|
document.body.appendChild(confirmationDialogViewNode);
|
||||||
|
|
||||||
|
confirmationDialogPreviousFocus = document.activeElement as HTMLElement;
|
||||||
|
|
||||||
|
window.ReactDOM.render(
|
||||||
|
// eslint-disable-next-line react/react-in-jsx-scope, react/jsx-no-undef
|
||||||
|
<window.Signal.Components.ConfirmationModal
|
||||||
|
actions={[
|
||||||
|
{
|
||||||
|
action: () => {
|
||||||
|
removeConfirmationDialog();
|
||||||
|
options.resolve();
|
||||||
|
},
|
||||||
|
style: options.confirmStyle,
|
||||||
|
text: options.okText || window.i18n('ok'),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
cancelText={options.cancelText || window.i18n('cancel')}
|
||||||
|
i18n={window.i18n}
|
||||||
|
onClose={() => {
|
||||||
|
removeConfirmationDialog();
|
||||||
|
if (options.reject) {
|
||||||
|
options.reject();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
title={options.message}
|
||||||
|
/>,
|
||||||
|
confirmationDialogViewNode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.showConfirmationDialog = showConfirmationDialog;
|
|
@ -286,15 +286,6 @@
|
||||||
"updated": "2018-09-19T21:59:32.770Z",
|
"updated": "2018-09-19T21:59:32.770Z",
|
||||||
"reasonDetail": "Protected from arbitrary input"
|
"reasonDetail": "Protected from arbitrary input"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"rule": "jQuery-appendTo(",
|
|
||||||
"path": "js/permissions_popup_start.js",
|
|
||||||
"line": "window.view.$el.appendTo($body);",
|
|
||||||
"lineNumber": 52,
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2020-06-02T21:51:34.813Z",
|
|
||||||
"reasonDetail": "Interacting with already-existing DOM nodes"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"rule": "jQuery-$(",
|
"rule": "jQuery-$(",
|
||||||
"path": "js/settings_start.js",
|
"path": "js/settings_start.js",
|
||||||
|
@ -357,15 +348,6 @@
|
||||||
"updated": "2018-09-19T18:13:29.628Z",
|
"updated": "2018-09-19T18:13:29.628Z",
|
||||||
"reasonDetail": "Interacting with already-existing DOM nodes"
|
"reasonDetail": "Interacting with already-existing DOM nodes"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"rule": "jQuery-$(",
|
|
||||||
"path": "js/views/confirmation_dialog_view.js",
|
|
||||||
"line": " setTimeout(() => this.$('.cancel').focus(), 1);",
|
|
||||||
"lineNumber": 76,
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2019-12-07T02:04:56.987Z",
|
|
||||||
"reasonDetail": "Protected from arbitrary input"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"rule": "jQuery-append(",
|
"rule": "jQuery-append(",
|
||||||
"path": "js/views/contact_list_view.js",
|
"path": "js/views/contact_list_view.js",
|
||||||
|
@ -1359,20 +1341,11 @@
|
||||||
"updated": "2018-09-15T00:38:04.183Z",
|
"updated": "2018-09-15T00:38:04.183Z",
|
||||||
"reasonDetail": "Value set came directly from Mustache tempating engine"
|
"reasonDetail": "Value set came directly from Mustache tempating engine"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"rule": "jQuery-append(",
|
|
||||||
"path": "js/views/whisper_view.js",
|
|
||||||
"line": " this.$el.append(dialog.el);",
|
|
||||||
"lineNumber": 63,
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2018-09-19T18:13:29.628Z",
|
|
||||||
"reasonDetail": "Interacting with already-existing DOM nodes"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"rule": "jQuery-$(",
|
"rule": "jQuery-$(",
|
||||||
"path": "js/views/whisper_view.js",
|
"path": "js/views/whisper_view.js",
|
||||||
"line": " $('script[type=\"text/x-tmpl-mustache\"]').each((i, el) => {",
|
"line": " $('script[type=\"text/x-tmpl-mustache\"]').each((i, el) => {",
|
||||||
"lineNumber": 72,
|
"lineNumber": 70,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2018-09-19T21:59:32.770Z",
|
"updated": "2018-09-19T21:59:32.770Z",
|
||||||
"reasonDetail": "Protected from arbitrary input"
|
"reasonDetail": "Protected from arbitrary input"
|
||||||
|
@ -1381,7 +1354,7 @@
|
||||||
"rule": "jQuery-$(",
|
"rule": "jQuery-$(",
|
||||||
"path": "js/views/whisper_view.js",
|
"path": "js/views/whisper_view.js",
|
||||||
"line": " const $el = $(el);",
|
"line": " const $el = $(el);",
|
||||||
"lineNumber": 73,
|
"lineNumber": 71,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2018-09-19T21:59:32.770Z",
|
"updated": "2018-09-19T21:59:32.770Z",
|
||||||
"reasonDetail": "Protected from arbitrary input"
|
"reasonDetail": "Protected from arbitrary input"
|
||||||
|
@ -1390,7 +1363,7 @@
|
||||||
"rule": "jQuery-html(",
|
"rule": "jQuery-html(",
|
||||||
"path": "js/views/whisper_view.js",
|
"path": "js/views/whisper_view.js",
|
||||||
"line": " templates[id] = $el.html();",
|
"line": " templates[id] = $el.html();",
|
||||||
"lineNumber": 75,
|
"lineNumber": 73,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2018-09-15T00:38:04.183Z",
|
"updated": "2018-09-15T00:38:04.183Z",
|
||||||
"reasonDetail": "Getting the value, not setting it"
|
"reasonDetail": "Getting the value, not setting it"
|
||||||
|
|
|
@ -2034,7 +2034,8 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.$('.microphone').hide();
|
this.$('.microphone').hide();
|
||||||
},
|
},
|
||||||
handleAudioConfirm(blob: any, lostFocus: any) {
|
handleAudioConfirm(blob: any, lostFocus: any) {
|
||||||
const dialog = new Whisper.ConfirmationDialogView({
|
window.showConfirmationDialog({
|
||||||
|
confirmStyle: 'negative',
|
||||||
cancelText: window.i18n('discard'),
|
cancelText: window.i18n('discard'),
|
||||||
message: lostFocus
|
message: lostFocus
|
||||||
? window.i18n('voiceRecordingInterruptedBlur')
|
? window.i18n('voiceRecordingInterruptedBlur')
|
||||||
|
@ -2044,9 +2045,6 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
await this.handleAudioCapture(blob);
|
await this.handleAudioCapture(blob);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$el.prepend(dialog.el);
|
|
||||||
dialog.focusCancel();
|
|
||||||
},
|
},
|
||||||
async handleAudioCapture(blob: any) {
|
async handleAudioCapture(blob: any) {
|
||||||
if (this.hasFiles()) {
|
if (this.hasFiles()) {
|
||||||
|
@ -2346,7 +2344,8 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
throw new Error(`forceSend: Did not find message for id ${messageId}`);
|
throw new Error(`forceSend: Did not find message for id ${messageId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialog = new Whisper.ConfirmationDialogView({
|
window.showConfirmationDialog({
|
||||||
|
confirmStyle: 'negative',
|
||||||
message: window.i18n('identityKeyErrorOnSend', {
|
message: window.i18n('identityKeyErrorOnSend', {
|
||||||
name1: contact.getTitle(),
|
name1: contact.getTitle(),
|
||||||
name2: contact.getTitle(),
|
name2: contact.getTitle(),
|
||||||
|
@ -2367,9 +2366,6 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
message.resend(contact.getSendTarget());
|
message.resend(contact.getSendTarget());
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$el.prepend(dialog.el);
|
|
||||||
dialog.focusCancel();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showSafetyNumber(id: any) {
|
showSafetyNumber(id: any) {
|
||||||
|
@ -2513,7 +2509,8 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialog = new Whisper.ConfirmationDialogView({
|
window.showConfirmationDialog({
|
||||||
|
confirmStyle: 'negative',
|
||||||
message: window.i18n('deleteWarning'),
|
message: window.i18n('deleteWarning'),
|
||||||
okText: window.i18n('delete'),
|
okText: window.i18n('delete'),
|
||||||
resolve: () => {
|
resolve: () => {
|
||||||
|
@ -2530,9 +2527,6 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.resetPanel();
|
this.resetPanel();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$el.prepend(dialog.el);
|
|
||||||
dialog.focusCancel();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteMessageForEveryone(messageId: string) {
|
deleteMessageForEveryone(messageId: string) {
|
||||||
|
@ -2543,7 +2537,8 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialog = new Whisper.ConfirmationDialogView({
|
window.showConfirmationDialog({
|
||||||
|
confirmStyle: 'negative',
|
||||||
message: window.i18n('deleteForEveryoneWarning'),
|
message: window.i18n('deleteForEveryoneWarning'),
|
||||||
okText: window.i18n('delete'),
|
okText: window.i18n('delete'),
|
||||||
resolve: async () => {
|
resolve: async () => {
|
||||||
|
@ -2551,9 +2546,6 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.resetPanel();
|
this.resetPanel();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$el.prepend(dialog.el);
|
|
||||||
dialog.focusCancel();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showStickerPackPreview(packId: any, packKey: any) {
|
showStickerPackPreview(packId: any, packKey: any) {
|
||||||
|
|
15
ts/window.d.ts
vendored
15
ts/window.d.ts
vendored
|
@ -64,6 +64,7 @@ import { MessageModel } from './models/messages';
|
||||||
import { ConversationModel } from './models/conversations';
|
import { ConversationModel } from './models/conversations';
|
||||||
import { combineNames } from './util';
|
import { combineNames } from './util';
|
||||||
import { BatcherType } from './util/batcher';
|
import { BatcherType } from './util/batcher';
|
||||||
|
import { ConfirmationModal } from './components/ConfirmationModal';
|
||||||
import { ErrorModal } from './components/ErrorModal';
|
import { ErrorModal } from './components/ErrorModal';
|
||||||
import { ProgressModal } from './components/ProgressModal';
|
import { ProgressModal } from './components/ProgressModal';
|
||||||
import { ContactModal } from './components/conversation/ContactModal';
|
import { ContactModal } from './components/conversation/ContactModal';
|
||||||
|
@ -74,6 +75,17 @@ type TaskResultType = any;
|
||||||
|
|
||||||
export type WhatIsThis = any;
|
export type WhatIsThis = any;
|
||||||
|
|
||||||
|
// Synced with the type in ts/shims/showConfirmationDialog
|
||||||
|
// we are duplicating it here because that file cannot import/export.
|
||||||
|
type ConfirmationDialogViewProps = {
|
||||||
|
cancelText?: string;
|
||||||
|
confirmStyle?: 'affirmative' | 'negative';
|
||||||
|
message: string;
|
||||||
|
okText: string;
|
||||||
|
reject?: () => void;
|
||||||
|
resolve: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
_: typeof Underscore;
|
_: typeof Underscore;
|
||||||
|
@ -160,6 +172,7 @@ declare global {
|
||||||
setAutoHideMenuBar: (value: WhatIsThis) => void;
|
setAutoHideMenuBar: (value: WhatIsThis) => void;
|
||||||
setBadgeCount: (count: number) => void;
|
setBadgeCount: (count: number) => void;
|
||||||
setMenuBarVisibility: (value: WhatIsThis) => void;
|
setMenuBarVisibility: (value: WhatIsThis) => void;
|
||||||
|
showConfirmationDialog: (options: ConfirmationDialogViewProps) => void;
|
||||||
showKeyboardShortcuts: () => void;
|
showKeyboardShortcuts: () => void;
|
||||||
storage: {
|
storage: {
|
||||||
addBlockedGroup: (group: string) => void;
|
addBlockedGroup: (group: string) => void;
|
||||||
|
@ -397,6 +410,7 @@ declare global {
|
||||||
Components: {
|
Components: {
|
||||||
AttachmentList: any;
|
AttachmentList: any;
|
||||||
CaptionEditor: any;
|
CaptionEditor: any;
|
||||||
|
ConfirmationModal: typeof ConfirmationModal;
|
||||||
ContactDetail: any;
|
ContactDetail: any;
|
||||||
ErrorModal: typeof ErrorModal;
|
ErrorModal: typeof ErrorModal;
|
||||||
ContactModal: typeof ContactModal;
|
ContactModal: typeof ContactModal;
|
||||||
|
@ -600,7 +614,6 @@ export type WhisperType = {
|
||||||
MessageType: MessageModel;
|
MessageType: MessageModel;
|
||||||
GroupMemberConversation: WhatIsThis;
|
GroupMemberConversation: WhatIsThis;
|
||||||
KeyChangeListener: WhatIsThis;
|
KeyChangeListener: WhatIsThis;
|
||||||
ConfirmationDialogView: WhatIsThis;
|
|
||||||
ClearDataView: WhatIsThis;
|
ClearDataView: WhatIsThis;
|
||||||
ReactWrapperView: WhatIsThis;
|
ReactWrapperView: WhatIsThis;
|
||||||
activeConfirmationView: WhatIsThis;
|
activeConfirmationView: WhatIsThis;
|
||||||
|
|
Loading…
Add table
Reference in a new issue