migrate to database storage, fix css goofs
This commit is contained in:
parent
c90ebab27c
commit
5971c8ff5d
|
@ -5,6 +5,12 @@
|
|||
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.3/resharper-host/local/Transient/Rider/v203/SolutionCaches/_c3stream.-187536235.00" t="ExcludeRecursive" />
|
||||
<e p="$PROJECT_DIR$" t="IncludeRecursive">
|
||||
<e p=".gitignore" t="Include" />
|
||||
<e p="DataModels" t="Include">
|
||||
<e p="Database.cs" t="Include" />
|
||||
<e p="Tables" t="Include">
|
||||
<e p="States.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
<e p="LICENSE" t="Include" />
|
||||
<e p="Pages" t="Include">
|
||||
<e p="Conference.cshtml" t="Include" />
|
||||
|
@ -37,13 +43,15 @@
|
|||
<e p="c3stream.csproj" t="IncludeRecursive" />
|
||||
<e p="c3stream.sln" t="IncludeFlat" />
|
||||
<e p="obj" t="ExcludeRecursive">
|
||||
<e p="x64" t="Include">
|
||||
<e p="Debug" t="Include">
|
||||
<e p="netcoreapp3.1" t="Include">
|
||||
<e p="net50" t="Include">
|
||||
<e p="c3stream.AssemblyInfo.cs" t="Include" />
|
||||
<e p="c3stream.RazorAssemblyInfo.cs" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
</e>
|
||||
</e>
|
||||
<e p="packages" t="ExcludeRecursive" />
|
||||
<e p="wwwroot" t="Include">
|
||||
<e p="css" t="Include">
|
||||
|
@ -108,31 +116,86 @@
|
|||
</e>
|
||||
</e>
|
||||
<e p="webfonts" t="Include">
|
||||
<e p="fa-brands-400.eot" t="Include" />
|
||||
<e p="fa-brands-400.svg" t="Include" />
|
||||
<e p="fa-brands-400.ttf" t="Include" />
|
||||
<e p="fa-brands-400.woff" t="Include" />
|
||||
<e p="fa-brands-400.woff2" t="Include" />
|
||||
<e p="fa-duotone-900.eot" t="Include" />
|
||||
<e p="fa-duotone-900.svg" t="Include" />
|
||||
<e p="fa-duotone-900.ttf" t="Include" />
|
||||
<e p="fa-duotone-900.woff" t="Include" />
|
||||
<e p="fa-duotone-900.woff2" t="Include" />
|
||||
<e p="fa-light-300.eot" t="Include" />
|
||||
<e p="fa-light-300.svg" t="Include" />
|
||||
<e p="fa-light-300.ttf" t="Include" />
|
||||
<e p="fa-light-300.woff" t="Include" />
|
||||
<e p="fa-light-300.woff2" t="Include" />
|
||||
<e p="fa-regular-400.eot" t="Include" />
|
||||
<e p="fa-regular-400.svg" t="Include" />
|
||||
<e p="fa-regular-400.ttf" t="Include" />
|
||||
<e p="fa-regular-400.woff" t="Include" />
|
||||
<e p="fa-regular-400.woff2" t="Include" />
|
||||
<e p="fa-solid-900.eot" t="Include" />
|
||||
<e p="fa-solid-900.svg" t="Include" />
|
||||
<e p="fa-solid-900.ttf" t="Include" />
|
||||
<e p="fa-solid-900.woff" t="Include" />
|
||||
<e p="fa-solid-900.woff2" t="Include" />
|
||||
<e p="pro-fa-brands-400-5.0.0.woff2" t="Include" />
|
||||
<e p="pro-fa-brands-400-5.12.0.woff2" t="Include" />
|
||||
<e p="pro-fa-brands-400-5.3.0.woff2" t="Include" />
|
||||
<e p="pro-fa-brands-400-5.8.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.10.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.11.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.13.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.3.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.5.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.7.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.0.9.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.1.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.10.1.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.10.2.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.11.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.11.1.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.12.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.2.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.3.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.4.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.8.0.woff2" t="Include" />
|
||||
<e p="pro-fa-duotone-900-5.9.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.10.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.11.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.13.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.3.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.5.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.7.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.0.9.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.1.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.10.1.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.10.2.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.11.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.11.1.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.12.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.2.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.3.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.4.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.8.0.woff2" t="Include" />
|
||||
<e p="pro-fa-light-300-5.9.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.10.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.11.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.13.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.3.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.5.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.7.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.0.9.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.1.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.10.1.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.10.2.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.11.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.11.1.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.12.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.2.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.3.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.4.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.8.0.woff2" t="Include" />
|
||||
<e p="pro-fa-regular-400-5.9.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.0.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.0.11.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.0.13.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.0.3.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.0.5.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.0.7.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.0.9.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.1.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.10.1.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.10.2.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.11.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.11.1.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.12.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.12.1.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.2.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.3.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.4.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.8.0.woff2" t="Include" />
|
||||
<e p="pro-fa-solid-900-5.9.0.woff2" t="Include" />
|
||||
</e>
|
||||
</e>
|
||||
</e>
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using c3stream.DataModels.Tables;
|
||||
using LinqToDB;
|
||||
using LinqToDB.Configuration;
|
||||
using LinqToDB.Data;
|
||||
|
||||
namespace c3stream.DataModels {
|
||||
public class Database {
|
||||
public class ConnectionStringSettings : IConnectionStringSettings {
|
||||
public string ConnectionString { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string ProviderName { get; set; }
|
||||
public bool IsGlobal => false;
|
||||
}
|
||||
|
||||
public class Settings : ILinqToDBSettings {
|
||||
public IEnumerable<IDataProviderSettings> DataProviders => Enumerable.Empty<IDataProviderSettings>();
|
||||
|
||||
public string DefaultConfiguration => "SQLite";
|
||||
public string DefaultDataProvider => "SQLite";
|
||||
|
||||
public IEnumerable<IConnectionStringSettings> ConnectionStrings {
|
||||
get { yield return new ConnectionStringSettings {Name = "db", ProviderName = "SQLite", ConnectionString = @"Data Source=data/c3stream.sqlite;"}; }
|
||||
}
|
||||
}
|
||||
|
||||
public class DbConn : DataConnection {
|
||||
public DbConn() : base("db") { }
|
||||
|
||||
public ITable<States> States => GetTable<States>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
using LinqToDB.Mapping;
|
||||
|
||||
namespace c3stream.DataModels.Tables {
|
||||
[Table(Name = "States")]
|
||||
public class States {
|
||||
[Column(Name = "TalkId"), PrimaryKey, NotNull] public string TalkId { get; set; }
|
||||
[Column(Name = "UserId"), PrimaryKey, NotNull] public string UserId { get; set; }
|
||||
[Column(Name = "State"), NotNull] public string State { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
@page
|
||||
@model ConferenceModel
|
||||
@using System.Net
|
||||
@using global::c3stream.DataModels
|
||||
@using static ConferenceModel
|
||||
@{
|
||||
if (c3stream.Conferences.All(c => c.Acronym != Request.Query["c"])) {
|
||||
|
@ -9,7 +10,6 @@
|
|||
}
|
||||
|
||||
c3stream.UpdateCookie(Request, Response, $"/Conference?c={Request.Query["c"]}");
|
||||
ReadUserData();
|
||||
ViewData["Title"] = Request.Query["c"];
|
||||
var wc = new WebClient();
|
||||
var conference = c3stream.Conferences.First(c => c.Acronym == Request.Query["c"]);
|
||||
|
@ -17,6 +17,8 @@
|
|||
c3stream.UpdateConference(conference);
|
||||
}
|
||||
wc.Dispose();
|
||||
await using var db = new Database.DbConn();
|
||||
var states = db.States.ToList();
|
||||
}
|
||||
|
||||
<table class="table">
|
||||
|
@ -34,7 +36,7 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
@foreach (var talk in Request.Query["orderby"] == "published" ? conference.Talks.OrderByDescending(p => p.ReleaseDate) : conference.Talks.OrderBy(p => p.Date)) {
|
||||
var state = UserData.FirstOrDefault(p => p.TalkId == talk.Guid && p.UserId == Request.Cookies["bookmark"])?.State;
|
||||
var state = states.FirstOrDefault(p => p.TalkId == talk.Guid && p.UserId == Request.Cookies["bookmark"])?.State;
|
||||
var isWatched = state == "watched";
|
||||
var isMarked = state == "marked";
|
||||
var file = $"{talk.Slug}.mp4";
|
||||
|
@ -66,43 +68,43 @@
|
|||
<td>@talk.OriginalLanguage</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="@talk.FrontendLink.AbsoluteUri" role="button" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Play">
|
||||
<a href="@talk.FrontendLink.AbsoluteUri" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Play">
|
||||
<i class="fas fa-play-circle"></i>
|
||||
</a>
|
||||
@if (System.IO.File.Exists(System.IO.Path.Combine(c3stream.CachePath, conference.Acronym, file))) {
|
||||
<a href="@(c3stream.CacheUrl + $"{conference.Acronym}/{file}")" role="button" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Mirror">
|
||||
<a href="@(c3stream.CacheUrl + $"{conference.Acronym}/{file}")" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Mirror">
|
||||
<i class="fas fa-cloud-download"></i>
|
||||
</a>
|
||||
}
|
||||
else {
|
||||
<a href="/" role="button" class="btn btn-primary disabled">
|
||||
<a href="/" role="button" class="btn btn-primary btn-c3saction disabled">
|
||||
<i class="fas fa-cloud-download"></i>
|
||||
</a>
|
||||
}
|
||||
<a href="/Info?guid=@talk.Guid" role="button" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Info">
|
||||
<a href="/Info?guid=@talk.Guid" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Info">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</a>
|
||||
@if (isWatched) {
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Mark unwatched">
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Mark unwatched">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
<button class="btn btn-primary disabled">
|
||||
<button class="btn btn-primary btn-c3saction disabled">
|
||||
<i class="fas fa-clock"></i>
|
||||
</button>
|
||||
}
|
||||
else if (isMarked) {
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Mark watched">
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Mark watched">
|
||||
<i class="fas fa-check"></i>
|
||||
</button>
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Remove from watch later">
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Remove from watch later">
|
||||
<i class="fas fa-undo-alt"></i>
|
||||
</button>
|
||||
}
|
||||
else {
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Mark watched">
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Mark watched">
|
||||
<i class="fas fa-check"></i>
|
||||
</button>
|
||||
<button onclick="SetState('@talk.Guid', 'marked')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="top" title="Add to watch later">
|
||||
<button onclick="SetState('@talk.Guid', 'marked')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="top" title="Add to watch later">
|
||||
<i class="fas fa-clock"></i>
|
||||
</button>
|
||||
}
|
||||
|
|
|
@ -1,58 +1,39 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using c3stream.DataModels;
|
||||
using c3stream.DataModels.Tables;
|
||||
using LinqToDB;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace c3stream.Pages {
|
||||
public class ConferenceModel : PageModel {
|
||||
public static List<UserStatus> UserData = new List<UserStatus>();
|
||||
private readonly ILogger<ConferenceModel> _logger;
|
||||
|
||||
public ConferenceModel(ILogger<ConferenceModel> logger) => _logger = logger;
|
||||
|
||||
public void OnGet() {
|
||||
var guid = Request.Query["guid"];
|
||||
var state = Request.Query["state"];
|
||||
var guid = Request.Query["guid"].ToString();
|
||||
var state = Request.Query["state"].ToString();
|
||||
var userid = Request.Cookies["bookmark"];
|
||||
if (string.IsNullOrWhiteSpace(guid) || string.IsNullOrWhiteSpace(state) || !Request.Cookies.ContainsKey("bookmark"))
|
||||
return;
|
||||
|
||||
lock (c3stream.Lock) {
|
||||
ReadUserData();
|
||||
var existing = UserData.FirstOrDefault(p => p.TalkId == guid && p.UserId == userid);
|
||||
using var db = new Database.DbConn();
|
||||
var existing = db.States.FirstOrDefault(p => p.TalkId == guid && p.UserId == userid);
|
||||
if (existing != null)
|
||||
if (state == "unwatched")
|
||||
UserData.Remove(existing);
|
||||
else
|
||||
db.States.Delete(p => p == existing);
|
||||
else {
|
||||
existing.State = state;
|
||||
db.Update(existing);
|
||||
}
|
||||
else
|
||||
UserData.Add(new UserStatus(userid, guid, state));
|
||||
WriteUserData();
|
||||
db.Insert(new States {
|
||||
State = state, TalkId = guid, UserId = userid
|
||||
});
|
||||
Response.Redirect("/");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadUserData() {
|
||||
lock (c3stream.Lock)
|
||||
UserData = JsonConvert.DeserializeObject<List<UserStatus>>(System.IO.File.ReadAllText(c3stream.DbPath));
|
||||
}
|
||||
|
||||
public static void WriteUserData() {
|
||||
lock (c3stream.Lock)
|
||||
System.IO.File.WriteAllText(c3stream.DbPath, JsonConvert.SerializeObject(UserData));
|
||||
}
|
||||
|
||||
public class UserStatus {
|
||||
public readonly string TalkId;
|
||||
public readonly string UserId;
|
||||
public string State;
|
||||
|
||||
public UserStatus(string userId, string talkId, string state = "unwatched") {
|
||||
UserId = userId;
|
||||
State = state;
|
||||
TalkId = talkId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
@page
|
||||
@using global::c3stream.DataModels
|
||||
@model InfoModel
|
||||
@{
|
||||
ViewData["Title"] = "Info";
|
||||
|
@ -11,9 +12,10 @@
|
|||
|
||||
c3stream.UpdateCookie(Request, Response, $"/Info?guid={Request.Query["guid"]}");
|
||||
|
||||
ConferenceModel.ReadUserData();
|
||||
await using var db = new Database.DbConn();
|
||||
|
||||
var talk = c3stream.GetEventByGuid(Request.Query["guid"]);
|
||||
var state = ConferenceModel.UserData.FirstOrDefault(p => p.TalkId == Request.Query["guid"] && p.UserId == Request.Cookies["bookmark"])?.State;
|
||||
var state = db.States.FirstOrDefault(p => p.TalkId == Request.Query["guid"].ToString() && p.UserId == Request.Cookies["bookmark"])?.State;
|
||||
if (talk == null) {
|
||||
Response.Redirect("/");
|
||||
return;
|
||||
|
@ -44,6 +46,7 @@
|
|||
3 => talk.Tags[2],
|
||||
4 => talk.Tags[3],
|
||||
5 => talk.Tags[3],
|
||||
6 => talk.Tags[3], // rc3: is this correct?
|
||||
_ => "<unknown tag format>"
|
||||
};
|
||||
}
|
||||
|
@ -67,40 +70,40 @@ else {
|
|||
|
||||
<h5>@eventName - @category - @talk.Date?.Date.ToShortDateString()</h5>
|
||||
<div class="btn-group" role="group" style="margin-bottom: 10px">
|
||||
<a href="@talk.FrontendLink.AbsoluteUri" role="button" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="right" title="Play">
|
||||
<a href="@talk.FrontendLink.AbsoluteUri" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="right" title="Play">
|
||||
<i class="fas fa-play-circle"></i>
|
||||
</a>
|
||||
@if (System.IO.File.Exists(System.IO.Path.Combine(c3stream.CachePath, conference.Acronym, file))) {
|
||||
<a href="@(c3stream.CacheUrl + $"{conference.Acronym}/{file}")" role="button" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="right" title="Mirror">
|
||||
<a href="@(c3stream.CacheUrl + $"{conference.Acronym}/{file}")" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="right" title="Mirror">
|
||||
<i class="fas fa-cloud-download"></i>
|
||||
</a>
|
||||
}
|
||||
else {
|
||||
<a href="/" role="button" class="btn btn-primary disabled">
|
||||
<a href="/" role="button" class="btn btn-primary btn-c3saction disabled">
|
||||
<i class="fas fa-cloud-download"></i>
|
||||
</a>
|
||||
}
|
||||
@if (isWatched) {
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="left" title="Mark unwatched">
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark unwatched">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
<button class="btn btn-primary disabled">
|
||||
<button class="btn btn-primary btn-c3saction disabled">
|
||||
<i class="fas fa-clock"></i>
|
||||
</button>
|
||||
}
|
||||
else if (isMarked) {
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
|
||||
<i class="fas fa-check"></i>
|
||||
</button>
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="left" title="Remove from watch later">
|
||||
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Remove from watch later">
|
||||
<i class="fas fa-undo-alt"></i>
|
||||
</button>
|
||||
}
|
||||
else {
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
|
||||
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
|
||||
<i class="fas fa-check"></i>
|
||||
</button>
|
||||
<button onclick="SetState('@talk.Guid', 'marked')" class="btn btn-primary w-100" data-toggle="tooltip" data-placement="left" title="Add to watch later">
|
||||
<button onclick="SetState('@talk.Guid', 'marked')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Add to watch later">
|
||||
<i class="fas fa-clock"></i>
|
||||
</button>
|
||||
}
|
||||
|
|
16
c3stream.cs
16
c3stream.cs
|
@ -3,7 +3,10 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using c3stream.DataModels;
|
||||
using c3stream.Pages;
|
||||
using LinqToDB.Common;
|
||||
using LinqToDB.Data;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
@ -11,13 +14,13 @@ using Microsoft.Extensions.Hosting;
|
|||
namespace c3stream {
|
||||
public static class c3stream {
|
||||
public const string DataPath = "data";
|
||||
public const string DbFile = "c3stream.user.json";
|
||||
public const string DbFile = "c3stream.sqlite";
|
||||
public const string CachePath = "/mnt/storage/archive/Video/congress/";
|
||||
public const string CacheUrl = "https://c3stream-mirror.zotan.services/";
|
||||
public static object Lock = new object();
|
||||
public static object Lock = new();
|
||||
public static string DbPath = Path.Combine(DataPath, DbFile);
|
||||
|
||||
public static List<ConferenceObject> Conferences = new List<ConferenceObject> {
|
||||
public static readonly List<ConferenceObject> Conferences = new() {
|
||||
new ConferenceObject("rc3", true),
|
||||
new ConferenceObject("36c3"),
|
||||
new ConferenceObject("camp2019"),
|
||||
|
@ -34,7 +37,9 @@ namespace c3stream {
|
|||
if (!Directory.Exists(DataPath))
|
||||
Directory.CreateDirectory(DataPath);
|
||||
if (!File.Exists(DbPath))
|
||||
ConferenceModel.WriteUserData();
|
||||
File.Copy(Path.Combine(DataPath, "database.init.sqlite"), DbPath);
|
||||
|
||||
DataConnection.DefaultSettings = new Database.Settings();
|
||||
|
||||
foreach (var conference in Conferences)
|
||||
UpdateConference(conference);
|
||||
|
@ -55,6 +60,7 @@ namespace c3stream {
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: move this to the database as well
|
||||
public static void UpdateConference(ConferenceObject conference) {
|
||||
using var wc = new WebClient();
|
||||
|
||||
|
@ -111,7 +117,7 @@ namespace c3stream {
|
|||
public string Acronym;
|
||||
public bool Ongoing;
|
||||
public string LogoUri;
|
||||
public List<Event> Talks = new List<Event>();
|
||||
public List<Event> Talks = new();
|
||||
|
||||
public ConferenceObject(string acronym, bool ongoing = false) {
|
||||
Acronym = acronym;
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net50</TargetFramework>
|
||||
<Configurations>Release;Debug</Configurations>
|
||||
<Platforms>x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="linq2db" Version="3.2.2" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.1" PrivateAssets="none" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -32,5 +36,7 @@
|
|||
<Content Remove="data\**" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DataModels" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
12
c3stream.sln
12
c3stream.sln
|
@ -4,13 +4,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "c3stream", "c3stream.csproj
|
|||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Debug|x64.Build.0 = Debug|x64
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Release|x64.ActiveCfg = Release|x64
|
||||
{BC6A24FE-B35F-4F0A-8E8E-221E61E41EEF}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -88,6 +88,9 @@ body {
|
|||
color: #ffffff;
|
||||
border-color: #3c6385;
|
||||
background-color: #375a7a;
|
||||
}
|
||||
|
||||
.btn-c3saction {
|
||||
width: 42px !important;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue