Merge pull request #1007 from MrTimscampi/apiclient-be-gone

Remove API Client from the tree
This commit is contained in:
dkanada 2020-05-08 03:05:24 +09:00 committed by GitHub
commit a7241d39f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 444 additions and 2694 deletions

View File

@ -183,7 +183,9 @@ module.exports = {
'Uint32Array', 'Uint32Array',
'Float32Array', 'Float32Array',
'Float64Array', 'Float64Array',
'Reflect' 'Reflect',
// Temporary while eslint-compat-plugin is buggy
'document.querySelector'
] ]
} }
} }

View File

@ -65,6 +65,7 @@
"hls.js": "^0.13.1", "hls.js": "^0.13.1",
"howler": "^2.1.3", "howler": "^2.1.3",
"intersection-observer": "^0.10.0", "intersection-observer": "^0.10.0",
"jellyfin-apiclient": "^1.1.1",
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto", "jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
"jquery": "^3.5.0", "jquery": "^3.5.0",
"jstree": "^3.3.7", "jstree": "^3.3.7",
@ -91,9 +92,9 @@
"src/components/autoFocuser.js", "src/components/autoFocuser.js",
"src/components/cardbuilder/cardBuilder.js", "src/components/cardbuilder/cardBuilder.js",
"src/components/filedownloader.js", "src/components/filedownloader.js",
"src/components/playback/mediasession.js",
"src/components/images/imageLoader.js", "src/components/images/imageLoader.js",
"src/components/lazyloader/lazyloader-intersectionobserver.js", "src/components/lazyloader/lazyloader-intersectionobserver.js",
"src/components/playback/mediasession.js",
"src/components/sanatizefilename.js", "src/components/sanatizefilename.js",
"src/components/scrollManager.js", "src/components/scrollManager.js",
"src/scripts/dfnshelper.js", "src/scripts/dfnshelper.js",

View File

