Skip to content

Commit

Permalink
Getting the saved data and models right
Browse files Browse the repository at this point in the history
  • Loading branch information
abjerner committed Mar 23, 2022
1 parent edd331a commit da4c970
Show file tree
Hide file tree
Showing 11 changed files with 512 additions and 114 deletions.
9 changes: 7 additions & 2 deletions src/Limbo.Umbraco.YouTube/Controllers/YouTubeController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq;
using Limbo.Umbraco.YouTube.Models.Credentials;
using Limbo.Umbraco.YouTube.Options;
using Limbo.Umbraco.YouTube.Services;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
Expand Down Expand Up @@ -57,13 +58,17 @@ public class YouTubeController : UmbracoAuthorizedApiController {
JObject embed = JObject.FromObject(options);
embed.Remove("videoId");

return new {
JObject json = JObject.FromObject(new {
credentials = new {
key = credentials.Key
},
video = video.JObject,
embed
};
});

if (!embed.Properties().Any()) json.Remove("embed");

return json;

}

Expand Down
32 changes: 32 additions & 0 deletions src/Limbo.Umbraco.YouTube/Extensions/YouTubeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using Skybrud.Essentials.Http.Collections;
using Skybrud.Essentials.Strings;

namespace Limbo.Umbraco.YouTube.Extensions {

internal static class YouTubeExtensions {

public static void Deconstruct<T>(this IList<T> list, out T first, out T second) {
// TODO: Move to Skybrud.Essentials
first = list.Count > 0 ? list[0] : default;
second = list.Count > 1 ? list[1] : default;
}

public static bool TryGetBoolean(this IHttpQueryString query, string key, out bool result) {
// TODO: Move to Skybrud.Essentials.Http
return StringUtils.TryParseBoolean(query[key], out result);
}

public static bool TryGetInt32(this IHttpQueryString query, string key, out int result) {
// TODO: Move to Skybrud.Essentials.Http
return int.TryParse(query[key], out result);
}

public static bool TryGetDouble(this IHttpQueryString query, string key, out double result) {
// TODO: Move to Skybrud.Essentials.Http
return double.TryParse(query[key], out result);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Globalization;
using Newtonsoft.Json;

namespace Limbo.Umbraco.YouTube.Json.Converters {

/// <summary>
/// JSON converter for seriqalizing and deserializating between instances of <see cref="TimeSpan"/> and the total
/// amount of seconds represented by the time span.
/// </summary>
internal class TimeSpanSecondsConverter : JsonConverter {

// TODO: Move to Skybrud.Essentials

/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {

switch (value) {

case null:
writer.WriteNull();
break;

case TimeSpan ts:
writer.WriteRawValue(ts.TotalSeconds.ToString(CultureInfo.InvariantCulture));
break;

default:
throw new JsonSerializationException($"Unsupported type: {value.GetType()}");

}

}

/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {

if (objectType != typeof(TimeSpan) && objectType != typeof(TimeSpan?)) throw new JsonSerializationException($"Object type {objectType} is not supported");

switch (reader.TokenType) {

case JsonToken.Null:
return objectType != typeof(TimeSpan?) ? null : default(TimeSpan);

case JsonToken.Integer:
case JsonToken.Float:
return TimeSpan.FromSeconds((double) Convert.ChangeType(reader.Value, typeof(double), CultureInfo.InvariantCulture));

default:
throw new JsonSerializationException("Unexpected token type: " + reader.TokenType);

}

}

/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns><c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.</returns>
public override bool CanConvert(Type objectType) {
return objectType == typeof(TimeSpan);
}

}

}
18 changes: 16 additions & 2 deletions src/Limbo.Umbraco.YouTube/Models/Videos/YouTubeEmbed.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Limbo.Umbraco.Video.Models.Videos;
using Limbo.Umbraco.YouTube.Services;
using Limbo.Umbraco.YouTube.Options;
using Microsoft.AspNetCore.Html;
using Newtonsoft.Json;
using Skybrud.Essentials.Json.Converters;
Expand All @@ -13,19 +13,33 @@ public class YouTubeEmbed : IVideoEmbed {

#region Properties

/// <summary>
/// Gets the embed URL.
/// </summary>
[JsonProperty("url")]
public string Url { get; }

/// <summary>
/// Gets the HTML embed code.
/// </summary>
[JsonProperty("html")]
[JsonConverter(typeof(StringJsonConverter))]
public HtmlString Html { get; }

/// <summary>
/// Gets the player options.
/// </summary>
[JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)]
public YouTubeEmbedPlayerOptions Options { get; }

#endregion

#region Constructors

internal YouTubeEmbed(YouTubeVideoDetails video) {
Html = new YouTubeVideoOptions(video.Id).GetEmbedCode();
YouTubeEmbedOptions o = new(video, Options ?? new YouTubeEmbedPlayerOptions());
Url = o.GetEmbedUrl();
Html = o.GetEmbedCode();
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion src/Limbo.Umbraco.YouTube/Models/Videos/YouTubeValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class YouTubeValue : IVideoValue {
/// <summary>
/// Gets the source (URL or embed code) as entered by the user.
/// </summary>
[JsonProperty("source")]
[JsonIgnore]
public string Source { get; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class YouTubeVideoDetails : IVideoDetails {
/// Gets the Vimeo URL of the video.
/// </summary>
[JsonProperty("url")]
public string Url => null;
public string Url => $"https://www.youtube.com/watch?v={Id}";

/// <summary>
/// Gets the title of the video.
Expand Down Expand Up @@ -107,11 +107,13 @@ public class YouTubeVideoDetails : IVideoDetails {
/// <summary>
/// Gets a reference to the <strong>statistics</strong> part of the video.
/// </summary>
[JsonIgnore]
public YouTubeVideoStatistics Statistics => Data?.Statistics;

/// <summary>
/// Gets whether the <see cref="Statistics"/> property was included in the response.
/// </summary>
[JsonIgnore]
public bool HasStatistics => Statistics != null;

IEnumerable<IVideoThumbnail> IVideoDetails.Thumbnails => Thumbnails;
Expand Down
114 changes: 114 additions & 0 deletions src/Limbo.Umbraco.YouTube/Options/YouTubeEmbedOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System;
using System.Web;
using Limbo.Umbraco.YouTube.Models.Videos;
using Microsoft.AspNetCore.Html;
using Newtonsoft.Json;
using Skybrud.Essentials.Common;

namespace Limbo.Umbraco.YouTube.Options {

/// <summary>
/// Class representing the embed options for a Vimeo video
/// </summary>
public class YouTubeEmbedOptions {

#region Properties

/// <summary>
/// Gets or sets the ID of the video.
/// </summary>
[JsonProperty("id")]
public string Id { get; set; }

/// <summary>
/// Gets or sets the title of the embed iframe.
/// </summary>
[JsonProperty("title", NullValueHandling = NullValueHandling.Ignore)]
public string Title { get; set; }

/// <summary>
/// Gets or sets the options for the player.
/// </summary>
[JsonProperty("player", NullValueHandling = NullValueHandling.Ignore)]
public YouTubeEmbedPlayerOptions Player { get; set; }

#endregion

#region Constructors

/// <summary>
/// Initializes a new instance based on the specified <paramref name="id"/>.
/// </summary>
/// <param name="id">The ID of the video.</param>
public YouTubeEmbedOptions(string id) {
Id = id;
}

/// <summary>
/// Initializes a new instance based on the specified <paramref name="video"/>.
/// </summary>
/// <param name="video">The Vimeo video.</param>
public YouTubeEmbedOptions(YouTubeVideoDetails video) {
Id = video.Id;
Title = video.Snippet?.Title;
}

/// <summary>
/// Initializes a new instance based on the specified <paramref name="video"/>.
/// </summary>
/// <param name="video">The Vimeo video.</param>
/// <param name="player">The options for the YouTube video player.</param>
public YouTubeEmbedOptions(YouTubeVideoDetails video, YouTubeEmbedPlayerOptions player) {
Id = video.Id;
Title = video.Snippet?.Title;
Player = player;
}

#endregion

#region Member methods

/// <summary>
/// Returns the embed URL for the video.
/// </summary>
/// <returns>The embed URL.</returns>
public string GetEmbedUrl() {
return (Player ?? new YouTubeEmbedPlayerOptions()).GetEmbedUrl(Id);
}

/// <summary>
/// Returns the HTML embed code for the video described by this options instance.
/// </summary>
/// <returns>An instance of <see cref="HtmlString"/> representing the HTML embed code.</returns>
public virtual HtmlString GetEmbedCode() {
return GetEmbedCode(null, null);
}

/// <summary>
/// Returns the HTML embed code for the video described by this options instance.
/// </summary>
/// <param name="width">The width of the video.</param>
/// <param name="height">The height of the video.</param>
/// <returns>An instance of <see cref="HtmlString"/> representing the HTML embed code.</returns>
public virtual HtmlString GetEmbedCode(int? width, int? height) {

width ??= 560;
height ??= 315;

if (string.IsNullOrWhiteSpace(Id)) throw new PropertyNotSetException(nameof(Id));

string url = (Player ?? new YouTubeEmbedPlayerOptions()).GetEmbedUrl(Id);

string title = string.IsNullOrWhiteSpace(Title) ? "Vimeo video player" : Title;

string html = $"<iframe width=\"{width}\" height=\"{height}\" src=\"{HttpUtility.HtmlAttributeEncode(url)}\" title=\"{HttpUtility.HtmlAttributeEncode(title)}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>";

return new HtmlString(html);

}

#endregion

}

}

0 comments on commit da4c970

Please sign in to comment.