background.ts/conversation_view.ts modules, Whisper.View/ToastView in TS
This commit is contained in:
parent
2aa2aca9f2
commit
d0e3a2ce29
34 changed files with 957 additions and 887 deletions
|
@ -19,7 +19,7 @@
|
||||||
img-src 'self' blob: data:;
|
img-src 'self' blob: data:;
|
||||||
media-src 'self' blob:;
|
media-src 'self' blob:;
|
||||||
object-src 'none';
|
object-src 'none';
|
||||||
script-src 'self';
|
script-src 'self' 'sha256-5J9nLKMi84ERvoy7r/3XVwiW1iZ5YaPic9BNaF/0rtI=';
|
||||||
style-src 'self' 'unsafe-inline';"
|
style-src 'self' 'unsafe-inline';"
|
||||||
>
|
>
|
||||||
<title>Signal</title>
|
<title>Signal</title>
|
||||||
|
@ -348,14 +348,11 @@
|
||||||
<script type='text/javascript' src='js/message_controller.js'></script>
|
<script type='text/javascript' src='js/message_controller.js'></script>
|
||||||
|
|
||||||
<script type='text/javascript' src='js/views/react_wrapper_view.js'></script>
|
<script type='text/javascript' src='js/views/react_wrapper_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/whisper_view.js'></script>
|
|
||||||
<script type='text/javascript' src='js/views/toast_view.js'></script>
|
|
||||||
<script type='text/javascript' src='js/views/list_view.js'></script>
|
<script type='text/javascript' src='js/views/list_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/contact_list_view.js'></script>
|
<script type='text/javascript' src='js/views/contact_list_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/key_verification_view.js'></script>
|
<script type='text/javascript' src='js/views/key_verification_view.js'></script>
|
||||||
<script type='text/javascript' src='js/views/group_member_list_view.js'></script>
|
<script type='text/javascript' src='js/views/group_member_list_view.js'></script>
|
||||||
<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='js/views/inbox_view.js'></script>
|
<script type='text/javascript' src='js/views/inbox_view.js'></script>
|
||||||
<script type='text/javascript' src='ts/shims/showConfirmationDialog.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>
|
||||||
|
@ -386,6 +383,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type='text/javascript' src='ts/background.js'></script>
|
<!--
|
||||||
|
Note: this inline script cannot be changed without also changing the hash in
|
||||||
|
the CSP at the top of this file
|
||||||
|
-->
|
||||||
|
<script type='text/javascript'>
|
||||||
|
window.startApp();
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -55,8 +55,6 @@
|
||||||
</script>
|
</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/toast_view.js'></script>
|
|
||||||
<script type='text/javascript' src='js/views/debug_log_view.js'></script>
|
<script type='text/javascript' src='js/views/debug_log_view.js'></script>
|
||||||
<script type='text/javascript' src='js/debug_log_start.js'></script>
|
<script type='text/javascript' src='js/debug_log_start.js'></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -29,6 +29,9 @@ window.nodeSetImmediate = setImmediate;
|
||||||
window.getNodeVersion = () => config.node_version;
|
window.getNodeVersion = () => config.node_version;
|
||||||
window.getEnvironment = getEnvironment;
|
window.getEnvironment = getEnvironment;
|
||||||
|
|
||||||
|
window.Backbone = require('backbone');
|
||||||
|
require('./ts/backbone/views/whisper_view');
|
||||||
|
require('./ts/backbone/views/toast_view');
|
||||||
require('./ts/logging/set_up_renderer_logging');
|
require('./ts/logging/set_up_renderer_logging');
|
||||||
|
|
||||||
window.closeDebugLog = () => ipcRenderer.send('close-debug-log');
|
window.closeDebugLog = () => ipcRenderer.send('close-debug-log');
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2017-2020 Signal Messenger, LLC
|
// Copyright 2017-2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global Whisper */
|
/* global Whisper, $ */
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
Whisper.BannerView = Whisper.View.extend({
|
Whisper.BannerView = Whisper.View.extend({
|
||||||
className: 'banner',
|
className: 'banner',
|
||||||
templateName: 'banner',
|
template: () => $('#banner').html(),
|
||||||
events: {
|
events: {
|
||||||
'click .dismiss': 'onDismiss',
|
'click .dismiss': 'onDismiss',
|
||||||
'click .body': 'onClick',
|
'click .body': 'onClick',
|
||||||
|
|
|
@ -1,10 +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 i18n: false */
|
/* global i18n, Whisper, $ */
|
||||||
/* global Whisper: false */
|
|
||||||
|
|
||||||
/* eslint-disable no-new */
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -16,7 +13,7 @@
|
||||||
DELETING: 2,
|
DELETING: 2,
|
||||||
};
|
};
|
||||||
window.Whisper.ClearDataView = Whisper.View.extend({
|
window.Whisper.ClearDataView = Whisper.View.extend({
|
||||||
templateName: 'clear-data',
|
template: () => $('#clear-data').html(),
|
||||||
className: 'full-screen-flow overlay',
|
className: 'full-screen-flow overlay',
|
||||||
events: {
|
events: {
|
||||||
'click .cancel': 'onCancel',
|
'click .cancel': 'onCancel',
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
// Copyright 2015-2020 Signal Messenger, LLC
|
// Copyright 2015-2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global Whisper: false */
|
/* global Whisper, textsecure, $ */
|
||||||
/* global textsecure: false */
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -13,7 +12,7 @@
|
||||||
itemView: Whisper.View.extend({
|
itemView: Whisper.View.extend({
|
||||||
tagName: 'div',
|
tagName: 'div',
|
||||||
className: 'contact',
|
className: 'contact',
|
||||||
templateName: 'contact',
|
template: () => $('#contact').html(),
|
||||||
initialize(options) {
|
initialize(options) {
|
||||||
this.ourNumber = textsecure.storage.user.getNumber();
|
this.ourNumber = textsecure.storage.user.getNumber();
|
||||||
this.listenBack = options.listenBack;
|
this.listenBack = options.listenBack;
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
// Copyright 2015-2021 Signal Messenger, LLC
|
// Copyright 2015-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global i18n: false */
|
/* global i18n, Whisper, $ */
|
||||||
/* global Whisper: false */
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -31,7 +30,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.DebugLogLinkView = Whisper.View.extend({
|
Whisper.DebugLogLinkView = Whisper.View.extend({
|
||||||
templateName: 'debug-log-link',
|
template: () => $('#debug-log-link').html(),
|
||||||
initialize(options) {
|
initialize(options) {
|
||||||
this.url = options.url;
|
this.url = options.url;
|
||||||
},
|
},
|
||||||
|
@ -66,7 +65,7 @@
|
||||||
* edit them in their own editor. This is mostly a stopgap solution.
|
* edit them in their own editor. This is mostly a stopgap solution.
|
||||||
*/
|
*/
|
||||||
Whisper.DebugLogView = Whisper.View.extend({
|
Whisper.DebugLogView = Whisper.View.extend({
|
||||||
templateName: 'debug-log',
|
template: () => $('#debug-log').html(),
|
||||||
className: 'debug-log modal',
|
className: 'debug-log modal',
|
||||||
initialize() {
|
initialize() {
|
||||||
this.render();
|
this.render();
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
// Copyright 2015-2020 Signal Messenger, LLC
|
// Copyright 2015-2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global Whisper, i18n */
|
/* global Whisper, i18n, $ */
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
window.Whisper = window.Whisper || {};
|
window.Whisper = window.Whisper || {};
|
||||||
|
|
||||||
// TODO: take a title string which could replace the 'members' header
|
|
||||||
Whisper.GroupMemberList = Whisper.View.extend({
|
Whisper.GroupMemberList = Whisper.View.extend({
|
||||||
className: 'group-member-list panel',
|
className: 'group-member-list panel',
|
||||||
templateName: 'group-member-list',
|
template: () => $('#group-member-list').html(),
|
||||||
initialize(options) {
|
initialize(options) {
|
||||||
this.needVerify = options.needVerify;
|
this.needVerify = options.needVerify;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2015-2021 Signal Messenger, LLC
|
// Copyright 2015-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global Whisper, loadImage */
|
/* global Whisper, loadImage, $ */
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
* Render an avatar identicon to an svg for use in a notification.
|
* Render an avatar identicon to an svg for use in a notification.
|
||||||
*/
|
*/
|
||||||
Whisper.IdenticonSVGView = Whisper.View.extend({
|
Whisper.IdenticonSVGView = Whisper.View.extend({
|
||||||
templateName: 'identicon-svg',
|
template: () => $('#identicon-svg').html(),
|
||||||
initialize(options) {
|
initialize(options) {
|
||||||
this.render_attributes = options;
|
this.render_attributes = options;
|
||||||
this.render_attributes.color = COLORS[this.render_attributes.color];
|
this.render_attributes.color = COLORS[this.render_attributes.color];
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
ConversationController,
|
ConversationController,
|
||||||
i18n,
|
i18n,
|
||||||
Whisper,
|
Whisper,
|
||||||
Signal
|
Signal,
|
||||||
|
$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
|
@ -60,7 +61,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.AppLoadingScreen = Whisper.View.extend({
|
Whisper.AppLoadingScreen = Whisper.View.extend({
|
||||||
templateName: 'app-loading-screen',
|
template: () => $('#app-loading-screen').html(),
|
||||||
className: 'app-loading-screen',
|
className: 'app-loading-screen',
|
||||||
updateProgress(count) {
|
updateProgress(count) {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
|
@ -74,7 +75,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.InboxView = Whisper.View.extend({
|
Whisper.InboxView = Whisper.View.extend({
|
||||||
templateName: 'two-column',
|
template: () => $('#two-column').html(),
|
||||||
className: 'inbox index',
|
className: 'inbox index',
|
||||||
initialize(options = {}) {
|
initialize(options = {}) {
|
||||||
this.ready = false;
|
this.ready = false;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
const TOO_OLD = 409;
|
const TOO_OLD = 409;
|
||||||
|
|
||||||
Whisper.InstallView = Whisper.View.extend({
|
Whisper.InstallView = Whisper.View.extend({
|
||||||
templateName: 'link-flow-template',
|
template: () => $('#link-flow-template').html(),
|
||||||
className: 'main full-screen-flow',
|
className: 'main full-screen-flow',
|
||||||
events: {
|
events: {
|
||||||
'click .try-again': 'connect',
|
'click .try-again': 'connect',
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
// Copyright 2015-2020 Signal Messenger, LLC
|
// Copyright 2015-2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global Backbone, Signal, Whisper */
|
/* global Backbone, Signal, Whisper, $ */
|
||||||
|
|
||||||
/* eslint-disable more/no-then */
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -11,7 +9,7 @@
|
||||||
|
|
||||||
Whisper.KeyVerificationPanelView = Whisper.View.extend({
|
Whisper.KeyVerificationPanelView = Whisper.View.extend({
|
||||||
className: 'panel',
|
className: 'panel',
|
||||||
templateName: 'key-verification',
|
template: () => $('#key-verification').html(),
|
||||||
initialize(options) {
|
initialize(options) {
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2015-2020 Signal Messenger, LLC
|
// Copyright 2015-2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global libphonenumber, Whisper */
|
/* global libphonenumber, Whisper, $ */
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
Whisper.PhoneInputView = Whisper.View.extend({
|
Whisper.PhoneInputView = Whisper.View.extend({
|
||||||
tagName: 'div',
|
tagName: 'div',
|
||||||
className: 'phone-input',
|
className: 'phone-input',
|
||||||
templateName: 'phone-number',
|
template: () => $('#phone-number').html(),
|
||||||
initialize() {
|
initialize() {
|
||||||
this.$('input.number').intlTelInput();
|
this.$('input.number').intlTelInput();
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
Whisper.RecorderView = Whisper.View.extend({
|
Whisper.RecorderView = Whisper.View.extend({
|
||||||
className: 'recorder clearfix',
|
className: 'recorder clearfix',
|
||||||
templateName: 'recorder',
|
template: () => $('#recorder').html(),
|
||||||
initialize() {
|
initialize() {
|
||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
this.interval = setInterval(this.updateTime.bind(this), 1000);
|
this.interval = setInterval(this.updateTime.bind(this), 1000);
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
// Copyright 2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
/* global Whisper, Signal */
|
/* global Whisper, Signal, $ */
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
// eslint-disable-next-line func-names
|
||||||
(function () {
|
(function () {
|
||||||
window.Whisper = window.Whisper || {};
|
window.Whisper = window.Whisper || {};
|
||||||
|
|
||||||
Whisper.SafetyNumberChangeDialogView = Whisper.View.extend({
|
Whisper.SafetyNumberChangeDialogView = Whisper.View.extend({
|
||||||
templateName: 'safety-number-change-dialog',
|
template: () => $('#safety-number-change-dialog').html(),
|
||||||
initialize(options) {
|
initialize(options) {
|
||||||
const dialog = new Whisper.ReactWrapperView({
|
const dialog = new Whisper.ReactWrapperView({
|
||||||
Component: window.Signal.Components.SafetyNumberChangeDialog,
|
Component: window.Signal.Components.SafetyNumberChangeDialog,
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
});
|
});
|
||||||
Whisper.SettingsView = Whisper.View.extend({
|
Whisper.SettingsView = Whisper.View.extend({
|
||||||
className: 'settings modal expand',
|
className: 'settings modal expand',
|
||||||
templateName: 'settings',
|
template: () => $('#settings').html(),
|
||||||
initialize() {
|
initialize() {
|
||||||
this.render();
|
this.render();
|
||||||
new RadioButtonGroupView({
|
new RadioButtonGroupView({
|
||||||
|
@ -271,7 +271,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const SyncView = Whisper.View.extend({
|
const SyncView = Whisper.View.extend({
|
||||||
templateName: 'syncSettings',
|
template: () => $('#syncSettings').html(),
|
||||||
className: 'syncSettings',
|
className: 'syncSettings',
|
||||||
events: {
|
events: {
|
||||||
'click .sync': 'sync',
|
'click .sync': 'sync',
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
window.Whisper = window.Whisper || {};
|
window.Whisper = window.Whisper || {};
|
||||||
|
|
||||||
Whisper.StandaloneRegistrationView = Whisper.View.extend({
|
Whisper.StandaloneRegistrationView = Whisper.View.extend({
|
||||||
templateName: 'standalone',
|
template: () => $('#standalone').html(),
|
||||||
className: 'full-screen-flow',
|
className: 'full-screen-flow',
|
||||||
initialize() {
|
initialize() {
|
||||||
window.readyForUpdates();
|
window.readyForUpdates();
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
// Copyright 2015-2020 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
/* global Whisper, Mustache, _ */
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
|
||||||
(function () {
|
|
||||||
window.Whisper = window.Whisper || {};
|
|
||||||
|
|
||||||
Whisper.ToastView = Whisper.View.extend({
|
|
||||||
className: 'toast',
|
|
||||||
templateName: 'toast',
|
|
||||||
initialize() {
|
|
||||||
this.$el.hide();
|
|
||||||
this.timeout = 2000;
|
|
||||||
},
|
|
||||||
|
|
||||||
close() {
|
|
||||||
this.$el.fadeOut(this.remove.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
|
||||||
this.$el.html(
|
|
||||||
Mustache.render(
|
|
||||||
_.result(this, 'template', ''),
|
|
||||||
_.result(this, 'render_attributes', '')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.$el.attr('tabIndex', 0);
|
|
||||||
this.$el.show();
|
|
||||||
setTimeout(this.close.bind(this), this.timeout);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Whisper.ToastView.show = (View, el) => {
|
|
||||||
const toast = new View();
|
|
||||||
toast.$el.appendTo(el);
|
|
||||||
toast.render();
|
|
||||||
};
|
|
||||||
})();
|
|
|
@ -1,79 +0,0 @@
|
||||||
// Copyright 2015-2020 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
/* global Whisper, Backbone, Mustache, _, $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Whisper.View
|
|
||||||
*
|
|
||||||
* This is the base for most of our views. The Backbone view is extended
|
|
||||||
* with some conveniences:
|
|
||||||
*
|
|
||||||
* 1. Pre-parses all our mustache templates for performance.
|
|
||||||
* https://github.com/janl/mustache.js#pre-parsing-and-caching-templates
|
|
||||||
*
|
|
||||||
* 2. Defines a default definition for render() which allows sub-classes
|
|
||||||
* to simply specify a templateName and renderAttributes which are plugged
|
|
||||||
* into Mustache.render
|
|
||||||
*
|
|
||||||
* 3. Makes all the templates available for rendering as partials.
|
|
||||||
* https://github.com/janl/mustache.js#partials
|
|
||||||
*
|
|
||||||
* 4. Provides some common functionality, e.g. confirmation dialog
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
|
||||||
(function () {
|
|
||||||
window.Whisper = window.Whisper || {};
|
|
||||||
|
|
||||||
Whisper.View = Backbone.View.extend(
|
|
||||||
{
|
|
||||||
constructor(...params) {
|
|
||||||
Backbone.View.call(this, ...params);
|
|
||||||
Mustache.parse(_.result(this, 'template'));
|
|
||||||
},
|
|
||||||
render_attributes() {
|
|
||||||
return _.result(this.model, 'attributes', {});
|
|
||||||
},
|
|
||||||
render_partials() {
|
|
||||||
return Whisper.View.Templates;
|
|
||||||
},
|
|
||||||
template() {
|
|
||||||
if (this.templateName) {
|
|
||||||
return Whisper.View.Templates[this.templateName];
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
render() {
|
|
||||||
const attrs = _.result(this, 'render_attributes', {});
|
|
||||||
const template = _.result(this, 'template', '');
|
|
||||||
const partials = _.result(this, 'render_partials', '');
|
|
||||||
this.$el.html(Mustache.render(template, attrs, partials));
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
confirm(message, okText) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
window.showConfirmationDialog({
|
|
||||||
message,
|
|
||||||
okText,
|
|
||||||
resolve,
|
|
||||||
reject,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Class attributes
|
|
||||||
Templates: (() => {
|
|
||||||
const templates = {};
|
|
||||||
$('script[type="text/x-tmpl-mustache"]').each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
const id = $el.attr('id');
|
|
||||||
templates[id] = $el.html();
|
|
||||||
});
|
|
||||||
return templates;
|
|
||||||
})(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
})();
|
|
|
@ -25,7 +25,6 @@
|
||||||
</body>
|
</body>
|
||||||
<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='ts/shims/showConfirmationDialog.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>
|
||||||
|
|
|
@ -520,6 +520,11 @@ try {
|
||||||
require('./ts/models/messages');
|
require('./ts/models/messages');
|
||||||
require('./ts/models/conversations');
|
require('./ts/models/conversations');
|
||||||
|
|
||||||
|
require('./ts/backbone/views/whisper_view');
|
||||||
|
require('./ts/backbone/views/toast_view');
|
||||||
|
require('./ts/views/conversation_view');
|
||||||
|
require('./ts/background');
|
||||||
|
|
||||||
function wrapWithPromise(fn) {
|
function wrapWithPromise(fn) {
|
||||||
return (...args) => Promise.resolve(fn(...args));
|
return (...args) => Promise.resolve(fn(...args));
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,6 @@
|
||||||
</script>
|
</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/settings_view.js'></script>
|
<script type='text/javascript' src='js/views/settings_view.js'></script>
|
||||||
<script type='text/javascript' src='js/settings_start.js'></script>
|
<script type='text/javascript' src='js/settings_start.js'></script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -126,6 +126,7 @@ function makeSetter(name) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
require('./ts/logging/set_up_renderer_logging');
|
|
||||||
|
|
||||||
window.Backbone = require('backbone');
|
window.Backbone = require('backbone');
|
||||||
|
require('./ts/backbone/views/whisper_view');
|
||||||
|
require('./ts/backbone/views/toast_view');
|
||||||
|
require('./ts/logging/set_up_renderer_logging');
|
||||||
|
|
35
ts/backbone/views/toast_view.ts
Normal file
35
ts/backbone/views/toast_view.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2015-2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
window.Whisper = window.Whisper || {};
|
||||||
|
|
||||||
|
window.Whisper.ToastView = window.Whisper.View.extend({
|
||||||
|
className: 'toast',
|
||||||
|
template: () => $('#toast').html(),
|
||||||
|
initialize() {
|
||||||
|
this.$el.hide();
|
||||||
|
this.timeout = 2000;
|
||||||
|
},
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.$el.fadeOut(this.remove.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.$el.html(
|
||||||
|
window.Mustache.render(
|
||||||
|
window._.result(this, 'template', ''),
|
||||||
|
window._.result(this, 'render_attributes', '')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
this.$el.attr('tabIndex', 0);
|
||||||
|
this.$el.show();
|
||||||
|
setTimeout(this.close.bind(this), this.timeout);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
window.Whisper.ToastView.show = (View, el) => {
|
||||||
|
const toast = new View();
|
||||||
|
toast.$el.appendTo(el);
|
||||||
|
toast.render();
|
||||||
|
};
|
32
ts/backbone/views/whisper_view.ts
Normal file
32
ts/backbone/views/whisper_view.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2015-2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines a default definition for render() which allows sub-classes
|
||||||
|
* to simply specify a template property and renderAttributes which are plugged
|
||||||
|
* into Mustache.render
|
||||||
|
*/
|
||||||
|
|
||||||
|
// eslint-disable-next-line func-names
|
||||||
|
(function () {
|
||||||
|
window.Whisper = window.Whisper || {};
|
||||||
|
|
||||||
|
window.Whisper.View = Backbone.View.extend({
|
||||||
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||||
|
constructor(...params: Array<any>) {
|
||||||
|
window.Backbone.View.call(this, ...params);
|
||||||
|
|
||||||
|
// Checks for syntax errors
|
||||||
|
window.Mustache.parse(_.result(this, 'template'));
|
||||||
|
},
|
||||||
|
render_attributes() {
|
||||||
|
return _.result(this.model, 'attributes', {});
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const attrs = window._.result(this, 'render_attributes', {});
|
||||||
|
const template = window._.result(this, 'template', '');
|
||||||
|
this.$el.html(window.Mustache.render(template, attrs));
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})();
|
|
@ -1,15 +1,10 @@
|
||||||
// Copyright 2020-2021 Signal Messenger, LLC
|
// Copyright 2020-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
// This allows us to pull in types despite the fact that this is not a module. We can't
|
import { DataMessageClass } from './textsecure.d';
|
||||||
// use normal import syntax, nor can we use 'import type' syntax, or this will be turned
|
import { WhatIsThis } from './window.d';
|
||||||
// into a module, and we'll get the dreaded 'exports is not defined' error.
|
|
||||||
// see https://github.com/microsoft/TypeScript/issues/41562
|
|
||||||
type DataMessageClass = import('./textsecure.d').DataMessageClass;
|
|
||||||
type WhatIsThis = import('./window.d').WhatIsThis;
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
export async function startApp(): Promise<void> {
|
||||||
(async function () {
|
|
||||||
const eventHandlerQueue = new window.PQueue({
|
const eventHandlerQueue = new window.PQueue({
|
||||||
concurrency: 1,
|
concurrency: 1,
|
||||||
timeout: 1000 * 60 * 2,
|
timeout: 1000 * 60 * 2,
|
||||||
|
@ -23,7 +18,7 @@ type WhatIsThis = import('./window.d').WhatIsThis;
|
||||||
wait: 500,
|
wait: 500,
|
||||||
maxSize: 500,
|
maxSize: 500,
|
||||||
processBatch: async (items: WhatIsThis) => {
|
processBatch: async (items: WhatIsThis) => {
|
||||||
const byConversationId = _.groupBy(items, item =>
|
const byConversationId = window._.groupBy(items, item =>
|
||||||
window.ConversationController.ensureContactIds({
|
window.ConversationController.ensureContactIds({
|
||||||
e164: item.source,
|
e164: item.source,
|
||||||
uuid: item.sourceUuid,
|
uuid: item.sourceUuid,
|
||||||
|
@ -205,12 +200,12 @@ type WhatIsThis = import('./window.d').WhatIsThis;
|
||||||
if (messageReceiver) {
|
if (messageReceiver) {
|
||||||
return messageReceiver.getStatus();
|
return messageReceiver.getStatus();
|
||||||
}
|
}
|
||||||
if (_.isNumber(preMessageReceiverStatus)) {
|
if (window._.isNumber(preMessageReceiverStatus)) {
|
||||||
return preMessageReceiverStatus;
|
return preMessageReceiverStatus;
|
||||||
}
|
}
|
||||||
return WebSocket.CLOSED;
|
return WebSocket.CLOSED;
|
||||||
};
|
};
|
||||||
window.Whisper.events = _.clone(window.Backbone.Events);
|
window.Whisper.events = window._.clone(window.Backbone.Events);
|
||||||
let accountManager: typeof window.textsecure.AccountManager;
|
let accountManager: typeof window.textsecure.AccountManager;
|
||||||
window.getAccountManager = () => {
|
window.getAccountManager = () => {
|
||||||
if (!accountManager) {
|
if (!accountManager) {
|
||||||
|
@ -2632,7 +2627,7 @@ type WhatIsThis = import('./window.d').WhatIsThis;
|
||||||
sentTo = data.unidentifiedStatus.map(
|
sentTo = data.unidentifiedStatus.map(
|
||||||
(item: WhatIsThis) => item.destinationUuid || item.destination
|
(item: WhatIsThis) => item.destinationUuid || item.destination
|
||||||
);
|
);
|
||||||
const unidentified = _.filter(data.unidentifiedStatus, item =>
|
const unidentified = window._.filter(data.unidentifiedStatus, item =>
|
||||||
Boolean(item.unidentified)
|
Boolean(item.unidentified)
|
||||||
);
|
);
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
@ -3284,4 +3279,6 @@ type WhatIsThis = import('./window.d').WhatIsThis;
|
||||||
// Note: We don't wait for completion here
|
// Note: We don't wait for completion here
|
||||||
window.Whisper.DeliveryReceipts.onReceipt(receipt);
|
window.Whisper.DeliveryReceipts.onReceipt(receipt);
|
||||||
}
|
}
|
||||||
})();
|
}
|
||||||
|
|
||||||
|
window.startApp = startApp;
|
||||||
|
|
|
@ -61,7 +61,7 @@ export async function joinViaLink(hash: string): Promise<void> {
|
||||||
window.reduxActions.conversations.openConversationInternal({
|
window.reduxActions.conversations.openConversationInternal({
|
||||||
conversationId: existingConversation.id,
|
conversationId: existingConversation.id,
|
||||||
});
|
});
|
||||||
window.window.Whisper.ToastView.show(
|
window.Whisper.ToastView.show(
|
||||||
window.Whisper.AlreadyGroupMemberToast,
|
window.Whisper.AlreadyGroupMemberToast,
|
||||||
document.getElementsByClassName('conversation-stack')[0]
|
document.getElementsByClassName('conversation-stack')[0]
|
||||||
);
|
);
|
||||||
|
@ -333,7 +333,7 @@ export async function joinViaLink(hash: string): Promise<void> {
|
||||||
|
|
||||||
window.log.info(`joinViaLink/${logId}: Showing modal`);
|
window.log.info(`joinViaLink/${logId}: Showing modal`);
|
||||||
|
|
||||||
let groupV2InfoDialog = new Whisper.ReactWrapperView({
|
let groupV2InfoDialog = new window.Whisper.ReactWrapperView({
|
||||||
className: 'group-v2-join-dialog-wrapper',
|
className: 'group-v2-join-dialog-wrapper',
|
||||||
JSX: window.Signal.State.Roots.createGroupV2JoinModal(window.reduxStore, {
|
JSX: window.Signal.State.Roots.createGroupV2JoinModal(window.reduxStore, {
|
||||||
join,
|
join,
|
||||||
|
|
|
@ -4052,7 +4052,7 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
this.set({ left: true });
|
this.set({ left: true });
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
window.Signal.Data.updateConversation(this.attributes);
|
||||||
|
|
||||||
const model = new Whisper.Message(({
|
const model = new window.Whisper.Message(({
|
||||||
group_update: { left: 'You' },
|
group_update: { left: 'You' },
|
||||||
conversationId: this.id,
|
conversationId: this.id,
|
||||||
type: 'outgoing',
|
type: 'outgoing',
|
||||||
|
@ -4062,7 +4062,7 @@ export class ConversationModel extends window.Backbone.Model<
|
||||||
} as unknown) as MessageAttributesType);
|
} as unknown) as MessageAttributesType);
|
||||||
|
|
||||||
const id = await window.Signal.Data.saveMessage(model.attributes, {
|
const id = await window.Signal.Data.saveMessage(model.attributes, {
|
||||||
Message: Whisper.Message,
|
Message: window.Whisper.Message,
|
||||||
});
|
});
|
||||||
model.set({ id });
|
model.set({ id });
|
||||||
|
|
||||||
|
@ -5128,13 +5128,13 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
||||||
|
|
||||||
// We create a new model if it's not already a model
|
// We create a new model if it's not already a model
|
||||||
if (!item.get) {
|
if (!item.get) {
|
||||||
hydratedData.push(new Whisper.Conversation(item));
|
hydratedData.push(new window.Whisper.Conversation(item));
|
||||||
} else {
|
} else {
|
||||||
hydratedData.push(item);
|
hydratedData.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!data.get) {
|
} else if (!data.get) {
|
||||||
hydratedData = new Whisper.Conversation(data);
|
hydratedData = new window.Whisper.Conversation(data);
|
||||||
} else {
|
} else {
|
||||||
hydratedData = data;
|
hydratedData = data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ type ConfirmationDialogViewProps = {
|
||||||
confirmStyle?: 'affirmative' | 'negative';
|
confirmStyle?: 'affirmative' | 'negative';
|
||||||
message: string;
|
message: string;
|
||||||
okText: string;
|
okText: string;
|
||||||
reject?: () => void;
|
reject?: (error: Error) => void;
|
||||||
resolve: () => void;
|
resolve: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ function showConfirmationDialog(options: ConfirmationDialogViewProps) {
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
removeConfirmationDialog();
|
removeConfirmationDialog();
|
||||||
if (options.reject) {
|
if (options.reject) {
|
||||||
options.reject();
|
options.reject(new Error('showConfirmationDialog: onClose called'));
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
title={options.message}
|
title={options.message}
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe('Message', () => {
|
||||||
const ourUuid = window.getGuid();
|
const ourUuid = window.getGuid();
|
||||||
|
|
||||||
function createMessage(attrs: { [key: string]: unknown }) {
|
function createMessage(attrs: { [key: string]: unknown }) {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
return messages.add(attrs);
|
return messages.add(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,13 +136,13 @@ describe('Message', () => {
|
||||||
|
|
||||||
describe('getContact', () => {
|
describe('getContact', () => {
|
||||||
it('gets outgoing contact', () => {
|
it('gets outgoing contact', () => {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
const message = messages.add(attributes);
|
const message = messages.add(attributes);
|
||||||
message.getContact();
|
message.getContact();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gets incoming contact', () => {
|
it('gets incoming contact', () => {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
const message = messages.add({
|
const message = messages.add({
|
||||||
type: 'incoming',
|
type: 'incoming',
|
||||||
source,
|
source,
|
||||||
|
@ -153,7 +153,7 @@ describe('Message', () => {
|
||||||
|
|
||||||
describe('isIncoming', () => {
|
describe('isIncoming', () => {
|
||||||
it('checks if is incoming message', () => {
|
it('checks if is incoming message', () => {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
let message = messages.add(attributes);
|
let message = messages.add(attributes);
|
||||||
assert.notOk(message.isIncoming());
|
assert.notOk(message.isIncoming());
|
||||||
message = messages.add({ type: 'incoming' });
|
message = messages.add({ type: 'incoming' });
|
||||||
|
@ -163,7 +163,7 @@ describe('Message', () => {
|
||||||
|
|
||||||
describe('isOutgoing', () => {
|
describe('isOutgoing', () => {
|
||||||
it('checks if is outgoing message', () => {
|
it('checks if is outgoing message', () => {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
let message = messages.add(attributes);
|
let message = messages.add(attributes);
|
||||||
assert.ok(message.isOutgoing());
|
assert.ok(message.isOutgoing());
|
||||||
message = messages.add({ type: 'incoming' });
|
message = messages.add({ type: 'incoming' });
|
||||||
|
@ -173,7 +173,7 @@ describe('Message', () => {
|
||||||
|
|
||||||
describe('isGroupUpdate', () => {
|
describe('isGroupUpdate', () => {
|
||||||
it('checks if is group update', () => {
|
it('checks if is group update', () => {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
let message = messages.add(attributes);
|
let message = messages.add(attributes);
|
||||||
assert.notOk(message.isGroupUpdate());
|
assert.notOk(message.isGroupUpdate());
|
||||||
|
|
||||||
|
@ -584,7 +584,7 @@ describe('Message', () => {
|
||||||
|
|
||||||
describe('isEndSession', () => {
|
describe('isEndSession', () => {
|
||||||
it('checks if it is end of the session', () => {
|
it('checks if it is end of the session', () => {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
let message = messages.add(attributes);
|
let message = messages.add(attributes);
|
||||||
assert.notOk(message.isEndSession());
|
assert.notOk(message.isEndSession());
|
||||||
|
|
||||||
|
@ -596,7 +596,7 @@ describe('Message', () => {
|
||||||
|
|
||||||
describe('MessageCollection', () => {
|
describe('MessageCollection', () => {
|
||||||
it('should be ordered oldest to newest', () => {
|
it('should be ordered oldest to newest', () => {
|
||||||
const messages = new Whisper.MessageCollection();
|
const messages = new window.Whisper.MessageCollection();
|
||||||
// Timestamps
|
// Timestamps
|
||||||
const today = Date.now();
|
const today = Date.now();
|
||||||
const tomorrow = today + 12345;
|
const tomorrow = today + 12345;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,14 +16,14 @@ export async function longRunningTaskWrapper<T>({
|
||||||
const ONE_SECOND = 1000;
|
const ONE_SECOND = 1000;
|
||||||
const TWO_SECONDS = 2000;
|
const TWO_SECONDS = 2000;
|
||||||
|
|
||||||
let progressView: typeof Whisper.ReactWrapperView | undefined;
|
let progressView: typeof window.Whisper.ReactWrapperView | undefined;
|
||||||
let spinnerStart;
|
let spinnerStart;
|
||||||
let progressTimeout: NodeJS.Timeout | undefined = setTimeout(() => {
|
let progressTimeout: NodeJS.Timeout | undefined = setTimeout(() => {
|
||||||
window.log.info(`longRunningTaskWrapper/${idLog}: Creating spinner`);
|
window.log.info(`longRunningTaskWrapper/${idLog}: Creating spinner`);
|
||||||
|
|
||||||
// Note: this component uses a portal to render itself into the top-level DOM. No
|
// Note: this component uses a portal to render itself into the top-level DOM. No
|
||||||
// need to attach it to the DOM here.
|
// need to attach it to the DOM here.
|
||||||
progressView = new Whisper.ReactWrapperView({
|
progressView = new window.Whisper.ReactWrapperView({
|
||||||
className: 'progress-modal-wrapper',
|
className: 'progress-modal-wrapper',
|
||||||
Component: window.Signal.Components.ProgressModal,
|
Component: window.Signal.Components.ProgressModal,
|
||||||
});
|
});
|
||||||
|
@ -76,7 +76,7 @@ export async function longRunningTaskWrapper<T>({
|
||||||
|
|
||||||
// Note: this component uses a portal to render itself into the top-level DOM. No
|
// Note: this component uses a portal to render itself into the top-level DOM. No
|
||||||
// need to attach it to the DOM here.
|
// need to attach it to the DOM here.
|
||||||
const errorView = new Whisper.ReactWrapperView({
|
const errorView = new window.Whisper.ReactWrapperView({
|
||||||
className: 'error-modal-wrapper',
|
className: 'error-modal-wrapper',
|
||||||
Component: window.Signal.Components.ErrorModal,
|
Component: window.Signal.Components.ErrorModal,
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -3,14 +3,10 @@
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
// This allows us to pull in types despite the fact that this is not a module. We can't
|
import { AttachmentType } from '../types/Attachment';
|
||||||
// use normal import syntax, nor can we use 'import type' syntax, or this will be turned
|
import { GroupV2PendingMemberType } from '../model-types.d';
|
||||||
// into a module, and we'll get the dreaded 'exports is not defined' error.
|
import { MediaItemType } from '../components/LightboxGallery';
|
||||||
// see https://github.com/microsoft/TypeScript/issues/41562
|
import { MessageType } from '../state/ducks/conversations';
|
||||||
type AttachmentType = import('../types/Attachment').AttachmentType;
|
|
||||||
type GroupV2PendingMemberType = import('../model-types.d').GroupV2PendingMemberType;
|
|
||||||
type MediaItemType = import('../components/LightboxGallery').MediaItemType;
|
|
||||||
type MessageType = import('../state/ducks/conversations').MessageType;
|
|
||||||
|
|
||||||
type GetLinkPreviewImageResult = {
|
type GetLinkPreviewImageResult = {
|
||||||
data: ArrayBuffer;
|
data: ArrayBuffer;
|
||||||
|
@ -250,7 +246,7 @@ Whisper.MessageBodyTooLongToast = Whisper.ToastView.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.FileSizeToast = Whisper.ToastView.extend({
|
Whisper.FileSizeToast = Whisper.ToastView.extend({
|
||||||
templateName: 'file-size-modal',
|
template: () => $('#file-size-modal').html(),
|
||||||
render_attributes() {
|
render_attributes() {
|
||||||
return {
|
return {
|
||||||
'file-size-warning': window.i18n('fileSizeWarning'),
|
'file-size-warning': window.i18n('fileSizeWarning'),
|
||||||
|
@ -267,31 +263,31 @@ Whisper.UnableToLoadToast = Whisper.ToastView.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.DangerousFileTypeToast = Whisper.ToastView.extend({
|
Whisper.DangerousFileTypeToast = Whisper.ToastView.extend({
|
||||||
template: window.i18n('dangerousFileType'),
|
template: () => window.i18n('dangerousFileType'),
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.OneNonImageAtATimeToast = Whisper.ToastView.extend({
|
Whisper.OneNonImageAtATimeToast = Whisper.ToastView.extend({
|
||||||
template: window.i18n('oneNonImageAtATimeToast'),
|
template: () => window.i18n('oneNonImageAtATimeToast'),
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.CannotMixImageAndNonImageAttachmentsToast = Whisper.ToastView.extend({
|
Whisper.CannotMixImageAndNonImageAttachmentsToast = Whisper.ToastView.extend({
|
||||||
template: window.i18n('cannotMixImageAndNonImageAttachments'),
|
template: () => window.i18n('cannotMixImageAndNonImageAttachments'),
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.MaxAttachmentsToast = Whisper.ToastView.extend({
|
Whisper.MaxAttachmentsToast = Whisper.ToastView.extend({
|
||||||
template: window.i18n('maximumAttachments'),
|
template: () => window.i18n('maximumAttachments'),
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.AlreadyGroupMemberToast = Whisper.ToastView.extend({
|
Whisper.AlreadyGroupMemberToast = Whisper.ToastView.extend({
|
||||||
template: window.i18n('GroupV2--join--already-in-group'),
|
template: () => window.i18n('GroupV2--join--already-in-group'),
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.AlreadyRequestedToJoinToast = Whisper.ToastView.extend({
|
Whisper.AlreadyRequestedToJoinToast = Whisper.ToastView.extend({
|
||||||
template: window.i18n('GroupV2--join--already-awaiting-approval'),
|
template: () => window.i18n('GroupV2--join--already-awaiting-approval'),
|
||||||
});
|
});
|
||||||
|
|
||||||
Whisper.ConversationLoadingScreen = Whisper.View.extend({
|
Whisper.ConversationLoadingScreen = Whisper.View.extend({
|
||||||
templateName: 'conversation-loading-screen',
|
template: () => $('#conversation-loading-screen').html(),
|
||||||
className: 'conversation-loading-screen',
|
className: 'conversation-loading-screen',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -302,7 +298,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
id() {
|
id() {
|
||||||
return `conversation-${this.model.cid}`;
|
return `conversation-${this.model.cid}`;
|
||||||
},
|
},
|
||||||
template: $('#conversation').html(),
|
template: () => $('#conversation').html(),
|
||||||
render_attributes() {
|
render_attributes() {
|
||||||
return {
|
return {
|
||||||
'send-message': window.i18n('sendMessage'),
|
'send-message': window.i18n('sendMessage'),
|
||||||
|
@ -374,31 +370,37 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.downloadNewVersion
|
this.downloadNewVersion
|
||||||
);
|
);
|
||||||
|
|
||||||
this.lazyUpdateVerified = _.debounce(
|
this.lazyUpdateVerified = window._.debounce(
|
||||||
this.model.updateVerified.bind(this.model),
|
this.model.updateVerified.bind(this.model),
|
||||||
1000 // one second
|
1000 // one second
|
||||||
);
|
);
|
||||||
this.model.throttledGetProfiles =
|
this.model.throttledGetProfiles =
|
||||||
this.model.throttledGetProfiles ||
|
this.model.throttledGetProfiles ||
|
||||||
_.throttle(this.model.getProfiles.bind(this.model), FIVE_MINUTES);
|
window._.throttle(this.model.getProfiles.bind(this.model), FIVE_MINUTES);
|
||||||
this.model.throttledUpdateSharedGroups =
|
this.model.throttledUpdateSharedGroups =
|
||||||
this.model.throttledUpdateSharedGroups ||
|
this.model.throttledUpdateSharedGroups ||
|
||||||
_.throttle(this.model.updateSharedGroups.bind(this.model), FIVE_MINUTES);
|
window._.throttle(
|
||||||
|
this.model.updateSharedGroups.bind(this.model),
|
||||||
|
FIVE_MINUTES
|
||||||
|
);
|
||||||
this.model.throttledFetchLatestGroupV2Data =
|
this.model.throttledFetchLatestGroupV2Data =
|
||||||
this.model.throttledFetchLatestGroupV2Data ||
|
this.model.throttledFetchLatestGroupV2Data ||
|
||||||
_.throttle(
|
window._.throttle(
|
||||||
this.model.fetchLatestGroupV2Data.bind(this.model),
|
this.model.fetchLatestGroupV2Data.bind(this.model),
|
||||||
FIVE_MINUTES
|
FIVE_MINUTES
|
||||||
);
|
);
|
||||||
this.model.throttledMaybeMigrateV1Group =
|
this.model.throttledMaybeMigrateV1Group =
|
||||||
this.model.throttledMaybeMigrateV1Group ||
|
this.model.throttledMaybeMigrateV1Group ||
|
||||||
_.throttle(this.model.maybeMigrateV1Group.bind(this.model), FIVE_MINUTES);
|
window._.throttle(
|
||||||
|
this.model.maybeMigrateV1Group.bind(this.model),
|
||||||
|
FIVE_MINUTES
|
||||||
|
);
|
||||||
|
|
||||||
this.debouncedMaybeGrabLinkPreview = _.debounce(
|
this.debouncedMaybeGrabLinkPreview = window._.debounce(
|
||||||
this.maybeGrabLinkPreview.bind(this),
|
this.maybeGrabLinkPreview.bind(this),
|
||||||
200
|
200
|
||||||
);
|
);
|
||||||
this.debouncedSaveDraft = _.debounce(this.saveDraft.bind(this), 200);
|
this.debouncedSaveDraft = window._.debounce(this.saveDraft.bind(this), 200);
|
||||||
|
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
|
@ -1506,7 +1508,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
const draftAttachments = this.model.get('draftAttachments') || [];
|
const draftAttachments = this.model.get('draftAttachments') || [];
|
||||||
|
|
||||||
this.model.set({
|
this.model.set({
|
||||||
draftAttachments: _.reject(
|
draftAttachments: window._.reject(
|
||||||
draftAttachments,
|
draftAttachments,
|
||||||
item => item.path === attachment.path
|
item => item.path === attachment.path
|
||||||
),
|
),
|
||||||
|
@ -1553,7 +1555,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
const draftAttachments = this.model.get('draftAttachments') || [];
|
const draftAttachments = this.model.get('draftAttachments') || [];
|
||||||
const files = _.compact(
|
const files = window._.compact(
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
draftAttachments.map((attachment: any) => this.getFile(attachment))
|
draftAttachments.map((attachment: any) => this.getFile(attachment))
|
||||||
)
|
)
|
||||||
|
@ -1575,7 +1577,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
..._.pick(attachment, [
|
...window._.pick(attachment, [
|
||||||
'contentType',
|
'contentType',
|
||||||
'fileName',
|
'fileName',
|
||||||
'size',
|
'size',
|
||||||
|
@ -1620,14 +1622,14 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
if (toWrite.data) {
|
if (toWrite.data) {
|
||||||
const path = await writeNewDraftData(toWrite.data);
|
const path = await writeNewDraftData(toWrite.data);
|
||||||
toWrite = {
|
toWrite = {
|
||||||
..._.omit(toWrite, ['data']),
|
...window._.omit(toWrite, ['data']),
|
||||||
path,
|
path,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (toWrite.screenshotData) {
|
if (toWrite.screenshotData) {
|
||||||
const screenshotPath = await writeNewDraftData(toWrite.screenshotData);
|
const screenshotPath = await writeNewDraftData(toWrite.screenshotData);
|
||||||
toWrite = {
|
toWrite = {
|
||||||
..._.omit(toWrite, ['screenshotData']),
|
...window._.omit(toWrite, ['screenshotData']),
|
||||||
screenshotPath,
|
screenshotPath,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3168,8 +3170,10 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
async destroyMessages() {
|
async destroyMessages() {
|
||||||
try {
|
window.showConfirmationDialog({
|
||||||
await this.confirm(window.i18n('deleteConversationConfirmation'));
|
message: window.i18n('deleteConversationConfirmation'),
|
||||||
|
okText: window.i18n('delete'),
|
||||||
|
resolve: () => {
|
||||||
this.longRunningTaskWrapper({
|
this.longRunningTaskWrapper({
|
||||||
name: 'destroymessages',
|
name: 'destroymessages',
|
||||||
task: async () => {
|
task: async () => {
|
||||||
|
@ -3178,9 +3182,11 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
this.model.updateLastMessage();
|
this.model.updateLastMessage();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
},
|
||||||
// nothing to see here, user canceled out of dialog
|
reject: () => {
|
||||||
}
|
window.log.info('destroyMessages: User canceled delete');
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async isCallSafe() {
|
async isCallSafe() {
|
||||||
|
@ -3981,7 +3987,7 @@ Whisper.ConversationView = Whisper.View.extend({
|
||||||
// We eliminate the ObjectURL here, unneeded for send or save
|
// We eliminate the ObjectURL here, unneeded for send or save
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
image: _.omit(item.image, 'url'),
|
image: window._.omit(item.image, 'url'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
66
ts/window.d.ts
vendored
66
ts/window.d.ts
vendored
|
@ -107,7 +107,7 @@ type ConfirmationDialogViewProps = {
|
||||||
confirmStyle?: 'affirmative' | 'negative';
|
confirmStyle?: 'affirmative' | 'negative';
|
||||||
message: string;
|
message: string;
|
||||||
okText: string;
|
okText: string;
|
||||||
reject?: () => void;
|
reject?: (error: Error) => void;
|
||||||
resolve: () => void;
|
resolve: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -115,6 +115,8 @@ declare global {
|
||||||
// We want to extend `window`'s properties, so we need an interface.
|
// We want to extend `window`'s properties, so we need an interface.
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
interface Window {
|
interface Window {
|
||||||
|
startApp: () => void;
|
||||||
|
|
||||||
_: typeof Underscore;
|
_: typeof Underscore;
|
||||||
$: typeof jQuery;
|
$: typeof jQuery;
|
||||||
|
|
||||||
|
@ -127,6 +129,10 @@ declare global {
|
||||||
|
|
||||||
PQueue: typeof PQueue;
|
PQueue: typeof PQueue;
|
||||||
PQueueType: PQueue;
|
PQueueType: PQueue;
|
||||||
|
Mustache: {
|
||||||
|
render: (template: string, data: any, partials?: any) => string;
|
||||||
|
parse: (template: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
WhatIsThis: WhatIsThis;
|
WhatIsThis: WhatIsThis;
|
||||||
|
|
||||||
|
@ -655,7 +661,7 @@ export type WhisperType = {
|
||||||
ClearDataView: WhatIsThis;
|
ClearDataView: WhatIsThis;
|
||||||
ReactWrapperView: WhatIsThis;
|
ReactWrapperView: WhatIsThis;
|
||||||
activeConfirmationView: WhatIsThis;
|
activeConfirmationView: WhatIsThis;
|
||||||
ToastView: typeof Whisper.View & {
|
ToastView: typeof window.Whisper.View & {
|
||||||
show: (view: typeof Backbone.View, el: Element) => void;
|
show: (view: typeof Backbone.View, el: Element) => void;
|
||||||
};
|
};
|
||||||
ConversationArchivedToast: WhatIsThis;
|
ConversationArchivedToast: WhatIsThis;
|
||||||
|
@ -731,33 +737,35 @@ export type WhisperType = {
|
||||||
deliveryReceiptBatcher: BatcherType<WhatIsThis>;
|
deliveryReceiptBatcher: BatcherType<WhatIsThis>;
|
||||||
RotateSignedPreKeyListener: WhatIsThis;
|
RotateSignedPreKeyListener: WhatIsThis;
|
||||||
|
|
||||||
AlreadyGroupMemberToast: typeof Whisper.ToastView;
|
AlreadyGroupMemberToast: typeof window.Whisper.ToastView;
|
||||||
AlreadyRequestedToJoinToast: typeof Whisper.ToastView;
|
AlreadyRequestedToJoinToast: typeof window.Whisper.ToastView;
|
||||||
BlockedGroupToast: typeof Whisper.ToastView;
|
BlockedGroupToast: typeof window.Whisper.ToastView;
|
||||||
BlockedToast: typeof Whisper.ToastView;
|
BlockedToast: typeof window.Whisper.ToastView;
|
||||||
CannotMixImageAndNonImageAttachmentsToast: typeof Whisper.ToastView;
|
CannotMixImageAndNonImageAttachmentsToast: typeof window.Whisper.ToastView;
|
||||||
DangerousFileTypeToast: typeof Whisper.ToastView;
|
DangerousFileTypeToast: typeof window.Whisper.ToastView;
|
||||||
ExpiredToast: typeof Whisper.ToastView;
|
ExpiredToast: typeof window.Whisper.ToastView;
|
||||||
FileSavedToast: typeof Whisper.ToastView;
|
FileSavedToast: typeof window.Whisper.ToastView;
|
||||||
FileSizeToast: any;
|
FileSizeToast: any;
|
||||||
FoundButNotLoadedToast: typeof Whisper.ToastView;
|
FoundButNotLoadedToast: typeof window.Whisper.ToastView;
|
||||||
InvalidConversationToast: typeof Whisper.ToastView;
|
InvalidConversationToast: typeof window.Whisper.ToastView;
|
||||||
LeftGroupToast: typeof Whisper.ToastView;
|
LeftGroupToast: typeof window.Whisper.ToastView;
|
||||||
MaxAttachmentsToast: typeof Whisper.ToastView;
|
MaxAttachmentsToast: typeof window.Whisper.ToastView;
|
||||||
MessageBodyTooLongToast: typeof Whisper.ToastView;
|
MessageBodyTooLongToast: typeof window.Whisper.ToastView;
|
||||||
OneNonImageAtATimeToast: typeof Whisper.ToastView;
|
OneNonImageAtATimeToast: typeof window.Whisper.ToastView;
|
||||||
OriginalNoLongerAvailableToast: typeof Whisper.ToastView;
|
OriginalNoLongerAvailableToast: typeof window.Whisper.ToastView;
|
||||||
OriginalNotFoundToast: typeof Whisper.ToastView;
|
OriginalNotFoundToast: typeof window.Whisper.ToastView;
|
||||||
PinnedConversationsFullToast: typeof Whisper.ToastView;
|
PinnedConversationsFullToast: typeof window.Whisper.ToastView;
|
||||||
ReactionFailedToast: typeof Whisper.ToastView;
|
ReactionFailedToast: typeof window.Whisper.ToastView;
|
||||||
TapToViewExpiredIncomingToast: typeof Whisper.ToastView;
|
TapToViewExpiredIncomingToast: typeof window.Whisper.ToastView;
|
||||||
TapToViewExpiredOutgoingToast: typeof Whisper.ToastView;
|
TapToViewExpiredOutgoingToast: typeof window.Whisper.ToastView;
|
||||||
TimerConflictToast: typeof Whisper.ToastView;
|
TimerConflictToast: typeof window.Whisper.ToastView;
|
||||||
UnableToLoadToast: typeof Whisper.ToastView;
|
UnableToLoadToast: typeof window.Whisper.ToastView;
|
||||||
VoiceNoteLimit: typeof Whisper.ToastView;
|
VoiceNoteLimit: typeof window.Whisper.ToastView;
|
||||||
VoiceNoteMustBeOnlyAttachmentToast: typeof Whisper.ToastView;
|
VoiceNoteMustBeOnlyAttachmentToast: typeof window.Whisper.ToastView;
|
||||||
|
|
||||||
ConversationLoadingScreen: typeof Whisper.View;
|
ConversationLoadingScreen: typeof window.Whisper.View;
|
||||||
ConversationView: typeof Whisper.View;
|
ConversationView: typeof window.Whisper.View;
|
||||||
View: typeof Backbone.View;
|
View: typeof Backbone.View & {
|
||||||
|
Templates: Record<string, string>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue