diff --git a/dashboard-ui/apiclient/apiclient.js b/dashboard-ui/apiclient/apiclient.js index 5500913ecb..1fa44dc771 100644 --- a/dashboard-ui/apiclient/apiclient.js +++ b/dashboard-ui/apiclient/apiclient.js @@ -3449,6 +3449,56 @@ }); }; + self.reportOfflineActions = function (actions) { + + if (!actions) { + throw new Error("null actions"); + } + + var url = self.getUrl("Sync/OfflineActions"); + + return self.ajax({ + type: "POST", + data: JSON.stringify(actions), + contentType: "application/json", + url: url + }); + }; + + self.syncData = function (data) { + + if (!data) { + throw new Error("null data"); + } + + var url = self.getUrl("Sync/Data"); + + return self.ajax({ + type: "POST", + data: JSON.stringify(data), + contentType: "application/json", + url: url, + dataType: "json" + }); + }; + + self.getReadySyncItems = function (deviceId) { + + if (!deviceId) { + throw new Error("null deviceId"); + } + + var url = self.getUrl("Sync/Items/Ready", { + TargetId: deviceId + }); + + return self.ajax({ + type: "GET", + url: url, + dataType: "json" + }); + }; + /** * Reports a user has stopped playing an item * @param {String} userId diff --git a/dashboard-ui/apiclient/localassetmanager.js b/dashboard-ui/apiclient/localassetmanager.js index fe948c9046..91a16f832a 100644 --- a/dashboard-ui/apiclient/localassetmanager.js +++ b/dashboard-ui/apiclient/localassetmanager.js @@ -16,10 +16,45 @@ return deferred.promise(); } + function getOfflineActions(serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, [[]]); + return deferred.promise(); + } + + function getServerItemIds(serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, [[]]); + return deferred.promise(); + } + + function removeLocalItem(itemId, serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, []); + return deferred.promise(); + } + + function getLocalItem(itemId, serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, []); + return deferred.promise(); + } + + function addOrUpdateLocalItem(localItem) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, []); + return deferred.promise(); + } + window.LocalAssetManager = { getLocalMediaSource: getLocalMediaSource, saveOfflineUser: saveOfflineUser, - getCameraPhotos: getCameraPhotos + getCameraPhotos: getCameraPhotos, + getOfflineActions: getOfflineActions, + getServerItemIds: getServerItemIds, + removeLocalItem: removeLocalItem, + getLocalItem: getLocalItem, + addOrUpdateLocalItem: addOrUpdateLocalItem }; })(); \ No newline at end of file diff --git a/dashboard-ui/apiclient/sync/mediasync.js b/dashboard-ui/apiclient/sync/mediasync.js index 315a0d17d2..7edb165137 100644 --- a/dashboard-ui/apiclient/sync/mediasync.js +++ b/dashboard-ui/apiclient/sync/mediasync.js @@ -4,20 +4,20 @@ var self = this; - self.sync = function (apiClient) { + self.sync = function (apiClient, serverInfo) { var deferred = DeferredBuilder.Deferred(); - reportOfflineActions(apiClient).done(function () { + reportOfflineActions(apiClient, serverInfo).done(function () { // Do the first data sync - syncData(apiClient, false).done(function () { + syncData(apiClient, serverInfo, false).done(function () { // Download new content getNewMedia(apiClient).done(function () { // Do the second data sync - syncData(apiClient, false).done(function () { + syncData(apiClient, serverInfo, false).done(function () { deferred.resolve(); @@ -32,29 +32,227 @@ return deferred.promise(); }; - function reportOfflineActions(apiClient) { + function reportOfflineActions(apiClient, serverInfo) { + + Logger.log('Begin reportOfflineActions'); var deferred = DeferredBuilder.Deferred(); - deferred.resolve(); + require(['localassetmanager'], function () { + + LocalAssetManager.getOfflineActions(serverInfo.Id).done(function (actions) { + + if (!actions.length) { + deferred.resolve(); + return; + } + + apiClient.reportOfflineActions(actions).done(function () { + + deferred.resolve(); + + }).fail(getOnFail(deferred)); + + }).fail(getOnFail(deferred)); + }); return deferred.promise(); } - function syncData(apiClient, syncUserItemAccess) { + function syncData(apiClient, serverInfo, syncUserItemAccess) { + + Logger.log('Begin syncData'); var deferred = DeferredBuilder.Deferred(); + require(['localassetmanager'], function () { + + LocalAssetManager.getServerItemIds(serverInfo.Id).done(function (localIds) { + + var request = { + TargetId: apiClient.deviceId(), + LocalItemIds: localIds, + OfflineUserIds: (serverInfo.Users || []).map(function (u) { return u.Id; }) + }; + + apiClient.syncData(request).done(function (result) { + + afterSyncData(apiClient, serverInfo, syncUserItemAccess, result, deferred); + + }).fail(getOnFail(deferred)); + + }).fail(getOnFail(deferred)); + }); + + return deferred.promise(); + } + + function afterSyncData(apiClient, serverInfo, enableSyncUserItemAccess, syncDataResult, deferred) { + + Logger.log('Begin afterSyncData'); + + removeLocalItems(syncDataResult, serverInfo.Id).done(function (result) { + + if (enableSyncUserItemAccess) { + syncUserItemAccess(syncDataResult, serverInfo.Id).done(function () { + + deferred.resolve(); + + }).fail(getOnFail(deferred)); + } + else { + deferred.resolve(); + } + + }).fail(getOnFail(deferred)); + deferred.resolve(); + } + + function removeLocalItems(syncDataResult, serverId) { + + Logger.log('Begin removeLocalItems'); + + var deferred = DeferredBuilder.Deferred(); + + removeNextLocalItem(syncDataResult.ItemIdsToRemove, 0, serverId, deferred); + + return deferred.promise(); + } + + function removeNextLocalItem(itemIdsToRemove, index, serverId, deferred) { + + var length = itemIdsToRemove.length; + + if (index >= length) { + + deferred.resolve(); + return; + } + + removeLocalItem(itemIdsToRemove[index], serverId).done(function () { + + removeNextLocalItem(itemIdsToRemove, index + 1, serverId, deferred); + }).fail(function () { + removeNextLocalItem(itemIdsToRemove, index + 1, serverId, deferred); + }); + } + + function removeLocalItem(itemId, serverId) { + + Logger.log('Begin removeLocalItem'); + + var deferred = DeferredBuilder.Deferred(); + + require(['localassetmanager'], function () { + + LocalAssetManager.removeLocalItem(itemId, serverId).done(function (localIds) { + + deferred.resolve(); + + }).fail(getOnFail(deferred)); + }); return deferred.promise(); } function getNewMedia(apiClient) { + Logger.log('Begin getNewMedia'); + var deferred = DeferredBuilder.Deferred(); + apiClient.getReadySyncItems(apiClient.deviceId()).done(function (jobItems) { + + getNextNewItem(jobItems, 0, apiClient, deferred); + + }).fail(getOnFail(deferred)); + + return deferred.promise(); + } + + function getNextNewItem(jobItems, index, apiClient, deferred) { + + var length = jobItems.length; + + if (index >= length) { + + deferred.resolve(); + return; + } + + getNewItem(jobItems[index], apiClient).done(function () { + + getNextNewItem(jobItems, index + 1, apiClient, deferred); + }).fail(function () { + getNextNewItem(jobItems, index + 1, apiClient, deferred); + }); + } + + function getNewItem(jobItem, apiClient) { + var deferred = DeferredBuilder.Deferred(); deferred.resolve(); + return deferred.promise(); + } + + function syncUserItemAccess(syncDataResult, serverId) { + Logger.log('Begin syncUserItemAccess'); + + var deferred = DeferredBuilder.Deferred(); + + var itemIds = []; + for (var id in syncDataResult.ItemUserAccess) { + itemIds.push(id); + } + + syncNextUserAccessForItem(itemIds, 0, syncDataResult, serverId, deferred); + + return deferred.promise(); + } + + function syncNextUserAccessForItem(itemIds, index, syncDataResult, serverId, deferred) { + + var length = itemIds.length; + + if (index >= length) { + + deferred.resolve(); + return; + } + + syncUserAccessForItem(itemIds[index], syncDataResult).done(function () { + + syncNextUserAccessForItem(itemIds, index + 1, syncDataResult, serverId, deferred); + }).fail(function () { + syncNextUserAccessForItem(itemIds, index + 1, syncDataResult, serverId, deferred); + }); + } + + function syncUserAccessForItem(itemId, syncDataResult) { + Logger.log('Begin syncUserAccessForItem'); + + var deferred = DeferredBuilder.Deferred(); + + require(['localassetmanager'], function () { + + LocalAssetManager.getLocalItem(itemId, serverId).done(function (localItem) { + + var userIdsWithAccess = syncDataResult.ItemUserAccess[itemId]; + + if (userIdsWithAccess.join(',') == localItem.UserIdsWithAccess.join(',')) { + // Hasn't changed, nothing to do + deferred.resolve(); + } + else { + + localItem.UserIdsWithAccess = userIdsWithAccess; + localAssetManager.addOrUpdateLocalItem(localItem).done(function () { + deferred.resolve(); + }).fail(getOnFail(deferred)); + } + + }).fail(getOnFail(deferred)); + }); return deferred.promise(); } diff --git a/dashboard-ui/apiclient/sync/serversync.js b/dashboard-ui/apiclient/sync/serversync.js index f212503229..51671e8d4d 100644 --- a/dashboard-ui/apiclient/sync/serversync.js +++ b/dashboard-ui/apiclient/sync/serversync.js @@ -87,7 +87,7 @@ var apiClient = connectionManager.getApiClient(server.Id); - new MediaBrowser.MediaSync().sync(apiClient).done(function () { + new MediaBrowser.MediaSync().sync(apiClient, server).done(function () { Logger.log("MediaSync succeeded to server: " + server.Id); diff --git a/dashboard-ui/cordova/android/localassetmanager.js b/dashboard-ui/cordova/android/localassetmanager.js deleted file mode 100644 index 01820a5a2d..0000000000 --- a/dashboard-ui/cordova/android/localassetmanager.js +++ /dev/null @@ -1,31 +0,0 @@ -(function () { - - function getLocalMediaSource(serverId, itemId) { - var json = ApiClientBridge.getLocalMediaSource(serverId, itemId); - - if (json) { - return JSON.parse(json); - } - - return null; - } - - function saveOfflineUser(user) { - var deferred = DeferredBuilder.Deferred(); - deferred.resolve(); - return deferred.promise(); - } - - function getCameraPhotos() { - var deferred = DeferredBuilder.Deferred(); - deferred.resolveWith(null, [[]]); - return deferred.promise(); - } - - window.LocalAssetManager = { - getLocalMediaSource: getLocalMediaSource, - saveOfflineUser: saveOfflineUser, - getCameraPhotos: getCameraPhotos - }; - -})(); \ No newline at end of file diff --git a/dashboard-ui/cordova/localassetmanager.js b/dashboard-ui/cordova/localassetmanager.js index 487181cfbe..e97bd41fe2 100644 --- a/dashboard-ui/cordova/localassetmanager.js +++ b/dashboard-ui/cordova/localassetmanager.js @@ -1,6 +1,16 @@ (function () { function getLocalMediaSource(serverId, itemId) { + + // android + if (window.ApiClientBridge) { + var json = ApiClientBridge.getLocalMediaSource(serverId, itemId); + + if (json) { + return JSON.parse(json); + } + } + return null; } @@ -36,10 +46,45 @@ return deferred.promise(); } + function getOfflineActions(serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, [[]]); + return deferred.promise(); + } + + function getServerItemIds(serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, [[]]); + return deferred.promise(); + } + + function removeLocalItem(itemId, serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, []); + return deferred.promise(); + } + + function getLocalItem(itemId, serverId) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, []); + return deferred.promise(); + } + + function addOrUpdateLocalItem(localItem) { + var deferred = DeferredBuilder.Deferred(); + deferred.resolveWith(null, []); + return deferred.promise(); + } + window.LocalAssetManager = { getLocalMediaSource: getLocalMediaSource, saveOfflineUser: saveOfflineUser, - getCameraPhotos: getCameraPhotos + getCameraPhotos: getCameraPhotos, + getOfflineActions: getOfflineActions, + getServerItemIds: getServerItemIds, + removeLocalItem: removeLocalItem, + getLocalItem: getLocalItem, + addOrUpdateLocalItem: addOrUpdateLocalItem }; })(); \ No newline at end of file diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index 6bd8eabcda..0175e9119f 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -1103,7 +1103,12 @@ outerHtml += ''; - html += '