Clipboard sync on new connection

Summary: Added a timestamp to track clipboard changes, so when a new device connects it will sync the most recently updated clipboard to both devices.

Reviewers: #kde_connect, albertvaka

Reviewed By: #kde_connect, albertvaka

Subscribers: albertvaka, sredman, kdeconnect

Tags: #kde_connect

Differential Revision: https://phabricator.kde.org/D22584
This commit is contained in:
Colin Redman 2019-07-23 16:21:39 +02:00 committed by Albert Vaca Cintora
parent 88e0ffa01a
commit 7799973371
5 changed files with 82 additions and 14 deletions

View file

@ -38,16 +38,28 @@ void ClipboardListener::updateClipboard(QClipboard::Mode mode)
QString content = clipboard->text();
if (content == currentContent) {
if (content == m_currentContent) {
return;
}
currentContent = content;
m_updateTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
m_currentContent = content;
Q_EMIT clipboardChanged(content);
}
QString ClipboardListener::currentContent()
{
return m_currentContent;
}
qint64 ClipboardListener::updateTimestamp(){
return m_updateTimestamp;
}
void ClipboardListener::setText(const QString& content)
{
currentContent = content;
m_updateTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
m_currentContent = content;
clipboard->setText(content);
}

View file

@ -21,6 +21,7 @@
#ifndef CLIPBOARDLISTENER_H
#define CLIPBOARDLISTENER_H
#include <QDateTime>
#include <QTimer>
#include <QObject>
#include <QClipboard>
@ -35,7 +36,8 @@ class ClipboardListener : public QObject
private:
ClipboardListener();
QString currentContent;
QString m_currentContent;
qint64 m_updateTimestamp = 0;
QClipboard* clipboard;
#ifdef Q_OS_MAC
QTimer m_clipboardMonitorTimer;
@ -56,6 +58,9 @@ public:
void setText(const QString& content);
QString currentContent();
qint64 updateTimestamp();
Q_SIGNALS:
void clipboardChanged(const QString& content);
};

View file

@ -35,17 +35,44 @@ ClipboardPlugin::ClipboardPlugin(QObject* parent, const QVariantList& args)
this, &ClipboardPlugin::propagateClipboard);
}
void ClipboardPlugin::connected()
{
sendConnectPacket();
}
void ClipboardPlugin::propagateClipboard(const QString& content)
{
NetworkPacket np(PACKET_TYPE_CLIPBOARD, {{QStringLiteral("content"), content}});
sendPacket(np);
}
void ClipboardPlugin::sendConnectPacket()
{
NetworkPacket np(PACKET_TYPE_CLIPBOARD_CONNECT, {
{QStringLiteral("content"), ClipboardListener::instance()->currentContent()},
{QStringLiteral("timestamp"), ClipboardListener::instance()->updateTimestamp()}
});
sendPacket(np);
}
bool ClipboardPlugin::receivePacket(const NetworkPacket& np)
{
QString content = np.get<QString>(QStringLiteral("content"));
if (np.type() == PACKET_TYPE_CLIPBOARD) {
ClipboardListener::instance()->setText(content);
return true;
} else if (np.type() == PACKET_TYPE_CLIPBOARD_CONNECT) {
qint64 packetTime = np.get<qint64>(QStringLiteral("timestamp"));
// If the packetTime is 0, it means the timestamp is unknown (so do nothing).
if (packetTime == 0 || packetTime < ClipboardListener::instance()->updateTimestamp()) {
return false;
}
ClipboardListener::instance()->setText(content);
return true;
}
return false;
}
#include "clipboardplugin.moc"

View file

@ -27,8 +27,32 @@
#include <core/kdeconnectplugin.h>
Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_CLIPBOARD)
/**
* Packet containing just clipboard contents, sent when a device updates its clipboard.
* <p>
* The body should look like so:
* {
* "content": "password"
* }
*/
#define PACKET_TYPE_CLIPBOARD QStringLiteral("kdeconnect.clipboard")
/**
* Packet containing clipboard contents and a timestamp that the contents were last updated, sent
* on first connection
* <p>
* The timestamp is milliseconds since epoch. It can be 0, which indicates that the clipboard
* update time is currently unknown.
* <p>
* The body should look like so:
* {
* "timestamp": 542904563213,
* "content": "password"
* }
*/
#define PACKET_TYPE_CLIPBOARD_CONNECT QStringLiteral("kdeconnect.clipboard.connect")
class ClipboardPlugin
: public KdeConnectPlugin
{
@ -38,10 +62,10 @@ public:
explicit ClipboardPlugin(QObject* parent, const QVariantList& args);
bool receivePacket(const NetworkPacket& np) override;
void connected() override { }
void connected() override;
private Q_SLOTS:
void propagateClipboard(const QString& content);
void sendConnectPacket();
};

View file

@ -129,9 +129,9 @@
"Website": "https://albertvaka.wordpress.com"
},
"X-KdeConnect-OutgoingPacketType": [
"kdeconnect.clipboard"
"kdeconnect.clipboard", "kdeconnect.clipboard.connect"
],
"X-KdeConnect-SupportedPacketType": [
"kdeconnect.clipboard"
"kdeconnect.clipboard", "kdeconnect.clipboard.connect"
]
}