@ -108,6 +108,7 @@ _define('page', function() {
return page; return page;
}); });
// core-js
var polyfill = require('@babel/polyfill/dist/polyfill'); var polyfill = require('@babel/polyfill/dist/polyfill');
_define('polyfill', function () { _define('polyfill', function () {
return polyfill; return polyfill;
@ -152,3 +153,26 @@ var headroom = require('headroom.js/dist/headroom');
_define('headroom', function () { _define('headroom', function () {
return headroom; return headroom;
}); });
// apiclient
var apiclient = require('jellyfin-apiclient');
_define('apiclient', function () {
return apiclient.apiclient;
});
_define('events', function () {
return apiclient.Events;
});
_define('credentialprovider', function () {
return apiclient.Credentials;
});
_define('connectionManagerFactory', function () {
return apiclient.ConnectionManager;
});
_define('appStorage', function () {
return apiclient.AppStorage;
});

View File

@ -109,7 +109,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
var now = Date.now(); var now = Date.now();
if (window.performance && window.performance.now) { if (window.performance && window.performance.now) {
now = performance.now(); now = performance.now(); // eslint-disable-line compat/compat
} }
if (!recoverDecodingErrorDate || (now - recoverDecodingErrorDate) > 3000) { if (!recoverDecodingErrorDate || (now - recoverDecodingErrorDate) > 3000) {

View File

@ -1,236 +0,0 @@
//TODO: (vitorsemeano) modify this lines for webpack
define(["libraries/apiclient/apiclientcore", "localassetmanager"], function(ApiClient, localassetmanager) {
"use strict";
if ("cordova" !== window.appMode && "android" !== window.appMode) {
return ApiClient;
}
function isLocalId(str) {
return startsWith(str, localPrefix)
}
function isLocalViewId(str) {
return startsWith(str, localViewPrefix)
}
function isTopLevelLocalViewId(str) {
return "localview" === str
}
function stripLocalPrefix(str) {
var res = stripStart(str, localPrefix);
return res = stripStart(res, localViewPrefix)
}
function startsWith(str, find) {
return !!(str && find && str.length > find.length && 0 === str.indexOf(find))
}
function stripStart(str, find) {
return startsWith(str, find) ? str.substr(find.length) : str
}
function createEmptyList() {
return {
Items: [],
TotalRecordCount: 0
}
}
function convertGuidToLocal(guid) {
return guid ? isLocalId(guid) ? guid : "local:" + guid : null
}
function adjustGuidProperties(downloadedItem) {
downloadedItem.Id = convertGuidToLocal(downloadedItem.Id), downloadedItem.SeriesId = convertGuidToLocal(downloadedItem.SeriesId), downloadedItem.SeasonId = convertGuidToLocal(downloadedItem.SeasonId), downloadedItem.AlbumId = convertGuidToLocal(downloadedItem.AlbumId), downloadedItem.ParentId = convertGuidToLocal(downloadedItem.ParentId), downloadedItem.ParentThumbItemId = convertGuidToLocal(downloadedItem.ParentThumbItemId), downloadedItem.ParentPrimaryImageItemId = convertGuidToLocal(downloadedItem.ParentPrimaryImageItemId), downloadedItem.PrimaryImageItemId = convertGuidToLocal(downloadedItem.PrimaryImageItemId), downloadedItem.ParentLogoItemId = convertGuidToLocal(downloadedItem.ParentLogoItemId), downloadedItem.ParentBackdropItemId = convertGuidToLocal(downloadedItem.ParentBackdropItemId), downloadedItem.ParentBackdropImageTags = null
}
function getLocalView(instance, serverId, userId) {
return instance.getLocalFolders(serverId, userId).then(function(views) {
var localView = null;
return views.length > 0 && (localView = {
Name: instance.downloadsTitleText || "Downloads",
ServerId: serverId,
Id: "localview",
Type: "localview",
IsFolder: !0
}), Promise.resolve(localView)
})
}
function ApiClientEx(serverAddress, clientName, applicationVersion, deviceName, deviceId) {
ApiClient.call(this, serverAddress, clientName, applicationVersion, deviceName, deviceId)
}
var localPrefix = "local:",
localViewPrefix = "localview:";
return Object.assign(ApiClientEx.prototype, ApiClient.prototype), ApiClientEx.prototype.getPlaybackInfo = function(itemId, options, deviceProfile) {
var onFailure = function() {
return ApiClient.prototype.getPlaybackInfo.call(instance, itemId, options, deviceProfile)
};
if (isLocalId(itemId)) return localassetmanager.getLocalItem(this.serverId(), stripLocalPrefix(itemId)).then(function(item) {
return {
MediaSources: item.Item.MediaSources.map(function(m) {
return m.SupportsDirectPlay = !0, m.SupportsDirectStream = !1, m.SupportsTranscoding = !1, m.IsLocal = !0, m
})
}
}, onFailure);
var instance = this;
return localassetmanager.getLocalItem(this.serverId(), itemId).then(function(item) {
if (item) {
var mediaSources = item.Item.MediaSources.map(function(m) {
return m.SupportsDirectPlay = !0, m.SupportsDirectStream = !1, m.SupportsTranscoding = !1, m.IsLocal = !0, m
});
return localassetmanager.fileExists(item.LocalPath).then(function(exists) {
if (exists) {
var res = {
MediaSources: mediaSources
};
return Promise.resolve(res)
}
return ApiClient.prototype.getPlaybackInfo.call(instance, itemId, options, deviceProfile)
}, onFailure)
}
return ApiClient.prototype.getPlaybackInfo.call(instance, itemId, options, deviceProfile)
}, onFailure)
}, ApiClientEx.prototype.getItems = function(userId, options) {
var i, serverInfo = this.serverInfo();
if (serverInfo && "localview" === options.ParentId) return this.getLocalFolders(serverInfo.Id, userId).then(function(items) {
var result = {
Items: items,
TotalRecordCount: items.length
};
return Promise.resolve(result)
});
if (serverInfo && options && (isLocalId(options.ParentId) || isLocalId(options.SeriesId) || isLocalId(options.SeasonId) || isLocalViewId(options.ParentId) || isLocalId(options.AlbumIds))) return localassetmanager.getViewItems(serverInfo.Id, userId, options).then(function(items) {
items.forEach(function(item) {
adjustGuidProperties(item)
});
var result = {
Items: items,
TotalRecordCount: items.length
};
return Promise.resolve(result)
});
if (options && options.ExcludeItemIds && options.ExcludeItemIds.length) {
var exItems = options.ExcludeItemIds.split(",");
for (i = 0; i < exItems.length; i++)
if (isLocalId(exItems[i])) return Promise.resolve(createEmptyList())
} else if (options && options.Ids && options.Ids.length) {
var ids = options.Ids.split(","),
hasLocal = !1;
for (i = 0; i < ids.length; i++) isLocalId(ids[i]) && (hasLocal = !0);
if (hasLocal) return localassetmanager.getItemsFromIds(serverInfo.Id, ids).then(function(items) {
items.forEach(function(item) {
adjustGuidProperties(item)
});
var result = {
Items: items,
TotalRecordCount: items.length
};
return Promise.resolve(result)
})
}
return ApiClient.prototype.getItems.call(this, userId, options)
}, ApiClientEx.prototype.getUserViews = function(options, userId) {
var instance = this;
options = options || {};
var basePromise = ApiClient.prototype.getUserViews.call(instance, options, userId);
return options.enableLocalView ? basePromise.then(function(result) {
var serverInfo = instance.serverInfo();
return serverInfo ? getLocalView(instance, serverInfo.Id, userId).then(function(localView) {
return localView && (result.Items.push(localView), result.TotalRecordCount++), Promise.resolve(result)
}) : Promise.resolve(result)
}) : basePromise
}, ApiClientEx.prototype.getItem = function(userId, itemId) {
if (!itemId) throw new Error("null itemId");
itemId && (itemId = itemId.toString());
var serverInfo;
return isTopLevelLocalViewId(itemId) && (serverInfo = this.serverInfo()) ? getLocalView(this, serverInfo.Id, userId) : isLocalViewId(itemId) && (serverInfo = this.serverInfo()) ? this.getLocalFolders(serverInfo.Id, userId).then(function(items) {
var views = items.filter(function(item) {
return item.Id === itemId
});
return views.length > 0 ? Promise.resolve(views[0]) : Promise.reject()
}) : isLocalId(itemId) && (serverInfo = this.serverInfo()) ? localassetmanager.getLocalItem(serverInfo.Id, stripLocalPrefix(itemId)).then(function(item) {
return adjustGuidProperties(item.Item), Promise.resolve(item.Item)
}) : ApiClient.prototype.getItem.call(this, userId, itemId)
}, ApiClientEx.prototype.getLocalFolders = function(userId) {
var serverInfo = this.serverInfo();
return userId = userId || serverInfo.UserId, localassetmanager.getViews(serverInfo.Id, userId)
}, ApiClientEx.prototype.getNextUpEpisodes = function(options) {
return options.SeriesId && isLocalId(options.SeriesId) ? Promise.resolve(createEmptyList()) : ApiClient.prototype.getNextUpEpisodes.call(this, options)
}, ApiClientEx.prototype.getSeasons = function(itemId, options) {
return isLocalId(itemId) ? (options.SeriesId = itemId, options.IncludeItemTypes = "Season", options.SortBy = "SortName", this.getItems(this.getCurrentUserId(), options)) : ApiClient.prototype.getSeasons.call(this, itemId, options)
}, ApiClientEx.prototype.getEpisodes = function(itemId, options) {
return isLocalId(options.SeasonId) || isLocalId(options.seasonId) ? (options.SeriesId = itemId, options.IncludeItemTypes = "Episode", options.SortBy = "SortName", this.getItems(this.getCurrentUserId(), options)) : isLocalId(itemId) ? (options.SeriesId = itemId, options.IncludeItemTypes = "Episode", options.SortBy = "SortName", this.getItems(this.getCurrentUserId(), options)) : ApiClient.prototype.getEpisodes.call(this, itemId, options)
}, ApiClientEx.prototype.getLatestOfflineItems = function(options) {
options.SortBy = "DateCreated", options.SortOrder = "Descending";
var serverInfo = this.serverInfo();
return serverInfo ? localassetmanager.getViewItems(serverInfo.Id, null, options).then(function(items) {
return items.forEach(function(item) {
adjustGuidProperties(item)
}), Promise.resolve(items)
}) : Promise.resolve([])
}, ApiClientEx.prototype.getThemeMedia = function(userId, itemId, inherit) {
return isLocalViewId(itemId) || isLocalId(itemId) || isTopLevelLocalViewId(itemId) ? Promise.reject() : ApiClient.prototype.getThemeMedia.call(this, userId, itemId, inherit)
}, ApiClientEx.prototype.getSpecialFeatures = function(userId, itemId) {
return isLocalId(itemId) ? Promise.resolve([]) : ApiClient.prototype.getSpecialFeatures.call(this, userId, itemId)
}, ApiClientEx.prototype.getSimilarItems = function(itemId, options) {
return isLocalId(itemId) ? Promise.resolve(createEmptyList()) : ApiClient.prototype.getSimilarItems.call(this, itemId, options)
}, ApiClientEx.prototype.updateFavoriteStatus = function(userId, itemId, isFavorite) {
return isLocalId(itemId) ? Promise.resolve() : ApiClient.prototype.updateFavoriteStatus.call(this, userId, itemId, isFavorite)
}, ApiClientEx.prototype.getScaledImageUrl = function(itemId, options) {
if (isLocalId(itemId) || options && options.itemid && isLocalId(options.itemid)) {
var serverInfo = this.serverInfo(),
id = stripLocalPrefix(itemId);
return localassetmanager.getImageUrl(serverInfo.Id, id, options)
}
return ApiClient.prototype.getScaledImageUrl.call(this, itemId, options)
}, ApiClientEx.prototype.reportPlaybackStart = function(options) {
if (!options) throw new Error("null options");
return isLocalId(options.ItemId) ? Promise.resolve() : ApiClient.prototype.reportPlaybackStart.call(this, options)
}, ApiClientEx.prototype.reportPlaybackProgress = function(options) {
if (!options) throw new Error("null options");
if (isLocalId(options.ItemId)) {
var serverInfo = this.serverInfo();
return serverInfo ? localassetmanager.getLocalItem(serverInfo.Id, stripLocalPrefix(options.ItemId)).then(function(item) {
var libraryItem = item.Item;
return "Video" === libraryItem.MediaType || "AudioBook" === libraryItem.Type ? (libraryItem.UserData = libraryItem.UserData || {}, libraryItem.UserData.PlaybackPositionTicks = options.PositionTicks, libraryItem.UserData.PlayedPercentage = Math.min(libraryItem.RunTimeTicks ? (options.PositionTicks || 0) / libraryItem.RunTimeTicks * 100 : 0, 100), localassetmanager.addOrUpdateLocalItem(item)) : Promise.resolve()
}) : Promise.resolve()
}
return ApiClient.prototype.reportPlaybackProgress.call(this, options)
}, ApiClientEx.prototype.reportPlaybackStopped = function(options) {
if (!options) throw new Error("null options");
if (isLocalId(options.ItemId)) {
var serverInfo = this.serverInfo(),
action = {
Date: (new Date).getTime(),
ItemId: stripLocalPrefix(options.ItemId),
PositionTicks: options.PositionTicks,
ServerId: serverInfo.Id,
Type: 0,
UserId: this.getCurrentUserId()
};
return localassetmanager.recordUserAction(action)
}
return ApiClient.prototype.reportPlaybackStopped.call(this, options)
}, ApiClientEx.prototype.getIntros = function(itemId) {
return isLocalId(itemId) ? Promise.resolve({
Items: [],
TotalRecordCount: 0
}) : ApiClient.prototype.getIntros.call(this, itemId)
}, ApiClientEx.prototype.getInstantMixFromItem = function(itemId, options) {
return isLocalId(itemId) ? Promise.resolve({
Items: [],
TotalRecordCount: 0
}) : ApiClient.prototype.getInstantMixFromItem.call(this, itemId, options)
}, ApiClientEx.prototype.getItemDownloadUrl = function(itemId) {
if (isLocalId(itemId)) {
var serverInfo = this.serverInfo();
if (serverInfo) return localassetmanager.getLocalItem(serverInfo.Id, stripLocalPrefix(itemId)).then(function(item) {
return Promise.resolve(item.LocalPath)
})
}
return ApiClient.prototype.getItemDownloadUrl.call(this, itemId)
}, ApiClientEx
});

View File

@ -1,53 +0,0 @@
define([], function() {
"use strict";
function onCachePutFail(e) {
console.error("cannot put to a cache: " + e);
}
function updateCache(instance) {
if (instance.cache) {
instance.cache.put("data", new Response(JSON.stringify(instance.localData))).catch(onCachePutFail);
}
}
function onCacheOpened(result) {
this.cache = result;
this.localData = {};
}
function MyStore() {
this.setItem = function(name, value) {
localStorage.setItem(name, value);
if (this.localData && this.localData[name] !== value) {
this.localData[name] = value;
updateCache(this);
}
};
this.getItem = function(name) {
return localStorage.getItem(name);
};
this.removeItem = function(name) {
localStorage.removeItem(name);
if (this.localData) {
delete this.localData[name];
updateCache(this);
}
};
try {
if (self.caches) {
self.caches.open("embydata").then(onCacheOpened.bind(this));
}
} catch (err) {
console.error("error opening cache: " + err);
}
}
return new MyStore;
});

View File

@ -1,807 +0,0 @@
define(["events", "apiclient", "appStorage"], function (events, apiClientFactory, appStorage) {
"use strict";
function getServerAddress(server, mode) {
switch (mode) {
case ConnectionMode.Local:
return server.LocalAddress;
case ConnectionMode.Manual:
return server.ManualAddress;
case ConnectionMode.Remote:
return server.RemoteAddress;
default:
return server.ManualAddress || server.LocalAddress || server.RemoteAddress;
}
}
function paramsToString(params) {
var values = [];
for (var key in params) {
var value = params[key];
if (null !== value && void 0 !== value && "" !== value) {
values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
}
}
return values.join("&");
}
function resolveFailure(instance, resolve) {
resolve({
State: "Unavailable",
});
}
function mergeServers(credentialProvider, list1, list2) {
for (var i = 0, length = list2.length; i < length; i++) {
credentialProvider.addOrUpdateServer(list1, list2[i]);
}
return list1;
}
function updateServerInfo(server, systemInfo) {
server.Name = systemInfo.ServerName;
if (systemInfo.Id) {
server.Id = systemInfo.Id;
}
if (systemInfo.LocalAddress) {
server.LocalAddress = systemInfo.LocalAddress;
}
}
function getEmbyServerUrl(baseUrl, handler) {
return baseUrl + "/" + handler;
}
function getFetchPromise(request) {
var headers = request.headers || {};
if ("json" === request.dataType) {
headers.accept = "application/json";
}
var fetchRequest = {
headers: headers,
method: request.type,
credentials: "same-origin"
};
var contentType = request.contentType;
if (request.data) {
if ("string" == typeof request.data) {
fetchRequest.body = request.data;
} else {
fetchRequest.body = paramsToString(request.data);
contentType = contentType || "application/x-www-form-urlencoded; charset=UTF-8";
}
}
if (contentType) {
headers["Content-Type"] = contentType;
}
if (request.timeout) {
return fetchWithTimeout(request.url, fetchRequest, request.timeout);
}
return fetch(request.url, fetchRequest);
}
function fetchWithTimeout(url, options, timeoutMs) {
console.debug("fetchWithTimeout: timeoutMs: " + timeoutMs + ", url: " + url);
return new Promise(function (resolve, reject) {
var timeout = setTimeout(reject, timeoutMs);
options = options || {};
options.credentials = "same-origin";
fetch(url, options).then(function (response) {
clearTimeout(timeout);
console.debug("fetchWithTimeout: succeeded connecting to url: " + url);
resolve(response);
}, function (error) {
clearTimeout(timeout);
console.error("fetchWithTimeout: timed out connecting to url: " + url);
reject();
});
});
}
function ajax(request) {
if (!request) {
throw new Error("Request cannot be null");
}
request.headers = request.headers || {};
console.debug("ConnectionManager requesting url: " + request.url);
return getFetchPromise(request).then(function (response) {
console.debug("ConnectionManager response status: " + response.status + ", url: " + request.url);
if (response.status < 400) {
if ("json" === request.dataType || "application/json" === request.headers.accept) {
return response.json();
}
return response;
}
return Promise.reject(response);
}, function (err) {
console.error("ConnectionManager request failed to url: " + request.url);
throw err;
});
}
function replaceAll(originalString, strReplace, strWith) {
var reg = new RegExp(strReplace, "ig");
return originalString.replace(reg, strWith);
}
function normalizeAddress(address) {
address = address.trim();
if (0 !== address.toLowerCase().indexOf("http")) {
address = "http://" + address;
}
address = replaceAll(address, "Http:", "http:");
address = replaceAll(address, "Https:", "https:");
return address;
}
function stringEqualsIgnoreCase(str1, str2) {
return (str1 || "").toLowerCase() === (str2 || "").toLowerCase();
}
function compareVersions(a, b) {
a = a.split(".");
b = b.split(".");
for (var i = 0, length = Math.max(a.length, b.length); i < length; i++) {
var aVal = parseInt(a[i] || "0");
var bVal = parseInt(b[i] || "0");
if (aVal < bVal) {
return -1;
}
if (aVal > bVal) {
return 1;
}
}
return 0;
}
var defaultTimeout = 20000;
var ConnectionMode = {
Local: 0,
Remote: 1,
Manual: 2
};
var ConnectionManager = function (credentialProvider, appName, appVersion, deviceName, deviceId, capabilities) {
function onAuthenticated(apiClient, result, options, saveCredentials) {
var credentials = credentialProvider.credentials();
var servers = credentials.Servers.filter(function (s) {
return s.Id === result.ServerId;
});
var server = servers.length ? servers[0] : apiClient.serverInfo();
if (false !== options.updateDateLastAccessed) {
server.DateLastAccessed = new Date().getTime();
}
server.Id = result.ServerId;
if (saveCredentials) {
server.UserId = result.User.Id;
server.AccessToken = result.AccessToken;
} else {
server.UserId = null;
server.AccessToken = null;
}
credentialProvider.addOrUpdateServer(credentials.Servers, server);
credentialProvider.credentials(credentials);
apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection;
apiClient.serverInfo(server);
afterConnected(apiClient, options);
return onLocalUserSignIn(server, apiClient.serverAddress(), result.User);
}
function afterConnected(apiClient, options) {
options = options || {};
if (false !== options.reportCapabilities) {
apiClient.reportCapabilities(capabilities);
}
apiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection;
if (false !== options.enableWebSocket) {
console.debug("calling apiClient.ensureWebSocket");
apiClient.ensureWebSocket();
}
}
function onLocalUserSignIn(server, serverUrl, user) {
self._getOrAddApiClient(server, serverUrl);
var promise = self.onLocalUserSignedIn ? self.onLocalUserSignedIn.call(self, user) : Promise.resolve();
return promise.then(function () {
events.trigger(self, "localusersignedin", [user])
})
}
function validateAuthentication(server, serverUrl) {
return ajax({
type: "GET",
url: getEmbyServerUrl(serverUrl, "System/Info"),
dataType: "json",
headers: {
"X-MediaBrowser-Token": server.AccessToken
}
}).then(function (systemInfo) {
updateServerInfo(server, systemInfo);
return Promise.resolve();
}, function () {
server.UserId = null;
server.AccessToken = null;
return Promise.resolve();
});
}
function getImageUrl(localUser) {
if (localUser && localUser.PrimaryImageTag) {
return {
url: self.getApiClient(localUser).getUserImageUrl(localUser.Id, {
tag: localUser.PrimaryImageTag,
type: "Primary"
}),
supportsParams: true
};
}
return {
url: null,
supportsParams: false
};
}
function logoutOfServer(apiClient) {
var serverInfo = apiClient.serverInfo() || {};
var logoutInfo = {
serverId: serverInfo.Id
};
return apiClient.logout().then(function () {
events.trigger(self, "localusersignedout", [logoutInfo]);
}, function () {
events.trigger(self, "localusersignedout", [logoutInfo]);
});
}
function findServers() {
return new Promise(function (resolve, reject) {
var onFinish = function (foundServers) {
var servers = foundServers.map(function (foundServer) {
var info = {
Id: foundServer.Id,
LocalAddress: convertEndpointAddressToManualAddress(foundServer) || foundServer.Address,
Name: foundServer.Name
};
info.LastConnectionMode = info.ManualAddress ? ConnectionMode.Manual : ConnectionMode.Local;
return info;
});
resolve(servers);
};
if (window.NativeShell && typeof window.NativeShell.findServers === 'function') {
window.NativeShell.findServers(1e3).then(onFinish, function () {
onFinish([]);
});
} else {
resolve([]);
}
});
}
function convertEndpointAddressToManualAddress(info) {
if (info.Address && info.EndpointAddress) {
var address = info.EndpointAddress.split(":")[0];
var parts = info.Address.split(":");
if (parts.length > 1) {
var portString = parts[parts.length - 1];
if (!isNaN(parseInt(portString))) {
address += ":" + portString;
}
}
return normalizeAddress(address);
}
return null;
}
function getTryConnectPromise(url, connectionMode, state, resolve, reject) {
console.debug("getTryConnectPromise " + url);
ajax({
url: getEmbyServerUrl(url, "system/info/public"),
timeout: defaultTimeout,
type: "GET",
dataType: "json"
}).then(function (result) {
if (!state.resolved) {
state.resolved = true;
console.debug("Reconnect succeeded to " + url);
resolve({
url: url,
connectionMode: connectionMode,
data: result
});
}
}, function () {
if (!state.resolved) {
console.error("Reconnect failed to " + url);
if (++state.rejects >= state.numAddresses) {
reject();
}
}
});
}
function tryReconnect(serverInfo) {
var addresses = [];
var addressesStrings = [];
if (!serverInfo.manualAddressOnly && serverInfo.LocalAddress && -1 === addressesStrings.indexOf(serverInfo.LocalAddress)) {
addresses.push({
url: serverInfo.LocalAddress,
mode: ConnectionMode.Local,
timeout: 0
});
addressesStrings.push(addresses[addresses.length - 1].url);
}
if (serverInfo.ManualAddress && -1 === addressesStrings.indexOf(serverInfo.ManualAddress)) {
addresses.push({
url: serverInfo.ManualAddress,
mode: ConnectionMode.Manual,
timeout: 100
});
addressesStrings.push(addresses[addresses.length - 1].url);
}
if (!serverInfo.manualAddressOnly && serverInfo.RemoteAddress && -1 === addressesStrings.indexOf(serverInfo.RemoteAddress)) {
addresses.push({
url: serverInfo.RemoteAddress,
mode: ConnectionMode.Remote,
timeout: 200
});
addressesStrings.push(addresses[addresses.length - 1].url);
}
console.debug("tryReconnect: " + addressesStrings.join("|"));
return new Promise(function (resolve, reject) {
var state = {};
state.numAddresses = addresses.length;
state.rejects = 0;
addresses.map(function (url) {
setTimeout(function () {
if (!state.resolved) {
getTryConnectPromise(url.url, url.mode, state, resolve, reject);
}
}, url.timeout);
});
});
}
function onSuccessfulConnection(server, systemInfo, connectionMode, serverUrl, options, resolve) {
var credentials = credentialProvider.credentials();
options = options || {};
afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, true, options, resolve);
}
function afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, verifyLocalAuthentication, options, resolve) {
options = options || {};
if (false === options.enableAutoLogin) {
server.UserId = null;
server.AccessToken = null;
} else if (verifyLocalAuthentication && server.AccessToken && false !== options.enableAutoLogin) {
return void validateAuthentication(server, serverUrl).then(function () {
afterConnectValidated(server, credentials, systemInfo, connectionMode, serverUrl, false, options, resolve);
});
}
updateServerInfo(server, systemInfo);
server.LastConnectionMode = connectionMode;
if (false !== options.updateDateLastAccessed) {
server.DateLastAccessed = new Date().getTime();
}
credentialProvider.addOrUpdateServer(credentials.Servers, server);
credentialProvider.credentials(credentials);
var result = {
Servers: []
};
result.ApiClient = self._getOrAddApiClient(server, serverUrl);
result.ApiClient.setSystemInfo(systemInfo);
result.State = server.AccessToken && false !== options.enableAutoLogin ? "SignedIn" : "ServerSignIn";
result.Servers.push(server);
result.ApiClient.enableAutomaticBitrateDetection = options.enableAutomaticBitrateDetection;
result.ApiClient.updateServerInfo(server, serverUrl);
var resolveActions = function () {
resolve(result);
events.trigger(self, "connected", [result]);
};
if ("SignedIn" === result.State) {
afterConnected(result.ApiClient, options);
result.ApiClient.getCurrentUser().then(function (user) {
onLocalUserSignIn(server, serverUrl, user).then(resolveActions, resolveActions);
}, resolveActions);
} else {
resolveActions();
}
}
console.debug("Begin ConnectionManager constructor");
var self = this;
this._apiClients = [];
self._minServerVersion = "3.2.33";
self.appVersion = function () {
return appVersion;
};
self.appName = function () {
return appName;
};
self.capabilities = function () {
return capabilities;
};
self.deviceId = function () {
return deviceId;
};
self.credentialProvider = function () {
return credentialProvider;
};
self.getServerInfo = function (id) {
return credentialProvider.credentials().Servers.filter(function (s) {
return s.Id === id;
})[0];
};
self.getLastUsedServer = function () {
var servers = credentialProvider.credentials().Servers;
servers.sort(function (a, b) {
return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0);
});
if (servers.length) {
return servers[0];
}
return null;
};
self.addApiClient = function (apiClient) {
self._apiClients.push(apiClient);
var existingServers = credentialProvider.credentials().Servers.filter(function (s) {
return stringEqualsIgnoreCase(s.ManualAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.LocalAddress, apiClient.serverAddress()) || stringEqualsIgnoreCase(s.RemoteAddress, apiClient.serverAddress());
});
var existingServer = existingServers.length ? existingServers[0] : apiClient.serverInfo();
existingServer.DateLastAccessed = new Date().getTime();
existingServer.LastConnectionMode = ConnectionMode.Manual;
existingServer.ManualAddress = apiClient.serverAddress();
if (apiClient.manualAddressOnly) {
existingServer.manualAddressOnly = true;
}
apiClient.serverInfo(existingServer);
apiClient.onAuthenticated = function (instance, result) {
return onAuthenticated(instance, result, {}, true);
};
if (!existingServers.length) {
var credentials = credentialProvider.credentials();
credentials.Servers = [existingServer];
credentialProvider.credentials(credentials);
}
events.trigger(self, "apiclientcreated", [apiClient]);
};
self.clearData = function () {
console.debug("connection manager clearing data");
var credentials = credentialProvider.credentials();
credentials.Servers = [];
credentialProvider.credentials(credentials);
};
self._getOrAddApiClient = function (server, serverUrl) {
var apiClient = self.getApiClient(server.Id);
if (!apiClient) {
apiClient = new apiClientFactory(serverUrl, appName, appVersion, deviceName, deviceId);
self._apiClients.push(apiClient);
apiClient.serverInfo(server);
apiClient.onAuthenticated = function (instance, result) {
return onAuthenticated(instance, result, {}, true);
};
events.trigger(self, "apiclientcreated", [apiClient]);
}
console.debug("returning instance from getOrAddApiClient");
return apiClient;
};
self.getOrCreateApiClient = function (serverId) {
var credentials = credentialProvider.credentials();
var servers = credentials.Servers.filter(function (s) {
return stringEqualsIgnoreCase(s.Id, serverId);
});
if (!servers.length) {
throw new Error("Server not found: " + serverId);
}
var server = servers[0];
return self._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode));
};
self.user = function (apiClient) {
return new Promise(function (resolve, reject) {
function onLocalUserDone(e) {
if (apiClient && apiClient.getCurrentUserId()) {
apiClient.getCurrentUser().then(function (u) {
localUser = u;
var image = getImageUrl(localUser);
resolve({
localUser: localUser,
name: localUser ? localUser.Name : null,
imageUrl: image.url,
supportsImageParams: image.supportsParams,
});
}, onLocalUserDone);
}
}
var localUser;
if (apiClient && apiClient.getCurrentUserId()) {
onLocalUserDone();
}
});
};
self.logout = function () {
console.debug("begin connectionManager loguot");
var promises = [];
for (var i = 0, length = self._apiClients.length; i < length; i++) {
var apiClient = self._apiClients[i];
if (apiClient.accessToken()) {
promises.push(logoutOfServer(apiClient));
}
}
return Promise.all(promises).then(function () {
var credentials = credentialProvider.credentials();
var servers = credentials.Servers.filter(function (u) {
return "Guest" !== u.UserLinkType;
});
for (var j = 0, numServers = servers.length; j < numServers; j++) {
var server = servers[j];
server.UserId = null;
server.AccessToken = null;
server.ExchangeToken = null;
}
});
};
self.getSavedServers = function () {
var credentials = credentialProvider.credentials();
var servers = credentials.Servers.slice(0);
servers.sort(function (a, b) {
return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0);
});
return servers;
};
self.getAvailableServers = function () {
console.debug("begin getAvailableServers");
var credentials = credentialProvider.credentials();
return Promise.all([findServers()]).then(function (responses) {
var foundServers = responses[0];
var servers = credentials.Servers.slice(0);
mergeServers(credentialProvider, servers, foundServers);
servers.sort(function (a, b) {
return (b.DateLastAccessed || 0) - (a.DateLastAccessed || 0);
});
credentials.Servers = servers;
credentialProvider.credentials(credentials);
return servers;
});
};
self.connectToServers = function (servers, options) {
console.debug("begin connectToServers, with " + servers.length + " servers");
var firstServer = servers.length ? servers[0] : null;
if (firstServer) {
return self.connectToServer(firstServer, options).then(function (result) {
if ("Unavailable" === result.State) {
result.State = "ServerSelection";
}
console.debug("resolving connectToServers with result.State: " + result.State);
return result;
});
}
return Promise.resolve({
Servers: servers,
State: "ServerSelection"
});
};
self.connectToServer = function (server, options) {
console.debug("begin connectToServer");
return new Promise(function (resolve, reject) {
options = options || {};
tryReconnect(server).then(function (result) {
var serverUrl = result.url;
var connectionMode = result.connectionMode;
result = result.data;
if (1 === compareVersions(self.minServerVersion(), result.Version)) {
console.debug("minServerVersion requirement not met. Server version: " + result.Version);
resolve({
State: "ServerUpdateNeeded",
Servers: [server]
});
} else {
if (server.Id && result.Id !== server.Id) {
console.debug("http request succeeded, but found a different server Id than what was expected");
resolveFailure(self, resolve);
} else {
onSuccessfulConnection(server, result, connectionMode, serverUrl, options, resolve);
}
}
}, function () {
resolveFailure(self, resolve);
});
});
};
self.connectToAddress = function (address, options) {
function onFail() {
console.error("connectToAddress " + address + " failed");
return Promise.resolve({
State: "Unavailable",
});
}
if (!address) {
return Promise.reject();
}
address = normalizeAddress(address);
var instance = this;
var server = {
ManualAddress: address,
LastConnectionMode: ConnectionMode.Manual
};
return self.connectToServer(server, options).catch(onFail);
};
self.deleteServer = function (serverId) {
if (!serverId) {
throw new Error("null serverId");
}
var server = credentialProvider.credentials().Servers.filter(function (s) {
return s.Id === serverId;
});
server = server.length ? server[0] : null;
return new Promise(function (resolve, reject) {
function onDone() {
var credentials = credentialProvider.credentials();
credentials.Servers = credentials.Servers.filter(function (s) {
return s.Id !== serverId;
});
credentialProvider.credentials(credentials);
resolve();
}
if (!server.ConnectServerId) {
return void onDone();
}
});
};
};
ConnectionManager.prototype.connect = function (options) {
console.debug("begin connect");
var instance = this;
return instance.getAvailableServers().then(function (servers) {
return instance.connectToServers(servers, options);
});
};
ConnectionManager.prototype.getApiClients = function () {
var servers = this.getSavedServers();
for (var i = 0, length = servers.length; i < length; i++) {
var server = servers[i];
if (server.Id) {
this._getOrAddApiClient(server, getServerAddress(server, server.LastConnectionMode));
}
}
return this._apiClients;
};
ConnectionManager.prototype.getApiClient = function (item) {
if (!item) {
throw new Error("item or serverId cannot be null");
}
if (item.ServerId) {
item = item.ServerId;
}
return this._apiClients.filter(function (a) {
var serverInfo = a.serverInfo();
return !serverInfo || serverInfo.Id === item;
})[0];
};
ConnectionManager.prototype.minServerVersion = function (val) {
if (val) {
this._minServerVersion = val;
}
return this._minServerVersion;
};
ConnectionManager.prototype.handleMessageReceived = function (msg) {
var serverId = msg.ServerId;
if (serverId) {
var apiClient = this.getApiClient(serverId);
if (apiClient) {
if ("string" == typeof msg.Data) {
try {
msg.Data = JSON.parse(msg.Data);
} catch (err) {}
}
apiClient.handleMessageReceived(msg);
}
}
};
return ConnectionManager;
});

View File

@ -1,29 +0,0 @@
define(["events", "appStorage"], function(events, appStorage) {
"use strict";
function ensure(instance, data) {
if (!instance._credentials) {
var json = appStorage.getItem(instance.key) || "{}";
console.debug("credentials initialized with: " + json), instance._credentials = JSON.parse(json), instance._credentials.Servers = instance._credentials.Servers || []
}
}
function set(instance, data) {
data ? (instance._credentials = data, appStorage.setItem(instance.key, JSON.stringify(data))) : instance.clear(), events.trigger(instance, "credentialsupdated")
}
function Credentials(key) {
this.key = key || "jellyfin_credentials"
}
return Credentials.prototype.clear = function() {
this._credentials = null, appStorage.removeItem(this.key)
}, Credentials.prototype.credentials = function(data) {
return data && set(this, data), ensure(this), this._credentials
}, Credentials.prototype.addOrUpdateServer = function(list, server) {
if (!server.Id) throw new Error("Server.Id cannot be null or empty");
var existing = list.filter(function(s) {
return s.Id === server.Id
})[0];
return existing ? (existing.DateLastAccessed = Math.max(existing.DateLastAccessed || 0, server.DateLastAccessed || 0), existing.UserLinkType = server.UserLinkType, server.AccessToken && (existing.AccessToken = server.AccessToken, existing.UserId = server.UserId), server.ExchangeToken && (existing.ExchangeToken = server.ExchangeToken), server.RemoteAddress && (existing.RemoteAddress = server.RemoteAddress), server.ManualAddress && (existing.ManualAddress = server.ManualAddress), server.LocalAddress && (existing.LocalAddress = server.LocalAddress), server.Name && (existing.Name = server.Name), null != server.LastConnectionMode && (existing.LastConnectionMode = server.LastConnectionMode), server.ConnectServerId && (existing.ConnectServerId = server.ConnectServerId), existing) : (list.push(server), server)
}, Credentials
});

