Skip to content

Commit

Permalink
Fix album mapping by using a new caching mechanism
Browse files Browse the repository at this point in the history
We were still partially using the old caching mechanism used to map the entire filesystem before loading anything. This led to holes in the mapping as well as lots of redundant an partial information being stored.
This new approach is custom made and can probably still be improved
Fixes #206
  • Loading branch information
oparoz committed Jul 7, 2015
1 parent a85728b commit 2011fc1
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 80 deletions.
8 changes: 5 additions & 3 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ $(document).ready(function () {
$.getJSON(Gallery.utility.buildGalleryUrl('config', '', {}))
.then(function (config) {
Gallery.config = new Gallery.Config(config);
Gallery.getFiles().then(function () {
var currentLocation = window.location.href.split('#')[1] || '';
Gallery.getFiles(currentLocation).then(function () {
Gallery.activeSlideShow = new SlideShow();
$.when(Gallery.activeSlideShow.init(false, null))
.then(function () {
Expand Down Expand Up @@ -86,15 +87,16 @@ $(document).ready(function () {
window.onhashchange = function () {
"use strict";
// The hash location is ALWAYS encoded
var path = decodeURIComponent(window.location.href.split('#')[1] || '');
var currentLocation = window.location.href.split('#')[1] || '';
var path = decodeURIComponent(currentLocation);
var albumPath = OC.dirname(path);
if (Gallery.albumMap[path]) {
albumPath = path;
} else if (!Gallery.albumMap[albumPath]) {
albumPath = '';
}
if (Gallery.currentAlbum !== null && Gallery.currentAlbum !== albumPath) {
Gallery.getFiles().done(function () {
Gallery.getFiles(currentLocation).done(function () {
Gallery.refresh(path, albumPath);
});
} else {
Expand Down
199 changes: 123 additions & 76 deletions js/gallery.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,25 @@
(function (OC, $, t) {
"use strict";
var Gallery = {
images: [],
currentAlbum: null,
config: {},
/** Map of the whole gallery, built as we navigate through folders */
albumMap: {},
/** Used to pick an image based on the URL */
imageMap: {},
albumCache: {},
appName: 'galleryplus',
token: undefined,
activeSlideShow: null,
buttonsWidth: 320,
browserToolbarHeight: 150,

/**
* Builds a map of the albums located in the current folder
*
* @param {string} path
*
* @returns {Album}
*/
getAlbum: function (path) {
if (!Gallery.albumMap[path]) {
Gallery.albumMap[path] = new Album(path, [], [], OC.basename(path));
// Attaches this album as a sub-album to the parent folder
if (path !== '') {
var parent = OC.dirname(path);
if (parent === path) {
parent = '';
}
Gallery.getAlbum(parent).subAlbums.push(Gallery.albumMap[path]);
}
}
return Gallery.albumMap[path];
},

/**
* Refreshes the view and starts the slideshow if required
*
* @param {string} path
* @param {string} albumPath
*/
refresh: function (path, albumPath) {

// FIXME DEBUG CODE
console.log('refresh albumPath', albumPath);

if (Gallery.currentAlbum !== albumPath) {
Gallery.view.init(albumPath);
}
Expand All @@ -64,18 +38,20 @@
/**
* Retrieves information about all the images and albums located in the current folder
*
* @param {string} currentLocation
*
* @returns {*}
*/
getFiles: function () {
var album, image, albumEtag;
Gallery.images = [];
Gallery.albumMap = {};
Gallery.imageMap = {};
var currentLocation = window.location.href.split('#')[1] || '';
var albumCache = Gallery.albumCache[decodeURIComponent(currentLocation)];
getFiles: function (currentLocation) {
// Checks if we've visited this location before ands saves the etag to use for
// comparison later
var albumEtag;
var albumCache = Gallery.albumMap[decodeURIComponent(currentLocation)];
if (!$.isEmptyObject(albumCache)) {
albumEtag = albumCache.etag;
}

// Sends the request to the server
var params = {
location: currentLocation,
mediatypes: Gallery.config.getMediaTypes(),
Expand All @@ -85,49 +61,14 @@
// Only use the folder as a GET parameter and not as part of the URL
var url = Gallery.utility.buildGalleryUrl('files', '', params);
return $.getJSON(url).then(function (/**{albuminfo}*/ data) {
var path = null;
var fileId = null;
var mimeType = null;
var mTime = null;
var etag = null;
var files = null;
var albumInfo = data.albuminfo;
Gallery.config.setAlbumConfig(albumInfo);
if (albumInfo.etag === albumEtag) {
Gallery.images = albumCache.images;
// Both the folder and the etag have to match
if ((decodeURIComponent(currentLocation) === albumInfo.path)
&& (albumInfo.etag === albumEtag)) {
Gallery.imageMap = albumCache.imageMap;
Gallery.albumMap = albumCache.albumMap;
} else {
files = data.files;
if (files.length > 0) {
for (var i = 0; i < files.length; i++) {
path = files[i].path;
fileId = files[i].fileid;
mimeType = files[i].mimetype;
mTime = files[i].mtime;
etag = files[i].etag;

Gallery.images.push(path);

image = new GalleryImage(path, path, fileId, mimeType, mTime, etag);
var dir = OC.dirname(path);
if (dir === path) {
dir = '';
}
album = Gallery.getAlbum(dir);
album.images.push(image);
Gallery.imageMap[image.path] = image;
}
Gallery.albumCache[albumInfo.path] = {
etag: albumInfo.etag,
files: files,
images: Gallery.images,
imageMap: Gallery.imageMap,
albumMap: Gallery.albumMap
};
} else {
Gallery.getAlbum(albumInfo.path);
}
Gallery.mapFiles(data);
}
}, function () {
// Triggered if we couldn't find a working folder
Expand All @@ -137,6 +78,114 @@
});
},

/**
* Builds the album's model
*
* @param {{albuminfo:Array, files:Array}} data
*/
mapFiles: function (data) {
Gallery.imageMap = {};
var image = null;
var path = null;
var fileId = null;
var mimeType = null;
var mTime = null;
var etag = null;
var albumInfo = data.albuminfo;
var currentLocation = albumInfo.path;
// This adds a new node to the map for each parent album
Gallery.mapStructure(currentLocation);
var files = data.files;
if (files.length > 0) {
var subAlbumCache = {};
var albumCache = Gallery.albumMap[currentLocation]
= new Album(currentLocation, [], [], OC.basename(currentLocation));
for (var i = 0; i < files.length; i++) {
path = files[i].path;
fileId = files[i].fileid;
mimeType = files[i].mimetype;
mTime = files[i].mtime;
etag = files[i].etag;

image = new GalleryImage(path, path, fileId, mimeType, mTime, etag);

// Determines the folder name for the image
var dir = OC.dirname(path);
if (dir === path) {
dir = '';
}
if (dir === currentLocation) {
// The image belongs to the current album, so we can add it directly
albumCache.images.push(image);
} else {
// The image belongs to a sub-album, so we create a sub-album cache if it
// doesn't exist and add images to it
if (!subAlbumCache[dir]) {
subAlbumCache[dir] = new Album(dir, [], [],
OC.basename(dir));
}
subAlbumCache[dir].images.push(image);

// The sub-album also has to be added to the global map
if (!Gallery.albumMap[dir]) {
Gallery.albumMap[dir] = {};
}
}
Gallery.imageMap[image.path] = image;
}
// Adds the sub-albums to the current album
Gallery.mapAlbums(albumCache, subAlbumCache);

// Caches the information which is not already cached
albumCache.etag = albumInfo.etag;
albumCache.imageMap = Gallery.imageMap;
}
},

/**
* Adds every album leading the current folder to a global album map
*
* Per example, if you have Root/Folder1/Folder2/CurrentFolder then the map will contain:
* * Root
* * Folder1
* * Folder2
* * CurrentFolder
*
* Every time a new location is loaded, the map is completed
*
*
* @param {string} path
*
* @returns {Album}
*/
mapStructure: function (path) {
if (!Gallery.albumMap[path]) {
Gallery.albumMap[path] = {};
// Builds relationships between albums
if (path !== '') {
var parent = OC.dirname(path);
if (parent === path) {
parent = '';
}
Gallery.mapStructure(parent);
}
}
return Gallery.albumMap[path];
},

/**
* Adds the sub-albums to the current album
*
* @param {Album} albumCache
* @param {{Album}} subAlbumCache
*/
mapAlbums: function (albumCache, subAlbumCache) {
for (var j = 0, keys = Object.keys(subAlbumCache); j <
keys.length; j++) {
albumCache.subAlbums.push(subAlbumCache[keys[j]]);
}
},

/**
* Sorts albums and images based on user preferences
*/
Expand Down Expand Up @@ -242,8 +291,6 @@

/**
* Lets the user add the shared files to his ownCloud
*
* @param event
*/
showSaveForm: function () {
$(this).hide();
Expand Down
3 changes: 2 additions & 1 deletion js/galleryview.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@
* @param {string} albumPath
*/
init: function (albumPath) {
if (Gallery.images.length === 0) {
if ($.isEmptyObject(Gallery.imageMap)) {
//Gallery.showEmpty();
// FIXME Make the diff between a root and deep folder
this.clear();
Gallery.showEmptyFolder();
Gallery.currentAlbum = albumPath;
this.breadcrumb = new Gallery.Breadcrumb(albumPath);
Expand Down

0 comments on commit 2011fc1

Please sign in to comment.