@@ -20,12 +20,14 @@ mac{ | |||||
LIBS += -framework Foundation | LIBS += -framework Foundation | ||||
OBJECTIVE_SOURCES += osx/notification.mm | |||||
OBJECTIVE_SOURCES += osx/notification.mm\ | |||||
osx/notificationimpl.mm | |||||
SOURCES += osx/osxplatform.cpp | SOURCES += osx/osxplatform.cpp | ||||
HEADERS += osx/notification.h\ | HEADERS += osx/notification.h\ | ||||
osx/osxplatform.h | |||||
osx/osxplatform.h\ | |||||
osx/notificationimpl.h | |||||
} | } | ||||
SOURCES += main.cpp\ | SOURCES += main.cpp\ | ||||
@@ -54,7 +56,6 @@ SOURCES += main.cpp\ | |||||
chooseemojiwidget.cpp \ | chooseemojiwidget.cpp \ | ||||
sendtextedit.cpp \ | sendtextedit.cpp \ | ||||
feiqwin.cpp \ | feiqwin.cpp \ | ||||
plugin/unreadchecker.cpp \ | |||||
plugin/iplugin.cpp \ | plugin/iplugin.cpp \ | ||||
plugin/rankuser.cpp \ | plugin/rankuser.cpp \ | ||||
settings.cpp | settings.cpp | ||||
@@ -94,7 +95,6 @@ HEADERS += mainwindow.h \ | |||||
sendtextedit.h \ | sendtextedit.h \ | ||||
plugin/iplugin.h \ | plugin/iplugin.h \ | ||||
feiqwin.h \ | feiqwin.h \ | ||||
plugin/unreadchecker.h \ | |||||
plugin/rankuser.h \ | plugin/rankuser.h \ | ||||
settings.h | settings.h | ||||
@@ -2,8 +2,6 @@ | |||||
#include "mainwindow.h" | #include "mainwindow.h" | ||||
#include "plugin/iplugin.h" | #include "plugin/iplugin.h" | ||||
#include "plugin/unreadchecker.h" | |||||
FeiqWin::FeiqWin() | FeiqWin::FeiqWin() | ||||
{ | { | ||||
@@ -34,11 +32,6 @@ Settings *FeiqWin::settings() | |||||
return mMainWin->mSettings; | return mMainWin->mSettings; | ||||
} | } | ||||
int FeiqWin::getUnreadCount() | |||||
{ | |||||
return mMainWin->getUnreadCount(); | |||||
} | |||||
void FeiqWin::init(MainWindow *mainWin) | void FeiqWin::init(MainWindow *mainWin) | ||||
{ | { | ||||
mMainWin = mainWin; | mMainWin = mainWin; | ||||
@@ -27,9 +27,6 @@ public: | |||||
const FeiqModel* feiqModel(); | const FeiqModel* feiqModel(); | ||||
Settings* settings(); | Settings* settings(); | ||||
public: | |||||
int getUnreadCount(); | |||||
private: | private: | ||||
void init(MainWindow* mainWin); | void init(MainWindow* mainWin); | ||||
void unInit(); | void unInit(); | ||||
@@ -80,6 +80,9 @@ MainWindow::MainWindow(QWidget *parent) : | |||||
connect(ui->actionSendKnock, SIGNAL(triggered(bool)), this, SLOT(sendKnock())); | connect(ui->actionSendKnock, SIGNAL(triggered(bool)), this, SLOT(sendKnock())); | ||||
connect(ui->actionSendFile, SIGNAL(triggered(bool)), this, SLOT(sendFile())); | connect(ui->actionSendFile, SIGNAL(triggered(bool)), this, SLOT(sendFile())); | ||||
//初始化平台相关特性 | |||||
PlatformDepend::instance().setMainWnd(this); | |||||
//初始化飞秋引擎 | //初始化飞秋引擎 | ||||
connect(this, SIGNAL(feiqViewEvent(shared_ptr<ViewEvent>)), this, SLOT(handleFeiqViewEvent(shared_ptr<ViewEvent>))); | connect(this, SIGNAL(feiqViewEvent(shared_ptr<ViewEvent>)), this, SLOT(handleFeiqViewEvent(shared_ptr<ViewEvent>))); | ||||
@@ -105,13 +108,55 @@ void MainWindow::setFeiqWin(FeiqWin *feiqWin) | |||||
mFeiqWin->init(this); | mFeiqWin->init(this); | ||||
} | } | ||||
void MainWindow::onNotifyClicked(const QString& fellowIp) | |||||
{ | |||||
qDebug()<<fellowIp; | |||||
auto fellow = mFeiq.getModel().findFirstFellowOf(fellowIp.toStdString()); | |||||
if (fellow) | |||||
openChartTo(fellow.get()); | |||||
raise(); | |||||
activateWindow(); | |||||
showNormal(); | |||||
} | |||||
void MainWindow::onNotifyReplied(long notifyId, const QString &fellowIp, const QString &reply) | |||||
{ | |||||
auto fellow = mFeiq.getModel().findFirstFellowOf(fellowIp.toStdString()); | |||||
if (fellow) | |||||
{ | |||||
//回复消息 | |||||
auto content = make_shared<TextContent>(); | |||||
content->text = reply.toStdString(); | |||||
mFeiq.send(fellow, content); | |||||
//设为已回复 | |||||
auto msgRepliedTo = findUnshownMessage(notifyId); | |||||
if (msgRepliedTo) | |||||
{ | |||||
msgRepliedTo->replied=true; | |||||
} | |||||
//将自己的回复放入未显示列表 | |||||
auto event = make_shared<MessageViewEvent>(); | |||||
event->contents.push_back(content); | |||||
event->fellow = nullptr; | |||||
auto& msg = addUnshownMessage(fellow.get(), event); | |||||
msg.read = true; | |||||
updateUnshownHint(fellow.get()); | |||||
} | |||||
} | |||||
void MainWindow::enterEvent(QEvent *event) | void MainWindow::enterEvent(QEvent *event) | ||||
{ | { | ||||
auto fellow = mRecvTextEdit->curFellow(); | auto fellow = mRecvTextEdit->curFellow(); | ||||
if (fellow) | if (fellow) | ||||
{ | { | ||||
flushUnread(fellow); | |||||
updateUnread(fellow); | |||||
flushUnshown(fellow); | |||||
updateUnshownHint(fellow); | |||||
} | } | ||||
PlatformDepend::instance().hideAllNotify(); | PlatformDepend::instance().hideAllNotify(); | ||||
@@ -122,8 +167,8 @@ void MainWindow::openChartTo(const Fellow *fellow) | |||||
mFellowList.top(*fellow); | mFellowList.top(*fellow); | ||||
mRecvTextEdit->setCurFellow(fellow); | mRecvTextEdit->setCurFellow(fellow); | ||||
setWindowTitle(mTitle + " - 与"+fellow->getName().c_str()+"会话中"); | setWindowTitle(mTitle + " - 与"+fellow->getName().c_str()+"会话中"); | ||||
flushUnread(fellow); | |||||
updateUnread(fellow); | |||||
flushUnshown(fellow); | |||||
updateUnshownHint(fellow); | |||||
} | } | ||||
shared_ptr<Fellow> MainWindow::checkCurFellow() | shared_ptr<Fellow> MainWindow::checkCurFellow() | ||||
@@ -150,7 +195,9 @@ void MainWindow::onStateChanged(FileTask *fileTask) | |||||
if (fileTask->getState()==FileTaskState::Finish) | if (fileTask->getState()==FileTaskState::Finish) | ||||
{ | { | ||||
auto title = QString(fileTask->getTaskTypeDes().c_str())+"完成"; | auto title = QString(fileTask->getTaskTypeDes().c_str())+"完成"; | ||||
PlatformDepend::instance().showNotify(title, fileTask->getContent()->filename.c_str()); | |||||
PlatformDepend::instance().showNotify(title, | |||||
fileTask->getContent()->filename.c_str(), | |||||
fileTask->fellow()->getIp().c_str()); | |||||
} | } | ||||
else if (fileTask->getState()==FileTaskState::Error) | else if (fileTask->getState()==FileTaskState::Error) | ||||
{ | { | ||||
@@ -158,7 +205,9 @@ void MainWindow::onStateChanged(FileTask *fileTask) | |||||
auto content = QString(fileTask->getContent()->filename.c_str()); | auto content = QString(fileTask->getContent()->filename.c_str()); | ||||
content += "\n"; | content += "\n"; | ||||
content += fileTask->getDetailInfo().c_str(); | content += fileTask->getDetailInfo().c_str(); | ||||
PlatformDepend::instance().showNotify(title, content); | |||||
PlatformDepend::instance().showNotify(title, | |||||
content, | |||||
fileTask->fellow()->getIp().c_str()); | |||||
} | } | ||||
if (mDownloadFileDlg->isVisible()) | if (mDownloadFileDlg->isVisible()) | ||||
@@ -200,23 +249,15 @@ void MainWindow::handleFeiqViewEvent(shared_ptr<ViewEvent> event) | |||||
auto e = static_cast<FellowViewEvent*>(event.get()); | auto e = static_cast<FellowViewEvent*>(event.get()); | ||||
auto fellow = e->fellow.get(); | auto fellow = e->fellow.get(); | ||||
if (isActiveWindow()) | |||||
if (isActiveWindow() && fellow == mRecvTextEdit->curFellow()) | |||||
{//窗口可见,处理当前用户消息,其他用户消息则放入通知队列 | {//窗口可见,处理当前用户消息,其他用户消息则放入通知队列 | ||||
if (fellow == mRecvTextEdit->curFellow()) | |||||
{ | |||||
readEvent(event.get()); | |||||
} | |||||
else | |||||
{ | |||||
mUnreadEvents[fellow].push_back(event); | |||||
updateUnread(fellow); | |||||
} | |||||
readEvent(event.get()); | |||||
} | } | ||||
else | else | ||||
{//窗口不可见,放入未读队列并通知 | {//窗口不可见,放入未读队列并通知 | ||||
mUnreadEvents[fellow].push_back(event); | |||||
updateUnread(fellow); | |||||
notifyUnread(event.get()); | |||||
auto& umsg = addUnshownMessage(fellow, event); | |||||
notifyUnshown(umsg); | |||||
updateUnshownHint(fellow); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -277,31 +318,39 @@ void MainWindow::userAddFellow(QString ip) | |||||
mFeiq.sendImOnLine(fellow->getIp()); | mFeiq.sendImOnLine(fellow->getIp()); | ||||
} | } | ||||
void MainWindow::notifyUnread(const ViewEvent *event) | |||||
void MainWindow::notifyUnshown(UnshownMessage& umsg) | |||||
{ | { | ||||
auto event = umsg.event.get(); | |||||
if (event->what == ViewEventType::SEND_TIMEO) | if (event->what == ViewEventType::SEND_TIMEO) | ||||
{ | { | ||||
auto e = static_cast<const SendTimeoEvent*>(event); | auto e = static_cast<const SendTimeoEvent*>(event); | ||||
auto fellow = e->fellow.get(); | auto fellow = e->fellow.get(); | ||||
showNotification(fellow, "发送超时:"+simpleTextOf(e->content.get())); | |||||
umsg.notifyId = showNotification(fellow, "发送超时:"+simpleTextOf(e->content.get())); | |||||
} | } | ||||
else if (event->what == ViewEventType::MESSAGE) | else if (event->what == ViewEventType::MESSAGE) | ||||
{ | { | ||||
auto e = static_cast<const MessageViewEvent*>(event); | auto e = static_cast<const MessageViewEvent*>(event); | ||||
auto fellow = e->fellow.get(); | auto fellow = e->fellow.get(); | ||||
QString text=""; | |||||
bool first=false; | |||||
for (auto content : e->contents) | for (auto content : e->contents) | ||||
{ | { | ||||
showNotification(fellow, simpleTextOf(content.get())); | |||||
auto t = simpleTextOf(content.get()); | |||||
if (first) | |||||
text = t; | |||||
else | |||||
text = text+"\n"+t; | |||||
} | } | ||||
umsg.notifyId = showNotification(fellow, text); | |||||
} | } | ||||
} | } | ||||
void MainWindow::showNotification(const Fellow *fellow, const QString &text) | |||||
long MainWindow::showNotification(const Fellow *fellow, const QString &text) | |||||
{ | { | ||||
QString content(text); | QString content(text); | ||||
if (content.length()>20) | if (content.length()>20) | ||||
content = content.left(20)+"..."; | content = content.left(20)+"..."; | ||||
PlatformDepend::instance().showNotify(QString(fellow->getName().c_str())+":", content); | |||||
return PlatformDepend::instance().showNotify(QString(fellow->getName().c_str())+":", content, fellow->getIp().c_str()); | |||||
} | } | ||||
void MainWindow::navigateToFileTask(IdType packetNo, IdType fileId, bool upload) | void MainWindow::navigateToFileTask(IdType packetNo, IdType fileId, bool upload) | ||||
@@ -462,12 +511,12 @@ void MainWindow::initFeiq() | |||||
qDebug()<<"feiq started"; | qDebug()<<"feiq started"; | ||||
} | } | ||||
void MainWindow::updateUnread(const Fellow *fellow) | |||||
void MainWindow::updateUnshownHint(const Fellow *fellow) | |||||
{ | { | ||||
auto it = mUnreadEvents.find(fellow); | |||||
if (it != mUnreadEvents.end()) | |||||
auto it = mUnshownEvents.find(fellow); | |||||
if (it != mUnshownEvents.end()) | |||||
{ | { | ||||
auto count = (*it).second.size(); | |||||
auto count = it->second.size(); | |||||
if (count == 0) | if (count == 0) | ||||
{ | { | ||||
mFellowList.mark(*fellow, ""); | mFellowList.mark(*fellow, ""); | ||||
@@ -483,26 +532,30 @@ void MainWindow::updateUnread(const Fellow *fellow) | |||||
int MainWindow::getUnreadCount() | int MainWindow::getUnreadCount() | ||||
{ | { | ||||
auto begin = mUnreadEvents.begin(); | |||||
auto end = mUnreadEvents.end(); | |||||
auto begin = mUnshownEvents.begin(); | |||||
auto end = mUnshownEvents.end(); | |||||
auto count = 0; | auto count = 0; | ||||
for (auto it = begin; it != end; it++) | for (auto it = begin; it != end; it++) | ||||
{ | { | ||||
count += it->second.size(); | |||||
for (auto msg : it->second) | |||||
{ | |||||
if (msg.isUnread()) | |||||
++count; | |||||
} | |||||
} | } | ||||
return count; | return count; | ||||
} | } | ||||
void MainWindow::flushUnread(const Fellow *fellow) | |||||
void MainWindow::flushUnshown(const Fellow *fellow) | |||||
{ | { | ||||
auto it = mUnreadEvents.find(fellow); | |||||
if (it != mUnreadEvents.end()) | |||||
auto it = mUnshownEvents.find(fellow); | |||||
if (it != mUnshownEvents.end()) | |||||
{ | { | ||||
auto& list = (*it).second; | auto& list = (*it).second; | ||||
while (!list.empty()) | while (!list.empty()) | ||||
{ | { | ||||
auto event = list.front(); | |||||
readEvent(event.get()); | |||||
auto msg = list.front(); | |||||
readEvent(msg.event.get()); | |||||
list.pop_front(); | list.pop_front(); | ||||
} | } | ||||
} | } | ||||
@@ -525,7 +578,10 @@ void MainWindow::readEvent(const ViewEvent *event) | |||||
auto time = e->when.time_since_epoch().count(); | auto time = e->when.time_since_epoch().count(); | ||||
for (auto content : e->contents) | for (auto content : e->contents) | ||||
{ | { | ||||
mRecvTextEdit->addFellowContent(content.get(), time); | |||||
if (e->fellow == nullptr) | |||||
mRecvTextEdit->addMyContent(content.get(), time); | |||||
else | |||||
mRecvTextEdit->addFellowContent(content.get(), time); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -550,3 +606,27 @@ QString MainWindow::simpleTextOf(const Content *content) | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
UnshownMessage &MainWindow::addUnshownMessage(const Fellow *fellow, shared_ptr<ViewEvent> event) | |||||
{ | |||||
UnshownMessage msg; | |||||
msg.event = event; | |||||
mUnshownEvents[fellow].push_back(msg); | |||||
return mUnshownEvents[fellow].back(); | |||||
} | |||||
UnshownMessage* MainWindow::findUnshownMessage(int id) | |||||
{ | |||||
auto begin = mUnshownEvents.begin(); | |||||
auto end = mUnshownEvents.end(); | |||||
for (auto it = begin; it != end; it++) | |||||
{ | |||||
for (auto& msg : it->second){ | |||||
if (msg.notifyId == id) | |||||
return &msg; | |||||
} | |||||
} | |||||
return nullptr; | |||||
} |
@@ -21,6 +21,19 @@ class MainWindow; | |||||
class FeiqWin; | class FeiqWin; | ||||
struct UnshownMessage | |||||
{ | |||||
shared_ptr<ViewEvent> event; | |||||
bool replied = false; | |||||
bool read = false; | |||||
long notifyId = 0; | |||||
bool isUnread() | |||||
{ | |||||
return !replied && !read; | |||||
} | |||||
}; | |||||
Q_DECLARE_METATYPE(shared_ptr<ViewEvent>) | Q_DECLARE_METATYPE(shared_ptr<ViewEvent>) | ||||
class MainWindow : public QMainWindow, IFeiqView | class MainWindow : public QMainWindow, IFeiqView | ||||
{ | { | ||||
@@ -33,6 +46,10 @@ public: | |||||
void setFeiqWin(FeiqWin* feiqWin); | void setFeiqWin(FeiqWin* feiqWin); | ||||
public slots: | |||||
void onNotifyClicked(const QString& fellowIp); | |||||
void onNotifyReplied(long notifyId, const QString& fellowIp, const QString& reply); | |||||
protected: | protected: | ||||
void enterEvent(QEvent *event); | void enterEvent(QEvent *event); | ||||
@@ -62,19 +79,22 @@ private slots: | |||||
private: | private: | ||||
void userAddFellow(QString ip); | void userAddFellow(QString ip); | ||||
void notifyUnread(const ViewEvent* event); | |||||
void showNotification(const Fellow* fellow, const QString& text); | |||||
long showNotification(const Fellow* fellow, const QString& text); | |||||
shared_ptr<Fellow> checkCurFellow(); | shared_ptr<Fellow> checkCurFellow(); | ||||
void showResult(pair<bool, string> ret, const Content *content); | void showResult(pair<bool, string> ret, const Content *content); | ||||
vector<const Fellow*> fellowSearchDriver(const QString& text); | vector<const Fellow*> fellowSearchDriver(const QString& text); | ||||
void initFeiq(); | void initFeiq(); | ||||
void updateUnread(const Fellow* fellow); | |||||
int getUnreadCount(); | |||||
void flushUnread(const Fellow* fellow); | |||||
void readEvent(const ViewEvent* event); | void readEvent(const ViewEvent* event); | ||||
void setBadgeNumber(int number); | void setBadgeNumber(int number); | ||||
QString simpleTextOf(const Content* content); | QString simpleTextOf(const Content* content); | ||||
UnshownMessage& addUnshownMessage(const Fellow *fellow, shared_ptr<ViewEvent> event); | |||||
UnshownMessage *findUnshownMessage(int id); | |||||
void notifyUnshown(UnshownMessage &umsg); | |||||
void updateUnshownHint(const Fellow* fellow); | |||||
int getUnreadCount(); | |||||
void flushUnshown(const Fellow* fellow); | |||||
// IFileTaskObserver interface | // IFileTaskObserver interface | ||||
public: | public: | ||||
void onStateChanged(FileTask *fileTask); | void onStateChanged(FileTask *fileTask); | ||||
@@ -95,7 +115,7 @@ private: | |||||
RecvTextEdit* mRecvTextEdit; | RecvTextEdit* mRecvTextEdit; | ||||
SendTextEdit* mSendTextEdit; | SendTextEdit* mSendTextEdit; | ||||
QString mTitle; | QString mTitle; | ||||
unordered_map<const Fellow*, list<shared_ptr<ViewEvent>>> mUnreadEvents; | |||||
unordered_map<const Fellow*, list<UnshownMessage>> mUnshownEvents; | |||||
FeiqWin* mFeiqWin = nullptr; | FeiqWin* mFeiqWin = nullptr; | ||||
}; | }; | ||||
@@ -2,13 +2,18 @@ | |||||
#define OSXNOTIFICATION_H | #define OSXNOTIFICATION_H | ||||
#include <QString> | #include <QString> | ||||
#include <QObject> | |||||
class MainWindow; | |||||
class Notification | class Notification | ||||
{ | { | ||||
public: | public: | ||||
explicit Notification(); | explicit Notification(); | ||||
void show(const QString& title, const QString& content); | |||||
int show(const QString& title, const QString& content, const QString &fellowIp); | |||||
void hideAll(); | void hideAll(); | ||||
public: | |||||
void setMainWnd(MainWindow* mainWnd); | |||||
}; | }; | ||||
#endif // OSXNOTIFICATION_H | #endif // OSXNOTIFICATION_H |
@@ -1,22 +1,46 @@ | |||||
#include "notification.h" | #include "notification.h" | ||||
#include "notificationimpl.h" | |||||
#include <QDebug> | |||||
#include "../mainwindow.h" | |||||
#import <cocoa/Cocoa.h> | |||||
static NotificationImpl* impl = [[NotificationImpl alloc] init]; | |||||
static void clickCallback(void* arg, NSString* fellowIp) | |||||
{ | |||||
MainWindow* mainWnd = (MainWindow*)arg; | |||||
const char* ip = [fellowIp UTF8String]; | |||||
mainWnd->onNotifyClicked(ip); | |||||
} | |||||
static void replyCallback(void* arg, long notifyId, NSString* fellowIp, NSString* str) | |||||
{ | |||||
const char* reply = [str UTF8String]; | |||||
const char* ip = [fellowIp UTF8String]; | |||||
MainWindow* mainWnd = (MainWindow*)arg; | |||||
mainWnd->onNotifyReplied(notifyId, ip, reply); | |||||
} | |||||
Notification::Notification() | Notification::Notification() | ||||
{ | { | ||||
} | } | ||||
void Notification::show(const QString &title, const QString &content) | |||||
int Notification::show(const QString &title, const QString &content, const QString& fellowIp) | |||||
{ | { | ||||
NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease]; | |||||
userNotification.title = title.toNSString(); | |||||
userNotification.informativeText = content.toNSString(); | |||||
NSUserNotificationCenter* center = [NSUserNotificationCenter defaultUserNotificationCenter]; | |||||
[center deliverNotification:userNotification]; | |||||
NSString* objcTitle = title.toNSString(); | |||||
NSString* objcMessage = content.toNSString(); | |||||
return [impl show: objcTitle message: objcMessage extra: fellowIp.toNSString()]; | |||||
} | } | ||||
void Notification::hideAll() | void Notification::hideAll() | ||||
{ | { | ||||
[[NSUserNotificationCenter defaultUserNotificationCenter] removeAllDeliveredNotifications]; | |||||
[impl hideAll]; | |||||
} | |||||
void Notification::setMainWnd(MainWindow *mainWnd) | |||||
{ | |||||
impl->clickCallback = clickCallback; | |||||
impl->replyCallback = replyCallback; | |||||
impl->callbackArg = mainWnd; | |||||
} | } |
@@ -0,0 +1,32 @@ | |||||
#ifndef NOTIFICATIONIMPL_H | |||||
#define NOTIFICATIONIMPL_H | |||||
#ifdef __cplusplus | |||||
extern "C"{ | |||||
#endif | |||||
#import <Foundation/Foundation.h> | |||||
typedef void(*ClickCallback)(void*, NSString*); | |||||
typedef void(*ReplyCallback)(void*, long, NSString*, NSString*); | |||||
@interface NotificationImpl : NSObject | |||||
{ | |||||
@public | |||||
ClickCallback clickCallback; | |||||
ReplyCallback replyCallback; | |||||
void* callbackArg; | |||||
@private | |||||
int id; | |||||
} | |||||
-(instancetype)init; | |||||
-(long)show: (NSString*)title message:(NSString*)msg extra:(NSString*)who; | |||||
-(void)hideAll; | |||||
@end | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif // NOTIFICATIONIMPL_H |
@@ -0,0 +1,61 @@ | |||||
#include "notificationimpl.h" | |||||
#include <QDebug> | |||||
@interface NotificationImpl () <NSUserNotificationCenterDelegate> | |||||
@end | |||||
@implementation NotificationImpl | |||||
-(instancetype)init | |||||
{ | |||||
self = [super init]; | |||||
if(self) | |||||
{ | |||||
id=0; | |||||
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self]; | |||||
} | |||||
return self; | |||||
} | |||||
-(long)show:(NSString*)title message:(NSString*)msg extra:(NSString*)who | |||||
{ | |||||
NSUserNotification* notification = [[NSUserNotification alloc] init]; | |||||
notification.title = title; | |||||
if (who != nil && who.length > 0) | |||||
{ | |||||
notification.userInfo=@{@"extra":who}; | |||||
notification.hasReplyButton = true; | |||||
} | |||||
int myid = ++id; | |||||
notification.identifier = [NSString stringWithFormat:@"%d",myid]; | |||||
notification.informativeText = msg; | |||||
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification: notification]; | |||||
return (long)myid; | |||||
} | |||||
-(void)hideAll | |||||
{ | |||||
[[NSUserNotificationCenter defaultUserNotificationCenter] removeAllDeliveredNotifications]; | |||||
} | |||||
-(BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresent:(NSUserNotification *)notification | |||||
{ | |||||
return YES; | |||||
} | |||||
-(void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification | |||||
{ | |||||
NSString* who = [notification.userInfo objectForKey:@"extra"]; | |||||
int myid = notification.identifier.intValue; | |||||
if (notification.activationType == NSUserNotificationActivationTypeContentsClicked){ | |||||
clickCallback(callbackArg, who); | |||||
} | |||||
else if (notification.activationType == NSUserNotificationActivationTypeReplied){ | |||||
replyCallback(callbackArg, myid, who, notification.response.string); | |||||
} | |||||
} | |||||
@end |
@@ -6,9 +6,9 @@ OsxPlatform::OsxPlatform() | |||||
} | } | ||||
void OsxPlatform::showNotify(const QString &title, const QString &content) | |||||
long OsxPlatform::showNotify(const QString &title, const QString &content, const QString & fellowIp) | |||||
{ | { | ||||
mNotify.show(title, content); | |||||
return mNotify.show(title, content, fellowIp); | |||||
} | } | ||||
void OsxPlatform::hideAllNotify() | void OsxPlatform::hideAllNotify() | ||||
@@ -23,3 +23,9 @@ void OsxPlatform::setBadgeNumber(int number) | |||||
else | else | ||||
QtMac::setBadgeLabelText(QString::number(number)); | QtMac::setBadgeLabelText(QString::number(number)); | ||||
} | } | ||||
void OsxPlatform::setMainWnd(MainWindow *mainWnd) | |||||
{ | |||||
IPlatform::setMainWnd(mainWnd); | |||||
mNotify.setMainWnd(mainWnd); | |||||
} |
@@ -10,11 +10,12 @@ public: | |||||
OsxPlatform(); | OsxPlatform(); | ||||
public: | public: | ||||
void showNotify(const QString& title, const QString& content) override; | |||||
long showNotify(const QString& title, const QString& content, const QString &fellowIp) override; | |||||
void hideAllNotify() override; | void hideAllNotify() override; | ||||
void setBadgeNumber(int number) override; | void setBadgeNumber(int number) override; | ||||
void setMainWnd(MainWindow *mainWnd) override; | |||||
private: | private: | ||||
Notification mNotify; | Notification mNotify; | ||||
}; | }; | ||||
@@ -7,10 +7,12 @@ | |||||
class MockPlatform : public IPlatform | class MockPlatform : public IPlatform | ||||
{ | { | ||||
public: | public: | ||||
void showNotify(const QString& title, const QString& content) | |||||
long showNotify(const QString& title, const QString& content, const QString& data) | |||||
{ | { | ||||
(void)title; | (void)title; | ||||
(void)content; | (void)content; | ||||
(void)data; | |||||
return 0; | |||||
} | } | ||||
void hideAllNotify() | void hideAllNotify() | ||||
{ | { | ||||
@@ -43,9 +45,9 @@ PlatformDepend &PlatformDepend::instance() | |||||
return me; | return me; | ||||
} | } | ||||
void PlatformDepend::showNotify(const QString &title, const QString &content) | |||||
long PlatformDepend::showNotify(const QString &title, const QString &content, const QString &fellowIp) | |||||
{ | { | ||||
mImpl->showNotify(title, content); | |||||
return mImpl->showNotify(title, content, fellowIp); | |||||
} | } | ||||
void PlatformDepend::hideAllNotify() | void PlatformDepend::hideAllNotify() | ||||
@@ -57,3 +59,9 @@ void PlatformDepend::setBadgeNumber(int number) | |||||
{ | { | ||||
mImpl->setBadgeNumber(number); | mImpl->setBadgeNumber(number); | ||||
} | } | ||||
void PlatformDepend::setMainWnd(MainWindow *mainWnd) | |||||
{ | |||||
IPlatform::setMainWnd(mainWnd); | |||||
mImpl->setMainWnd(mainWnd); | |||||
} |
@@ -2,15 +2,22 @@ | |||||
#define PLATFORMDEPEND_H | #define PLATFORMDEPEND_H | ||||
#include <QString> | #include <QString> | ||||
class MainWindow; | |||||
class IPlatform | class IPlatform | ||||
{ | { | ||||
public: | public: | ||||
virtual ~IPlatform(){} | virtual ~IPlatform(){} | ||||
virtual void showNotify(const QString& title, const QString& content) = 0; | |||||
virtual long showNotify(const QString& title, const QString& content, const QString & fellowIp) = 0; | |||||
virtual void hideAllNotify() = 0; | virtual void hideAllNotify() = 0; | ||||
virtual void setBadgeNumber(int number) = 0; | virtual void setBadgeNumber(int number) = 0; | ||||
virtual void setMainWnd(MainWindow* mainWnd) | |||||
{ | |||||
Q_UNUSED(mainWnd); | |||||
} | |||||
}; | }; | ||||
class PlatformDepend : public IPlatform | class PlatformDepend : public IPlatform | ||||
@@ -23,11 +30,12 @@ public: | |||||
static PlatformDepend& instance(); | static PlatformDepend& instance(); | ||||
public: | public: | ||||
void showNotify(const QString& title, const QString& content) override; | |||||
long showNotify(const QString& title, const QString& content, const QString & fellowIp) override; | |||||
void hideAllNotify() override; | void hideAllNotify() override; | ||||
void setBadgeNumber(int number) override; | void setBadgeNumber(int number) override; | ||||
void setMainWnd(MainWindow* mainWnd) override; | |||||
private: | private: | ||||
IPlatform* mImpl; | IPlatform* mImpl; | ||||
}; | }; | ||||
@@ -1,39 +0,0 @@ | |||||
#include "unreadchecker.h" | |||||
#include <QTimerEvent> | |||||
#include "platformdepend.h" | |||||
#define PLUGIN_NAME "unread_checker" | |||||
REGISTER_PLUGIN(PLUGIN_NAME, UnreadChecker) | |||||
UnreadChecker::UnreadChecker() | |||||
{ | |||||
} | |||||
void UnreadChecker::timerEvent(QTimerEvent *event) | |||||
{ | |||||
if (event->timerId() == mUnreadTimerId) | |||||
{ | |||||
auto count = mFeiq->getUnreadCount(); | |||||
if (count > 0) | |||||
{ | |||||
PlatformDepend::instance().hideAllNotify(); | |||||
PlatformDepend::instance().showNotify("未读提醒", QString("还有%1条未读消息").arg(count)); | |||||
} | |||||
} | |||||
} | |||||
void UnreadChecker::init() | |||||
{ | |||||
IPlugin::init(); | |||||
auto settings = mFeiq->settings(); | |||||
mUnreadTimerInterval = settings->value(PLUGIN_NAME"/timer", "600").toInt(); | |||||
if (mUnreadTimerInterval > 0) | |||||
mUnreadTimerId = startTimer(mUnreadTimerInterval*1000, Qt::VeryCoarseTimer); | |||||
} | |||||
void UnreadChecker::unInit() | |||||
{ | |||||
if (mUnreadTimerId > 0) | |||||
killTimer(mUnreadTimerId); | |||||
} |
@@ -1,25 +0,0 @@ | |||||
#ifndef UNREADCHECKER_H | |||||
#define UNREADCHECKER_H | |||||
#include "iplugin.h" | |||||
#include <QObject> | |||||
class UnreadChecker : public QObject, public IPlugin | |||||
{ | |||||
Q_OBJECT | |||||
public: | |||||
UnreadChecker(); | |||||
void init() override; | |||||
void unInit() override; | |||||
protected: | |||||
void timerEvent(QTimerEvent *event) override; | |||||
private: | |||||
int mUnreadTimerInterval; | |||||
int mUnreadTimerId=-1; | |||||
int mLastCheckCount=0; | |||||
}; | |||||
#endif // UNREADCHECKER_H |