View File

@ -1,30 +0,0 @@
define([], function() {
"use strict";
function getCallbacks(obj, name) {
if (!obj) throw new Error("obj cannot be null!");
obj._callbacks = obj._callbacks || {};
var list = obj._callbacks[name];
return list || (obj._callbacks[name] = [], list = obj._callbacks[name]), list
}
return {
on: function(obj, eventName, fn) {
getCallbacks(obj, eventName).push(fn)
},
off: function(obj, eventName, fn) {
var list = getCallbacks(obj, eventName),
i = list.indexOf(fn); - 1 !== i && list.splice(i, 1)
},
trigger: function(obj, eventName) {
var eventObject = {
type: eventName
},
eventArgs = [];
eventArgs.push(eventObject);
for (var additionalArgs = arguments[2] || [], i = 0, length = additionalArgs.length; i < length; i++) eventArgs.push(additionalArgs[i]);
getCallbacks(obj, eventName).slice(0).forEach(function(c) {
c.apply(obj, eventArgs)
})
}
}
});

View File

@ -1,406 +0,0 @@
define(["filerepository", "itemrepository", "useractionrepository", "transfermanager"], function(filerepository, itemrepository, useractionrepository, transfermanager) {
"use strict";
function getLocalItem(serverId, itemId) {
return console.debug("localassetmanager: begin getLocalItem"), itemrepository.get(serverId, itemId)
}
function recordUserAction(action) {
return action.Id = createGuid(), useractionrepository.set(action.Id, action)
}
function getUserActions(serverId) {
return useractionrepository.getByServerId(serverId)
}
function deleteUserAction(action) {
return useractionrepository.remove(action.Id)
}
function deleteUserActions(actions) {
var results = [];
return actions.forEach(function(action) {
results.push(deleteUserAction(action))
}), Promise.all(results)
}
function getServerItems(serverId) {
return console.debug("localassetmanager: begin getServerItems"), itemrepository.getAll(serverId)
}
function getItemsFromIds(serverId, ids) {
var actions = ids.map(function(id) {
var strippedId = stripStart(id, "local:");
return getLocalItem(serverId, strippedId)
});
return Promise.all(actions).then(function(items) {
var libItems = items.map(function(locItem) {
return locItem.Item
});
return Promise.resolve(libItems)
})
}
function getViews(serverId, userId) {
return itemrepository.getServerItemTypes(serverId, userId).then(function(types) {
var item, list = [];
return types.indexOf("Audio") > -1 && (item = {
Name: "Music",
ServerId: serverId,
Id: "localview:MusicView",
Type: "MusicView",
CollectionType: "music",
IsFolder: !0
}, list.push(item)), types.indexOf("Photo") > -1 && (item = {
Name: "Photos",
ServerId: serverId,
Id: "localview:PhotosView",
Type: "PhotosView",
CollectionType: "photos",
IsFolder: !0
}, list.push(item)), types.indexOf("Episode") > -1 && (item = {
Name: "TV",
ServerId: serverId,
Id: "localview:TVView",
Type: "TVView",
CollectionType: "tvshows",
IsFolder: !0
}, list.push(item)), types.indexOf("Movie") > -1 && (item = {
Name: "Movies",
ServerId: serverId,
Id: "localview:MoviesView",
Type: "MoviesView",
CollectionType: "movies",
IsFolder: !0
}, list.push(item)), types.indexOf("Video") > -1 && (item = {
Name: "Videos",
ServerId: serverId,
Id: "localview:VideosView",
Type: "VideosView",
CollectionType: "videos",
IsFolder: !0
}, list.push(item)), types.indexOf("MusicVideo") > -1 && (item = {
Name: "Music Videos",
ServerId: serverId,
Id: "localview:MusicVideosView",
Type: "MusicVideosView",
CollectionType: "videos",
IsFolder: !0
}, list.push(item)), Promise.resolve(list)
})
}
function updateFiltersForTopLevelView(parentId, mediaTypes, includeItemTypes, query) {
switch (parentId) {
case "MusicView":
return query.Recursive ? includeItemTypes.push("Audio") : includeItemTypes.push("MusicAlbum"), !0;
case "PhotosView":
return query.Recursive ? includeItemTypes.push("Photo") : includeItemTypes.push("PhotoAlbum"), !0;
case "TVView":
return query.Recursive ? includeItemTypes.push("Episode") : includeItemTypes.push("Series"), !0;
case "VideosView":
return query.Recursive, includeItemTypes.push("Video"), !0;
case "MoviesView":
return query.Recursive, includeItemTypes.push("Movie"), !0;
case "MusicVideosView":
return query.Recursive, includeItemTypes.push("MusicVideo"), !0
}
return !1
}
function normalizeId(id) {
return id ? (id = stripStart(id, "localview:"), id = stripStart(id, "local:")) : null
}
function normalizeIdList(val) {
return val ? val.split(",").map(normalizeId) : []
}
function shuffle(array) {
for (var temporaryValue, randomIndex, currentIndex = array.length; 0 !== currentIndex;) randomIndex = Math.floor(Math.random() * currentIndex), currentIndex -= 1, temporaryValue = array[currentIndex], array[currentIndex] = array[randomIndex], array[randomIndex] = temporaryValue;
return array
}
function sortItems(items, query) {
if (!query.SortBy || 0 === query.SortBy.length) return items;
if ("Random" === query.SortBy) return shuffle(items);
var sortSpec = getSortSpec(query);
return items.sort(function(a, b) {
for (var i = 0; i < sortSpec.length; i++) {
var result = compareValues(a, b, sortSpec[i].Field, sortSpec[i].OrderDescending);
if (0 !== result) return result
}
return 0
}), items
}
function compareValues(a, b, field, orderDesc) {
if (!a.hasOwnProperty(field) || !b.hasOwnProperty(field)) return 0;
var valA = a[field],
valB = b[field],
result = 0;
return "string" == typeof valA || "string" == typeof valB ? (valA = valA || "", valB = valB || "", result = valA.toLowerCase().localeCompare(valB.toLowerCase())) : valA > valB ? result = 1 : valA < valB && (result = -1), orderDesc && (result *= -1), result
}
function getSortSpec(query) {
for (var sortFields = (query.SortBy || "").split(","), sortOrders = (query.SortOrder || "").split(","), sortSpec = [], i = 0; i < sortFields.length; i++) {
var orderDesc = !1;
i < sortOrders.length && -1 !== sortOrders[i].toLowerCase().indexOf("desc") && (orderDesc = !0), sortSpec.push({
Field: sortFields[i],
OrderDescending: orderDesc
})
}
return sortSpec
}
function getViewItems(serverId, userId, options) {
var searchParentId = options.ParentId;
searchParentId = normalizeId(searchParentId);
var seasonId = normalizeId(options.SeasonId || options.seasonId),
seriesId = normalizeId(options.SeriesId || options.seriesId),
albumIds = normalizeIdList(options.AlbumIds || options.albumIds),
includeItemTypes = options.IncludeItemTypes ? options.IncludeItemTypes.split(",") : [],
filters = options.Filters ? options.Filters.split(",") : [],
mediaTypes = options.MediaTypes ? options.MediaTypes.split(",") : [];
return updateFiltersForTopLevelView(searchParentId, mediaTypes, includeItemTypes, options) && (searchParentId = null), getServerItems(serverId).then(function(items) {
var itemsMap = new Map,
subtreeIdSet = new Set;
if (items.forEach(function(item) {
item.Item.LocalChildren = [], itemsMap.set(item.Item.Id, item.Item)
}), itemsMap.forEach(function(item, ignored, ignored2) {
if (item.ParentId && itemsMap.has(item.ParentId)) {
itemsMap.get(item.ParentId).LocalChildren.push(item)
}
}), options.Recursive && searchParentId && itemsMap.has(searchParentId)) {
var addSubtreeIds = function(recurseItem) {
subtreeIdSet.has(recurseItem.Id) || subtreeIdSet.add(recurseItem.Id), recurseItem.LocalChildren.forEach(function(childItem) {
addSubtreeIds(childItem)
})
},
searchParentItem = itemsMap.get(searchParentId);
addSubtreeIds(searchParentItem)
}
var resultItems = items.filter(function(item) {
return (!item.SyncStatus || "synced" === item.SyncStatus) && ((!mediaTypes.length || -1 !== mediaTypes.indexOf(item.Item.MediaType || "")) && ((!seriesId || item.Item.SeriesId === seriesId) && ((!seasonId || item.Item.SeasonId === seasonId) && ((!albumIds.length || -1 !== albumIds.indexOf(item.Item.AlbumId || "")) && ((!item.Item.IsFolder || -1 === filters.indexOf("IsNotFolder")) && (!(!item.Item.IsFolder && -1 !== filters.indexOf("IsFolder")) && ((!includeItemTypes.length || -1 !== includeItemTypes.indexOf(item.Item.Type || "")) && (!searchParentId || (options.Recursive ? subtreeIdSet.has(item.Item.Id) : item.Item.ParentId === searchParentId)))))))))
}).map(function(item2) {
return item2.Item
});
return resultItems = sortItems(resultItems, options), options.Limit && (resultItems = resultItems.slice(0, options.Limit)), Promise.resolve(resultItems)
})
}
function removeObsoleteContainerItems(serverId) {
return getServerItems(serverId).then(function(items) {
var seriesItems = items.filter(function(item) {
return "series" === (item.Item.Type || "").toLowerCase()
}),
seasonItems = items.filter(function(item) {
return "season" === (item.Item.Type || "").toLowerCase()
}),
albumItems = items.filter(function(item) {
var type = (item.Item.Type || "").toLowerCase();
return "musicalbum" === type || "photoalbum" === type
}),
requiredSeriesIds = items.filter(function(item) {
return "episode" === (item.Item.Type || "").toLowerCase()
}).map(function(item2) {
return item2.Item.SeriesId
}).filter(filterDistinct),
requiredSeasonIds = items.filter(function(item) {
return "episode" === (item.Item.Type || "").toLowerCase()
}).map(function(item2) {
return item2.Item.SeasonId
}).filter(filterDistinct),
requiredAlbumIds = items.filter(function(item) {
var type = (item.Item.Type || "").toLowerCase();
return "audio" === type || "photo" === type
}).map(function(item2) {
return item2.Item.AlbumId
}).filter(filterDistinct),
obsoleteItems = [];
seriesItems.forEach(function(item) {
requiredSeriesIds.indexOf(item.Item.Id) < 0 && obsoleteItems.push(item)
}), seasonItems.forEach(function(item) {
requiredSeasonIds.indexOf(item.Item.Id) < 0 && obsoleteItems.push(item)
}), albumItems.forEach(function(item) {
requiredAlbumIds.indexOf(item.Item.Id) < 0 && obsoleteItems.push(item)
});
var p = Promise.resolve();
return obsoleteItems.forEach(function(item) {
p = p.then(function() {
return itemrepository.remove(item.ServerId, item.Id)
})
}), p
})
}
function removeLocalItem(localItem) {
return itemrepository.get(localItem.ServerId, localItem.Id).then(function(item) {
var onFileDeletedSuccessOrFail = function() {
return itemrepository.remove(localItem.ServerId, localItem.Id)
},
p = Promise.resolve();
return item.LocalPath && (p = p.then(function() {
return filerepository.deleteFile(item.LocalPath)
})), item && item.Item && item.Item.MediaSources && item.Item.MediaSources.forEach(function(mediaSource) {
mediaSource.MediaStreams && mediaSource.MediaStreams.length > 0 && mediaSource.MediaStreams.forEach(function(mediaStream) {
mediaStream.Path && (p = p.then(function() {
return filerepository.deleteFile(mediaStream.Path)
}))
})
}), p.then(onFileDeletedSuccessOrFail, onFileDeletedSuccessOrFail)
}, function(item) {
return Promise.resolve()
})
}
function addOrUpdateLocalItem(localItem) {
return itemrepository.set(localItem.ServerId, localItem.Id, localItem)
}
function getSubtitleSaveFileName(localItem, mediaPath, language, isForced, format) {
var name = getNameWithoutExtension(mediaPath);
name = filerepository.getValidFileName(name), language && (name += "." + language.toLowerCase()), isForced && (name += ".foreign"), name = name + "." + format.toLowerCase();
var mediaFolder = filerepository.getParentPath(localItem.LocalPath);
return filerepository.combinePath(mediaFolder, name)
}
function getItemFileSize(path) {
return filerepository.getItemFileSize(path)
}
function getNameWithoutExtension(path) {
var fileName = path,
pos = fileName.lastIndexOf(".");
return pos > 0 && (fileName = fileName.substring(0, pos)), fileName
}
function downloadFile(url, localItem) {
var imageUrl = getImageUrl(localItem.Item.ServerId, localItem.Item.Id, {
type: "Primary",
index: 0
});
return transfermanager.downloadFile(url, localItem, imageUrl)
}
function downloadSubtitles(url, fileName) {
return transfermanager.downloadSubtitles(url, fileName)
}
function getImageUrl(serverId, itemId, imageOptions) {
var imageType = imageOptions.type,
index = imageOptions.index,
pathArray = getImagePath(serverId, itemId, imageType, index);
return filerepository.getImageUrl(pathArray)
}
function hasImage(serverId, itemId, imageType, index) {
var pathArray = getImagePath(serverId, itemId, imageType, index),
localFilePath = filerepository.getFullMetadataPath(pathArray);
return filerepository.fileExists(localFilePath).then(function(exists) {
return Promise.resolve(exists)
}, function(err) {
return Promise.resolve(!1)
})
}
function fileExists(localFilePath) {
return filerepository.fileExists(localFilePath)
}
function downloadImage(localItem, url, serverId, itemId, imageType, index) {
var localPathParts = getImagePath(serverId, itemId, imageType, index);
return transfermanager.downloadImage(url, localPathParts)
}
function isDownloadFileInQueue(path) {
return transfermanager.isDownloadFileInQueue(path)
}
function getDownloadItemCount() {
return transfermanager.getDownloadItemCount()
}
function getDirectoryPath(item) {
var parts = [],
itemtype = item.Type.toLowerCase(),
mediaType = (item.MediaType || "").toLowerCase();
"episode" === itemtype || "series" === itemtype || "season" === itemtype ? parts.push("TV") : "video" === mediaType ? parts.push("Videos") : "audio" === itemtype || "musicalbum" === itemtype || "musicartist" === itemtype ? parts.push("Music") : "photo" === itemtype || "photoalbum" === itemtype ? parts.push("Photos") : null;
var albumArtist = item.AlbumArtist;
albumArtist && parts.push(albumArtist);
var seriesName = item.SeriesName;
seriesName && parts.push(seriesName);
var seasonName = item.SeasonName;
seasonName && parts.push(seasonName), item.Album && parts.push(item.Album), ("video" === mediaType && "episode" !== itemtype || item.IsFolder) && parts.push(item.Name);
for (var finalParts = [], i = 0; i < parts.length; i++) finalParts.push(filerepository.getValidFileName(parts[i]));
return finalParts
}
function getImagePath(serverId, itemId, imageType, index) {
var parts = [];
parts.push("images"), index = index || 0, parts.push(itemId + "_" + imageType + "_" + index.toString());
for (var finalParts = [], i = 0; i < parts.length; i++) finalParts.push(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();
return window.performance && "function" == typeof window.performance.now && (d += performance.now()), "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r = (d + 16 * Math.random()) % 16 | 0;
return d = Math.floor(d / 16), ("x" === c ? r : 3 & r | 8).toString(16)
})
}
function startsWith(str, find) {
return !!(str && find && str.length > find.length && 0 === str.indexOf(find))
}
function stripStart(str, find) {
return startsWith(str, find) ? str.substr(find.length) : str
}
function filterDistinct(value, index, self) {
return self.indexOf(value) === index
}
function enableBackgroundCompletion() {
return transfermanager.enableBackgroundCompletion
}
return {
getLocalItem: getLocalItem,
getDirectoryPath: getDirectoryPath,
getLocalFileName: getLocalFileName,
recordUserAction: recordUserAction,
getUserActions: getUserActions,
deleteUserAction: deleteUserAction,
deleteUserActions: deleteUserActions,
removeLocalItem: removeLocalItem,
addOrUpdateLocalItem: addOrUpdateLocalItem,
downloadFile: downloadFile,
downloadSubtitles: downloadSubtitles,
hasImage: hasImage,
downloadImage: downloadImage,
getImageUrl: getImageUrl,
getSubtitleSaveFileName: getSubtitleSaveFileName,
getServerItems: getServerItems,
getItemFileSize: getItemFileSize,
isDownloadFileInQueue: isDownloadFileInQueue,
getDownloadItemCount: getDownloadItemCount,
getViews: getViews,
getViewItems: getViewItems,
resyncTransfers: resyncTransfers,
getItemsFromIds: getItemsFromIds,
removeObsoleteContainerItems: removeObsoleteContainerItems,
fileExists: fileExists,
enableBackgroundCompletion: enableBackgroundCompletion
}
});

View File

@ -1,3 +0,0 @@
{
"main": "apiclient.js"
}

View File

@ -1,45 +0,0 @@
define([], function() {
"use strict";
function getValidFileName(path) {
return path
}
function getFullLocalPath(pathArray) {
return pathArray.join("/")
}
function getPathFromArray(pathArray) {
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)
}
function getImageUrl(pathParts) {
return pathParts.join("/")
}
return {
getValidFileName: getValidFileName,
getFullLocalPath: getFullLocalPath,
getPathFromArray: getPathFromArray,
deleteFile: deleteFile,
deleteDirectory: deleteDirectory,
fileExists: fileExists,
getItemFileSize: getItemFileSize,
getImageUrl: getImageUrl
}
});

View File

@ -1,123 +0,0 @@
define([], function() {
"use strict";
function ServerDatabase(dbName, readyCallback) {
var request = indexedDB.open(dbName, dbVersion);
request.onerror = function(event) {}, request.onupgradeneeded = function(event) {
var db = event.target.result;
db.createObjectStore(dbName).transaction.oncomplete = function(event) {
readyCallback(db)
}
}, request.onsuccess = function(event) {
var db = event.target.result;
readyCallback(db)
}
}
function getDbName(serverId) {
return "items_" + serverId
}
function getDb(serverId, callback) {
var dbName = getDbName(serverId),
db = databases[dbName];
if (db) return void callback(db);
new ServerDatabase(dbName, function(db) {
databases[dbName] = db, callback(db)
})
}
function getServerItemTypes(serverId, userId) {
return getAll(serverId, userId).then(function(all) {
return all.map(function(item2) {
return item2.Item.Type || ""
}).filter(filterDistinct)
})
}
function getAll(serverId, userId) {
return new Promise(function(resolve, reject) {
getDb(serverId, function(db) {
var request, storeName = getDbName(serverId),
transaction = db.transaction([storeName], "readonly"),
objectStore = transaction.objectStore(storeName);
if ("getAll" in objectStore) request = objectStore.getAll(null, 1e4), request.onsuccess = function(event) {
resolve(event.target.result)
};
else {
var results = [];
request = objectStore.openCursor(), request.onsuccess = function(event) {
var cursor = event.target.result;
cursor ? (results.push(cursor.value), cursor.continue()) : resolve(results)
}
}
request.onerror = reject
})
})
}
function get(serverId, key) {
return new Promise(function(resolve, reject) {
getDb(serverId, function(db) {
var storeName = getDbName(serverId),
transaction = db.transaction([storeName], "readonly"),
objectStore = transaction.objectStore(storeName),
request = objectStore.get(key);
request.onerror = reject, request.onsuccess = function(event) {
resolve(request.result)
}
})
})
}
function set(serverId, key, val) {
return new Promise(function(resolve, reject) {
getDb(serverId, function(db) {
var storeName = getDbName(serverId),
transaction = db.transaction([storeName], "readwrite"),
objectStore = transaction.objectStore(storeName),
request = objectStore.put(val, key);
request.onerror = reject, request.onsuccess = resolve
})
})
}
function remove(serverId, key) {
return new Promise(function(resolve, reject) {
getDb(serverId, function(db) {
var storeName = getDbName(serverId),
transaction = db.transaction([storeName], "readwrite"),
objectStore = transaction.objectStore(storeName),
request = objectStore.delete(key);
request.onerror = reject, request.onsuccess = resolve
})
})
}
function clear(serverId) {
return new Promise(function(resolve, reject) {
getDb(serverId, function(db) {
var storeName = getDbName(serverId),
transaction = db.transaction([storeName], "readwrite"),
objectStore = transaction.objectStore(storeName),
request = objectStore.clear();
request.onerror = reject, request.onsuccess = resolve
})
})
}
function filterDistinct(value, index, self) {
return self.indexOf(value) === index
}
var indexedDB = self.indexedDB || self.mozIndexedDB || self.webkitIndexedDB || self.msIndexedDB,
dbVersion = (self.IDBTransaction || self.webkitIDBTransaction || self.msIDBTransaction, self.IDBKeyRange || self.webkitIDBKeyRange || self.msIDBKeyRange, 1),
databases = {};
return {
get: get,
set: set,
remove: remove,
clear: clear,
getAll: getAll,
getServerItemTypes: getServerItemTypes
}
});

