mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
update sync scripts
This commit is contained in:
parent
ec06f3cc61
commit
fc210d8ad2
18 changed files with 1394 additions and 564 deletions
|
@ -16,12 +16,12 @@
|
|||
},
|
||||
"devDependencies": {},
|
||||
"ignore": [],
|
||||
"version": "1.1.98",
|
||||
"_release": "1.1.98",
|
||||
"version": "1.1.101",
|
||||
"_release": "1.1.101",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.1.98",
|
||||
"commit": "2c96ef1ead7a5e4a4613f5f73bcf494095c778dc"
|
||||
"tag": "1.1.101",
|
||||
"commit": "ee067b87820c7fc8b43499f48b3035fd0e594032"
|
||||
},
|
||||
"_source": "https://github.com/MediaBrowser/Emby.ApiClient.Javascript.git",
|
||||
"_target": "^1.1.51",
|
||||
|
|
114
dashboard-ui/bower_components/emby-apiclient/nullassetmanager.js
vendored
Normal file
114
dashboard-ui/bower_components/emby-apiclient/nullassetmanager.js
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
define([], function () {
|
||||
'use strict';
|
||||
|
||||
function getLocalMediaSource(serverId, itemId) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
function saveOfflineUser(user) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function deleteOfflineUser(id) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function getCameraPhotos() {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
function recordUserAction(action) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function getUserActions(serverId) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
function deleteUserAction(action) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function deleteUserActions(actions) {
|
||||
//TODO:
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function getServerItemIds(serverId) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
function removeLocalItem(localItem) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function getLocalItem(itemId, serverId) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function addOrUpdateLocalItem(localItem) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function createLocalItem(libraryItem, serverInfo, jobItem) {
|
||||
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
function downloadFile(url, localPath) {
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function downloadSubtitles(url, localItem, subtitleStreamh) {
|
||||
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
||||
function hasImage(serverId, itemId, imageTag) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
function downloadImage(url, serverId, itemId, imageTag) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
function fileExists(path) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
function translateFilePath(path) {
|
||||
return Promise.resolve(path);
|
||||
}
|
||||
|
||||
function getLocalFilePath(path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getLocalItemById(id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
getLocalItem: getLocalItem,
|
||||
saveOfflineUser: saveOfflineUser,
|
||||
deleteOfflineUser: deleteOfflineUser,
|
||||
getCameraPhotos: getCameraPhotos,
|
||||
recordUserAction: recordUserAction,
|
||||
getUserActions: getUserActions,
|
||||
deleteUserAction: deleteUserAction,
|
||||
deleteUserActions: deleteUserActions,
|
||||
getServerItemIds: getServerItemIds,
|
||||
removeLocalItem: removeLocalItem,
|
||||
addOrUpdateLocalItem: addOrUpdateLocalItem,
|
||||
createLocalItem: createLocalItem,
|
||||
downloadFile: downloadFile,
|
||||
downloadSubtitles: downloadSubtitles,
|
||||
hasImage: hasImage,
|
||||
downloadImage: downloadImage,
|
||||
fileExists: fileExists,
|
||||
translateFilePath: translateFilePath,
|
||||
getLocalFilePath: getLocalFilePath,
|
||||
getLocalItemById: getLocalItemById
|
||||
};
|
||||
});
|
42
dashboard-ui/bower_components/emby-apiclient/sync/filerepository.js
vendored
Normal file
42
dashboard-ui/bower_components/emby-apiclient/sync/filerepository.js
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
define([], function () {
|
||||
'use strict';
|
||||
|
||||
function getValidFileName(path) {
|
||||
|
||||
// TODO
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
function getFullLocalPath(pathArray) {
|
||||
|
||||
// TODO
|
||||
return pathArray.join('/');
|
||||
|
||||
}
|
||||
|
||||
function deleteFile(path) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function deleteDirectory(path) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function fileExists(path) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function getItemFileSize(path) {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
|
||||
return {
|
||||
getValidFileName: getValidFileName,
|
||||
getFullLocalPath: getFullLocalPath,
|
||||
deleteFile: deleteFile,
|
||||
deleteDirectory: deleteDirectory,
|
||||
fileExists: fileExists,
|
||||
getItemFileSize: getItemFileSize
|
||||
};
|
||||
});
|
97
dashboard-ui/bower_components/emby-apiclient/sync/itemrepository.js
vendored
Normal file
97
dashboard-ui/bower_components/emby-apiclient/sync/itemrepository.js
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
define(['idb'], function () {
|
||||
'use strict';
|
||||
|
||||
// Database name
|
||||
var dbName = "items";
|
||||
|
||||
// Database version
|
||||
var dbVersion = 1;
|
||||
|
||||
var dbPromise;
|
||||
|
||||
function setup() {
|
||||
|
||||
dbPromise = idb.open(dbName, dbVersion, function (upgradeDB) {
|
||||
// Note: we don't use 'break' in this switch statement,
|
||||
// the fall-through behaviour is what we want.
|
||||
switch (upgradeDB.oldVersion) {
|
||||
case 0:
|
||||
upgradeDB.createObjectStore(dbName);
|
||||
//case 1:
|
||||
// upgradeDB.createObjectStore('stuff', { keyPath: '' });
|
||||
}
|
||||
}); //.then(db => console.log("DB opened!", db));
|
||||
}
|
||||
|
||||
function getServerItemIds(serverId) {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).getAll(null, 10000).then(function (all) {
|
||||
return all.filter(function (item) {
|
||||
return item.ServerId === serverId;
|
||||
}).map(function (item2) {
|
||||
return item2.ItemId;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getServerIds(serverId) {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).getAll(null, 10000).then(function (all) {
|
||||
return all.filter(function (item) {
|
||||
return item.ServerId === serverId;
|
||||
}).map(function (item2) {
|
||||
return item2.Id;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).getAll(null, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
function get(key) {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).get(key);
|
||||
});
|
||||
}
|
||||
|
||||
function set(key, val) {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).put(val, key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
function remove(key) {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).delete(key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
function clear() {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).clear(key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
return {
|
||||
get: get,
|
||||
set: set,
|
||||
remove: remove,
|
||||
clear: clear,
|
||||
getAll: getAll,
|
||||
getServerItemIds: getServerItemIds,
|
||||
getServerIds: getServerIds
|
||||
};
|
||||
});
|
|
@ -1,471 +1,488 @@
|
|||
define(['localassetmanager'], function (LocalAssetManager) {
|
||||
define(['localassetmanager'], function (localassetmanager) {
|
||||
'use strict';
|
||||
|
||||
function processDownloadStatus(apiClient, serverInfo, options) {
|
||||
|
||||
console.log('[mediasync] Begin processDownloadStatus');
|
||||
|
||||
return localassetmanager.getServerItems(serverInfo.Id).then(function (items) {
|
||||
|
||||
console.log('[mediasync] Begin processDownloadStatus getServerItems completed');
|
||||
|
||||
var progressItems = items.filter(function (item) {
|
||||
return item.SyncStatus === 'transferring' || item.SyncStatus === 'queued';
|
||||
});
|
||||
|
||||
var p = Promise.resolve();
|
||||
var cnt = 0;
|
||||
|
||||
progressItems.forEach(function (item) {
|
||||
p = p.then(function () {
|
||||
return reportTransfer(apiClient, item);
|
||||
});
|
||||
cnt++;
|
||||
});
|
||||
|
||||
return p.then(function () {
|
||||
console.log('[mediasync] Exit processDownloadStatus. Items reported: ' + cnt.toString());
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function reportTransfer(apiClient, item) {
|
||||
|
||||
return localassetmanager.getItemFileSize(item.LocalPath).then(function (size) {
|
||||
// The background transfer service on Windows leaves the file empty (size = 0) until it
|
||||
// has been downloaded completely
|
||||
if (size > 0) {
|
||||
return apiClient.reportSyncJobItemTransferred(item.SyncJobItemId).then(function () {
|
||||
item.SyncStatus = 'synced';
|
||||
return localassetmanager.addOrUpdateLocalItem(item);
|
||||
}, function (error) {
|
||||
console.error("[mediasync] Mediasync error on reportSyncJobItemTransferred", error);
|
||||
item.SyncStatus = 'error';
|
||||
return localassetmanager.addOrUpdateLocalItem(item);
|
||||
});
|
||||
} else {
|
||||
return localassetmanager.isDownloadInQueue(item.SyncJobItemId).then(function (result) {
|
||||
if (result) {
|
||||
// just wait for completion
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
console.log("[mediasync] reportTransfer: Size is 0 and download no longer in queue. Deleting item.");
|
||||
return localassetmanager.removeLocalItem(item).then(function () {
|
||||
console.log('[mediasync] reportTransfer: Item deleted.');
|
||||
return Promise.resolve();
|
||||
}, function (err2) {
|
||||
console.log('[mediasync] reportTransfer: Failed to delete item.', error);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}, function (error) {
|
||||
|
||||
console.error('[mediasync] reportTransfer: error on getItemFileSize. Deleting item.', error);
|
||||
return localassetmanager.removeLocalItem(item).then(function () {
|
||||
console.log('[mediasync] reportTransfer: Item deleted.');
|
||||
return Promise.resolve();
|
||||
}, function (err2) {
|
||||
console.log('[mediasync] reportTransfer: Failed to delete item.', error);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function reportOfflineActions(apiClient, serverInfo) {
|
||||
|
||||
console.log('[mediasync] Begin reportOfflineActions');
|
||||
|
||||
return localassetmanager.getUserActions(serverInfo.Id).then(function (actions) {
|
||||
|
||||
if (!actions.length) {
|
||||
console.log('[mediasync] Exit reportOfflineActions (no actions)');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return apiClient.reportOfflineActions(actions).then(function () {
|
||||
|
||||
return localassetmanager.deleteUserActions(actions).then(function () {
|
||||
console.log('[mediasync] Exit reportOfflineActions (actions reported and deleted.)');
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
|
||||
// delete those actions even on failure, because if the error is caused by
|
||||
// the action data itself, this could otherwise lead to a situation that
|
||||
// never gets resolved
|
||||
console.error('[mediasync] error on apiClient.reportOfflineActions: ' + err.toString());
|
||||
return localassetmanager.deleteUserActions(actions);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function syncData(apiClient, serverInfo, syncUserItemAccess) {
|
||||
|
||||
console.log('[mediasync] Begin syncData');
|
||||
|
||||
return localassetmanager.getServerItems(serverInfo.Id).then(function (items) {
|
||||
|
||||
var completedItems = items.filter(function (item) {
|
||||
return (item) && ((item.SyncStatus === 'synced') || (item.SyncStatus === 'error'));
|
||||
});
|
||||
|
||||
var request = {
|
||||
TargetId: apiClient.deviceId(),
|
||||
LocalItemIds: completedItems.map(function (xitem) { return xitem.ItemId; }),
|
||||
OfflineUserIds: (serverInfo.Users || []).map(function (u) { return u.Id; })
|
||||
};
|
||||
|
||||
return apiClient.syncData(request).then(function (result) {
|
||||
|
||||
return afterSyncData(apiClient, serverInfo, syncUserItemAccess, result).then(function () {
|
||||
return Promise.resolve();
|
||||
}, function () {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function afterSyncData(apiClient, serverInfo, enableSyncUserItemAccess, syncDataResult) {
|
||||
|
||||
console.log('[mediasync] Begin afterSyncData');
|
||||
|
||||
var p = Promise.resolve();
|
||||
|
||||
if (syncDataResult.ItemIdsToRemove) {
|
||||
syncDataResult.ItemIdsToRemove.forEach(function (itemId) {
|
||||
p = p.then(function () {
|
||||
return removeLocalItem(itemId, serverInfo.Id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (enableSyncUserItemAccess) {
|
||||
p = p.then(function () {
|
||||
return syncUserItemAccess(syncDataResult, serverInfo.Id);
|
||||
});
|
||||
}
|
||||
|
||||
return p.then(function () {
|
||||
console.log('[mediasync] Exit afterSyncData');
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function removeLocalItem(itemId, serverId) {
|
||||
|
||||
console.log('[mediasync] Begin removeLocalItem');
|
||||
|
||||
return localassetmanager.getLocalItem(serverId, itemId).then(function (item) {
|
||||
|
||||
if (item) {
|
||||
return localassetmanager.removeLocalItem(item);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function getNewMedia(apiClient, serverInfo, options) {
|
||||
|
||||
console.log('[mediasync] Begin getNewMedia');
|
||||
|
||||
return apiClient.getReadySyncItems(apiClient.deviceId()).then(function (jobItems) {
|
||||
|
||||
var p = Promise.resolve();
|
||||
|
||||
jobItems.forEach(function (jobItem) {
|
||||
p = p.then(function () {
|
||||
return getNewItem(jobItem, apiClient, serverInfo, options);
|
||||
});
|
||||
});
|
||||
|
||||
return p.then(function () {
|
||||
console.log('[mediasync] Exit getNewMedia');
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getNewItem(jobItem, apiClient, serverInfo, options) {
|
||||
|
||||
console.log('[mediasync] Begin getNewItem');
|
||||
|
||||
var libraryItem = jobItem.Item;
|
||||
|
||||
return localassetmanager.getLocalItem(serverInfo.Id, libraryItem.Id).then(function (existingItem) {
|
||||
|
||||
console.log('[mediasync] getNewItem.getLocalItem completed');
|
||||
|
||||
if (existingItem) {
|
||||
if (existingItem.SyncStatus === 'queued' || existingItem.SyncStatus === 'transferring' || existingItem.SyncStatus === 'synced') {
|
||||
console.log('[mediasync] getNewItem.getLocalItem found existing item');
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[mediasync] getNewItem.getLocalItem no existing item found');
|
||||
|
||||
return localassetmanager.createLocalItem(libraryItem, serverInfo, jobItem).then(function (localItem) {
|
||||
|
||||
console.log('[mediasync] getNewItem.createLocalItem completed');
|
||||
|
||||
localItem.SyncStatus = 'queued';
|
||||
|
||||
return downloadMedia(apiClient, jobItem, localItem, options).then(function () {
|
||||
|
||||
return getImages(apiClient, jobItem, localItem).then(function () {
|
||||
|
||||
return getSubtitles(apiClient, jobItem, localItem);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function downloadMedia(apiClient, jobItem, localItem, options) {
|
||||
|
||||
console.log('[mediasync] Begin downloadMedia');
|
||||
|
||||
var url = apiClient.getUrl("Sync/JobItems/" + jobItem.SyncJobItemId + "/File", {
|
||||
api_key: apiClient.accessToken()
|
||||
});
|
||||
|
||||
var localPath = localItem.LocalPath;
|
||||
|
||||
console.log('[mediasync] Downloading media. Url: ' + url + '. Local path: ' + localPath);
|
||||
|
||||
options = options || {};
|
||||
|
||||
return localassetmanager.downloadFile(url, localItem).then(function (filename) {
|
||||
|
||||
localItem.SyncStatus = 'transferring';
|
||||
return localassetmanager.addOrUpdateLocalItem(localItem);
|
||||
});
|
||||
}
|
||||
|
||||
function getImages(apiClient, jobItem, localItem) {
|
||||
|
||||
console.log('[mediasync] Begin getImages');
|
||||
|
||||
return getNextImage(0, apiClient, localItem);
|
||||
}
|
||||
|
||||
function getNextImage(index, apiClient, localItem) {
|
||||
|
||||
console.log('[mediasync] Begin getNextImage');
|
||||
|
||||
//if (index >= 4) {
|
||||
|
||||
// deferred.resolve();
|
||||
// return;
|
||||
//}
|
||||
|
||||
// Just for now while media syncing gets worked out
|
||||
return Promise.resolve();
|
||||
|
||||
//var libraryItem = localItem.Item;
|
||||
|
||||
//var serverId = libraryItem.ServerId;
|
||||
//var itemId = null;
|
||||
//var imageTag = null;
|
||||
//var imageType = "Primary";
|
||||
|
||||
//switch (index) {
|
||||
|
||||
// case 0:
|
||||
// itemId = libraryItem.Id;
|
||||
// imageType = "Primary";
|
||||
// imageTag = (libraryItem.ImageTags || {})["Primary"];
|
||||
// break;
|
||||
// case 1:
|
||||
// itemId = libraryItem.SeriesId;
|
||||
// imageType = "Primary";
|
||||
// imageTag = libraryItem.SeriesPrimaryImageTag;
|
||||
// break;
|
||||
// case 2:
|
||||
// itemId = libraryItem.SeriesId;
|
||||
// imageType = "Thumb";
|
||||
// imageTag = libraryItem.SeriesPrimaryImageTag;
|
||||
// break;
|
||||
// case 3:
|
||||
// itemId = libraryItem.AlbumId;
|
||||
// imageType = "Primary";
|
||||
// imageTag = libraryItem.AlbumPrimaryImageTag;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
//}
|
||||
|
||||
//if (!itemId || !imageTag) {
|
||||
// getNextImage(index + 1, apiClient, localItem, deferred);
|
||||
// return;
|
||||
//}
|
||||
|
||||
//downloadImage(apiClient, serverId, itemId, imageTag, imageType).then(function () {
|
||||
|
||||
// // For the sake of simplicity, limit to one image
|
||||
// deferred.resolve();
|
||||
// return;
|
||||
|
||||
// getNextImage(index + 1, apiClient, localItem, deferred);
|
||||
|
||||
//}, getOnFail(deferred));
|
||||
}
|
||||
|
||||
function downloadImage(apiClient, serverId, itemId, imageTag, imageType) {
|
||||
|
||||
console.log('[mediasync] Begin downloadImage');
|
||||
|
||||
return localassetmanager.hasImage(serverId, itemId, imageTag).then(function (hasImage) {
|
||||
|
||||
if (hasImage) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var imageUrl = apiClient.getImageUrl(itemId, {
|
||||
tag: imageTag,
|
||||
type: imageType,
|
||||
api_key: apiClient.accessToken()
|
||||
});
|
||||
|
||||
return localassetmanager.downloadImage(imageUrl, serverId, itemId, imageTag);
|
||||
});
|
||||
}
|
||||
|
||||
function getSubtitles(apiClient, jobItem, localItem) {
|
||||
|
||||
console.log('[mediasync] Begin getSubtitles');
|
||||
|
||||
if (!jobItem.Item.MediaSources.length) {
|
||||
console.log("[mediasync] Cannot download subtitles because video has no media source info.");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var files = jobItem.AdditionalFiles.filter(function (f) {
|
||||
return f.Type === 'Subtitles';
|
||||
});
|
||||
|
||||
var mediaSource = jobItem.Item.MediaSources[0];
|
||||
|
||||
var p = Promise.resolve();
|
||||
|
||||
files.forEach(function (file) {
|
||||
p = p.then(function () {
|
||||
return getItemSubtitle(file, apiClient, jobItem, localItem, mediaSource);
|
||||
});
|
||||
});
|
||||
|
||||
return p.then(function () {
|
||||
console.log('[mediasync] Exit getSubtitles');
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function getItemSubtitle(file, apiClient, jobItem, localItem, mediaSource) {
|
||||
|
||||
console.log('[mediasync] Begin getItemSubtitle');
|
||||
|
||||
var subtitleStream = mediaSource.MediaStreams.filter(function (m) {
|
||||
return m.Type === 'Subtitle' && m.Index === file.Index;
|
||||
})[0];
|
||||
|
||||
if (!subtitleStream) {
|
||||
|
||||
// We shouldn't get in here, but let's just be safe anyway
|
||||
console.log("[mediasync] Cannot download subtitles because matching stream info wasn't found.");
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var url = apiClient.getUrl("Sync/JobItems/" + jobItem.SyncJobItemId + "/AdditionalFiles", {
|
||||
Name: file.Name,
|
||||
api_key: apiClient.accessToken()
|
||||
});
|
||||
|
||||
var fileName = localassetmanager.getSubtitleSaveFileName(jobItem.OriginalFileName, subtitleStream.Language, subtitleStream.IsForced, subtitleStream.Codec);
|
||||
var localFilePath = localassetmanager.getLocalFilePath(localItem, fileName);
|
||||
|
||||
return localassetmanager.downloadSubtitles(url, localFilePath).then(function (subtitlePath) {
|
||||
|
||||
subtitleStream.Path = subtitlePath;
|
||||
return localassetmanager.addOrUpdateLocalItem(localItem);
|
||||
});
|
||||
}
|
||||
|
||||
return function () {
|
||||
|
||||
var self = this;
|
||||
|
||||
self.sync = function (apiClient, serverInfo, options) {
|
||||
|
||||
return reportOfflineActions(apiClient, serverInfo).then(function () {
|
||||
console.log("[mediasync]************************************* Start sync");
|
||||
|
||||
// Do the first data sync
|
||||
return syncData(apiClient, serverInfo, false).then(function () {
|
||||
return processDownloadStatus(apiClient, serverInfo, options).then(function () {
|
||||
|
||||
return reportOfflineActions(apiClient, serverInfo).then(function () {
|
||||
|
||||
//// Do the first data sync
|
||||
//return syncData(apiClient, serverInfo, false).then(function () {
|
||||
|
||||
// Download new content
|
||||
return getNewMedia(apiClient, serverInfo, options).then(function () {
|
||||
|
||||
// Do the second data sync
|
||||
return syncData(apiClient, serverInfo, false);
|
||||
return syncData(apiClient, serverInfo, false).then(function () {
|
||||
console.log("[mediasync]************************************* Exit sync");
|
||||
});
|
||||
});
|
||||
//});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function reportOfflineActions(apiClient, serverInfo) {
|
||||
|
||||
console.log('Begin reportOfflineActions');
|
||||
|
||||
return LocalAssetManager.getOfflineActions(serverInfo.Id).then(function (actions) {
|
||||
|
||||
if (!actions.length) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return apiClient.reportOfflineActions(actions).then(function () {
|
||||
|
||||
return LocalAssetManager.deleteOfflineActions(actions);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function syncData(apiClient, serverInfo, syncUserItemAccess) {
|
||||
|
||||
console.log('Begin syncData');
|
||||
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
LocalAssetManager.getServerItemIds(serverInfo.Id).then(function (localIds) {
|
||||
|
||||
var request = {
|
||||
TargetId: apiClient.deviceId(),
|
||||
LocalItemIds: localIds,
|
||||
OfflineUserIds: (serverInfo.Users || []).map(function (u) { return u.Id; })
|
||||
};
|
||||
|
||||
apiClient.syncData(request).then(function (result) {
|
||||
|
||||
afterSyncData(apiClient, serverInfo, syncUserItemAccess, result, deferred);
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function afterSyncData(apiClient, serverInfo, enableSyncUserItemAccess, syncDataResult, deferred) {
|
||||
|
||||
console.log('Begin afterSyncData');
|
||||
|
||||
removeLocalItems(syncDataResult, serverInfo.Id).then(function (result) {
|
||||
|
||||
if (enableSyncUserItemAccess) {
|
||||
syncUserItemAccess(syncDataResult, serverInfo.Id).then(function () {
|
||||
|
||||
deferred.resolve();
|
||||
|
||||
}, getOnFail(deferred));
|
||||
}
|
||||
else {
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
function removeLocalItems(syncDataResult, serverId) {
|
||||
|
||||
console.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).then(function () {
|
||||
|
||||
removeNextLocalItem(itemIdsToRemove, index + 1, serverId, deferred);
|
||||
}, function () {
|
||||
removeNextLocalItem(itemIdsToRemove, index + 1, serverId, deferred);
|
||||
});
|
||||
}
|
||||
|
||||
function removeLocalItem(itemId, serverId) {
|
||||
|
||||
console.log('Begin removeLocalItem');
|
||||
|
||||
return LocalAssetManager.removeLocalItem(itemId, serverId);
|
||||
}
|
||||
|
||||
function getNewMedia(apiClient, serverInfo, options) {
|
||||
|
||||
console.log('Begin getNewMedia');
|
||||
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
apiClient.getReadySyncItems(apiClient.deviceId()).then(function (jobItems) {
|
||||
|
||||
getNextNewItem(jobItems, 0, apiClient, serverInfo, options, deferred);
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function getNextNewItem(jobItems, index, apiClient, serverInfo, options, deferred) {
|
||||
|
||||
var length = jobItems.length;
|
||||
|
||||
if (index >= length) {
|
||||
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
var hasGoneNext = false;
|
||||
var goNext = function () {
|
||||
|
||||
if (!hasGoneNext) {
|
||||
hasGoneNext = true;
|
||||
getNextNewItem(jobItems, index + 1, apiClient, serverInfo, options, deferred);
|
||||
}
|
||||
};
|
||||
|
||||
getNewItem(jobItems[index], apiClient, serverInfo, options).then(goNext, goNext);
|
||||
}
|
||||
|
||||
function getNewItem(jobItem, apiClient, serverInfo, options) {
|
||||
|
||||
console.log('Begin getNewItem');
|
||||
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
var libraryItem = jobItem.Item;
|
||||
LocalAssetManager.createLocalItem(libraryItem, serverInfo, jobItem.OriginalFileName).then(function (localItem) {
|
||||
|
||||
downloadMedia(apiClient, jobItem, localItem, options).then(function (isQueued) {
|
||||
|
||||
if (isQueued) {
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
getImages(apiClient, jobItem, localItem).then(function () {
|
||||
|
||||
getSubtitles(apiClient, jobItem, localItem).then(function () {
|
||||
|
||||
apiClient.reportSyncJobItemTransferred(jobItem.SyncJobItemId).then(function () {
|
||||
|
||||
deferred.resolve();
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function downloadMedia(apiClient, jobItem, localItem, options) {
|
||||
|
||||
console.log('Begin downloadMedia');
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
var url = apiClient.getUrl("Sync/JobItems/" + jobItem.SyncJobItemId + "/File", {
|
||||
api_key: apiClient.accessToken()
|
||||
});
|
||||
|
||||
var localPath = localItem.LocalPath;
|
||||
|
||||
console.log('Downloading media. Url: ' + url + '. Local path: ' + localPath);
|
||||
|
||||
options = options || {};
|
||||
|
||||
LocalAssetManager.downloadFile(url, localPath, options.enableBackgroundTransfer, options.enableNewDownloads).then(function (path, isQueued) {
|
||||
|
||||
if (isQueued) {
|
||||
deferred.resolveWith(null, [true]);
|
||||
return;
|
||||
}
|
||||
LocalAssetManager.addOrUpdateLocalItem(localItem).then(function () {
|
||||
|
||||
deferred.resolveWith(null, [false]);
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function getImages(apiClient, jobItem, localItem) {
|
||||
|
||||
console.log('Begin getImages');
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
getNextImage(0, apiClient, localItem, deferred);
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function getNextImage(index, apiClient, localItem, deferred) {
|
||||
|
||||
console.log('Begin getNextImage');
|
||||
if (index >= 4) {
|
||||
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// Just for now while media syncing gets worked out
|
||||
deferred.resolve();
|
||||
|
||||
//var libraryItem = localItem.Item;
|
||||
|
||||
//var serverId = libraryItem.ServerId;
|
||||
//var itemId = null;
|
||||
//var imageTag = null;
|
||||
//var imageType = "Primary";
|
||||
|
||||
//switch (index) {
|
||||
|
||||
// case 0:
|
||||
// itemId = libraryItem.Id;
|
||||
// imageType = "Primary";
|
||||
// imageTag = (libraryItem.ImageTags || {})["Primary"];
|
||||
// break;
|
||||
// case 1:
|
||||
// itemId = libraryItem.SeriesId;
|
||||
// imageType = "Primary";
|
||||
// imageTag = libraryItem.SeriesPrimaryImageTag;
|
||||
// break;
|
||||
// case 2:
|
||||
// itemId = libraryItem.SeriesId;
|
||||
// imageType = "Thumb";
|
||||
// imageTag = libraryItem.SeriesPrimaryImageTag;
|
||||
// break;
|
||||
// case 3:
|
||||
// itemId = libraryItem.AlbumId;
|
||||
// imageType = "Primary";
|
||||
// imageTag = libraryItem.AlbumPrimaryImageTag;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
//}
|
||||
|
||||
//if (!itemId || !imageTag) {
|
||||
// getNextImage(index + 1, apiClient, localItem, deferred);
|
||||
// return;
|
||||
//}
|
||||
|
||||
//downloadImage(apiClient, serverId, itemId, imageTag, imageType).then(function () {
|
||||
|
||||
// // For the sake of simplicity, limit to one image
|
||||
// deferred.resolve();
|
||||
// return;
|
||||
|
||||
// getNextImage(index + 1, apiClient, localItem, deferred);
|
||||
|
||||
//}, getOnFail(deferred));
|
||||
}
|
||||
|
||||
function downloadImage(apiClient, serverId, itemId, imageTag, imageType) {
|
||||
|
||||
console.log('Begin downloadImage');
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
LocalAssetManager.hasImage(serverId, itemId, imageTag).then(function (hasImage) {
|
||||
|
||||
if (hasImage) {
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
var imageUrl = apiClient.getImageUrl(itemId, {
|
||||
tag: imageTag,
|
||||
type: imageType,
|
||||
api_key: apiClient.accessToken()
|
||||
});
|
||||
|
||||
LocalAssetManager.downloadImage(imageUrl, serverId, itemId, imageTag).then(function () {
|
||||
|
||||
deferred.resolve();
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
});
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function getSubtitles(apiClient, jobItem, localItem) {
|
||||
|
||||
console.log('Begin getSubtitles');
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
if (!jobItem.Item.MediaSources.length) {
|
||||
console.log("Cannot download subtitles because video has no media source info.");
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
var files = jobItem.AdditionalFiles.filter(function (f) {
|
||||
return f.Type === 'Subtitles';
|
||||
});
|
||||
|
||||
var mediaSource = jobItem.Item.MediaSources[0];
|
||||
|
||||
getNextSubtitle(files, 0, apiClient, jobItem, localItem, mediaSource, deferred);
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function getNextSubtitle(files, index, apiClient, jobItem, localItem, mediaSource, deferred) {
|
||||
|
||||
var length = files.length;
|
||||
|
||||
if (index >= length) {
|
||||
|
||||
deferred.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
getItemSubtitle(file, apiClient, jobItem, localItem, mediaSource).then(function () {
|
||||
|
||||
getNextSubtitle(files, index + 1, apiClient, jobItem, localItem, mediaSource, deferred);
|
||||
|
||||
}, function () {
|
||||
getNextSubtitle(files, index + 1, apiClient, jobItem, localItem, mediaSource, deferred);
|
||||
});
|
||||
}
|
||||
|
||||
function getItemSubtitle(file, apiClient, jobItem, localItem, mediaSource) {
|
||||
|
||||
console.log('Begin getItemSubtitle');
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
var subtitleStream = mediaSource.MediaStreams.filter(function (m) {
|
||||
return m.Type === 'Subtitle' && m.Index === file.Index;
|
||||
})[0];
|
||||
|
||||
if (!subtitleStream) {
|
||||
|
||||
// We shouldn't get in here, but let's just be safe anyway
|
||||
console.log("Cannot download subtitles because matching stream info wasn't found.");
|
||||
deferred.reject();
|
||||
return;
|
||||
}
|
||||
|
||||
var url = apiClient.getUrl("Sync/JobItems/" + jobItem.SyncJobItemId + "/AdditionalFiles", {
|
||||
Name: file.Name,
|
||||
api_key: apiClient.accessToken()
|
||||
});
|
||||
|
||||
LocalAssetManager.downloadSubtitles(url, localItem, subtitleStream).then(function (subtitlePath) {
|
||||
|
||||
subtitleStream.Path = subtitlePath;
|
||||
LocalAssetManager.addOrUpdateLocalItem(localItem).then(function () {
|
||||
deferred.resolve();
|
||||
}, getOnFail(deferred));
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function syncUserItemAccess(syncDataResult, serverId) {
|
||||
console.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).then(function () {
|
||||
|
||||
syncNextUserAccessForItem(itemIds, index + 1, syncDataResult, serverId, deferred);
|
||||
}, function () {
|
||||
syncNextUserAccessForItem(itemIds, index + 1, syncDataResult, serverId, deferred);
|
||||
});
|
||||
}
|
||||
|
||||
function syncUserAccessForItem(itemId, syncDataResult) {
|
||||
console.log('Begin syncUserAccessForItem');
|
||||
|
||||
var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
LocalAssetManager.getUserIdsWithAccess(itemId, serverId).then(function (savedUserIdsWithAccess) {
|
||||
|
||||
var userIdsWithAccess = syncDataResult.ItemUserAccess[itemId];
|
||||
|
||||
if (userIdsWithAccess.join(',') === savedUserIdsWithAccess.join(',')) {
|
||||
// Hasn't changed, nothing to do
|
||||
deferred.resolve();
|
||||
}
|
||||
else {
|
||||
|
||||
LocalAssetManager.saveUserIdsWithAccess(itemId, serverId, userIdsWithAccess).then(function () {
|
||||
deferred.resolve();
|
||||
}, getOnFail(deferred));
|
||||
}
|
||||
|
||||
}, getOnFail(deferred));
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
function getOnFail(deferred) {
|
||||
return function () {
|
||||
|
||||
deferred.reject();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//function syncUserItemAccess(syncDataResult, serverId) {
|
||||
// console.log('[mediasync] Begin syncUserItemAccess');
|
||||
|
||||
// var itemIds = [];
|
||||
// for (var id in syncDataResult.ItemUserAccess) {
|
||||
// itemIds.push(id);
|
||||
// }
|
||||
|
||||
// return syncNextUserAccessForItem(itemIds, 0, syncDataResult, serverId);
|
||||
//}
|
||||
|
||||
//function syncNextUserAccessForItem(itemIds, index, syncDataResult, serverId) {
|
||||
|
||||
// var length = itemIds.length;
|
||||
|
||||
// if (index >= length) {
|
||||
|
||||
// return Promise.resolve
|
||||
// return;
|
||||
// }
|
||||
|
||||
// syncUserAccessForItem(itemIds[index], syncDataResult).then(function () {
|
||||
|
||||
// syncNextUserAccessForItem(itemIds, index + 1, syncDataResult, serverId, deferred);
|
||||
// }, function () {
|
||||
// syncNextUserAccessForItem(itemIds, index + 1, syncDataResult, serverId, deferred);
|
||||
// });
|
||||
//}
|
||||
|
||||
//function syncUserAccessForItem(itemId, syncDataResult) {
|
||||
// console.log('[mediasync] Begin syncUserAccessForItem');
|
||||
|
||||
// var deferred = DeferredBuilder.Deferred();
|
||||
|
||||
// localassetmanager.getUserIdsWithAccess(itemId, serverId).then(function (savedUserIdsWithAccess) {
|
||||
|
||||
// var userIdsWithAccess = syncDataResult.ItemUserAccess[itemId];
|
||||
|
||||
// if (userIdsWithAccess.join(',') === savedUserIdsWithAccess.join(',')) {
|
||||
// // Hasn't changed, nothing to do
|
||||
// deferred.resolve();
|
||||
// }
|
||||
// else {
|
||||
|
||||
// localassetmanager.saveUserIdsWithAccess(itemId, serverId, userIdsWithAccess).then(function () {
|
||||
// deferred.resolve();
|
||||
// }, getOnFail(deferred));
|
||||
// }
|
||||
|
||||
// }, getOnFail(deferred));
|
||||
|
||||
// return deferred.promise();
|
||||
//}
|
||||
|
||||
//}
|
||||
|
||||
});
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
function performSync(server, options) {
|
||||
|
||||
console.log("Creating ContentUploader to server: " + server.Id);
|
||||
console.log("ServerSync.performSync to server: " + server.Id);
|
||||
|
||||
options = options || {};
|
||||
|
||||
|
@ -47,34 +47,27 @@
|
|||
uploadPhotos = false;
|
||||
}
|
||||
|
||||
if (!uploadPhotos) {
|
||||
return syncOfflineUsers(server, options);
|
||||
}
|
||||
var pr = syncOfflineUsers(server, options);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
return pr.then(function () {
|
||||
|
||||
require(['contentuploader'], function (ContentUploader) {
|
||||
if (uploadPhotos) {
|
||||
return uploadContent(server, options);
|
||||
}
|
||||
|
||||
new ContentUploader(connectionManager).uploadImages(server).then(function () {
|
||||
return Promise.resolve();
|
||||
|
||||
console.log("ContentUploaded succeeded to server: " + server.Id);
|
||||
}).then(function () {
|
||||
|
||||
syncOfflineUsers(server, options).then(resolve, reject);
|
||||
|
||||
}, function () {
|
||||
|
||||
console.log("ContentUploaded failed to server: " + server.Id);
|
||||
|
||||
syncOfflineUsers(server, options).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
return syncMedia(server, options);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function syncOfflineUsers(server, options) {
|
||||
|
||||
if (options.syncOfflineUsers === false) {
|
||||
return syncMedia(server, options);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
@ -83,13 +76,19 @@
|
|||
|
||||
var apiClient = connectionManager.getApiClient(server.Id);
|
||||
|
||||
new OfflineUserSync().sync(apiClient, server).then(function () {
|
||||
new OfflineUserSync().sync(apiClient, server).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
console.log("OfflineUserSync succeeded to server: " + server.Id);
|
||||
function uploadContent(server, options) {
|
||||
|
||||
syncMedia(server, options).then(resolve, reject);
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
}, reject);
|
||||
require(['contentuploader'], function (contentuploader) {
|
||||
|
||||
uploader = new ContentUploader(connectionManager);
|
||||
uploader.uploadImages(server).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
23
dashboard-ui/bower_components/emby-apiclient/sync/transfermanager.js
vendored
Normal file
23
dashboard-ui/bower_components/emby-apiclient/sync/transfermanager.js
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
define(['filerepository'], function (filerepository) {
|
||||
'use strict';
|
||||
|
||||
function downloadFile(url, localPath) {
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function downloadSubtitles(url, localItem, subtitleStreamh) {
|
||||
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
||||
function downloadImage(url, serverId, itemId, imageTag) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return {
|
||||
downloadFile: downloadFile,
|
||||
downloadSubtitles: downloadSubtitles,
|
||||
downloadImage: downloadImage
|
||||
};
|
||||
});
|
82
dashboard-ui/bower_components/emby-apiclient/sync/useractionrepository.js
vendored
Normal file
82
dashboard-ui/bower_components/emby-apiclient/sync/useractionrepository.js
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
define(['idb'], function () {
|
||||
'use strict';
|
||||
|
||||
// Database name
|
||||
var dbName = "useractions";
|
||||
|
||||
// Database version
|
||||
var dbVersion = 1;
|
||||
|
||||
var dbPromise;
|
||||
|
||||
function setup() {
|
||||
|
||||
dbPromise = idb.open(dbName, dbVersion, function (upgradeDB) {
|
||||
// Note: we don't use 'break' in this switch statement,
|
||||
// the fall-through behaviour is what we want.
|
||||
switch (upgradeDB.oldVersion) {
|
||||
case 0:
|
||||
upgradeDB.createObjectStore(dbName);
|
||||
//case 1:
|
||||
// upgradeDB.createObjectStore('stuff', { keyPath: '' });
|
||||
}
|
||||
}); //.then(db => console.log("DB opened!", db));
|
||||
}
|
||||
|
||||
function getByServerId(serverId) {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).getAll(null, 1000).then(function (all) {
|
||||
return all.filter(function (item) {
|
||||
return item.ServerId === serverId;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).getAll(null, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
function get(key) {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).get(key);
|
||||
});
|
||||
}
|
||||
|
||||
function set(key, val) {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).put(val, key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
function remove(key) {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).delete(key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
function clear() {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).clear(key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
return {
|
||||
get: get,
|
||||
set: set,
|
||||
remove: remove,
|
||||
clear: clear,
|
||||
getAll: getAll,
|
||||
getByServerId: getByServerId
|
||||
};
|
||||
});
|
71
dashboard-ui/bower_components/emby-apiclient/sync/userrepository.js
vendored
Normal file
71
dashboard-ui/bower_components/emby-apiclient/sync/userrepository.js
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
define(['idb'], function () {
|
||||
'use strict';
|
||||
|
||||
// Database name
|
||||
var dbName = "users";
|
||||
|
||||
// Database version
|
||||
var dbVersion = 1;
|
||||
|
||||
var dbPromise;
|
||||
|
||||
function setup() {
|
||||
|
||||
dbPromise = idb.open(dbName, dbVersion, function (upgradeDB) {
|
||||
// Note: we don't use 'break' in this switch statement,
|
||||
// the fall-through behaviour is what we want.
|
||||
switch (upgradeDB.oldVersion) {
|
||||
case 0:
|
||||
upgradeDB.createObjectStore(dbName);
|
||||
//case 1:
|
||||
// upgradeDB.createObjectStore('stuff', { keyPath: '' });
|
||||
}
|
||||
}); //.then(db => console.log("DB opened!", db));
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).getAll(null, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
function get(key) {
|
||||
return dbPromise.then(function (db) {
|
||||
return db.transaction(dbName).objectStore(dbName).get(key);
|
||||
});
|
||||
}
|
||||
|
||||
function set(key, val) {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).put(val, key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
function remove(key) {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).delete(key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
function clear() {
|
||||
return dbPromise.then(function (db) {
|
||||
var tx = db.transaction(dbName, 'readwrite');
|
||||
tx.objectStore(dbName).clear(key);
|
||||
return tx.complete;
|
||||
});
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
return {
|
||||
get: get,
|
||||
set: set,
|
||||
remove: remove,
|
||||
clear: clear,
|
||||
getAll: getAll
|
||||
};
|
||||
});
|
|
@ -14,12 +14,12 @@
|
|||
},
|
||||
"devDependencies": {},
|
||||
"ignore": [],
|
||||
"version": "1.4.375",
|
||||
"_release": "1.4.375",
|
||||
"version": "1.4.380",
|
||||
"_release": "1.4.380",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.4.375",
|
||||
"commit": "728db9b8c27dcea2b8679e4d7ba6f556cfb9dc20"
|
||||
"tag": "1.4.380",
|
||||
"commit": "ef70fed326cf70ed366390f05df489943b155c13"
|
||||
},
|
||||
"_source": "https://github.com/MediaBrowser/emby-webcomponents.git",
|
||||
"_target": "^1.2.1",
|
||||
|
|
|
@ -55,6 +55,11 @@
|
|||
}
|
||||
|
||||
function isStyleSupported(prop, value) {
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If no value is supplied, use "inherit"
|
||||
value = arguments.length === 2 ? value : 'inherit';
|
||||
// Try the native standard method first
|
||||
|
@ -220,7 +225,7 @@
|
|||
};
|
||||
};
|
||||
|
||||
var userAgent = window.navigator.userAgent;
|
||||
var userAgent = navigator.userAgent;
|
||||
var matched = uaMatch(userAgent);
|
||||
var browser = {};
|
||||
|
||||
|
@ -248,7 +253,7 @@
|
|||
}
|
||||
|
||||
browser.xboxOne = userAgent.toLowerCase().indexOf('xbox') !== -1;
|
||||
browser.animate = document.documentElement.animate != null;
|
||||
browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null;
|
||||
browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || userAgent.toLowerCase().indexOf('smarthub') !== -1;
|
||||
browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1;
|
||||
browser.edgeUwp = browser.edge && userAgent.toLowerCase().indexOf('msapphost') !== -1;
|
||||
|
@ -264,8 +269,10 @@
|
|||
browser.slow = true;
|
||||
}
|
||||
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
|
||||
browser.touch = true;
|
||||
if (typeof document !== 'undefined') {
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
|
||||
browser.touch = true;
|
||||
}
|
||||
}
|
||||
|
||||
browser.keyboard = hasKeyboard(browser);
|
||||
|
|
323
dashboard-ui/bower_components/emby-webcomponents/idb.js
vendored
Normal file
323
dashboard-ui/bower_components/emby-webcomponents/idb.js
vendored
Normal file
|
@ -0,0 +1,323 @@
|
|||
// from https://github.com/jakearchibald/idb
|
||||
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
function toArray(arr) {
|
||||
return Array.prototype.slice.call(arr);
|
||||
}
|
||||
|
||||
function promisifyRequest(request) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
request.onsuccess = function () {
|
||||
resolve(request.result);
|
||||
};
|
||||
|
||||
request.onerror = function () {
|
||||
reject(request.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function promisifyRequestCall(obj, method, args) {
|
||||
var request;
|
||||
var p = new Promise(function (resolve, reject) {
|
||||
request = obj[method].apply(obj, args);
|
||||
promisifyRequest(request).then(resolve, reject);
|
||||
});
|
||||
|
||||
p.request = request;
|
||||
return p;
|
||||
}
|
||||
|
||||
function promisifyCursorRequestCall(obj, method, args) {
|
||||
var p = promisifyRequestCall(obj, method, args);
|
||||
return p.then(function (value) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
return new Cursor(value, p.request);
|
||||
});
|
||||
}
|
||||
|
||||
function proxyProperties(ProxyClass, targetProp, properties) {
|
||||
properties.forEach(function (prop) {
|
||||
Object.defineProperty(ProxyClass.prototype, prop, {
|
||||
get: function () {
|
||||
return this[targetProp][prop];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) {
|
||||
properties.forEach(function (prop) {
|
||||
if (!(prop in Constructor.prototype)) {
|
||||
return;
|
||||
}
|
||||
ProxyClass.prototype[prop] = function () {
|
||||
return promisifyRequestCall(this[targetProp], prop, arguments);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function proxyMethods(ProxyClass, targetProp, Constructor, properties) {
|
||||
properties.forEach(function (prop) {
|
||||
if (!(prop in Constructor.prototype)) {
|
||||
return;
|
||||
}
|
||||
ProxyClass.prototype[prop] = function () {
|
||||
return this[targetProp][prop].apply(this[targetProp], arguments);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) {
|
||||
properties.forEach(function (prop) {
|
||||
if (!(prop in Constructor.prototype)) {
|
||||
return;
|
||||
}
|
||||
ProxyClass.prototype[prop] = function () {
|
||||
return promisifyCursorRequestCall(this[targetProp], prop, arguments);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function Index(index) {
|
||||
this._index = index;
|
||||
}
|
||||
|
||||
proxyProperties(Index, '_index', [
|
||||
'name',
|
||||
'keyPath',
|
||||
'multiEntry',
|
||||
'unique'
|
||||
]);
|
||||
|
||||
proxyRequestMethods(Index, '_index', IDBIndex, [
|
||||
'get',
|
||||
'getKey',
|
||||
'getAll',
|
||||
'getAllKeys',
|
||||
'count'
|
||||
]);
|
||||
|
||||
proxyCursorRequestMethods(Index, '_index', IDBIndex, [
|
||||
'openCursor',
|
||||
'openKeyCursor'
|
||||
]);
|
||||
|
||||
function Cursor(cursor, request) {
|
||||
this._cursor = cursor;
|
||||
this._request = request;
|
||||
}
|
||||
|
||||
proxyProperties(Cursor, '_cursor', [
|
||||
'direction',
|
||||
'key',
|
||||
'primaryKey',
|
||||
'value'
|
||||
]);
|
||||
|
||||
proxyRequestMethods(Cursor, '_cursor', IDBCursor, [
|
||||
'update',
|
||||
'delete'
|
||||
]);
|
||||
|
||||
// proxy 'next' methods
|
||||
['advance', 'continue', 'continuePrimaryKey'].forEach(function (methodName) {
|
||||
if (!(methodName in IDBCursor.prototype)) {
|
||||
return;
|
||||
}
|
||||
Cursor.prototype[methodName] = function () {
|
||||
var cursor = this;
|
||||
var args = arguments;
|
||||
return Promise.resolve().then(function () {
|
||||
cursor._cursor[methodName].apply(cursor._cursor, args);
|
||||
return promisifyRequest(cursor._request).then(function (value) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
return new Cursor(value, cursor._request);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
function ObjectStore(store) {
|
||||
this._store = store;
|
||||
}
|
||||
|
||||
ObjectStore.prototype.createIndex = function () {
|
||||
return new Index(this._store.createIndex.apply(this._store, arguments));
|
||||
};
|
||||
|
||||
ObjectStore.prototype.index = function () {
|
||||
return new Index(this._store.index.apply(this._store, arguments));
|
||||
};
|
||||
|
||||
proxyProperties(ObjectStore, '_store', [
|
||||
'name',
|
||||
'keyPath',
|
||||
'indexNames',
|
||||
'autoIncrement'
|
||||
]);
|
||||
|
||||
proxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [
|
||||
'put',
|
||||
'add',
|
||||
'delete',
|
||||
'clear',
|
||||
'get',
|
||||
'getAll',
|
||||
'getAllKeys',
|
||||
'count'
|
||||
]);
|
||||
|
||||
proxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [
|
||||
'openCursor',
|
||||
'openKeyCursor'
|
||||
]);
|
||||
|
||||
proxyMethods(ObjectStore, '_store', IDBObjectStore, [
|
||||
'deleteIndex'
|
||||
]);
|
||||
|
||||
function Transaction(idbTransaction) {
|
||||
this._tx = idbTransaction;
|
||||
this.complete = new Promise(function (resolve, reject) {
|
||||
idbTransaction.oncomplete = function () {
|
||||
resolve();
|
||||
};
|
||||
idbTransaction.onerror = function () {
|
||||
reject(idbTransaction.error);
|
||||
};
|
||||
idbTransaction.onabort = function () {
|
||||
reject(idbTransaction.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Transaction.prototype.objectStore = function () {
|
||||
return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments));
|
||||
};
|
||||
|
||||
proxyProperties(Transaction, '_tx', [
|
||||
'objectStoreNames',
|
||||
'mode'
|
||||
]);
|
||||
|
||||
proxyMethods(Transaction, '_tx', IDBTransaction, [
|
||||
'abort'
|
||||
]);
|
||||
|
||||
function UpgradeDB(db, oldVersion, transaction) {
|
||||
this._db = db;
|
||||
this.oldVersion = oldVersion;
|
||||
this.transaction = new Transaction(transaction);
|
||||
}
|
||||
|
||||
UpgradeDB.prototype.createObjectStore = function () {
|
||||
return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments));
|
||||
};
|
||||
|
||||
proxyProperties(UpgradeDB, '_db', [
|
||||
'name',
|
||||
'version',
|
||||
'objectStoreNames'
|
||||
]);
|
||||
|
||||
proxyMethods(UpgradeDB, '_db', IDBDatabase, [
|
||||
'deleteObjectStore',
|
||||
'close'
|
||||
]);
|
||||
|
||||
function DB(db) {
|
||||
this._db = db;
|
||||
}
|
||||
|
||||
DB.prototype.transaction = function () {
|
||||
return new Transaction(this._db.transaction.apply(this._db, arguments));
|
||||
};
|
||||
|
||||
proxyProperties(DB, '_db', [
|
||||
'name',
|
||||
'version',
|
||||
'objectStoreNames'
|
||||
]);
|
||||
|
||||
proxyMethods(DB, '_db', IDBDatabase, [
|
||||
'close'
|
||||
]);
|
||||
|
||||
// Add cursor iterators
|
||||
// TODO: remove this once browsers do the right thing with promises
|
||||
['openCursor', 'openKeyCursor'].forEach(function (funcName) {
|
||||
[ObjectStore, Index].forEach(function (Constructor) {
|
||||
Constructor.prototype[funcName.replace('open', 'iterate')] = function () {
|
||||
var args = toArray(arguments);
|
||||
var callback = args[args.length - 1];
|
||||
var nativeObject = this._store || this._index;
|
||||
var request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1));
|
||||
request.onsuccess = function () {
|
||||
callback(request.result);
|
||||
};
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// polyfill getAll
|
||||
[Index, ObjectStore].forEach(function (Constructor) {
|
||||
if (Constructor.prototype.getAll) {
|
||||
return;
|
||||
}
|
||||
Constructor.prototype.getAll = function (query, count) {
|
||||
var instance = this;
|
||||
var items = [];
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
instance.iterateCursor(query, function (cursor) {
|
||||
if (!cursor) {
|
||||
resolve(items);
|
||||
return;
|
||||
}
|
||||
items.push(cursor.value);
|
||||
|
||||
if (count !== undefined && items.length === count) {
|
||||
resolve(items);
|
||||
return;
|
||||
}
|
||||
cursor.continue();
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
var exp = {
|
||||
open: function (name, version, upgradeCallback) {
|
||||
var p = promisifyRequestCall(indexedDB, 'open', [name, version]);
|
||||
var request = p.request;
|
||||
|
||||
request.onupgradeneeded = function (event) {
|
||||
if (upgradeCallback) {
|
||||
upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction));
|
||||
}
|
||||
};
|
||||
|
||||
return p.then(function (db) {
|
||||
return new DB(db);
|
||||
});
|
||||
},
|
||||
delete: function (name) {
|
||||
return promisifyRequestCall(indexedDB, 'deleteDatabase', [name]);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = exp;
|
||||
}
|
||||
else {
|
||||
self.idb = exp;
|
||||
}
|
||||
}());
|
|
@ -353,5 +353,6 @@
|
|||
"HeaderPlayMyMedia": "Play my Media",
|
||||
"HeaderDiscoverEmbyPremiere": "Discover Emby Premiere",
|
||||
"OneChannel": "One channel",
|
||||
"ConfirmRemoveDownload": "Remove download?",
|
||||
"AddedOnValue": "Added {0}"
|
||||
}
|
85
dashboard-ui/bower_components/emby-webcomponents/sync/synctoggle.js
vendored
Normal file
85
dashboard-ui/bower_components/emby-webcomponents/sync/synctoggle.js
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
define(['itemHelper', 'globalize', 'apphost', 'connectionManager', 'events', 'emby-checkbox'], function (itemHelper, globalize, appHost, connectionManager, events) {
|
||||
'use strict';
|
||||
|
||||
function updateSyncStatus(container, item) {
|
||||
|
||||
container.querySelector('.chkOffline').checked = item.SyncPercent != null;
|
||||
}
|
||||
|
||||
function syncToggle(options) {
|
||||
|
||||
var self = this;
|
||||
|
||||
function resetSyncStatus() {
|
||||
updateSyncStatus(options.container, options.item);
|
||||
}
|
||||
|
||||
function onSyncLocalClick() {
|
||||
|
||||
if (this.checked) {
|
||||
require(['syncDialog'], function (syncDialog) {
|
||||
syncDialog.showMenu({
|
||||
items: [options.item],
|
||||
isLocalSync: true,
|
||||
serverId: options.item.ServerId
|
||||
|
||||
}).then(function () {
|
||||
events.trigger(self, 'sync');
|
||||
}, resetSyncStatus);
|
||||
});
|
||||
} else {
|
||||
|
||||
require(['confirm'], function (confirm) {
|
||||
|
||||
confirm(globalize.translate('sharedcomponents#ConfirmRemoveDownload')).then(function () {
|
||||
connectionManager.getApiClient(options.item.ServerId).cancelSyncItems([options.item.Id]);
|
||||
}, resetSyncStatus);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var container = options.container;
|
||||
var user = options.user;
|
||||
var item = options.item;
|
||||
|
||||
var html = '';
|
||||
html += '<label class="checkboxContainer" style="margin: 0;">';
|
||||
html += '<input type="checkbox" is="emby-checkbox" class="chkOffline" />';
|
||||
html += '<span>' + globalize.translate('sharedcomponents#MakeAvailableOffline') + '</span>';
|
||||
html += '</label>';
|
||||
|
||||
if (itemHelper.canSync(user, item)) {
|
||||
if (appHost.supports('sync')) {
|
||||
container.classList.remove('hide');
|
||||
} else {
|
||||
container.classList.add('hide');
|
||||
}
|
||||
|
||||
container.innerHTML = html;
|
||||
|
||||
container.querySelector('.chkOffline').addEventListener('change', onSyncLocalClick);
|
||||
updateSyncStatus(container, item);
|
||||
|
||||
} else {
|
||||
container.classList.add('hide');
|
||||
}
|
||||
}
|
||||
|
||||
syncToggle.prototype.refresh = function(item) {
|
||||
|
||||
this.options.item = item;
|
||||
updateSyncStatus(this.options.container, item);
|
||||
};
|
||||
|
||||
syncToggle.prototype.destroy = function () {
|
||||
|
||||
var options = this.options;
|
||||
|
||||
if (options) {
|
||||
options.container.innerHTML = '';
|
||||
this.options = null;
|
||||
}
|
||||
};
|
||||
|
||||
return syncToggle;
|
||||
});
|
|
@ -777,6 +777,13 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
|
|||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 800px), (max-height: 800px) {
|
||||
|
||||
.detailsHiddenOnMobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#criticReviewsContent.hiddenScrollX {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -825,4 +832,4 @@ span.itemCommunityRating:not(:empty) + .userDataIcons {
|
|||
|
||||
.mediaInfoText-upper {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
|
@ -49,10 +49,6 @@
|
|||
</div>
|
||||
|
||||
<div class="syncLocalContainer hide" style="margin: 1em 0;">
|
||||
<label class="checkboxContainer" style="margin: 0;">
|
||||
<input type="checkbox" is="emby-checkbox" class="chkOffline" />
|
||||
<span>${MakeAvailableOffline}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="recordingFields hide" style="margin: .5em 0 1.5em;">
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
define(['layoutManager', 'cardBuilder', 'datetime', 'mediaInfo', 'backdrop', 'listView', 'itemContextMenu', 'itemHelper', 'userdataButtons', 'dom', 'indicators', 'apphost', 'imageLoader', 'libraryMenu', 'shell', 'globalize', 'browser', 'scrollStyles', 'emby-itemscontainer', 'emby-checkbox'], function (layoutManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, userdataButtons, dom, indicators, appHost, imageLoader, libraryMenu, shell, globalize, browser) {
|
||||
define(['layoutManager', 'cardBuilder', 'datetime', 'mediaInfo', 'backdrop', 'listView', 'itemContextMenu', 'itemHelper', 'userdataButtons', 'dom', 'indicators', 'apphost', 'imageLoader', 'libraryMenu', 'shell', 'globalize', 'browser', 'events', 'scrollStyles', 'emby-itemscontainer', 'emby-checkbox'], function (layoutManager, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, userdataButtons, dom, indicators, appHost, imageLoader, libraryMenu, shell, globalize, browser, events) {
|
||||
'use strict';
|
||||
|
||||
var currentItem;
|
||||
var currentRecordingFields;
|
||||
|
||||
function getPromise(params) {
|
||||
|
||||
var id = params.id;
|
||||
|
@ -40,6 +37,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
var currentItem;
|
||||
var currentRecordingFields;
|
||||
|
||||
function reload(page, params) {
|
||||
|
||||
Dashboard.showLoadingMsg();
|
||||
|
@ -87,14 +87,25 @@
|
|||
return options;
|
||||
}
|
||||
|
||||
function updateSyncStatus(page, item) {
|
||||
function renderSyncLocalContainer(page, params, user, item) {
|
||||
|
||||
var i, length;
|
||||
var elems = page.querySelectorAll('.chkOffline');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
elems[i].checked = item.SyncPercent != null;
|
||||
if (page.syncToggleInstance) {
|
||||
page.syncToggleInstance.refresh(item);
|
||||
return;
|
||||
}
|
||||
|
||||
require(['syncToggle'], function (syncToggle) {
|
||||
|
||||
page.syncToggleInstance = new syncToggle({
|
||||
user: user,
|
||||
item: item,
|
||||
container: page.querySelector('.syncLocalContainer')
|
||||
});
|
||||
|
||||
events.on(page.syncToggleInstance, 'sync', function () {
|
||||
reload(page, params);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function reloadFromItem(page, params, item) {
|
||||
|
@ -166,19 +177,7 @@
|
|||
hideAll(page, 'btnDeleteItem');
|
||||
}
|
||||
|
||||
if (itemHelper.canSync(user, item)) {
|
||||
if (appHost.supports('sync')) {
|
||||
hideAll(page, 'syncLocalContainer', true);
|
||||
hideAll(page, 'btnSync');
|
||||
} else {
|
||||
hideAll(page, 'syncLocalContainer');
|
||||
hideAll(page, 'btnSync', true);
|
||||
}
|
||||
updateSyncStatus(page, item);
|
||||
} else {
|
||||
hideAll(page, 'btnSync');
|
||||
hideAll(page, 'syncLocalContainer');
|
||||
}
|
||||
renderSyncLocalContainer(page, params, user, item);
|
||||
|
||||
if (hasAnyButton || item.Type !== 'Program') {
|
||||
hideAll(page, 'mainDetailButtons', true);
|
||||
|
@ -641,6 +640,12 @@
|
|||
}
|
||||
|
||||
var overview = page.querySelector('.overview');
|
||||
var externalLinksElem = page.querySelector('.itemExternalLinks');
|
||||
|
||||
if (item.Type === 'Season' || item.Type === 'MusicAlbum' || item.Type === 'MusicArtist') {
|
||||
overview.classList.add('detailsHiddenOnMobile');
|
||||
externalLinksElem.classList.add('detailsHiddenOnMobile');
|
||||
}
|
||||
|
||||
renderOverview([overview], item);
|
||||
|
||||
|
@ -677,7 +682,7 @@
|
|||
|
||||
renderStudios(page.querySelector('.itemStudios'), item, isStatic);
|
||||
renderUserDataIcons(page, item);
|
||||
renderLinks(page.querySelector('.itemExternalLinks'), item);
|
||||
renderLinks(externalLinksElem, item);
|
||||
|
||||
page.querySelector('.criticRatingScore').innerHTML = (item.CriticRating || '0') + '%';
|
||||
|
||||
|
@ -2175,53 +2180,10 @@
|
|||
|
||||
return function (view, params) {
|
||||
|
||||
function resetSyncStatus() {
|
||||
updateSyncStatus(view, currentItem);
|
||||
}
|
||||
|
||||
function onSyncLocalClick() {
|
||||
|
||||
if (this.checked) {
|
||||
require(['syncDialog'], function (syncDialog) {
|
||||
syncDialog.showMenu({
|
||||
items: [currentItem],
|
||||
isLocalSync: true,
|
||||
serverId: ApiClient.serverId()
|
||||
|
||||
}).then(function () {
|
||||
reload(view, params);
|
||||
}, resetSyncStatus);
|
||||
});
|
||||
} else {
|
||||
|
||||
require(['confirm'], function (confirm) {
|
||||
|
||||
confirm(globalize.translate('ConfirmRemoveDownload')).then(function () {
|
||||
ApiClient.cancelSyncItems([currentItem.Id]);
|
||||
}, resetSyncStatus);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onPlayTrailerClick() {
|
||||
playTrailer(view);
|
||||
}
|
||||
|
||||
function onRecordClick() {
|
||||
var id = params.id;
|
||||
Dashboard.showLoadingMsg();
|
||||
|
||||
require(['recordingCreator'], function (recordingCreator) {
|
||||
recordingCreator.show(id, currentItem.ServerId).then(function () {
|
||||
reload(view, params);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onCancelRecordingClick() {
|
||||
deleteTimer(view, params, currentItem.TimerId);
|
||||
}
|
||||
|
||||
function onMoreCommandsClick() {
|
||||
var button = this;
|
||||
|
||||
|
@ -2257,11 +2219,6 @@
|
|||
splitVersions(view, params);
|
||||
});
|
||||
|
||||
elems = view.querySelectorAll('.chkOffline');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].addEventListener('change', onSyncLocalClick);
|
||||
}
|
||||
|
||||
elems = view.querySelectorAll('.btnMoreCommands');
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].addEventListener('click', onMoreCommandsClick);
|
||||
|
@ -2349,7 +2306,7 @@
|
|||
var page = this;
|
||||
reload(page, params);
|
||||
|
||||
Events.on(ApiClient, 'websocketmessage', onWebSocketMessage);
|
||||
events.on(ApiClient, 'websocketmessage', onWebSocketMessage);
|
||||
});
|
||||
|
||||
view.addEventListener('viewbeforehide', function () {
|
||||
|
@ -2357,8 +2314,16 @@
|
|||
currentItem = null;
|
||||
currentRecordingFields = null;
|
||||
|
||||
Events.off(ApiClient, 'websocketmessage', onWebSocketMessage);
|
||||
events.off(ApiClient, 'websocketmessage', onWebSocketMessage);
|
||||
libraryMenu.setTransparentMenu(false);
|
||||
});
|
||||
|
||||
view.addEventListener('viewdestroy', function () {
|
||||
|
||||
if (view.syncToggleInstance) {
|
||||
view.syncToggleInstance.destroy();
|
||||
view.syncToggleInstance = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
|
@ -1293,6 +1293,7 @@ var AppInfo = {};
|
|||
define("guide-settings-dialog", [embyWebComponentsBowerPath + "/guide/guide-settings"], returnFirstDependency);
|
||||
define("guide-categories-dialog", [embyWebComponentsBowerPath + "/guide/guide-categories"], returnFirstDependency);
|
||||
define("syncDialog", [embyWebComponentsBowerPath + "/sync/sync"], returnFirstDependency);
|
||||
define("syncToggle", [embyWebComponentsBowerPath + "/sync/synctoggle"], returnFirstDependency);
|
||||
define("voiceDialog", [embyWebComponentsBowerPath + "/voice/voicedialog"], returnFirstDependency);
|
||||
define("voiceReceiver", [embyWebComponentsBowerPath + "/voice/voicereceiver"], returnFirstDependency);
|
||||
define("voiceProcessor", [embyWebComponentsBowerPath + "/voice/voiceprocessor"], returnFirstDependency);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue