mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-08 17:15:16 -04:00
Improve QML app Contacts view performances
Simplified sorting getting rid of complicated DelegateModel Offload sorting work to another thread via WorkerScript Get rid of polling and use token system instead
This commit is contained in:
parent
7d9e89e3d2
commit
8e03fab8da
4 changed files with 166 additions and 154 deletions
|
@ -28,58 +28,83 @@ Item
|
|||
property string own_gxs_id: ""
|
||||
property string own_nick: ""
|
||||
property bool searching: false
|
||||
property var unreadMessages: ({})
|
||||
onSearchingChanged: !searching && contactsSortWorker.sendMessage({})
|
||||
|
||||
Component.onCompleted: refreshOwn()
|
||||
Component.onCompleted: refreshAll()
|
||||
onFocusChanged: focus && refreshAll()
|
||||
|
||||
function refreshData()
|
||||
WorkerScript
|
||||
{
|
||||
function refreshCallback(par)
|
||||
id: contactsSortWorker
|
||||
source: "qrc:/qml/ContactSort.js"
|
||||
onMessage: contactsListModel.json = JSON.stringify(messageObject)
|
||||
}
|
||||
|
||||
function refreshAll()
|
||||
{
|
||||
refreshOwn()
|
||||
refreshContacts()
|
||||
refreshUnread()
|
||||
}
|
||||
|
||||
function refreshContactsCallback(par)
|
||||
{
|
||||
console.log("contactsView.refreshContactsCB()", visible)
|
||||
if (contactsListModel.model.count < 1)
|
||||
contactsListModel.json = par.response
|
||||
var token = JSON.parse(par.response).statetoken
|
||||
mainWindow.registerToken(token, refreshContacts)
|
||||
contactsSortWorker.sendMessage(
|
||||
{'action': 'refreshContacts', 'response': par.response})
|
||||
}
|
||||
function refreshContacts()
|
||||
{
|
||||
console.log("contactsView.refreshContacts()", visible)
|
||||
if(!visible) return
|
||||
rsApi.request("/identity/*/", "", refreshContactsCallback)
|
||||
}
|
||||
|
||||
function refreshOwnCallback(par)
|
||||
{
|
||||
console.log("contactsView.refreshOwnCallback(par)", visible)
|
||||
var json = JSON.parse(par.response)
|
||||
var token = json.statetoken
|
||||
mainWindow.registerToken(token, refreshOwn)
|
||||
|
||||
if(json.data.length > 0)
|
||||
{
|
||||
gxsIdsModel.json = par.response
|
||||
if(contactsView.own_gxs_id == "") refreshOwn()
|
||||
contactsView.own_gxs_id = json.data[0].gxs_id
|
||||
contactsView.own_nick = json.data[0].name
|
||||
}
|
||||
rsApi.request("/identity/*/", "", refreshCallback)
|
||||
else createIdentityDialog.visible = true
|
||||
}
|
||||
function refreshOwn()
|
||||
{
|
||||
rsApi.request("/identity/own", "", function(par)
|
||||
{
|
||||
var json = JSON.parse(par.response)
|
||||
if(json.data.length > 0)
|
||||
{
|
||||
contactsView.own_gxs_id = json.data[0].gxs_id
|
||||
contactsView.own_nick = json.data[0].name
|
||||
}
|
||||
else createIdentityDialog.visible = true
|
||||
})
|
||||
console.log("contactsView.refreshOwn()", visible)
|
||||
rsApi.request("/identity/own", "", refreshOwnCallback)
|
||||
}
|
||||
|
||||
function refreshUnreadCallback(par)
|
||||
{
|
||||
console.log("contactsView.refreshUnreadCB()", visible)
|
||||
var json = JSON.parse(par.response)
|
||||
mainWindow.registerToken(json.statetoken, refreshUnread)
|
||||
contactsSortWorker.sendMessage(
|
||||
{'action': 'refreshUnread', 'response': par.response})
|
||||
}
|
||||
function refreshUnread()
|
||||
{
|
||||
console.log("contactsView.refreshUnread()", visible)
|
||||
if(!visible) return
|
||||
rsApi.request("/chat/unread_msgs", "", refreshUnreadCallback)
|
||||
}
|
||||
|
||||
function startChatCallback(par)
|
||||
{
|
||||
var chId = JSON.parse(par.response).data.chat_id
|
||||
stackView.push("qrc:/qml/ChatView.qml", {'chatId': chId})
|
||||
}
|
||||
|
||||
function refreshUnread()
|
||||
{
|
||||
rsApi.request("/chat/unread_msgs", "", function(par)
|
||||
{
|
||||
var jsonData = JSON.parse(par.response).data
|
||||
var dataLen = jsonData.length
|
||||
if(JSON.stringify(unreadMessages) != JSON.stringify(jsonData))
|
||||
{
|
||||
unreadMessages = {}
|
||||
for ( var i=0; i<dataLen; ++i)
|
||||
{
|
||||
var el = jsonData[i]
|
||||
if(el.is_distant_chat_id)
|
||||
unreadMessages[el.remote_author_id] = el.unread_count
|
||||
}
|
||||
|
||||
visualModel.resetSorting()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** This must be equivalent to
|
||||
p3GxsTunnelService::makeGxsTunnelId(...) */
|
||||
|
@ -88,116 +113,21 @@ Item
|
|||
return from_gxs < to_gxs ? from_gxs + to_gxs : to_gxs + from_gxs
|
||||
}
|
||||
|
||||
|
||||
|
||||
onFocusChanged: focus && refreshData()
|
||||
|
||||
JSONListModel
|
||||
{
|
||||
id: gxsIdsModel
|
||||
id: contactsListModel
|
||||
query: "$.data[*]"
|
||||
}
|
||||
|
||||
DelegateModel
|
||||
{
|
||||
/* More documentation about this is available at:
|
||||
* http://doc.qt.io/qt-5/qml-qtqml-models-delegatemodel.html
|
||||
* http://doc.qt.io/qt-5/qtquick-tutorials-dynamicview-dynamicview4-example.html
|
||||
* http://imaginativethinking.ca/use-qt-quicks-delegatemodelgroup/
|
||||
*/
|
||||
id: visualModel
|
||||
model: gxsIdsModel.model
|
||||
|
||||
property var lessThan:
|
||||
[
|
||||
function(left, right)
|
||||
{
|
||||
var lfun = unreadMessages.hasOwnProperty(left.gxs_id) ?
|
||||
unreadMessages[left.gxs_id] : 0
|
||||
var rgun = unreadMessages.hasOwnProperty(right.gxs_id) ?
|
||||
unreadMessages[right.gxs_id] : 0
|
||||
if( lfun !== rgun ) return lfun > rgun
|
||||
if(left.name !== right.name) return left.name < right.name
|
||||
return left.gxs_id < right.gxs_id
|
||||
},
|
||||
function(left, right)
|
||||
{
|
||||
if(searchText.length > 0)
|
||||
{
|
||||
var mtc = searchText.text.toLowerCase()
|
||||
var lfn = left.name.toLowerCase()
|
||||
var rgn = right.name.toLowerCase()
|
||||
var lfml = lfn.indexOf(mtc)
|
||||
var rgml = rgn.indexOf(mtc)
|
||||
if ( lfml !== rgml )
|
||||
{
|
||||
lfml = lfml >= 0 ? lfml : Number.MAX_VALUE
|
||||
rgml = rgml >= 0 ? rgml : Number.MAX_VALUE
|
||||
return lfml < rgml
|
||||
}
|
||||
}
|
||||
return lessThan[0](left, right)
|
||||
}
|
||||
]
|
||||
|
||||
property int sortOrder: contactsView.searching ? 1 : 0
|
||||
onSortOrderChanged: resetSorting()
|
||||
|
||||
property bool isSorting: false
|
||||
|
||||
function insertPosition(lessThan, item)
|
||||
{
|
||||
var lower = 0
|
||||
var upper = items.count
|
||||
while (lower < upper)
|
||||
{
|
||||
var middle = Math.floor(lower + (upper - lower) / 2)
|
||||
var result = lessThan(item.model, items.get(middle).model);
|
||||
if (result) upper = middle
|
||||
else lower = middle + 1
|
||||
}
|
||||
return lower
|
||||
}
|
||||
|
||||
function resetSorting() { items.setGroups(0, items.count, "unsorted") }
|
||||
|
||||
function sort()
|
||||
{
|
||||
while (unsortedItems.count > 0)
|
||||
{
|
||||
var item = unsortedItems.get(0)
|
||||
var index = insertPosition(lessThan[visualModel.sortOrder],
|
||||
item)
|
||||
item.groups = ["items"]
|
||||
items.move(item.itemsIndex, index)
|
||||
}
|
||||
}
|
||||
|
||||
items.includeByDefault: false
|
||||
|
||||
groups:
|
||||
[
|
||||
DelegateModelGroup
|
||||
{
|
||||
id: unsortedItems
|
||||
name: "unsorted"
|
||||
|
||||
includeByDefault: true
|
||||
onChanged: visualModel.sort()
|
||||
}
|
||||
]
|
||||
|
||||
delegate: GxsIdentityDelegate {}
|
||||
}
|
||||
|
||||
ListView
|
||||
{
|
||||
id: locationsListView
|
||||
width: parent.width
|
||||
height: contactsView.searching ?
|
||||
parent.height - searchBox.height : parent.height
|
||||
model: visualModel
|
||||
model: contactsListModel.model
|
||||
anchors.top: contactsView.searching ? searchBox.bottom : parent.top
|
||||
delegate: GxsIdentityDelegate {}
|
||||
}
|
||||
|
||||
Rectangle
|
||||
|
@ -224,7 +154,9 @@ Item
|
|||
id: searchText
|
||||
anchors.left: searchIcon.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onTextChanged: visualModel.resetSorting()
|
||||
onTextChanged:
|
||||
contactsSortWorker.sendMessage(
|
||||
{'action': 'searchContact', 'sexp': text})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,21 +170,6 @@ Item
|
|||
text: "Open Chat as: " + contactsView.own_nick + " " + contactsView.own_gxs_id
|
||||
}
|
||||
|
||||
Timer
|
||||
{
|
||||
id: refreshTimer
|
||||
interval: 5000
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered:
|
||||
if(contactsView.visible)
|
||||
{
|
||||
contactsView.refreshUnread()
|
||||
contactsView.refreshData()
|
||||
}
|
||||
Component.onCompleted: start()
|
||||
}
|
||||
|
||||
Dialog
|
||||
{
|
||||
id: createIdentityDialog
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue