diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 6884d2e1f6..915213508c 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -145,6 +145,22 @@ Rectangle { } pal.sendToScript({method: 'refreshNearby', params: params}); } + function refreshConnections() { + var flickable = connectionsUserModel.flickable; + connectionsRefreshScrollTimer.oldY = flickable.contentY; + flickable.contentY = 0; + connectionsUserModel.getFirstPage('delayRefresh', function () { + connectionsRefreshScrollTimer.start(); + }); + } + Timer { + id: connectionsRefreshScrollTimer; + interval: 500; + property real oldY: 0; + onTriggered: { + connectionsUserModel.flickable.contentY = oldY; + } + } Rectangle { id: palTabContainer; @@ -276,7 +292,10 @@ Rectangle { id: reloadConnections; width: reloadConnections.height; glyph: hifi.glyphs.reload; - onClicked: connectionsUserModel.getFirstPage('delayRefresh'); + onClicked: { + pal.sendToScript({method: 'refreshConnections'}); + refreshConnections(); + } } } // "CONNECTIONS" text @@ -1209,6 +1228,9 @@ Rectangle { case 'clearLocalQMLData': ignored = {}; break; + case 'refreshConnections': + refreshConnections(); + break; case 'avatarDisconnected': var sessionID = message.params[0]; delete ignored[sessionID]; diff --git a/interface/resources/qml/hifi/models/PSFListModel.qml b/interface/resources/qml/hifi/models/PSFListModel.qml index 988502dd91..542145904f 100644 --- a/interface/resources/qml/hifi/models/PSFListModel.qml +++ b/interface/resources/qml/hifi/models/PSFListModel.qml @@ -93,7 +93,7 @@ ListModel { property int totalPages: 0; property int totalEntries: 0; // Check consistency and call processPage. - function handlePage(error, response) { + function handlePage(error, response, cb) { var processed; console.debug('handlePage', listModelName, additionalFirstPageRequested, error, JSON.stringify(response)); function fail(message) { @@ -134,7 +134,9 @@ ListModel { if (additionalFirstPageRequested) { console.debug('deferred getFirstPage', listModelName); additionalFirstPageRequested = false; - getFirstPage('delayedClear'); + getFirstPage('delayedClear', cb); + } else if (cb) { + cb(); } } function debugView(label) { @@ -147,7 +149,7 @@ ListModel { // Override either http or getPage. property var http; // An Item that has a request function. - property var getPage: function () { // Any override MUST call handlePage(), above, even if results empty. + property var getPage: function (cb) { // Any override MUST call handlePage(), above, even if results empty. if (!http) { return console.warn("Neither http nor getPage was set for", listModelName); } // If it is a path starting with slash, add the metaverseServer domain. var url = /^\//.test(endpoint) ? (Account.metaverseServerURL + endpoint) : endpoint; @@ -165,12 +167,12 @@ ListModel { var parametersSeparator = /\?/.test(url) ? '&' : '?'; url = url + parametersSeparator + parameters.join('&'); console.debug('getPage', listModelName, currentPageToRetrieve); - http.request({uri: url}, handlePage); + http.request({uri: url}, cb ? function (error, result) { handlePage(error, result, cb); } : handlePage); } // Start the show by retrieving data according to `getPage()`. // It can be custom-defined by this item's Parent. - property var getFirstPage: function (delayClear) { + property var getFirstPage: function (delayClear, cb) { if (requestPending) { console.debug('deferring getFirstPage', listModelName); additionalFirstPageRequested = true; @@ -180,7 +182,7 @@ ListModel { resetModel(); requestPending = true; console.debug("getFirstPage", listModelName, currentPageToRetrieve); - getPage(); + getPage(cb); } property bool additionalFirstPageRequested: false; property bool requestPending: false; // For de-bouncing getNextPage. diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 9485b8b49a..ebb45130e5 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -268,7 +268,6 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See break; case 'refreshConnections': print('Refreshing Connections...'); - getConnectionData(false); UserActivityLogger.palAction("refresh_connections", ""); break; case 'removeConnection': @@ -281,7 +280,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See print("Error: unable to remove connection", connectionUserName, error || response.status); return; } - getConnectionData(false); + sendToQml({ method: 'refreshConnections' }); }); break; @@ -361,8 +360,9 @@ function getProfilePicture(username, callback) { // callback(url) if successfull callback(matched[1]); }); } +var SAFETY_LIMIT = 400; function getAvailableConnections(domain, callback) { // callback([{usename, location}...]) if successfull. (Logs otherwise) - var url = METAVERSE_BASE + '/api/v1/users?per_page=400&'; + var url = METAVERSE_BASE + '/api/v1/users?per_page=' + SAFETY_LIMIT + '&'; if (domain) { url += 'status=' + domain.slice(1, -1); // without curly braces } else { @@ -373,8 +373,10 @@ function getAvailableConnections(domain, callback) { // callback([{usename, loca }); } function getInfoAboutUser(specificUsername, callback) { - var url = METAVERSE_BASE + '/api/v1/users?filter=connections'; + var url = METAVERSE_BASE + '/api/v1/users?filter=connections&per_page=' + SAFETY_LIMIT + '&search=' + encodeURIComponent(specificUsername); requestJSON(url, function (connectionsData) { + // You could have (up to SAFETY_LIMIT connections whose usernames contain the specificUsername. + // Search returns all such matches. for (user in connectionsData.users) { if (connectionsData.users[user].username === specificUsername) { callback(connectionsData.users[user]); @@ -406,16 +408,14 @@ function getConnectionData(specificUsername, domain) { // Update all the usernam print('Error: Unable to find information about ' + specificUsername + ' in connectionsData!'); } }); - } else { + } else if (domain) { getAvailableConnections(domain, function (users) { - if (domain) { - users.forEach(function (user) { - updateUser(frob(user)); - }); - } else { - sendToQml({ method: 'connections', params: users.map(frob) }); - } + users.forEach(function (user) { + updateUser(frob(user)); + }); }); + } else { + print("Error: unrecognized getConnectionData()"); } }