mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:24:00 +02:00
prototype
This commit is contained in:
parent
bcee128de0
commit
3132cca482
3 changed files with 244 additions and 1 deletions
|
@ -11,8 +11,13 @@
|
|||
import Hifi 1.0
|
||||
import QtQuick 2.4
|
||||
import "controls"
|
||||
import "controls-uit" as HifiControls
|
||||
import "styles"
|
||||
import "windows"
|
||||
import "hifi"
|
||||
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
@ -43,12 +48,52 @@ Window {
|
|||
// Explicitly center in order to avoid warnings at shutdown
|
||||
anchors.centerIn = parent;
|
||||
}
|
||||
|
||||
|
||||
function goCard(card) {
|
||||
addressLine.text = card.userStory.name;
|
||||
toggleOrGo();
|
||||
}
|
||||
|
||||
AddressBarDialog {
|
||||
id: addressBarDialog
|
||||
implicitWidth: backgroundImage.width
|
||||
implicitHeight: backgroundImage.height
|
||||
|
||||
Column {
|
||||
width: backgroundImage.width;
|
||||
anchors {
|
||||
left: backgroundImage.left;
|
||||
leftMargin: backgroundImage.height + 2 * hifi.layout.spacing
|
||||
bottom: backgroundImage.top;
|
||||
bottomMargin: 2 * hifi.layout.spacing;
|
||||
}
|
||||
Text {
|
||||
text: "Suggestions"
|
||||
}
|
||||
Row {
|
||||
Card {
|
||||
id: s0;
|
||||
width: 200;
|
||||
height: 200;
|
||||
goFunction: goCard
|
||||
}
|
||||
HifiControls.HorizontalSpacer { }
|
||||
Card {
|
||||
id: s1;
|
||||
width: 200;
|
||||
height: 200;
|
||||
goFunction: goCard
|
||||
}
|
||||
HifiControls.HorizontalSpacer { }
|
||||
Card {
|
||||
id: s2;
|
||||
width: 200;
|
||||
height: 200;
|
||||
goFunction: goCard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: backgroundImage
|
||||
source: "../images/address-bar.svg"
|
||||
|
@ -135,9 +180,124 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects.
|
||||
// TODO: make available to other .qml.
|
||||
var request = new XMLHttpRequest();
|
||||
// QT bug: apparently doesn't handle onload. Workaround using readyState.
|
||||
request.onreadystatechange = function () {
|
||||
var READY_STATE_DONE = 4;
|
||||
var HTTP_OK = 200;
|
||||
if (request.readyState >= READY_STATE_DONE) {
|
||||
var error = (request.status !== HTTP_OK) && request.status.toString() + ':' + request.statusText,
|
||||
response = !error && request.responseText,
|
||||
contentType = !error && request.getResponseHeader('content-type');
|
||||
if (!error && contentType.indexOf('application/json') === 0) {
|
||||
try {
|
||||
response = JSON.parse(response);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
}
|
||||
cb(error, response);
|
||||
}
|
||||
};
|
||||
request.open("GET", url, true);
|
||||
request.send();
|
||||
}
|
||||
// call iterator(element, icb) once for each element of array, and then cb(error) when icb(error) has been called by each iterator.
|
||||
// short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.)
|
||||
function asyncEach(array, iterator, cb) {
|
||||
var count = array.length;
|
||||
function icb(error) {
|
||||
if (!--count || error) {
|
||||
count = -1; // don't cb multiple times (e.g., if error)
|
||||
cb(error);
|
||||
}
|
||||
}
|
||||
if (!count) {
|
||||
return cb();
|
||||
}
|
||||
array.forEach(function (element) {
|
||||
iterator(element, icb);
|
||||
});
|
||||
}
|
||||
|
||||
function addPictureToDomain(domainInfo, cb) { // asynchronously add thumbnail and lobby to domainInfo, if available, and cb(error)
|
||||
asyncEach([domainInfo.name].concat(domainInfo.names || null).filter(function (x) { return x; }), function (name, icb) {
|
||||
var url = "https://metaverse.highfidelity.com/api/v1/places/" + name;
|
||||
getRequest(url, function (error, json) {
|
||||
var previews = !error && json.data.place.previews;
|
||||
if (previews) {
|
||||
if (!domainInfo.thumbnail) { // just grab tghe first one
|
||||
domainInfo.thumbnail = previews.thumbnail;
|
||||
}
|
||||
if (!domainInfo.lobby) {
|
||||
domainInfo.lobby = previews.lobby;
|
||||
}
|
||||
}
|
||||
icb(error);
|
||||
});
|
||||
}, cb);
|
||||
}
|
||||
|
||||
function getDomains(options, cb) { // cb(error, arrayOfData)
|
||||
if (!options.page) {
|
||||
options.page = 1;
|
||||
}
|
||||
// FIXME: really want places I'm allowed in, not just open ones
|
||||
var url = "https://metaverse.highfidelity.com/api/v1/domains/all?open&active&page=" + options.page + "&users=" + options.minUsers + "-" + options.maxUsers;
|
||||
getRequest(url, function (error, json) {
|
||||
if (!error && (json.status !== 'success')) {
|
||||
error = new Error("Bad response: " + JSON.stringify(json));
|
||||
}
|
||||
if (error) {
|
||||
error.message += ' for ' + url;
|
||||
return cb(error);
|
||||
}
|
||||
var domains = json.data.domains;
|
||||
asyncEach(domains, addPictureToDomain, function (error) {
|
||||
if (json.current_page < json.total_pages) {
|
||||
options.page++;
|
||||
return getDomains(options, function (error, others) {
|
||||
cb(error, domains.concat(others));
|
||||
});
|
||||
}
|
||||
cb(null, domains);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function fillDestinations () {
|
||||
function fill1(target, data) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
console.log('suggestion:', JSON.stringify(data));
|
||||
target.userStory = data;
|
||||
if (data.lobby) {
|
||||
console.log('target', target);
|
||||
console.log('target.image', target.image);
|
||||
console.log('url', data.lobby);
|
||||
target.image.source = data.lobby;
|
||||
}
|
||||
target.placeText = data.name;
|
||||
target.usersText = data.online_users + ((data.online_users === 1) ? ' user' : ' users');
|
||||
}
|
||||
getDomains({minUsers: 0, maxUsers: 20}, function (e, d) {
|
||||
var withLobby = !e && d.filter(function (d1) { return d1.lobby; });
|
||||
console.log(e, d.length, withLobby.length);
|
||||
withLobby.sort(function (a, b) { return b.online_users - a.online_users; });
|
||||
console.log(withLobby.map(function (d) { return d.online_users; }));
|
||||
fill1(s0, withLobby[0]);
|
||||
fill1(s1, withLobby[1]);
|
||||
fill1(s2, withLobby[2]);
|
||||
});
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
addressLine.forceActiveFocus()
|
||||
fillDestinations();
|
||||
} else {
|
||||
addressLine.text = ""
|
||||
}
|
||||
|
|
19
interface/resources/qml/controls-uit/HorizontalSpacer.qml
Normal file
19
interface/resources/qml/controls-uit/HorizontalSpacer.qml
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// HorizontalSpacer.qml
|
||||
//
|
||||
// Created by Howard Stearns on 12 July 2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
Item {
|
||||
HifiConstants { id: hifi }
|
||||
height: 1 // Must be non-zero
|
||||
width: hifi.dimensions.controlInterlineHeight
|
||||
}
|
64
interface/resources/qml/hifi/Card.qml
Normal file
64
interface/resources/qml/hifi/Card.qml
Normal file
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// Card.qml
|
||||
// qml/hifi
|
||||
//
|
||||
// Displays a clickable card representing a user story or destination.
|
||||
//
|
||||
// Created by Howard Stearns on 7/13/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import Hifi 1.0
|
||||
import QtQuick 2.5
|
||||
import "../styles-uit"
|
||||
|
||||
Rectangle {
|
||||
property var goFunction: null;
|
||||
property var userStory: null;
|
||||
property alias image: lobby;
|
||||
property alias placeText: place.text;
|
||||
property alias usersText: users.text;
|
||||
HifiConstants { id: hifi }
|
||||
Image {
|
||||
id: lobby;
|
||||
width: parent.width;
|
||||
height: parent.height;
|
||||
fillMode: Image.PreserveAspectCrop;
|
||||
// source gets filled in later
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.left: parent.left;
|
||||
onStatusChanged: {
|
||||
if (status == Image.Error) {
|
||||
console.log("source: " + source + ": failed to load " + JSON.stringify(userStory));
|
||||
// FIXME: let's get our own
|
||||
source = "http://www.davidluke.com/wp-content/themes/david-luke/media/ims/placeholder720.gif"
|
||||
}
|
||||
}
|
||||
}
|
||||
RalewaySemiBold {
|
||||
id: place;
|
||||
color: hifi.colors.lightGrayText;
|
||||
anchors {
|
||||
leftMargin: 2 * hifi.layout.spacing;
|
||||
topMargin: 2 * hifi.layout.spacing;
|
||||
}
|
||||
}
|
||||
RalewayRegular {
|
||||
id: users;
|
||||
color: hifi.colors.lightGrayText;
|
||||
anchors {
|
||||
bottom: parent.bottom;
|
||||
right: parent.right;
|
||||
bottomMargin: 2 * hifi.layout.spacing;
|
||||
rightMargin: 2 * hifi.layout.spacing;
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent;
|
||||
acceptedButtons: Qt.LeftButton;
|
||||
onClicked: goFunction(parent);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue