about summary refs log tree commit diff
path: root/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor
blob: 2176467c68d99dd1ad3a9f598e80fcf126fee021 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
@using LibMatrix.Homeservers
@using LibMatrix.RoomTypes
@using LibMatrix
@using LibMatrix.Responses
@using MatrixUtils.LibDMSpace
@using MatrixUtils.LibDMSpace.StateEvents
@using Microsoft.Extensions.Primitives
@using ArcaneLibs.Extensions
@using LibMatrix.EventTypes.Spec.State
@using MatrixUtils.Abstractions
<b>
    <u>DM Space setup tool - stage 1: Configure space</u>
</b>
<p>You will need a space to use for DM rooms.</p>
@if (SetupData is not null) {
    if (SetupData.Spaces is not null) {
        <p>
            Selected space:
            <InputSelect @bind-Value="SetupData.DmSpaceConfiguration.DMSpaceId">
                <option value="">New space</option>
                @foreach (var (id, roomInfo) in SetupData.Spaces) {
                    <option value="@id">@roomInfo.RoomName</option>
                }
            </InputSelect>
        </p>
        <p>
            <InputCheckbox @bind-Value="SetupData.DmSpaceInfo.LayerByUser"></InputCheckbox>
            Create sub-spaces per user
        </p>
        
        <br/>
        <LinkButton OnClick="@Disband" Color="#FF0000">Disband</LinkButton>
        <LinkButton OnClick="@Execute">Next</LinkButton>
    }
    else {
        <p>Discovering spaces, please wait...</p>
    }
}
else {
    <b>Error: Setup data is null!</b>
}


@if (!string.IsNullOrWhiteSpace(Status)) {
    <p>@Status</p>
}

@code {

    private string? Status {
        get => _status;
        set {
            _status = value;
            StateHasChanged();
        }
    }

    private string? _status;

    [CascadingParameter]
    public DMSpace.DMSpaceSetupData SetupData { get; set; }

    SemaphoreSlim _semaphoreSlim = new(1, 1);

    protected override async Task OnInitializedAsync() {
        if (SetupData is null)
            return;

        await _semaphoreSlim.WaitAsync();

        Dictionary<string, RoomInfo> spaces = [];
        SetupData.DmSpaceConfiguration ??= new();

        Status = "Looking for spaces...";
        var userRoomsEnum = SetupData.Homeserver!.GetJoinedRoomsByType("m.space");

        List<GenericRoom> userRooms = new();
        await foreach (var room in userRoomsEnum) {
            userRooms.Add(room);
        }

        var roomChecks = userRooms.Select(GetFeasibleSpaces).ToAsyncEnumerable();
        await foreach (var room in roomChecks)
            if (room.HasValue)
                spaces.TryAdd(room.Value.id, room.Value.roomInfo);

        SetupData.Spaces = spaces;

        Status = "Done!";
        _semaphoreSlim.Release();
        await base.OnParametersSetAsync();
    }

    private async Task Execute() {
        if (string.IsNullOrWhiteSpace(SetupData!.DmSpaceConfiguration!.DMSpaceId)) {
            var createRoomRequest = CreateRoomRequest.CreatePrivate(SetupData.Homeserver!, "Direct Messages");
            createRoomRequest.CreationContentBaseType.Type = "m.space";
            SetupData.DmSpaceConfiguration.DMSpaceId = (await SetupData.Homeserver!.CreateRoom(createRoomRequest)).RoomId;
        }

        await SetupData.Homeserver!.SetAccountDataAsync(DMSpaceConfiguration.EventId, SetupData.DmSpaceConfiguration);
        var space = SetupData.Homeserver.GetRoom(SetupData.DmSpaceConfiguration.DMSpaceId);
        await space.SendStateEventAsync(DMSpaceInfo.EventId, SetupData.DmSpaceInfo);
        SetupData.DMSpaceRoomInfo = new RoomInfo(space);
        await SetupData.DMSpaceRoomInfo.FetchAllStateAsync();

        NavigationManager.NavigateTo("/User/DMSpace/Setup?stage=2");
    }

    public async Task<(string id, RoomInfo roomInfo)?> GetFeasibleSpaces(GenericRoom room) {
        try {
            var ri = new RoomInfo(room);
            
            await foreach(var evt in room.GetFullStateAsync())
                ri.StateEvents.Add(evt);

            var powerLevels = (await ri.GetStateEvent(RoomPowerLevelEventContent.EventId)).TypedContent as RoomPowerLevelEventContent;
            if (!powerLevels.UserHasStatePermission(SetupData.Homeserver.WhoAmI.UserId, SpaceChildEventContent.EventId)) {
                Console.WriteLine($"No permission to send m.space.child in {room.RoomId}...");
                return null;
            }
            
            Status = $"Found viable space: {ri.RoomName}";
            if (!string.IsNullOrWhiteSpace(SetupData.DmSpaceConfiguration!.DMSpaceId)) {
                if (await room.GetStateOrNullAsync<DMSpaceInfo>(DMSpaceInfo.EventId) is { } dsi) {
                    SetupData.DmSpaceConfiguration.DMSpaceId = room.RoomId;
                    SetupData.DmSpaceInfo = dsi;
                    Console.WriteLine(dsi.ToJson(ignoreNull: true));
                }
            }

            if (ri.RoomName == room.RoomId)
                ri.RoomName = await room.GetNameOrFallbackAsync();

            return (room.RoomId, ri);
        }
        catch (MatrixException e) {
            if (e.ErrorCode == "M_NOT_FOUND") Console.WriteLine($"m.room.power_levels does not exist in {room.RoomId}!!!");
            else throw;
        }

        return null;
    }

    private async Task Disband() {
        var space = new DMSpaceRoom(SetupData.Homeserver, SetupData.DmSpaceConfiguration.DMSpaceId);
        await space.DisbandDMSpace();
        NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
    }

}