View File

@ -1,17 +0,0 @@
define(["connectionManager"], function(connectionManager) {
"use strict";
var isSyncing;
return {
sync: function(options) {
return console.debug("localSync.sync starting..."), isSyncing ? Promise.resolve() : (isSyncing = !0, new Promise(function(resolve, reject) {
require(["multiserversync", "appSettings"], function(MultiServerSync, appSettings) {
options = options || {}, options.cameraUploadServers = appSettings.cameraUploadServers(), (new MultiServerSync).sync(connectionManager, options).then(function() {
isSyncing = null, resolve()
}, function(err) {
isSyncing = null, reject(err)
})
})
}))
}
}
});

View File

@ -1,370 +0,0 @@
define(["localassetmanager"], function(localassetmanager) {
"use strict";
function processDownloadStatus(apiClient, serverInfo, options) {
return console.debug("mediasync: begin processDownloadStatus"), localassetmanager.resyncTransfers().then(function() {
return localassetmanager.getServerItems(serverInfo.Id).then(function(items) {
console.debug("mediasync: begin processDownloadStatus getServerItems completed");
var p = Promise.resolve(),
cnt = 0;
return items.filter(function(item) {
return "transferring" === item.SyncStatus || "queued" === item.SyncStatus
}).forEach(function(item) {
p = p.then(function() {
return reportTransfer(apiClient, item)
}), cnt++
}), p.then(function() {
console.debug("mediasync: exit processDownloadStatus");
console.debug("items reported: " + cnt.toString());
return Promise.resolve();
})
})
})
}
function reportTransfer(apiClient, item) {
return localassetmanager.getItemFileSize(item.LocalPath).then(function(size) {
return size > 0 ? apiClient.reportSyncJobItemTransferred(item.SyncJobItemId).then(function() {
return item.SyncStatus = "synced", console.debug("mediasync: reportSyncJobItemTransferred called for " + item.LocalPath), localassetmanager.addOrUpdateLocalItem(item)
}, function(error) {
return console.error("mediasync: mediasync error on reportSyncJobItemTransferred", error), item.SyncStatus = "error", localassetmanager.addOrUpdateLocalItem(item)
}) : localassetmanager.isDownloadFileInQueue(item.LocalPath).then(function(result) {
return result ? Promise.resolve() : (console.debug("mediasync: reportTransfer: Size is 0 and download no longer in queue. Deleting item."), localassetmanager.removeLocalItem(item).then(function() {
return console.debug("mediasync: reportTransfer: Item deleted."), Promise.resolve()
}, function(err2) {
return console.debug("mediasync: reportTransfer: Failed to delete item.", err2), Promise.resolve()
}))
})
}, function(error) {
return console.error("mediasync: reportTransfer: error on getItemFileSize. Deleting item.", error), localassetmanager.removeLocalItem(item).then(function() {
return console.debug("mediasync: reportTransfer: Item deleted."), Promise.resolve()
}, function(err2) {
return console.error("mediasync: reportTransfer: Failed to delete item.", err2), Promise.resolve()
})
})
}
function reportOfflineActions(apiClient, serverInfo) {
return console.debug("mediasync: begin reportOfflineActions"), localassetmanager.getUserActions(serverInfo.Id).then(function(actions) {
return actions.length ? apiClient.reportOfflineActions(actions).then(function() {
return localassetmanager.deleteUserActions(actions).then(function() {
return console.debug("mediasync: exit reportOfflineActions (actions reported and deleted.)"), Promise.resolve()
})
}, function(err) {
return console.error("mediasync: error on apiClient.reportOfflineActions: " + err.toString()), localassetmanager.deleteUserActions(actions)
}) : (console.debug("mediasync: exit reportOfflineActions (no actions)"), Promise.resolve())
})
}
function syncData(apiClient, serverInfo) {
return console.debug("mediasync: begin syncData"), localassetmanager.getServerItems(serverInfo.Id).then(function(items) {
var completedItems = items.filter(function(item) {
return item && ("synced" === item.SyncStatus || "error" === item.SyncStatus)
}),
request = {
TargetId: apiClient.deviceId(),
LocalItemIds: completedItems.map(function(xitem) {
return xitem.ItemId
})
};
return apiClient.syncData(request).then(function(result) {
return afterSyncData(apiClient, serverInfo, result).then(function() {
return console.debug("mediasync: exit syncData"), Promise.resolve()
}, function(err) {
return console.error("mediasync: error in syncData: " + err.toString()), Promise.resolve()
})
})
})
}
function afterSyncData(apiClient, serverInfo, syncDataResult) {
console.debug("mediasync: begin afterSyncData");
var p = Promise.resolve();
return syncDataResult.ItemIdsToRemove && syncDataResult.ItemIdsToRemove.length > 0 && syncDataResult.ItemIdsToRemove.forEach(function(itemId) {
p = p.then(function() {
return removeLocalItem(itemId, serverInfo.Id)
})
}), p = p.then(function() {
return removeObsoleteContainerItems(serverInfo.Id)
}), p.then(function() {
return console.debug("mediasync: exit afterSyncData"), Promise.resolve()
})
}
function removeObsoleteContainerItems(serverId) {
return console.debug("mediasync: begin removeObsoleteContainerItems"), localassetmanager.removeObsoleteContainerItems(serverId)
}
function removeLocalItem(itemId, serverId) {
return console.debug("mediasync: begin removeLocalItem"), localassetmanager.getLocalItem(serverId, itemId).then(function(item) {
return item ? localassetmanager.removeLocalItem(item) : Promise.resolve()
}, function(err2) {
return console.error("mediasync: removeLocalItem: Failed: ", err2), Promise.resolve()
})
}
function getNewMedia(apiClient, downloadCount) {
return console.debug("mediasync: begin getNewMedia"), apiClient.getReadySyncItems(apiClient.deviceId()).then(function(jobItems) {
console.debug("mediasync: getReadySyncItems returned " + jobItems.length + " items");
var p = Promise.resolve(),
currentCount = downloadCount;
return jobItems.forEach(function(jobItem) {
currentCount++ <= 10 && (p = p.then(function() {
return getNewItem(jobItem, apiClient)
}))
}), p.then(function() {
return console.debug("mediasync: exit getNewMedia"), Promise.resolve()
})
}, function(err) {
return console.error("mediasync: getReadySyncItems: Failed: ", err), Promise.resolve()
})
}
function afterMediaDownloaded(apiClient, jobItem, localItem) {
return console.debug("mediasync: begin afterMediaDownloaded"), getImages(apiClient, jobItem, localItem).then(function() {
var libraryItem = jobItem.Item;
return downloadParentItems(apiClient, jobItem, libraryItem).then(function() {
return getSubtitles(apiClient, jobItem, localItem)
})
})
}
function createLocalItem(libraryItem, jobItem) {
console.debug("localassetmanager: begin createLocalItem");
var item = {
Item: libraryItem,
ItemId: libraryItem.Id,
ServerId: libraryItem.ServerId,
Id: libraryItem.Id
};
return jobItem && (item.SyncJobItemId = jobItem.SyncJobItemId), console.debug("localassetmanager: end createLocalItem"), item
}
function getNewItem(jobItem, apiClient) {
console.debug("mediasync: begin getNewItem");
var libraryItem = jobItem.Item;
return localassetmanager.getLocalItem(libraryItem.ServerId, libraryItem.Id).then(function(existingItem) {
if (existingItem && ("queued" === existingItem.SyncStatus || "transferring" === existingItem.SyncStatus || "synced" === existingItem.SyncStatus) && (console.debug("mediasync: getNewItem: getLocalItem found existing item"), localassetmanager.enableBackgroundCompletion())) return Promise.resolve();
libraryItem.CanDelete = !1, libraryItem.CanDownload = !1, libraryItem.SupportsSync = !1, libraryItem.People = [], libraryItem.Chapters = [], libraryItem.Studios = [], libraryItem.SpecialFeatureCount = null, libraryItem.LocalTrailerCount = null, libraryItem.RemoteTrailers = [];
var localItem = createLocalItem(libraryItem, jobItem);
return localItem.SyncStatus = "queued", downloadMedia(apiClient, jobItem, localItem)
})
}
function downloadParentItems(apiClient, jobItem, libraryItem) {
var p = Promise.resolve();
return libraryItem.SeriesId && (p = p.then(function() {
return downloadItem(apiClient, libraryItem.SeriesId)
})), libraryItem.SeasonId && (p = p.then(function() {
return downloadItem(apiClient, libraryItem.SeasonId).then(function(seasonItem) {
return libraryItem.SeasonPrimaryImageTag = (seasonItem.Item.ImageTags || {}).Primary, Promise.resolve()
})
})), libraryItem.AlbumId && (p = p.then(function() {
return downloadItem(apiClient, libraryItem.AlbumId)
})), p
}
function downloadItem(apiClient, itemId) {
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function(downloadedItem) {
downloadedItem.CanDelete = !1, downloadedItem.CanDownload = !1, downloadedItem.SupportsSync = !1, downloadedItem.People = [], downloadedItem.SpecialFeatureCount = null, downloadedItem.BackdropImageTags = null, downloadedItem.ParentBackdropImageTags = null, downloadedItem.ParentArtImageTag = null, downloadedItem.ParentLogoImageTag = null;
var localItem = createLocalItem(downloadedItem, null);
return localassetmanager.addOrUpdateLocalItem(localItem).then(function() {
return Promise.resolve(localItem)
}, function(err) {
return console.error("mediasync: downloadItem failed: " + err.toString()), Promise.resolve(null)
})
})
}
function ensureLocalPathParts(localItem, jobItem) {
if (!localItem.LocalPathParts) {
var libraryItem = localItem.Item,
parts = localassetmanager.getDirectoryPath(libraryItem);
parts.push(localassetmanager.getLocalFileName(libraryItem, jobItem.OriginalFileName)), localItem.LocalPathParts = parts
}
}
function downloadMedia(apiClient, jobItem, localItem) {
console.debug("mediasync: downloadMedia: start.");
var url = apiClient.getUrl("Sync/JobItems/" + jobItem.SyncJobItemId + "/File", {
api_key: apiClient.accessToken()
});
return ensureLocalPathParts(localItem, jobItem), localassetmanager.downloadFile(url, localItem).then(function(result) {
console.debug("mediasync: downloadMedia-downloadFile returned path: " + result.path);
var localPath = result.path,
libraryItem = localItem.Item;
if (localPath && libraryItem.MediaSources)
for (var i = 0; i < libraryItem.MediaSources.length; i++) {
var mediaSource = libraryItem.MediaSources[i];
mediaSource.Path = localPath, mediaSource.Protocol = "File"
}
return localItem.LocalPath = localPath, localItem.SyncStatus = "transferring", localassetmanager.addOrUpdateLocalItem(localItem).then(function() {
return afterMediaDownloaded(apiClient, jobItem, localItem).then(function() {
return result.isComplete ? (localItem.SyncStatus = "synced", reportTransfer(apiClient, localItem)) : Promise.resolve()
}, function(err) {
return console.debug("mediasync: downloadMedia: afterMediaDownloaded failed: " + err), Promise.reject(err)
})
}, function(err) {
return console.debug("mediasync: downloadMedia: addOrUpdateLocalItem failed: " + err), Promise.reject(err)
})
}, function(err) {
return console.debug("mediasync: downloadMedia: localassetmanager.downloadFile failed: " + err), Promise.reject(err)
})
}
function getImages(apiClient, jobItem, localItem) {
console.debug("mediasync: begin getImages");
var p = Promise.resolve(),
libraryItem = localItem.Item,
serverId = libraryItem.ServerId,
mainImageTag = (libraryItem.ImageTags || {}).Primary;
libraryItem.Id && mainImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.Id, mainImageTag, "Primary")
}));
var logoImageTag = (libraryItem.ImageTags || {}).Logo;
libraryItem.Id && logoImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.Id, logoImageTag, "Logo")
}));
var artImageTag = (libraryItem.ImageTags || {}).Art;
libraryItem.Id && artImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.Id, artImageTag, "Art")
}));
var bannerImageTag = (libraryItem.ImageTags || {}).Banner;
libraryItem.Id && bannerImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.Id, bannerImageTag, "Banner")
}));
var thumbImageTag = (libraryItem.ImageTags || {}).Thumb;
if (libraryItem.Id && thumbImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.Id, thumbImageTag, "Thumb")
})), libraryItem.Id && libraryItem.BackdropImageTags)
for (var i = 0; i < libraryItem.BackdropImageTags.length; i++);
return libraryItem.SeriesId && libraryItem.SeriesPrimaryImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.SeriesId, libraryItem.SeriesPrimaryImageTag, "Primary")
})), libraryItem.SeriesId && libraryItem.SeriesThumbImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.SeriesId, libraryItem.SeriesThumbImageTag, "Thumb")
})), libraryItem.SeasonId && libraryItem.SeasonPrimaryImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.SeasonId, libraryItem.SeasonPrimaryImageTag, "Primary")
})), libraryItem.AlbumId && libraryItem.AlbumPrimaryImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.AlbumId, libraryItem.AlbumPrimaryImageTag, "Primary")
})), libraryItem.ParentThumbItemId && libraryItem.ParentThumbImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.ParentThumbItemId, libraryItem.ParentThumbImageTag, "Thumb")
})), libraryItem.ParentPrimaryImageItemId && libraryItem.ParentPrimaryImageTag && (p = p.then(function() {
return downloadImage(localItem, apiClient, serverId, libraryItem.ParentPrimaryImageItemId, libraryItem.ParentPrimaryImageTag, "Primary")
})), p.then(function() {
return console.debug("mediasync: finished getImages"), localassetmanager.addOrUpdateLocalItem(localItem)
}, function(err) {
return console.error("mediasync: error getImages: " + err.toString()), Promise.resolve()
})
}
function downloadImage(localItem, apiClient, serverId, itemId, imageTag, imageType, index) {
return index = index || 0, localassetmanager.hasImage(serverId, itemId, imageType, index).then(function(hasImage) {
if (hasImage) return console.debug("mediasync: downloadImage - skip existing: " + itemId + " " + imageType + "_" + index.toString()), Promise.resolve();
var maxWidth = 400;
"backdrop" === imageType && (maxWidth = null);
var imageUrl = apiClient.getScaledImageUrl(itemId, {
tag: imageTag,
type: imageType,
maxWidth: maxWidth,
api_key: apiClient.accessToken()
});
return console.debug("mediasync: downloadImage " + itemId + " " + imageType + "_" + index.toString()), localassetmanager.downloadImage(localItem, imageUrl, serverId, itemId, imageType, index).then(function(result) {
return Promise.resolve(result)
}, function(err) {
return console.error("mediasync: error downloadImage: " + err.toString()), Promise.resolve()
})
}, function(err) {
return console.error("mediasync: error downloadImage: " + err.toString()), Promise.resolve()
})
}
function getSubtitles(apiClient, jobItem, localItem) {
if (console.debug("mediasync: begin getSubtitles"), !jobItem.Item.MediaSources.length) return console.debug("mediasync: cannot download subtitles because video has no media source info."), Promise.resolve();
var files = jobItem.AdditionalFiles.filter(function(f) {
return "Subtitles" === f.Type
}),
mediaSource = jobItem.Item.MediaSources[0],
p = Promise.resolve();
return files.forEach(function(file) {
p = p.then(function() {
return getItemSubtitle(file, apiClient, jobItem, localItem, mediaSource)
})
}), p.then(function() {
return console.debug("mediasync: exit getSubtitles"), Promise.resolve()
})
}
function getItemSubtitle(file, apiClient, jobItem, localItem, mediaSource) {
console.debug("mediasync: begin getItemSubtitle");
var subtitleStream = mediaSource.MediaStreams.filter(function(m) {
return "Subtitle" === m.Type && m.Index === file.Index
})[0];
if (!subtitleStream) return console.debug("mediasync: cannot download subtitles because matching stream info was not found."), Promise.resolve();
var url = apiClient.getUrl("Sync/JobItems/" + jobItem.SyncJobItemId + "/AdditionalFiles", {
Name: file.Name,
api_key: apiClient.accessToken()
}),
fileName = localassetmanager.getSubtitleSaveFileName(localItem, jobItem.OriginalFileName, subtitleStream.Language, subtitleStream.IsForced, subtitleStream.Codec);
return localassetmanager.downloadSubtitles(url, fileName).then(function(subtitleResult) {
return localItem.AdditionalFiles && localItem.AdditionalFiles.forEach(function(item) {
item.Name === file.Name && (item.Path = subtitleResult.path)
}), subtitleStream.Path = subtitleResult.path, subtitleStream.DeliveryMethod = "External", localassetmanager.addOrUpdateLocalItem(localItem)
})
}
function checkLocalFileExistence(apiClient, serverInfo, options) {
return options.checkFileExistence ? (console.debug("mediasync: begin checkLocalFileExistence"), localassetmanager.getServerItems(serverInfo.Id).then(function(items) {
var completedItems = items.filter(function(item) {
return item && ("synced" === item.SyncStatus || "error" === item.SyncStatus)
}),
p = Promise.resolve();
return completedItems.forEach(function(completedItem) {
p = p.then(function() {
return localassetmanager.fileExists(completedItem.LocalPath).then(function(exists) {
return exists ? Promise.resolve() : localassetmanager.removeLocalItem(completedItem).then(function() {
return Promise.resolve()
}, function() {
return Promise.resolve()
})
})
})
}), p
})) : Promise.resolve()
}
return function() {
var self = this;
"string" == typeof webWorkerBaseUrl && -1 !== webWorkerBaseUrl.indexOf("ms-appx://") ? self.sync = function(apiClient, serverInfo, options) {
return console.debug("mediasync: start sync"), checkLocalFileExistence(apiClient, serverInfo, options).then(function() {
return processDownloadStatus(apiClient, serverInfo, options).then(function() {
return localassetmanager.getDownloadItemCount().then(function(downloadCount) {
return !0 === options.syncCheckProgressOnly && downloadCount > 2 ? Promise.resolve() : reportOfflineActions(apiClient, serverInfo).then(function() {
return getNewMedia(apiClient, downloadCount).then(function() {
return syncData(apiClient, serverInfo).then(function() {
return console.debug("mediasync: Exit sync"), Promise.resolve()
})
})
})
})
})
}, function(err) {
console.error(err.toString())
})
} : self.sync = function(apiClient, serverInfo, options) {
return console.debug("mediasync: Start sync"), checkLocalFileExistence(apiClient, serverInfo, options).then(function() {
return syncData(apiClient, serverInfo).then(function() {
return processDownloadStatus(apiClient, serverInfo, options).then(function() {
return localassetmanager.getDownloadItemCount().then(function(downloadCount) {
return !0 === options.syncCheckProgressOnly && downloadCount > 2 ? Promise.resolve() : reportOfflineActions(apiClient, serverInfo).then(function() {
return getNewMedia(apiClient, downloadCount).then(function() {
return syncData(apiClient, serverInfo)
})
})
})
})
})
}, function(err) {
console.error(err.toString())
})
}
}
});

