mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-02 05:04:31 -04:00
fixes #1001 - Support downloading
This commit is contained in:
parent
4ae6b5f675
commit
b6d59c7688
@ -226,6 +226,18 @@ namespace MediaBrowser.Api.Library
|
|||||||
public string TvdbId { get; set; }
|
public string TvdbId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")]
|
||||||
|
[Authenticated(Roles = "download")]
|
||||||
|
public class GetDownload
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the id.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The id.</value>
|
||||||
|
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class LibraryService
|
/// Class LibraryService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -289,6 +301,28 @@ namespace MediaBrowser.Api.Library
|
|||||||
Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
|
Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Get(GetDownload request)
|
||||||
|
{
|
||||||
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
|
|
||||||
|
if (!item.CanDelete())
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Item does not support downloading");
|
||||||
|
}
|
||||||
|
|
||||||
|
var headers = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
// Quotes are valid in linux. They'll possibly cause issues here
|
||||||
|
var filename = Path.GetFileName(item.Path).Replace("\"", string.Empty);
|
||||||
|
headers["Content-Disposition"] = string.Format("inline; filename=\"{0}\"", filename);
|
||||||
|
|
||||||
|
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
|
||||||
|
{
|
||||||
|
Path = item.Path,
|
||||||
|
ResponseHeaders = headers
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public object Get(GetFile request)
|
public object Get(GetFile request)
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(request.Id);
|
var item = _libraryManager.GetItemById(request.Id);
|
||||||
@ -458,24 +492,10 @@ namespace MediaBrowser.Api.Library
|
|||||||
var auth = _authContext.GetAuthorizationInfo(Request);
|
var auth = _authContext.GetAuthorizationInfo(Request);
|
||||||
var user = _userManager.GetUserById(auth.UserId);
|
var user = _userManager.GetUserById(auth.UserId);
|
||||||
|
|
||||||
if (item is Playlist || item is BoxSet)
|
if (!item.CanDelete(user))
|
||||||
{
|
|
||||||
// For now this is allowed if user can see the playlist
|
|
||||||
}
|
|
||||||
else if (item is ILiveTvRecording)
|
|
||||||
{
|
|
||||||
if (!user.Policy.EnableLiveTvManagement)
|
|
||||||
{
|
{
|
||||||
throw new UnauthorizedAccessException();
|
throw new UnauthorizedAccessException();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!user.Policy.EnableContentDeletion)
|
|
||||||
{
|
|
||||||
throw new UnauthorizedAccessException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var task = _libraryManager.DeleteItem(item);
|
var task = _libraryManager.DeleteItem(item);
|
||||||
|
|
||||||
|
@ -323,13 +323,13 @@ namespace MediaBrowser.Api.Playback
|
|||||||
switch (qualitySetting)
|
switch (qualitySetting)
|
||||||
{
|
{
|
||||||
case EncodingQuality.HighSpeed:
|
case EncodingQuality.HighSpeed:
|
||||||
param += " -crf 23";
|
param += " -subq 0 -crf 23";
|
||||||
break;
|
break;
|
||||||
case EncodingQuality.HighQuality:
|
case EncodingQuality.HighQuality:
|
||||||
param += " -crf 20";
|
param += " -subq 3 -crf 20";
|
||||||
break;
|
break;
|
||||||
case EncodingQuality.MaxQuality:
|
case EncodingQuality.MaxQuality:
|
||||||
param += " -crf 18";
|
param += " -subq 6 -crf 18";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,7 +507,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return param;
|
return "-pix_fmt yuv420p " + param;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetAudioFilterParam(StreamState state, bool isHls)
|
protected string GetAudioFilterParam(StreamState state, bool isHls)
|
||||||
|
@ -97,6 +97,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
// Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js
|
||||||
format = " -f mp4 -movflags frag_keyframe+empty_moov";
|
format = " -f mp4 -movflags frag_keyframe+empty_moov";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,5 +67,10 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata");
|
return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ using MediaBrowser.Model.Channels;
|
|||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Users;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Model.Users;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Channels
|
namespace MediaBrowser.Controller.Channels
|
||||||
{
|
{
|
||||||
@ -89,5 +89,10 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
using System;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
using MediaBrowser.Model.Channels;
|
using MediaBrowser.Model.Channels;
|
||||||
using MediaBrowser.Model.Configuration;
|
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
|
using MediaBrowser.Model.Users;
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Users;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Channels
|
namespace MediaBrowser.Controller.Channels
|
||||||
{
|
{
|
||||||
@ -76,5 +75,10 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
|
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,11 @@ using MediaBrowser.Model.Channels;
|
|||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Users;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Model.Users;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Channels
|
namespace MediaBrowser.Controller.Channels
|
||||||
{
|
{
|
||||||
@ -119,5 +119,10 @@ namespace MediaBrowser.Controller.Channels
|
|||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
|
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The _virtual children
|
/// The _virtual children
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -113,6 +113,13 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDownload()
|
||||||
|
{
|
||||||
|
var locationType = LocationType;
|
||||||
|
return locationType != LocationType.Remote &&
|
||||||
|
locationType != LocationType.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the artist.
|
/// Gets or sets the artist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
using System.Runtime.Serialization;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Common.Progress;
|
|
||||||
using MediaBrowser.Controller.Providers;
|
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Users;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Users;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Audio
|
namespace MediaBrowser.Controller.Entities.Audio
|
||||||
{
|
{
|
||||||
@ -35,6 +34,11 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
get { return true; }
|
get { return true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return !IsAccessedByName;
|
||||||
|
}
|
||||||
|
|
||||||
protected override IEnumerable<BaseItem> ActualChildren
|
protected override IEnumerable<BaseItem> ActualChildren
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -39,6 +39,11 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is owned item.
|
/// Gets a value indicating whether this instance is owned item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -239,6 +239,38 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
get { return this.GetImagePath(ImageType.Primary); }
|
get { return this.GetImagePath(ImageType.Primary); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual bool CanDelete()
|
||||||
|
{
|
||||||
|
var locationType = LocationType;
|
||||||
|
return locationType != LocationType.Remote &&
|
||||||
|
locationType != LocationType.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool IsAuthorizedToDelete(User user)
|
||||||
|
{
|
||||||
|
return user.Policy.EnableContentDeletion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanDelete(User user)
|
||||||
|
{
|
||||||
|
return CanDelete() && IsAuthorizedToDelete(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool CanDownload()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool IsAuthorizedToDownload(User user)
|
||||||
|
{
|
||||||
|
return user.Policy.EnableContentDownloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanDownload(User user)
|
||||||
|
{
|
||||||
|
return CanDownload() && IsAuthorizedToDownload(user);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the date created.
|
/// Gets or sets the date created.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -11,5 +11,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
get { return null; }
|
get { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
@ -37,6 +38,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Tags = new List<string>();
|
Tags = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDownload()
|
||||||
|
{
|
||||||
|
var locationType = LocationType;
|
||||||
|
return locationType != LocationType.Remote &&
|
||||||
|
locationType != LocationType.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
{
|
{
|
||||||
return config.BlockUnratedItems.Contains(UnratedItem.Book);
|
return config.BlockUnratedItems.Contains(UnratedItem.Book);
|
||||||
|
@ -35,6 +35,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public string CollectionType { get; set; }
|
public string CollectionType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Users;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using MediaBrowser.Model.Users;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -38,6 +38,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
public List<Guid> RemoteTrailerIds { get; set; }
|
public List<Guid> RemoteTrailerIds { get; set; }
|
||||||
|
|
||||||
|
public override bool CanDownload()
|
||||||
|
{
|
||||||
|
var locationType = LocationType;
|
||||||
|
return locationType != LocationType.Remote &&
|
||||||
|
locationType != LocationType.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the tags.
|
/// Gets or sets the tags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -43,6 +43,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems)
|
public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems)
|
||||||
{
|
{
|
||||||
return inputItems.Where(GetItemFilter());
|
return inputItems.Where(GetItemFilter());
|
||||||
|
@ -34,6 +34,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is owned item.
|
/// Gets a value indicating whether this instance is owned item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,6 +15,10 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
||||||
IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems);
|
IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the item filter.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Func<BaseItem, System.Boolean>.</returns>
|
||||||
Func<BaseItem, bool> GetItemFilter();
|
Func<BaseItem, bool> GetItemFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,11 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the trailer ids.
|
/// Gets the trailer ids.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is owned item.
|
/// Gets a value indicating whether this instance is owned item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -40,6 +40,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is owned item.
|
/// Gets a value indicating whether this instance is owned item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -40,6 +40,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return result.Items;
|
return result.Items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
|
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
|
||||||
{
|
{
|
||||||
var result = GetItems(new InternalItemsQuery
|
var result = GetItems(new InternalItemsQuery
|
||||||
|
@ -64,6 +64,19 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
LinkedAlternateVersions = new List<LinkedChild>();
|
LinkedAlternateVersions = new List<LinkedChild>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDownload()
|
||||||
|
{
|
||||||
|
if (VideoType == VideoType.HdDvd || VideoType == VideoType.Dvd ||
|
||||||
|
VideoType == VideoType.BluRay)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationType = LocationType;
|
||||||
|
return locationType != LocationType.Remote &&
|
||||||
|
locationType != LocationType.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsAddingToPlaylist
|
public override bool SupportsAddingToPlaylist
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is owned item.
|
/// Gets a value indicating whether this instance is owned item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -25,5 +25,9 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
Task RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken);
|
Task RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken);
|
||||||
|
|
||||||
PlayAccess GetPlayAccess(User user);
|
PlayAccess GetPlayAccess(User user);
|
||||||
|
|
||||||
|
bool CanDelete();
|
||||||
|
|
||||||
|
bool CanDelete(User user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
@ -93,5 +94,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
|
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
|
{
|
||||||
|
return user.Policy.EnableLiveTvManagement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System.Runtime.Serialization;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
@ -8,6 +7,7 @@ using MediaBrowser.Model.MediaInfo;
|
|||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
@ -135,5 +135,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata");
|
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
using System.Runtime.Serialization;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
|
using MediaBrowser.Model.Users;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
|
||||||
using MediaBrowser.Model.Users;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
@ -215,5 +215,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
|
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool CanDelete()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,5 +92,10 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
{
|
{
|
||||||
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
|
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
|
{
|
||||||
|
return user.Policy.EnableLiveTvManagement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities.Audio;
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Querying;
|
using MediaBrowser.Model.Querying;
|
||||||
using System;
|
using System;
|
||||||
@ -40,6 +38,11 @@ namespace MediaBrowser.Controller.Playlists
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsSaveLocalMetadataEnabled()
|
public override bool IsSaveLocalMetadataEnabled()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -631,13 +631,13 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
switch (qualitySetting)
|
switch (qualitySetting)
|
||||||
{
|
{
|
||||||
case EncodingQuality.HighSpeed:
|
case EncodingQuality.HighSpeed:
|
||||||
param += " -crf 23";
|
param += " -subq 0 -crf 23";
|
||||||
break;
|
break;
|
||||||
case EncodingQuality.HighQuality:
|
case EncodingQuality.HighQuality:
|
||||||
param += " -crf 20";
|
param += " -subq 3 -crf 20";
|
||||||
break;
|
break;
|
||||||
case EncodingQuality.MaxQuality:
|
case EncodingQuality.MaxQuality:
|
||||||
param += " -crf 18";
|
param += " -subq 6 -crf 18";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -740,7 +740,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
|||||||
param += " -level " + state.Options.Level.Value.ToString(UsCulture);
|
param += " -level " + state.Options.Level.Value.ToString(UsCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
return param;
|
return "-pix_fmt yuv420p " + param;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetVideoBitrateParam(EncodingJob state, string videoCodec, bool isHls)
|
protected string GetVideoBitrateParam(EncodingJob state, string videoCodec, bool isHls)
|
||||||
|
@ -56,6 +56,8 @@ namespace MediaBrowser.Model.Dto
|
|||||||
public int? AirsBeforeEpisodeNumber { get; set; }
|
public int? AirsBeforeEpisodeNumber { get; set; }
|
||||||
public int? AbsoluteEpisodeNumber { get; set; }
|
public int? AbsoluteEpisodeNumber { get; set; }
|
||||||
public bool? DisplaySpecialsWithSeasons { get; set; }
|
public bool? DisplaySpecialsWithSeasons { get; set; }
|
||||||
|
public bool? CanDelete { get; set; }
|
||||||
|
public bool? CanDownload { get; set; }
|
||||||
|
|
||||||
public string PreferredMetadataLanguage { get; set; }
|
public string PreferredMetadataLanguage { get; set; }
|
||||||
public string PreferredMetadataCountryCode { get; set; }
|
public string PreferredMetadataCountryCode { get; set; }
|
||||||
|
@ -99,6 +99,12 @@ namespace MediaBrowser.Model.LiveTv
|
|||||||
/// <value>The path.</value>
|
/// <value>The path.</value>
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this instance can delete.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>null</c> if [can delete] contains no value, <c>true</c> if [can delete]; otherwise, <c>false</c>.</value>
|
||||||
|
public bool? CanDelete { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overview of the recording.
|
/// Overview of the recording.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
|
namespace MediaBrowser.Model.Querying
|
||||||
namespace MediaBrowser.Model.Querying
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to control the data that gets attached to DtoBaseItems
|
/// Used to control the data that gets attached to DtoBaseItems
|
||||||
@ -26,6 +25,16 @@ namespace MediaBrowser.Model.Querying
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Budget,
|
Budget,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The can delete
|
||||||
|
/// </summary>
|
||||||
|
CanDelete,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The can download
|
||||||
|
/// </summary>
|
||||||
|
CanDownload,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The chapters
|
/// The chapters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -42,6 +42,7 @@ namespace MediaBrowser.Model.Users
|
|||||||
|
|
||||||
public bool EnableMediaPlayback { get; set; }
|
public bool EnableMediaPlayback { get; set; }
|
||||||
public bool EnableContentDeletion { get; set; }
|
public bool EnableContentDeletion { get; set; }
|
||||||
|
public bool EnableContentDownloading { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether [enable synchronize].
|
/// Gets or sets a value indicating whether [enable synchronize].
|
||||||
@ -80,6 +81,8 @@ namespace MediaBrowser.Model.Users
|
|||||||
|
|
||||||
EnabledDevices = new string[] { };
|
EnabledDevices = new string[] { };
|
||||||
EnableAllDevices = true;
|
EnableAllDevices = true;
|
||||||
|
|
||||||
|
EnableContentDownloading = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,6 +284,20 @@ namespace MediaBrowser.Server.Implementations.Dto
|
|||||||
AttachLinkedChildImages(dto, playlist, user, options);
|
AttachLinkedChildImages(dto, playlist, user, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fields.Contains(ItemFields.CanDelete))
|
||||||
|
{
|
||||||
|
dto.CanDelete = user == null
|
||||||
|
? item.CanDelete()
|
||||||
|
: item.CanDelete(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.Contains(ItemFields.CanDownload))
|
||||||
|
{
|
||||||
|
dto.CanDownload = user == null
|
||||||
|
? item.CanDownload()
|
||||||
|
: item.CanDownload(user);
|
||||||
|
}
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||||||
ValidateUserAccess(user, request, authAttribtues, auth);
|
ValidateUserAccess(user, request, authAttribtues, auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsExemptFromRoles(auth, authAttribtues))
|
var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"];
|
||||||
|
|
||||||
|
if (!IsExemptFromRoles(auth, authAttribtues, info))
|
||||||
{
|
{
|
||||||
var roles = authAttribtues.GetRoles().ToList();
|
var roles = authAttribtues.GetRoles().ToList();
|
||||||
|
|
||||||
@ -142,7 +144,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||||||
StringComparer.OrdinalIgnoreCase);
|
StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues)
|
private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, AuthenticationInfo tokenInfo)
|
||||||
{
|
{
|
||||||
if (!_config.Configuration.IsStartupWizardCompleted &&
|
if (!_config.Configuration.IsStartupWizardCompleted &&
|
||||||
authAttribtues.AllowBeforeStartupWizard)
|
authAttribtues.AllowBeforeStartupWizard)
|
||||||
@ -150,6 +152,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(auth.Token))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenInfo != null && string.IsNullOrWhiteSpace(tokenInfo.UserId))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +187,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (roles.Contains("download", StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (user == null || !user.Policy.EnableContentDownloading)
|
||||||
|
{
|
||||||
|
throw new SecurityException("User does not have download access.")
|
||||||
|
{
|
||||||
|
SecurityExceptionType = SecurityExceptionType.Unauthenticated
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsValidConnectKey(string token)
|
private bool IsValidConnectKey(string token)
|
||||||
|
@ -229,6 +229,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|||||||
ServerId = _appHost.SystemId
|
ServerId = _appHost.SystemId
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dto.CanDelete = user == null
|
||||||
|
? recording.CanDelete()
|
||||||
|
: recording.CanDelete(user);
|
||||||
|
|
||||||
dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
|
dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
|
||||||
|
|
||||||
if (info.Status == RecordingStatus.InProgress)
|
if (info.Status == RecordingStatus.InProgress)
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
"LabelFailed": "(failed)",
|
"LabelFailed": "(failed)",
|
||||||
"ButtonHelp": "Help",
|
"ButtonHelp": "Help",
|
||||||
"ButtonSave": "Save",
|
"ButtonSave": "Save",
|
||||||
|
"ButtonDownload": "Download",
|
||||||
"SyncJobStatusQueued": "Queued",
|
"SyncJobStatusQueued": "Queued",
|
||||||
"SyncJobStatusConverting": "Converting",
|
"SyncJobStatusConverting": "Converting",
|
||||||
"SyncJobStatusFailed": "Failed",
|
"SyncJobStatusFailed": "Failed",
|
||||||
@ -56,6 +57,7 @@
|
|||||||
"SyncJobStatusReadyToTransfer": "Ready to Transfer",
|
"SyncJobStatusReadyToTransfer": "Ready to Transfer",
|
||||||
"SyncJobStatusTransferring": "Transferring",
|
"SyncJobStatusTransferring": "Transferring",
|
||||||
"SyncJobStatusCompletedWithError": "Synced with errors",
|
"SyncJobStatusCompletedWithError": "Synced with errors",
|
||||||
|
"SyncJobItemStatusReadyToTransfer": "Ready to Transfer",
|
||||||
"LabelCollection": "Collection",
|
"LabelCollection": "Collection",
|
||||||
"HeaderAddToCollection": "Add to Collection",
|
"HeaderAddToCollection": "Add to Collection",
|
||||||
"NewCollectionNameExample": "Example: Star Wars Collection",
|
"NewCollectionNameExample": "Example: Star Wars Collection",
|
||||||
|
@ -285,10 +285,10 @@
|
|||||||
"ButtonHelp": "Help",
|
"ButtonHelp": "Help",
|
||||||
"OptionAllowUserToManageServer": "Allow this user to manage the server",
|
"OptionAllowUserToManageServer": "Allow this user to manage the server",
|
||||||
"HeaderFeatureAccess": "Feature Access",
|
"HeaderFeatureAccess": "Feature Access",
|
||||||
"OptionAllowMediaPlayback": "Allow media playback",
|
"OptionAllowMediaPlayback": "Media playback",
|
||||||
"OptionAllowBrowsingLiveTv": "Allow browsing of live tv",
|
"OptionAllowBrowsingLiveTv": "Live TV",
|
||||||
"OptionAllowDeleteLibraryContent": "Allow deletion of library content",
|
"OptionAllowDeleteLibraryContent": "Media deletion",
|
||||||
"OptionAllowManageLiveTv": "Allow management of live tv recordings",
|
"OptionAllowManageLiveTv": "Live TV recording management",
|
||||||
"OptionAllowRemoteControlOthers": "Allow remote control of other users",
|
"OptionAllowRemoteControlOthers": "Allow remote control of other users",
|
||||||
"OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
|
"OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
|
||||||
"OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.",
|
"OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.",
|
||||||
@ -1362,7 +1362,8 @@
|
|||||||
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
|
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
|
||||||
"TabActivity": "Activity",
|
"TabActivity": "Activity",
|
||||||
"TitleSync": "Sync",
|
"TitleSync": "Sync",
|
||||||
"OptionAllowSyncContent": "Allow syncing media to devices",
|
"OptionAllowSyncContent": "Sync",
|
||||||
|
"OptionAllowContentDownloading": "Media downloading",
|
||||||
"NameSeasonUnknown": "Season Unknown",
|
"NameSeasonUnknown": "Season Unknown",
|
||||||
"NameSeasonNumber": "Season {0}",
|
"NameSeasonNumber": "Season {0}",
|
||||||
"LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)",
|
"LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)",
|
||||||
|
@ -311,8 +311,10 @@ namespace MediaBrowser.Server.Implementations.Sync
|
|||||||
var itemByName = item as IItemByName;
|
var itemByName = item as IItemByName;
|
||||||
if (itemByName != null)
|
if (itemByName != null)
|
||||||
{
|
{
|
||||||
|
var itemByNameFilter = itemByName.GetItemFilter();
|
||||||
|
|
||||||
return user.RootFolder
|
return user.RootFolder
|
||||||
.GetRecursiveChildren(user, itemByName.GetItemFilter());
|
.GetRecursiveChildren(user, i => !i.IsFolder && itemByNameFilter(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.IsFolder)
|
if (item.IsFolder)
|
||||||
|
@ -414,7 +414,6 @@ namespace MediaBrowser.WebDashboard.Api
|
|||||||
"indexpage.js",
|
"indexpage.js",
|
||||||
"itembynamedetailpage.js",
|
"itembynamedetailpage.js",
|
||||||
"itemdetailpage.js",
|
"itemdetailpage.js",
|
||||||
"itemgallery.js",
|
|
||||||
"itemlistpage.js",
|
"itemlistpage.js",
|
||||||
"librarypathmapping.js",
|
"librarypathmapping.js",
|
||||||
"reports.js",
|
"reports.js",
|
||||||
|
@ -1656,9 +1656,6 @@
|
|||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="dashboard-ui\itemgallery.html">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\librarysettings.html">
|
<Content Include="dashboard-ui\librarysettings.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
@ -1707,9 +1704,6 @@
|
|||||||
<Content Include="dashboard-ui\scripts\edititemmetadata.js">
|
<Content Include="dashboard-ui\scripts\edititemmetadata.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\itemgallery.js">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</Content>
|
|
||||||
<Content Include="dashboard-ui\scripts\librarysettings.js">
|
<Content Include="dashboard-ui\scripts\librarysettings.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user