diff --git a/dashboard-ui/bower_components/emby-apiclient/localassetmanager.js b/dashboard-ui/bower_components/emby-apiclient/localassetmanager.js index 4ced1f00c..bafee7522 100644 --- a/dashboard-ui/bower_components/emby-apiclient/localassetmanager.js +++ b/dashboard-ui/bower_components/emby-apiclient/localassetmanager.js @@ -1,94 +1,481 @@ -define([], function () { +define(['filerepository', 'itemrepository', 'userrepository', 'useractionrepository', 'transfermanager', 'cryptojs-md5'], function (filerepository, itemrepository, userrepository, useractionrepository, transfermanager) { 'use strict'; - function getLocalMediaSource(serverId, itemId) { - return Promise.resolve(null); + function getLocalItem(serverId, itemId) { + var id = getLocalId(serverId, itemId); + return itemrepository.get(id); + } + + function getLocalItemById(id) { + return itemrepository.get(id); + } + + function getLocalId(serverId, itemId) { + + return CryptoJS.MD5(serverId + itemId).toString(); } function saveOfflineUser(user) { - return Promise.resolve(); + return userrepository.set(user.Id, user); } function deleteOfflineUser(id) { - return Promise.resolve(); + return userrepository.remove(id); } + //TODO: function getCameraPhotos() { return Promise.resolve([]); } - function getOfflineActions(serverId) { - return Promise.resolve([]); + function recordUserAction(action) { + + action.Id = createGuid(); + return useractionrepository.set(action.Id, action); } - function deleteOfflineActions(actions) { - return Promise.resolve([]); + function getUserActions(serverId) { + return useractionrepository.getByServerId(serverId); + } + + function deleteUserAction(action) { + return useractionrepository.remove(action.Id); + } + + function deleteUserActions(actions) { + var results = []; + + actions.forEach(function (action) { + results.push(deleteUserAction(action)); + }); + + return Promise.all(results); } function getServerItemIds(serverId) { - return Promise.resolve([]); + return itemrepository.getServerItemIds(serverId); } - function removeLocalItem(itemId, serverId) { - return Promise.resolve(); + function getServerItems(serverId) { + + return itemrepository.getServerIds(serverId).then(function (localIds) { + + var actions = localIds.map(function (id) { + return getLocalItemById(id); + }); + + return Promise.all(actions).then(function (items) { + + return Promise.resolve(items); + }); + }); } - function getLocalItem(itemId, serverId) { - return Promise.resolve(); + function getViews(serverId, userId) { + + return itemrepository.getServerItemTypes(serverId, userId).then(function (types) { + + var list = []; + var item; + + if (types.indexOf('audio') > -1) { + + item = { + Name: 'Music', + ServerId: serverId, + Id: 'localview:MusicView', + Type: 'MusicView', + CollectionType: 'Music', + IsFolder: true + }; + + list.push(item); + } + + if (types.indexOf('photo') > -1) { + + item = { + Name: 'Photos', + ServerId: serverId, + Id: 'localview:PhotosView', + Type: 'PhotosView', + CollectionType: 'Photos', + IsFolder: true + }; + + list.push(item); + } + + if (types.indexOf('episode') > -1) { + + item = { + Name: 'TV', + ServerId: serverId, + Id: 'localview:TVView', + Type: 'TVView', + CollectionType: 'TvShows', + IsFolder: true + }; + + list.push(item); + } + + if (types.indexOf('video') > -1 || + types.indexOf('movie') > -1 || + types.indexOf('musicvideo') > -1) { + + item = { + Name: 'Videos', + ServerId: serverId, + Id: 'localview:VideosView', + Type: 'VideosView', + CollectionType: 'HomeVideos', + IsFolder: true + }; + + list.push(item); + } + + return Promise.resolve(list); + }); + } + + function getViewItems(serverId, userId, parentId) { + + return getServerItems(serverId).then(function (items) { + + var resultItems = items.filter(function (item) { + + var type = (item.Item.Type || '').toLowerCase(); + + switch (parentId) { + case 'localview:MusicView': + return type === 'audio'; + case 'localview:PhotosView': + return type === 'photo'; + case 'localview:TVView': + return type === 'episode'; + case 'localview:VideosView': + return type === 'movie' || type === 'video' || type === 'musicvideo'; + default: + return false; + } + }).map(function (item2) { + return item2.Item; + }); + + return Promise.resolve(resultItems); + }); + } + + + function removeLocalItem(localItem) { + + return itemrepository.get(localItem.Id).then(function (item) { + return filerepository.deleteFile(item.LocalPath).then(function () { + + var p = Promise.resolve(true); + + if (item.AdditionalFiles) { + item.AdditionalFiles.forEach(function (file) { + p = p.then(function () { + return filerepository.deleteFile(file.Path); + }); + }); + } + + return p.then(function (file) { + return itemrepository.remove(localItem.Id); + }); + + }, function (error) { + + var p = Promise.resolve(true); + + if (item.AdditionalFiles) { + item.AdditionalFiles.forEach(function (file) { + p = p.then(function (item) { + return filerepository.deleteFile(file.Path); + }); + }); + } + + return p.then(function (file) { + return itemrepository.remove(localItem.Id); + }); + }); + }); } function addOrUpdateLocalItem(localItem) { - return Promise.resolve(); + return itemrepository.set(localItem.Id, localItem); } - function createLocalItem(libraryItem, serverInfo, originalFileName) { + function createLocalItem(libraryItem, serverInfo, jobItem) { - return Promise.resolve({}); + var path = getDirectoryPath(libraryItem, serverInfo); + var localFolder = filerepository.getFullLocalPath(path); + + path.push(getLocalFileName(libraryItem, jobItem.OriginalFileName)); + + var localPath = filerepository.getFullLocalPath(path); + + for (var i = 0; i < libraryItem.MediaSources.length; i++) { + var mediaSource = libraryItem.MediaSources[i]; + mediaSource.Path = localPath; + mediaSource.Protocol = 'File'; + } + + var item = { + + Item: libraryItem, + ItemId: libraryItem.Id, + ServerId: serverInfo.Id, + LocalPath: localPath, + LocalFolder: localFolder, + AdditionalFiles: jobItem.AdditionalFiles.slice(0), + Id: getLocalId(serverInfo.Id, libraryItem.Id), + SyncJobItemId: jobItem.SyncJobItemId + }; + + return Promise.resolve(item); } - function downloadFile(url, localPath) { + function getSubtitleSaveFileName(localItem, mediaPath, language, isForced, format) { + + var name = getNameWithoutExtension(mediaPath); + + if (language) { + name += "." + language.toLowerCase(); + } + + if (isForced) { + name += ".foreign"; + } + + name = name + "." + format.toLowerCase(); + + var localPathArray = [localItem.LocalFolder, name]; + var localFilePath = filerepository.getPathFromArray(localPathArray); + + return localFilePath; - return Promise.resolve(); } - function downloadSubtitles(url, localItem, subtitleStreamh) { - - return Promise.resolve(''); + function getItemFileSize(path) { + return filerepository.getItemFileSize(path); } - function hasImage(serverId, itemId, imageTag) { - return Promise.resolve(false); + function getNameWithoutExtension(path) { + + var fileName = path; + + var pos = fileName.lastIndexOf("."); + + if (pos > 0) { + fileName = fileName.substring(0, pos); + } + + return fileName; } - function downloadImage(url, serverId, itemId, imageTag) { - return Promise.resolve(false); + function downloadFile(url, localItem) { + + return transfermanager.downloadFile(url, localItem); } - function fileExists(path) { - return Promise.resolve(false); + function downloadSubtitles(url, fileName) { + + return transfermanager.downloadSubtitles(url, fileName); + } + + function getImageUrl(serverId, itemId, imageType, index) { + + var pathArray = getImagePath(serverId, itemId, imageType, index); + var relPath = pathArray.join('/'); + + var prefix = 'ms-appdata:///local'; + return prefix + '/' + relPath; + } + + function hasImage(serverId, itemId, imageType, index) { + + var pathArray = getImagePath(serverId, itemId, imageType, index); + var localFilePath = filerepository.getFullLocalPath(pathArray); + + return filerepository.fileExists(localFilePath).then(function (exists) { + // TODO: Maybe check for broken download when file size is 0 and item is not queued + ////if (exists) { + //// if (!transfermanager.isDownloadFileInQueue(localFilePath)) { + //// // If file exists but + //// exists = false; + //// } + ////} + + return Promise.resolve(exists); + }, function (err) { + return Promise.resolve(false); + }); + } + + function downloadImage(localItem, url, serverId, itemId, imageType, index) { + + var pathArray = getImagePath(serverId, itemId, imageType, index); + var localFilePath = filerepository.getFullLocalPath(pathArray); + + if (!localItem.AdditionalFiles) { + localItem.AdditionalFiles = []; + } + + var fileInfo = { + Path: localFilePath, + Type: 'Image', + Name: imageType + index.toString(), + ImageType: imageType + }; + + localItem.AdditionalFiles.push(fileInfo); + + return transfermanager.downloadImage(url, localFilePath); + } + + function isDownloadFileInQueue(path) { + + return transfermanager.isDownloadFileInQueue(path); } function translateFilePath(path) { return Promise.resolve(path); } + // Helpers *********************************************************** + + function getDirectoryPath(item, server) { + + var parts = []; + parts.push(server.Name); + + var itemtype = item.Type.toLowerCase(); + + if (itemtype === 'episode') { + + parts.push("TV"); + + var seriesName = item.SeriesName; + if (seriesName) { + parts.push(seriesName); + } + + var seasonName = item.SeasonName; + if (seasonName) { + parts.push(seasonName); + } + + } else if (itemtype === 'video') { + + parts.push("Videos"); + parts.push(item.Name); + + } else if (itemtype === 'audio') { + + parts.push("Music"); + + var albumArtist = item.AlbumArtist; + if (albumArtist) { + parts.push(albumArtist); + } + + if ((item.AlbumId) && (item.Album)) { + parts.push(item.Album); + } + + } else if (itemtype === 'photo') { + + parts.push("Photos"); + + if ((item.AlbumId) && (item.Album)) { + parts.push(item.Album); + } + + } + + var finalParts = []; + for (var i = 0; i < parts.length; i++) { + + finalParts.push(filerepository.getValidFileName(parts[i])); + } + + return finalParts; + } + + function getImagePath(serverId, itemId, imageType, index) { + + var parts = []; + parts.push('Metadata'); + parts.push(serverId); + parts.push('images'); + parts.push(itemId + '_' + imageType + '_' + index.toString() + '.png'); + + var finalParts = []; + for (var i = 0; i < parts.length; i++) { + + finalParts.push(filerepository.getValidFileName(parts[i])); + } + + return finalParts; + } + + function getLocalFileName(item, originalFileName) { + + var filename = originalFileName || item.Name; + + return filerepository.getValidFileName(filename); + } + + function resyncTransfers() { + return transfermanager.resyncTransfers(); + } + + function createGuid() { + var d = new Date().getTime(); + if (window.performance && typeof window.performance.now === "function") { + d += performance.now(); //use high-precision timer if available + } + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); + }); + return uuid; + } + return { - getLocalMediaSource: getLocalMediaSource, + + getLocalItem: getLocalItem, saveOfflineUser: saveOfflineUser, deleteOfflineUser: deleteOfflineUser, getCameraPhotos: getCameraPhotos, - getOfflineActions: getOfflineActions, - deleteOfflineActions: deleteOfflineActions, + recordUserAction: recordUserAction, + getUserActions: getUserActions, + deleteUserAction: deleteUserAction, + deleteUserActions: deleteUserActions, getServerItemIds: getServerItemIds, removeLocalItem: removeLocalItem, - getLocalItem: getLocalItem, addOrUpdateLocalItem: addOrUpdateLocalItem, createLocalItem: createLocalItem, downloadFile: downloadFile, downloadSubtitles: downloadSubtitles, hasImage: hasImage, downloadImage: downloadImage, - fileExists: fileExists, - translateFilePath: translateFilePath + getImageUrl: getImageUrl, + translateFilePath: translateFilePath, + getSubtitleSaveFileName: getSubtitleSaveFileName, + getLocalItemById: getLocalItemById, + getServerItems: getServerItems, + getItemFileSize: getItemFileSize, + isDownloadFileInQueue: isDownloadFileInQueue, + getViews: getViews, + getViewItems: getViewItems, + resyncTransfers: resyncTransfers }; }); \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js b/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js index 89e12ef74..df681c3a7 100644 --- a/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js +++ b/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js @@ -267,7 +267,7 @@ var serverId = libraryItem.ServerId; // case 0 - var mainImageTag = (libraryItem.ImageTags || {})['Primary']; + var mainImageTag = (libraryItem.ImageTags || {}).Primary; if (libraryItem.Id && mainImageTag) { p = p.then(function () { @@ -276,7 +276,7 @@ } // case 0a - var logoImageTag = (libraryItem.ImageTags || {})['Logo']; + var logoImageTag = (libraryItem.ImageTags || {}).Logo; if (libraryItem.Id && logoImageTag) { p = p.then(function () { return downloadImage(localItem, apiClient, serverId, libraryItem.Id, logoImageTag, 'Logo'); @@ -284,7 +284,7 @@ } // case 0b - var artImageTag = (libraryItem.ImageTags || {})['Art']; + var artImageTag = (libraryItem.ImageTags || {}).Art; if (libraryItem.Id && artImageTag) { p = p.then(function () { return downloadImage(localItem, apiClient, serverId, libraryItem.Id, artImageTag, 'Art'); @@ -292,7 +292,7 @@ } // case 0c - var bannerImageTag = (libraryItem.ImageTags || {})['Banner']; + var bannerImageTag = (libraryItem.ImageTags || {}).Banner; if (libraryItem.Id && bannerImageTag) { p = p.then(function () { return downloadImage(localItem, apiClient, serverId, libraryItem.Id, bannerImageTag, 'Banner'); @@ -300,7 +300,7 @@ } // case 0d - var thumbImageTag = (libraryItem.ImageTags || {})['Thumb']; + var thumbImageTag = (libraryItem.ImageTags || {}).Thumb; if (libraryItem.Id && thumbImageTag) { p = p.then(function () { return downloadImage(localItem, apiClient, serverId, libraryItem.Id, thumbImageTag, 'Thumb'); @@ -308,19 +308,19 @@ } // Backdrops - if (libraryItem.Id && libraryItem.BackdropImageTags) { - for (var i = 0; i < libraryItem.BackdropImageTags.length; i++) { + //if (libraryItem.Id && libraryItem.BackdropImageTags) { + // for (var i = 0; i < libraryItem.BackdropImageTags.length; i++) { - var backdropImageTag = libraryItem.BackdropImageTags[i]; + // var backdropImageTag = libraryItem.BackdropImageTags[i]; - // use self-invoking function to simulate block-level variable scope - (function (index, tag) { - p = p.then(function () { - return downloadImage(localItem, apiClient, serverId, libraryItem.Id, tag, 'backdrop', index); - }); - })(i, backdropImageTag); - } - } + // // use self-invoking function to simulate block-level variable scope + // (function (index, tag) { + // p = p.then(function () { + // return downloadImage(localItem, apiClient, serverId, libraryItem.Id, tag, 'backdrop', index); + // }); + // })(i, backdropImageTag); + // } + //} // case 1/2: if (libraryItem.SeriesId && libraryItem.SeriesPrimaryImageTag) { diff --git a/dashboard-ui/scripts/mediacontroller.js b/dashboard-ui/scripts/mediacontroller.js index 98c439eaa..73e7dfacc 100644 --- a/dashboard-ui/scripts/mediacontroller.js +++ b/dashboard-ui/scripts/mediacontroller.js @@ -889,25 +889,26 @@ return new Promise(function (resolve, reject) { - require(['localassetmanager'], function (LocalAssetManager) { + require([], function () { + //require(['localassetmanager'], function (LocalAssetManager) { var serverInfo = ApiClient.serverInfo(); - if (serverInfo.Id) { - LocalAssetManager.getLocalMediaSource(serverInfo.Id, itemId).then(function (localMediaSource) { - // Use the local media source if a specific one wasn't requested, or the smae one was requested - if (localMediaSource && (!mediaSource || mediaSource.Id == localMediaSource.Id)) { + //if (serverInfo.Id) { + // LocalAssetManager.getLocalMediaSource(serverInfo.Id, itemId).then(function (localMediaSource) { + // // Use the local media source if a specific one wasn't requested, or the smae one was requested + // if (localMediaSource && (!mediaSource || mediaSource.Id == localMediaSource.Id)) { - var playbackInfo = getPlaybackInfoFromLocalMediaSource(itemId, deviceProfile, startPosition, localMediaSource); + // var playbackInfo = getPlaybackInfoFromLocalMediaSource(itemId, deviceProfile, startPosition, localMediaSource); - resolve(playbackInfo); - return; - } + // resolve(playbackInfo); + // return; + // } - getPlaybackInfoWithoutLocalMediaSource(itemId, deviceProfile, startPosition, mediaSource, audioStreamIndex, subtitleStreamIndex, liveStreamId, resolve, reject); - }); - return; - } + // getPlaybackInfoWithoutLocalMediaSource(itemId, deviceProfile, startPosition, mediaSource, audioStreamIndex, subtitleStreamIndex, liveStreamId, resolve, reject); + // }); + // return; + //} getPlaybackInfoWithoutLocalMediaSource(itemId, deviceProfile, startPosition, mediaSource, audioStreamIndex, subtitleStreamIndex, liveStreamId, resolve, reject); }); @@ -1003,11 +1004,14 @@ if (mediaSource.Protocol == 'File') { - require(['localassetmanager'], function (LocalAssetManager) { + require(['filesystem'], function (fileSystem) { - LocalAssetManager.fileExists(mediaSource.Path).then(function (exists) { - console.log('LocalAssetManager.fileExists: path: ' + mediaSource.Path + ' result: ' + exists); - resolve(exists); + fileSystem.fileExists(mediaSource.Path).then(function () { + console.log('fileSystem.fileExists: path: ' + mediaSource.Path + ' result: ' + true); + resolve(true); + }, function () { + console.log('fileSystem.fileExists: path: ' + mediaSource.Path + ' result: ' + false); + resolve(false); }); }); }