@ -167,6 +167,11 @@ MessageList::MessageList(DbManager* db, QWidget *parent)
void MessageList : : loadChannel ( const QString & channelId ) {
QWidget * prevFocus = QApplication : : focusWidget ( ) ;
/* Save state of current channel before switching */
if ( ! m_currentChannelId . isEmpty ( ) & & m_currentChannelId ! = channelId )
saveChannelState ( ) ;
m_model - > clear ( ) ;
m_avatarCache . clear ( ) ;
m_currentChannelId = channelId ;
@ -174,9 +179,6 @@ void MessageList::loadChannel(const QString& channelId) {
auto msgs = m_db - > getMessages ( channelId , 100 ) ;
struct ReactionKey { qint64 msgId ; quint64 node ; QString emoji ; } ;
QHash < qint64 , QHash < QString , QList < QColor > > > reactMap ;
for ( const auto & m : msgs ) {
AccountRow acc = m_db - > getAccount ( m . authorNodeId ) ;
QString author = m_db - > getDisplayName ( m . authorNodeId ) ;
@ -194,11 +196,12 @@ void MessageList::loadChannel(const QString& channelId) {
auto * item = new QStandardItem ( ) ;
setMsg ( item , author , QString : : fromUtf8 ( m . data ) , time , avatar , false ,
false , QString ( ) , QString ( ) , reacts ) ;
item - > setData ( m . id , MsgIdRole ) ;
m_model - > appendRow ( item ) ;
}
if ( m_model - > rowCount ( ) > 0 )
m_view - > scrollToBottom ( ) ;
restoreScrollPosition ( channelId ) ;
if ( prevFocus )
prevFocus - > setFocus ( ) ;
else
@ -238,3 +241,60 @@ void MessageList::addMessage(const QString& channelId, quint64 authorNodeId,
m_view - > scrollToBottom ( ) ;
}
void MessageList : : saveChannelState ( ) {
if ( m_currentChannelId . isEmpty ( ) | | m_model - > rowCount ( ) = = 0 ) return ;
int vpHeight = m_view - > viewport ( ) - > height ( ) ;
QModelIndex topIdx = m_view - > indexAt ( QPoint ( 0 , 0 ) ) ;
QModelIndex bottomIdx = m_view - > indexAt ( QPoint ( 0 , vpHeight - 1 ) ) ;
qint64 lastReadMsgId = 0 ;
qint64 lastPosMsgId = 0 ;
if ( topIdx . isValid ( ) )
lastPosMsgId = topIdx . data ( MsgIdRole ) . toLongLong ( ) ;
if ( bottomIdx . isValid ( ) )
lastReadMsgId = bottomIdx . data ( MsgIdRole ) . toLongLong ( ) ;
else if ( m_model - > rowCount ( ) > 0 )
lastReadMsgId = m_model - > item ( m_model - > rowCount ( ) - 1 ) - > data ( MsgIdRole ) . toLongLong ( ) ;
if ( lastReadMsgId = = 0 & & lastPosMsgId = = 0 ) return ;
QByteArray cid = m_currentChannelId . toUtf8 ( ) ;
auto saveKey = [ & cid ] ( const char * suffix , qint64 val ) {
QByteArray key = " ch_ " + cid + suffix ;
QByteArray valStr = QByteArray : : number ( val ) ;
size_t klen = key . size ( ) , vlen = valStr . size ( ) ;
size_t total = klen + 1 + vlen + 1 ;
if ( total > 256 ) return ;
void * arg = u_malloc ( total ) ;
memcpy ( arg , key . constData ( ) , klen + 1 ) ;
memcpy ( ( char * ) arg + klen + 1 , valStr . constData ( ) , vlen + 1 ) ;
gui_bridge_post_uasync_fn ( chat_core_save_ui_state_trampoline , arg ) ;
} ;
if ( lastReadMsgId > 0 ) saveKey ( " _last_read " , lastReadMsgId ) ;
if ( lastPosMsgId > 0 ) saveKey ( " _last_pos " , lastPosMsgId ) ;
}
void MessageList : : restoreScrollPosition ( const QString & channelId ) {
if ( ! m_db | | m_model - > rowCount ( ) = = 0 ) {
return ;
}
qint64 lastPosMsgId = m_db - > getUiStateInt64 (
QStringLiteral ( " ch_%1_last_pos " ) . arg ( channelId ) , 0 ) ;
if ( lastPosMsgId > 0 ) {
for ( int row = 0 ; row < m_model - > rowCount ( ) ; row + + ) {
QStandardItem * item = m_model - > item ( row ) ;
if ( item & & item - > data ( MsgIdRole ) . toLongLong ( ) = = lastPosMsgId ) {
m_view - > scrollTo ( m_model - > index ( row , 0 ) , QAbstractItemView : : PositionAtTop ) ;
return ;
}
}
}
m_view - > scrollToBottom ( ) ;
}