Anapher/Strive

View on GitHub
src/Services/ConferenceManagement/Strive.Core/Services/Scenes/Providers/PresenterSceneProvider.cs

Summary

Maintainability
A
35 mins
Test Coverage
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using MediatR;
using Newtonsoft.Json.Linq;
using Strive.Core.Extensions;
using Strive.Core.Services.Permissions;
using Strive.Core.Services.Rooms;
using Strive.Core.Services.Scenes.Scenes;
using Strive.Core.Services.Scenes.Utilities;
using Strive.Core.Services.Synchronization.Extensions;

namespace Strive.Core.Services.Scenes.Providers
{
    public class PresenterSceneProvider : ISceneProvider
    {
        private static readonly IReadOnlyDictionary<string, JValue> PresenterPermissions = new[]
        {
            DefinedPermissions.Media.CanShareAudio.Configure(true),
            DefinedPermissions.Media.CanShareWebcam.Configure(true),
            DefinedPermissions.Media.CanShareScreen.Configure(true),
            DefinedPermissions.Scenes.CanOverwriteContentScene.Configure(true),
        }.ToImmutableDictionary();

        private readonly IMediator _mediator;

        public PresenterSceneProvider(IMediator mediator)
        {
            _mediator = mediator;
        }

        public async ValueTask<IEnumerable<IScene>> GetAvailableScenes(string conferenceId, string roomId,
            IReadOnlyList<IScene> sceneStack)
        {
            if (sceneStack.OfType<PresenterScene>().Any())
            {
                var rooms = await _mediator.FetchSynchronizedObject<SynchronizedRooms>(conferenceId,
                    SynchronizedRooms.SyncObjId);

                return GetAvailableScenes(roomId, rooms, sceneStack);
            }

            return Enumerable.Empty<IScene>();
        }

        public async ValueTask<SceneUpdate> IsUpdateRequired(string conferenceId, string roomId, string syncObjId,
            object synchronizedObject, object? previousValue)
        {
            if (synchronizedObject is SynchronizedRooms rooms)
            {
                if (SceneUtilities.ParticipantsOfRoomChanged(roomId, rooms, previousValue as SynchronizedRooms))
                    return SceneUpdate.AvailableScenesChanged;
            }

            return SceneUpdate.NotRequired;
        }

        private static IEnumerable<IScene> GetAvailableScenes(string roomId, SynchronizedRooms rooms,
            IReadOnlyList<IScene> scenes)
        {
            var presenterScenes = scenes.OfType<PresenterScene>();

            return presenterScenes.Where(x =>
                rooms.Participants.TryGetValue(x.PresenterParticipantId, out var presenterRoomId) &&
                presenterRoomId == roomId);
        }

        public bool IsProvided(IScene scene)
        {
            return scene is PresenterScene;
        }

        public async ValueTask<IEnumerable<IScene>> BuildStack(IScene scene, SceneBuilderContext context,
            SceneStackFunc sceneProviderFunc)
        {
            var presenterScene = (PresenterScene) scene;
            var stack = new List<IScene> {presenterScene};

            var screenShare = context.AvailableScenes.OfType<ScreenShareScene>()
                .FirstOrDefault(x => x.ParticipantId == presenterScene.PresenterParticipantId);
            if (screenShare != null)
            {
                stack.Add(screenShare);
            }
            else
            {
                stack.Add(ActiveSpeakerScene.Instance);
            }

            return stack;
        }

        public async ValueTask<IEnumerable<PermissionLayer>> FetchPermissionsForParticipant(IScene scene,
            Participant participant, IReadOnlyList<IScene> sceneStack)
        {
            if (scene is PresenterScene presenterScene && presenterScene.PresenterParticipantId == participant.Id)
            {
                return new List<PermissionLayer> {CommonPermissionLayers.ScenePresenter(PresenterPermissions)};
            }

            return Enumerable.Empty<PermissionLayer>();
        }
    }
}