Skip to content

Commit 9b33f41

Browse files
committed
Implement input field for notification replies and connect actions to NotificationClient
1 parent bd7590d commit 9b33f41

File tree

6 files changed

+219
-11
lines changed

6 files changed

+219
-11
lines changed

src/MainWindow.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ void MainWindow::setupUI()
5050
// Create notification panel
5151
m_notificationPanel = new NotificationPanel();
5252

53+
// Set notification manager reference for action handling
54+
m_notificationPanel->setNotificationManager(m_notificationManager);
55+
5356
// Create animation manager
5457
m_animationManager = new AnimationManager(m_notificationPanel, this);
5558

src/NotificationCard.cpp

Lines changed: 166 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@ NotificationCard::NotificationCard(const NotificationData& notification, QWidget
2424
, m_actionIndicator(nullptr)
2525
, m_actionWidget(nullptr)
2626
, m_actionButtonsLayout(nullptr)
27+
, m_inputWidget(nullptr)
28+
, m_replyInput(nullptr)
29+
, m_sendButton(nullptr)
30+
, m_cancelButton(nullptr)
2731
, m_isHovered(false)
2832
, m_actionsVisible(false)
2933
, m_bodiesExpanded(false)
34+
, m_inputVisible(false)
3035
{
3136
setupUI();
3237

@@ -182,6 +187,10 @@ void NotificationCard::setupUI()
182187

183188
// Setup action buttons (initially hidden)
184189
setupActionButtons();
190+
191+
// Setup input field (initially hidden)
192+
setupInputField();
193+
185194
updateGeometry();
186195
}
187196

@@ -280,6 +289,104 @@ void NotificationCard::setupActionButtons()
280289
m_actionWidget->hide();
281290
}
282291

292+
void NotificationCard::setupInputField()
293+
{
294+
// Create input widget container
295+
m_inputWidget = new QWidget(this);
296+
m_inputLayout = new QVBoxLayout(m_inputWidget);
297+
m_inputLayout->setContentsMargins(0, 5, 0, 0);
298+
m_inputLayout->setSpacing(6);
299+
300+
// Create reply input field
301+
m_replyInput = new QLineEdit(m_inputWidget);
302+
m_replyInput->setPlaceholderText("Type your reply...");
303+
m_replyInput->setStyleSheet(
304+
"QLineEdit {"
305+
" background-color: rgba(60, 60, 60, 0.8);"
306+
" border: 1px solid rgba(255, 255, 255, 0.2);"
307+
" border-radius: 4px;"
308+
" color: white;"
309+
" font-size: 12px;"
310+
" padding: 6px 8px;"
311+
"}"
312+
"QLineEdit:focus {"
313+
" border: 1px solid rgba(70, 130, 180, 0.8);"
314+
" background-color: rgba(70, 70, 70, 0.9);"
315+
"}"
316+
);
317+
318+
// Connect return key to send
319+
connect(m_replyInput, &QLineEdit::returnPressed, this, &NotificationCard::onInputReturnPressed);
320+
321+
m_inputLayout->addWidget(m_replyInput);
322+
323+
// Create buttons layout
324+
m_inputButtonsLayout = new QHBoxLayout();
325+
m_inputButtonsLayout->setSpacing(8);
326+
327+
// Create send button
328+
m_sendButton = new QPushButton("Send", m_inputWidget);
329+
m_sendButton->setStyleSheet(
330+
"QPushButton {"
331+
" background-color: rgba(70, 130, 180, 0.8);"
332+
" border: 1px solid rgba(255, 255, 255, 0.2);"
333+
" border-radius: 4px;"
334+
" color: white;"
335+
" font-size: 11px;"
336+
" padding: 4px 12px;"
337+
" min-width: 50px;"
338+
"}"
339+
"QPushButton:hover {"
340+
" background-color: rgba(70, 130, 180, 1.0);"
341+
" border: 1px solid rgba(255, 255, 255, 0.4);"
342+
"}"
343+
"QPushButton:pressed {"
344+
" background-color: rgba(50, 110, 160, 1.0);"
345+
"}"
346+
);
347+
348+
// Create cancel button
349+
m_cancelButton = new QPushButton("Cancel", m_inputWidget);
350+
m_cancelButton->setStyleSheet(
351+
"QPushButton {"
352+
" background-color: rgba(120, 120, 120, 0.6);"
353+
" border: 1px solid rgba(255, 255, 255, 0.2);"
354+
" border-radius: 4px;"
355+
" color: white;"
356+
" font-size: 11px;"
357+
" padding: 4px 12px;"
358+
" min-width: 50px;"
359+
"}"
360+
"QPushButton:hover {"
361+
" background-color: rgba(140, 140, 140, 0.8);"
362+
" border: 1px solid rgba(255, 255, 255, 0.4);"
363+
"}"
364+
"QPushButton:pressed {"
365+
" background-color: rgba(100, 100, 100, 0.8);"
366+
"}"
367+
);
368+
369+
// Connect button signals
370+
connect(m_sendButton, &QPushButton::clicked, this, &NotificationCard::onSendButtonClicked);
371+
connect(m_cancelButton, &QPushButton::clicked, this, &NotificationCard::onCancelButtonClicked);
372+
373+
// Add buttons to layout
374+
m_inputButtonsLayout->addWidget(m_sendButton);
375+
m_inputButtonsLayout->addWidget(m_cancelButton);
376+
m_inputButtonsLayout->addStretch();
377+
378+
// Create buttons container widget
379+
QWidget* buttonsWidget = new QWidget(m_inputWidget);
380+
buttonsWidget->setLayout(m_inputButtonsLayout);
381+
m_inputLayout->addWidget(buttonsWidget);
382+
383+
// Add input widget to main layout
384+
m_mainLayout->addWidget(m_inputWidget);
385+
386+
// Initially hidden
387+
m_inputWidget->hide();
388+
}
389+
283390
void NotificationCard::showActions()
284391
{
285392
if (m_actionWidget && !m_notificationData.actions.isEmpty()) {
@@ -318,6 +425,33 @@ void NotificationCard::hideBodies()
318425
}
319426
}
320427

