mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 17:49:27 +02:00
Merge pull request #8638 from howard-stearns/uniform-story-handling
Uniform story handling
This commit is contained in:
commit
3f31da68fe
5 changed files with 146 additions and 199 deletions
|
@ -9,10 +9,10 @@
|
||||||
.st1{fill:#E6E7E8;}
|
.st1{fill:#E6E7E8;}
|
||||||
.st2{fill:#FFFFFF;}
|
.st2{fill:#FFFFFF;}
|
||||||
</style>
|
</style>
|
||||||
<path class="st0" d="M1428.61,172H11.46c-6.27,0-11.39-5.13-11.39-11.39V49.58c0-6.27,5.13-11.39,11.39-11.39h1417.15
|
<path class="st0" d="M1428.6,172H11.5c-6.3,0-11.4-5.1-11.4-11.4v-111c0-6.3,5.1-11.4,11.4-11.4h1417.2c6.3,0,11.4,5.1,11.4,11.4
|
||||||
c6.27,0,11.39,5.13,11.39,11.39v111.03C1440,166.87,1434.87,172,1428.61,172z"/>
|
v111C1440,166.9,1434.9,172,1428.6,172z"/>
|
||||||
<path class="st1" d="M1428.61,165.81H11.46c-6.27,0-11.39-5.13-11.39-11.39V43.39c0-6.27,5.13-11.39,11.39-11.39h1417.15
|
<path class="st1" d="M1428.6,165.8H11.5c-6.3,0-11.4-5.1-11.4-11.4v-111C0.1,37.1,5.2,32,11.5,32h1417.2c6.3,0,11.4,5.1,11.4,11.4
|
||||||
c6.27,0,11.39,5.13,11.39,11.39v111.03C1440,160.68,1434.87,165.81,1428.61,165.81z"/>
|
v111C1440,160.7,1434.9,165.8,1428.6,165.8z"/>
|
||||||
<path class="st2" d="M1133.24,165.81H417.95c-4.47,0-8.12-3.65-8.12-8.12V40.11c0-4.47,3.65-8.12,8.12-8.12h715.28
|
<path class="st2" d="M1429.9,165.8H421.3c-6.3,0-11.5-3.6-11.5-8.1V40.1c0-4.5,5.1-8.1,11.5-8.1h1008.6c6.3,0,11.5,3.7,11.5,8.1
|
||||||
c4.47,0,8.12,3.65,8.12,8.12v117.57C1141.36,162.15,1137.7,165.81,1133.24,165.81z"/>
|
v117.6C1441.4,162.1,1436.2,165.8,1429.9,165.8z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
53
interface/resources/images/concurrency.svg
Normal file
53
interface/resources/images/concurrency.svg
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 32 64" style="enable-background:new 0 0 32 64;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#168DB7;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
.st2{opacity:0.63;fill:#58595B;enable-background:new ;}
|
||||||
|
</style>
|
||||||
|
<circle cx="15.8" cy="48.2" r="14.7"/>
|
||||||
|
<circle class="st0" cx="15.8" cy="47.6" r="14.7"/>
|
||||||
|
<circle cx="16.1" cy="44.9" r="3"/>
|
||||||
|
<path d="M18.2,50.2H14c-1.7,0-3.1,1.5-3.1,3.2V55c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2C21.3,51.7,19.9,50.2,18.2,50.2z
|
||||||
|
"/>
|
||||||
|
<circle cx="22.9" cy="44.9" r="1.6"/>
|
||||||
|
<path d="M24,47.9h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2v0.3
|
||||||
|
c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,48.8,24.6,47.9,24,47.9z"/>
|
||||||
|
<circle cx="9.1" cy="45.2" r="1.6"/>
|
||||||
|
<path d="M8.7,53.2c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3s0-0.1,0-0.2c0-0.1,0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||||
|
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,50.6,7.9,52.3,8.7,53.2z"/>
|
||||||
|
<circle class="st1" cx="16.1" cy="44.3" r="3"/>
|
||||||
|
<path class="st1" d="M18.2,49.6H14c-1.7,0-3.1,1.5-3.1,3.2v1.6c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2
|
||||||
|
C21.3,51.1,19.9,49.6,18.2,49.6z"/>
|
||||||
|
<circle class="st1" cx="22.9" cy="44.4" r="1.6"/>
|
||||||
|
<path class="st1" d="M24,47.4h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2
|
||||||
|
v0.3c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,48.2,24.6,47.4,24,47.4z"/>
|
||||||
|
<circle class="st1" cx="9.1" cy="44.6" r="1.6"/>
|
||||||
|
<path class="st1" d="M8.7,52.7c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3s0-0.1,0-0.2c0-0.1,0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||||
|
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,50,7.9,51.7,8.7,52.7z"/>
|
||||||
|
<path d="M15.9,3.4c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7s12.7-5.7,12.7-12.7S22.9,3.4,15.9,3.4z M15.9,27.2
|
||||||
|
c-6.1,0-11.1-5-11.1-11.1S9.8,5,15.9,5C22,4.9,27,9.9,27,16.1C27,22.2,22,27.2,15.9,27.2z"/>
|
||||||
|
<circle class="st2" cx="15.9" cy="15.5" r="12.4"/>
|
||||||
|
<path class="st1" d="M15.9,2.8c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7s12.7-5.7,12.7-12.7S22.9,2.8,15.9,2.8z M15.9,26.6
|
||||||
|
c-6.1,0-11.1-5-11.1-11.1s5-11.1,11.1-11.1C22,4.4,27,9.4,27,15.5S22,26.6,15.9,26.6z"/>
|
||||||
|
<circle cx="16.1" cy="12.9" r="3"/>
|
||||||
|
<path d="M18.2,18.2H14c-1.7,0-3.1,1.5-3.1,3.2V23c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2C21.3,19.7,19.9,18.2,18.2,18.2z
|
||||||
|
"/>
|
||||||
|
<circle cx="22.9" cy="12.9" r="1.6"/>
|
||||||
|
<path d="M24,15.9h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2v0.3
|
||||||
|
c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,16.8,24.6,15.9,24,15.9z"/>
|
||||||
|
<circle cx="9.1" cy="13.2" r="1.6"/>
|
||||||
|
<path d="M8.7,21.2c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.1,0-0.2s0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||||
|
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,18.6,7.9,20.2,8.7,21.2z"/>
|
||||||
|
<circle class="st1" cx="16.1" cy="12.3" r="3"/>
|
||||||
|
<path class="st1" d="M18.2,17.6H14c-1.7,0-3.1,1.5-3.1,3.2v1.6c1.4,1.1,3.1,1.7,4.9,1.7c2.1,0,4-0.8,5.4-2.1v-1.2
|
||||||
|
C21.3,19.1,19.9,17.6,18.2,17.6z"/>
|
||||||
|
<circle class="st1" cx="22.9" cy="12.4" r="1.6"/>
|
||||||
|
<path class="st1" d="M24,15.4h-1.8c-0.4,0-0.8,0.2-1,0.4c0.5,0.3,1,0.7,1.4,1.1c0.5,0.5,0.7,1.2,0.7,1.9c0.1,0.4,0.1,0.8,0.1,1.2
|
||||||
|
v0.3c0.8-1,1.5-2.7,1.8-3.6v-0.1C25.2,16.2,24.6,15.4,24,15.4z"/>
|
||||||
|
<circle class="st1" cx="9.1" cy="12.6" r="1.6"/>
|
||||||
|
<path class="st1" d="M8.7,20.7c0-0.3,0-0.6,0-0.9v-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.1,0-0.2s0-0.1,0-0.2c0.1-0.9,0.7-2,1.4-2.5
|
||||||
|
c0.2-0.2,0.4-0.3,0.6-0.4c-0.2-0.2-0.6-0.3-0.9-0.3H8c-0.6,0-1.2,0.8-1.1,1.2v0.1C7.2,18,7.9,19.7,8.7,20.7z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
33
interface/resources/images/snapshot.svg
Normal file
33
interface/resources/images/snapshot.svg
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 32 64" style="enable-background:new 0 0 32 64;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{opacity:0.64;fill:#58595B;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
.st2{fill:#168DB7;}
|
||||||
|
</style>
|
||||||
|
<circle class="st0" cx="15.8" cy="15.5" r="12.5"/>
|
||||||
|
<path d="M15.8,3.4c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7c7,0,12.7-5.7,12.7-12.7S22.8,3.4,15.8,3.4z M15.8,27.3
|
||||||
|
c-6.2,0-11.2-5-11.2-11.2C4.6,10,9.7,5,15.8,5C22,5,27,10,27,16.1C27,22.3,22,27.3,15.8,27.3z"/>
|
||||||
|
<path class="st1" d="M15.8,2.8c-7,0-12.7,5.7-12.7,12.7s5.7,12.7,12.7,12.7c7,0,12.7-5.7,12.7-12.7S22.8,2.8,15.8,2.8z M15.8,26.7
|
||||||
|
c-6.2,0-11.2-5-11.2-11.2c0-6.2,5-11.2,11.2-11.2C22,4.4,27,9.4,27,15.6C27,21.7,22,26.7,15.8,26.7z"/>
|
||||||
|
<path d="M21.5,11.6H20V11c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2v0.6h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6c0,1,0.8,1.9,1.9,1.9h11
|
||||||
|
c1,0,1.7-1.1,1.7-2.1V13C23.3,12,22.5,11.6,21.5,11.6z M16.1,20.1c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4c2.3,0,4,1.8,4,4
|
||||||
|
S18.4,20.1,16.1,20.1z"/>
|
||||||
|
<circle cx="16.1" cy="16" r="2.4"/>
|
||||||
|
<path class="st1" d="M21.5,11H20v-0.6c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2V11h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6
|
||||||
|
c0,1,0.8,1.9,1.9,1.9h11c1,0,1.7-1.1,1.7-2.1v-6.4C23.3,11.5,22.5,11,21.5,11z M16.1,19.5c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4
|
||||||
|
c2.3,0,4,1.8,4,4S18.4,19.5,16.1,19.5z"/>
|
||||||
|
<circle class="st1" cx="16.1" cy="15.5" r="2.4"/>
|
||||||
|
<circle cx="15.8" cy="48.2" r="14.8"/>
|
||||||
|
<circle class="st2" cx="15.8" cy="47.6" r="14.8"/>
|
||||||
|
<path d="M21.5,43.6H20V43c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2v0.6h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6c0,1,0.8,1.9,1.9,1.9h11
|
||||||
|
c1,0,1.7-1.1,1.7-2.1V45C23.3,44.1,22.5,43.6,21.5,43.6z M16.1,52.1c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4c2.3,0,4,1.8,4,4
|
||||||
|
C20.1,50.2,18.4,52.1,16.1,52.1z"/>
|
||||||
|
<circle cx="16.1" cy="48" r="2.4"/>
|
||||||
|
<path class="st1" d="M21.5,43.1H20v-0.6c0-1-0.6-1.2-1.6-1.2h-5c-1,0-1.5,0.2-1.5,1.2v0.6h-1.5c-1,0-1.9,0.4-1.9,1.4v6.6
|
||||||
|
c0,1,0.8,1.9,1.9,1.9h11c1,0,1.7-1.1,1.7-2.1v-6.4C23.3,43.5,22.5,43.1,21.5,43.1z M16.1,51.5c-2.3,0-4-1.8-4-4c0-2.3,1.8-4,4-4
|
||||||
|
c2.3,0,4,1.8,4,4C20.1,49.7,18.4,51.5,16.1,51.5z"/>
|
||||||
|
<circle class="st1" cx="16.1" cy="47.5" r="2.4"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -50,16 +50,15 @@ Window {
|
||||||
function resetAfterTeleport() {
|
function resetAfterTeleport() {
|
||||||
storyCardFrame.shown = root.shown = false;
|
storyCardFrame.shown = root.shown = false;
|
||||||
}
|
}
|
||||||
function goCard(card) {
|
function goCard(targetString) {
|
||||||
if (addressBarDialog.useFeed) {
|
if (0 !== targetString.indexOf('hifi://')) {
|
||||||
storyCardHTML.url = addressBarDialog.metaverseServerUrl + "/user_stories/" + card.storyId;
|
storyCardHTML.url = addressBarDialog.metaverseServerUrl + targetString;
|
||||||
storyCardFrame.shown = true;
|
storyCardFrame.shown = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addressLine.text = card.hifiUrl;
|
addressLine.text = targetString;
|
||||||
toggleOrGo(true);
|
toggleOrGo(true);
|
||||||
}
|
}
|
||||||
property var allPlaces: [];
|
|
||||||
property var allStories: [];
|
property var allStories: [];
|
||||||
property int cardWidth: 200;
|
property int cardWidth: 200;
|
||||||
property int cardHeight: 152;
|
property int cardHeight: 152;
|
||||||
|
@ -72,7 +71,6 @@ Window {
|
||||||
// The buttons have their button state changed on hover, so we have to manually fix them up here
|
// The buttons have their button state changed on hover, so we have to manually fix them up here
|
||||||
onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0;
|
onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0;
|
||||||
onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0;
|
onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0;
|
||||||
onUseFeedChanged: updateFeedState();
|
|
||||||
onReceivedHifiSchemeURL: resetAfterTeleport();
|
onReceivedHifiSchemeURL: resetAfterTeleport();
|
||||||
|
|
||||||
ListModel { id: suggestions }
|
ListModel { id: suggestions }
|
||||||
|
@ -97,7 +95,6 @@ Window {
|
||||||
userName: model.username;
|
userName: model.username;
|
||||||
placeName: model.place_name;
|
placeName: model.place_name;
|
||||||
hifiUrl: model.place_name + model.path;
|
hifiUrl: model.place_name + model.path;
|
||||||
imageUrl: model.image_url;
|
|
||||||
thumbnail: model.thumbnail_url;
|
thumbnail: model.thumbnail_url;
|
||||||
action: model.action;
|
action: model.action;
|
||||||
timestamp: model.created_at;
|
timestamp: model.created_at;
|
||||||
|
@ -179,9 +176,9 @@ Window {
|
||||||
top: parent.top
|
top: parent.top
|
||||||
bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
left: forwardArrow.right
|
left: forwardArrow.right
|
||||||
right: placesButton.left
|
right: parent.right
|
||||||
leftMargin: forwardArrow.width
|
leftMargin: forwardArrow.width
|
||||||
rightMargin: placesButton.width
|
rightMargin: forwardArrow.width / 2
|
||||||
topMargin: parent.inputAreaStep + hifi.layout.spacing
|
topMargin: parent.inputAreaStep + hifi.layout.spacing
|
||||||
bottomMargin: parent.inputAreaStep + hifi.layout.spacing
|
bottomMargin: parent.inputAreaStep + hifi.layout.spacing
|
||||||
}
|
}
|
||||||
|
@ -191,32 +188,6 @@ Window {
|
||||||
helperItalic: true
|
helperItalic: true
|
||||||
onTextChanged: filterChoicesByText()
|
onTextChanged: filterChoicesByText()
|
||||||
}
|
}
|
||||||
// These two are radio buttons.
|
|
||||||
ToolbarButton {
|
|
||||||
id: placesButton
|
|
||||||
imageURL: "../images/places.svg"
|
|
||||||
buttonState: 1
|
|
||||||
defaultState: addressBarDialog.useFeed ? 0 : 1;
|
|
||||||
hoverState: addressBarDialog.useFeed ? 2 : -1;
|
|
||||||
onClicked: addressBarDialog.useFeed ? toggleFeed() : identity()
|
|
||||||
anchors {
|
|
||||||
right: feedButton.left;
|
|
||||||
bottom: addressLine.bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ToolbarButton {
|
|
||||||
id: feedButton;
|
|
||||||
imageURL: "../images/snap-feed.svg";
|
|
||||||
buttonState: 0
|
|
||||||
defaultState: addressBarDialog.useFeed ? 1 : 0;
|
|
||||||
hoverState: addressBarDialog.useFeed ? -1 : 2;
|
|
||||||
onClicked: addressBarDialog.useFeed ? identity() : toggleFeed();
|
|
||||||
anchors {
|
|
||||||
right: parent.right;
|
|
||||||
bottom: addressLine.bottom;
|
|
||||||
rightMargin: feedButton.width / 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
|
@ -240,16 +211,6 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function toggleFeed() {
|
|
||||||
addressBarDialog.useFeed = !addressBarDialog.useFeed;
|
|
||||||
updateFeedState();
|
|
||||||
}
|
|
||||||
function updateFeedState() {
|
|
||||||
placesButton.buttonState = addressBarDialog.useFeed ? 0 : 1;
|
|
||||||
feedButton.buttonState = addressBarDialog.useFeed ? 1 : 0;
|
|
||||||
filterChoicesByText();
|
|
||||||
}
|
|
||||||
function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects.
|
function getRequest(url, cb) { // cb(error, responseOfCorrectContentType) of url. General for 'get' text/html/json, but without redirects.
|
||||||
// TODO: make available to other .qml.
|
// TODO: make available to other .qml.
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
|
@ -274,37 +235,6 @@ Window {
|
||||||
request.open("GET", url, true);
|
request.open("GET", url, true);
|
||||||
request.send();
|
request.send();
|
||||||
}
|
}
|
||||||
function asyncMap(array, iterator, cb) {
|
|
||||||
// call iterator(element, icb) once for each element of array, and then cb(error, mappedResult)
|
|
||||||
// when icb(error, mappedElement) has been called by each iterator.
|
|
||||||
// Calls to iterator are overlapped and may call icb in any order, but the mappedResults are collected in the same
|
|
||||||
// order as the elements of the array.
|
|
||||||
// Short-circuits if error. Note that iterator MUST be an asynchronous function. (Use setTimeout if necessary.)
|
|
||||||
var count = array.length, results = [];
|
|
||||||
if (!count) {
|
|
||||||
return cb(null, results);
|
|
||||||
}
|
|
||||||
array.forEach(function (element, index) {
|
|
||||||
if (count < 0) { // don't keep iterating after we short-circuit
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
iterator(element, function (error, mapped) {
|
|
||||||
results[index] = mapped;
|
|
||||||
if (error || !--count) {
|
|
||||||
count = 0; // don't cb multiple times if error
|
|
||||||
cb(error, results);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Example:
|
|
||||||
/*asyncMap([0, 1, 2, 3, 4, 5, 6], function (elt, icb) {
|
|
||||||
console.log('called', elt);
|
|
||||||
setTimeout(function () {
|
|
||||||
console.log('answering', elt);
|
|
||||||
icb(null, elt);
|
|
||||||
}, Math.random() * 1000);
|
|
||||||
}, console.log); */
|
|
||||||
|
|
||||||
function identity(x) {
|
function identity(x) {
|
||||||
return x;
|
return x;
|
||||||
|
@ -324,131 +254,61 @@ Window {
|
||||||
cb(error);
|
cb(error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
function resolveUrl(url) {
|
||||||
function getPlace(placeData, cb) { // cb(error, side-effected-placeData), after adding path, thumbnails, and description
|
return (url.indexOf('/') === 0) ? (addressBarDialog.metaverseServerUrl + url) : url;
|
||||||
var url = metaverseBase + 'places/' + placeData.place_name;
|
|
||||||
getRequest(url, function (error, data) {
|
|
||||||
if (handleError(url, error, data, cb)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var place = data.data.place, previews = place.previews;
|
|
||||||
placeData.path = place.path;
|
|
||||||
if (previews && previews.thumbnail) {
|
|
||||||
placeData.thumbnail_url = previews.thumbnail;
|
|
||||||
}
|
|
||||||
if (place.description) {
|
|
||||||
placeData.description = place.description;
|
|
||||||
placeData.searchText += ' ' + place.description.toUpperCase();
|
|
||||||
}
|
|
||||||
cb(error, placeData);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function makeModelData(data, optionalPlaceName) { // create a new obj from data
|
|
||||||
|
function makeModelData(data) { // create a new obj from data
|
||||||
// ListModel elements will only ever have those properties that are defined by the first obj that is added.
|
// 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.
|
// 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,
|
var name = data.place_name,
|
||||||
tags = data.tags || [data.action, data.username],
|
tags = data.tags || [data.action, data.username],
|
||||||
description = data.description || "",
|
description = data.description || "",
|
||||||
thumbnail_url = data.thumbnail_url || "",
|
thumbnail_url = data.thumbnail_url || "";
|
||||||
image_url = thumbnail_url;
|
|
||||||
if (data.details) {
|
|
||||||
try {
|
|
||||||
image_url = JSON.parse(data.details).image_url || thumbnail_url;
|
|
||||||
} catch (e) {
|
|
||||||
console.log(name, "has bad details", data.details);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
place_name: name,
|
place_name: name,
|
||||||
username: data.username || "",
|
username: data.username || "",
|
||||||
path: data.path || "",
|
path: data.path || "",
|
||||||
created_at: data.created_at || "",
|
created_at: data.created_at || "",
|
||||||
action: data.action || "",
|
action: data.action || "",
|
||||||
thumbnail_url: thumbnail_url,
|
thumbnail_url: resolveUrl(thumbnail_url),
|
||||||
image_url: image_url,
|
|
||||||
|
|
||||||
metaverseId: (data.id || "").toString(), // Some are strings from server while others are numbers. Model objects require uniformity.
|
metaverseId: (data.id || "").toString(), // Some are strings from server while others are numbers. Model objects require uniformity.
|
||||||
|
|
||||||
tags: tags,
|
tags: tags,
|
||||||
description: description,
|
description: description,
|
||||||
online_users: data.online_users || 0,
|
online_users: data.details.concurrency || 0,
|
||||||
|
|
||||||
searchText: [name].concat(tags, description || []).join(' ').toUpperCase()
|
searchText: [name].concat(tags, description || []).join(' ').toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function mapDomainPlaces(domain, cb) { // cb(error, arrayOfDomainPlaceData)
|
|
||||||
function addPlace(name, icb) {
|
|
||||||
getPlace(makeModelData(domain, name), icb);
|
|
||||||
}
|
|
||||||
// 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.
|
|
||||||
asyncMap(domain.names || [], addPlace, cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
function suggestable(place) {
|
function suggestable(place) {
|
||||||
if (addressBarDialog.useFeed) {
|
if (place.action === 'snapshot') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (place.place_name !== AddressManager.hostname) // Not our entry, but do show other entry points to current domain.
|
return (place.place_name !== AddressManager.hostname); // Not our entry, but do show other entry points to current domain.
|
||||||
&& place.thumbnail_url
|
// could also require right protocolVersion
|
||||||
&& place.online_users // at least one present means it's actually online
|
|
||||||
&& place.online_users <= 20;
|
|
||||||
}
|
|
||||||
function getDomainPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
|
|
||||||
// Each page of results is processed completely before we start on the next page.
|
|
||||||
// For each page of domains, we process each domain in parallel, and for each domain, process each place name in parallel.
|
|
||||||
// This gives us minimum latency within the page, but we do preserve the order within the page by using asyncMap and
|
|
||||||
// only appending the collected results.
|
|
||||||
var params = [
|
|
||||||
'open', // published hours handle now
|
|
||||||
// TBD: should determine if place is actually running?
|
|
||||||
'restriction=open', // Not by whitelist, etc. TBD: If logged in, add hifi to the restriction options, in order to include places that require login?
|
|
||||||
// TBD: add maturity?
|
|
||||||
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
|
|
||||||
'sort_by=users',
|
|
||||||
'sort_order=desc',
|
|
||||||
'page=' + pageNumber
|
|
||||||
];
|
|
||||||
var url = metaverseBase + 'domains/all?' + params.join('&');
|
|
||||||
getRequest(url, function (error, data) {
|
|
||||||
if (handleError(url, error, data, cb)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
asyncMap(data.data.domains, mapDomainPlaces, function (error, pageResults) {
|
|
||||||
if (error) {
|
|
||||||
return cb(error);
|
|
||||||
}
|
|
||||||
// pageResults is now [ [ placeDataOneForDomainOne, placeDataTwoForDomainOne, ...], [ placeDataTwoForDomainTwo...] ]
|
|
||||||
pageResults.forEach(function (domainResults) {
|
|
||||||
allPlaces = allPlaces.concat(domainResults);
|
|
||||||
if (!addressLine.text && !addressBarDialog.useFeed) { // Don't add if the user is already filtering
|
|
||||||
domainResults.forEach(function (place) {
|
|
||||||
if (suggestable(place)) {
|
|
||||||
suggestions.append(place);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (data.current_page < data.total_pages) {
|
|
||||||
return getDomainPage(pageNumber + 1, cb);
|
|
||||||
}
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
|
function getUserStoryPage(pageNumber, cb) { // cb(error) after all pages of domain data have been added to model
|
||||||
var url = metaverseBase + 'user_stories?page=' + pageNumber;
|
var options = [
|
||||||
|
'include_actions=snapshot,concurrency',
|
||||||
|
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
|
||||||
|
'page=' + pageNumber
|
||||||
|
];
|
||||||
|
var url = metaverseBase + 'user_stories?' + options.join('&');
|
||||||
getRequest(url, function (error, data) {
|
getRequest(url, function (error, data) {
|
||||||
if (handleError(url, error, data, cb)) {
|
if (handleError(url, error, data, cb)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var stories = data.user_stories.map(function (story) { // explicit single-argument function
|
var stories = data.user_stories.map(function (story) { // explicit single-argument function
|
||||||
return makeModelData(story);
|
return makeModelData(story, url);
|
||||||
});
|
});
|
||||||
allStories = allStories.concat(stories);
|
allStories = allStories.concat(stories);
|
||||||
if (!addressLine.text && addressBarDialog.useFeed) { // Don't add if the user is already filtering
|
if (!addressLine.text) { // Don't add if the user is already filtering
|
||||||
stories.forEach(function (story) {
|
stories.forEach(function (story) {
|
||||||
suggestions.append(story);
|
if (suggestable(story)) {
|
||||||
|
suggestions.append(story);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if ((data.current_page < data.total_pages) && (data.current_page <= 10)) { // just 10 pages = 100 stories for now
|
if ((data.current_page < data.total_pages) && (data.current_page <= 10)) { // just 10 pages = 100 stories for now
|
||||||
|
@ -460,7 +320,7 @@ Window {
|
||||||
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 = addressBarDialog.useFeed ? allStories : allPlaces;
|
data = allStories;
|
||||||
function matches(place) {
|
function matches(place) {
|
||||||
if (!words.length) {
|
if (!words.length) {
|
||||||
return suggestable(place);
|
return suggestable(place);
|
||||||
|
@ -477,12 +337,8 @@ Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillDestinations() {
|
function fillDestinations() {
|
||||||
allPlaces = [];
|
|
||||||
allStories = [];
|
allStories = [];
|
||||||
suggestions.clear();
|
suggestions.clear();
|
||||||
getDomainPage(1, function (error) {
|
|
||||||
console.log('domain query', error || 'ok', allPlaces.length);
|
|
||||||
});
|
|
||||||
getUserStoryPage(1, function (error) {
|
getUserStoryPage(1, function (error) {
|
||||||
console.log('user stories query', error || 'ok', allStories.length);
|
console.log('user stories query', error || 'ok', allStories.length);
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
import Hifi 1.0
|
import Hifi 1.0
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
|
import "toolbars"
|
||||||
import "../styles-uit"
|
import "../styles-uit"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -23,16 +24,13 @@ Rectangle {
|
||||||
property string timestamp: "";
|
property string timestamp: "";
|
||||||
property string hifiUrl: "";
|
property string hifiUrl: "";
|
||||||
property string thumbnail: defaultThumbnail;
|
property string thumbnail: defaultThumbnail;
|
||||||
property string imageUrl: "";
|
|
||||||
property var goFunction: null;
|
property var goFunction: null;
|
||||||
property string storyId: "";
|
property string storyId: "";
|
||||||
|
|
||||||
property string timePhrase: pastTime(timestamp);
|
property string timePhrase: pastTime(timestamp);
|
||||||
property string actionPhrase: makeActionPhrase(action);
|
|
||||||
property int onlineUsers: 0;
|
property int onlineUsers: 0;
|
||||||
property bool isUserStory: userName && !onlineUsers;
|
|
||||||
|
|
||||||
property int textPadding: 20;
|
property int textPadding: 10;
|
||||||
property int textSize: 24;
|
property int textSize: 24;
|
||||||
property int textSizeSmall: 18;
|
property int textSizeSmall: 18;
|
||||||
property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif");
|
property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif");
|
||||||
|
@ -58,14 +56,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
return 'about a minute ago';
|
return 'about a minute ago';
|
||||||
}
|
}
|
||||||
function makeActionPhrase(actionLabel) {
|
|
||||||
switch (actionLabel) {
|
|
||||||
case "snapshot":
|
|
||||||
return "took a snapshot";
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: lobby;
|
id: lobby;
|
||||||
|
@ -100,7 +90,7 @@ Rectangle {
|
||||||
spread: dropSpread;
|
spread: dropSpread;
|
||||||
}
|
}
|
||||||
DropShadow {
|
DropShadow {
|
||||||
visible: desktop.gradientsSupported;
|
visible: users.visible && desktop.gradientsSupported;
|
||||||
source: users;
|
source: users;
|
||||||
anchors.fill: users;
|
anchors.fill: users;
|
||||||
horizontalOffset: dropHorizontalOffset;
|
horizontalOffset: dropHorizontalOffset;
|
||||||
|
@ -112,7 +102,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: place;
|
id: place;
|
||||||
text: isUserStory ? "" : placeName;
|
text: placeName;
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
size: textSize;
|
size: textSize;
|
||||||
anchors {
|
anchors {
|
||||||
|
@ -121,14 +111,15 @@ Rectangle {
|
||||||
margins: textPadding;
|
margins: textPadding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RalewayRegular {
|
FiraSansRegular {
|
||||||
id: users;
|
id: users;
|
||||||
text: isUserStory ? timePhrase : (onlineUsers + ((onlineUsers === 1) ? ' person' : ' people'));
|
visible: action === 'concurrency';
|
||||||
size: textSizeSmall;
|
text: onlineUsers;
|
||||||
|
size: textSize;
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
anchors {
|
anchors {
|
||||||
bottom: parent.bottom;
|
verticalCenter: usersImage.verticalCenter;
|
||||||
right: parent.right;
|
right: usersImage.left;
|
||||||
margins: textPadding;
|
margins: textPadding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,9 +132,23 @@ Rectangle {
|
||||||
id: zmouseArea;
|
id: zmouseArea;
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
acceptedButtons: Qt.LeftButton;
|
acceptedButtons: Qt.LeftButton;
|
||||||
onClicked: goFunction(parent);
|
onClicked: goFunction("hifi://" + hifiUrl);
|
||||||
hoverEnabled: true;
|
hoverEnabled: true;
|
||||||
onEntered: hoverThunk();
|
onEntered: hoverThunk();
|
||||||
onExited: unhoverThunk();
|
onExited: unhoverThunk();
|
||||||
}
|
}
|
||||||
|
ToolbarButton {
|
||||||
|
id: usersImage;
|
||||||
|
imageURL: "../../images/" + action + ".svg";
|
||||||
|
size: 32;
|
||||||
|
onClicked: goFunction("/user_stories/" + storyId);
|
||||||
|
buttonState: 0;
|
||||||
|
defaultState: 0;
|
||||||
|
hoverState: 1;
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom;
|
||||||
|
right: parent.right;
|
||||||
|
margins: textPadding;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue