mirror of
https://github.com/overte-org/overte.git
synced 2025-08-05 20:10:29 +02:00
basic display of user story feed (hardcoded switch place names vs feed)
This commit is contained in:
parent
5a0db63a6f
commit
e593077b4b
1 changed files with 101 additions and 29 deletions
|
@ -49,9 +49,31 @@ Window {
|
||||||
addressLine.text = card.path;
|
addressLine.text = card.path;
|
||||||
toggleOrGo(true);
|
toggleOrGo(true);
|
||||||
}
|
}
|
||||||
|
property bool useFeed: false;
|
||||||
property var allPlaces: [];
|
property var allPlaces: [];
|
||||||
|
property var allStories: [];
|
||||||
property int cardWidth: 200;
|
property int cardWidth: 200;
|
||||||
property int cardHeight: 152;
|
property int cardHeight: 152;
|
||||||
|
function pastTime(timestamp) { // Answer a descriptive string
|
||||||
|
timestamp = new Date(timestamp);
|
||||||
|
var then = timestamp.getTime(),
|
||||||
|
now = Date.now(),
|
||||||
|
since = now - then,
|
||||||
|
ONE_MINUTE = 1000 * 60,
|
||||||
|
ONE_HOUR = ONE_MINUTE * 60,
|
||||||
|
hours = since / ONE_HOUR,
|
||||||
|
minutes = (hours % 1) * 60;
|
||||||
|
if (hours > 24) {
|
||||||
|
return timestamp.toDateString();
|
||||||
|
}
|
||||||
|
if (hours > 1) {
|
||||||
|
return Math.floor(hours).toString() + ' hr ' + Math.floor(minutes) + ' min ago';
|
||||||
|
}
|
||||||
|
if (minutes >= 2) {
|
||||||
|
return Math.floor(minutes).toString() + ' min ago';
|
||||||
|
}
|
||||||
|
return 'about a minute ago';
|
||||||
|
}
|
||||||
|
|
||||||
AddressBarDialog {
|
AddressBarDialog {
|
||||||
id: addressBarDialog
|
id: addressBarDialog
|
||||||
|
@ -76,10 +98,10 @@ Window {
|
||||||
width: cardWidth;
|
width: cardWidth;
|
||||||
height: cardHeight;
|
height: cardHeight;
|
||||||
goFunction: goCard;
|
goFunction: goCard;
|
||||||
path: model.name + model.path;
|
path: model.place_name + model.path;
|
||||||
thumbnail: model.thumbnail;
|
thumbnail: model.thumbnail_url;
|
||||||
placeText: model.name;
|
placeText: model.place_name;
|
||||||
usersText: model.online_users + ((model.online_users === 1) ? ' person' : ' people');
|
usersText: (model.created_at ? pastTime(model.created_at) : (model.online_users + ((model.online_users === 1) ? ' person' : ' people')));
|
||||||
hoverThunk: function () { ListView.view.currentIndex = index; }
|
hoverThunk: function () { ListView.view.currentIndex = index; }
|
||||||
unhoverThunk: function () { ListView.view.currentIndex = -1; }
|
unhoverThunk: function () { ListView.view.currentIndex = -1; }
|
||||||
}
|
}
|
||||||
|
@ -235,23 +257,31 @@ Window {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleError(error, data, cb) { // cb(error) and answer truthy if needed, else falsey
|
function handleError(url, error, data, cb) { // cb(error) and answer truthy if needed, else falsey
|
||||||
if (!error && (data.status === 'success')) {
|
if (!error && (data.status === 'success')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cb(error || new Error(data.status + ': ' + data.error));
|
if (!error) { // Create a message from the data
|
||||||
|
error = data.status + ': ' + data.error;
|
||||||
|
}
|
||||||
|
if (typeof(error) === 'string') { // Make a proper Error object
|
||||||
|
error = new Error(error);
|
||||||
|
}
|
||||||
|
error.message += ' in ' + url; // Include the url.
|
||||||
|
cb(error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description
|
function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description
|
||||||
getRequest('https://metaverse.highfidelity.com/api/v1/places/' + placeData.name, function (error, data) {
|
var url = 'https://metaverse.highfidelity.com/api/v1/places/' + placeData.place_name;
|
||||||
if (handleError(error, data, cb)) {
|
getRequest(url, function (error, data) {
|
||||||
|
if (handleError(url, error, data, cb)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var place = data.data.place, previews = place.previews;
|
var place = data.data.place, previews = place.previews;
|
||||||
placeData.path = place.path;
|
placeData.path = place.path;
|
||||||
if (previews && previews.thumbnail) {
|
if (previews && previews.thumbnail) {
|
||||||
placeData.thumbnail = previews.thumbnail;
|
placeData.thumbnail_url = previews.thumbnail;
|
||||||
}
|
}
|
||||||
if (place.description) {
|
if (place.description) {
|
||||||
placeData.description = place.description;
|
placeData.description = place.description;
|
||||||
|
@ -260,17 +290,28 @@ Window {
|
||||||
cb(error, placeData);
|
cb(error, placeData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function makeModelData(data, optionalPlaceName) { // create a new obj from data
|
||||||
|
// ListModel elements will only ever have those properties that are defined by the first obj that is added.
|
||||||
|
// So here we make sure that we have all the properties we need, regardless of whether it is a place data or user story.
|
||||||
|
var name = optionalPlaceName || data.place_name,
|
||||||
|
tags = data.tags || [data.action],
|
||||||
|
description = data.description || "";
|
||||||
|
return {
|
||||||
|
place_name: name,
|
||||||
|
path: data.path || "",
|
||||||
|
created_at: data.create_at || "8/3/2016",
|
||||||
|
thumbnail_url: data.thumbnail_url || "",
|
||||||
|
|
||||||
|
tags: tags,
|
||||||
|
description: description,
|
||||||
|
online_users: data.online_users,
|
||||||
|
|
||||||
|
searchText: [name].concat(tags, description).join(' ').toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData)
|
function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData)
|
||||||
function addPlace(name, icb) {
|
function addPlace(name, icb) {
|
||||||
getPlace({
|
getPlace(makeModelData(domain, name), icb);
|
||||||
name: name,
|
|
||||||
tags: domain.tags,
|
|
||||||
thumbnail: "",
|
|
||||||
description: "",
|
|
||||||
path: "",
|
|
||||||
searchText: [name].concat(domain.tags).join(' ').toUpperCase(),
|
|
||||||
online_users: domain.online_users
|
|
||||||
}, icb);
|
|
||||||
}
|
}
|
||||||
// IWBNI we could get these results in order with most-recent-entered first.
|
// IWBNI we could get these results in order with most-recent-entered first.
|
||||||
// In any case, we don't really need to preserve the domain.names order in the results.
|
// In any case, we don't really need to preserve the domain.names order in the results.
|
||||||
|
@ -278,8 +319,11 @@ Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
function suggestable(place) {
|
function suggestable(place) {
|
||||||
return (place.name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain.
|
if (useFeed) {
|
||||||
&& place.thumbnail
|
return true;
|
||||||
|
}
|
||||||
|
return (place.place_name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain.
|
||||||
|
&& place.thumbnail_url
|
||||||
&& place.online_users // at least one present means it's actually online
|
&& place.online_users // at least one present means it's actually online
|
||||||
&& place.online_users <= 20;
|
&& place.online_users <= 20;
|
||||||
}
|
}
|
||||||
|
@ -298,8 +342,9 @@ Window {
|
||||||
'sort_order=desc',
|
'sort_order=desc',
|
||||||
'page=' + pageNumber
|
'page=' + pageNumber
|
||||||
];
|
];
|
||||||
getRequest('https://metaverse.highfidelity.com/api/v1/domains/all?' + params.join('&'), function (error, data) {
|
var url = 'https://metaverse.highfidelity.com/api/v1/domains/all?' + params.join('&');
|
||||||
if (handleError(error, data, cb)) {
|
getRequest(url, function (error, data) {
|
||||||
|
if (handleError(url, error, data, cb)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) {
|
asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) {
|
||||||
|
@ -309,7 +354,7 @@ Window {
|
||||||
// pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ]
|
// pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ]
|
||||||
pageResults.forEach(function (domainResults) {
|
pageResults.forEach(function (domainResults) {
|
||||||
allPlaces = allPlaces.concat(domainResults);
|
allPlaces = allPlaces.concat(domainResults);
|
||||||
if (!addressLine.text) { // Don't add if the user is already filtering
|
if (!addressLine.text && !useFeed) { // Don't add if the user is already filtering
|
||||||
domainResults.forEach(function (place) {
|
domainResults.forEach(function (place) {
|
||||||
if (suggestable(place)) {
|
if (suggestable(place)) {
|
||||||
suggestions.append(place);
|
suggestions.append(place);
|
||||||
|
@ -324,9 +369,35 @@ Window {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
|
||||||
|
var url = 'https://metaverse.highfidelity.com/api/v1/user_stories?page=' + pageNumber;
|
||||||
|
getRequest(url, function (error, data) {
|
||||||
|
if (handleError(url, error, data, cb)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// FIXME: For debugging until we have real data
|
||||||
|
data = {user_stories: [
|
||||||
|
{created_at: "8/3/2016", action: "snapshot", path: "/4257.1,126.084,1335.45/0,-0.857368,0,0.514705", place_name: "SpiritMoving", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/c28/a26/f0-/thumbnail/hifi-place-c28a26f0-6991-4654-9c2b-e64228c06954.jpg?1456878797"},
|
||||||
|
{created_at: "8/3/2016", action: "snapshot", path: "/10077.4,4003.6,9972.56/0,-0.410351,0,0.911928", place_name: "Ventura", thumbnail_url:"https://hifi-metaverse.s3-us-west-1.amazonaws.com/images/places/previews/1f5/e6b/00-/thumbnail/hifi-place-1f5e6b00-2bf0-4319-b9ae-a2344a72354c.png?1454321596"}
|
||||||
|
]};
|
||||||
|
|
||||||
|
var stories = data.user_stories.map(makeModelData);
|
||||||
|
allStories = allStories.concat(stories);
|
||||||
|
if (!addressLine.text && useFeed) { // Don't add if the user is already filtering
|
||||||
|
stories.forEach(function (story) {
|
||||||
|
suggestions.append(story);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.current_page < data.total_pages) {
|
||||||
|
return getUserStoryPage(pageNumber + 1, cb);
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
}
|
||||||
function filterChoicesByText() {
|
function filterChoicesByText() {
|
||||||
suggestions.clear();
|
suggestions.clear();
|
||||||
var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity);
|
var words = addressLine.text.toUpperCase().split(/\s+/).filter(identity),
|
||||||
|
data = useFeed ? allStories : allPlaces;
|
||||||
function matches(place) {
|
function matches(place) {
|
||||||
if (!words.length) {
|
if (!words.length) {
|
||||||
return suggestable(place);
|
return suggestable(place);
|
||||||
|
@ -335,7 +406,7 @@ Window {
|
||||||
return place.searchText.indexOf(word) >= 0;
|
return place.searchText.indexOf(word) >= 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
allPlaces.forEach(function (place) {
|
data.forEach(function (place) {
|
||||||
if (matches(place)) {
|
if (matches(place)) {
|
||||||
suggestions.append(place);
|
suggestions.append(place);
|
||||||
}
|
}
|
||||||
|
@ -344,12 +415,13 @@ Window {
|
||||||
|
|
||||||
function fillDestinations() {
|
function fillDestinations() {
|
||||||
allPlaces = [];
|
allPlaces = [];
|
||||||
|
allStories = [];
|
||||||
suggestions.clear();
|
suggestions.clear();
|
||||||
getDomainPage(1, function (error) {
|
getDomainPage(1, function (error) {
|
||||||
if (error) {
|
console.log('domain query', error, allPlaces.length);
|
||||||
console.log('domain query failed:', error);
|
});
|
||||||
}
|
getUserStoryPage(1, function (error) {
|
||||||
console.log('domain query finished', allPlaces.length);
|
console.log('user stories query', error, allStories.length);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue