Preserve scroll position when adding/removing staged quote

pull/272/head
Scott Nonnenberg 6 years ago
parent cba47668cd
commit 7db7a3ad44

@ -1542,6 +1542,7 @@
this.quoteView = null; this.quoteView = null;
} }
if (!this.quotedMessage) { if (!this.quotedMessage) {
this.view.restoreBottomOffset();
this.updateMessageFieldSize({}); this.updateMessageFieldSize({});
return; return;
} }
@ -1565,16 +1566,18 @@
this.quoteView = new Whisper.ReactWrapperView({ this.quoteView = new Whisper.ReactWrapperView({
className: 'quote-wrapper', className: 'quote-wrapper',
Component: window.Signal.Components.Quote, Component: window.Signal.Components.Quote,
elCallback: el => this.$('.send').prepend(el),
props: Object.assign({}, props, { props: Object.assign({}, props, {
withContentAbove: true, withContentAbove: true,
onClose: () => { onClose: () => {
this.setQuoteMessage(null); this.setQuoteMessage(null);
}, },
}), }),
onInitialRender: () => {
this.view.restoreBottomOffset();
this.updateMessageFieldSize({});
},
}); });
this.$('.send').prepend(this.quoteView.el);
this.updateMessageFieldSize({});
}, },
async sendMessage(e) { async sendMessage(e) {

@ -70,6 +70,15 @@
resetScrollPosition() { resetScrollPosition() {
this.$el.scrollTop(this.scrollPosition - this.$el.outerHeight()); this.$el.scrollTop(this.scrollPosition - this.$el.outerHeight());
}, },
restoreBottomOffset() {
if (_.isNumber(this.bottomOffset)) {
// + 10 is necessary to account for padding
const height = this.$el.height() + 10;
const topOfBottomScreen = this.el.scrollHeight - height;
this.$el.scrollTop(topOfBottomScreen - this.bottomOffset);
}
},
scrollToBottomIfNeeded() { scrollToBottomIfNeeded() {
// This is counter-intuitive. Our current bottomOffset is reflective of what // This is counter-intuitive. Our current bottomOffset is reflective of what
// we last measured, not necessarily the current state. And this is called // we last measured, not necessarily the current state. And this is called

@ -12,20 +12,43 @@
window.Whisper.ReactWrapperView = Backbone.View.extend({ window.Whisper.ReactWrapperView = Backbone.View.extend({
className: 'react-wrapper', className: 'react-wrapper',
initialize(options) { initialize(options) {
const { Component, props, onClose } = options; const {
Component,
props,
onClose,
tagName,
className,
onInitialRender,
elCallback,
} = options;
this.render(); this.render();
if (elCallback) {
elCallback(this.el);
}
this.tagName = options.tagName; this.tagName = tagName;
this.className = options.className; this.className = className;
this.Component = Component; this.Component = Component;
this.onClose = onClose; this.onClose = onClose;
this.onInitialRender = onInitialRender;
this.update(props); this.update(props);
this.hasRendered = false;
}, },
update(props) { update(props) {
const updatedProps = this.augmentProps(props); const updatedProps = this.augmentProps(props);
const reactElement = React.createElement(this.Component, updatedProps); const reactElement = React.createElement(this.Component, updatedProps);
ReactDOM.render(reactElement, this.el); ReactDOM.render(reactElement, this.el, () => {
if (this.hasRendered) {
return;
}
this.hasRendered = true;
if (this.onInitialRender) {
this.onInitialRender();
}
});
}, },
augmentProps(props) { augmentProps(props) {
return Object.assign({}, props, { return Object.assign({}, props, {

@ -1099,26 +1099,26 @@
{ {
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "js/views/conversation_view.js", "path": "js/views/conversation_view.js",
"line": " this.$('.send').prepend(this.quoteView.el);", "line": " elCallback: el => this.$('.send').prepend(el),",
"lineNumber": 1576, "lineNumber": 1569,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-12-15T02:21:20.921Z", "updated": "2019-01-15T03:15:22.532Z",
"reasonDetail": "Protected from arbitrary input" "reasonDetail": "Protected from arbitrary input"
}, },
{ {
"rule": "jQuery-prepend(", "rule": "jQuery-prepend(",
"path": "js/views/conversation_view.js", "path": "js/views/conversation_view.js",
"line": " this.$('.send').prepend(this.quoteView.el);", "line": " elCallback: el => this.$('.send').prepend(el),",
"lineNumber": 1576, "lineNumber": 1569,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-12-15T02:21:20.921Z", "updated": "2019-01-15T03:15:22.532Z",
"reasonDetail": "Protected from arbitrary input" "reasonDetail": "Protected from arbitrary input"
}, },
{ {
"rule": "jQuery-appendTo(", "rule": "jQuery-appendTo(",
"path": "js/views/conversation_view.js", "path": "js/views/conversation_view.js",
"line": " toast.$el.appendTo(this.$el);", "line": " toast.$el.appendTo(this.$el);",
"lineNumber": 1600, "lineNumber": 1603,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-12-15T02:21:20.921Z", "updated": "2018-12-15T02:21:20.921Z",
"reasonDetail": "Protected from arbitrary input" "reasonDetail": "Protected from arbitrary input"
@ -1127,7 +1127,7 @@
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "js/views/conversation_view.js", "path": "js/views/conversation_view.js",
"line": " this.$('.bottom-bar form').submit();", "line": " this.$('.bottom-bar form').submit();",
"lineNumber": 1655, "lineNumber": 1658,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-12-15T02:21:20.921Z", "updated": "2018-12-15T02:21:20.921Z",
"reasonDetail": "Protected from arbitrary input" "reasonDetail": "Protected from arbitrary input"
@ -1136,7 +1136,7 @@
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "js/views/conversation_view.js", "path": "js/views/conversation_view.js",
"line": " const $attachmentPreviews = this.$('.attachment-previews');", "line": " const $attachmentPreviews = this.$('.attachment-previews');",
"lineNumber": 1664, "lineNumber": 1667,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-12-15T02:21:20.921Z", "updated": "2018-12-15T02:21:20.921Z",
"reasonDetail": "Protected from arbitrary input" "reasonDetail": "Protected from arbitrary input"
@ -1145,7 +1145,7 @@
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "js/views/conversation_view.js", "path": "js/views/conversation_view.js",
"line": " this.$('.panel').css('display') === 'none'", "line": " this.$('.panel').css('display') === 'none'",
"lineNumber": 1695, "lineNumber": 1698,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-12-15T02:21:20.921Z", "updated": "2018-12-15T02:21:20.921Z",
"reasonDetail": "Protected from arbitrary input" "reasonDetail": "Protected from arbitrary input"
@ -1683,7 +1683,7 @@
"rule": "jQuery-append(", "rule": "jQuery-append(",
"path": "js/views/message_list_view.js", "path": "js/views/message_list_view.js",
"line": " this.$messages.append(view.el);", "line": " this.$messages.append(view.el);",
"lineNumber": 102, "lineNumber": 111,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-11-14T18:51:15.180Z", "updated": "2018-11-14T18:51:15.180Z",
"reasonDetail": "view.el is a known DOM element" "reasonDetail": "view.el is a known DOM element"
@ -1692,7 +1692,7 @@
"rule": "jQuery-prepend(", "rule": "jQuery-prepend(",
"path": "js/views/message_list_view.js", "path": "js/views/message_list_view.js",
"line": " this.$messages.prepend(view.el);", "line": " this.$messages.prepend(view.el);",
"lineNumber": 105, "lineNumber": 114,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-11-14T18:51:15.180Z", "updated": "2018-11-14T18:51:15.180Z",
"reasonDetail": "view.el is a known DOM element" "reasonDetail": "view.el is a known DOM element"
@ -1701,7 +1701,7 @@
"rule": "jQuery-$(", "rule": "jQuery-$(",
"path": "js/views/message_list_view.js", "path": "js/views/message_list_view.js",
"line": " const next = this.$(`#${this.collection.at(index + 1).id}`);", "line": " const next = this.$(`#${this.collection.at(index + 1).id}`);",
"lineNumber": 108, "lineNumber": 117,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-11-14T18:51:15.180Z", "updated": "2018-11-14T18:51:15.180Z",
"reasonDetail": "Message ids are GUIDs, and therefore the resultant string for $() is an id" "reasonDetail": "Message ids are GUIDs, and therefore the resultant string for $() is an id"
@ -1710,7 +1710,7 @@
"rule": "jQuery-insertBefore(", "rule": "jQuery-insertBefore(",
"path": "js/views/message_list_view.js", "path": "js/views/message_list_view.js",
"line": " view.$el.insertBefore(next);", "line": " view.$el.insertBefore(next);",
"lineNumber": 111, "lineNumber": 120,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-11-14T18:51:15.180Z", "updated": "2018-11-14T18:51:15.180Z",
"reasonDetail": "next is a known DOM element" "reasonDetail": "next is a known DOM element"
@ -1719,7 +1719,7 @@
"rule": "jQuery-insertAfter(", "rule": "jQuery-insertAfter(",
"path": "js/views/message_list_view.js", "path": "js/views/message_list_view.js",
"line": " view.$el.insertAfter(prev);", "line": " view.$el.insertAfter(prev);",
"lineNumber": 113, "lineNumber": 122,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-11-14T18:51:15.180Z", "updated": "2018-11-14T18:51:15.180Z",
"reasonDetail": "prev is a known DOM element" "reasonDetail": "prev is a known DOM element"
@ -1728,7 +1728,7 @@
"rule": "jQuery-insertBefore(", "rule": "jQuery-insertBefore(",
"path": "js/views/message_list_view.js", "path": "js/views/message_list_view.js",
"line": " view.$el.insertBefore(elements[i]);", "line": " view.$el.insertBefore(elements[i]);",
"lineNumber": 122, "lineNumber": 131,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-11-14T18:51:15.180Z", "updated": "2018-11-14T18:51:15.180Z",
"reasonDetail": "elements[i] is a known DOM element" "reasonDetail": "elements[i] is a known DOM element"
@ -1737,7 +1737,7 @@
"rule": "jQuery-append(", "rule": "jQuery-append(",
"path": "js/views/message_list_view.js", "path": "js/views/message_list_view.js",
"line": " this.$messages.append(view.el);", "line": " this.$messages.append(view.el);",
"lineNumber": 127, "lineNumber": 136,
"reasonCategory": "usageTrusted", "reasonCategory": "usageTrusted",
"updated": "2018-11-14T18:51:15.180Z", "updated": "2018-11-14T18:51:15.180Z",
"reasonDetail": "view.el is a known DOM element" "reasonDetail": "view.el is a known DOM element"

Loading…
Cancel
Save