Implement Privacy Screen

* Add handles for window focus gained / focus lossed and connect to timer
* Clean up some of the PrivacyScreen.qml code
* Connect settings to PrivacyScreen visibility
pull/446/head
Joseph Donofry 4 years ago
parent cb93ac3402
commit bfeb766a91
No known key found for this signature in database
GPG Key ID: E8A1D78EF044B0CB
  1. 2
      .ci/format.sh
  2. 120
      resources/qml/PrivacyScreen.qml
  3. 2
      src/ChatPage.cpp
  4. 2
      src/ChatPage.h
  5. 16
      src/MainWindow.cpp
  6. 4
      src/MainWindow.h
  7. 10
      src/UserSettingsPage.cpp
  8. 10
      src/timeline/TimelineViewManager.h

@ -22,6 +22,8 @@ if [ ! -z "$QMLFORMAT_PATH" ]; then
do do
qmlformat -i "$f" qmlformat -i "$f"
done; done;
else
echo "qmlformat not found; skipping qml formatting"
fi fi
git diff --exit-code git diff --exit-code

@ -1,13 +1,28 @@
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import QtQuick 2.12 import QtQuick 2.12
import im.nheko 1.0
Item { Item {
id: privacyScreen
property var timelineRoot property var timelineRoot
property var imageSource property var imageSource: ""
property int screenTimeout property int screenTimeout
anchors.fill: parent anchors.fill: parent
Connections {
target: TimelineManager
onFocusChanged: {
if (TimelineManager.isWindowFocused) {
screenSaverTimer.stop();
screenSaver.state = "Invisible";
} else {
screenSaverTimer.start();
}
}
}
Timer { Timer {
id: screenSaverTimer id: screenSaverTimer
@ -15,36 +30,98 @@ Item {
running: true running: true
onTriggered: { onTriggered: {
timelineRoot.grabToImage(function(result) { timelineRoot.grabToImage(function(result) {
screenSaver.state = "Visible";
imageSource = result.url; imageSource = result.url;
screenSaver.visible = true;
particles.resume();
}, Qt.size(width, height)); }, Qt.size(width, height));
} }
} }
// Reset screensaver timer when clicks are received
MouseArea {
anchors.fill: parent
// Pass mouse events through
propagateComposedEvents: true
hoverEnabled: true
onClicked: {
screenSaverTimer.restart();
mouse.accepted = false;
}
}
Rectangle { Rectangle {
id: screenSaver id: screenSaver
state: "Invisible"
anchors.fill: parent anchors.fill: parent
visible: false visible: false
color: "transparent" color: "transparent"
states: [
State {
name: "Visible"
PropertyChanges {
target: screenSaver
visible: true
}
PropertyChanges {
target: screenSaver
opacity: 1
}
},
State {
name: "Invisible"
PropertyChanges {
target: screenSaver
opacity: 0
}
PropertyChanges {
target: screenSaver
visible: false
}
}
]
transitions: [
Transition {
from: "Visible"
to: "Invisible"
SequentialAnimation {
NumberAnimation {
target: screenSaver
property: "opacity"
duration: 250
easing.type: Easing.InQuad
}
NumberAnimation {
target: screenSaver
property: "visible"
duration: 0
}
}
},
Transition {
from: "Invisible"
to: "Visible"
SequentialAnimation {
NumberAnimation {
target: screenSaver
property: "visible"
duration: 0
}
NumberAnimation {
target: screenSaver
property: "opacity"
duration: 500
easing.type: Easing.InQuad
}
}
}
]
Image { Image {
id: image id: image
visible: screenSaver.visible cache: false
anchors.fill: parent anchors.fill: parent
source: imageSource source: imageSource
} }
@ -65,17 +142,6 @@ Item {
radius: 50 radius: 50
} }
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
hoverEnabled: true
onClicked: {
screenSaver.visible = false;
screenSaverTimer.restart();
mouse.accepted = false;
}
}
} }
} }

