Merge pull request #8463 from howard-stearns/html-user-story

html drill-down user story
This commit is contained in:
Howard Stearns 2016-08-18 16:15:47 -07:00 committed by GitHub
commit 01fcaa024d
10 changed files with 95 additions and 19 deletions

View file

@ -15,6 +15,7 @@ import "styles"
import "windows"
import "hifi"
import "hifi/toolbars"
import "controls-uit" as HifiControls
Window {
id: root
@ -46,15 +47,23 @@ Window {
anchors.centerIn = parent;
}
function resetAfterTeleport() {
storyCardFrame.shown = root.shown = false;
}
function goCard(card) {
if (addressBarDialog.useFeed) {
storyCard.imageUrl = card.imageUrl;
storyCard.userName = card.userName;
storyCard.placeName = card.placeName;
storyCard.actionPhrase = card.actionPhrase;
storyCard.timePhrase = card.timePhrase;
storyCard.hifiUrl = card.hifiUrl;
storyCard.visible = true;
if (useHTML) {
storyCardHTML.url = metaverseBase + "user_stories/" + card.storyId + ".html";
storyCardFrame.shown = true;
} else {
storyCardQML.imageUrl = card.imageUrl;
storyCardQML.userName = card.userName;
storyCardQML.placeName = card.placeName;
storyCardQML.actionPhrase = card.actionPhrase;
storyCardQML.timePhrase = card.timePhrase;
storyCardQML.hifiUrl = card.hifiUrl;
storyCardQML.visible = true;
}
return;
}
addressLine.text = card.hifiUrl;
@ -65,6 +74,8 @@ Window {
property int cardWidth: 200;
property int cardHeight: 152;
property string metaverseBase: "https://metaverse.highfidelity.com/api/v1/";
//property string metaverseBase: "http://10.0.0.241:3000/api/v1/";
property bool useHTML: false; // fixme: remove this and all false branches after the server is updated
AddressBarDialog {
id: addressBarDialog
@ -74,6 +85,7 @@ Window {
onBackEnabledChanged: backArrow.buttonState = addressBarDialog.backEnabled ? 1 : 0;
onForwardEnabledChanged: forwardArrow.buttonState = addressBarDialog.forwardEnabled ? 1 : 0;
onUseFeedChanged: { updateFeedState(); }
onReceivedHifiSchemeURL: resetAfterTeleport();
ListModel { id: suggestions }
@ -102,6 +114,7 @@ Window {
action: model.action;
timestamp: model.created_at;
onlineUsers: model.online_users;
storyId: model.metaverseId;
hoverThunk: function () { ListView.view.currentIndex = index; }
unhoverThunk: function () { ListView.view.currentIndex = -1; }
}
@ -114,6 +127,7 @@ Window {
Image { // Just a visual indicator that the user can swipe the cards over to see more.
source: "../images/Swipe-Icon-single.svg"
width: 50;
visible: suggestions.count > 3;
anchors {
right: scroll.right;
verticalCenter: scroll.verticalCenter;
@ -215,10 +229,10 @@ Window {
}
UserStoryCard {
id: storyCard;
id: storyCardQML;
visible: false;
visitPlace: function (hifiUrl) {
storyCard.visible = false;
storyCardQML.visible = false;
addressLine.text = hifiUrl;
toggleOrGo(true);
};
@ -228,6 +242,25 @@ Window {
verticalCenterOffset: 50;
}
}
Window {
width: 750;
height: 360;
HifiControls.WebView {
anchors.fill: parent;
id: storyCardHTML;
}
id: storyCardFrame;
shown: false;
destroyOnCloseButton: false;
pinnable: false;
anchors {
verticalCenter: scroll.verticalCenter;
horizontalCenter: scroll.horizontalCenter;
verticalCenterOffset: 50;
}
}
}
@ -357,6 +390,8 @@ Window {
thumbnail_url: thumbnail_url,
image_url: image_url,
metaverseId: (data.id || "").toString(), // Some are strings from server while others are numbers. Model objects require uniformity.
tags: tags,
description: description,
online_users: data.online_users || 0,

View file

@ -25,6 +25,7 @@ Rectangle {
property string thumbnail: defaultThumbnail;
property string imageUrl: "";
property var goFunction: null;
property string storyId: "";
property string timePhrase: pastTime(timestamp);
property string actionPhrase: makeActionPhrase(action);

View file

@ -4853,6 +4853,7 @@ bool Application::canAcceptURL(const QString& urlString) const {
bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
if (urlString.startsWith(HIFI_URL_SCHEME)) {
// this is a hifi URL - have the AddressManager handle it
emit receivedHifiSchemeURL(urlString);
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
Qt::AutoConnection, Q_ARG(const QString&, urlString));
return true;

View file

@ -266,6 +266,7 @@ signals:
void activeDisplayPluginChanged();
void uploadRequest(QString path);
void receivedHifiSchemeURL(QString path);
public slots:
QVector<EntityItemID> pasteEntities(float x, float y, float z);

View file

@ -26,6 +26,11 @@ bool AccountScriptingInterface::isLoggedIn() {
return accountManager->isLoggedIn();
}
bool AccountScriptingInterface::checkAndSignalForAccessToken() {
auto accountManager = DependencyManager::get<AccountManager>();
return accountManager->checkAndSignalForAccessToken();
}
QString AccountScriptingInterface::getUsername() {
auto accountManager = DependencyManager::get<AccountManager>();
if (accountManager->isLoggedIn()) {

View file

@ -26,6 +26,7 @@ public slots:
static AccountScriptingInterface* getInstance();
QString getUsername();
bool isLoggedIn();
bool checkAndSignalForAccessToken();
};
#endif // hifi_AccountScriptingInterface_h

View file

@ -39,6 +39,7 @@ AddressBarDialog::AddressBarDialog(QQuickItem* parent) : OffscreenQmlDialog(pare
_backEnabled = !(DependencyManager::get<AddressManager>()->getBackStack().isEmpty());
_forwardEnabled = !(DependencyManager::get<AddressManager>()->getForwardStack().isEmpty());
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::setUseFeed, this, &AddressBarDialog::setUseFeed);
connect(qApp, &Application::receivedHifiSchemeURL, this, &AddressBarDialog::receivedHifiSchemeURL);
}
void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions) {

View file

@ -33,6 +33,7 @@ signals:
void backEnabledChanged();
void forwardEnabledChanged();
void useFeedChanged();
void receivedHifiSchemeURL(QString url);
protected:
void displayAddressOfflineMessage();

View file

@ -84,6 +84,9 @@
}
function handleShareButtons(shareMsg) {
var openFeed = document.getElementById('openFeed');
openFeed.checked = shareMsg.openFeedAfterShare;
openFeed.onchange = function () { EventBridge.emitWebEvent(openFeed.checked ? 'setOpenFeedTrue' : 'setOpenFeedFalse'); };
if (!shareMsg.canShare) {
// this means you may or may not be logged in, but can't share
// because you are not in a public place.
@ -116,10 +119,10 @@
};
// beware of bug: Cannot send objects at top level. (Nested in arrays is fine.)
shareSelected = function () {
EventBridge.emitWebEvent(paths.concat({openFeed: document.getElementById("openFeed").checked}));
EventBridge.emitWebEvent(paths);
};
doNotShare = function () {
EventBridge.emitWebEvent([{openFeed: document.getElementById("openFeed").checked}]);
EventBridge.emitWebEvent([]);
};
snapshotSettings = function () {
EventBridge.emitWebEvent("openSettings");

View file

@ -20,39 +20,62 @@ var button = toolBar.addButton({
alpha: 0.9,
});
function shouldOpenFeedAfterShare() {
var persisted = Settings.getValue('openFeedAfterShare', true); // might answer true, false, "true", or "false"
return persisted && (persisted !== 'false');
}
function showFeedWindow() {
DialogsManager.showFeed();
}
var openFeed, outstanding;
var outstanding;
function confirmShare(data) {
var dialog = new OverlayWebWindow('Snapshot Review', Script.resolvePath("html/ShareSnapshot.html"), 800, 470);
function onMessage(message) {
// Receives message from the html dialog via the qwebchannel EventBridge. This is complicated by the following:
// 1. Although we can send POJOs, we cannot receive a toplevel object. (Arrays of POJOs are fine, though.)
// 2. Although we currently use a single image, we would like to take snapshot, a selfie, a 360 etc. all at the
// same time, show the user all of them, and have the user deselect any that they do not want to share.
// So we'll ultimately be receiving a set of objects, perhaps with different post processing for each.
var isLoggedIn, needsLogin = false;
switch (message) {
case 'ready':
dialog.emitScriptEvent(data); // Send it.
openFeed = false;
outstanding = 0;
break;
case 'openSettings':
Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog");
break;
case 'setOpenFeedFalse':
Settings.setValue('openFeedAfterShare', false)
break;
case 'setOpenFeedTrue':
Settings.setValue('openFeedAfterShare', true)
break;
default:
dialog.webEventReceived.disconnect(onMessage); // I'm not certain that this is necessary. If it is, what do we do on normal close?
dialog.close();
dialog.deleteLater();
isLoggedIn = Account.isLoggedIn();
message.forEach(function (submessage) {
if (submessage.share && !isLoggedIn) {
needsLogin = true;
submessage.share = false;
}
if (submessage.share) {
print('sharing', submessage.localPath);
outstanding++;
Window.shareSnapshot(submessage.localPath);
} else if (submessage.openFeed) {
openFeed = true;
} else {
print('not sharing', submessage.localPath);
}
});
if (openFeed && !outstanding) {
if (!outstanding && shouldOpenFeedAfterShare()) {
showFeedWindow();
}
if (needsLogin) { // after the possible feed, so that the login is on top
Account.checkAndSignalForAccessToken();
}
}
}
dialog.webEventReceived.connect(onMessage);
@ -67,7 +90,7 @@ function snapshotShared(success) {
// for now just print an error.
print('snapshot upload/share failed');
}
if ((--outstanding <= 0) && openFeed) {
if ((--outstanding <= 0) && shouldOpenFeedAfterShare()) {
showFeedWindow();
}
}
@ -114,8 +137,12 @@ function resetButtons(path, notify) {
// last element in data array tells dialog whether we can share or not
confirmShare([
{ localPath: path },
{ canShare: Boolean(Window.location.placename), isLoggedIn: Account.isLoggedIn() }
{ localPath: path },
{
canShare: Boolean(Window.location.placename),
isLoggedIn: true, // Just have the dialog act as though we are. To be removed at both ends later.
openFeedAfterShare: shouldOpenFeedAfterShare()
}
]);
}