summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2016-04-15 17:03:02 (GMT)
committerKevin Smith <kevin.smith@isode.com>2016-04-25 08:38:46 (GMT)
commitef341e4762b1017047555c37dac1dfdc6ba2489d (patch)
treee4b3454c3f7b0fd3523269f193c8402c0bf30c4c
parent511c43aec78279ecaa6008bd7f4f08159d3a5c00 (diff)
downloadswift-ef341e4762b1017047555c37dac1dfdc6ba2489d.zip
swift-ef341e4762b1017047555c37dac1dfdc6ba2489d.tar.bz2
Fix detection of vertical scroll bar position in chat views
Chat views are expected to remember the scroll position. If the user scrolled all the way down, the view should keep scrolled all the way down, even if the windows is resized, new messages are added or the user enters a multi line message in the message input box. Qt WebKit only provides reliable scroll position updates in their web environment. This requires to have scroll changes call a JS hook that calls our C++ signal. Test-Information: Tested and verified the following cases for correct behavior: * entering a multi line message keeping the view scrolled down * resizing the window and keeping it scrolled down * receiving messages and the view keeps being scrolled down * verified that view does not scroll down if it is not yet on resize of the window, entering multi line messages, and receiving new messages Change-Id: I579a07d0b073c34e7a46b0fde1bc09f3da08d5da
-rw-r--r--Swift/QtUI/QtChatWindowJSBridge.h1
-rw-r--r--Swift/QtUI/QtWebKitChatView.cpp51
-rw-r--r--Swift/QtUI/QtWebKitChatView.h5
3 files changed, 34 insertions, 23 deletions
diff --git a/Swift/QtUI/QtChatWindowJSBridge.h b/Swift/QtUI/QtChatWindowJSBridge.h
index bedf6a4..553e929 100644
--- a/Swift/QtUI/QtChatWindowJSBridge.h
+++ b/Swift/QtUI/QtChatWindowJSBridge.h
@@ -27,6 +27,7 @@ public:
virtual ~QtChatWindowJSBridge();
signals:
void buttonClicked(QString id, QString arg1, QString arg2, QString arg3, QString arg4, QString arg5);
+ void verticalScrollBarPositionChanged(double scrollbarPosition);
};
}
diff --git a/Swift/QtUI/QtWebKitChatView.cpp b/Swift/QtUI/QtWebKitChatView.cpp
index 46e8763..aec8589 100644
--- a/Swift/QtUI/QtWebKitChatView.cpp
+++ b/Swift/QtUI/QtWebKitChatView.cpp
@@ -84,7 +84,6 @@ QtWebKitChatView::QtWebKitChatView(QtChatWindow* window, UIEventStream* eventStr
}
webView_->setPage(webPage_);
connect(webPage_, SIGNAL(selectionChanged()), SLOT(copySelectionToClipboard()));
- connect(webPage_, SIGNAL(scrollRequested(int, int, const QRect&)), SLOT(handleScrollRequested(int, int, const QRect&)));
viewReady_ = false;
isAtBottom_ = true;
@@ -93,7 +92,7 @@ QtWebKitChatView::QtWebKitChatView(QtChatWindow* window, UIEventStream* eventStr
jsBridge = new QtChatWindowJSBridge();
addToJSEnvironment("chatwindow", jsBridge);
connect(jsBridge, SIGNAL(buttonClicked(QString,QString,QString,QString,QString,QString)), this, SLOT(handleHTMLButtonClicked(QString,QString,QString,QString,QString,QString)));
-
+ connect(jsBridge, SIGNAL(verticalScrollBarPositionChanged(double)), this, SLOT(handleVerticalScrollBarPositionChanged(double)));
}
QtWebKitChatView::~QtWebKitChatView() {
@@ -253,7 +252,9 @@ void QtWebKitChatView::displayReceiptInfo(const QString& id, bool showIt) {
}
void QtWebKitChatView::rememberScrolledToBottom() {
- isAtBottom_ = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) >= (webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical) - 1);
+ if (webPage_) {
+ isAtBottom_ = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) >= (webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical) - 1);
+ }
}
void QtWebKitChatView::scrollToBottom() {
@@ -339,6 +340,11 @@ void QtWebKitChatView::resetView() {
scrollToBottom();
connect(webPage_->mainFrame(), SIGNAL(contentsSizeChanged(const QSize&)), this, SLOT(handleFrameSizeChanged()), Qt::UniqueConnection);
+
+ // Hooking up to scroll bar update, because Qt does not provide a way to retrieve accurate scroll bar updates from C++ directly.
+ QWebElement body = document_.findFirst("body");
+ assert(!body.isNull());
+ body.setAttribute("onscroll", "chatwindow.verticalScrollBarPositionChanged(document.body.scrollTop / (document.body.scrollHeight - window.innerHeight))");
}
static QWebElement findElementWithID(QWebElement document, QString elementName, QString id) {
@@ -446,20 +452,6 @@ void QtWebKitChatView::askDesktopToOpenFile(const QString& filename) {
}
}
-void QtWebKitChatView::handleScrollRequested(int, int dy, const QRect&) {
- rememberScrolledToBottom();
-
- int pos = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) - dy;
- emit scrollRequested(pos);
-
- if (pos == 0) {
- emit scrollReachedTop();
- }
- else if (pos == webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical)) {
- emit scrollReachedBottom();
- }
-}
-
int QtWebKitChatView::getSnippetPositionByDate(const QDate& date) {
QWebElement message = webPage_->mainFrame()->documentElement().findFirst(".date" + date.toString(Qt::ISODate));
@@ -590,6 +582,16 @@ QString QtWebKitChatView::buildChatWindowButton(const QString& name, const QStri
return html;
}
+void QtWebKitChatView::resizeEvent(QResizeEvent* event) {
+ // This code ensures that if the user is scrolled all to the bottom of a chat view,
+ // the view stays scrolled to the bottom if the view is resized or if the message
+ // input widget becomes multi line.
+ if (isAtBottom_) {
+ scrollToBottom();
+ }
+ QWidget::resizeEvent(event);
+}
+
std::string QtWebKitChatView::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes, const std::string& description) {
SWIFT_LOG(debug) << "addFileTransfer" << std::endl;
QString ft_id = QString("ft%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++)));
@@ -788,6 +790,16 @@ void QtWebKitChatView::handleHTMLButtonClicked(QString id, QString encodedArgume
}
}
+void QtWebKitChatView::handleVerticalScrollBarPositionChanged(double position) {
+ rememberScrolledToBottom();
+ if (position == 0) {
+ emit scrollReachedTop();
+ }
+ else if (position == 1) {
+ emit scrollReachedBottom();
+ }
+}
+
void QtWebKitChatView::addErrorMessage(const ChatWindow::ChatMessage& errorMessage) {
if (window_->isWidgetSelected()) {
window_->onAllMessagesRead();
@@ -968,9 +980,4 @@ ChatSnippet::Direction QtWebKitChatView::getActualDirection(const ChatWindow::Ch
}
}
-// void QtWebKitChatView::setShowEmoticons(bool value) {
-// showEmoticons_ = value;
-// }
-
-
}
diff --git a/Swift/QtUI/QtWebKitChatView.h b/Swift/QtUI/QtWebKitChatView.h
index 31bf8a5..098c1ac 100644
--- a/Swift/QtUI/QtWebKitChatView.h
+++ b/Swift/QtUI/QtWebKitChatView.h
@@ -124,8 +124,8 @@ namespace Swift {
void handleViewLoadFinished(bool);
void handleFrameSizeChanged();
void handleClearRequested();
- void handleScrollRequested(int dx, int dy, const QRect& rectToScroll);
void handleHTMLButtonClicked(QString id, QString arg1, QString arg2, QString arg3, QString arg4, QString arg5);
+ void handleVerticalScrollBarPositionChanged(double position);
private:
enum PreviousMessageKind {
@@ -159,6 +159,9 @@ namespace Swift {
QString chatMessageToHTML(const ChatWindow::ChatMessage& message);
static QString buildChatWindowButton(const QString& name, const QString& id, const QString& arg1 = QString(), const QString& arg2 = QString(), const QString& arg3 = QString(), const QString& arg4 = QString(), const QString& arg5 = QString());
+ protected:
+ void resizeEvent(QResizeEvent* event) SWIFTEN_OVERRIDE;
+
private:
void headerEncode();
void messageEncode();