Skip to content

Commit

Permalink
fixing missing images
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianovide committed Jun 11, 2021
1 parent 0354d97 commit a0d5a42
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 95 deletions.
8 changes: 8 additions & 0 deletions firestore.indexes.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
{ "fieldPath": "moderated", "mode": "ASCENDING" },
{ "fieldPath": "updated", "mode": "DESCENDING" }
]
},
{
"collectionGroup": "photos",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "published", "mode": "ASCENDING" },
{ "fieldPath": "updated", "mode": "DESCENDING" }
]
}
]
}
2 changes: 1 addition & 1 deletion scripts/populateDemoData.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ async function run(num, storage, location) {
const digits = 12;

const queue = new Queue({
concurrent: 100,
concurrent: 10,
interval: 10
});

Expand Down
152 changes: 67 additions & 85 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,13 @@ class App extends Component {
let { photoId, mapLocation } = this.extractPathnameParams();
this.setState({ photoId, mapLocation });

this.unregisterAuthObserver = authFirebase.onAuthStateChanged((user) => {
// will do this after the user has been loaded. It should speed up the users login.
// not sure if we need this if.
if (!this.initDone) {
this.initDone = true;
this.someInits(photoId, user);
}
// TODO: test it. Does it slow down starting up ?
if (!this.initDone) {
this.initDone = true;
this.someInits(photoId);
}

this.unregisterAuthObserver = authFirebase.onAuthStateChanged((user) => {
// lets start fresh if the user logged out
if (this.state.user && !user) {
gtagEvent("Signed out", "User");
Expand Down Expand Up @@ -225,12 +224,19 @@ class App extends Component {
}

geojson.features = _.map(this.featuresDict, (f) => f);

// save only if different
if (!_.isEqual(this.state.geojson, geojson)) {
this.setState({ geojson });
// after the first time, wait for a bit before updating.
localforage.setItem("cachedGeoJson", geojson);

const stats = this.props.config.getStats(geojson, this.state.dbStats);
this.setState({ geojson, stats });

this.featuresDict = geojson.features.reduce((acc, feature) => {
acc[feature.properties.id] = feature;
return acc;
}, {});

}

console.debug("Geo Json updated");
Expand Down Expand Up @@ -258,103 +264,77 @@ class App extends Component {
this.delayedSaveGeojson();
};

someInits(photoId, user) {
async someInits(photoId) {
this.unregisterConnectionObserver = dbFirebase.onConnectionStateChanged(
(online) => {
this.setState({ online });
}
);

// when photoId is defined (when acceding the app with photoid query string), need to get the photo info.
this.fetchPhotoIfUndefined(photoId).then(async () => {
// If the selectedFeature is not null, it means that we were able to retrieve a photo from the URL and so we landed
// into the photoId.
this.setState({ photoAccessedByUrl: !!this.state.selectedFeature });

dbFirebase.fetchStats().then((dbStats) => {
console.log(dbStats);
this.setState({
usersLeaderboard: dbStats.users,
dbStats,
stats: this.props.config.getStats(
this.state.geojson,
this.state.dbStats
),
});

return dbStats;
});

gtagPageView(this.props.location.pathname);
});

// use the locals one if we have them: faster boot.
localforage
.getItem("cachedGeoJson")
.then((geojson) => {
if (geojson) {
this.geojson = geojson;
const stats = this.props.config.getStats(geojson, this.state.dbStats);
this.setState({ geojson, stats });
this.featuresDict = geojson.features.reduce((acc, feature) => {
acc[feature.properties.id] = feature;
return acc;
}, {});
// Get the photos from the cache first.
const geojson = await localforage.getItem("cachedGeoJson");

if (geojson) {
this.setState({ geojson });
this.featuresDict = geojson.features.reduce((acc, feature) => {
acc[feature.properties.id] = feature;
return acc;
}, {});
} else {
await this.fetchPhotos();
}

this.registerPublishedPhotosRT();
}

// listen for changes since the last photo in the cache.
const latestPhoto = _.maxBy(geojson.features, (photo) => {
return photo.properties.updated;
});
async registerPublishedPhotosRT() {
if (this.unregisterPublishedPhotosRT) {
await this.unregisterPublishedPhotosRT();
}

const lastUpdated = _.get(latestPhoto, "properties.updated");
this.unregisterPublishedPhotosRT = dbFirebase.publishedPhotosRT(
this.addFeature,
this.modifyFeature,
this.removeFeature,
(error) => {
console.log(error);
alert(error);
window.location.reload();
},
lastUpdated
);
} else {
// ??? TODO ????: fetch at least 100 photos, just to show something in the map.... otherwise it will show "LOADING PHOTOS"
// ...
this.fetchPhotos();
}
})
.catch(console.error);
// The following line should speedup things. It reads all the photos until before trigger the RT listener
await this.fetchPhotos(false, this.calculateLastUpdate());

this.unregisterPublishedPhotosRT = dbFirebase.publishedPhotosRT(
this.addFeature,
this.modifyFeature,
this.removeFeature,
(error) => {
console.log(error);
alert(error);
window.location.reload();
},
this.calculateLastUpdate()
);
}

fetchPhotos(fromAPI = true) {
dbFirebase
.fetchPhotos(fromAPI)
.then(async (photos) => {
let lastUpdated = new Date(null);
calculateLastUpdate() {
let lastUpdated = new Date(null);
if (this.state.geojson) {
const latestPhoto = _.maxBy(this.state.geojson.features, (photo) => {
return photo.properties.updated;
});
lastUpdated = _.get(latestPhoto, "properties.updated");
}
return lastUpdated;
}

async fetchPhotos(fromAPI = true, lastUpdate = new Date(null)) {
return dbFirebase
.fetchPhotos(fromAPI, lastUpdate)
.then((photos) => {
_.forEach(photos, (photo) => {
this.addFeature(photo);
if (photo.updated > lastUpdated) {
lastUpdated = photo.updated;
}
});
this.delayedSaveGeojson();
// at this point we retrieve ALL the photos and we have the date of the last photo comming from the cache.
// So we listen for changes since then

if (this.unregisterPublishedPhotosRT) {
await this.unregisterPublishedPhotosRT();
}
this.unregisterPublishedPhotosRT = dbFirebase.publishedPhotosRT(
this.addFeature,
this.modifyFeature,
this.removeFeature,
(error) => {
console.log(error);
alert(error);
window.location.reload();
},
lastUpdated
);
})
.catch(console.error);
}
Expand Down Expand Up @@ -662,6 +642,8 @@ class App extends Component {

// it will open the "loading photos" message
this.setState({ geojson: null });

// fetch all the photos from firestore instead than from the CDN
this.fetchPhotos(false);
};

Expand Down
11 changes: 2 additions & 9 deletions src/features/firebase/dbFirebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,12 @@ const configObserver = (onNext, onError) => {
}, onError);
};

async function fetchStats() {
return fetch(appConfig.FIREBASE.apiURL + "/stats", {
mode: "cors",
}).then((response) => response.json());
}

/**
* Open reload all the photos using the REST API. In this way it will laverage CDN caching saving firestore quota.
*
* @param {*} fromAPI if true it will get it from the API which is very usefull for caching.
*/
async function fetchPhotos(fromAPI = true) {
async function fetchPhotos(fromAPI = true, sinceDate = new Date(null)) {
let photos = {};
if (fromAPI) {
const photosResponse = await axios.get(
Expand All @@ -119,9 +113,9 @@ async function fetchPhotos(fromAPI = true) {
const querySnapshot = await firestore
.collection("photos")
.where("published", "==", true)
.where("updated", ">=", sinceDate)
.get();
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
photos[doc.id] = convertFirebaseTimestampFieldsIntoDate(doc.data());
});
}
Expand Down Expand Up @@ -404,7 +398,6 @@ function buildStorageUrl(path) {
const rtn = {
onConnectionStateChanged,
publishedPhotosRT,
fetchStats,
fetchFeedbacks,
fetchPhotos,
getUser,
Expand Down

0 comments on commit a0d5a42

Please sign in to comment.