feature/dotnet #3
|
@ -0,0 +1,8 @@
|
||||||
|
using System;
|
||||||
|
namespace VCinemaApi.Hubs
|
||||||
|
{
|
||||||
|
public interface IVCinemaHub
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,107 +5,41 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using VCinemaApi.Models;
|
using VCinemaApi.Models;
|
||||||
|
using VCinemaApi.Repositories;
|
||||||
|
|
||||||
namespace VCinemaApi.Hubs
|
namespace VCinemaApi.Hubs
|
||||||
{
|
{
|
||||||
public class VCinemaHub : Hub
|
public class VCinemaHub : Hub<IVCinemaHub>
|
||||||
{
|
{
|
||||||
private readonly VCinemaContext _context;
|
private readonly IScreenRepository _screenRepository;
|
||||||
|
private readonly IWatcherRepository _watcherRepository;
|
||||||
|
|
||||||
public VCinemaHub(VCinemaContext context)
|
public VCinemaHub(IScreenRepository screenRepository, IWatcherRepository watcherRepository)
|
||||||
{
|
{
|
||||||
_context = context;
|
_screenRepository = screenRepository;
|
||||||
|
_watcherRepository = watcherRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task OnConnectedAsync()
|
public override async Task OnConnectedAsync()
|
||||||
{
|
{
|
||||||
var watcher = new Watcher()
|
await _watcherRepository.CreateWatcher(Context.ConnectionId);
|
||||||
{
|
|
||||||
ConnectionId = Context.ConnectionId,
|
|
||||||
};
|
|
||||||
await _context.Watchers.AddAsync(watcher);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
await base.OnConnectedAsync();
|
await base.OnConnectedAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task OnDisconnectedAsync(Exception exception)
|
public override async Task OnDisconnectedAsync(Exception exception)
|
||||||
{
|
{
|
||||||
Watcher watcher = await _context.Watchers.SingleOrDefaultAsync(watcher => watcher.ConnectionId == Context.ConnectionId);
|
await _watcherRepository.DeleteWatcher(Context.ConnectionId);
|
||||||
_context.Watchers.Remove(watcher);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
await base.OnDisconnectedAsync(exception);
|
await base.OnDisconnectedAsync(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetScreens()
|
public async Task<IEnumerable<Screen>> GetScreens()
|
||||||
{
|
{
|
||||||
List<Screen> screens = await _context.Screens.ToListAsync();
|
return await _screenRepository.GetScreens();
|
||||||
await Clients.Caller.SendAsync("ReceiveScreens", screens);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task GetScreen(int screenId)
|
public async Task<Screen> GetScreenById(int screenId)
|
||||||
{
|
{
|
||||||
Screen screen = await _context.Screens.SingleOrDefaultAsync(screen => screen.ScreenId == screenId);
|
return await _screenRepository.GetScreenById(screenId);
|
||||||
if (screen == null)
|
|
||||||
{
|
|
||||||
throw new HubException($"No screen with ID {screenId} found.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CreateScreen(string name, string source)
|
|
||||||
{
|
|
||||||
var screen = new Screen()
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Source = source
|
|
||||||
};
|
|
||||||
await _context.AddAsync<Screen>(screen);
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
var screens = await _context.Screens.ToListAsync();
|
|
||||||
await Clients.All.SendAsync("ReceiveScreens", screens);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task JoinScreen(int screenId)
|
|
||||||
{
|
|
||||||
Screen screen = await _context.Screens.SingleOrDefaultAsync(screen => screen.ScreenId == screenId);
|
|
||||||
if (screen == null)
|
|
||||||
{
|
|
||||||
throw new HubException($"No screen with ID {screenId} found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Watcher watcher = await _context.Watchers.SingleOrDefaultAsync(watcher => watcher.ConnectionId == Context.ConnectionId);
|
|
||||||
if (watcher == null)
|
|
||||||
{
|
|
||||||
throw new HubException($"No watcher with connection ID {Context.ConnectionId} found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
watcher.Screen = screen;
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
await Groups.AddToGroupAsync(Context.ConnectionId, screenId.ToString());
|
|
||||||
await Clients.Caller.SendAsync("ReceiveScreen", screen);
|
|
||||||
|
|
||||||
/* Send new watcher notification of watchers to screen. */
|
|
||||||
await Clients.Group(screenId.ToString()).SendAsync("NewWatcher", watcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task LeaveScreen()
|
|
||||||
{
|
|
||||||
Watcher watcher = await _context.Watchers.SingleOrDefaultAsync(watcher => watcher.ConnectionId == Context.ConnectionId);
|
|
||||||
if (watcher == null)
|
|
||||||
{
|
|
||||||
throw new HubException($"No watcher with connection ID {Context.ConnectionId} found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
int screenId = watcher.Screen.ScreenId;
|
|
||||||
if (screenId == 0)
|
|
||||||
{
|
|
||||||
throw new HubException($"Watcher is not joined to any screens.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, screenId.ToString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@ namespace VCinemaApi.Models
|
||||||
[Key]
|
[Key]
|
||||||
public int WatcherId { get; set; }
|
public int WatcherId { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; }
|
[Required]
|
||||||
public string ConnectionId { get; set; }
|
public string ConnectionId { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
public Screen Screen { get; set; }
|
public Screen Screen { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VCinemaApi.Models;
|
||||||
|
|
||||||
|
namespace VCinemaApi.Repositories
|
||||||
|
{
|
||||||
|
public interface IScreenRepository
|
||||||
|
{
|
||||||
|
Task<List<Screen>> GetScreens();
|
||||||
|
Task<Screen> GetScreenById(int screenId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VCinemaApi.Models;
|
||||||
|
|
||||||
|
namespace VCinemaApi.Repositories
|
||||||
|
{
|
||||||
|
public interface IWatcherRepository
|
||||||
|
{
|
||||||
|
Task<List<Watcher>> GetWatchersByScreenId(int screenId);
|
||||||
|
Task<Watcher> GetWatcherByConnectionId(string connectionId);
|
||||||
|
Task CreateWatcher(string connectionId);
|
||||||
|
Task DeleteWatcher(string connectionId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VCinemaApi.Models;
|
||||||
|
|
||||||
|
namespace VCinemaApi.Repositories
|
||||||
|
{
|
||||||
|
public class MockScreenRepository : IScreenRepository
|
||||||
|
{
|
||||||
|
public Task<List<Screen>> GetScreens()
|
||||||
|
{
|
||||||
|
var screens = new List<Screen>
|
||||||
|
{
|
||||||
|
new Screen {
|
||||||
|
ScreenId = 1,
|
||||||
|
Name = "Kirby's screen",
|
||||||
|
Source = "https://vcinema.b-cdn.net/shrek.mp4",
|
||||||
|
PlayStateUpdated = new DateTime(2020, 9, 21, 21, 02, 57),
|
||||||
|
PlayState = true,
|
||||||
|
PlayOffset = 1337
|
||||||
|
},
|
||||||
|
new Screen {
|
||||||
|
ScreenId = 2,
|
||||||
|
Name = "Sid's screen",
|
||||||
|
Source = "https://vcinema.b-cdn.net/weeb.mp4",
|
||||||
|
PlayStateUpdated = new DateTime(2020, 9, 21, 21, 03, 22),
|
||||||
|
PlayState = true,
|
||||||
|
PlayOffset = 69
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Task.FromResult<List<Screen>>(screens);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Screen> GetScreenById(int screenId)
|
||||||
|
{
|
||||||
|
var screen = new Screen
|
||||||
|
{
|
||||||
|
ScreenId = 1,
|
||||||
|
Name = "Kirby's screen",
|
||||||
|
Source = "https://vcinema.b-cdn.net/shrek.mp4",
|
||||||
|
PlayStateUpdated = DateTime.UtcNow,
|
||||||
|
PlayState = true,
|
||||||
|
PlayOffset = 1337
|
||||||
|
};
|
||||||
|
return Task.FromResult<Screen>(screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using VCinemaApi.Models;
|
||||||
|
|
||||||
|
namespace VCinemaApi.Repositories
|
||||||
|
{
|
||||||
|
public class MockWatcherRepository : IWatcherRepository
|
||||||
|
{
|
||||||
|
public Task<List<Watcher>> GetWatchersByScreenId(int screenId)
|
||||||
|
{
|
||||||
|
var watchers = new List<Watcher>
|
||||||
|
{
|
||||||
|
new Watcher
|
||||||
|
{
|
||||||
|
WatcherId = 1,
|
||||||
|
ConnectionId = "dJSbEc73n6YjGIhj-SZz1Q",
|
||||||
|
Name = "Kirby",
|
||||||
|
Screen = new Screen {
|
||||||
|
ScreenId = 1,
|
||||||
|
Name = "Kirby's screen",
|
||||||
|
Source = "https://vcinema.b-cdn.net/shrek.mp4",
|
||||||
|
PlayStateUpdated = new DateTime(2020, 9, 21, 21, 02, 57),
|
||||||
|
PlayState = true,
|
||||||
|
PlayOffset = 1337
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Watcher
|
||||||
|
{
|
||||||
|
WatcherId = 2,
|
||||||
|
ConnectionId = "rNA9Jn7ytYPzQfFJ-j3NBa",
|
||||||
|
Name = "Sid",
|
||||||
|
Screen = new Screen {
|
||||||
|
ScreenId = 2,
|
||||||
|
Name = "Sid's screen",
|
||||||
|
Source = "https://vcinema.b-cdn.net/weeb.mp4",
|
||||||
|
PlayStateUpdated = new DateTime(2020, 9, 21, 21, 03, 22),
|
||||||
|
PlayState = true,
|
||||||
|
PlayOffset = 69
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Task.FromResult<List<Watcher>>(watchers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Watcher> GetWatcherByConnectionId(string connectionId)
|
||||||
|
{
|
||||||
|
var watcher = new Watcher
|
||||||
|
{
|
||||||
|
WatcherId = 1,
|
||||||
|
ConnectionId = "dJSbEc73n6YjGIhj-SZz1Q",
|
||||||
|
Name = "Kirby",
|
||||||
|
Screen = new Screen
|
||||||
|
{
|
||||||
|
ScreenId = 1,
|
||||||
|
Name = "Kirby's screen",
|
||||||
|
Source = "https://vcinema.b-cdn.net/shrek.mp4",
|
||||||
|
PlayStateUpdated = new DateTime(2020, 9, 21, 21, 02, 57),
|
||||||
|
PlayState = true,
|
||||||
|
PlayOffset = 1337
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Task.FromResult<Watcher>(watcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task CreateWatcher(string connectionId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task DeleteWatcher(string connectionId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,27 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using VCinemaApi.Models;
|
||||||
|
|
||||||
namespace VCinemaApi.Repositories
|
namespace VCinemaApi.Repositories
|
||||||
{
|
{
|
||||||
public class ScreenRepository
|
public class ScreenRepository : IScreenRepository
|
||||||
{
|
{
|
||||||
public ScreenRepository()
|
private readonly VCinemaContext _context;
|
||||||
|
|
||||||
|
public ScreenRepository(VCinemaContext context)
|
||||||
{
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<List<Screen>> GetScreens()
|
||||||
|
{
|
||||||
|
return _context.Screens.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Screen> GetScreenById(int screenId)
|
||||||
|
{
|
||||||
|
return _context.Screens.SingleOrDefaultAsync(screen => screen.ScreenId == screenId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,46 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using VCinemaApi.Models;
|
||||||
|
|
||||||
namespace VCinemaApi.Repositories
|
namespace VCinemaApi.Repositories
|
||||||
{
|
{
|
||||||
public class WatcherRepository
|
public class WatcherRepository : IWatcherRepository
|
||||||
{
|
{
|
||||||
public WatcherRepository()
|
private readonly VCinemaContext _context;
|
||||||
|
|
||||||
|
public WatcherRepository(VCinemaContext context)
|
||||||
{
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<List<Watcher>> GetWatchersByScreenId(int screenId)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Watcher> GetWatcherByConnectionId(string connectionId)
|
||||||
|
{
|
||||||
|
return _context.Watchers.SingleOrDefaultAsync(watcher => watcher.ConnectionId == connectionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CreateWatcher(string connectionId)
|
||||||
|
{
|
||||||
|
var watcher = new Watcher()
|
||||||
|
{
|
||||||
|
ConnectionId = connectionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
await _context.Watchers.AddAsync(watcher);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteWatcher(string connectionId)
|
||||||
|
{
|
||||||
|
var watcher = await GetWatcherByConnectionId(connectionId);
|
||||||
|
_context.Watchers.Remove(watcher);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using VCinemaApi.Hubs;
|
using VCinemaApi.Hubs;
|
||||||
using VCinemaApi.Models;
|
using VCinemaApi.Models;
|
||||||
|
using VCinemaApi.Repositories;
|
||||||
|
|
||||||
namespace VCinemaApi
|
namespace VCinemaApi
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,8 @@ namespace VCinemaApi
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddDbContext<VCinemaContext>(options => options.UseInMemoryDatabase("VCinema"));
|
services.AddDbContext<VCinemaContext>(options => options.UseInMemoryDatabase("VCinema"));
|
||||||
|
services.AddScoped<IScreenRepository, ScreenRepository>();
|
||||||
|
services.AddScoped<IWatcherRepository, WatcherRepository>();
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
services.AddSignalR();
|
services.AddSignalR();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(RunConfiguration)' == 'VCinema' " />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Models\" />
|
<Folder Include="Models\" />
|
||||||
<Folder Include="Hubs\" />
|
<Folder Include="Hubs\" />
|
||||||
|
|
Loading…
Reference in New Issue