From 747c43d0656d0ec33050d3079ab2c55c490e18a0 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 11 Aug 2016 16:43:29 -0700 Subject: [PATCH] basic user story card --- interface/resources/qml/AddressBarDialog.qml | 63 ++++++++------ .../resources/qml/controls-uit/Button.qml | 2 + interface/resources/qml/hifi/Card.qml | 51 ++++++++++-- .../resources/qml/hifi/UserStoryCard.qml | 83 +++++++++++++++++++ 4 files changed, 167 insertions(+), 32 deletions(-) create mode 100644 interface/resources/qml/hifi/UserStoryCard.qml diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 8590121fa0..a65a228cf8 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -47,7 +47,16 @@ Window { } function goCard(card) { - addressLine.text = card.path; + if (useFeed) { + storyCard.imageUrl = card.imageUrl; //"http://howard-stearns.github.io/models/images/dancing-avatars.jpg"; + storyCard.userName = card.userName; + storyCard.placeName = card.placeName; + storyCard.actionPhrase = card.actionPhrase; + storyCard.timePhrase = card.timePhrase; + storyCard.visible = true; + return; + } + addressLine.text = card.hifiUrl; toggleOrGo(true); } property bool useFeed: false; @@ -56,26 +65,6 @@ Window { property int cardWidth: 200; property int cardHeight: 152; property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/"; - 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 { id: addressBarDialog @@ -88,6 +77,7 @@ Window { ListModel { id: suggestions } ListView { + id: scroll width: (3 * cardWidth) + (2 * hifi.layout.spacing); height: cardHeight; spacing: hifi.layout.spacing; @@ -103,10 +93,14 @@ Window { width: cardWidth; height: cardHeight; goFunction: goCard; - path: model.place_name + model.path; + userName: model.username; + placeName: model.place_name; + hifiUrl: model.place_name + model.path; + imageUrl: model.thumbnail_url; // This is wrong, but it will have to wait. thumbnail: model.thumbnail_url; - placeText: model.created_at ? "" : model.place_name; - usersText: model.created_at ? pastTime(model.created_at) : (model.online_users + ((model.online_users === 1) ? ' person' : ' people')); + action: model.action; + timestamp: model.created_at; + onlineUsers: model.online_users; hoverThunk: function () { ListView.view.currentIndex = index; } unhoverThunk: function () { ListView.view.currentIndex = -1; } } @@ -209,8 +203,24 @@ Window { } } } + + UserStoryCard { + id: storyCard; + visible: false; + visitPlace: function (hifiUrl) { + storyCard.visible = false; + addressLine.text = hifiUrl; + toggleOrGo(true); + }; + anchors { + verticalCenter: scroll.verticalCenter; + horizontalCenter: scroll.horizontalCenter; + verticalCenterOffset: 50; + } + } } + function toggleFeed () { useFeed = !useFeed; placesButton.buttonState = useFeed ? 0 : 1; @@ -318,13 +328,15 @@ Window { description = data.description || ""; return { place_name: name, + username: data.username || "", path: data.path || "", created_at: data.created_at || "", + action: data.action || "", thumbnail_url: data.thumbnail_url || "", tags: tags, description: description, - online_users: data.online_users, + online_users: data.online_users || 0, searchText: [name].concat(tags, description).join(' ').toUpperCase() } @@ -402,7 +414,6 @@ Window { {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(function (story) { // explicit single-argument function return makeModelData(story); }); diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml index 298943b551..59f8a63238 100644 --- a/interface/resources/qml/controls-uit/Button.qml +++ b/interface/resources/qml/controls-uit/Button.qml @@ -21,6 +21,8 @@ Original.Button { width: 120 height: hifi.dimensions.controlLineHeight + HifiConstants { id: hifi } + style: ButtonStyle { background: Rectangle { diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 5fae628283..278f9330d3 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -17,17 +17,54 @@ import QtGraphicalEffects 1.0 import "../styles-uit" Rectangle { + property string userName: ""; + property string placeName: ""; + property string action: ""; + property string timestamp: ""; + property string hifiUrl: ""; + property string thumbnail: defaultThumbnail; + property string imageUrl: ""; property var goFunction: null; - property alias image: lobby; - property alias placeText: place.text; - property alias usersText: users.text; + + property string timePhrase: pastTime(timestamp); + property string actionPhrase: makeActionPhrase(action); + property int onlineUsers: 0; + property bool isUserStory: userName && !onlineUsers; + property int textPadding: 20; property int textSize: 24; property int textSizeSmall: 18; property string defaultThumbnail: Qt.resolvedUrl("../../images/default-domain.gif"); - property string thumbnail: defaultThumbnail; - property string path: ""; HifiConstants { id: hifi } + 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'; + } + function makeActionPhrase(actionLabel) { + switch (actionLabel) { + case "snapshot": + return "took a snapshot"; + default: + return "unknown" + } + } + Image { id: lobby; width: parent.width; @@ -39,7 +76,7 @@ Rectangle { anchors.left: parent.left; onStatusChanged: { if (status == Image.Error) { - console.log("source: " + source + ": failed to load " + path); + console.log("source: " + source + ": failed to load " + hfiUrl); source = defaultThumbnail; } } @@ -71,6 +108,7 @@ Rectangle { } RalewaySemiBold { id: place; + text: isUserStory ? "" : placeName; color: hifi.colors.white; size: textSize; anchors { @@ -81,6 +119,7 @@ Rectangle { } RalewayRegular { id: users; + text: isUserStory ? timePhrase : (onlineUsers + ((onlineUsers === 1) ? ' person' : ' people')); size: textSizeSmall; color: hifi.colors.white; anchors { diff --git a/interface/resources/qml/hifi/UserStoryCard.qml b/interface/resources/qml/hifi/UserStoryCard.qml new file mode 100644 index 0000000000..4b6c37dae8 --- /dev/null +++ b/interface/resources/qml/hifi/UserStoryCard.qml @@ -0,0 +1,83 @@ +// +// UserStoryCard.qml +// qml/hifi +// +// Displays a clickable card representing a user story or destination. +// +// Created by Howard Stearns on 8/11/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" as HifiStyles +import "../controls-uit" as HifiControls + +Rectangle { + id: storyCard; + width: 500; + height: 330; + property string userName: "User"; + property string placeName: "Home"; + property string actionPhrase: "did something"; + property string timePhrase: ""; + property string hifiUrl: storyCard.placeName; + property string imageUrl: Qt.resolvedUrl("../images/default-domain.gif"); + property var visitPlace: function (ignore) { }; + color: "white"; + HifiStyles.HifiConstants { id: otherHifi } + MouseArea { + anchors.fill: parent; + acceptedButtons: Qt.LeftButton; + onClicked: storyCard.visible = false; + hoverEnabled: true; + // The content of the storyCard has buttons. For these to work without being + // blanketed by the MouseArea, they need to be children of the MouseArea. + Image { + id: storyImage; + source: storyCard.imageUrl; + width: storyCard.width - 100; + height: storyImage.width / 1.91; + fillMode: Image.PreserveAspectCrop; + anchors { + horizontalCenter: parent.horizontalCenter; + top: parent.top; + topMargin: 20; + } + } + HifiStyles.RalewayRegular { + id: storyLabel; + text: storyCard.userName + " " + storyCard.actionPhrase + " in " + storyCard.placeName + size: 20; + color: "black" + anchors { + horizontalCenter: storyImage.horizontalCenter; + top: storyImage.bottom; + topMargin: hifi.layout.spacing + } + } + HifiStyles.RalewayRegular { + text: storyCard.timePhrase; + size: 15; + color: "slategrey" + anchors { + verticalCenter: visitButton.verticalCenter; + left: storyImage.left; + } + } + HifiControls.Button { + id: visitButton; + text: "visit " + storyCard.placeName; + color: otherHifi.buttons.blue; + onClicked: visitPlace(storyCard.hifiUrl); + anchors { + top: storyLabel.bottom; + topMargin: hifi.layout.spacing; + right: storyImage.right; + } + } + } +}