@ -312,6 +312,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
&ChatPage::initializeMentions, &ChatPage::initializeMentions,
user_mentions_popup_, user_mentions_popup_,
&popups::UserMentions::initializeMentions); &popups::UserMentions::initializeMentions);
connect(
this, &ChatPage::chatFocusChanged, view_manager_, &TimelineViewManager::chatFocusChanged);
connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) { connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) {
try { try {
room_list_->cleanupInvites(cache::invites()); room_list_->cleanupInvites(cache::invites());

@ -127,7 +127,6 @@ public slots:
void receivedSessionKey(const std::string &room_id, const std::string &session_id); void receivedSessionKey(const std::string &room_id, const std::string &session_id);
void decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc, void decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
const SecretsToDecrypt &secrets); const SecretsToDecrypt &secrets);
signals: signals:
void connectionLost(); void connectionLost();
void connectionRestored(); void connectionRestored();
@ -176,6 +175,7 @@ signals:
void retrievedPresence(const QString &statusMsg, mtx::presence::PresenceState state); void retrievedPresence(const QString &statusMsg, mtx::presence::PresenceState state);
void themeChanged(); void themeChanged();
void decryptSidebarChanged(); void decryptSidebarChanged();
void chatFocusChanged(const bool focused);
//! Signals for device verificaiton //! Signals for device verificaiton
void receivedDeviceVerificationAccept( void receivedDeviceVerificationAccept(

@ -130,6 +130,9 @@ MainWindow::MainWindow(QWidget *parent)
SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar())); connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
connect(this, &MainWindow::focusChanged, chat_page_, &ChatPage::chatFocusChanged);
connect( connect(
chat_page_, &ChatPage::showUserSettingsPage, this, &MainWindow::showUserSettingsPage); chat_page_, &ChatPage::showUserSettingsPage, this, &MainWindow::showUserSettingsPage);
@ -204,6 +207,19 @@ MainWindow::resizeEvent(QResizeEvent *event)
QMainWindow::resizeEvent(event); QMainWindow::resizeEvent(event);
} }
bool
MainWindow::event(QEvent *event)
{
auto type = event->type();
if (type == QEvent::WindowActivate) {
emit focusChanged(true);
} else if (type == QEvent::WindowDeactivate) {
emit focusChanged(false);
}
return QMainWindow::event(event);
}
void void
MainWindow::adjustSideBars() MainWindow::adjustSideBars()
{ {

@ -88,6 +88,7 @@ protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;
void showEvent(QShowEvent *event) override; void showEvent(QShowEvent *event) override;
bool event(QEvent *event) override;
private slots: private slots:
//! Show or hide the sidebars based on window's size. //! Show or hide the sidebars based on window's size.
@ -115,6 +116,9 @@ private slots:
virtual void setWindowTitle(int notificationCount); virtual void setWindowTitle(int notificationCount);
signals:
void focusChanged(const bool focused);
private: private:
bool loadJdenticonPlugin(); bool loadJdenticonPlugin();

@ -836,13 +836,15 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
decryptSidebar_, decryptSidebar_,
tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in " tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in "
"encrypted chats.")); "encrypted chats."));
boxWrap(tr("Encrypted chat privacy screen"), boxWrap(tr("Privacy Screen"),
privacyScreen_, privacyScreen_,
tr("When the window loses focus, the timeline will\nbe blurred.")); tr("When the window loses focus, the timeline will\nbe blurred."));
boxWrap(tr("Privacy screen timeout"), boxWrap(
tr("Privacy screen timeout"),
privacyScreenTimeout_, privacyScreenTimeout_,
tr("Set timeout for how long after window loses\nfocus before the screen" tr("Set timeout (in seconds) for how long after window loses\nfocus before the screen"
" will be blurred.\nSet to 0 to blur immediately after focus loss.")); " will be blurred.\nSet to 0 to blur immediately after focus loss. Max value of 1 "
"hour (3600 seconds)"));
boxWrap(tr("Show buttons in timeline"), boxWrap(tr("Show buttons in timeline"),
timelineButtonsToggle_, timelineButtonsToggle_,
tr("Show buttons to quickly reply, react or access additional options next to each " tr("Show buttons to quickly reply, react or access additional options next to each "

@ -36,6 +36,8 @@ class TimelineViewManager : public QObject
bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged) bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
Q_PROPERTY( Q_PROPERTY(
bool isNarrowView MEMBER isNarrowView_ READ isNarrowView NOTIFY narrowViewChanged) bool isNarrowView MEMBER isNarrowView_ READ isNarrowView NOTIFY narrowViewChanged)
Q_PROPERTY(
bool isWindowFocused MEMBER isWindowFocused_ READ isWindowFocused NOTIFY focusChanged)
public: public:
TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr); TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr);
@ -54,6 +56,7 @@ public:
Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; } Q_INVOKABLE TimelineModel *activeTimeline() const { return timeline_; }
Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; } Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
bool isNarrowView() const { return isNarrowView_; } bool isNarrowView() const { return isNarrowView_; }
bool isWindowFocused() const { return isWindowFocused_; }
Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const; Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId) const;
Q_INVOKABLE QColor userColor(QString id, QColor background); Q_INVOKABLE QColor userColor(QString id, QColor background);
Q_INVOKABLE QString escapeEmoji(QString str) const; Q_INVOKABLE QString escapeEmoji(QString str) const;
@ -83,11 +86,17 @@ signals:
void inviteUsers(QStringList users); void inviteUsers(QStringList users);
void showRoomList(); void showRoomList();
void narrowViewChanged(); void narrowViewChanged();
void focusChanged();
public slots: public slots:
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids); void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
void receivedSessionKey(const std::string &room_id, const std::string &session_id); void receivedSessionKey(const std::string &room_id, const std::string &session_id);
void initWithMessages(const std::vector<QString> &roomIds); void initWithMessages(const std::vector<QString> &roomIds);
void chatFocusChanged(bool focused)
{
isWindowFocused_ = focused;
emit focusChanged();
}
void setHistoryView(const QString &room_id); void setHistoryView(const QString &room_id);
TimelineModel *getHistoryView(const QString &room_id) TimelineModel *getHistoryView(const QString &room_id)
@ -147,6 +156,7 @@ private:
bool isInitialSync_ = true; bool isInitialSync_ = true;
bool isNarrowView_ = false; bool isNarrowView_ = false;
bool isWindowFocused_ = false;
QHash<QString, QColor> userColors; QHash<QString, QColor> userColors;

Loading…
Cancel
Save