View File

@ -1,22 +0,0 @@
define(["serversync"], function(ServerSync) {
"use strict";
function syncNext(connectionManager, servers, index, options, resolve, reject) {
var length = servers.length;
if (index >= length) return console.debug("MultiServerSync.sync complete"), void resolve();
var server = servers[index];
console.debug("Creating ServerSync to server: " + server.Id), (new ServerSync).sync(connectionManager, server, options).then(function() {
console.debug("ServerSync succeeded to server: " + server.Id), syncNext(connectionManager, servers, index + 1, options, resolve, reject)
}, function(err) {
console.error("ServerSync failed to server: " + server.Id + ". " + err), syncNext(connectionManager, servers, index + 1, options, resolve, reject)
})
}
function MultiServerSync() {}
return MultiServerSync.prototype.sync = function(connectionManager, options) {
return console.debug("MultiServerSync.sync starting..."), new Promise(function(resolve, reject) {
var servers = connectionManager.getSavedServers();
syncNext(connectionManager, servers, 0, options, resolve, reject)
})
}, MultiServerSync
});

View File

@ -1,42 +0,0 @@
define([], function() {
"use strict";
function performSync(connectionManager, server, options) {
console.debug("ServerSync.performSync to server: " + server.Id), options = options || {};
var cameraUploadServers = options.cameraUploadServers || [];
console.debug("ServerSync cameraUploadServers: " + JSON.stringify(cameraUploadServers));
var uploadPhotos = -1 !== cameraUploadServers.indexOf(server.Id);
return console.debug("ServerSync uploadPhotos: " + uploadPhotos), (uploadPhotos ? uploadContent(connectionManager, server, options) : Promise.resolve()).then(function() {
return syncMedia(connectionManager, server, options)
})
}
function uploadContent(connectionManager, server, options) {
return new Promise().reject();
}
function syncMedia(connectionManager, server, options) {
return new Promise(function(resolve, reject) {
require(["mediasync"], function(MediaSync) {
var apiClient = connectionManager.getApiClient(server.Id);
(new MediaSync).sync(apiClient, server, options).then(resolve, reject)
})
})
}
function ServerSync() {}
return ServerSync.prototype.sync = function(connectionManager, server, options) {
if (!server.AccessToken && !server.ExchangeToken) return console.debug("Skipping sync to server " + server.Id + " because there is no saved authentication information."), Promise.resolve();
var connectionOptions = {
updateDateLastAccessed: !1,
enableWebSocket: !1,
reportCapabilities: !1,
enableAutomaticBitrateDetection: !1
};
return connectionManager.connectToServer(server, connectionOptions).then(function(result) {
return "SignedIn" === result.State ? performSync(connectionManager, server, options) : (console.error("Unable to connect to server id: " + server.Id), Promise.reject())
}, function(err) {
throw console.error("Unable to connect to server id: " + server.Id), err
})
}, ServerSync
});

