Skip to content

Commit

Permalink
Current version of Psi+ is 1.5.2002
Browse files Browse the repository at this point in the history
It is based on:
* psi: 1a24bce5
* plugins: 7a65467
* psimedia: 478567e
* resources: e32ef4b
  • Loading branch information
tehnick committed Jun 28, 2024
1 parent bb5608e commit de922a1
Show file tree
Hide file tree
Showing 19 changed files with 821 additions and 23 deletions.
9 changes: 5 additions & 4 deletions iris/src/xmpp/xmpp-im/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1449,6 +1449,7 @@ Stanza Message::toStanza(Stream *stream) const
e.appendChild(s.createTextElement(reactionsNS, QStringLiteral("reaction"), reaction));
}
s.appendChild(e);
s.appendChild(s.createElement(QStringLiteral("urn:xmpp:hints"), QStringLiteral("store")));
}

return s;
Expand Down Expand Up @@ -1804,13 +1805,13 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf
}

// XEP-0444 message reactions
auto reactionStanza
auto reactions
= childElementsByTagNameNS(root, "urn:xmpp:reactions:0", QStringLiteral("reactions")).item(0).toElement();
if (!reactionStanza.isNull()) {
d->reactions.targetId = reactionStanza.attribute(QLatin1String("id"));
if (!reactions.isNull()) {
d->reactions.targetId = reactions.attribute(QLatin1String("id"));
if (!d->reactions.targetId.isEmpty()) {
auto reactionTag = QStringLiteral("reaction");
auto reaction = reactionStanza.firstChildElement(reactionTag);
auto reaction = reactions.firstChildElement(reactionTag);
while (!reaction.isNull()) {
d->reactions.reactions.insert(reaction.text().trimmed());
reaction = reaction.nextSiblingElement(reactionTag);
Expand Down
10 changes: 10 additions & 0 deletions src/chatdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,14 @@ void ChatDlg::init()
chatView()->setDialog(this);
bool isPrivate = account()->groupchats().contains(jid().bare());
chatView()->setSessionData(false, isPrivate, jid(), jid().full()); // FIXME fix nick updating
chatView()->setLocalNickname(account()->nick());
#ifdef WEBKIT
chatView()->setAccount(account());
#else
chatView()->setMediaOpener(account()->fileSharingDeviceOpener());
#endif
chatView()->init();
connect(chatView(), &ChatView::outgoingReactions, this, &ChatDlg::sendOutgoingReactions);

// seems its useless hack
// connect(chatView(), SIGNAL(selectionChanged()), SLOT(logSelectionChanged())); //
Expand Down Expand Up @@ -758,6 +760,14 @@ void ChatDlg::doneSend()
resetComposing();
}

void ChatDlg::sendOutgoingReactions(const QString &messageId, const QSet<QString> &reactions)
{
Message m(jid());
m.setType(Message::Type::Chat);
m.setReactions({ messageId, reactions });
emit aSend(m);
}

void ChatDlg::encryptedMessageSent(int x, bool b, int e, const QString &dtext)
{
Q_UNUSED(e);
Expand Down
1 change: 1 addition & 0 deletions src/chatdlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ private slots:
void initComposing();
void setComposing();
void getHistory();
void sendOutgoingReactions(const QString &messageId, const QSet<QString> &reactions);

protected slots:
void checkComposing();
Expand Down
6 changes: 5 additions & 1 deletion src/chatview_te.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ void ChatView::setSessionData(bool isMuc, bool isMucPrivate, const XMPP::Jid &ji
name_ = name;
}

void ChatView::setLocalNickname(const QString &nickname) {
localNickname_ = nickname;
}

void ChatView::clear()
{
PsiTextView::clear();
Expand All @@ -106,7 +110,7 @@ void ChatView::contextMenuEvent(QContextMenuEvent *e)
const QUrl anc = QUrl::fromEncoded(anchorAt(e->pos()).toLatin1());

if (anc.scheme() == "addnick") {
emit showNM(anc.path().mid(1));
emit showNickMenu(anc.path().mid(1));
e->accept();
} else {
QMenu *menu = createStandardContextMenu(e->pos());
Expand Down
5 changes: 4 additions & 1 deletion src/chatview_te.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class ChatView : public PsiTextView, public ChatViewCommon {
void init();
void setDialog(QWidget *dialog);
void setSessionData(bool isMuc, bool isMucPrivate, const XMPP::Jid &jid, const QString name);
void setLocalNickname(const QString &nickname);

void insertText(const QString &text, QTextCursor &insertCursor);
void appendText(const QString &text);
Expand Down Expand Up @@ -97,9 +98,10 @@ private slots:
void slotScroll();

signals:
void showNM(const QString &);
void showNickMenu(const QString &);
void quote(const QString &text);
void nickInsertClick(const QString &nick);
void outgoingReactions(const QString &messageId, const QSet<QString> &reactions);

private:
bool isMuc_;
Expand All @@ -109,6 +111,7 @@ private slots:
int oldTrackBarPosition;
XMPP::Jid jid_;
QString name_;
QString localNickname_;
QPointer<QWidget> dialog_;
QAction *actQuote_;
};
Expand Down
42 changes: 38 additions & 4 deletions src/chatview_webkit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ class ChatViewThemeSessionBridge;

class ChatViewPrivate {
public:
ChatViewPrivate() = default;
ChatViewPrivate(ChatView *q) : q(q) { }

ChatView *q;

Theme theme;

Expand All @@ -90,6 +92,7 @@ class ChatViewPrivate {
AvatarFactory::UserHashes remoteIcons;
AvatarFactory::UserHashes localIcons;
ChatViewThemeProvider *themeProvider = nullptr;
QString localNickName;

static QString closeIconTags(const QString &richText)
{
Expand Down Expand Up @@ -298,6 +301,27 @@ class ChatViewJSObject : public ChatViewThemeSession {
connect(reply, SIGNAL(finished()), SLOT(onUrlHeadersReady()));
}

Q_INVOKABLE void react(const QString &messageId, const QString &reaction)
{
if (messageId.isEmpty()) {
qWarning("empty message id on sending reaction. broken theme?");
return;
}
_view->outgoingReaction(messageId, reaction);
}

Q_INVOKABLE void deleteMessage(const QString &messageId) { qDebug() << "deleteMessage" << messageId; }

Q_INVOKABLE void replyMessage(const QString &messageId) { qDebug() << "replyMessage" << messageId; }

Q_INVOKABLE void copyMessage(const QString &messageId) { qDebug() << "copyMessage" << messageId; }

Q_INVOKABLE void showInfo(const QString &nick) { qDebug() << "showInfo" << nick; }

Q_INVOKABLE void openChat(const QString &nick) { qDebug() << "openChat" << nick; }

Q_INVOKABLE void kick(const QString &nick) { qDebug() << "kick" << nick; }

private slots:
void onUrlHeadersReady()
{
Expand Down Expand Up @@ -420,7 +444,7 @@ class ChatViewPage : public QWebPage {
//----------------------------------------------------------------------------
// ChatView
//----------------------------------------------------------------------------
ChatView::ChatView(QWidget *parent) : QFrame(parent), d(new ChatViewPrivate)
ChatView::ChatView(QWidget *parent) : QFrame(parent), d(new ChatViewPrivate(this))
{
d->jsObject = new ChatViewJSObject(this); /* It's a session bridge between html and c++ part */
d->webView = new WebView(this);
Expand Down Expand Up @@ -536,6 +560,8 @@ void ChatView::setAccount(PsiAccount *acc)
connect(d->themeProvider, SIGNAL(themeChanged()), SLOT(init()));
}

void ChatView::setLocalNickname(const QString &nickname) { d->localNickName = nickname; }

void ChatView::contextMenuEvent(QContextMenuEvent *e)
{
QUrl linkUrl;
Expand All @@ -550,7 +576,7 @@ void ChatView::contextMenuEvent(QContextMenuEvent *e)
linkUrl = d->webView->page()->mainFrame()->hitTestContent(e->pos()).linkUrl();
#endif
if (linkUrl.scheme() == "addnick") {
emit showNM(linkUrl.path().mid(1));
emit showNickMenu(linkUrl.path().mid(1));
e->accept();
}
}
Expand Down Expand Up @@ -697,7 +723,8 @@ void ChatView::dispatchMessage(const MessageView &mv)
m["sender"] = mv.nick();
m["messageid"] = mv.reactionsId();
{
auto rl = updateReactions(mv.nick(), mv.reactionsId(), mv.reactions());
auto n = d->isMuc_ ? mv.nick() : QString::fromLatin1(mv.isLocal() ? "l" : "r");
auto rl = updateReactions(n, mv.reactionsId(), mv.reactions());
auto vl = QVariantList();
for (auto &r : std::as_const(rl)) {
auto vmr = QVariantMap();
Expand Down Expand Up @@ -805,4 +832,11 @@ QWidget *ChatView::realTextWidget() { return d->webView; }

QObject *ChatView::jsBridge() { return d->jsObject; }

void ChatView::outgoingReaction(const QString &messageId, const QString &reaction)
{
auto n = d->isMuc_ ? d->localNickName : QString::fromLatin1("l");
auto reactions = onReactionSwitched(n, messageId, reaction);
emit outgoingReactions(messageId, reactions);
}

#include "chatview_webkit.moc"
7 changes: 6 additions & 1 deletion src/chatview_webkit.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ChatView : public QFrame, public ChatViewCommon {
void setDialog(QWidget *dialog);
void setSessionData(bool isMuc, bool isMucPrivate, const XMPP::Jid &jid, const QString name);
void setAccount(PsiAccount *acc);
void setLocalNickname(const QString &nickname);

void contextMenuEvent(QContextMenuEvent *event);
bool handleCopyEvent(QObject *object, QEvent *event, ChatEdit *chatEdit);
Expand Down Expand Up @@ -80,6 +81,9 @@ public slots:
void changeEvent(QEvent *event);
// void keyPressEvent(QKeyEvent *);

private:
void outgoingReaction(const QString &messageId, const QString &reaction);

protected slots:
void psiOptionChanged(const QString &);
// void autoCopy();
Expand All @@ -92,9 +96,10 @@ private slots:
void sessionInited();

signals:
void showNM(const QString &);
void showNickMenu(const QString &);
void nickInsertClick(const QString &nick);
void quote(const QString &text);
void outgoingReactions(const QString &messageId, const QSet<QString> &reactions);

private:
friend class ChatViewPrivate;
Expand Down
20 changes: 20 additions & 0 deletions src/chatviewcommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,23 @@ ChatViewCommon::updateReactions(const QString &senderNickname, const QString &me
}
return ret;
}

QSet<QString> ChatViewCommon::onReactionSwitched(const QString &senderNickname, const QString &messageId,
const QString &reaction)
{
auto msgIt = _reactions.find(messageId);
if (msgIt == _reactions.end()) {
return { { reaction } };
}
auto userIt = msgIt->perUser.find(senderNickname);
if (userIt == msgIt->perUser.end()) {
return { { reaction } };
}
auto ret = *userIt;
if (ret.contains(reaction)) {
ret.remove(reaction);
} else {
ret.insert(reaction);
}
return ret;
}
5 changes: 5 additions & 0 deletions src/chatviewcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ChatViewCommon {
QList<QColor> getPalette();

protected:
// a cache of reactions per message
struct Reactions {
QMap<QString, QStringList> total; // unicode reaction => nicknames
QHash<QString, QSet<QString>> perUser; // nickname => unicode reactions
Expand All @@ -54,9 +55,13 @@ class ChatViewCommon {
void removeUser(const QString &nickname);
void renameUser(const QString &oldNickname, const QString &newNickname);

// takes incoming reactions and returns reactions to be send to UI
QList<ReactionsItem> updateReactions(const QString &senderNickname, const QString &messageId,
const QSet<QString> &reactions);

// to be called from UI stuff. return list of reactions to send over network
QSet<QString> onReactionSwitched(const QString &senderNickname, const QString &messageId, const QString &reaction);

protected:
QDateTime _lastMsgTime;

Expand Down
22 changes: 21 additions & 1 deletion src/groupchatdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ public slots:
if (!nick.isEmpty()) {
prev_self = self;
self = nick;
dlg->ui_.log->setLocalNickname(self);
dlg->account()->groupChatChangeNick(dlg->jid().domain(), dlg->jid().node(), self,
dlg->account()->status());
}
Expand Down Expand Up @@ -404,6 +405,7 @@ join <channel>{,<channel>} [pass{,<pass>}
// FIXME nick can't be empty....
prev_self = self;
self = nick;
dlg->ui_.log->setLocalNickname(self);
dlg->account()->groupChatChangeNick(dlg->jid().domain(), dlg->jid().node(), self,
dlg->account()->status());
newstate = nullptr;
Expand Down Expand Up @@ -675,6 +677,19 @@ void GCMainDlg::onNickInsertClick(const QString &nick)
ui_.mle->chatEdit()->setFocus();
}

void GCMainDlg::outgoingReactions(const QString &messageId, const QSet<QString> &reactions)
{
Message m(jid());
m.setType(Message::Type::Groupchat);
m.setReactions({ messageId, reactions });
QString id = account()->client()->genUniqueId();
m.setId(id); // we need id early for message manipulations in chatview
m.setTimeStamp(QDateTime::currentDateTime());
// d->mle()->appendMessageHistory(m.body());

emit aSend(m);
}

void GCMainDlg::doContactContextMenu(const QString &nick)
{
auto itm = d->usersModel->findEntry(nick);
Expand Down Expand Up @@ -865,15 +880,17 @@ GCMainDlg::GCMainDlg(PsiAccount *pa, const Jid &j, TabManager *tabManager) : Tab
d->tabmode = PsiOptions::instance()->getOption("options.ui.tabs.use-tabs").toBool();

ui_.log->setSessionData(true, false, jid(), jid().full()); // FIXME change conference name
ui_.log->setLocalNickname(d->self);
#ifdef WEBKIT
ui_.log->setAccount(account());
#else
ui_.log->setMediaOpener(account()->fileSharingDeviceOpener());
#endif

connect(ui_.log, SIGNAL(showNM(QString)), this, SLOT(doContactContextMenu(QString)));
connect(ui_.log, SIGNAL(showNickMenu(QString)), this, SLOT(doContactContextMenu(QString)));
connect(URLObject::getInstance(), SIGNAL(openURL(QString)), SLOT(openURL(QString)));
connect(ui_.log, SIGNAL(nickInsertClick(QString)), SLOT(onNickInsertClick(QString)));
connect(ui_.log, &ChatView::outgoingReactions, this, &GCMainDlg::outgoingReactions);

PsiToolTip::install(ui_.le_topic);

Expand Down Expand Up @@ -1438,6 +1455,7 @@ void GCMainDlg::mle_returnPressed()
if (!nick.isEmpty() && newJid.isValid()) {
d->prev_self = d->self;
d->self = newJid.resource();
ui_.log->setLocalNickname(d->self);
account()->groupChatChangeNick(jid().domain(), jid().node(), d->self, account()->status());
}
ui_.mle->chatEdit()->setText("");
Expand Down Expand Up @@ -1697,6 +1715,7 @@ void GCMainDlg::setJid(const Jid &j)
{
TabbableWidget::setJid(j);
d->self = d->prev_self = j.resource();
ui_.log->setLocalNickname(d->self);
}

void GCMainDlg::goConn()
Expand Down Expand Up @@ -1823,6 +1842,7 @@ void GCMainDlg::presence(const QString &nick, const Status &s)
if (s.errorCode() == 409) {
message = tr("Please choose a different nickname");
d->self = d->prev_self;
ui_.log->setLocalNickname(d->self);
} else {
message = tr("An error occurred (errorcode: %1)").arg(s.errorCode());
}
Expand Down
1 change: 1 addition & 0 deletions src/groupchatdlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ private slots:
void avatarUpdated(const Jid &jid);
void doContactContextMenu(const QString &nick);

void outgoingReactions(const QString &messageId, const QSet<QString> &reactions);
public:
class Private;
friend class Private;
Expand Down
2 changes: 1 addition & 1 deletion src/psiaccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2821,7 +2821,7 @@ void PsiAccount::processIncomingMessage(const Message &_m)
if (_m.type() != Message::Type::Error && _m.body().isEmpty() && _m.urlList().isEmpty() && _m.invite().isEmpty()
&& !_m.containsEvents() && _m.chatState() == StateNone && _m.subject().isNull()
&& _m.rosterExchangeItems().isEmpty() && _m.mucInvites().isEmpty() && _m.getForm().fields().empty()
&& _m.messageReceipt() == ReceiptNone && _m.getMUCStatuses().isEmpty())
&& _m.messageReceipt() == ReceiptNone && _m.getMUCStatuses().isEmpty() && _m.reactions().targetId.isEmpty())
return;

// skip headlines?
Expand Down
2 changes: 2 additions & 0 deletions themes/chatview.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<file>chatview/adium/Template.html</file>
<file>chatview/adium/adapter.js</file>
<file>chatview/psi/psi.css</file>
<file>chatview/psi/bubble/index.html</file>
<file>chatview/psi/bubble/load.js</file>
<file>chatview/psi/LunnaCat_Classic/index.html</file>
<file>chatview/psi/LunnaCat_Classic/images/HR.png</file>
<file>chatview/psi/LunnaCat_Classic/images/ChatLog.png</file>
Expand Down
Loading

0 comments on commit de922a1

Please sign in to comment.