428+
void NotificationCard::showInput(const QString& actionKey)
429+
{
430+
if (m_inputWidget) {
431+
m_currentActionKey = actionKey;
432+
m_replyInput->clear();
433+
m_replyInput->setFocus();
434+
m_inputWidget->show();
435+
m_inputVisible = true;
436+
437+
// Hide action buttons when showing input
438+
hideActions();
439+
440+
updateCardHeight();
441+
}
442+
}
443+
444+
void NotificationCard::hideInput()
445+
{
446+
if (m_inputWidget) {
447+
m_inputWidget->hide();
448+
m_inputVisible = false;
449+
m_currentActionKey.clear();
450+
451+
updateCardHeight();
452+
}
453+
}
454+
321455
void NotificationCard::onActionButtonClicked()
322456
{
323457
QPushButton* button = qobject_cast<QPushButton*>(sender());
@@ -327,10 +461,10 @@ void NotificationCard::onActionButtonClicked()
327461
QString actionType = button->property("actionType").toString();
328462

329463
if (actionType == "remote_input") {
330-
// For now, emit a signal to handle reply input
331-
// In a full implementation, you'd show an input dialog
332-
emit replyRequested(actionKey, "Quick reply from desktop");
464+
// Show input field for reply
465+
showInput(actionKey);
333466
} else {
467+
// Regular action - emit signal immediately
334468
emit actionClicked(actionKey);
335469
}
336470
}
@@ -347,12 +481,32 @@ bool NotificationCard::eventFilter(QObject *obj, QEvent *event)
347481
return QWidget::eventFilter(obj, event);
348482
}
349483

484+
void NotificationCard::onSendButtonClicked()
485+
{
486+
QString replyText = m_replyInput->text().trimmed();
487+
if (!replyText.isEmpty() && !m_currentActionKey.isEmpty()) {
488+
emit replyRequested(m_currentActionKey, replyText);
489+
hideInput();
490+
}
491+
}
492+
493+
void NotificationCard::onCancelButtonClicked()
494+
{
495+
hideInput();
496+
}
497+
498+
void NotificationCard::onInputReturnPressed()
499+
{
500+
onSendButtonClicked();
501+
}
502+
350503
void NotificationCard::onActionIndicatorClicked()
351504
{
352-
if (m_actionsVisible || m_bodiesExpanded) {
353-
// Hide expanded content (actions and/or bodies)
505+
if (m_actionsVisible || m_bodiesExpanded || m_inputVisible) {
506+
// Hide expanded content (actions, bodies, and/or input)
354507
hideActions();
355508
hideBodies();
509+
hideInput();
356510
if (m_actionIndicator) {
357511
m_actionIndicator->setText(""); // Down arrow
358512
}
@@ -365,3 +519,10 @@ void NotificationCard::onActionIndicatorClicked()
365519
}
366520
}
367521
}
522+
523+
void NotificationCard::updateCardHeight()
524+
{
525+
// Let Qt handle the height automatically through layout system
526+
updateGeometry();
527+
update();
528+
}

src/NotificationCard.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <QPushButton>
77
#include <QHBoxLayout>
88
#include <QVBoxLayout>
9+
#include <QLineEdit>
910
#include <QEnterEvent>
1011
#include "NotificationData.h"
1112

@@ -36,15 +37,21 @@ private slots:
3637
void onRemoveClicked();
3738
void onActionButtonClicked();
3839
void onActionIndicatorClicked();
40+
void onSendButtonClicked();
41+
void onCancelButtonClicked();
42+
void onInputReturnPressed();
3943

4044
private:
4145
void setupUI();
4246
void updateTimeLabel();
4347
void setupActionButtons();
48+
void setupInputField();
4449
void showActions();
4550
void hideActions();
4651
void showBodies();
4752
void hideBodies();
53+
void showInput(const QString& actionKey);
54+
void hideInput();
4855
void updateCardHeight();
4956

