reusable feeds

This commit is contained in:
howard-stearns 2017-04-19 16:33:02 -07:00
parent 3ce238b8a0
commit 2512255dd0
2 changed files with 46 additions and 43 deletions

View file

@ -17,19 +17,22 @@ import QtGraphicalEffects 1.0
import "toolbars" import "toolbars"
import "../styles-uit" import "../styles-uit"
Rectangle { Column {
id: root; id: root;
property int cardWidth: 212; property int cardWidth: 212;
property int cardHeight: 152; property int cardHeight: 152;
property int stackedCardShadowHeight: 10; property int stackedCardShadowHeight: 10;
property string metaverseServerUrl: ''; property string metaverseServerUrl: '';
property string actions: 'snapshot';
onActionsChanged: fillDestinations();
Component.onCompleted: fillDestinations();
property string labelText: actions;
property string filter: ''; property string filter: '';
onFilterChanged: filterChoicesByText(); onFilterChanged: filterChoicesByText();
property alias suggestions: feed; // fixme. don't need to expose
HifiConstants { id: hifi } HifiConstants { id: hifi }
ListModel { id: feed; } ListModel { id: suggestions; }
function resolveUrl(url) { function resolveUrl(url) {
return (url.indexOf('/') === 0) ? (metaverseServerUrl + url) : url; return (url.indexOf('/') === 0) ? (metaverseServerUrl + url) : url;
@ -66,7 +69,7 @@ Rectangle {
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 options = [ var options = [
'now=' + new Date().toISOString(), 'now=' + new Date().toISOString(),
'include_actions=' + selectedTab.includeActions, 'include_actions=' + actions,
'restriction=' + (Account.isLoggedIn() ? 'open,hifi' : 'open'), 'restriction=' + (Account.isLoggedIn() ? 'open,hifi' : 'open'),
'require_online=true', 'require_online=true',
'protocol=' + encodeURIComponent(AddressManager.protocolVersion()), 'protocol=' + encodeURIComponent(AddressManager.protocolVersion()),
@ -78,11 +81,7 @@ Rectangle {
if ((thisRequestId !== requestId) || handleError(url, error, data, cb)) { if ((thisRequestId !== requestId) || handleError(url, error, data, cb)) {
return; // abandon stale requests return; // abandon stale requests
} }
var stories = data.user_stories.map(function (story) { // explicit single-argument function allStories = allStories.concat(data.user_stories.map(makeModelData));
return makeModelData(story, url);
});
allStories = allStories.concat(stories);
stories.forEach(makeFilteredPlaceProcessor());
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
return getUserStoryPage(pageNumber + 1, cb); return getUserStoryPage(pageNumber + 1, cb);
} }
@ -94,11 +93,12 @@ Rectangle {
suggestions.clear(); suggestions.clear();
placeMap = {}; placeMap = {};
getUserStoryPage(1, function (error) { getUserStoryPage(1, function (error) {
console.log('user stories query', error || 'ok', allStories.length); allStories.forEach(makeFilteredStoryProcessor());
console.log('user stories query', actions, error || 'ok', allStories.length, 'filtered to', suggestions.count);
}); });
} }
function addToSuggestions(place) { // fixme: move to makeFilteredPlaceProcessor function addToSuggestions(place) { // fixme: move to makeFilteredStoryProcessor
var collapse = allTab.selected && (place.action !== 'concurrency'); var collapse = (actions === 'snapshot,concurrency') && (place.action !== 'concurrency'); // fixme generalize?
if (collapse) { if (collapse) {
var existing = placeMap[place.place_name]; var existing = placeMap[place.place_name];
if (existing) { if (existing) {
@ -113,61 +113,49 @@ Rectangle {
suggestions.get(suggestions.count - 1).drillDownToPlace = true; // Don't change raw place object (in allStories). suggestions.get(suggestions.count - 1).drillDownToPlace = true; // Don't change raw place object (in allStories).
} }
} }
function suggestable(place) { // fixme add to makeFilteredPlaceProcessor function suggestable(story) { // fixme add to makeFilteredStoryProcessor
if (place.action === 'snapshot') { if (story.action === 'snapshot') {
return true; return true;
} }
return (place.place_name !== AddressManager.placename); // Not our entry, but do show other entry points to current domain. return (story.place_name !== AddressManager.placename); // Not our entry, but do show other entry points to current domain.
} }
function makeFilteredPlaceProcessor() { // answer a function(placeData) that adds it to suggestions if it matches function makeFilteredStoryProcessor() { // answer a function(storyData) that adds it to suggestions if it matches
var words = filter.toUpperCase().split(/\s+/).filter(identity), var words = filter.toUpperCase().split(/\s+/).filter(identity);
data = allStories; function matches(story) {
function matches(place) {
if (!words.length) { if (!words.length) {
return suggestable(place); return suggestable(story);
} }
return words.every(function (word) { return words.every(function (word) {
return place.searchText.indexOf(word) >= 0; return story.searchText.indexOf(word) >= 0;
}); });
} }
return function (place) { return function (story) {
if (matches(place)) { if (matches(story)) {
addToSuggestions(place); addToSuggestions(story);
} }
}; };
} }
function filterChoicesByText() { function filterChoicesByText() {
suggestions.clear(); suggestions.clear();
placeMap = {}; placeMap = {};
allStories.forEach(makeFilteredPlaceProcessor()); allStories.forEach(makeFilteredStoryProcessor());
} }
RalewayLight { RalewayLight {
id: label; id: label;
text: "Places"; text: labelText;
color: hifi.colors.blueHighlight; color: hifi.colors.blueHighlight;
size: 38; size: 28;
width: root.width;
anchors {
top: parent.top;
left: parent.left;
margins: 10;
}
} }
ListView { ListView {
id: scroll; id: scroll;
clip: true; clip: true;
model: feed; model: suggestions;
orientation: ListView.Horizontal; orientation: ListView.Horizontal;
spacing: 14; spacing: 14;
width: parent.width;
height: cardHeight + stackedCardShadowHeight; height: cardHeight + stackedCardShadowHeight;
anchors {
top: label.bottom;
left: parent.left;
right: parent.right;
leftMargin: 10;
}
delegate: Card { delegate: Card {
width: cardWidth; width: cardWidth;
height: cardHeight; height: cardHeight;

View file

@ -39,7 +39,6 @@ StackView {
Component { id: tabletWebView; TabletWebView {} } Component { id: tabletWebView; TabletWebView {} }
Component.onCompleted: { Component.onCompleted: {
updateLocationText(false); updateLocationText(false);
feed.fillDestinations();
addressLine.focus = !HMD.active; addressLine.focus = !HMD.active;
root.parentChanged.connect(center); root.parentChanged.connect(center);
center(); center();
@ -286,11 +285,28 @@ StackView {
topMargin: 0; topMargin: 0;
} }
Feed { Feed {
id: feed; id: happeningNow;
width: bgMain.width; width: bgMain.width;
metaverseServerUrl: addressBarDialog.metaverseServerUrl; metaverseServerUrl: addressBarDialog.metaverseServerUrl;
actions: selectedTab.includeActions;
filter: addressLine.text; filter: addressLine.text;
} }
Feed {
id: places;
width: bgMain.width;
metaverseServerUrl: addressBarDialog.metaverseServerUrl;
actions: 'concurrency';
filter: addressLine.text;
anchors.top: happeningNow.bottom;
}
Feed {
id: snapshots;
width: bgMain.width;
metaverseServerUrl: addressBarDialog.metaverseServerUrl;
actions: 'snapshot';
filter: addressLine.text;
anchors.top: places.bottom;
}
} }
Timer { Timer {
@ -374,7 +390,6 @@ StackView {
property var selectedTab: allTab; property var selectedTab: allTab;
function tabSelect(textButton) { function tabSelect(textButton) {
selectedTab = textButton; selectedTab = textButton;
feed.fillDestinations();
} }
function updateLocationText(enteringAddress) { function updateLocationText(enteringAddress) {