diff --git a/VCinema/Hubs/IVCinemaHub.cs b/VCinema/Hubs/IVCinemaHub.cs new file mode 100644 index 0000000..30adabc --- /dev/null +++ b/VCinema/Hubs/IVCinemaHub.cs @@ -0,0 +1,8 @@ +using System; +namespace VCinemaApi.Hubs +{ + public interface IVCinemaHub + { + + } +} diff --git a/VCinema/Hubs/VCinemaHub.cs b/VCinema/Hubs/VCinemaHub.cs index 860681f..d59c1e0 100644 --- a/VCinema/Hubs/VCinemaHub.cs +++ b/VCinema/Hubs/VCinemaHub.cs @@ -5,107 +5,41 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; using VCinemaApi.Models; +using VCinemaApi.Repositories; namespace VCinemaApi.Hubs { - public class VCinemaHub : Hub + public class VCinemaHub : Hub { - 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() { - var watcher = new Watcher() - { - ConnectionId = Context.ConnectionId, - }; - await _context.Watchers.AddAsync(watcher); - await _context.SaveChangesAsync(); - + await _watcherRepository.CreateWatcher(Context.ConnectionId); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception exception) { - Watcher watcher = await _context.Watchers.SingleOrDefaultAsync(watcher => watcher.ConnectionId == Context.ConnectionId); - _context.Watchers.Remove(watcher); - await _context.SaveChangesAsync(); - + await _watcherRepository.DeleteWatcher(Context.ConnectionId); await base.OnDisconnectedAsync(exception); } - public async Task GetScreens() + public async Task> GetScreens() { - List screens = await _context.Screens.ToListAsync(); - await Clients.Caller.SendAsync("ReceiveScreens", screens); + return await _screenRepository.GetScreens(); } - public async Task GetScreen(int screenId) + public async Task GetScreenById(int screenId) { - Screen screen = await _context.Screens.SingleOrDefaultAsync(screen => screen.ScreenId == 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); - 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()); + return await _screenRepository.GetScreenById(screenId); } } } diff --git a/VCinema/Models/Watcher.cs b/VCinema/Models/Watcher.cs index c6e0436..3d53711 100644 --- a/VCinema/Models/Watcher.cs +++ b/VCinema/Models/Watcher.cs @@ -9,9 +9,10 @@ namespace VCinemaApi.Models [Key] public int WatcherId { get; set; } - public string Name { get; set; } + [Required] public string ConnectionId { get; set; } + public string Name { get; set; } public Screen Screen { get; set; } } } diff --git a/VCinema/Repositories/IScreenRepository.cs b/VCinema/Repositories/IScreenRepository.cs new file mode 100644 index 0000000..f77ba14 --- /dev/null +++ b/VCinema/Repositories/IScreenRepository.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using VCinemaApi.Models; + +namespace VCinemaApi.Repositories +{ + public interface IScreenRepository + { + Task> GetScreens(); + Task GetScreenById(int screenId); + } +} diff --git a/VCinema/Repositories/IWatcherRepository.cs b/VCinema/Repositories/IWatcherRepository.cs new file mode 100644 index 0000000..8a60330 --- /dev/null +++ b/VCinema/Repositories/IWatcherRepository.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using VCinemaApi.Models; + +namespace VCinemaApi.Repositories +{ + public interface IWatcherRepository + { + Task> GetWatchersByScreenId(int screenId); + Task GetWatcherByConnectionId(string connectionId); + Task CreateWatcher(string connectionId); + Task DeleteWatcher(string connectionId); + } +} diff --git a/VCinema/Repositories/MockScreenRepository.cs b/VCinema/Repositories/MockScreenRepository.cs new file mode 100644 index 0000000..acf61a8 --- /dev/null +++ b/VCinema/Repositories/MockScreenRepository.cs @@ -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> GetScreens() + { + var screens = new List + { + 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>(screens); + } + + public Task 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); + } + } +} diff --git a/VCinema/Repositories/MockWatcherRepository.cs b/VCinema/Repositories/MockWatcherRepository.cs new file mode 100644 index 0000000..d6cc877 --- /dev/null +++ b/VCinema/Repositories/MockWatcherRepository.cs @@ -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> GetWatchersByScreenId(int screenId) + { + var watchers = new List + { + 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>(watchers); + } + + public Task 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); + } + + public Task CreateWatcher(string connectionId) + { + throw new NotImplementedException(); + } + + public Task DeleteWatcher(string connectionId) + { + throw new NotImplementedException(); + } + } +} diff --git a/VCinema/Repositories/ScreenRepository.cs b/VCinema/Repositories/ScreenRepository.cs index 7c7af6d..cce58e1 100644 --- a/VCinema/Repositories/ScreenRepository.cs +++ b/VCinema/Repositories/ScreenRepository.cs @@ -1,10 +1,27 @@ -using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using VCinemaApi.Models; + namespace VCinemaApi.Repositories { - public class ScreenRepository + public class ScreenRepository : IScreenRepository { - public ScreenRepository() + private readonly VCinemaContext _context; + + public ScreenRepository(VCinemaContext context) { + _context = context; + } + + public Task> GetScreens() + { + return _context.Screens.ToListAsync(); + } + + public Task GetScreenById(int screenId) + { + return _context.Screens.SingleOrDefaultAsync(screen => screen.ScreenId == screenId); } } } diff --git a/VCinema/Repositories/WatcherRepository.cs b/VCinema/Repositories/WatcherRepository.cs index ab78fb0..7193bb6 100644 --- a/VCinema/Repositories/WatcherRepository.cs +++ b/VCinema/Repositories/WatcherRepository.cs @@ -1,10 +1,46 @@ using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using VCinemaApi.Models; + namespace VCinemaApi.Repositories { - public class WatcherRepository + public class WatcherRepository : IWatcherRepository { - public WatcherRepository() + private readonly VCinemaContext _context; + + public WatcherRepository(VCinemaContext context) { + _context = context; + } + + public Task> GetWatchersByScreenId(int screenId) + { + throw new NotImplementedException(); + } + + public Task 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(); } } } diff --git a/VCinema/Startup.cs b/VCinema/Startup.cs index df845b7..4185ef0 100644 --- a/VCinema/Startup.cs +++ b/VCinema/Startup.cs @@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using VCinemaApi.Hubs; using VCinemaApi.Models; +using VCinemaApi.Repositories; namespace VCinemaApi { @@ -21,7 +22,9 @@ namespace VCinemaApi // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddDbContext(options => options.UseInMemoryDatabase("VCinema")); + services.AddDbContext(options => options.UseInMemoryDatabase("VCinema")); + services.AddScoped(); + services.AddScoped(); services.AddControllers(); services.AddSignalR(); } diff --git a/VCinema/VCinemaApi.csproj b/VCinema/VCinemaApi.csproj index ca55094..a2bb656 100644 --- a/VCinema/VCinemaApi.csproj +++ b/VCinema/VCinemaApi.csproj @@ -5,6 +5,7 @@ +