5057
NotificationData m_notificationData;
@@ -64,9 +71,19 @@ private slots:
6471
QHBoxLayout* m_actionButtonsLayout;
6572
QList<QPushButton*> m_actionButtons;
6673

74+
// Input field for remote_input actions
75+
QWidget* m_inputWidget; // Container for input field and send/cancel buttons
76+
QVBoxLayout* m_inputLayout;
77+
QLineEdit* m_replyInput;
78+
QHBoxLayout* m_inputButtonsLayout;
79+
QPushButton* m_sendButton;
80+
QPushButton* m_cancelButton;
81+
QString m_currentActionKey; // Track which action key the input is for
82+
6783
bool m_isHovered;
6884
bool m_actionsVisible;
6985
bool m_bodiesExpanded; // Track if we're showing all bodies
86+
bool m_inputVisible; // Track if input field is visible
7087

7188
static constexpr int CARD_MARGIN = 12;
7289
static constexpr int CARD_SPACING = 8;

src/NotificationClient.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -392,18 +392,19 @@ void NotificationClient::sendNotificationReply(const QString& notificationId, co
392392
{
393393
if (!m_handshakeComplete) return;
394394

395-
QJsonObject replyMsg;
396-
replyMsg["type"] = "notification_reply";
397-
replyMsg["id"] = QUuid::createUuid().toString(QUuid::WithoutBraces);
398-
replyMsg["timestamp"] = QDateTime::currentSecsSinceEpoch();
395+
QJsonObject actionMsg;
396+
actionMsg["type"] = "notification_action";
397+
actionMsg["id"] = QUuid::createUuid().toString(QUuid::WithoutBraces);
398+
actionMsg["timestamp"] = QDateTime::currentSecsSinceEpoch();
399399

400400
QJsonObject payload;
401401
payload["id"] = notificationId;
402402
payload["key"] = actionKey;
403+
payload["type"] = "remote_input";
403404
payload["body"] = replyText;
404-
replyMsg["payload"] = payload;
405+
actionMsg["payload"] = payload;
405406

406-
sendMessage(replyMsg);
407+
sendMessage(actionMsg);
407408
}
408409

409410
void NotificationClient::sendNotificationAction(const QString& notificationId, const QString& actionKey)
@@ -418,6 +419,7 @@ void NotificationClient::sendNotificationAction(const QString& notificationId, c
418419
QJsonObject payload;
419420
payload["id"] = notificationId;
420421
payload["key"] = actionKey;
422+
payload["type"] = "action";
421423
actionMsg["payload"] = payload;
422424

423425
sendMessage(actionMsg);

src/NotificationPanel.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "NotificationPanel.h"
22
#include "NotificationCard.h"
3+
#include "NotificationManager.h"
4+
#include "NotificationClient.h"
35

46
#include <QApplication>
57
#include <QScreen>
@@ -20,6 +22,7 @@ NotificationPanel::NotificationPanel(QWidget *parent)
2022
, m_scrollLayout(nullptr)
2123
, m_emptyLabel(nullptr)
2224
, m_clearButton(nullptr)
25+
, m_notificationManager(nullptr)
2326
{
2427
setupUI();
2528
positionPanel();
@@ -192,6 +195,11 @@ void NotificationPanel::positionPanel()
192195
}
193196
}
194197

198+
void NotificationPanel::setNotificationManager(NotificationManager* manager)
199+
{
200+
m_notificationManager = manager;
201+
}
202+
195203
void NotificationPanel::addNotification(const NotificationData& notification)
196204
{
197205
// Hide empty label if visible
@@ -238,6 +246,21 @@ void NotificationPanel::addNotification(const NotificationData& notification)
238246
removeNotification(card->getNotificationId());
239247
});
240248

249+
// Connect action signals to notification client
250+
if (m_notificationManager && m_notificationManager->getClient()) {
251+
auto client = m_notificationManager->getClient();
252+
253+
connect(card, &NotificationCard::actionClicked,
254+
this, [client, card](const QString& actionKey) {
255+
client->sendNotificationAction(card->getNotificationData().stringId, actionKey);
256+
});
257+
258+
connect(card, &NotificationCard::replyRequested,
259+
this, [client, card](const QString& actionKey, const QString& replyText) {
260+
client->sendNotificationReply(card->getNotificationData().stringId, actionKey, replyText);
261+
});
262+
}
263+
241264
// Insert at the beginning (newest first)
242265
m_scrollLayout->insertWidget(0, card);
243266
m_notificationCards.prepend(card);

src/NotificationPanel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class NotificationPanel : public QWidget
2121

2222
void setupUI();
2323
void positionPanel();
24+
void setNotificationManager(class NotificationManager* manager);
2425

2526
public slots:
2627
void addNotification(const NotificationData& notification);
@@ -49,6 +50,7 @@ public slots:
4950
QPushButton* m_clearButton;
5051

5152
QList<NotificationCard*> m_notificationCards;
53+
class NotificationManager* m_notificationManager;
5254
};
5355

5456
#endif // NOTIFICATIONPANEL_H

0 commit comments

Comments
 (0)