View File

@ -1,30 +0,0 @@
define([], function() {
"use strict";
function downloadFile(url, folder, localItem, imageUrl) {
return Promise.reject()
}
function downloadSubtitles(url, folder, fileName) {
return Promise.reject()
}
function downloadImage(url, folder, fileName) {
return Promise.reject()
}
function resyncTransfers() {
return Promise.resolve()
}
function getDownloadItemCount() {
return Promise.resolve(0)
}
return {
downloadFile: downloadFile,
downloadSubtitles: downloadSubtitles,
downloadImage: downloadImage,
resyncTransfers: resyncTransfers,
getDownloadItemCount: getDownloadItemCount
}
});

View File

@ -1,108 +0,0 @@
define([], function() {
"use strict";
function getDb(callback) {
var db = databaseInstance;
if (db) return void callback(db);
var request = indexedDB.open(dbName, dbVersion);
request.onerror = function(event) {}, request.onupgradeneeded = function(event) {
var db = event.target.result;
db.createObjectStore(dbName).transaction.oncomplete = function(event) {
callback(db)
}
}, request.onsuccess = function(event) {
var db = event.target.result;
callback(db)
}
}
function getByServerId(serverId) {
return getAll().then(function(items) {
return items.filter(function(item) {
return item.ServerId === serverId
})
})
}
function getAll() {
return new Promise(function(resolve, reject) {
getDb(function(db) {
var request, storeName = dbName,
transaction = db.transaction([storeName], "readonly"),
objectStore = transaction.objectStore(storeName);
if ("getAll" in objectStore) request = objectStore.getAll(null, 1e4), request.onsuccess = function(event) {
resolve(event.target.result)
};
else {
var results = [];
request = objectStore.openCursor(), request.onsuccess = function(event) {
var cursor = event.target.result;
cursor ? (results.push(cursor.value), cursor.continue()) : resolve(results)
}
}
request.onerror = reject
})
})
}
function get(key) {
return new Promise(function(resolve, reject) {
getDb(function(db) {
var storeName = dbName,
transaction = db.transaction([storeName], "readonly"),
objectStore = transaction.objectStore(storeName),
request = objectStore.get(key);
request.onerror = reject, request.onsuccess = function(event) {
resolve(request.result)
}
})
})
}
function set(key, val) {
return new Promise(function(resolve, reject) {
getDb(function(db) {
var storeName = dbName,
transaction = db.transaction([storeName], "readwrite"),
objectStore = transaction.objectStore(storeName),
request = objectStore.put(val, key);
request.onerror = reject, request.onsuccess = resolve
})
})
}
function remove(key) {
return new Promise(function(resolve, reject) {
getDb(function(db) {
var storeName = dbName,
transaction = db.transaction([storeName], "readwrite"),
objectStore = transaction.objectStore(storeName),
request = objectStore.delete(key);
request.onerror = reject, request.onsuccess = resolve
})
})
}
function clear() {
return new Promise(function(resolve, reject) {
getDb(function(db) {
var storeName = dbName,
transaction = db.transaction([storeName], "readwrite"),
objectStore = transaction.objectStore(storeName),
request = objectStore.clear();
request.onerror = reject, request.onsuccess = resolve
})
})
}
var databaseInstance, indexedDB = self.indexedDB || self.mozIndexedDB || self.webkitIndexedDB || self.msIndexedDB,
dbName = (self.IDBTransaction || self.webkitIDBTransaction || self.msIDBTransaction, self.IDBKeyRange || self.webkitIDBKeyRange || self.msIDBKeyRange, "useractions"),
dbVersion = 1;
return {
get: get,
set: set,
remove: remove,
clear: clear,
getAll: getAll,
getByServerId: getByServerId
}
});

View File

@ -912,12 +912,16 @@ define(['dom', 'layoutManager', 'inputManager', 'connectionManager', 'events', '
renderHeader(); renderHeader();
events.on(connectionManager, 'localusersignedin', function (e, user) { events.on(connectionManager, 'localusersignedin', function (e, user) {
var currentApiClient = connectionManager.getApiClient(user.ServerId);
currentDrawerType = null; currentDrawerType = null;
currentUser = { currentUser = {
localUser: user localUser: user
}; };
loadNavDrawer(); loadNavDrawer();
connectionManager.user(connectionManager.getApiClient(user.ServerId)).then(function (user) {
connectionManager.user(currentApiClient).then(function (user) {
currentUser = user; currentUser = user;
updateUserInHeader(user); updateUserInHeader(user);
}); });

View File

@ -378,8 +378,6 @@ var AppInfo = {};
define('lazyLoader', [componentsPath + '/lazyloader/lazyloader-intersectionobserver'], returnFirstDependency); define('lazyLoader', [componentsPath + '/lazyloader/lazyloader-intersectionobserver'], returnFirstDependency);
define('shell', [componentsPath + '/shell'], returnFirstDependency); define('shell', [componentsPath + '/shell'], returnFirstDependency);
define('apiclient', [bowerPath + '/apiclient/apiclient'], returnFirstDependency);
if ('registerElement' in document) { if ('registerElement' in document) {
define('registerElement', []); define('registerElement', []);
} else if (browser.msie) { } else if (browser.msie) {
@ -401,13 +399,8 @@ var AppInfo = {};
define('loading', [componentsPath + '/loading/loading'], returnFirstDependency); define('loading', [componentsPath + '/loading/loading'], returnFirstDependency);
define('multi-download', [componentsPath + '/multidownload'], returnFirstDependency); define('multi-download', [componentsPath + '/multidownload'], returnFirstDependency);
define('fileDownloader', [componentsPath + '/filedownloader'], returnFirstDependency); define('fileDownloader', [componentsPath + '/filedownloader'], returnFirstDependency);
define('localassetmanager', [bowerPath + '/apiclient/localassetmanager'], returnFirstDependency);
define('castSenderApiLoader', [componentsPath + '/castSenderApi'], returnFirstDependency); define('castSenderApiLoader', [componentsPath + '/castSenderApi'], returnFirstDependency);
define('transfermanager', [bowerPath + '/apiclient/sync/transfermanager'], returnFirstDependency);
define('filerepository', [bowerPath + '/apiclient/sync/filerepository'], returnFirstDependency);
define('localsync', [bowerPath + '/apiclient/sync/localsync'], returnFirstDependency);
} }
function init() { function init() {
@ -696,7 +689,12 @@ var AppInfo = {};
'intersection-observer', 'intersection-observer',
'classlist-polyfill', 'classlist-polyfill',
'screenfull', 'screenfull',
'headroom' 'headroom',
'apiclient',
'events',
'credentialprovider',
'connectionManagerFactory',
'appStorage'
] ]
}, },
urlArgs: urlArgs, urlArgs: urlArgs,
@ -743,17 +741,6 @@ var AppInfo = {};
define('appFooter', [componentsPath + '/appfooter/appfooter'], returnFirstDependency); define('appFooter', [componentsPath + '/appfooter/appfooter'], returnFirstDependency);
define('appFooter-shared', ['appFooter'], createSharedAppFooter); define('appFooter-shared', ['appFooter'], createSharedAppFooter);
// TODO pull apiclient out of this repository
define('events', [bowerPath + '/apiclient/events'], returnFirstDependency);
define('credentialprovider', [bowerPath + '/apiclient/credentialprovider'], returnFirstDependency);
define('connectionManagerFactory', [bowerPath + '/apiclient/connectionmanager'], returnFirstDependency);
define('appStorage', [bowerPath + '/apiclient/appStorage'], returnFirstDependency);
define('serversync', [bowerPath + '/apiclient/sync/serversync'], returnFirstDependency);
define('multiserversync', [bowerPath + '/apiclient/sync/multiserversync'], returnFirstDependency);
define('mediasync', [bowerPath + '/apiclient/sync/mediasync'], returnFirstDependency);
define('itemrepository', [bowerPath + '/apiclient/sync/itemrepository'], returnFirstDependency);
define('useractionrepository', [bowerPath + '/apiclient/sync/useractionrepository'], returnFirstDependency);
// TODO remove these libraries // TODO remove these libraries
// all of these have been modified so we need to fix that first // all of these have been modified so we need to fix that first
define('scroller', [bowerPath + '/scroller'], returnFirstDependency); define('scroller', [bowerPath + '/scroller'], returnFirstDependency);

View File

@ -11,7 +11,7 @@ module.exports = merge(common, {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
libraryTarget: 'amd-require' libraryTarget: 'amd-require'
}, },
devtool: '#inline-source-map', devtool: 'inline-source-map',
module: { module: {
rules: [ rules: [
{ {

751
yarn.lock

File diff suppressed because it is too large Load Diff