mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
Unread chat message event.
Shortcut to go at the end of chat. Avoid MarkAsRead when not at end of chat. Fix composers.
This commit is contained in:
parent
922d155146
commit
821d1e17da
28 changed files with 397 additions and 42 deletions
84
linphone-app/assets/images/move_to_bottom_custom.svg
Normal file
84
linphone-app/assets/images/move_to_bottom_custom.svg
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="80"
|
||||
height="80"
|
||||
viewBox="0 0 80 80"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="bottom_move_custom.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata
|
||||
id="metadata15">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>drop_down_list</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
id="namedview13"
|
||||
showgrid="false"
|
||||
inkscape:zoom="5.9599"
|
||||
inkscape:cx="4.2785953"
|
||||
inkscape:cy="30.201849"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg11"
|
||||
inkscape:pagecheckerboard="0" />
|
||||
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
|
||||
<title
|
||||
id="title2">drop_down_list</title>
|
||||
<desc
|
||||
id="desc4">Created with Sketch.</desc>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<g
|
||||
id="Symbols"
|
||||
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round"
|
||||
transform="matrix(3.3369868,0,0,2.857815,20,21)">
|
||||
<g
|
||||
id="drop_down_list"
|
||||
style="stroke:#000000;stroke-width:2">
|
||||
<path
|
||||
d="m 3.5,8.5 5,-5 M 3.5041964,-1.5 8.5,3.5"
|
||||
id="status_username_disconnected"
|
||||
transform="rotate(90,6,3.5)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="Symbols-3"
|
||||
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round"
|
||||
transform="matrix(3.3369868,0,0,2.857815,20,30)">
|
||||
<g
|
||||
id="drop_down_list-6"
|
||||
style="stroke:#000000;stroke-width:2">
|
||||
<path
|
||||
d="m 1,3.0995062 5,5 M 11,3.1037026 6,8.0995062"
|
||||
id="status_username_disconnected-7"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
|
@ -1563,6 +1563,14 @@ Klik her: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,14 @@ Klicken Sie hier: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation>Kurzlebige Nachrichten wurden aktualisiert: %1</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,14 @@ Click here: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation>Ephemeral messages have been updated: %1</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation>
|
||||
<numerusform>%1 unread message</numerusform>
|
||||
<numerusform>%1 unread messages</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,14 @@ Haga clic aquí: <a href="%1">%1 </a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,14 @@ Cliquez ici : <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation>Délai d’expiration des messages : %1</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1553,6 +1553,13 @@ Kattintson ide: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation>Mulandó üzenetek frissítve: %1</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,14 @@ Clicca: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1553,6 +1553,13 @@
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1573,6 +1573,15 @@ Spustelėkite čia: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,14 @@ Clique aqui: <a href="%1">%1 </a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation>Mensagens efêmeras foram atualizadas: %1</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1573,6 +1573,15 @@
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1563,6 +1563,14 @@ Klicka här: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1553,6 +1553,13 @@ Buraya tıklayın: <a href="%1">%1</a>
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1573,6 +1573,15 @@
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -1553,6 +1553,13 @@
|
|||
<extracomment>'Ephemeral messages have been updated: %1' : Little message to show on the event when ephemeral has been updated. %1 is a date time</extracomment>
|
||||
<translation>临时消息已被更新: %1</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>unreadMessageNotice</source>
|
||||
<extracomment>'%1 unread messages' : Little message to show on an event where unread messages begin.</extracomment>
|
||||
<translation type="unfinished">
|
||||
<numerusform></numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Notifier</name>
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@
|
|||
<file>assets/images/micro_on_custom.svg</file>
|
||||
<file>assets/images/missed_incoming_call_custom.svg</file>
|
||||
<file>assets/images/missed_outgoing_call_custom.svg</file>
|
||||
<file>assets/images/move_to_bottom_custom.svg</file>
|
||||
<file>assets/images/new_call_custom.svg</file>
|
||||
<file>assets/images/new_chat_group_custom.svg</file>
|
||||
<file>assets/images/new_conference_custom.svg</file>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,14 @@ ChatNoticeModel::ChatNoticeModel ( std::shared_ptr<linphone::EventLog> eventLog,
|
|||
mTimestamp = QDateTime::fromMSecsSinceEpoch(eventLog->getCreationTime() * 1000);
|
||||
}
|
||||
|
||||
ChatNoticeModel::ChatNoticeModel ( NoticeType noticeType, const QDateTime& timestamp, const QString& txt, QObject * parent) : ChatEvent(ChatRoomModel::EntryType::NoticeEntry, parent) {
|
||||
App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE
|
||||
mEventLogType = LinphoneEnums::EventLogType::EventLogTypeNone;
|
||||
setStatus(noticeType);
|
||||
setName(txt);
|
||||
mTimestamp = timestamp;
|
||||
}
|
||||
|
||||
ChatNoticeModel::~ChatNoticeModel(){
|
||||
}
|
||||
|
||||
|
|
@ -46,6 +54,15 @@ std::shared_ptr<ChatNoticeModel> ChatNoticeModel::create(std::shared_ptr<linphon
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ChatNoticeModel> ChatNoticeModel::create(NoticeType noticeType, const QDateTime& timestamp, const QString& txt, QObject * parent){
|
||||
auto model = std::make_shared<ChatNoticeModel>(noticeType, timestamp, txt, parent);
|
||||
if(model ){
|
||||
model->mSelf = model;
|
||||
return model;
|
||||
}else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::EventLog> ChatNoticeModel::getEventLog(){
|
||||
return mEventLog;
|
||||
}
|
||||
|
|
@ -53,6 +70,8 @@ std::shared_ptr<linphone::EventLog> ChatNoticeModel::getEventLog(){
|
|||
//---------------------------------------------------------------------------------------------
|
||||
bool ChatNoticeModel::update(){
|
||||
bool handledEvent = true;
|
||||
if(!mEventLog)
|
||||
return false;
|
||||
auto participantAddress = mEventLog->getParticipantAddress();
|
||||
|
||||
switch(mEventLog->getType()){
|
||||
|
|
@ -158,5 +177,6 @@ void ChatNoticeModel::setEventLogType(const LinphoneEnums::EventLogType& data){
|
|||
}
|
||||
|
||||
void ChatNoticeModel::deleteEvent(){
|
||||
mEventLog->deleteFromDatabase();
|
||||
if(mEventLog)
|
||||
mEventLog->deleteFromDatabase();
|
||||
}
|
||||
|
|
@ -32,16 +32,19 @@ class ChatNoticeModel : public ChatEvent {
|
|||
|
||||
public:
|
||||
enum NoticeType {
|
||||
NoticeMessage,
|
||||
NoticeError
|
||||
NoticeMessage, // This is a Linphone message
|
||||
NoticeError, // This is a Linphone error
|
||||
NoticeUnreadMessages
|
||||
};
|
||||
Q_ENUM(NoticeType);
|
||||
|
||||
static std::shared_ptr<ChatNoticeModel> create(std::shared_ptr<linphone::EventLog> eventLog, QObject * parent = nullptr);// Call it instead constructor
|
||||
static std::shared_ptr<ChatNoticeModel> create(NoticeType noticeType, const QDateTime& timestamp,const QString& txt, QObject * parent = nullptr);
|
||||
ChatNoticeModel (std::shared_ptr<linphone::EventLog> eventLog, QObject * parent = nullptr);
|
||||
ChatNoticeModel (NoticeType noticeType, const QDateTime& timestamp, const QString& txt, QObject * parent = nullptr);
|
||||
virtual ~ChatNoticeModel();
|
||||
|
||||
Q_PROPERTY(ChatRoomModel::EntryType type MEMBER mType CONSTANT)
|
||||
Q_PROPERTY(ChatRoomModel::EntryType type MEMBER mType CONSTANT)// NoticeEntry
|
||||
Q_PROPERTY(QDateTime timestamp MEMBER mTimestamp CONSTANT)
|
||||
Q_PROPERTY(QString name MEMBER mName WRITE setName NOTIFY nameChanged)
|
||||
Q_PROPERTY(NoticeType status MEMBER mStatus WRITE setStatus NOTIFY statusChanged)
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ ChatRoomModel::ChatRoomModel (std::shared_ptr<linphone::ChatRoom> chatRoom, QObj
|
|||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
CoreHandlers *coreHandlers = mCoreHandlers.get();
|
||||
QObject::connect(this, &ChatRoomModel::messageSent, this, &ChatRoomModel::resetMessageCount);
|
||||
//QObject::connect(coreHandlers, &CoreHandlers::messageReceived, this, &ChatRoomModel::handleMessageReceived);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::callCreated, this, &ChatRoomModel::handleCallCreated);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &ChatRoomModel::handleCallStateChanged);
|
||||
|
|
@ -482,6 +483,10 @@ bool ChatRoomModel::haveEncryption() const{
|
|||
return mChatRoom && mChatRoom->getCurrentParams()->getEncryptionBackend() != linphone::ChatRoomEncryptionBackend::None;
|
||||
}
|
||||
|
||||
bool ChatRoomModel::markAsReadEnabled() const{
|
||||
return mMarkAsReadEnabled;
|
||||
}
|
||||
|
||||
bool ChatRoomModel::isSecure() const{
|
||||
return mChatRoom && (mChatRoom->getSecurityLevel() == linphone::ChatRoomSecurityLevel::Encrypted
|
||||
|| mChatRoom->getSecurityLevel() == linphone::ChatRoomSecurityLevel::Safe);
|
||||
|
|
@ -514,11 +519,11 @@ bool ChatRoomModel::isCurrentProxy() const{
|
|||
bool ChatRoomModel::canHandleParticipants() const{
|
||||
return mChatRoom->canHandleParticipants();
|
||||
}
|
||||
/*
|
||||
|
||||
bool ChatRoomModel::getIsRemoteComposing () const {
|
||||
return mIsRemoteComposing;
|
||||
return mComposers.size() > 0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
std::shared_ptr<linphone::ChatRoom> ChatRoomModel::getChatRoom(){
|
||||
return mChatRoom;
|
||||
|
|
@ -603,6 +608,13 @@ void ChatRoomModel::setEphemeralLifetime(long lifetime){
|
|||
}
|
||||
}
|
||||
|
||||
void ChatRoomModel::enableMarkAsRead(const bool& enable){
|
||||
if( mMarkAsReadEnabled != enable){
|
||||
mMarkAsReadEnabled = enable;
|
||||
emit markAsReadEnabledChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ChatRoomModel::setReply(ChatMessageModel * model){
|
||||
if(model != mReplyModel.get()){
|
||||
if( model && model->getChatMessage() )
|
||||
|
|
@ -738,10 +750,16 @@ void ChatRoomModel::compose () {
|
|||
}
|
||||
|
||||
void ChatRoomModel::resetMessageCount () {
|
||||
if(mChatRoom && !mDeleteChatRoom){
|
||||
if(mChatRoom && !mDeleteChatRoom && markAsReadEnabled()){
|
||||
if (mChatRoom->getUnreadMessagesCount() > 0){
|
||||
mChatRoom->markAsRead();// Marking as read is only for messages. Not for calls.
|
||||
}
|
||||
if(!mUnreadMessageNotice.first)
|
||||
mUnreadMessageNotice.first = true;
|
||||
else if( mUnreadMessageNotice.second){
|
||||
removeEntry(mUnreadMessageNotice.second.get());
|
||||
mUnreadMessageNotice.second = nullptr;
|
||||
}
|
||||
setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount());
|
||||
setMissedCallsCount(0);
|
||||
emit messageCountReset();
|
||||
|
|
@ -831,9 +849,14 @@ void ChatRoomModel::initEntries(){
|
|||
// On call : reinitialize all entries. This allow to free up memory
|
||||
QList<std::shared_ptr<ChatEvent> > entries;
|
||||
QList<EntrySorterHelper> prepareEntries;
|
||||
QDateTime lastUnreadMessage = QDateTime::currentDateTime();
|
||||
// Get chat messages
|
||||
for (auto &message : mChatRoom->getHistory(mLastEntriesStep))
|
||||
for (auto &message : mChatRoom->getHistory(mLastEntriesStep)) {
|
||||
prepareEntries << EntrySorterHelper(message->getTime() ,MessageEntry, message);
|
||||
if( !message->isRead()) {
|
||||
lastUnreadMessage = min(lastUnreadMessage, QDateTime::fromMSecsSinceEpoch(message->getTime() * 1000));
|
||||
}
|
||||
}
|
||||
// Get events
|
||||
for(auto &eventLog : mChatRoom->getHistoryEvents(mLastEntriesStep))
|
||||
prepareEntries << EntrySorterHelper(eventLog->getCreationTime() , NoticeEntry, eventLog);
|
||||
|
|
@ -852,6 +875,12 @@ void ChatRoomModel::initEntries(){
|
|||
}
|
||||
EntrySorterHelper::getLimitedSelection(&entries, prepareEntries, mLastEntriesStep, this);
|
||||
|
||||
if( mChatRoom->getUnreadMessagesCount() > 0) {
|
||||
mUnreadMessageNotice.first = false;
|
||||
mUnreadMessageNotice.second = ChatNoticeModel::create(ChatNoticeModel::NoticeType::NoticeUnreadMessages, lastUnreadMessage, QString::number(mChatRoom->getUnreadMessagesCount()));
|
||||
entries.push_front(mUnreadMessageNotice.second);
|
||||
}
|
||||
|
||||
mIsInitialized = true;
|
||||
if(entries.size() >0){
|
||||
beginResetModel();
|
||||
|
|
@ -914,7 +943,7 @@ int ChatRoomModel::loadMoreEntries(){
|
|||
bool haveEntry = false;
|
||||
while(!haveEntry && itEntries != mEntries.end()){
|
||||
auto entry = dynamic_cast<ChatNoticeModel*>(itEntries->get());
|
||||
haveEntry = (entry && entry->getEventLog() == eventLog);
|
||||
haveEntry = (entry && entry->getEventLog() && entry->getEventLog() == eventLog);
|
||||
++itEntries;
|
||||
}
|
||||
if(!haveEntry)
|
||||
|
|
@ -1057,6 +1086,12 @@ void ChatRoomModel::insertNotices (const QList<std::shared_ptr<linphone::EventLo
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/*
|
||||
void ChatRoomModel::removeUnreadMessagesNotice() {
|
||||
|
||||
}*/
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ChatRoomModel::handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state) {
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ public:
|
|||
Q_PROPERTY(bool isMeAdmin READ isMeAdmin NOTIFY isMeAdminChanged)
|
||||
Q_PROPERTY(bool canHandleParticipants READ canHandleParticipants CONSTANT)
|
||||
|
||||
//Q_PROPERTY(bool isComposing MEMBER mIsRemoteComposing NOTIFY isRemoteComposingChanged)
|
||||
Q_PROPERTY(bool isComposing READ getIsRemoteComposing NOTIFY isRemoteComposingChanged)
|
||||
Q_PROPERTY(QList<QString> composers READ getComposers NOTIFY isRemoteComposingChanged)
|
||||
Q_PROPERTY(bool hasBeenLeft READ hasBeenLeft NOTIFY hasBeenLeftChanged)
|
||||
|
||||
|
|
@ -148,6 +148,7 @@ public:
|
|||
Q_PROPERTY(long ephemeralLifetime READ getEphemeralLifetime WRITE setEphemeralLifetime NOTIFY ephemeralLifetimeChanged)
|
||||
Q_PROPERTY(bool ephemeralEnabled READ isEphemeralEnabled WRITE setEphemeralEnabled NOTIFY ephemeralEnabledChanged)
|
||||
Q_PROPERTY(bool canBeEphemeral READ canBeEphemeral NOTIFY canBeEphemeralChanged)
|
||||
Q_PROPERTY(bool markAsReadEnabled READ markAsReadEnabled WRITE enableMarkAsRead NOTIFY markAsReadEnabledChanged)
|
||||
|
||||
Q_PROPERTY(ParticipantListModel* participants READ getParticipants CONSTANT)
|
||||
|
||||
|
|
@ -187,6 +188,7 @@ public:
|
|||
long getEphemeralLifetime() const;
|
||||
bool canBeEphemeral();
|
||||
bool haveEncryption() const;
|
||||
bool markAsReadEnabled() const;
|
||||
Q_INVOKABLE bool isSecure() const;
|
||||
int getSecurityLevel() const;
|
||||
bool isGroupEnabled() const;
|
||||
|
|
@ -211,6 +213,7 @@ public:
|
|||
void addMissedCallsCount(std::shared_ptr<linphone::Call> call);
|
||||
void setEphemeralEnabled(bool enabled);
|
||||
void setEphemeralLifetime(long lifetime);
|
||||
void enableMarkAsRead(const bool& enable);
|
||||
|
||||
void setReply(ChatMessageModel * model);
|
||||
ChatMessageModel * getReply()const;
|
||||
|
|
@ -237,6 +240,7 @@ public:
|
|||
|
||||
bool mDeleteChatRoom = false; // Use as workaround because of core->deleteChatRoom() that call destructor without takking account of count ref : call it in ChatRoomModel destructor
|
||||
int mLastEntriesStep = 50; // Retrieve a part of the history to avoid too much processing
|
||||
bool mMarkAsReadEnabled = true;
|
||||
|
||||
|
||||
void insertCall (const std::shared_ptr<linphone::CallLog> &callLog);
|
||||
|
|
@ -312,6 +316,7 @@ signals:
|
|||
void ephemeralEnabledChanged();
|
||||
void ephemeralLifetimeChanged();
|
||||
void canBeEphemeralChanged();
|
||||
void markAsReadEnabledChanged();
|
||||
void chatRoomDeleted();// Must be connected with DirectConnection mode
|
||||
void replyChanged();
|
||||
|
||||
|
|
@ -337,7 +342,7 @@ private:
|
|||
//void handleMessageReceived (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||
|
||||
//bool mIsRemoteComposing = false;
|
||||
|
||||
QPair<bool, std::shared_ptr<ChatEvent> > mUnreadMessageNotice;
|
||||
QList<std::shared_ptr<ChatEvent> > mEntries;
|
||||
std::shared_ptr<ParticipantListModel> mParticipantListModel;
|
||||
std::shared_ptr<CoreHandlers> mCoreHandlers;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ private:
|
|||
|
||||
ChatRoomProxyModel::ChatRoomProxyModel (QObject *parent) : QSortFilterProxyModel(parent) {
|
||||
setSourceModel(new ChatRoomModelFilter(this));
|
||||
mMarkAsReadEnabled = true;
|
||||
//mIsSecure = false;
|
||||
|
||||
App *app = App::getInstance();
|
||||
|
|
@ -240,6 +241,14 @@ void ChatRoomProxyModel::setFullLocalAddress (const QString &localAddress) {
|
|||
//reload();
|
||||
}
|
||||
|
||||
bool ChatRoomProxyModel::markAsReadEnabled() const{
|
||||
return mChatRoomModel->markAsReadEnabled();
|
||||
}
|
||||
|
||||
void ChatRoomProxyModel::enableMarkAsRead(const bool& enable){
|
||||
mChatRoomModel->enableMarkAsRead(enable);
|
||||
}
|
||||
|
||||
QList<QString> ChatRoomProxyModel::getComposers() const{
|
||||
return (mChatRoomModel?mChatRoomModel->getComposers():QList<QString>());
|
||||
}
|
||||
|
|
@ -266,6 +275,7 @@ void ChatRoomProxyModel::reload (ChatRoomModel *chatRoomModel) {
|
|||
QObject::disconnect(ChatRoomModel, &ChatRoomModel::isRemoteComposingChanged, this, &ChatRoomProxyModel::handleIsRemoteComposingChanged);
|
||||
QObject::disconnect(ChatRoomModel, &ChatRoomModel::messageReceived, this, &ChatRoomProxyModel::handleMessageReceived);
|
||||
QObject::disconnect(ChatRoomModel, &ChatRoomModel::messageSent, this, &ChatRoomProxyModel::handleMessageSent);
|
||||
QObject::disconnect(ChatRoomModel, &ChatRoomModel::markAsReadEnabledChanged, this, &ChatRoomProxyModel::markAsReadEnabledChanged);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -276,7 +286,8 @@ void ChatRoomProxyModel::reload (ChatRoomModel *chatRoomModel) {
|
|||
ChatRoomModel *ChatRoomModel = mChatRoomModel.get();
|
||||
QObject::connect(ChatRoomModel, &ChatRoomModel::isRemoteComposingChanged, this, &ChatRoomProxyModel::handleIsRemoteComposingChanged);
|
||||
QObject::connect(ChatRoomModel, &ChatRoomModel::messageReceived, this, &ChatRoomProxyModel::handleMessageReceived);
|
||||
QObject::connect(ChatRoomModel, &ChatRoomModel::messageSent, this, &ChatRoomProxyModel::handleMessageSent);
|
||||
QObject::connect(ChatRoomModel, &ChatRoomModel::messageSent, this, &ChatRoomProxyModel::handleMessageSent);
|
||||
QObject::connect(ChatRoomModel, &ChatRoomModel::markAsReadEnabledChanged, this, &ChatRoomProxyModel::markAsReadEnabledChanged);
|
||||
}
|
||||
|
||||
static_cast<ChatRoomModelFilter *>(sourceModel())->setSourceModel(mChatRoomModel.get());
|
||||
|
|
@ -324,7 +335,7 @@ static inline QWindow *getParentWindow (QObject *object) {
|
|||
}
|
||||
|
||||
void ChatRoomProxyModel::handleIsActiveChanged (QWindow *window) {
|
||||
if (mChatRoomModel && window->isActive() && getParentWindow(this) == window) {
|
||||
if (markAsReadEnabled() && mChatRoomModel && window->isActive() && getParentWindow(this) == window) {
|
||||
auto timeline = CoreManager::getInstance()->getTimelineListModel()->getTimeline(mChatRoomModel->getChatRoom(), false);
|
||||
if(timeline && timeline->mSelected){
|
||||
mChatRoomModel->resetMessageCount();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class ChatRoomProxyModel : public QSortFilterProxyModel {
|
|||
Q_PROPERTY(QString cachedText READ getCachedText)
|
||||
|
||||
Q_PROPERTY(QString filterText MEMBER mFilterText WRITE setFilterText NOTIFY filterTextChanged)
|
||||
Q_PROPERTY(bool markAsReadEnabled READ markAsReadEnabled WRITE enableMarkAsRead NOTIFY markAsReadEnabledChanged)// Focus is at end of the list. Used to reset message count if not at end
|
||||
|
||||
public:
|
||||
ChatRoomProxyModel (QObject *parent = Q_NULLPTR);
|
||||
|
|
@ -78,6 +79,7 @@ signals:
|
|||
void fullPeerAddressChanged (const QString &fullPeerAddress);
|
||||
void fullLocalAddressChanged (const QString &fullLocalAddress);
|
||||
bool isRemoteComposingChanged ();
|
||||
void markAsReadEnabledChanged();
|
||||
//bool isSecureChanged(bool secure);
|
||||
|
||||
void chatRoomModelChanged();
|
||||
|
|
@ -104,6 +106,9 @@ private:
|
|||
QString getFullLocalAddress () const;
|
||||
void setFullLocalAddress (const QString &localAddress);
|
||||
|
||||
bool markAsReadEnabled() const;
|
||||
void enableMarkAsRead(const bool& enable);
|
||||
|
||||
//bool isSecure () const;
|
||||
//void setIsSecure (const int &secure);
|
||||
|
||||
|
|
@ -129,6 +134,7 @@ private:
|
|||
QString mFullPeerAddress;
|
||||
QString mFullLocalAddress;
|
||||
static QString gCachedText;
|
||||
bool mMarkAsReadEnabled;
|
||||
|
||||
QString mFilterText;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,28 +6,51 @@ import Common 1.0
|
|||
// =============================================================================
|
||||
|
||||
ListView {
|
||||
id: view
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
ScrollBar.vertical: ForceScrollBar {
|
||||
id: vScrollBar
|
||||
|
||||
onPressedChanged: pressed ? view.movementStarted() : view.movementEnded()
|
||||
// ScrollBar.AsNeeded doesn't work. Do it ourself.
|
||||
policy: (view.contentHeight > view.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff)
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip: true
|
||||
contentWidth: width - (vScrollBar.visible?vScrollBar.width:0)
|
||||
spacing: 0
|
||||
synchronousDrag: true
|
||||
cacheBuffer: height
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// TODO: Find a solution at this bug =>
|
||||
// https://bugreports.qt.io/browse/QTBUG-31573
|
||||
// https://bugreports.qt.io/browse/QTBUG-49989
|
||||
id: view
|
||||
|
||||
function getVisibleIndex(checkMax) {
|
||||
var center_x = view.x + view.width / 2
|
||||
var index = -1
|
||||
var yCheck = 0
|
||||
var direction = checkMax ? -1 : 1
|
||||
var yStart = view.y + view.contentY + (checkMax ? view.height : 0)
|
||||
var yStep = 5
|
||||
while(index<0 && yCheck < view.height){
|
||||
index = indexAt( center_x, yStart + yCheck * direction)
|
||||
yCheck += yStep
|
||||
}
|
||||
return index
|
||||
}
|
||||
function getVisibleIndexRange() {
|
||||
return [getVisibleIndex(0), getVisibleIndex(1)]
|
||||
}
|
||||
function isIndexVisible(index){
|
||||
return getVisibleIndex(0) <= index && index <= getVisibleIndex(1)
|
||||
}
|
||||
function isIndexAfter(index){
|
||||
return getVisibleIndex(1) < index
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
ScrollBar.vertical: ForceScrollBar {
|
||||
id: vScrollBar
|
||||
|
||||
onPressedChanged: pressed ? view.movementStarted() : view.movementEnded()
|
||||
// ScrollBar.AsNeeded doesn't work. Do it ourself.
|
||||
policy: (view.contentHeight > view.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff)
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
clip: true
|
||||
contentWidth: width - (vScrollBar.visible?vScrollBar.width:0)
|
||||
spacing: 0
|
||||
synchronousDrag: true
|
||||
cacheBuffer: height
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// TODO: Find a solution at this bug =>
|
||||
// https://bugreports.qt.io/browse/QTBUG-31573
|
||||
// https://bugreports.qt.io/browse/QTBUG-49989
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,13 +296,19 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
footer: Item{
|
||||
implicitHeight: composersItem.implicitHeight
|
||||
width: parent.width
|
||||
Text {
|
||||
property var composers : container.proxyModel.composers
|
||||
id: composersItem
|
||||
property var composers : container.proxyModel.chatRoomModel.composers
|
||||
onComposersChanged: console.log(composers)
|
||||
onVisibleChanged: console.log(visible)
|
||||
color: ChatStyle.composingText.color
|
||||
font.pointSize: ChatStyle.composingText.pointSize
|
||||
height: visible ? undefined : 0
|
||||
leftPadding: ChatStyle.composingText.leftPadding
|
||||
visible: composers.length > 0 && (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled)
|
||||
visible: composers.length > 0 && ( (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled)
|
||||
|| (proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled) )
|
||||
wrapMode: Text.Wrap
|
||||
//: '%1 is typing...' indicate that someone is composing in chat
|
||||
text:(composers.length==0?'': qsTr('chatTyping','',composers.length).arg(container.proxyModel.getDisplayNameComposers()))
|
||||
|
|
@ -315,7 +321,7 @@ Rectangle {
|
|||
}
|
||||
Rectangle{
|
||||
id: messageBlock
|
||||
height: 32
|
||||
height: opacity > 0 ? 32 : 0
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
|
@ -375,6 +381,31 @@ Rectangle {
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
ActionButton{
|
||||
anchors.bottom: messageBlock.top
|
||||
anchors.bottomMargin: 10
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 40
|
||||
visible: chat.isIndexAfter(chat.count-1)
|
||||
onVisibleChanged: container.proxyModel.markAsReadEnabled = !visible
|
||||
|
||||
isCustom: true
|
||||
backgroundRadius: width/2
|
||||
colorSet: ChatStyle.gotToBottom
|
||||
onClicked: {
|
||||
chat.bindToEnd = true
|
||||
}
|
||||
MessageCounter{
|
||||
anchors.left: parent.right
|
||||
anchors.bottom: parent.top
|
||||
anchors.bottomMargin: -5
|
||||
anchors.leftMargin: -5
|
||||
count: container.proxyModel.chatRoomModel.unreadMessagesCount
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ RowLayout{
|
|||
id: mainLayout
|
||||
property string _type: {
|
||||
var status = $chatEntry.eventLogType
|
||||
var type = $chatEntry.status
|
||||
|
||||
if(type == ChatNoticeModel.NoticeUnreadMessages)
|
||||
//: '%1 unread messages' : Little message to show on an event where unread messages begin.
|
||||
return qsTr('unreadMessageNotice', '', $chatEntry.name)
|
||||
|
||||
if (status == LinphoneEnums.EventLogTypeConferenceCreated) {
|
||||
//: 'You have joined the group' : Little message to show on the event when the user join the chat group.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@ QtObject {
|
|||
}
|
||||
}
|
||||
|
||||
property QtObject gotToBottom: QtObject{
|
||||
property string name: 'goToBottom'
|
||||
property string icon: 'move_to_bottom_custom'
|
||||
property int iconSize: 30
|
||||
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_n', icon, 's_n_b_bg').color
|
||||
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_h', icon, 's_h_b_bg').color
|
||||
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_p', icon, 's_p_b_bg').color
|
||||
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_n', icon, 's_n_b_fg').color
|
||||
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_h', icon, 's_h_b_fg').color
|
||||
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_p', icon, 's_p_b_fg').color
|
||||
}
|
||||
|
||||
property QtObject sendArea: QtObject {
|
||||
property int height: 80
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 3d422c64a3a10289fe6dda31ccb0af17b41cfffa
|
||||
Subproject commit 5800f6e489b250c5ffccaa90c8771a10a9edad59
|
||||
Loading…
Add table
Reference in a new issue