diff options
Diffstat (limited to 'MatrixRoomUtils.Web')
48 files changed, 1217 insertions, 1540 deletions
diff --git a/MatrixRoomUtils.Web/App.razor b/MatrixRoomUtils.Web/App.razor index 4e2789d..e58212b 100644 --- a/MatrixRoomUtils.Web/App.razor +++ b/MatrixRoomUtils.Web/App.razor @@ -12,10 +12,9 @@ </Router> @code { - protected override async Task OnInitializedAsync() - { - if (!RuntimeCache.WasLoaded) - { + + protected override async Task OnInitializedAsync() { + if (!RuntimeCache.WasLoaded) { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); Console.WriteLine("Loaded from local storage"); StateHasChanged(); diff --git a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs index f70572b..4e7117d 100644 --- a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs +++ b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs @@ -3,23 +3,20 @@ using MatrixRoomUtils.Core; namespace MatrixRoomUtils.Web.Classes; -public partial class LocalStorageWrapper -{ - private static SemaphoreSlim _semaphoreSlim = new(1); +public class LocalStorageWrapper { + private static readonly SemaphoreSlim _semaphoreSlim = new(1); public static Settings Settings { get; set; } = new(); //some basic logic - public static async Task InitialiseRuntimeVariables(ILocalStorageService localStorage) - { + public static async Task InitialiseRuntimeVariables(ILocalStorageService localStorage) { //RuntimeCache stuff async void Save() => await SaveToLocalStorage(localStorage); RuntimeCache.Save = Save; RuntimeCache.SaveObject = async (key, obj) => await localStorage.SetItemAsync(key, obj); - RuntimeCache.RemoveObject = async (key) => await localStorage.RemoveItemAsync(key); - if (RuntimeCache.LastUsedToken != null) - { - Console.WriteLine($"Access token is not null, creating authenticated home server"); + RuntimeCache.RemoveObject = async key => await localStorage.RemoveItemAsync(key); + if (RuntimeCache.LastUsedToken != null) { + Console.WriteLine("Access token is not null, creating authenticated home server"); Console.WriteLine($"Homeserver cache: {RuntimeCache.HomeserverResolutionCache.Count} entries"); // Console.WriteLine(RuntimeCache.HomeserverResolutionCache.ToJson()); RuntimeCache.CurrentHomeServer = await new AuthenticatedHomeServer(RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.UserId, RuntimeCache.LastUsedToken, @@ -28,26 +25,24 @@ public partial class LocalStorageWrapper } } - public static async Task LoadFromLocalStorage(ILocalStorageService localStorage) - { + public static async Task LoadFromLocalStorage(ILocalStorageService localStorage) { await _semaphoreSlim.WaitAsync(); - if (RuntimeCache.WasLoaded) - { + if (RuntimeCache.WasLoaded) { _semaphoreSlim.Release(); return; } + Console.WriteLine("Loading from local storage..."); - Settings = await localStorage.GetItemAsync<Settings>("rory.matrixroomutils.settings") ?? new(); + Settings = await localStorage.GetItemAsync<Settings>("rory.matrixroomutils.settings") ?? new Settings(); RuntimeCache.LastUsedToken = await localStorage.GetItemAsync<string>("rory.matrixroomutils.last_used_token"); - RuntimeCache.LoginSessions = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.login_sessions") ?? new(); - RuntimeCache.HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new(); + RuntimeCache.LoginSessions = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.login_sessions") ?? new Dictionary<string, UserInfo>(); + RuntimeCache.HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new Dictionary<string, HomeServerResolutionResult>(); Console.WriteLine($"[LocalStorageWrapper] Loaded {RuntimeCache.LoginSessions.Count} login sessions, {RuntimeCache.HomeserverResolutionCache.Count} homeserver resolution cache entries"); //RuntimeCache.GenericResponseCache = await localStorage.GetItemAsync<Dictionary<string, ObjectCache<object>>>("rory.matrixroomutils.generic_cache") ?? new(); - foreach (var s in (await localStorage.KeysAsync()).Where(x => x.StartsWith("rory.matrixroomutils.generic_cache:")).ToList()) - { + foreach (var s in (await localStorage.KeysAsync()).Where(x => x.StartsWith("rory.matrixroomutils.generic_cache:")).ToList()) { Console.WriteLine($"Loading generic cache entry {s}"); RuntimeCache.GenericResponseCache[s.Replace("rory.matrixroomutils.generic_cache:", "")] = await localStorage.GetItemAsync<ObjectCache<object>>(s); } @@ -57,36 +52,31 @@ public partial class LocalStorageWrapper _semaphoreSlim.Release(); } - public static async Task SaveToLocalStorage(ILocalStorageService localStorage) - { + public static async Task SaveToLocalStorage(ILocalStorageService localStorage) { Console.WriteLine("Saving to local storage..."); await localStorage.SetItemAsync("rory.matrixroomutils.settings", Settings); if (RuntimeCache.LoginSessions != null) await localStorage.SetItemAsync("rory.matrixroomutils.login_sessions", RuntimeCache.LoginSessions); if (RuntimeCache.LastUsedToken != null) await localStorage.SetItemAsync("rory.matrixroomutils.last_used_token", RuntimeCache.LastUsedToken); } - public static async Task SaveCacheToLocalStorage(ILocalStorageService localStorage, bool awaitSave = true, bool saveGenericCache = true) - { + public static async Task SaveCacheToLocalStorage(ILocalStorageService localStorage, bool awaitSave = true, bool saveGenericCache = true) { await localStorage.SetItemAsync("rory.matrixroomutils.homeserver_resolution_cache", RuntimeCache.HomeserverResolutionCache.DistinctBy(x => x.Key) .ToDictionary(x => x.Key, x => x.Value)); //await localStorage.SetItemAsync("rory.matrixroomutils.generic_cache", RuntimeCache.GenericResponseCache); - if(saveGenericCache) - foreach (var s in RuntimeCache.GenericResponseCache.Keys) - { + if (saveGenericCache) + foreach (var s in RuntimeCache.GenericResponseCache.Keys) { var t = localStorage.SetItemAsync($"rory.matrixroomutils.generic_cache:{s}", RuntimeCache.GenericResponseCache[s]); if (awaitSave) await t; } } } -public class Settings -{ +public class Settings { public DeveloperSettings DeveloperSettings { get; set; } = new(); } -public class DeveloperSettings -{ +public class DeveloperSettings { public bool EnableLogViewers { get; set; } = false; public bool EnableConsoleLogging { get; set; } = true; public bool EnablePortableDevtools { get; set; } = false; diff --git a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs index c43bd3c..77c8281 100644 --- a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs +++ b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs @@ -1,110 +1,89 @@ +using System.Text.Json.Nodes; using MatrixRoomUtils.Core; using MatrixRoomUtils.Core.Responses; namespace MatrixRoomUtils.Web.Classes.RoomCreationTemplates; -public class DefaultRoomCreationTemplate : IRoomCreationTemplate -{ +public class DefaultRoomCreationTemplate : IRoomCreationTemplate { public string Name => "Default"; - public CreateRoomRequest CreateRoomRequest - { - get - { - return new() - { - Name = "My new room", - RoomAliasName = "myroom", - InitialState = new() - { - new() - { - Type = "m.room.history_visibility", - Content = new - { - history_visibility = "world_readable" - } - }, - new StateEvent<Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent> - { - Type = "m.room.guest_access", - Content = new() - { - GuestAccess = "can_join" - } - }, - new() - { - Type = "m.room.join_rules", - Content = new - { - join_rule = "public" - } - }, - new() - { - Type = "m.room.server_acl", - Content = new - { - allow = new[] { "*" }, - deny = Array.Empty<string>(), - allow_ip_literals = false - } - }, - new() - { - Type = "m.room.avatar", - Content = new - { - url = "mxc://feline.support/UKNhEyrVsrAbYteVvZloZcFj" - } + + public CreateRoomRequest CreateRoomRequest => + new CreateRoomRequest { + Name = "My new room", + RoomAliasName = "myroom", + InitialState = new List<StateEvent> { + new() { + Type = "m.room.history_visibility", + Content = new { + history_visibility = "world_readable" } }, - Visibility = "public", - PowerLevelContentOverride = new() - { - UsersDefault = 0, - EventsDefault = 100, - StateDefault = 50, - Invite = 0, - Redact = 50, - Kick = 50, - Ban = 50, - NotificationsPl = new() - { - Room = 50 - }, - Events = new() - { - { "im.vector.modular.widgets", 50 }, - { "io.element.voice_broadcast_info", 50 }, - { "m.reaction", 100 }, - { "m.room.avatar", 50 }, - { "m.room.canonical_alias", 50 }, - { "m.room.encryption", 100 }, - { "m.room.history_visibility", 100 }, - { "m.room.name", 50 }, - { "m.room.pinned_events", 50 }, - { "m.room.power_levels", 100 }, - { "m.room.redaction", 100 }, - { "m.room.server_acl", 100 }, - { "m.room.tombstone", 100 }, - { "m.room.topic", 50 }, - { "m.space.child", 50 }, - { "org.matrix.msc3401.call", 50 }, - { "org.matrix.msc3401.call.member", 50 } - }, - Users = new() - { - { RuntimeCache.CurrentHomeServer.UserId, 100 }, - }, + new StateEvent<Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent> { + Type = "m.room.guest_access", + Content = new Pages.RoomManager.RoomManagerCreateRoom.GuestAccessContent { + GuestAccess = "can_join" + } }, - CreationContent = new() - { - { - "type", null + new() { + Type = "m.room.join_rules", + Content = new { + join_rule = "public" + } + }, + new() { + Type = "m.room.server_acl", + Content = new { + allow = new[] { "*" }, + deny = Array.Empty<string>(), + allow_ip_literals = false } + }, + new() { + Type = "m.room.avatar", + Content = new { + url = "mxc://feline.support/UKNhEyrVsrAbYteVvZloZcFj" + } + } + }, + Visibility = "public", + PowerLevelContentOverride = new PowerLevelEvent { + UsersDefault = 0, + EventsDefault = 100, + StateDefault = 50, + Invite = 0, + Redact = 50, + Kick = 50, + Ban = 50, + NotificationsPl = new NotificationsPL { + Room = 50 + }, + Events = new Dictionary<string, int> { + { "im.vector.modular.widgets", 50 }, + { "io.element.voice_broadcast_info", 50 }, + { "m.reaction", 100 }, + { "m.room.avatar", 50 }, + { "m.room.canonical_alias", 50 }, + { "m.room.encryption", 100 }, + { "m.room.history_visibility", 100 }, + { "m.room.name", 50 }, + { "m.room.pinned_events", 50 }, + { "m.room.power_levels", 100 }, + { "m.room.redaction", 100 }, + { "m.room.server_acl", 100 }, + { "m.room.tombstone", 100 }, + { "m.room.topic", 50 }, + { "m.space.child", 50 }, + { "org.matrix.msc3401.call", 50 }, + { "org.matrix.msc3401.call.member", 50 } + }, + Users = new Dictionary<string, int> { + { RuntimeCache.CurrentHomeServer.UserId, 100 } + } + }, + CreationContent = new JsonObject { + { + "type", null } - }; - } - } + } + }; } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs index 7f84dc4..bbb09b7 100644 --- a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs +++ b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/IRoomCreationTemplate.cs @@ -2,8 +2,7 @@ using MatrixRoomUtils.Core.Responses; namespace MatrixRoomUtils.Web.Classes.RoomCreationTemplates; -public interface IRoomCreationTemplate -{ +public interface IRoomCreationTemplate { public CreateRoomRequest CreateRoomRequest { get; } public string Name { get; } } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/FileUploadTest.razor b/MatrixRoomUtils.Web/FileUploadTest.razor index 2e25b54..478a3e4 100644 --- a/MatrixRoomUtils.Web/FileUploadTest.razor +++ b/MatrixRoomUtils.Web/FileUploadTest.razor @@ -6,8 +6,7 @@ @code { - private async void FilePicked(InputFileChangeEventArgs obj) - { + private async void FilePicked(InputFileChangeEventArgs obj) { Console.WriteLine("FilePicked"); Console.WriteLine(obj.File.Name); Console.WriteLine(obj.File.Size); diff --git a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj index cf6ce87..c76452f 100644 --- a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj +++ b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj @@ -7,17 +7,17 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Blazored.LocalStorage" Version="4.3.0" /> - <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.3" /> - <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.3" PrivateAssets="all" /> + <PackageReference Include="Blazored.LocalStorage" Version="4.3.0"/> + <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.3"/> + <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.3" PrivateAssets="all"/> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\MatrixRoomUtils.Core\MatrixRoomUtils.Core.csproj" /> + <ProjectReference Include="..\MatrixRoomUtils.Core\MatrixRoomUtils.Core.csproj"/> </ItemGroup> <ItemGroup> - <Folder Include="Shared\TimelineComponents\TimelineMessageComponents" /> + <Folder Include="Shared\TimelineComponents\TimelineMessageComponents"/> </ItemGroup> - + </Project> diff --git a/MatrixRoomUtils.Web/Pages/About.razor b/MatrixRoomUtils.Web/Pages/About.razor index d47e60b..cf43c4f 100644 --- a/MatrixRoomUtils.Web/Pages/About.razor +++ b/MatrixRoomUtils.Web/Pages/About.razor @@ -13,26 +13,23 @@ <br/><br/> <p>You can find the source code on <a href="https://git.rory.gay/MatrixRoomUtils.git/">my git server</a>.<br/></p> <p>You can also join the <a href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support">Matrix room</a> for this project.</p> -@if (showBinDownload) -{ +@if (showBinDownload) { <p>This deployment also serves a copy of the compiled, hosting-ready binaries at <a href="MRU-BIN.tar.xz">/MRU-BIN.tar.xz</a>!</p> } -@if (showSrcDownload) -{ +@if (showSrcDownload) { <p>This deployment also serves a copy of the compiled, hosting-ready binaries at <a href="MRU-SRC.tar.xz">/MRU-SRC.tar.xz</a>!</p> } @code { - private bool showBinDownload { get; set; } = false; - private bool showSrcDownload { get; set; } = false; + private bool showBinDownload { get; set; } + private bool showSrcDownload { get; set; } - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { using var hc = new HttpClient(); - var hr = await hc.SendAsync(new(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri)); + var hr = await hc.SendAsync(new HttpRequestMessage(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri)); showBinDownload = hr.StatusCode == HttpStatusCode.OK; - hr = await hc.SendAsync(new(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-SRC.tar.xz").AbsoluteUri)); + hr = await hc.SendAsync(new HttpRequestMessage(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-SRC.tar.xz").AbsoluteUri)); showSrcDownload = hr.StatusCode == HttpStatusCode.OK; await base.OnInitializedAsync(); } diff --git a/MatrixRoomUtils.Web/Pages/DataExportPage.razor b/MatrixRoomUtils.Web/Pages/DataExportPage.razor index 49fb700..732cd74 100644 --- a/MatrixRoomUtils.Web/Pages/DataExportPage.razor +++ b/MatrixRoomUtils.Web/Pages/DataExportPage.razor @@ -1,5 +1,4 @@ @page "/Export" -@using MatrixRoomUtils.Web.Shared.IndexComponents @using System.Text.Json @inject NavigationManager NavigationManager @inject ILocalStorageService LocalStorage @@ -11,12 +10,10 @@ <br/><br/> <h5>Signed in accounts - <a href="/Login">Add new account</a> or <a href="/ImportUsers">Import from TSV</a></h5> <hr/> -@if (_isLoaded) -{ -@foreach (var (token, user) in RuntimeCache.LoginSessions) -{ +@if (_isLoaded) { + @foreach (var (token, user) in RuntimeCache.LoginSessions) { @* <IndexUserItem User="@user"/> *@ - <pre> + <pre> @user.LoginResponse.UserId[1..].Split(":")[0]\auth\access_token=@token @user.LoginResponse.UserId[1..].Split(":")[0]\auth\device_id=@user.LoginResponse.DeviceId @user.LoginResponse.UserId[1..].Split(":")[0]\auth\home_server=@(RuntimeCache.HomeserverResolutionCache.ContainsKey(user.LoginResponse.HomeServer) ? RuntimeCache.HomeserverResolutionCache[user.LoginResponse.HomeServer].Result : "loading...") @@ -26,10 +23,9 @@ @user.LoginResponse.UserId[1..].Split(":")[0]\user\online_key_backup=true @user.LoginResponse.UserId[1..].Split(":")[0]\user\only_share_keys_with_verified_users=false </pre> + } } -} -else -{ +else { <p>Loading...</p> <p>@resolvedHomeservers/@totalHomeservers homeservers resolved...</p> } @@ -39,31 +35,26 @@ else private int resolvedHomeservers; private int totalHomeservers; - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - if (!RuntimeCache.WasLoaded) - { + if (!RuntimeCache.WasLoaded) { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); } var homeservers = RuntimeCache.LoginSessions.Values.Select(x => x.LoginResponse.HomeServer).Distinct(); totalHomeservers = homeservers.Count(); StateHasChanged(); - foreach (var hs in homeservers) - { - if (RuntimeCache.HomeserverResolutionCache.ContainsKey(hs)) - { + foreach (var hs in homeservers) { + if (RuntimeCache.HomeserverResolutionCache.ContainsKey(hs)) { resolvedHomeservers++; continue; } var resolvedHomeserver = (await new RemoteHomeServer(hs).Configure()).FullHomeServerDomain; - RuntimeCache.HomeserverResolutionCache.Add(hs, new() { Result = resolvedHomeserver, ResolutionTime = DateTime.Now }); + RuntimeCache.HomeserverResolutionCache.Add(hs, new HomeServerResolutionResult { Result = resolvedHomeserver, ResolutionTime = DateTime.Now }); await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); Console.WriteLine("Saved to local storage:"); - Console.WriteLine(JsonSerializer.Serialize(RuntimeCache.HomeserverResolutionCache, new JsonSerializerOptions() - { + Console.WriteLine(JsonSerializer.Serialize(RuntimeCache.HomeserverResolutionCache, new JsonSerializerOptions { WriteIndented = true })); resolvedHomeservers++; diff --git a/MatrixRoomUtils.Web/Pages/DebugTools.razor b/MatrixRoomUtils.Web/Pages/DebugTools.razor index c8fabaa..da5c172 100644 --- a/MatrixRoomUtils.Web/Pages/DebugTools.razor +++ b/MatrixRoomUtils.Web/Pages/DebugTools.razor @@ -1,26 +1,24 @@ @page "/Debug" -@using MatrixRoomUtils.Core.Interfaces -@using MatrixRoomUtils.Core.Extensions @using System.Reflection +@using MatrixRoomUtils.Core.Extensions +@using MatrixRoomUtils.Core.Interfaces @inject ILocalStorageService LocalStorage @inject NavigationManager NavigationManager <h3>Debug Tools</h3> <hr/> -@if (Rooms.Count == 0) -{ +@if (Rooms.Count == 0) { <p>You are not in any rooms!</p> @* <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> *@ } -else -{ +else { <details> <summary>Room List</summary> - @foreach (var room in Rooms) - { - <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.', '~')"><RoomListItem RoomId="@room"></RoomListItem></a> + @foreach (var room in Rooms) { + <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.', '~')"> + <RoomListItem RoomId="@room"></RoomListItem> + </a> } </details> - } <details open> @@ -38,50 +36,44 @@ else @code { public List<string> Rooms { get; set; } = new(); - protected override async Task OnInitializedAsync() - { + + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeCache.CurrentHomeServer == null) - { + if (RuntimeCache.CurrentHomeServer == null) { NavigationManager.NavigateTo("/Login"); return; } - Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x=>x.RoomId).ToList(); + Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x => x.RoomId).ToList(); Console.WriteLine("Fetched joined rooms!"); } - //send req string get_request_url { get; set; } = ""; string get_request_result { get; set; } = ""; - private async Task SendGetRequest() - { + + private async Task SendGetRequest() { var field = typeof(IHomeServer).GetRuntimeFields().First(x => x.ToString().Contains("<_httpClient>k__BackingField")); var httpClient = field.GetValue(RuntimeCache.CurrentHomeServer) as HttpClient; - try - { + try { var res = await httpClient.GetAsync(get_request_url); - if (res.IsSuccessStatusCode) - { - if(res.Content.Headers.ContentType.MediaType == "application/json") + if (res.IsSuccessStatusCode) { + if (res.Content.Headers.ContentType.MediaType == "application/json") get_request_result = (await res.Content.ReadFromJsonAsync<object>()).ToJson(); else get_request_result = await res.Content.ReadAsStringAsync(); StateHasChanged(); return; } - if(res.Content.Headers.ContentType.MediaType == "application/json") + if (res.Content.Headers.ContentType.MediaType == "application/json") get_request_result = $"Error: {res.StatusCode}\n" + (await res.Content.ReadFromJsonAsync<object>()).ToJson(); else get_request_result = $"Error: {res.StatusCode}\n" + await res.Content.ReadAsStringAsync(); - } - catch (Exception e) - { + catch (Exception e) { get_request_result = $"Error: {e}"; } StateHasChanged(); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/DevOptions.razor b/MatrixRoomUtils.Web/Pages/DevOptions.razor index 3ca86b4..0843d5f 100644 --- a/MatrixRoomUtils.Web/Pages/DevOptions.razor +++ b/MatrixRoomUtils.Web/Pages/DevOptions.razor @@ -19,15 +19,13 @@ <summary>View caches</summary> <p>Generic cache:</p> <ul> - @foreach (var item in RuntimeCache.GenericResponseCache) - { + @foreach (var item in RuntimeCache.GenericResponseCache) { <li> @item.Key: @item.Value.Cache.Count entries<br/> - @if (item.Value.Cache.Count > 0) - { + @if (item.Value.Cache.Count > 0) { <p>Earliest expiry: @(item.Value.Cache.Min(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Min(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p> @* <p>Average expiry: @(item.Value.Cache.Average(x => x.Value.ExpiryTime.Value))(@item.Value.Cache.Average(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now) from now)</p> *@ - <p>Last expiry: @(item.Value.Cache.Max(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Max(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p> + <p>Last expiry: @(item.Value.Cache.Max(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Max(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p> } </li> } @@ -35,50 +33,42 @@ </details> @code { - protected override async Task OnInitializedAsync() - { + + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - Task.Run(async () => - { - while (true) - { + Task.Run(async () => { + while (true) { await Task.Delay(1000); StateHasChanged(); } }); } - protected async Task LogStuff() - { + protected async Task LogStuff() { await Task.Delay(100); Console.WriteLine($"Settings: {LocalStorageWrapper.Settings.ToJson()}"); - + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); } - protected async Task DropCaches() - { - foreach (var (key, value) in RuntimeCache.GenericResponseCache) - { + protected async Task DropCaches() { + foreach (var (key, value) in RuntimeCache.GenericResponseCache) { value.Cache.Clear(); } - - //RuntimeCache.GenericResponseCache.Clear(); + + //RuntimeCache.GenericResponseCache.Clear(); RuntimeCache.HomeserverResolutionCache.Clear(); await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } - protected async Task RandomiseCacheTimers() - { - foreach (var keyValuePair in RuntimeCache.GenericResponseCache) - { + protected async Task RandomiseCacheTimers() { + foreach (var keyValuePair in RuntimeCache.GenericResponseCache) { Console.WriteLine($"Randomising cache timer for {keyValuePair.Key}"); - foreach (var cacheItem in keyValuePair.Value.Cache) - { + foreach (var cacheItem in keyValuePair.Value.Cache) { cacheItem.Value.ExpiryTime = DateTime.Now.AddSeconds(Random.Shared.Next(15, 120)); } - + await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } } diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor index b77012b..f972236 100644 --- a/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor +++ b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor @@ -2,6 +2,10 @@ <h3>Homeserver Admininistration</h3> <hr/> +<h4>Synapse tools</h4> +<hr/> +<a href="/HSAdmin/RoomQuery">Query rooms</a> + @code { - + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor index 109ad7d..e6f95c7 100644 --- a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor +++ b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor @@ -1,73 +1,78 @@ -@page "/RoomQuery" +@page "/HSAdmin/RoomQuery" @using MatrixRoomUtils.Core.Extensions -@using System.Runtime.InteropServices -@using System.ComponentModel @using MatrixRoomUtils.Core.Responses.Admin <h3>Homeserver Administration - Room Query</h3> <label>Search name: </label> -<InputText @bind-Value="SearchTerm" /><br/> +<InputText @bind-Value="SearchTerm"/><br/> <label>Search id/name/creator (slow!): </label> -<InputText @bind-Value="ContentSearchTerm" /><br/> +<InputText @bind-Value="ContentSearchTerm"/><br/> <label>Order by: </label> <select @bind="OrderBy"> - @foreach (var item in validOrderBy) - { + @foreach (var item in validOrderBy) { <option value="@item.Key">@item.Value</option> } </select><br/> <label>Ascending: </label> -<InputCheckbox @bind-Value="Ascending" /><br/> +<InputCheckbox @bind-Value="Ascending"/><br/> <button class="btn btn-primary" @onclick="Search">Search</button> <br/> -@foreach (var res in Results) -{ +@foreach (var res in Results) { <div style="background-color: #ffffff11; border-radius: 0.5em; display: block; margin-top: 4px; padding: 4px;"> - <RoomListItem RoomId="@res.RoomId"></RoomListItem> - <p>@res.CanonicalAlias, created by <InlineUserItem UserId="@res.Creator"></InlineUserItem></p> + <RoomListItem RoomName="@res.Name" RoomId="@res.RoomId"></RoomListItem> + <p> + @res.CanonicalAlias + @if (!string.IsNullOrWhiteSpace(res.Creator)) { + <span> + , created by <InlineUserItem UserId="@res.Creator"></InlineUserItem> + </span> + } + </p> <p>@res.StateEvents state events</p> <p>@res.JoinedMembers members, of which @res.JoinedLocalMembers are on this server</p> </div> } @code { - - [Parameter, SupplyParameterFromQuery(Name = "order_by")] + + [Parameter] + [SupplyParameterFromQuery(Name = "order_by")] public string? OrderBy { get; set; } - - [Parameter, SupplyParameterFromQuery(Name = "search_term")] + + [Parameter] + [SupplyParameterFromQuery(Name = "search_term")] public string SearchTerm { get; set; } - - [Parameter, SupplyParameterFromQuery(Name = "content_search_term")] + + [Parameter] + [SupplyParameterFromQuery(Name = "content_search_term")] public string ContentSearchTerm { get; set; } - - [Parameter, SupplyParameterFromQuery(Name = "ascending")] + + [Parameter] + [SupplyParameterFromQuery(Name = "ascending")] public bool Ascending { get; set; } public List<AdminRoomListingResult.AdminRoomListingResultRoom> Results { get; set; } = new(); - - protected override async Task OnParametersSetAsync() - { - if(Ascending == null) + + private string Status { get; set; } + + protected override async Task OnParametersSetAsync() { + if (Ascending == null) Ascending = true; OrderBy ??= "name"; } - - private async Task Search() - { + + private async Task Search() { Results.Clear(); var searchRooms = RuntimeCache.CurrentHomeServer.Admin.SearchRoomsAsync(orderBy: OrderBy!, dir: Ascending ? "f" : "b", searchTerm: SearchTerm, contentSearch: ContentSearchTerm).GetAsyncEnumerator(); - while (await searchRooms.MoveNextAsync()) - { + while (await searchRooms.MoveNextAsync()) { var room = searchRooms.Current; - Console.WriteLine("Hit: " + room.ToJson(indent: false)); + Console.WriteLine("Hit: " + room.ToJson(false)); Results.Add(room); } } - private Dictionary<string, string> validOrderBy = new Dictionary<string, string>() - { + private readonly Dictionary<string, string> validOrderBy = new() { { "name", "Room name" }, { "canonical_alias", "Main alias address" }, { "joined_members", "Number of members (reversed)" }, @@ -80,7 +85,7 @@ { "join_rules", "Join rules" }, { "guest_access", "Guest access" }, { "history_visibility", "Visibility of history" }, - { "state_events", "Number of state events" }, + { "state_events", "Number of state events" } }; } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor index decdb0c..33cca61 100644 --- a/MatrixRoomUtils.Web/Pages/Index.razor +++ b/MatrixRoomUtils.Web/Pages/Index.razor @@ -12,18 +12,15 @@ Small collection of tools to do not-so-everyday things. <h5>Signed in accounts - <a href="/Login">Add new account</a></h5> <hr/> <form> - @foreach (var (token, user) in RuntimeCache.LoginSessions) - { + @foreach (var (token, user) in RuntimeCache.LoginSessions) { <IndexUserItem User="@user"/> } </form> @code { - protected override async Task OnInitializedAsync() - { - if (!RuntimeCache.WasLoaded) - { + protected override async Task OnInitializedAsync() { + if (!RuntimeCache.WasLoaded) { Console.WriteLine("[INDEX] !!! LOCALSTORAGE WAS NOT LOADED !!!"); await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); } diff --git a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor index 13b717d..92a8445 100644 --- a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor +++ b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor @@ -5,33 +5,25 @@ <h3>Known Homeserver List</h3> <hr/> -@if (!IsFinished) -{ +@if (!IsFinished) { <p>Loading... Please wait...</p> <progress value="@QueryProgress.ProcessedRooms" max="@QueryProgress.TotalRooms"></progress> <p>@QueryProgress.ProcessedRooms / @QueryProgress.TotalRooms</p> - @foreach (var (room, state) in QueryProgress.ProcessedUsers.Where(x => !x.Value.IsFinished).OrderByDescending(x => x.Value.Total).ToList()) - { - @if (state.Blocked) - { + @foreach (var (room, state) in QueryProgress.ProcessedUsers.Where(x => !x.Value.IsFinished).OrderByDescending(x => x.Value.Total).ToList()) { + @if (state.Blocked) { <p>🔒 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p> } - else if (state.Slowmode) - { - + else if (state.Slowmode) { <p>🐢 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p> } - else - { + else { <p>@room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...</p> } <progress value="@state.Processed" max="@state.Total"></progress> } } -else -{ - @foreach (var server in HomeServers.OrderByDescending(x => x.KnownUserCount).ThenBy(x => x.Server).ToList()) - { +else { + @foreach (var server in HomeServers.OrderByDescending(x => x.KnownUserCount).ThenBy(x => x.Server).ToList()) { <p>@server.Server - @server.KnownUserCount</p> } } @@ -42,15 +34,12 @@ else bool IsFinished { get; set; } HomeServerInfoQueryProgress QueryProgress { get; set; } = new(); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); var sw = Stopwatch.StartNew(); - HomeServers = await GetHomeservers(progressCallback: async progress => - { - if (sw.ElapsedMilliseconds > 1000) - { + HomeServers = await GetHomeservers(progressCallback: async progress => { + if (sw.ElapsedMilliseconds > 1000) { Console.WriteLine("Progress updated..."); QueryProgress = progress; StateHasChanged(); @@ -69,9 +58,7 @@ else await base.OnInitializedAsync(); } - - private async Task<List<HomeServerInfo>> GetHomeservers(int memberLimit = 1000, Func<HomeServerInfoQueryProgress, Task<bool>>? progressCallback = null) - { + private async Task<List<HomeServerInfo>> GetHomeservers(int memberLimit = 1000, Func<HomeServerInfoQueryProgress, Task<bool>>? progressCallback = null) { HomeServerInfoQueryProgress progress = new(); List<HomeServerInfo> homeServers = new(); var rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms(); @@ -79,16 +66,14 @@ else var semaphore = new SemaphoreSlim(4); var semLock = new SemaphoreSlim(1); - var tasks = rooms.Select(async room => - { + var tasks = rooms.Select(async room => { await semaphore.WaitAsync(); - progress.ProcessedUsers.Add(room, new()); + progress.ProcessedUsers.Add(room, new HomeServerInfoQueryProgress.State()); Console.WriteLine($"Fetching states for room ({rooms.IndexOf(room)}/{rooms.Count}) ({room.RoomId})"); var states = (await room.GetStateAsync("")).Value.Deserialize<List<StateEventResponse>>(); states.RemoveAll(x => x.Type != "m.room.member" || x.Content.GetProperty("membership").GetString() != "join"); Console.WriteLine($"Room {room.RoomId} has {states.Count} members"); - if (states.Count > memberLimit) - { + if (states.Count > memberLimit) { Console.WriteLine("Skipping!"); semaphore.Release(); progress.ProcessedUsers.Remove(room); @@ -97,37 +82,31 @@ else } progress.ProcessedUsers[room].Total = states.Count; var updateInterval = progress.ProcessedUsers[room].Total >= 1000 ? 1000 : 100; - while (progress.ProcessedUsers.Any(x => x.Value.Total == 0) && progress.ProcessedUsers[room].Total >= 1000) - { + while (progress.ProcessedUsers.Any(x => x.Value.Total == 0) && progress.ProcessedUsers[room].Total >= 1000) { progress.ProcessedUsers[room].Blocked = true; await Task.Delay(1000); - // if(progressCallback != null) - // await progressCallback.Invoke(progress); + // if(progressCallback != null) + // await progressCallback.Invoke(progress); } progress.ProcessedUsers[room].Blocked = false; - int processedStates = 0; - foreach (var state in states) - { + var processedStates = 0; + foreach (var state in states) { await semLock.WaitAsync(); semLock.Release(); - if (progress.ProcessedUsers.Count(x => x.Value.Total == 0) > 5 && progress.ProcessedUsers[room].Total >= 200) - { + if (progress.ProcessedUsers.Count(x => x.Value.Total == 0) > 5 && progress.ProcessedUsers[room].Total >= 200) { progress.ProcessedUsers[room].Slowmode = true; await Task.Delay(progress.ProcessedUsers[room].Total >= 500 ? 1000 : 100); } - else - { + else { progress.ProcessedUsers[room].Slowmode = false; } - if (!homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) - { - homeServers.Add(new HomeServerInfo() { Server = state.StateKey.Split(':')[1] }); + if (!homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) { + homeServers.Add(new HomeServerInfo { Server = state.StateKey.Split(':')[1] }); } var hs = homeServers.First(x => x.Server == state.StateKey.Split(':')[1]); if (!hs.KnownUsers.Contains(state.StateKey.Split(':')[0])) hs.KnownUsers.Add(state.StateKey.Split(':')[0]); - if (++progress.ProcessedUsers[room].Processed % updateInterval == 0 && progressCallback != null) - { + if (++progress.ProcessedUsers[room].Processed % updateInterval == 0 && progressCallback != null) { await semLock.WaitAsync(); var _ = await progressCallback.Invoke(progress); semLock.Release(); @@ -148,29 +127,26 @@ else return homeServers; } - class HomeServerInfo - { + class HomeServerInfo { public string Server { get; set; } public int? KnownUserCount { get; set; } - public List<string> KnownUsers { get; set; } = new(); + public List<string> KnownUsers { get; } = new(); } - class HomeServerInfoQueryProgress - { + class HomeServerInfoQueryProgress { public int ProcessedRooms { get; set; } public int TotalRooms { get; set; } - public Dictionary<Room, State> ProcessedUsers { get; set; } = new(); + public Dictionary<Room, State> ProcessedUsers { get; } = new(); public List<HomeServerInfo> CurrentState { get; set; } = new(); - public class State - { + public class State { public int Processed { get; set; } public int Total { get; set; } public bool Blocked { get; set; } public bool Slowmode { get; set; } public float Progress => (float)Processed / Total; public bool IsFinished { get; set; } - public Stopwatch Timing { get; set; } = Stopwatch.StartNew(); + public Stopwatch Timing { get; } = Stopwatch.StartNew(); } } diff --git a/MatrixRoomUtils.Web/Pages/LoginPage.razor b/MatrixRoomUtils.Web/Pages/LoginPage.razor index c46dc9a..16fdd24 100644 --- a/MatrixRoomUtils.Web/Pages/LoginPage.razor +++ b/MatrixRoomUtils.Web/Pages/LoginPage.razor @@ -1,6 +1,6 @@ @page "/Login" -@using System.Text.Json @using MatrixRoomUtils.Core.Authentication +@using System.Text.Json @using MatrixRoomUtils.Web.Shared.SimpleComponents @inject ILocalStorageService LocalStorage @inject IJSRuntime JsRuntime @@ -27,8 +27,7 @@ <h4>Parsed records</h4> <hr/> <table border="1"> - @foreach (var (homeserver, username, password) in records) - { + @foreach (var (homeserver, username, password) in records) { <tr style="background-color: @(RuntimeCache.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}") ? "green" : "unset")"> <td style="border-width: 1px;">@username</td> <td style="border-width: 1px;">@homeserver</td> @@ -41,19 +40,16 @@ <LogView></LogView> @code { - List<(string homeserver, string username, string password)> records = new(); + readonly List<(string homeserver, string username, string password)> records = new(); (string homeserver, string username, string password) newRecordInput = ("", "", ""); - async Task Login() - { - foreach (var (homeserver, username, password) in records) - { + async Task Login() { + foreach (var (homeserver, username, password) in records) { if (RuntimeCache.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}")) continue; var result = await MatrixAuth.Login(homeserver, username, password); Console.WriteLine($"Obtained access token for {result.UserId}!"); - var userinfo = new UserInfo() - { + var userinfo = new UserInfo { LoginResponse = result }; userinfo.Profile = await (await new AuthenticatedHomeServer(result.UserId, result.AccessToken, result.HomeServer).Configure()).GetProfile(result.UserId); @@ -66,18 +62,15 @@ await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); } - private async Task FileChanged(InputFileChangeEventArgs obj) - { - Console.WriteLine(JsonSerializer.Serialize(obj, new JsonSerializerOptions() - { + private async Task FileChanged(InputFileChangeEventArgs obj) { + Console.WriteLine(JsonSerializer.Serialize(obj, new JsonSerializerOptions { WriteIndented = true })); await using var rs = obj.File.OpenReadStream(); using var sr = new StreamReader(rs); - string TsvData = await sr.ReadToEndAsync(); + var TsvData = await sr.ReadToEndAsync(); records.Clear(); - foreach (var line in TsvData.Split('\n')) - { + foreach (var line in TsvData.Split('\n')) { var parts = line.Split('\t'); if (parts.Length != 3) continue; @@ -85,8 +78,7 @@ } } - private void AddRecord() - { + private void AddRecord() { records.Add(newRecordInput); newRecordInput = ("", "", ""); } diff --git a/MatrixRoomUtils.Web/Pages/MediaLocator.razor b/MatrixRoomUtils.Web/Pages/MediaLocator.razor index 19a0d4e..36cd8e6 100644 --- a/MatrixRoomUtils.Web/Pages/MediaLocator.razor +++ b/MatrixRoomUtils.Web/Pages/MediaLocator.razor @@ -7,8 +7,7 @@ <details> <summary>Checked homeserver list (@homeservers.Count entries)</summary> <ul> - @foreach (var hs in homeservers) - { + @foreach (var hs in homeservers) { <li>@hs</li> } </ul> @@ -16,26 +15,22 @@ <button @onclick="addMoreHomeservers">Add more homeservers</button> <br/> <span>MXC URL: </span> -<input type="text" @bind="mxcUrl" /> +<input type="text" @bind="mxcUrl"/> <button @onclick="executeSearch">Search</button> -@if (successResults.Count > 0) -{ +@if (successResults.Count > 0) { <h4>Successes</h4> <ul> - @foreach (var result in successResults) - { + @foreach (var result in successResults) { <li>@result</li> } </ul> } -@if (errorResults.Count > 0) -{ +@if (errorResults.Count > 0) { <h4>Errors</h4> <ul> - @foreach (var result in errorResults) - { + @foreach (var result in errorResults) { <li>@result</li> } </ul> @@ -44,15 +39,13 @@ @code { string mxcUrl { get; set; } - List<string> successResults = new List<string>(); - List<string> errorResults = new List<string>(); - List<string> homeservers = new List<string>(); + readonly List<string> successResults = new(); + readonly List<string> errorResults = new(); + readonly List<string> homeservers = new(); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - homeservers.AddRange(new [] - { + homeservers.AddRange(new[] { "matrix.org", "feline.support", "rory.gay", @@ -62,70 +55,58 @@ }); } - async Task executeSearch() - { + async Task executeSearch() { var sem = new SemaphoreSlim(128, 128); - homeservers.ForEach(async hs => - { + homeservers.ForEach(async hs => { await sem.WaitAsync(); var httpClient = new HttpClient { BaseAddress = new Uri(hs) }; httpClient.Timeout = TimeSpan.FromSeconds(5); var rmu = mxcUrl.Replace("mxc://", $"{hs}/_matrix/media/r0/download/"); - try - { + try { var res = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, rmu)); - if (res.IsSuccessStatusCode) - { + if (res.IsSuccessStatusCode) { successResults.Add($"{hs}: found - {res.Content.Headers.ContentLength} bytes"); StateHasChanged(); return; } errorResults.Add($"Error: {hs} - {res.StatusCode}\n" + await res.Content.ReadAsStringAsync()); } - catch (Exception e) - { + catch (Exception e) { errorResults.Add($"Error: {e}"); } - finally - { + finally { sem.Release(); } StateHasChanged(); }); } - - async Task addMoreHomeservers() - { + async Task addMoreHomeservers() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); var res = await Http.GetAsync("/homeservers.txt"); var content = await res.Content.ReadAsStringAsync(); homeservers.Clear(); var lines = content.Split("\n"); - + var rhs = new RemoteHomeServer("rory.gay"); var sem = new SemaphoreSlim(128, 128); - lines.ToList().ForEach(async line => - { + lines.ToList().ForEach(async line => { await sem.WaitAsync(); - try - { + try { homeservers.Add(await rhs.ResolveHomeserverFromWellKnown(line)); StateHasChanged(); - if(Random.Shared.Next(0,101) == 50) + if (Random.Shared.Next(0, 101) == 50) await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } - catch (Exception e) - { + catch (Exception e) { Console.WriteLine(e); } - finally - { + finally { sem.Release(); } }); - StateHasChanged(); } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor index bf03ee3..b15928a 100644 --- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor +++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor @@ -1,7 +1,7 @@ @page "/PolicyListEditor/{RoomId}" -@using System.Text.Json @using MatrixRoomUtils.Core.Extensions @using MatrixRoomUtils.Core.StateEventTypes +@using System.Text.Json @inject ILocalStorageService LocalStorage @inject NavigationManager NavigationManager <h3>Policy list editor - Editing @RoomId</h3> @@ -15,12 +15,10 @@ <InputCheckbox @bind-Value="_enableAvatars" @oninput="GetAllAvatars"></InputCheckbox><label>Enable avatars (WILL EXPOSE YOUR IP TO TARGET HOMESERVERS!)</label> -@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.server")) -{ +@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.server")) { <p>No server policies</p> } -else -{ +else { <h3>Server policies</h3> <hr/> <table class="table table-striped table-hover" style="width: fit-Content;"> @@ -33,8 +31,7 @@ else </tr> </thead> <tbody> - @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity != null)) - { + @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity != null)) { <tr> <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td> <td>@policyEvent.Content.Reason</td> @@ -59,23 +56,20 @@ else </tr> </thead> <tbody> - @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity == null)) - { + @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity == null)) { <tr> <td>@policyEvent.StateKey</td> - <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td> + <td>@policyEvent.Content.ToJson(false, true)</td> </tr> } </tbody> </table> </details> } -@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.room")) -{ +@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.room")) { <p>No room policies</p> } -else -{ +else { <h3>Room policies</h3> <hr/> <table class="table table-striped table-hover" style="width: fit-Content;"> @@ -88,8 +82,7 @@ else </tr> </thead> <tbody> - @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity != null)) - { + @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity != null)) { <tr> <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td> <td>@policyEvent.Content.Reason</td> @@ -113,30 +106,26 @@ else </tr> </thead> <tbody> - @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity == null)) - { + @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity == null)) { <tr> <td>@policyEvent.StateKey</td> - <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td> + <td>@policyEvent.Content.ToJson(false, true)</td> </tr> } </tbody> </table> </details> } -@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.user")) -{ +@if (!PolicyEvents.Any(x => x.Type == "m.policy.rule.user")) { <p>No user policies</p> } -else -{ +else { <h3>User policies</h3> <hr/> <table class="table table-striped table-hover" style="width: fit-Content;"> <thead> <tr> - @if (_enableAvatars) - { + @if (_enableAvatars) { <th scope="col"></th> } <th scope="col" style="max-width: 0.2vw; word-wrap: anywhere;">User</th> @@ -146,12 +135,12 @@ else </tr> </thead> <tbody> - @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) - { + @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) { <tr> - @if (_enableAvatars) - { - <td scope="col"><img style="width: 48px; height: 48px; aspect-ratio: unset; border-radius: 50%;" src="@(avatars.ContainsKey(policyEvent.Content.Entity) ? avatars[policyEvent.Content.Entity] : "")"/></td> + @if (_enableAvatars) { + <td scope="col"> + <img style="width: 48px; height: 48px; aspect-ratio: unset; border-radius: 50%;" src="@(avatars.ContainsKey(policyEvent.Content.Entity) ? avatars[policyEvent.Content.Entity] : "")"/> + </td> } <td style="word-wrap: anywhere;">Entity: @string.Join("", policyEvent.Content.Entity.Take(64))<br/>State: @string.Join("", policyEvent.StateKey.Take(64))</td> <td>@policyEvent.Content.Reason</td> @@ -175,11 +164,10 @@ else </tr> </thead> <tbody> - @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity == null)) - { + @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity == null)) { <tr> <td>@policyEvent.StateKey</td> - <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td> + <td>@policyEvent.Content.ToJson(false, true)</td> </tr> } </tbody> @@ -197,21 +185,19 @@ else [Parameter] public string? RoomId { get; set; } - - private bool _enableAvatars = false; - - static Dictionary<string, string?> avatars = new Dictionary<string, string?>(); - static Dictionary<string, RemoteHomeServer> servers = new Dictionary<string, RemoteHomeServer>(); + + private bool _enableAvatars; + + static readonly Dictionary<string, string?> avatars = new(); + static readonly Dictionary<string, RemoteHomeServer> servers = new(); public static List<StateEventResponse<PolicyRuleStateEventData>> PolicyEvents { get; set; } = new(); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - // if(RuntimeCache.AccessToken == null || RuntimeCache.CurrentHomeserver == null) - if (RuntimeCache.CurrentHomeServer == null) - { + // if(RuntimeCache.AccessToken == null || RuntimeCache.CurrentHomeserver == null) + if (RuntimeCache.CurrentHomeServer == null) { NavigationManager.NavigateTo("/Login"); return; } @@ -220,18 +206,16 @@ else Console.WriteLine("Policy list editor initialized!"); } - private async Task LoadStatesAsync() - { - // using var client = new HttpClient(); - // client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); - // var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); - // var Content = await response.Content.ReadAsStringAsync(); - // Console.WriteLine(JsonSerializer.Deserialize<object>(Content).ToJson()); - // var stateEvents = JsonSerializer.Deserialize<List<StateEventResponse>>(Content); + private async Task LoadStatesAsync() { + // using var client = new HttpClient(); + // client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken); + // var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); + // var Content = await response.Content.ReadAsStringAsync(); + // Console.WriteLine(JsonSerializer.Deserialize<object>(Content).ToJson()); + // var stateEvents = JsonSerializer.Deserialize<List<StateEventResponse>>(Content); var room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId); var stateEventsQuery = await room.GetStateAsync(""); - if (stateEventsQuery == null) - { + if (stateEventsQuery == null) { Console.WriteLine("state events query is null!!!"); } var stateEvents = stateEventsQuery.Value.Deserialize<List<StateEventResponse>>(); @@ -239,30 +223,25 @@ else .Select(x => JsonSerializer.Deserialize<StateEventResponse<PolicyRuleStateEventData>>(JsonSerializer.Serialize(x))).ToList(); StateHasChanged(); } - - private async Task GetAvatar(string userId) - { - try - { + + private async Task GetAvatar(string userId) { + try { if (avatars.ContainsKey(userId)) return; var hs = userId.Split(':')[1]; - RemoteHomeServer server = servers.ContainsKey(hs) ? servers[hs] : await new RemoteHomeServer(userId.Split(':')[1]).Configure(); + var server = servers.ContainsKey(hs) ? servers[hs] : await new RemoteHomeServer(userId.Split(':')[1]).Configure(); if (!servers.ContainsKey(hs)) servers.Add(hs, server); var profile = await server.GetProfile(userId); avatars.Add(userId, server.ResolveMediaUri(profile.AvatarUrl)); servers.Add(userId, server); StateHasChanged(); } - catch - { - // ignored + catch { + // ignored } } - - private async Task GetAllAvatars() - { - foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) - { + + private async Task GetAllAvatars() { + foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) { await GetAvatar(policyEvent.Content.Entity); } StateHasChanged(); diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor index e61598a..20eab7a 100644 --- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor +++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor @@ -1,29 +1,25 @@ @page "/PolicyListEditor" -@using System.Text.Json @using MatrixRoomUtils.Core.Extensions @inject ILocalStorageService LocalStorage @inject NavigationManager NavigationManager <h3>Policy list editor - Room list</h3> <hr/> -@if (PolicyRoomList.Count == 0) -{ +@if (PolicyRoomList.Count == 0) { <p>No policy rooms found.</p> <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> } -else -{ - @if (checkedRoomCount != totalRoomCount) - { +else { + @if (checkedRoomCount != totalRoomCount) { <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> } - foreach (var s in PolicyRoomList) - { - - <a style="color: unset; text-decoration: unset;" href="/PolicyListEditor/@s.RoomId.Replace('.','~')"><RoomListItem RoomId="@s.RoomId"> - <br/> - <span>Shortcode: @s.Shortcode</span> - </RoomListItem></a> + foreach (var s in PolicyRoomList) { + <a style="color: unset; text-decoration: unset;" href="/PolicyListEditor/@s.RoomId.Replace('.', '~')"> + <RoomListItem RoomId="@s.RoomId"> + <br/> + <span>Shortcode: @s.Shortcode</span> + </RoomListItem> + </a> @* <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">[@s.Shortcode] @s.Name (@s.RoomId)</a> *@ @* <br/> *@ } @@ -40,15 +36,13 @@ else public List<PolicyRoomInfo> PolicyRoomList { get; set; } = new(); - private int checkedRoomCount { get; set; } = 0; - private int totalRoomCount { get; set; } = 0; + private int checkedRoomCount { get; set; } + private int totalRoomCount { get; set; } - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeCache.CurrentHomeServer == null) - { + if (RuntimeCache.CurrentHomeServer == null) { NavigationManager.NavigateTo("/Login"); return; } @@ -56,59 +50,48 @@ else Console.WriteLine("Policy list editor initialized!"); } - private async Task EnumeratePolicyRooms() - { + private async Task EnumeratePolicyRooms() { var xxxrooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms(); totalRoomCount = xxxrooms.Count; StateHasChanged(); var xxxsemaphore = new SemaphoreSlim(1000); var xxxtasks = new List<Task<PolicyRoomInfo?>>(); - foreach (var room in xxxrooms) - { + foreach (var room in xxxrooms) { xxxtasks.Add(GetPolicyRoomInfo(room.RoomId, xxxsemaphore)); } var xxxresults = await Task.WhenAll(xxxtasks); PolicyRoomList.AddRange(xxxresults.Where(x => x != null).Select(x => x.Value)); Console.WriteLine($"Detected policy lists: {PolicyRoomList.ToJson()}"); - return; } - private async Task<PolicyRoomInfo?> GetPolicyRoomInfo(string room, SemaphoreSlim semaphore) - { - try - { + private async Task<PolicyRoomInfo?> GetPolicyRoomInfo(string room, SemaphoreSlim semaphore) { + try { await semaphore.WaitAsync(); - PolicyRoomInfo roomInfo = new() - { + PolicyRoomInfo roomInfo = new() { RoomId = room }; var r = await RuntimeCache.CurrentHomeServer.GetRoom(room); var shortcodeState = await r.GetStateAsync("org.matrix.mjolnir.shortcode"); - if(!shortcodeState.HasValue) return null; - roomInfo.Shortcode = shortcodeState.Value.TryGetProperty("shortcode", out JsonElement shortcode) ? shortcode.GetString() : null; + if (!shortcodeState.HasValue) return null; + roomInfo.Shortcode = shortcodeState.Value.TryGetProperty("shortcode", out var shortcode) ? shortcode.GetString() : null; - if (roomInfo.Shortcode != null) - { + if (roomInfo.Shortcode != null) { roomInfo.Name = await r.GetNameAsync(); return roomInfo; } return null; } - finally - - { + finally { checkedRoomCount++; StateHasChanged(); semaphore.Release(); } } - public struct PolicyRoomInfo - - { + public struct PolicyRoomInfo { public string RoomId { get; set; } @@ -118,4 +101,5 @@ else public string? Name { get; set; } } - } \ No newline at end of file + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor index 5daa97c..9b0bb88 100644 --- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor +++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor @@ -3,12 +3,10 @@ @inject NavigationManager NavigationManager <h3>Room manager</h3> <hr/> -@if (Rooms.Count == 0) -{ +@if (Rooms.Count == 0) { <p>You are not in any rooms!</p> } -else -{ +else { <p>You are in @Rooms.Count rooms and @Spaces.Count spaces</p> <p> <a href="/RoomManagerCreateRoom">Create room</a> @@ -16,8 +14,7 @@ else <details open> <summary>Space List</summary> - @foreach (var room in Spaces) - { + @foreach (var room in Spaces) { <a style="color: unset; text-decoration: unset;" href="/RoomManager/Space/@room.RoomId.Replace('.', '~')"> <RoomListItem Room="@room" ShowOwnProfile="false"></RoomListItem> </a> @@ -25,8 +22,7 @@ else </details> <details open> <summary>Room List</summary> - @foreach (var room in Rooms) - { + @foreach (var room in Rooms) { <a style="color: unset; text-decoration: unset;" href="/RoomManager/Room/@room.RoomId.Replace('.', '~')"> <RoomListItem Room="@room" ShowOwnProfile="true"></RoomListItem> </a> @@ -41,15 +37,13 @@ else public List<Room> Rooms { get; set; } = new(); public List<Room> Spaces { get; set; } = new(); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { Console.WriteLine("Initializing room manager"); await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); Console.WriteLine("Loaded from local storage"); await base.OnInitializedAsync(); Console.WriteLine("Initialized base"); - if (RuntimeCache.CurrentHomeServer == null) - { + if (RuntimeCache.CurrentHomeServer == null) { NavigationManager.NavigateTo("/Login"); return; } @@ -59,8 +53,7 @@ else Console.WriteLine($"Got {_rooms.Count} rooms"); var semaphore = new SemaphoreSlim(10); var tasks = new List<Task<Room?>>(); - foreach (var room in _rooms) - { + foreach (var room in _rooms) { tasks.Add(CheckIfSpace(room, semaphore)); } await Task.WhenAll(tasks); @@ -68,45 +61,36 @@ else Console.WriteLine("Fetched joined rooms!"); } - private async Task<Room?> CheckIfSpace(Room room, SemaphoreSlim semaphore) - { + private async Task<Room?> CheckIfSpace(Room room, SemaphoreSlim semaphore) { await semaphore.WaitAsync(); - // Console.WriteLine($"Checking if {room.RoomId} is a space"); - try - { + // Console.WriteLine($"Checking if {room.RoomId} is a space"); + try { var state = await room.GetStateAsync<CreateEvent>("m.room.create"); - if (state != null) - { + if (state != null) { //Console.WriteLine(state.Value.ToJson()); - if (state.Type != null) - { - if (state.Type == "m.space") - { + if (state.Type != null) { + if (state.Type == "m.space") { Console.WriteLine($"Room {room.RoomId} is a space!"); Spaces.Add(room); StateHasChanged(); return room; } - else - { + else { Console.WriteLine($"Encountered unknown room type {state.Type}"); } } - else - { + else { Rooms.Add(room); //this is fine, apprently... // Console.WriteLine($"Room {room.RoomId} has no Content.type in m.room.create!"); } } } - catch (Exception e) - { + catch (Exception e) { Console.WriteLine(e); return null; } - finally - { + finally { semaphore.Release(); } return null; diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor index d561eb0..5cfda77 100644 --- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor +++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor @@ -1,12 +1,13 @@ @page "/RoomManagerCreateRoom" -@using System.Text.Json @using MatrixRoomUtils.Core.Extensions @using MatrixRoomUtils.Core.Responses -@using MatrixRoomUtils.Web.Shared.SimpleComponents -@using System.Reflection -@using System.Runtime.Intrinsics.X86 +@using System.Text.Json @using System.Text.Json.Serialization +@using System.Reflection @using MatrixRoomUtils.Web.Classes.RoomCreationTemplates +@* ReSharper disable once RedundantUsingDirective - Must not remove this, Rider marks this as "unused" when it's not *@ +@using MatrixRoomUtils.Web.Shared.SimpleComponents + <h3>Room Manager - Create Room</h3> @* <pre Contenteditable="true" @onkeypress="@JsonChanged" ="JsonString">@JsonString</pre> *@ @@ -20,15 +21,13 @@ <td style="padding-bottom: 16px;">Preset:</td> <td style="padding-bottom: 16px;"> <InputSelect @bind-Value="@RoomPreset"> - @foreach (var createRoomRequest in Presets) - { + @foreach (var createRoomRequest in Presets) { <option value="@createRoomRequest.Key">@createRoomRequest.Key</option> } </InputSelect> </td> </tr> - @if (creationEvent != null) - { + @if (creationEvent != null) { <tr> <td>Room name:</td> <td> @@ -89,8 +88,7 @@ <td>Permissions:</td> <details> <summary>@creationEvent.PowerLevelContentOverride.Users.Count members</summary> - @foreach (var user in creationEvent.PowerLevelContentOverride.Events.Keys) - { + @foreach (var user in creationEvent.PowerLevelContentOverride.Events.Keys) { var _event = user; <tr> <td><FancyTextBox Formatter="@GetPermissionFriendlyName" Value="@_event" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Events.ChangeKey(_event, val); }"></FancyTextBox>:</td> @@ -99,8 +97,7 @@ </td> </tr> } - @foreach (var user in creationEvent.PowerLevelContentOverride.Users.Keys) - { + @foreach (var user in creationEvent.PowerLevelContentOverride.Users.Keys) { var _user = user; <tr> <td><FancyTextBox Value="@_user" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Users.ChangeKey(_user, val); creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); }"></FancyTextBox>:</td> @@ -131,8 +128,7 @@ <details> <summary>@creationEvent.InitialState.Count(x => x.Type == "m.room.member") members</summary> <button @onclick="() => { RuntimeCache.LoginSessions.Select(x => x.Value.LoginResponse.UserId).ToList().ForEach(InviteMember); }">Invite all logged in accounts</button> - @foreach (var member in creationEvent.InitialState.Where(x => x.Type == "m.room.member" && x.StateKey != RuntimeCache.CurrentHomeServer.UserId)) - { + @foreach (var member in creationEvent.InitialState.Where(x => x.Type == "m.room.member" && x.StateKey != RuntimeCache.CurrentHomeServer.UserId)) { <UserListItem UserId="@member.StateKey"></UserListItem> } </details> @@ -154,13 +150,11 @@ <summary>@creationEvent.InitialState.Count(x => !ImplementedStates.Contains(x.Type)) custom states</summary> <table> - @foreach (var initialState in creationEvent.InitialState.Where(x => !ImplementedStates.Contains(x.Type))) - { + @foreach (var initialState in creationEvent.InitialState.Where(x => !ImplementedStates.Contains(x.Type))) { <tr> <td style="vertical-align: top;"> @(initialState.Type): - @if (!string.IsNullOrEmpty(initialState.StateKey)) - { + @if (!string.IsNullOrEmpty(initialState.StateKey)) { <br/> <span>(@initialState.StateKey)</span> } @@ -176,8 +170,7 @@ <details> <summary>@creationEvent.InitialState.Count initial states</summary> <table> - @foreach (var initialState in creationEvent.InitialState) - { + @foreach (var initialState in creationEvent.InitialState) { var _state = initialState; <tr> <td style="vertical-align: top;"> @@ -214,25 +207,21 @@ @code { - private string RoomPreset - { - get - { - if (Presets.ContainsValue(creationEvent)) - { + private string RoomPreset { + get { + if (Presets.ContainsValue(creationEvent)) { return Presets.First(x => x.Value == creationEvent).Key; } return "Not a preset"; } - set - { + set { creationEvent = Presets[value]; JsonChanged(); OverwriteWrappedPropertiesFromEvent(); creationEvent.PowerLevelContentOverride.Events = creationEvent.PowerLevelContentOverride.Events.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); guestAccessEvent = creationEvent["m.room.guest_access"].As<GuestAccessContent>().Content; - + Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}"); Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessContent>().ToJson()}"); creationEvent["m.room.guest_access"].As<GuestAccessContent>().Content.IsGuestAccessEnabled = true; @@ -251,21 +240,18 @@ private Dictionary<string, CreateRoomRequest> Presets { get; set; } = new(); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); //creationEvent = Presets["Default room"] = - foreach (var x in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(IRoomCreationTemplate))).ToList()) - { + foreach (var x in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(IRoomCreationTemplate))).ToList()) { Console.WriteLine($"Found room creation template in class: {x.FullName}"); var instance = (IRoomCreationTemplate)Activator.CreateInstance(x); Presets[instance.Name] = instance.CreateRoomRequest; } Presets = Presets.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); - if (!Presets.ContainsKey("Default")) - { + if (!Presets.ContainsKey("Default")) { Console.WriteLine($"No default room found in {Presets.Count} presets: {string.Join(", ", Presets.Keys)}"); } else RoomPreset = "Default"; @@ -273,30 +259,23 @@ await base.OnInitializedAsync(); } - private void JsonChanged() - { - Console.WriteLine(creationEvent.ToJson()); - } - + private void JsonChanged() => Console.WriteLine(creationEvent.ToJson()); //wrappers private List<string> ServerACLAllowRules { get; set; } = new(); private List<string> ServerACLDenyRules { get; set; } = new(); - private void OverwriteWrappedPropertiesFromEvent() - { + private void OverwriteWrappedPropertiesFromEvent() { Console.WriteLine("Overwriting wrapped properties from event"); ServerACLAllowRules = creationEvent.ServerACLs.Allow; ServerACLDenyRules = creationEvent.ServerACLs.Deny; } - private async Task OverwriteWrappedProperties() - { + private async Task OverwriteWrappedProperties() { Console.WriteLine("Overwriting wrapped properties"); Console.WriteLine($"Allow: {ServerACLAllowRules.Count}: {string.Join(", ", ServerACLAllowRules)}"); Console.WriteLine($"Deny: {ServerACLDenyRules.Count}: {string.Join(", ", ServerACLDenyRules)}"); - creationEvent.ServerACLs = new() - { + creationEvent.ServerACLs = new ServerACL { Allow = ServerACLAllowRules, Deny = ServerACLDenyRules, AllowIpLiterals = creationEvent.ServerACLs.AllowIpLiterals @@ -305,16 +284,14 @@ StateHasChanged(); } - private async Task RoomIconFilePicked(InputFileChangeEventArgs obj) - { + private async Task RoomIconFilePicked(InputFileChangeEventArgs obj) { var res = await RuntimeCache.CurrentHomeServer.UploadFile(obj.File.Name, obj.File.OpenReadStream(), obj.File.ContentType); Console.WriteLine(res); creationEvent.RoomIcon = res; StateHasChanged(); } - private async Task CreateRoom() - { + private async Task CreateRoom() { Console.WriteLine("Create room"); Console.WriteLine(creationEvent.ToJson()); creationEvent.CreationContent.Add("rory.gay.created_using", "Rory&::MatrixRoomUtils (https://mru.rory.gay)"); @@ -323,22 +300,18 @@ // NavigationManager.NavigateTo($"/RoomManager/{id.RoomId.Replace('.','~')}"); } - private void InviteMember(string mxid) - { + private void InviteMember(string mxid) { if (!creationEvent.InitialState.Any(x => x.Type == "m.room.member" && x.StateKey == mxid) && RuntimeCache.CurrentHomeServer.UserId != mxid) - creationEvent.InitialState.Add(new() - { + creationEvent.InitialState.Add(new StateEvent { Type = "m.room.member", StateKey = mxid, - Content = new - { + Content = new { membership = "invite", reason = "Automatically invited at room creation time." } }); } - private string GetStateFriendlyName(string key) => key switch { "m.room.history_visibility" => "History visibility", "m.room.guest_access" => "Guest access", @@ -363,19 +336,14 @@ _ => key }; - public class GuestAccessContent - { + public class GuestAccessContent { [JsonPropertyName("guest_access")] public string GuestAccess { get; set; } - public bool IsGuestAccessEnabled - { + public bool IsGuestAccessEnabled { get => GuestAccess == "can_join"; set => GuestAccess = value ? "can_join" : "forbidden"; } } - - } - diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor index 1e7e065..c5e1569 100644 --- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor +++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor @@ -4,8 +4,7 @@ <h3>Room manager - Viewing Space</h3> <button onclick="@JoinAllRooms">Join all rooms</button> -@foreach (var room in Rooms) -{ +@foreach (var room in Rooms) { <RoomListItem Room="room" ShowOwnProfile="true"></RoomListItem> } @@ -13,8 +12,7 @@ <br/> <details style="background: #0002;"> <summary style="background: #fff1;">State list</summary> - @foreach (var stateEvent in States.OrderBy(x => x.StateKey).ThenBy(x => x.Type)) - { + @foreach (var stateEvent in States.OrderBy(x => x.StateKey).ThenBy(x => x.Type)) { <p>@stateEvent.StateKey/@stateEvent.Type:</p> <pre>@stateEvent.Content.ToJson()</pre> } @@ -24,61 +22,52 @@ [Parameter] public string RoomId { get; set; } = "invalid!!!!!!"; - + private Room? Room { get; set; } - + private StateEventResponse<object>[] States { get; set; } = Array.Empty<StateEventResponse<object>>(); - private List<Room> Rooms { get; set; } = new(); - private List<string> ServersInSpace { get; set; } = new(); - - protected override async Task OnInitializedAsync() - { + private List<Room> Rooms { get; } = new(); + private List<string> ServersInSpace { get; } = new(); + + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); Room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId.Replace('~', '.')); var state = await Room.GetStateAsync(""); - if (state != null) - { - // Console.WriteLine(state.Value.ToJson()); + if (state != null) { + // Console.WriteLine(state.Value.ToJson()); States = state.Value.Deserialize<StateEventResponse<object>[]>()!; - - foreach (var stateEvent in States) - { - if (stateEvent.Type == "m.space.child") - { - // if (stateEvent.Content.ToJson().Length < 5) return; + + foreach (var stateEvent in States) { + if (stateEvent.Type == "m.space.child") { + // if (stateEvent.Content.ToJson().Length < 5) return; var roomId = stateEvent.StateKey; var room = await RuntimeCache.CurrentHomeServer.GetRoom(roomId); - if (room != null) - { + if (room != null) { Rooms.Add(room); } } - else if (stateEvent.Type == "m.room.member") - { + else if (stateEvent.Type == "m.room.member") { var serverName = stateEvent.StateKey.Split(':').Last(); - if (!ServersInSpace.Contains(serverName)) - { + if (!ServersInSpace.Contains(serverName)) { ServersInSpace.Add(serverName); } } } - - // if(state.Value.TryGetProperty("Type", out var Type)) - // { - // } - // else - // { - // //this is fine, apprently... - // //Console.WriteLine($"Room {room.RoomId} has no Content.Type in m.room.create!"); - // } + + // if(state.Value.TryGetProperty("Type", out var Type)) + // { + // } + // else + // { + // //this is fine, apprently... + // //Console.WriteLine($"Room {room.RoomId} has no Content.Type in m.room.create!"); + // } } await base.OnInitializedAsync(); } - - private async Task JoinAllRooms() - { - foreach (var room in Rooms) - { + + private async Task JoinAllRooms() { + foreach (var room in Rooms) { room.JoinAsync(ServersInSpace.ToArray()); } } diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor index a8a7fc2..2db7cab 100644 --- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor +++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor @@ -1,12 +1,10 @@ @page "/RoomManager/Timeline/{RoomId}" @using MatrixRoomUtils.Web.Shared.TimelineComponents -@using MatrixRoomUtils.Core.Extensions <h3>RoomManagerTimeline</h3> <hr/> <p>Loaded @Events.Count events...</p> -@foreach (var evt in Events) -{ +@foreach (var evt in Events) { <div type="@evt.Type" key="@evt.StateKey" itemid="@evt.EventId"> <DynamicComponent Type="@ComponentType(evt)" Parameters="@(new Dictionary<string, object> { { "Event", evt }, { "Events", Events } })"></DynamicComponent> </div> @@ -17,18 +15,16 @@ [Parameter] public string RoomId { get; set; } = "invalid!!!!!!"; - private List<MessagesResponse> Messages { get; set; } = new(); - private List<StateEventResponse> Events { get; set; } = new(); + private List<MessagesResponse> Messages { get; } = new(); + private List<StateEventResponse> Events { get; } = new(); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); RoomId = RoomId.Replace('~', '.'); Console.WriteLine("RoomId: " + RoomId); var room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId); MessagesResponse? msgs = null; - do - { + do { msgs = await room.GetMessagesAsync(limit: 250, from: msgs?.End, dir: "b"); Messages.Add(msgs); Console.WriteLine($"Got {msgs.Chunk.Count} messages"); @@ -37,13 +33,11 @@ StateHasChanged(); } while (msgs.End != null); - await base.OnInitializedAsync(); } private StateEventResponse GetProfileEventBefore(StateEventResponse Event) => Events.TakeWhile(x => x != Event).Last(e => e.Type == "m.room.member" && e.StateKey == Event.Sender); - private Type ComponentType(StateEventResponse Event) => Event.Type switch { "m.room.message" => typeof(TimelineMessageItem), "m.room.member" => typeof(TimelineMemberItem), diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor index 3037dcc..74f4f92 100644 --- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor +++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor @@ -12,8 +12,7 @@ <br/> <InputSelect @bind-Value="shownStateKey"> <option value="">-- State key --</option> - @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != "").Select(x => x.StateKey).Distinct().OrderBy(x => x)) - { + @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != "").Select(x => x.StateKey).Distinct().OrderBy(x => x)) { <option value="@stateEvent">@stateEvent</option> Console.WriteLine(stateEvent); } @@ -21,8 +20,7 @@ <br/> <InputSelect @bind-Value="shownType"> <option value="">-- Type --</option> - @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != shownStateKey).Select(x => x.Type).Distinct().OrderBy(x => x)) - { + @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey != shownStateKey).Select(x => x.Type).Distinct().OrderBy(x => x)) { <option value="@stateEvent">@stateEvent</option> } </InputSelect> @@ -45,12 +43,10 @@ public List<StateEventResponse> Events { get; set; } = new(); public string status = ""; - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeCache.CurrentHomeServer != null) - { + if (RuntimeCache.CurrentHomeServer != null) { NavigationManager.NavigateTo("/Login"); return; } @@ -61,34 +57,29 @@ private DateTime _lastUpdate = DateTime.Now; - private async Task LoadStatesAsync() - { - int StateLoaded = 0; + private async Task LoadStatesAsync() { + var StateLoaded = 0; using var client = new HttpClient(); - //TODO: can this be improved? + //TODO: can this be improved? client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken); var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state"); // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json"); //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>(); var _data = await response.Content.ReadAsStreamAsync(); var __events = JsonSerializer.DeserializeAsyncEnumerable<StateEventResponse>(_data); - await foreach (var _ev in __events) - { - var e = new StateEventResponse() - { + await foreach (var _ev in __events) { + var e = new StateEventResponse { Type = _ev.Type, StateKey = _ev.StateKey, OriginServerTs = _ev.OriginServerTs, Content = _ev.Content }; Events.Add(e); - if (string.IsNullOrEmpty(e.StateKey)) - { + if (string.IsNullOrEmpty(e.StateKey)) { FilteredEvents.Add(e); } StateLoaded++; - if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) - { + if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) { _lastUpdate = DateTime.Now; status = $"Loaded {StateLoaded} state events"; StateHasChanged(); @@ -99,8 +90,7 @@ StateHasChanged(); } - private async Task RebuildFilteredData() - { + private async Task RebuildFilteredData() { status = "Rebuilding filtered data..."; StateHasChanged(); await Task.Delay(1); @@ -112,16 +102,14 @@ StateHasChanged(); await Task.Delay(1); FilteredEvents = _FilteredEvents; - - if(_shownType != null) + + if (_shownType != null) shownEventJson = _FilteredEvents.Where(x => x.Type == _shownType).First().Content.ToJson(indent: true, ignoreNull: true); - + StateHasChanged(); } - - public struct PreRenderedStateEvent - { + public struct PreRenderedStateEvent { public string content { get; set; } public long origin_server_ts { get; set; } public string state_key { get; set; } @@ -132,11 +120,9 @@ // public string ReplacesState { get; set; } } - public bool ShowMembershipEvents - { + public bool ShowMembershipEvents { get => _showMembershipEvents; - set - { + set { _showMembershipEvents = value; RebuildFilteredData(); } @@ -146,21 +132,17 @@ private string _shownStateKey; private string _shownType; - private string shownStateKey - { + private string shownStateKey { get => _shownStateKey; - set - { + set { _shownStateKey = value; RebuildFilteredData(); } } - private string shownType - { + private string shownType { get => _shownType; - set - { + set { _shownType = value; RebuildFilteredData(); } diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor index c654b13..82b5d75 100644 --- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor +++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor @@ -3,16 +3,15 @@ @inject NavigationManager NavigationManager <h3>Room state viewer - Room list</h3> <hr/> -@if (Rooms.Count == 0) -{ +@if (Rooms.Count == 0) { <p>You are not in any rooms!</p> @* <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> *@ } -else -{ - @foreach (var room in Rooms) - { - <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.','~')"><RoomListItem RoomId="@room"></RoomListItem></a> +else { + @foreach (var room in Rooms) { + <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.', '~')"> + <RoomListItem RoomId="@room"></RoomListItem> + </a> } <div style="margin-bottom: 4em;"></div> } @@ -21,16 +20,16 @@ else @code { public List<string> Rooms { get; set; } = new(); - protected override async Task OnInitializedAsync() - { + + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeCache.CurrentHomeServer == null) - { + if (RuntimeCache.CurrentHomeServer == null) { NavigationManager.NavigateTo("/Login"); return; } - Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x=>x.RoomId).ToList(); + Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x => x.RoomId).ToList(); Console.WriteLine("Fetched joined rooms!"); } -} \ No newline at end of file + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor index c7f9f3c..bfd4d10 100644 --- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor +++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor @@ -1,7 +1,7 @@ @page "/RoomStateViewer/{RoomId}" +@using MatrixRoomUtils.Core.Extensions @using System.Net.Http.Headers @using System.Text.Json -@using MatrixRoomUtils.Core.Extensions @inject ILocalStorageService LocalStorage @inject NavigationManager NavigationManager <h3>Room state viewer - Viewing @RoomId</h3> @@ -19,8 +19,7 @@ </tr> </thead> <tbody> - @foreach (var stateEvent in FilteredEvents.Where(x => x.state_key == "").OrderBy(x => x.origin_server_ts)) - { + @foreach (var stateEvent in FilteredEvents.Where(x => x.state_key == "").OrderBy(x => x.origin_server_ts)) { <tr> <td>@stateEvent.type</td> <td style="max-width: fit-Content;"> @@ -31,8 +30,7 @@ </tbody> </table> -@foreach (var group in FilteredEvents.GroupBy(x => x.state_key).OrderBy(x => x.Key).Where(x => x.Key != "")) -{ +@foreach (var group in FilteredEvents.GroupBy(x => x.state_key).OrderBy(x => x.Key).Where(x => x.Key != "")) { <details> <summary>@group.Key</summary> <table class="table table-striped table-hover" style="width: fit-Content;"> @@ -43,8 +41,7 @@ </tr> </thead> <tbody> - @foreach (var stateEvent in group.OrderBy(x => x.origin_server_ts)) - { + @foreach (var stateEvent in group.OrderBy(x => x.origin_server_ts)) { <tr> <td>@stateEvent.type</td> <td style="max-width: fit-Content;"> @@ -72,12 +69,10 @@ public List<PreRenderedStateEvent> Events { get; set; } = new(); public string status = ""; - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - if (RuntimeCache.CurrentHomeServer == null) - { + if (RuntimeCache.CurrentHomeServer == null) { NavigationManager.NavigateTo("/Login"); return; } @@ -85,56 +80,50 @@ await LoadStatesAsync(); Console.WriteLine("Policy list editor initialized!"); } + private DateTime _lastUpdate = DateTime.Now; - private async Task LoadStatesAsync() - { - int StateLoaded = 0; - //TODO: can we improve this? + private async Task LoadStatesAsync() { + var StateLoaded = 0; + //TODO: can we improve this? using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken); - var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state"); - // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json"); + var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/r0/rooms/{RoomId}/state"); + // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json"); //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>(); var _data = await response.Content.ReadAsStreamAsync(); var __events = JsonSerializer.DeserializeAsyncEnumerable<StateEventStruct>(_data); - await foreach (var _ev in __events) - { - var e = new PreRenderedStateEvent() - { + await foreach (var _ev in __events) { + var e = new PreRenderedStateEvent { type = _ev.type, state_key = _ev.state_key, origin_server_ts = _ev.origin_server_ts, - content = _ev.content.ToJson(indent: true, ignoreNull: true), + content = _ev.content.ToJson(true, true) }; Events.Add(e); - if (string.IsNullOrEmpty(e.state_key)) - { + if (string.IsNullOrEmpty(e.state_key)) { FilteredEvents.Add(e); } StateLoaded++; - if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) - { + if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) { _lastUpdate = DateTime.Now; status = $"Loaded {StateLoaded} state events"; StateHasChanged(); await Task.Delay(0); } - } StateHasChanged(); } - private async Task RebuildFilteredData() - { + private async Task RebuildFilteredData() { status = "Rebuilding filtered data..."; StateHasChanged(); await Task.Delay(1); var _FilteredEvents = Events; if (!ShowMembershipEvents) _FilteredEvents = _FilteredEvents.Where(x => x.type != "m.room.member").ToList(); - + status = "Done, rerendering!"; StateHasChanged(); await Task.Delay(1); @@ -142,9 +131,7 @@ StateHasChanged(); } - - public struct PreRenderedStateEvent - { + public struct PreRenderedStateEvent { public string content { get; set; } public long origin_server_ts { get; set; } public string state_key { get; set; } @@ -155,11 +142,9 @@ // public string ReplacesState { get; set; } } - public bool ShowMembershipEvents - { + public bool ShowMembershipEvents { get => _showMembershipEvents; - set - { + set { _showMembershipEvents = value; RebuildFilteredData(); } diff --git a/MatrixRoomUtils.Web/Program.cs b/MatrixRoomUtils.Web/Program.cs index 15c18f7..164f746 100644 --- a/MatrixRoomUtils.Web/Program.cs +++ b/MatrixRoomUtils.Web/Program.cs @@ -1,17 +1,16 @@ using System.Text.Json; using System.Text.Json.Serialization; using Blazored.LocalStorage; +using MatrixRoomUtils.Web; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using MatrixRoomUtils.Web; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); -builder.Services.AddBlazoredLocalStorage(config => -{ +builder.Services.AddBlazoredLocalStorage(config => { config.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; config.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; config.JsonSerializerOptions.IgnoreReadOnlyProperties = true; diff --git a/MatrixRoomUtils.Web/Shared/EditablePre.razor b/MatrixRoomUtils.Web/Shared/EditablePre.razor index 01bea0d..e759015 100644 --- a/MatrixRoomUtils.Web/Shared/EditablePre.razor +++ b/MatrixRoomUtils.Web/Shared/EditablePre.razor @@ -1,8 +1,9 @@ @inherits InputBase<string> <pre id="@Id" class="@CssClass" @onkeyup="Callback" contenteditable="true">@CurrentValue</pre> + @code { - protected override bool TryParseValueFromString(string? value, out string result, out string? validationErrorMessage) - { + + protected override bool TryParseValueFromString(string? value, out string result, out string? validationErrorMessage) { result = value; validationErrorMessage = null; return true; @@ -10,9 +11,6 @@ public object Id { get; set; } - private async Task Callback() - { - Console.WriteLine("beep"); - } + private async Task Callback() => Console.WriteLine("beep"); } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor index 03a7145..1fc70f2 100644 --- a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor +++ b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor @@ -1,10 +1,4 @@ -@using MatrixRoomUtils.Web.Classes -@using System.Text.Json -@using Blazored.LocalStorage -@using MatrixRoomUtils.Core @using MatrixRoomUtils.Core.Extensions -@using Index = MatrixRoomUtils.Web.Pages.Index -@using System.ComponentModel.DataAnnotations @inject ILocalStorageService LocalStorage @inject NavigationManager NavigationManager @@ -27,30 +21,33 @@ private string? _avatarUrl { get; set; } private int _roomCount { get; set; } = 0; - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { var hs = await new AuthenticatedHomeServer(User.LoginResponse.UserId, User.AccessToken, User.LoginResponse.HomeServer).Configure(); if (User.Profile.AvatarUrl != null && User.Profile.AvatarUrl != "") _avatarUrl = hs.ResolveMediaUri(User.Profile.AvatarUrl); else _avatarUrl = "https://api.dicebear.com/6.x/identicon/svg?seed=" + User.LoginResponse.UserId; - _roomCount = (await hs.GetJoinedRooms()).Count; + try { + _roomCount = (await hs.GetJoinedRooms()).Count; + } + catch { + _roomCount = -1; + } await base.OnInitializedAsync(); } - private async Task RemoveUser() - { + private async Task RemoveUser() { Console.WriteLine(User.ToJson()); RuntimeCache.LoginSessions.Remove(User.AccessToken); StateHasChanged(); } - private async Task SetCurrent() - { + private async Task SetCurrent() { RuntimeCache.LastUsedToken = User.AccessToken; //RuntimeCache.CurrentHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(LocalStorageWrapper.LoginSessions[Token].LoginResponse.HomeServer); await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); await LocalStorageWrapper.InitialiseRuntimeVariables(LocalStorage); StateHasChanged(); } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor index 56131c8..9833c62 100644 --- a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor +++ b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor @@ -4,8 +4,7 @@ <span style="position: relative; top: -5px;">@ProfileName</span> <div style="display: inline-block;"> - @if (ChildContent != null) - { + @if (ChildContent != null) { @ChildContent } </div> @@ -25,15 +24,13 @@ [Parameter] public string? ProfileAvatar { get; set; } = null; - + [Parameter] public string? ProfileName { get; set; } = null; - private static SemaphoreSlim _semaphoreSlim = new(128); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); @@ -41,19 +38,14 @@ var hs = await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure(); - if (User == null) - { - if (UserId == null) - { + if (User == null) { + if (UserId == null) { throw new ArgumentNullException(nameof(UserId)); } User = await hs.GetProfile(UserId); } - else - { - // UserId = User.; - } - + + // UserId = User.; ProfileAvatar ??= RuntimeCache.CurrentHomeServer.ResolveMediaUri(User.AvatarUrl); ProfileName ??= User.DisplayName; diff --git a/MatrixRoomUtils.Web/Shared/LogView.razor b/MatrixRoomUtils.Web/Shared/LogView.razor index 80fd355..2f83cb2 100644 --- a/MatrixRoomUtils.Web/Shared/LogView.razor +++ b/MatrixRoomUtils.Web/Shared/LogView.razor @@ -1,6 +1,5 @@ @using System.Text -@if (LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers) -{ +@if (LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers) { <u>Logs</u> <br/> <pre> @@ -10,11 +9,10 @@ @code { StringBuilder _stringBuilder = new(); - protected override async Task OnInitializedAsync() - { + + protected override async Task OnInitializedAsync() { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); - if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) - { + if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) { Console.WriteLine("Console logging disabled!"); var _sw = new StringWriter(); Console.SetOut(_sw); @@ -22,19 +20,16 @@ return; } if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers) return; - //intecept stdout with textwriter to get logs + //intecept stdout with textwriter to get logs var sw = new StringWriter(_stringBuilder); Console.SetOut(sw); Console.SetError(sw); - //keep updated - int length = 0; - Task.Run(async () => - { - while (true) - { + //keep updated + var length = 0; + Task.Run(async () => { + while (true) { await Task.Delay(100); - if (_stringBuilder.Length != length) - { + if (_stringBuilder.Length != length) { StateHasChanged(); length = _stringBuilder.Length; } @@ -43,4 +38,5 @@ }); await base.OnInitializedAsync(); } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/MainLayout.razor b/MatrixRoomUtils.Web/Shared/MainLayout.razor index cdb1205..317f9e6 100644 --- a/MatrixRoomUtils.Web/Shared/MainLayout.razor +++ b/MatrixRoomUtils.Web/Shared/MainLayout.razor @@ -11,8 +11,7 @@ <PortableDevTools></PortableDevTools> <a href="https://git.rory.gay/MatrixRoomUtils.git/" target="_blank">Git</a> <a href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" target="_blank">Matrix</a> - @if (showDownload) - { + @if (showDownload) { <a href="/MRU.tar.xz" target="_blank">Download</a> } </div> @@ -24,24 +23,22 @@ </div> @code { - private bool showDownload { get; set; } = false; + private bool showDownload { get; set; } - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { using var hc = new HttpClient(); - var hr = await hc.SendAsync(new(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri)); + var hr = await hc.SendAsync(new HttpRequestMessage(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri)); showDownload = hr.StatusCode == HttpStatusCode.OK; await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); - if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) - { + if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) { Console.WriteLine("Console logging disabled!"); var sw = new StringWriter(); Console.SetOut(sw); Console.SetError(sw); } - - await base.OnInitializedAsync(); + await base.OnInitializedAsync(); } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/MainLayout.razor.css b/MatrixRoomUtils.Web/Shared/MainLayout.razor.css index c865427..01a5066 100644 --- a/MatrixRoomUtils.Web/Shared/MainLayout.razor.css +++ b/MatrixRoomUtils.Web/Shared/MainLayout.razor.css @@ -21,20 +21,20 @@ main { align-items: center; } - .top-row ::deep a, .top-row ::deep .btn-link { - white-space: nowrap; - margin-left: 1.5rem; - text-decoration: none; - } +.top-row ::deep a, .top-row ::deep .btn-link { + white-space: nowrap; + margin-left: 1.5rem; + text-decoration: none; +} - .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { - text-decoration: underline; - } +.top-row ::deep a:hover, .top-row ::deep .btn-link:hover { + text-decoration: underline; +} - .top-row ::deep a:first-child { - overflow: hidden; - text-overflow: ellipsis; - } +.top-row ::deep a:first-child { + overflow: hidden; + text-overflow: ellipsis; +} @media (max-width: 640.98px) { .top-row:not(.auth) { diff --git a/MatrixRoomUtils.Web/Shared/NavMenu.razor b/MatrixRoomUtils.Web/Shared/NavMenu.razor index 44dd9df..9ddbd84 100644 --- a/MatrixRoomUtils.Web/Shared/NavMenu.razor +++ b/MatrixRoomUtils.Web/Shared/NavMenu.razor @@ -61,6 +61,13 @@ @* <span class="oi oi-plus" aria-hidden="true"></span> Media locator *@ @* </NavLink> *@ @* </div> *@ + + <div class="nav-item px-3"> + <NavLink class="nav-link" href="HSAdmin"> + <span class="oi oi-plus" aria-hidden="true"></span> HS Admin + </NavLink> + </div> + <div class="nav-item px-3"> <h5 style="margin-left: 1em;">MRU</h5> <hr style="margin-bottom: 0em;"/> @@ -78,9 +85,6 @@ private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; - private void ToggleNavMenu() - { - collapseNavMenu = !collapseNavMenu; - } + private void ToggleNavMenu() => collapseNavMenu = !collapseNavMenu; } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/NavMenu.razor.css b/MatrixRoomUtils.Web/Shared/NavMenu.razor.css index 604b7a1..447f2df 100644 --- a/MatrixRoomUtils.Web/Shared/NavMenu.razor.css +++ b/MatrixRoomUtils.Web/Shared/NavMenu.razor.css @@ -4,7 +4,7 @@ .top-row { height: 3.5rem; - background-color: rgba(0,0,0,0.4); + background-color: rgba(0, 0, 0, 0.4); } .navbar-brand { @@ -23,30 +23,30 @@ padding-bottom: 0.5rem; } - .nav-item:first-of-type { - padding-top: 1rem; - } +.nav-item:first-of-type { + padding-top: 1rem; +} - .nav-item:last-of-type { - padding-bottom: 1rem; - } +.nav-item:last-of-type { + padding-bottom: 1rem; +} - .nav-item ::deep a { - color: #d7d7d7; - border-radius: 4px; - height: 3rem; - display: flex; - align-items: center; - line-height: 3rem; - } +.nav-item ::deep a { + color: #d7d7d7; + border-radius: 4px; + height: 3rem; + display: flex; + align-items: center; + line-height: 3rem; +} .nav-item ::deep a.active { - background-color: rgba(255,255,255,0.25); + background-color: rgba(255, 255, 255, 0.25); color: white; } .nav-item ::deep a:hover { - background-color: rgba(255,255,255,0.1); + background-color: rgba(255, 255, 255, 0.1); color: white; } @@ -59,7 +59,7 @@ /* Never collapse the sidebar for wide screens */ display: block; } - + .nav-scrollable { /* Allow sidebar to scroll for tall menus */ height: calc(100vh - 3.5rem); diff --git a/MatrixRoomUtils.Web/Shared/PortableDevTools.razor b/MatrixRoomUtils.Web/Shared/PortableDevTools.razor index 84e7791..ffd7082 100644 --- a/MatrixRoomUtils.Web/Shared/PortableDevTools.razor +++ b/MatrixRoomUtils.Web/Shared/PortableDevTools.razor @@ -1,9 +1,7 @@ - -@if (Enabled) -{ +@if (Enabled) { <a href="/DevOptions">Portable devtools (enabled)</a> <div id="PortableDevTools" style="position: fixed; bottom: 0; right: 0; min-width: 200px; min-height: 100px; background: #0002;" draggable> - <p>Cache size: @RuntimeCache.GenericResponseCache.Sum(x=>x.Value.Cache.Count)</p> + <p>Cache size: @RuntimeCache.GenericResponseCache.Sum(x => x.Value.Cache.Count)</p> </div> } else { @@ -13,19 +11,16 @@ else { @code { private bool Enabled { get; set; } = LocalStorageWrapper.Settings.DeveloperSettings.EnablePortableDevtools; - protected override async Task OnInitializedAsync() - { - // if(!RuntimeCache.WasLoaded) - // await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); - // StateHasChanged(); - Task.Run(async () => - { - while (true) - { + protected override async Task OnInitializedAsync() => + // if(!RuntimeCache.WasLoaded) + // await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + // StateHasChanged(); + Task.Run(async () => { + while (true) { await Task.Delay(100); Enabled = LocalStorageWrapper.Settings.DeveloperSettings.EnablePortableDevtools; StateHasChanged(); } }); - } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor b/MatrixRoomUtils.Web/Shared/RoomListItem.razor index fb28c3c..f58ab3a 100644 --- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor +++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor @@ -1,18 +1,15 @@ -@using MatrixRoomUtils.Core.Authentication -@using System.Text.Json @using MatrixRoomUtils.Core.Extensions +@using System.Text.Json <div class="roomListItem" style="background-color: #ffffff11; border-radius: 25px; margin: 8px; width: fit-Content; @(hasDangerousRoomVersion ? "border: red 4px solid;" : hasOldRoomVersion ? "border: #FF0 1px solid;" : "")"> - @if (ShowOwnProfile) - { - <img class="imageUnloaded @(string.IsNullOrWhiteSpace(profileAvatar) ? "" : "imageLoaded")" style="@(ChildContent != null ? "vertical-align: baseline;":"") width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@(profileAvatar ?? "/icon-192.png")" @onload="Callback"/> + @if (ShowOwnProfile) { + <img class="imageUnloaded @(string.IsNullOrWhiteSpace(profileAvatar) ? "" : "imageLoaded")" style="@(ChildContent != null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@(profileAvatar ?? "/icon-192.png")" @onload="Callback"/> <span style="vertical-align: middle; margin-right: 8px; border-radius: 75px; @(hasCustomProfileName ? "background-color: red;" : "")">@(profileName ?? "Loading...")</span> <span style="vertical-align: middle; padding-right: 8px; padding-left: 0px;">-></span> } - <img style="@(ChildContent != null ? "vertical-align: baseline;":"") width: 32px; height: 32px; border-radius: 50%;" src="@roomIcon"/> + <img style="@(ChildContent != null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%;" src="@roomIcon"/> <div style="display: inline-block;"> - <span style="vertical-align: middle; padding-right: 8px;">@roomName</span> - @if (ChildContent != null) - { + <span style="vertical-align: middle; padding-right: 8px;">@RoomName</span> + @if (ChildContent != null) { @ChildContent } </div> @@ -33,103 +30,86 @@ [Parameter] public bool ShowOwnProfile { get; set; } = false; - private string roomName { get; set; } = "Loading..."; + [Parameter] + public string? RoomName { get; set; } + private string? roomIcon { get; set; } = "/icon-192.png"; private string? profileAvatar { get; set; } private string? profileName { get; set; } private bool hasCustomProfileAvatar { get; set; } = false; private bool hasCustomProfileName { get; set; } = false; - + private bool hasOldRoomVersion { get; set; } = false; private bool hasDangerousRoomVersion { get; set; } = false; - - + private static SemaphoreSlim _semaphoreSlim = new(128); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); - + await _semaphoreSlim.WaitAsync(); var hs = RuntimeCache.CurrentHomeServer; //await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure(); - - if (Room == null) - { - if (RoomId == null) - { + + if (Room == null) { + if (RoomId == null) { throw new ArgumentNullException(nameof(RoomId)); } Room = await hs.GetRoom(RoomId); } - else - { + else { RoomId = Room.RoomId; } - roomName = await Room.GetNameAsync() ?? "Unnamed room: " + RoomId; + RoomName ??= await Room.GetNameAsync() ?? "Unnamed room: " + RoomId; var ce = await Room.GetCreateEventAsync(); - if (ce != null) - { - if (int.TryParse(ce.RoomVersion, out int rv) && rv < 10) - { + if (ce != null) { + if (int.TryParse(ce.RoomVersion, out var rv) && rv < 10) { hasOldRoomVersion = true; } - if (new[] { "1", "8" }.Contains(ce.RoomVersion)) - { + if (new[] { "1", "8" }.Contains(ce.RoomVersion)) { hasDangerousRoomVersion = true; - roomName = "Dangerous room: " + roomName; + RoomName = "Dangerous room: " + RoomName; } } - var state = await Room.GetStateAsync("m.room.avatar"); - if (state != null) - { - try - { + if (state != null) { + try { var url = state.Value.GetProperty("url").GetString(); - if (url != null) - { + if (url != null) { roomIcon = hs.ResolveMediaUri(url); Console.WriteLine($"Got avatar for room {RoomId}: {roomIcon} ({url})"); } } - catch (InvalidOperationException e) - { + catch (InvalidOperationException e) { Console.WriteLine($"Failed to get avatar for room {RoomId}: {e.Message}\n{state.Value.ToJson()}"); } } - if (ShowOwnProfile) - { - var profile = await hs.GetProfile(hs.UserId, debounce: true); + if (ShowOwnProfile) { + var profile = await hs.GetProfile(hs.UserId, true); var memberState = await Room.GetStateAsync("m.room.member", hs.UserId); - if (memberState.HasValue) - { + if (memberState.HasValue) { memberState.Value.TryGetProperty("avatar_url", out var _avatar); - if (_avatar.ValueKind == JsonValueKind.String) - { + if (_avatar.ValueKind == JsonValueKind.String) { hasCustomProfileAvatar = _avatar.GetString() != profile.AvatarUrl; profileAvatar = hs.ResolveMediaUri(_avatar.GetString()); } - else - { + else { profileAvatar = "/icon-192.png"; } memberState.Value.TryGetProperty("displayname", out var _name); - if (_name.ValueKind == JsonValueKind.String) - { + if (_name.ValueKind == JsonValueKind.String) { hasCustomProfileName = _name.GetString() != profile.DisplayName; profileName = _name.GetString(); // Console.WriteLine($"{profile.DisplayName} - {_name.GetString()}: {hasCustomProfileName}"); } - else - { + else { profileName = "Unnamed user"; } } @@ -139,9 +119,6 @@ await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } - private void Callback(ProgressEventArgs obj) - { - Console.WriteLine("prog: " + obj.ToJson(indent: false)); - } + private void Callback(ProgressEventArgs obj) => Console.WriteLine("prog: " + obj.ToJson(false)); } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css b/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css index 8b9a9f6..da22d38 100644 --- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css +++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor.css @@ -5,6 +5,6 @@ /*}*/ .imageLoaded { - opacity: 1; - scale: 1; - } \ No newline at end of file + opacity: 1; + scale: 1; +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor index 4d90c57..42a5f64 100644 --- a/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor +++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/DictionaryEditor.razor @@ -1,9 +1,8 @@ @using MatrixRoomUtils.Core.Extensions <table> - @foreach(var i in Items.Keys) - { + @foreach (var i in Items.Keys) { var key = i; - <input value="@Items[key]" @oninput="(obj) => inputChanged(obj, key)"> + <input value="@Items[key]" @oninput="obj => inputChanged(obj, key)"> <button @onclick="() => { Items.Remove(key); ItemsChanged.InvokeAsync(); }">Remove</button> <br/> } @@ -11,28 +10,26 @@ <button @onclick="() => { Items.Add(string.Empty, default); ItemsChanged.InvokeAsync(); }">Add</button> @code { - + [Parameter] public Dictionary<string, object> Items { get; set; } = new(); - [Parameter, EditorRequired] + [Parameter] + [EditorRequired] public EventCallback ItemsChanged { get; set; } [Parameter] - public Func<string,string>? KeyFormatter { get; set; } - + public Func<string, string>? KeyFormatter { get; set; } + [Parameter] public Action? OnFocusLost { get; set; } - - protected override Task OnInitializedAsync() - { + protected override Task OnInitializedAsync() { Console.WriteLine($"DictionaryEditor initialized with {Items.Count} items: {Items.ToJson()}"); return base.OnInitializedAsync(); } - private void inputChanged(ChangeEventArgs obj, string key) - { + private void inputChanged(ChangeEventArgs obj, string key) { Console.WriteLine($"StringListEditor inputChanged {key} {obj.Value}"); Items[key] = obj.Value.ToString(); ItemsChanged.InvokeAsync(); diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor index 702d41e..d17d0de 100644 --- a/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor +++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor @@ -1,35 +1,29 @@ @inject IJSRuntime JsRuntime -@if (isVisible) -{ +@if (isVisible) { <input autofocus type="@(IsPassword ? "password" : "text")" @bind="Value" @onfocusout="() => { isVisible = false; ValueChanged.InvokeAsync(Value); }" @ref="elementToFocus"/> } -else -{ - <span tabindex="0" style="border-bottom: #ccc solid 1px; height: 1.4em; display: inline-block; @(string.IsNullOrEmpty(Value) ? "min-width: 50px;" : "")" @onfocusin="() => isVisible = true">@(Formatter?.Invoke(Value) ?? (IsPassword ? string.Join("", Value.Select(x=>'*')) : Value))</span> +else { + <span tabindex="0" style="border-bottom: #ccc solid 1px; height: 1.4em; display: inline-block; @(string.IsNullOrEmpty(Value) ? "min-width: 50px;" : "")" @onfocusin="() => isVisible = true">@(Formatter?.Invoke(Value) ?? (IsPassword ? string.Join("", Value.Select(x => '*')) : Value))</span> } @code { [Parameter] public string Value { get; set; } - + [Parameter] public bool IsPassword { get; set; } = false; - + [Parameter] public EventCallback<string> ValueChanged { get; set; } - + [Parameter] public Func<string?, string>? Formatter { get; set; } - private bool isVisible { get; set; } = false; private ElementReference elementToFocus; - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await JsRuntime.InvokeVoidAsync("BlazorFocusElement", elementToFocus); - } + protected override async Task OnAfterRenderAsync(bool firstRender) => await JsRuntime.InvokeVoidAsync("BlazorFocusElement", elementToFocus); } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor index fe3a938..2bd6ed5 100644 --- a/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor +++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/StringListEditor.razor @@ -1,5 +1,4 @@ -@for (int i = 0; i < Items.Count; i++) -{ +@for (var i = 0; i < Items.Count; i++) { var self = i; <button @onclick="() => { Items.RemoveAt(self); ItemsChanged.InvokeAsync(); }">Remove</button> <FancyTextBox Value="@Items[self]" ValueChanged="@(obj => inputChanged(obj, self))"/> @@ -10,19 +9,18 @@ @code { [Parameter] - public List<string> Items { get; set; } = new List<string>(); + public List<string> Items { get; set; } = new(); - [Parameter, EditorRequired] + [Parameter] + [EditorRequired] public EventCallback ItemsChanged { get; set; } - protected override Task OnInitializedAsync() - { + protected override Task OnInitializedAsync() { Console.WriteLine($"StringListEditor initialized with {Items.Count} items: {string.Join(",", Items)}"); return base.OnInitializedAsync(); } - private void inputChanged(string obj, int i) - { + private void inputChanged(string obj, int i) { Console.WriteLine($"StringListEditor inputChanged {i} {obj}"); Items[i] = obj; ItemsChanged.InvokeAsync(); diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor index 49a363d..1a38e26 100644 --- a/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor +++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/ToggleSlider.razor @@ -59,12 +59,14 @@ </style> @code { + [Parameter] public RenderFragment? ChildContent { get; set; } - + [Parameter] public bool Value { get; set; } + [Parameter] public EventCallback<bool> ValueChanged { get; set; } - + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor index 3803d38..4fb5596 100644 --- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor @@ -1,33 +1,25 @@ @using MatrixRoomUtils.Core.Extensions -@if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "ban") -{ +@if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "ban") { <i>@Event.StateKey was banned</i> } -else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "invite") -{ +else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "invite") { <i>@Event.StateKey was invited</i> } -else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "join") -{ - @if (Event.ReplacesState != null) - { +else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "join") { + @if (Event.ReplacesState != null) { <i>@Event.StateKey changed their display name to @(Event.ContentAsJsonNode["displayname"]!.GetValue<string>())</i> } - else - { + else { <i><InlineUserItem UserId="@Event.StateKey"></InlineUserItem> joined</i> } } -else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "leave") -{ +else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "leave") { <i>@Event.StateKey left</i> } -else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "knock") -{ +else if (Event.ContentAsJsonNode["membership"]!.GetValue<string>() == "knock") { <i>@Event.StateKey knocked</i> } -else -{ +else { <i>@Event.StateKey has an unknown state:</i> <pre> @Event.ToJson() diff --git a/MatrixRoomUtils.Web/Shared/UserListItem.razor b/MatrixRoomUtils.Web/Shared/UserListItem.razor index d357b0d..43c71ab 100644 --- a/MatrixRoomUtils.Web/Shared/UserListItem.razor +++ b/MatrixRoomUtils.Web/Shared/UserListItem.razor @@ -4,8 +4,7 @@ <span style="vertical-align: middle; margin-right: 8px; border-radius: 75px;">@profileName</span> <div style="display: inline-block;"> - @if (ChildContent != null) - { + @if (ChildContent != null) { @ChildContent } </div> @@ -26,11 +25,9 @@ private string? profileAvatar { get; set; } = "/icon-192.png"; private string? profileName { get; set; } = "Loading..."; - private static SemaphoreSlim _semaphoreSlim = new(128); - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); @@ -38,19 +35,14 @@ var hs = await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure(); - if (User == null) - { - if (UserId == null) - { + if (User == null) { + if (UserId == null) { throw new ArgumentNullException(nameof(UserId)); } User = await hs.GetProfile(UserId); } - else - { - // UserId = User.; - } - + + // UserId = User.; profileAvatar = RuntimeCache.CurrentHomeServer.ResolveMediaUri(User.AvatarUrl); profileName = User.DisplayName; diff --git a/MatrixRoomUtils.Web/_Imports.razor b/MatrixRoomUtils.Web/_Imports.razor index a558b8f..837780e 100644 --- a/MatrixRoomUtils.Web/_Imports.razor +++ b/MatrixRoomUtils.Web/_Imports.razor @@ -17,14 +17,12 @@ @code { - - protected override async Task OnInitializedAsync() - { - if (!RuntimeCache.WasLoaded) - { + + protected override async Task OnInitializedAsync() { + if (!RuntimeCache.WasLoaded) { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); Console.WriteLine("Loaded from local storage"); StateHasChanged(); } } -} +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/wwwroot/css/app.css b/MatrixRoomUtils.Web/wwwroot/css/app.css index c6d71d1..245566a 100644 --- a/MatrixRoomUtils.Web/wwwroot/css/app.css +++ b/MatrixRoomUtils.Web/wwwroot/css/app.css @@ -15,7 +15,7 @@ html, body { border-bottom: none; } -.table, .table-striped>tbody>tr:nth-of-type(odd), .table-hover>tbody>tr:hover { +.table, .table-striped > tbody > tr:nth-of-type(odd), .table-hover > tbody > tr:hover { color: unset; } @@ -34,7 +34,7 @@ a, .btn-link { } .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { - box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; + box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; } .content { @@ -65,12 +65,12 @@ a, .btn-link { z-index: 1000; } - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } +#blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; +} .blazor-error-boundary { background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; @@ -78,9 +78,9 @@ a, .btn-link { color: white; } - .blazor-error-boundary::after { - content: "An error has occurred." - } +.blazor-error-boundary::after { + content: "An error has occurred." +} .loading-progress { position: relative; @@ -90,19 +90,19 @@ a, .btn-link { margin: 20vh auto 1rem auto; } - .loading-progress circle { - fill: none; - stroke: #e0e0e0; - stroke-width: 0.6rem; - transform-origin: 50% 50%; - transform: rotate(-90deg); - } +.loading-progress circle { + fill: none; + stroke: #e0e0e0; + stroke-width: 0.6rem; + transform-origin: 50% 50%; + transform: rotate(-90deg); +} - .loading-progress circle:last-child { - stroke: #1b6ec2; - stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; - transition: stroke-dasharray 0.05s ease-in-out; - } +.loading-progress circle:last-child { + stroke: #1b6ec2; + stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%; + transition: stroke-dasharray 0.05s ease-in-out; +} .loading-progress-text { position: absolute; @@ -111,6 +111,6 @@ a, .btn-link { inset: calc(20vh + 3.25rem) 0 auto 0.2rem; } - .loading-progress-text:after { - content: var(--blazor-load-percentage-text, "Loading"); - } +.loading-progress-text:after { + content: var(--blazor-load-percentage-text, "Loading"); +} diff --git a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md index e34bd86..3ee3279 100644 --- a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md +++ b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/README.md @@ -3,8 +3,6 @@ ### Open Iconic is the open source sibling of [Iconic](https://github.com/iconic/open-iconic). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](https://github.com/iconic/open-iconic) - - ## What's in Open Iconic? * 223 icons designed to be legible down to 8 pixels @@ -14,7 +12,6 @@ * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. - ## Getting Started #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](https://github.com/iconic/open-iconic) and [Reference](https://github.com/iconic/open-iconic) sections. @@ -33,7 +30,8 @@ We like SVGs and we think they're the way to display icons on the web. Since Ope Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. -Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `<svg>` *tag and a unique class name for each different icon in the* `<use>` *tag.* +Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `<svg>` *tag and a unique class name for +each different icon in the* `<use>` *tag.* ``` <svg class="icon"> @@ -62,17 +60,14 @@ To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.c #### Using Open Iconic's Icon Font... - ##### …with Bootstrap You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` - ``` <link href="/open-iconic/font/css/open-iconic-bootstrap.css" rel="stylesheet"> ``` - ``` <span class="oi oi-icon-name" title="icon name" aria-hidden="true"></span> ``` @@ -85,7 +80,6 @@ You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css <link href="/open-iconic/font/css/open-iconic-foundation.css" rel="stylesheet"> ``` - ``` <span class="fi-icon-name" title="icon name" aria-hidden="true"></span> ``` @@ -102,7 +96,6 @@ You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, <span class="oi" data-glyph="icon-name" title="icon name" aria-hidden="true"></span> ``` - ## License ### Icons diff --git a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg index 32b2c4e..9d1833e 100644 --- a/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg +++ b/MatrixRoomUtils.Web/wwwroot/css/open-iconic/font/fonts/open-iconic.svg @@ -4,540 +4,541 @@ 2014-7-1: Created. --> <svg xmlns="http://www.w3.org/2000/svg"> -<metadata> -Created by FontForge 20120731 at Tue Jul 1 20:39:22 2014 - By P.J. Onori -Created by P.J. Onori with FontForge 2.0 (http://fontforge.sf.net) -</metadata> -<defs> -<font id="open-iconic" horiz-adv-x="800" > - <font-face - font-family="Icons" - font-weight="400" - font-stretch="normal" - units-per-em="800" - panose-1="2 0 5 3 0 0 0 0 0 0" - ascent="800" - descent="0" - bbox="-0.5 -101 802 800.126" - underline-thickness="50" - underline-position="-100" - unicode-range="U+E000-E0DE" - /> - <missing-glyph /> - <glyph glyph-name="" unicode="" -d="M300 700h500v-700h-500v100h400v500h-400v100zM400 500l200 -150l-200 -150v100h-400v100h400v100z" /> - <glyph glyph-name="1" unicode="" -d="M300 700h500v-700h-500v100h400v500h-400v100zM200 500v-100h400v-100h-400v-100l-200 150z" /> - <glyph glyph-name="2" unicode="" -d="M350 700c193 0 350 -157 350 -350v-50h100l-200 -200l-200 200h100v50c0 138 -112 250 -250 250s-250 -112 -250 -250c0 193 157 350 350 350z" /> - <glyph glyph-name="3" unicode="" -d="M450 700c193 0 350 -157 350 -350c0 138 -112 250 -250 250s-250 -112 -250 -250v-50h100l-200 -200l-200 200h100v50c0 193 157 350 350 350z" /> - <glyph glyph-name="4" unicode="" -d="M0 700h800v-100h-800v100zM100 500h600v-100h-600v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z" /> - <glyph glyph-name="5" unicode="" -d="M0 700h800v-100h-800v100zM0 500h600v-100h-600v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z" /> - <glyph glyph-name="6" unicode="" -d="M0 700h800v-100h-800v100zM200 500h600v-100h-600v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z" /> - <glyph glyph-name="7" unicode="" -d="M400 700c75 0 146 -23 206 -59l-75 -225l-322 234c57 31 122 50 191 50zM125 588l191 -138l-310 -222c-4 24 -6 47 -6 72c0 114 49 215 125 288zM688 575c69 -72 112 -168 112 -275c0 -35 -8 -68 -16 -100h-218zM216 253l112 -347c-128 23 -232 109 -287 222zM372 100 -h372c-64 -109 -177 -185 -310 -197z" /> - <glyph glyph-name="8" unicode="" horiz-adv-x="600" -d="M200 800h100v-500h200l-247 -300l-253 300h200v500z" /> - <glyph glyph-name="9" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 700v-300h-200l300 -300l300 300h-200v300h-200z" /> - <glyph glyph-name="a" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300l300 -300v200h300v200h-300v200z" /> - <glyph glyph-name="b" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700v-200h-300v-200h300v-200l300 300z" /> - <glyph glyph-name="c" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300h200v-300h200v300h200z" /> - <glyph glyph-name="d" unicode="" -d="M300 600v-200h500v-100h-500v-200l-300 247z" /> - <glyph glyph-name="e" unicode="" -d="M500 600l300 -247l-300 -253v200h-500v100h500v200z" /> - <glyph glyph-name="f" unicode="" horiz-adv-x="600" -d="M200 800h200v-500h200l-297 -300l-303 300h200v500z" /> - <glyph glyph-name="10" unicode="" -d="M300 700v-200h500v-200h-500v-200l-300 297z" /> - <glyph glyph-name="11" unicode="" -d="M500 700l300 -297l-300 -303v200h-500v200h500v200z" /> - <glyph glyph-name="12" unicode="" horiz-adv-x="600" -d="M297 800l303 -300h-200v-500h-200v500h-200z" /> - <glyph glyph-name="13" unicode="" horiz-adv-x="600" -d="M247 800l253 -300h-200v-500h-100v500h-200z" /> - <glyph glyph-name="14" unicode="" -d="M400 800h100v-800h-100v800zM200 700h100v-600h-100v600zM600 600h100v-400h-100v400zM0 500h100v-200h-100v200z" /> - <glyph glyph-name="15" unicode="" -d="M116 600l72 -72c-54 -54 -88 -126 -88 -209s34 -159 88 -213l-72 -72c-72 72 -116 175 -116 285s44 209 116 281zM684 600c72 -72 116 -171 116 -281s-44 -213 -116 -285l-72 72c54 54 88 130 88 213s-34 155 -88 209zM259 460l69 -72c-18 -18 -28 -41 -28 -69 -s10 -54 28 -72l-69 -72c-36 36 -59 89 -59 144s23 105 59 141zM541 459c36 -36 59 -85 59 -140s-23 -108 -59 -144l-69 72c18 18 28 44 28 72s-10 51 -28 69z" /> - <glyph glyph-name="16" unicode="" horiz-adv-x="400" -d="M200 800c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200s90 200 200 200zM100 319c31 -11 65 -19 100 -19s68 8 100 19v-319l-100 100l-100 -100v319z" /> - <glyph glyph-name="17" unicode="" -d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300c0 -66 21 -126 56 -175l419 419c-49 35 -109 56 -175 56zM644 575l-419 -419c49 -35 109 -56 175 -56c166 0 300 134 300 300 -c0 66 -21 126 -56 175z" /> - <glyph glyph-name="18" unicode="" -d="M0 700h100v-600h700v-100h-800v700zM500 700h200v-500h-200v500zM200 500h200v-300h-200v300z" /> - <glyph glyph-name="19" unicode="" -d="M397 800c13 1 23 -4 34 -13c2 -2 214 -254 241 -287h128v-100h-100v-366c0 -18 -16 -34 -34 -34h-532c-18 0 -34 16 -34 34v366h-100v100h128l234 281c9 11 22 18 35 19zM400 672l-144 -172h288zM250 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50 -v100c0 28 -22 50 -50 50zM550 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50v100c0 28 -22 50 -50 50z" /> - <glyph glyph-name="1a" unicode="" -d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9zM100 600v-400h500v400h-500z" /> - <glyph glyph-name="1b" unicode="" -d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9z" /> - <glyph glyph-name="1c" unicode="" -d="M92 650c0 23 19 50 45 50h3h5h5h500c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-141c9 -17 120 -231 166 -309c16 -26 34 -61 34 -106c0 -39 -15 -77 -41 -103h-3c-26 -25 -62 -41 -100 -41h-512c-39 0 -77 15 -103 41s-41 64 -41 103c0 46 18 80 34 106 -c46 78 157 292 166 309v141h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51zM500 600h-200v-162l-6 -10s-63 -123 -119 -228h450c-56 105 -119 228 -119 228l-6 10v162z" /> - <glyph glyph-name="1d" unicode="" -d="M400 800c110 0 200 -90 200 -200c0 -104 52 -198 134 -266c41 -34 66 -82 66 -134h-800c0 52 25 100 66 134c82 68 134 162 134 266c0 110 90 200 200 200zM300 100h200c0 -55 -45 -100 -100 -100s-100 45 -100 100z" /> - <glyph glyph-name="1e" unicode="" horiz-adv-x="600" -d="M150 800h50l350 -250l-225 -147l225 -153l-350 -250h-50v250l-75 -75l-75 75l150 150l-150 150l75 75l75 -75v250zM250 650v-200l150 100zM250 350v-200l150 100z" /> - <glyph glyph-name="1f" unicode="" -d="M0 800h500c110 0 200 -90 200 -200c0 -47 -17 -91 -44 -125c85 -40 144 -125 144 -225c0 -138 -112 -250 -250 -250h-550v100c55 0 100 45 100 100v400c0 55 -45 100 -100 100v100zM300 700v-200h100c55 0 100 45 100 100s-45 100 -100 100h-100zM300 400v-300h150 -c83 0 150 67 150 150s-67 150 -150 150h-150z" /> - <glyph glyph-name="20" unicode="" horiz-adv-x="600" -d="M300 800v-300h200l-300 -500v300h-200z" /> - <glyph glyph-name="21" unicode="" -d="M100 800h300v-300l100 100l100 -100v300h50c28 0 50 -22 50 -50v-550h-550c-28 0 -50 -22 -50 -50s22 -50 50 -50h550v-100h-550c-83 0 -150 67 -150 150v550l3 19c8 39 39 70 78 78z" /> - <glyph glyph-name="22" unicode="" horiz-adv-x="400" -d="M0 800h400v-800l-200 200l-200 -200v800z" /> - <glyph glyph-name="23" unicode="" -d="M0 800h800v-100h-800v100zM0 600h300v-103h203v103h297v-591c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v591z" /> - <glyph glyph-name="24" unicode="" -d="M300 800h200c55 0 100 -45 100 -100v-100h191c6 0 9 -3 9 -9v-241c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v241c0 6 3 9 9 9h191v100c0 55 45 100 100 100zM300 700v-100h200v100h-200zM0 209c16 -6 32 -9 50 -9h700c18 0 34 3 50 9v-200c0 -6 -3 -9 -9 -9h-782 -c-6 0 -9 3 -9 9v200z" /> - <glyph glyph-name="25" unicode="" horiz-adv-x="600" -d="M300 800c58 0 110 -16 147 -53s53 -89 53 -147h-100c0 39 -11 61 -25 75s-36 25 -75 25c-35 0 -55 -10 -72 -31s-28 -55 -28 -94c0 -51 20 -107 28 -175h172v-100h-178c-14 -60 -49 -127 -113 -200h491v-100h-600v122l16 12c69 69 95 121 106 166h-122v100h125 -c-8 50 -25 106 -25 175c0 58 16 114 50 156c34 43 88 69 150 69z" /> - <glyph glyph-name="26" unicode="" -d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-700c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v700v2c0 20 15 42 34 48zM150 600c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50zM350 600c-28 0 -50 -22 -50 -50s22 -50 50 -50h300c28 0 50 22 50 50 -s-22 50 -50 50h-300zM100 400v-400h600v400h-600z" /> - <glyph glyph-name="27" unicode="" -d="M744 797l6 -3l44 -44c4 -4 3 -8 0 -12l-266 -375l-15 -13l-25 -12c-23 72 -78 127 -150 150l12 25l13 15l375 266zM266 400c74 0 134 -60 134 -134c0 -147 -119 -266 -266 -266c-48 0 -95 12 -134 34c80 46 134 133 134 232c0 74 58 134 132 134z" /> - <glyph glyph-name="28" unicode="" -d="M9 451c0 23 19 50 46 50c8 0 19 -3 26 -7l131 -66l29 22c-79 81 -1 250 118 250s197 -167 119 -250l28 -22l131 66c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-115 -56c9 -16 19 -33 25 -50h68c28 0 50 -22 50 -50s-22 -50 -50 -50h-50 + <metadata> + Created by FontForge 20120731 at Tue Jul 1 20:39:22 2014 + By P.J. Onori + Created by P.J. Onori with FontForge 2.0 (http://fontforge.sf.net) + </metadata> + <defs> + <font id="open-iconic" horiz-adv-x="800"> + <font-face + font-family="Icons" + font-weight="400" + font-stretch="normal" + units-per-em="800" + panose-1="2 0 5 3 0 0 0 0 0 0" + ascent="800" + descent="0" + bbox="-0.5 -101 802 800.126" + underline-thickness="50" + underline-position="-100" + unicode-range="U+E000-E0DE" + /> + <missing-glyph/> + <glyph glyph-name="" unicode="" + d="M300 700h500v-700h-500v100h400v500h-400v100zM400 500l200 -150l-200 -150v100h-400v100h400v100z"/> + <glyph glyph-name="1" unicode="" + d="M300 700h500v-700h-500v100h400v500h-400v100zM200 500v-100h400v-100h-400v-100l-200 150z"/> + <glyph glyph-name="2" unicode="" + d="M350 700c193 0 350 -157 350 -350v-50h100l-200 -200l-200 200h100v50c0 138 -112 250 -250 250s-250 -112 -250 -250c0 193 157 350 350 350z"/> + <glyph glyph-name="3" unicode="" + d="M450 700c193 0 350 -157 350 -350c0 138 -112 250 -250 250s-250 -112 -250 -250v-50h100l-200 -200l-200 200h100v50c0 193 157 350 350 350z"/> + <glyph glyph-name="4" unicode="" + d="M0 700h800v-100h-800v100zM100 500h600v-100h-600v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z"/> + <glyph glyph-name="5" unicode="" + d="M0 700h800v-100h-800v100zM0 500h600v-100h-600v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z"/> + <glyph glyph-name="6" unicode="" + d="M0 700h800v-100h-800v100zM200 500h600v-100h-600v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z"/> + <glyph glyph-name="7" unicode="" + d="M400 700c75 0 146 -23 206 -59l-75 -225l-322 234c57 31 122 50 191 50zM125 588l191 -138l-310 -222c-4 24 -6 47 -6 72c0 114 49 215 125 288zM688 575c69 -72 112 -168 112 -275c0 -35 -8 -68 -16 -100h-218zM216 253l112 -347c-128 23 -232 109 -287 222zM372 100 +h372c-64 -109 -177 -185 -310 -197z"/> + <glyph glyph-name="8" unicode="" horiz-adv-x="600" + d="M200 800h100v-500h200l-247 -300l-253 300h200v500z"/> + <glyph glyph-name="9" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 700v-300h-200l300 -300l300 300h-200v300h-200z"/> + <glyph glyph-name="a" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300l300 -300v200h300v200h-300v200z"/> + <glyph glyph-name="b" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700v-200h-300v-200h300v-200l300 300z"/> + <glyph glyph-name="c" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700l-300 -300h200v-300h200v300h200z"/> + <glyph glyph-name="d" unicode="" + d="M300 600v-200h500v-100h-500v-200l-300 247z"/> + <glyph glyph-name="e" unicode="" + d="M500 600l300 -247l-300 -253v200h-500v100h500v200z"/> + <glyph glyph-name="f" unicode="" horiz-adv-x="600" + d="M200 800h200v-500h200l-297 -300l-303 300h200v500z"/> + <glyph glyph-name="10" unicode="" + d="M300 700v-200h500v-200h-500v-200l-300 297z"/> + <glyph glyph-name="11" unicode="" + d="M500 700l300 -297l-300 -303v200h-500v200h500v200z"/> + <glyph glyph-name="12" unicode="" horiz-adv-x="600" + d="M297 800l303 -300h-200v-500h-200v500h-200z"/> + <glyph glyph-name="13" unicode="" horiz-adv-x="600" + d="M247 800l253 -300h-200v-500h-100v500h-200z"/> + <glyph glyph-name="14" unicode="" + d="M400 800h100v-800h-100v800zM200 700h100v-600h-100v600zM600 600h100v-400h-100v400zM0 500h100v-200h-100v200z"/> + <glyph glyph-name="15" unicode="" + d="M116 600l72 -72c-54 -54 -88 -126 -88 -209s34 -159 88 -213l-72 -72c-72 72 -116 175 -116 285s44 209 116 281zM684 600c72 -72 116 -171 116 -281s-44 -213 -116 -285l-72 72c54 54 88 130 88 213s-34 155 -88 209zM259 460l69 -72c-18 -18 -28 -41 -28 -69 +s10 -54 28 -72l-69 -72c-36 36 -59 89 -59 144s23 105 59 141zM541 459c36 -36 59 -85 59 -140s-23 -108 -59 -144l-69 72c18 18 28 44 28 72s-10 51 -28 69z"/> + <glyph glyph-name="16" unicode="" horiz-adv-x="400" + d="M200 800c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200s90 200 200 200zM100 319c31 -11 65 -19 100 -19s68 8 100 19v-319l-100 100l-100 -100v319z"/> + <glyph glyph-name="17" unicode="" + d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300c0 -66 21 -126 56 -175l419 419c-49 35 -109 56 -175 56zM644 575l-419 -419c49 -35 109 -56 175 -56c166 0 300 134 300 300 +c0 66 -21 126 -56 175z"/> + <glyph glyph-name="18" unicode="" + d="M0 700h100v-600h700v-100h-800v700zM500 700h200v-500h-200v500zM200 500h200v-300h-200v300z"/> + <glyph glyph-name="19" unicode="" + d="M397 800c13 1 23 -4 34 -13c2 -2 214 -254 241 -287h128v-100h-100v-366c0 -18 -16 -34 -34 -34h-532c-18 0 -34 16 -34 34v366h-100v100h128l234 281c9 11 22 18 35 19zM400 672l-144 -172h288zM250 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50 +v100c0 28 -22 50 -50 50zM550 300c-28 0 -50 -22 -50 -50v-100c0 -28 22 -50 50 -50s50 22 50 50v100c0 28 -22 50 -50 50z"/> + <glyph glyph-name="1a" unicode="" + d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9zM100 600v-400h500v400h-500z"/> + <glyph glyph-name="1b" unicode="" + d="M9 700h682c6 0 9 -4 9 -10v-190h100v-200h-100v-191c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v582c0 6 3 9 9 9z"/> + <glyph glyph-name="1c" unicode="" + d="M92 650c0 23 19 50 45 50h3h5h5h500c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-141c9 -17 120 -231 166 -309c16 -26 34 -61 34 -106c0 -39 -15 -77 -41 -103h-3c-26 -25 -62 -41 -100 -41h-512c-39 0 -77 15 -103 41s-41 64 -41 103c0 46 18 80 34 106 +c46 78 157 292 166 309v141h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51zM500 600h-200v-162l-6 -10s-63 -123 -119 -228h450c-56 105 -119 228 -119 228l-6 10v162z"/> + <glyph glyph-name="1d" unicode="" + d="M400 800c110 0 200 -90 200 -200c0 -104 52 -198 134 -266c41 -34 66 -82 66 -134h-800c0 52 25 100 66 134c82 68 134 162 134 266c0 110 90 200 200 200zM300 100h200c0 -55 -45 -100 -100 -100s-100 45 -100 100z"/> + <glyph glyph-name="1e" unicode="" horiz-adv-x="600" + d="M150 800h50l350 -250l-225 -147l225 -153l-350 -250h-50v250l-75 -75l-75 75l150 150l-150 150l75 75l75 -75v250zM250 650v-200l150 100zM250 350v-200l150 100z"/> + <glyph glyph-name="1f" unicode="" + d="M0 800h500c110 0 200 -90 200 -200c0 -47 -17 -91 -44 -125c85 -40 144 -125 144 -225c0 -138 -112 -250 -250 -250h-550v100c55 0 100 45 100 100v400c0 55 -45 100 -100 100v100zM300 700v-200h100c55 0 100 45 100 100s-45 100 -100 100h-100zM300 400v-300h150 +c83 0 150 67 150 150s-67 150 -150 150h-150z"/> + <glyph glyph-name="20" unicode="" horiz-adv-x="600" + d="M300 800v-300h200l-300 -500v300h-200z"/> + <glyph glyph-name="21" unicode="" + d="M100 800h300v-300l100 100l100 -100v300h50c28 0 50 -22 50 -50v-550h-550c-28 0 -50 -22 -50 -50s22 -50 50 -50h550v-100h-550c-83 0 -150 67 -150 150v550l3 19c8 39 39 70 78 78z"/> + <glyph glyph-name="22" unicode="" horiz-adv-x="400" + d="M0 800h400v-800l-200 200l-200 -200v800z"/> + <glyph glyph-name="23" unicode="" + d="M0 800h800v-100h-800v100zM0 600h300v-103h203v103h297v-591c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v591z"/> + <glyph glyph-name="24" unicode="" + d="M300 800h200c55 0 100 -45 100 -100v-100h191c6 0 9 -3 9 -9v-241c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v241c0 6 3 9 9 9h191v100c0 55 45 100 100 100zM300 700v-100h200v100h-200zM0 209c16 -6 32 -9 50 -9h700c18 0 34 3 50 9v-200c0 -6 -3 -9 -9 -9h-782 +c-6 0 -9 3 -9 9v200z"/> + <glyph glyph-name="25" unicode="" horiz-adv-x="600" + d="M300 800c58 0 110 -16 147 -53s53 -89 53 -147h-100c0 39 -11 61 -25 75s-36 25 -75 25c-35 0 -55 -10 -72 -31s-28 -55 -28 -94c0 -51 20 -107 28 -175h172v-100h-178c-14 -60 -49 -127 -113 -200h491v-100h-600v122l16 12c69 69 95 121 106 166h-122v100h125 +c-8 50 -25 106 -25 175c0 58 16 114 50 156c34 43 88 69 150 69z"/> + <glyph glyph-name="26" unicode="" + d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-700c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v700v2c0 20 15 42 34 48zM150 600c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50zM350 600c-28 0 -50 -22 -50 -50s22 -50 50 -50h300c28 0 50 22 50 50 +s-22 50 -50 50h-300zM100 400v-400h600v400h-600z"/> + <glyph glyph-name="27" unicode="" + d="M744 797l6 -3l44 -44c4 -4 3 -8 0 -12l-266 -375l-15 -13l-25 -12c-23 72 -78 127 -150 150l12 25l13 15l375 266zM266 400c74 0 134 -60 134 -134c0 -147 -119 -266 -266 -266c-48 0 -95 12 -134 34c80 46 134 133 134 232c0 74 58 134 132 134z"/> + <glyph glyph-name="28" unicode="" + d="M9 451c0 23 19 50 46 50c8 0 19 -3 26 -7l131 -66l29 22c-79 81 -1 250 118 250s197 -167 119 -250l28 -22l131 66c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-115 -56c9 -16 19 -33 25 -50h68c28 0 50 -22 50 -50s-22 -50 -50 -50h-50 c0 -23 -2 -45 -6 -66l78 -40c21 -5 37 -28 37 -49c0 -28 -22 -50 -50 -50c-10 0 -23 5 -31 11l-65 35c-24 -46 -62 -86 -103 -110c-35 19 -60 45 -60 72v135v4v5v6v5v5v87c0 28 -22 50 -50 50c-24 0 -45 -17 -50 -40c1 -3 1 -8 1 -11s0 -8 -1 -11v-82v-4v-5v-144 -c0 -28 -24 -53 -59 -72c-41 25 -79 64 -103 110l-66 -35c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49l78 40c-4 21 -6 43 -6 66h-50h-5c-28 0 -50 22 -50 50c0 26 22 50 50 50h5h69c6 17 16 34 25 50l-116 56c-16 7 -28 27 -28 45z" /> - <glyph glyph-name="29" unicode="" -d="M600 700h91c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-91v600zM210 503l290 147v-500l-250 125v-3c-15 0 -25 -8 -28 -22l75 -178c11 -25 0 -58 -25 -69s-58 0 -69 25l-103 272h-91c-6 0 -9 3 -9 9v182c0 6 3 9 9 9h182z" /> - <glyph glyph-name="2a" unicode="" -d="M9 800h682c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM100 700v-200h500v200h-500zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-300h100v300h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z" /> - <glyph glyph-name="2b" unicode="" -d="M0 800h700v-200h-700v200zM0 500h700v-491c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v491zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z" /> - <glyph glyph-name="2c" unicode="" -d="M409 800h182c6 0 10 -4 12 -9l94 -182c2 -5 6 -9 12 -9h82c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v441c0 83 67 150 150 150h141c6 0 10 4 12 9l94 182c2 5 6 9 12 9zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z -M500 500c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM500 400c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z" /> - <glyph glyph-name="2d" unicode="" -d="M0 600h800l-400 -400z" /> - <glyph glyph-name="2e" unicode="" horiz-adv-x="400" -d="M400 800v-800l-400 400z" /> - <glyph glyph-name="2f" unicode="" horiz-adv-x="400" -d="M0 800l400 -400l-400 -400v800z" /> - <glyph glyph-name="30" unicode="" -d="M400 600l400 -400h-800z" /> - <glyph glyph-name="31" unicode="" -d="M0 550c0 23 20 50 46 50h3h5h4h200c17 0 37 -13 44 -28l38 -72h444c14 0 19 -12 15 -25l-81 -250c-4 -13 -21 -25 -35 -25h-350c-14 0 -30 12 -34 25c-27 83 -54 167 -81 250l-10 25h-150c-2 0 -5 -1 -7 -1c-28 0 -51 23 -51 51zM358 100c28 0 50 -22 50 -50 -s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM658 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" /> - <glyph glyph-name="32" unicode="" -d="M0 700h500v-100h-300v-300h-100l-100 -100v500zM300 500h500v-500l-100 100h-400v400z" /> - <glyph glyph-name="33" unicode="" -d="M641 700l143 -141l-493 -493c-71 76 -146 148 -219 222l-72 71l141 141c50 -51 101 -101 153 -150c116 117 234 231 347 350z" /> - <glyph glyph-name="34" unicode="" -d="M150 600l250 -250l250 250l150 -150l-400 -400l-400 400z" /> - <glyph glyph-name="35" unicode="" horiz-adv-x="600" -d="M400 800l150 -150l-250 -250l250 -250l-150 -150l-400 400z" /> - <glyph glyph-name="36" unicode="" horiz-adv-x="600" -d="M150 800l400 -400l-400 -400l-150 150l250 250l-250 250z" /> - <glyph glyph-name="37" unicode="" -d="M400 600l400 -400l-150 -150l-250 250l-250 -250l-150 150z" /> - <glyph glyph-name="38" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM600 622l-250 -250l-100 100l-72 -72l172 -172l322 322z" /> - <glyph glyph-name="39" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM250 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z" /> - <glyph glyph-name="3a" unicode="" -d="M350 800c28 0 50 -22 50 -50v-50h75c14 0 25 -11 25 -25v-75h-300v75c0 14 11 25 25 25h75v50c0 28 22 50 50 50zM25 700h75v-200h500v200h75c14 0 25 -11 25 -25v-650c0 -14 -11 -25 -25 -25h-650c-14 0 -25 11 -25 25v650c0 14 11 25 25 25z" /> - <glyph glyph-name="3b" unicode="" -d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM350 600h100v-181c23 -24 47 -47 72 -69l-72 -72c-27 30 -55 59 -84 88l-16 12 -v222z" /> - <glyph glyph-name="3c" unicode="" -d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-191v50c0 83 -67 150 -150 150s-150 -67 -150 -150v-50h-272c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM434 400h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1 -v-150h150l-200 -200l-200 200h150v150v2c0 20 15 42 34 48z" /> - <glyph glyph-name="3d" unicode="" -d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-141l-200 200l-200 -200h-222c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM450 350l250 -250h-200v-50c0 -28 -22 -50 -50 -50s-50 22 -50 50v50h-200z" /> - <glyph glyph-name="3e" unicode="" -d="M450 700c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200s90 200 200 200c23 114 129 200 250 200z" /> - <glyph glyph-name="3f" unicode="" -d="M250 800c82 0 154 -40 200 -100c-143 0 -270 -85 -325 -209c-36 -10 -70 -25 -100 -47c-16 33 -25 67 -25 106c0 138 112 250 250 250zM450 600c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200 -s90 200 200 200c23 114 129 200 250 200z" /> - <glyph glyph-name="40" unicode="" -d="M500 700h100l-300 -600h-100zM100 600h100l-100 -200l100 -200h-100l-100 200zM600 600h100l100 -200l-100 -200h-100l100 200z" /> - <glyph glyph-name="41" unicode="" -d="M350 800h100l50 -119l28 -12l119 50l72 -72l-50 -119l12 -28l119 -50v-100l-119 -50l-12 -28l50 -119l-72 -72l-119 50l-28 -12l-50 -119h-100l-50 119l-28 12l-119 -50l-72 72l50 119l-12 28l-119 50v100l119 50l12 28l-50 119l72 72l119 -50l28 12zM400 550 -c-83 0 -150 -67 -150 -150s67 -150 150 -150s150 67 150 150s-67 150 -150 150z" /> - <glyph glyph-name="42" unicode="" -d="M0 800h800v-200h-800v200zM200 500h400l-200 -200zM0 100h800v-100h-800v100z" /> - <glyph glyph-name="43" unicode="" -d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM500 600v-400l-200 200z" /> - <glyph glyph-name="44" unicode="" -d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM300 600l200 -200l-200 -200v400z" /> - <glyph glyph-name="45" unicode="" -d="M0 800h800v-100h-800v100zM400 500l200 -200h-400zM0 200h800v-200h-800v200z" /> - <glyph glyph-name="46" unicode="" -d="M150 700c83 0 150 -67 150 -150v-50h100v50c0 83 67 150 150 150s150 -67 150 -150s-67 -150 -150 -150h-50v-100h50c83 0 150 -67 150 -150s-67 -150 -150 -150s-150 67 -150 150v50h-100v-50c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150h50v100h-50 +c0 -28 -24 -53 -59 -72c-41 25 -79 64 -103 110l-66 -35c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49l78 40c-4 21 -6 43 -6 66h-50h-5c-28 0 -50 22 -50 50c0 26 22 50 50 50h5h69c6 17 16 34 25 50l-116 56c-16 7 -28 27 -28 45z"/> + <glyph glyph-name="29" unicode="" + d="M600 700h91c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-91v600zM210 503l290 147v-500l-250 125v-3c-15 0 -25 -8 -28 -22l75 -178c11 -25 0 -58 -25 -69s-58 0 -69 25l-103 272h-91c-6 0 -9 3 -9 9v182c0 6 3 9 9 9h182z"/> + <glyph glyph-name="2a" unicode="" + d="M9 800h682c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM100 700v-200h500v200h-500zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-300h100v300h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z"/> + <glyph glyph-name="2b" unicode="" + d="M0 800h700v-200h-700v200zM0 500h700v-491c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v491zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100z"/> + <glyph glyph-name="2c" unicode="" + d="M409 800h182c6 0 10 -4 12 -9l94 -182c2 -5 6 -9 12 -9h82c6 0 9 -3 9 -9v-582c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v441c0 83 67 150 150 150h141c6 0 10 4 12 9l94 182c2 5 6 9 12 9zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z +M500 500c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM500 400c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z"/> + <glyph glyph-name="2d" unicode="" + d="M0 600h800l-400 -400z"/> + <glyph glyph-name="2e" unicode="" horiz-adv-x="400" + d="M400 800v-800l-400 400z"/> + <glyph glyph-name="2f" unicode="" horiz-adv-x="400" + d="M0 800l400 -400l-400 -400v800z"/> + <glyph glyph-name="30" unicode="" + d="M400 600l400 -400h-800z"/> + <glyph glyph-name="31" unicode="" + d="M0 550c0 23 20 50 46 50h3h5h4h200c17 0 37 -13 44 -28l38 -72h444c14 0 19 -12 15 -25l-81 -250c-4 -13 -21 -25 -35 -25h-350c-14 0 -30 12 -34 25c-27 83 -54 167 -81 250l-10 25h-150c-2 0 -5 -1 -7 -1c-28 0 -51 23 -51 51zM358 100c28 0 50 -22 50 -50 +s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM658 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/> + <glyph glyph-name="32" unicode="" + d="M0 700h500v-100h-300v-300h-100l-100 -100v500zM300 500h500v-500l-100 100h-400v400z"/> + <glyph glyph-name="33" unicode="" + d="M641 700l143 -141l-493 -493c-71 76 -146 148 -219 222l-72 71l141 141c50 -51 101 -101 153 -150c116 117 234 231 347 350z"/> + <glyph glyph-name="34" unicode="" + d="M150 600l250 -250l250 250l150 -150l-400 -400l-400 400z"/> + <glyph glyph-name="35" unicode="" horiz-adv-x="600" + d="M400 800l150 -150l-250 -250l250 -250l-150 -150l-400 400z"/> + <glyph glyph-name="36" unicode="" horiz-adv-x="600" + d="M150 800l400 -400l-400 -400l-150 150l250 250l-250 250z"/> + <glyph glyph-name="37" unicode="" + d="M400 600l400 -400l-150 -150l-250 250l-250 -250l-150 150z"/> + <glyph glyph-name="38" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM600 622l-250 -250l-100 100l-72 -72l172 -172l322 322z"/> + <glyph glyph-name="39" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM250 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z"/> + <glyph glyph-name="3a" unicode="" + d="M350 800c28 0 50 -22 50 -50v-50h75c14 0 25 -11 25 -25v-75h-300v75c0 14 11 25 25 25h75v50c0 28 22 50 50 50zM25 700h75v-200h500v200h75c14 0 25 -11 25 -25v-650c0 -14 -11 -25 -25 -25h-650c-14 0 -25 11 -25 25v650c0 14 11 25 25 25z"/> + <glyph glyph-name="3b" unicode="" + d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM350 600h100v-181c23 -24 47 -47 72 -69l-72 -72c-27 30 -55 59 -84 88l-16 12 +v222z"/> + <glyph glyph-name="3c" unicode="" + d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-191v50c0 83 -67 150 -150 150s-150 -67 -150 -150v-50h-272c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM434 400h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1 +v-150h150l-200 -200l-200 200h150v150v2c0 20 15 42 34 48z"/> + <glyph glyph-name="3d" unicode="" + d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -18 -3 -34 -9 -50h-141l-200 200l-200 -200h-222c-17 30 -28 63 -28 100c0 110 90 200 200 200c23 114 129 200 250 200zM450 350l250 -250h-200v-50c0 -28 -22 -50 -50 -50s-50 22 -50 50v50h-200z"/> + <glyph glyph-name="3e" unicode="" + d="M450 700c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200s90 200 200 200c23 114 129 200 250 200z"/> + <glyph glyph-name="3f" unicode="" + d="M250 800c82 0 154 -40 200 -100c-143 0 -270 -85 -325 -209c-36 -10 -70 -25 -100 -47c-16 33 -25 67 -25 106c0 138 112 250 250 250zM450 600c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -83 -67 -150 -150 -150h-450c-110 0 -200 90 -200 200 +s90 200 200 200c23 114 129 200 250 200z"/> + <glyph glyph-name="40" unicode="" + d="M500 700h100l-300 -600h-100zM100 600h100l-100 -200l100 -200h-100l-100 200zM600 600h100l100 -200l-100 -200h-100l100 200z"/> + <glyph glyph-name="41" unicode="" + d="M350 800h100l50 -119l28 -12l119 50l72 -72l-50 -119l12 -28l119 -50v-100l-119 -50l-12 -28l50 -119l-72 -72l-119 50l-28 -12l-50 -119h-100l-50 119l-28 12l-119 -50l-72 72l50 119l-12 28l-119 50v100l119 50l12 28l-50 119l72 72l119 -50l28 12zM400 550 +c-83 0 -150 -67 -150 -150s67 -150 150 -150s150 67 150 150s-67 150 -150 150z"/> + <glyph glyph-name="42" unicode="" + d="M0 800h800v-200h-800v200zM200 500h400l-200 -200zM0 100h800v-100h-800v100z"/> + <glyph glyph-name="43" unicode="" + d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM500 600v-400l-200 200z"/> + <glyph glyph-name="44" unicode="" + d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM300 600l200 -200l-200 -200v400z"/> + <glyph glyph-name="45" unicode="" + d="M0 800h800v-100h-800v100zM400 500l200 -200h-400zM0 200h800v-200h-800v200z"/> + <glyph glyph-name="46" unicode="" + d="M150 700c83 0 150 -67 150 -150v-50h100v50c0 83 67 150 150 150s150 -67 150 -150s-67 -150 -150 -150h-50v-100h50c83 0 150 -67 150 -150s-67 -150 -150 -150s-150 67 -150 150v50h-100v-50c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150h50v100h-50 c-83 0 -150 67 -150 150s67 150 150 150zM150 600c-28 0 -50 -22 -50 -50s22 -50 50 -50h50v50c0 28 -22 50 -50 50zM550 600c-28 0 -50 -22 -50 -50v-50h50c28 0 50 22 50 50s-22 50 -50 50zM300 400v-100h100v100h-100zM150 200c-28 0 -50 -22 -50 -50s22 -50 50 -50 -s50 22 50 50v50h-50zM500 200v-50c0 -28 22 -50 50 -50s50 22 50 50s-22 50 -50 50h-50z" /> - <glyph glyph-name="47" unicode="" -d="M0 791c0 5 4 9 9 9h782c6 0 9 -4 9 -10v-790l-200 200h-591c-6 0 -9 3 -9 9v582z" /> - <glyph glyph-name="48" unicode="" -d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM600 600l-100 -300l-300 -100l100 300zM400 450c-28 0 -50 -22 -50 -50 -s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" /> - <glyph glyph-name="49" unicode="" -d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700v-600c166 0 300 134 300 300s-134 300 -300 300z" /> - <glyph glyph-name="4a" unicode="" -d="M0 800h800v-100h-800v100zM0 600h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100zM750 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" /> - <glyph glyph-name="4b" unicode="" -d="M25 700h750c14 0 25 -11 25 -25v-75h-800v75c0 14 11 25 25 25zM0 500h800v-375c0 -14 -11 -25 -25 -25h-750c-14 0 -25 11 -25 25v375zM100 300v-100h100v100h-100zM300 300v-100h100v100h-100z" /> - <glyph glyph-name="4c" unicode="" -d="M100 800h100v-100h450l100 100l50 -50l-100 -100v-450h100v-100h-100v-100h-100v100h-500v500h-100v100h100v100zM200 600v-350l350 350h-350zM600 550l-350 -350h350v350z" /> - <glyph glyph-name="4d" unicode="" -d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z -M200 452c0 20 15 42 34 48h3h3h8c12 0 28 -7 36 -16l91 -90l25 6c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100l6 25l-90 91c-9 8 -16 24 -16 36zM550 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" /> - <glyph glyph-name="4e" unicode="" -d="M300 800h200v-300h200l-300 -300l-300 300h200v300zM0 100h800v-100h-800v100z" /> - <glyph glyph-name="4f" unicode="" -d="M0 800h800v-100h-800v100zM400 600l300 -300h-200v-300h-200v300h-200z" /> - <glyph glyph-name="50" unicode="" -d="M200 700h600v-600h-600l-200 300zM350 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z" /> - <glyph glyph-name="51" unicode="" -d="M400 700c220 0 400 -180 400 -400h-100c0 166 -134 300 -300 300s-300 -134 -300 -300h-100c0 220 180 400 400 400zM341 491l59 -88l59 88c81 -25 141 -101 141 -191c0 -110 -90 -200 -200 -200s-200 90 -200 200c0 90 60 166 141 191z" /> - <glyph glyph-name="52" unicode="" -d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300zM100 600v-100h100v100h-100zM100 400v-100h100v100h-100zM100 200v-100h400v100h-400z" /> - <glyph glyph-name="53" unicode="" horiz-adv-x="600" -d="M200 700h100v-100h75c30 0 58 -6 81 -22s44 -44 44 -78v-100h-100v94c-4 3 -13 6 -25 6h-250c-14 0 -25 -11 -25 -25v-50c0 -15 20 -40 34 -44l257 -65c66 -16 109 -73 109 -141v-50c0 -68 -57 -125 -125 -125h-75v-100h-100v100h-75c-30 0 -58 6 -81 22s-44 44 -44 78 -v100h100v-94c4 -3 13 -6 25 -6h250c14 0 25 11 25 25v50c0 15 -20 40 -34 44l-257 65c-66 16 -109 73 -109 141v50c0 68 57 125 125 125h75v100z" /> - <glyph glyph-name="54" unicode="" -d="M0 700h300v-300l-300 -300v600zM500 700h300v-300l-300 -300v600z" /> - <glyph glyph-name="55" unicode="" -d="M300 700v-600h-300v300zM800 700v-600h-300v300z" /> - <glyph glyph-name="56" unicode="" -d="M300 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300zM800 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300z" /> - <glyph glyph-name="57" unicode="" -d="M0 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300zM500 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300z" /> - <glyph glyph-name="58" unicode="" horiz-adv-x="600" -d="M300 800l34 -34c11 -11 266 -270 266 -488c0 -165 -135 -300 -300 -300s-300 135 -300 300c0 218 255 477 266 488zM150 328c-28 0 -50 -22 -50 -50c0 -110 90 -200 200 -200c28 0 50 22 50 50s-22 50 -50 50c-55 0 -100 45 -100 100c0 28 -22 50 -50 50z" /> - <glyph glyph-name="59" unicode="" -d="M400 800l400 -500h-800zM0 200h800v-200h-800v200z" /> - <glyph glyph-name="5a" unicode="" horiz-adv-x="600" -d="M300 800l300 -300h-600zM0 300h600l-300 -300z" /> - <glyph glyph-name="5b" unicode="" -d="M0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200z" /> - <glyph glyph-name="5c" unicode="" -d="M0 700h800v-100l-400 -200l-400 200v100zM0 500l400 -200l400 200v-400h-800v400z" /> - <glyph glyph-name="5d" unicode="" -d="M400 800l400 -200v-600h-800v600zM400 688l-300 -150v-188l300 -150l300 150v188zM200 500h400v-100l-200 -100l-200 100v100z" /> - <glyph glyph-name="5e" unicode="" -d="M600 700c69 0 134 -19 191 -50l-16 -106c-49 35 -109 56 -175 56c-131 0 -240 -84 -281 -200h331l-16 -100h-334c0 -36 8 -68 19 -100h297l-16 -100h-222c55 -61 133 -100 222 -100c78 0 147 30 200 78v-122c-59 -35 -127 -56 -200 -56c-147 0 -274 82 -344 200h-256 -l19 100h197c-8 32 -16 66 -16 100h-200l25 100h191c45 172 198 300 384 300z" /> - <glyph glyph-name="5f" unicode="" -d="M0 700h700v-100h-700v100zM0 500h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100z" /> - <glyph glyph-name="60" unicode="" -d="M0 800h800v-100h-800v100zM200 600h400l-200 -200zM0 200h800v-200h-800v200z" /> - <glyph glyph-name="61" unicode="" -d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM200 600l200 -200l-200 -200v400z" /> - <glyph glyph-name="62" unicode="" -d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM600 600v-400l-200 200z" /> - <glyph glyph-name="63" unicode="" -d="M0 800h800v-200h-800v200zM400 400l200 -200h-400zM0 100h800v-100h-800v100z" /> - <glyph glyph-name="64" unicode="" -d="M0 800h200v-100h-100v-600h600v100h100v-200h-800v800zM400 800h400v-400l-150 150l-250 -250l-100 100l250 250z" /> - <glyph glyph-name="65" unicode="" -d="M403 700c247 0 397 -300 397 -300s-150 -300 -397 -300c-253 0 -403 300 -403 300s150 300 403 300zM400 600c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM400 500c10 0 19 -3 28 -6c-16 -8 -28 -24 -28 -44c0 -28 22 -50 50 -50 -c20 0 36 12 44 28c3 -9 6 -18 6 -28c0 -55 -45 -100 -100 -100s-100 45 -100 100s45 100 100 100z" /> - <glyph glyph-name="66" unicode="" horiz-adv-x="900" -d="M331 700h3h3c3 1 7 1 10 1c12 0 29 -8 37 -17l94 -93l66 65c57 57 155 57 212 0c58 -58 58 -154 0 -212l-65 -66l93 -94c10 -8 18 -25 18 -38c0 -28 -22 -50 -50 -50c-13 0 -32 9 -40 20l-62 65l-381 -381h-269v272l375 381l-63 63c-9 8 -16 24 -16 36c0 20 16 42 35 48z -M447 481l-313 -315l128 -132l316 316z" /> - <glyph glyph-name="67" unicode="" -d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300z" /> - <glyph glyph-name="68" unicode="" -d="M200 800c0 0 200 -100 200 -300s-298 -302 -200 -500c0 0 -200 100 -200 300s300 300 200 500zM500 500c0 0 200 -100 200 -300c0 -150 -60 -200 -100 -200h-300c0 200 300 300 200 500z" /> - <glyph glyph-name="69" unicode="" -d="M0 800h100v-800h-100v800zM200 800h300v-100h300l-200 -203l200 -197h-400v100h-200v400z" /> - <glyph glyph-name="6a" unicode="" horiz-adv-x="400" -d="M150 800h150l-100 -200h200l-150 -300h150l-300 -300l-100 300h134l66 200h-200z" /> - <glyph glyph-name="6b" unicode="" -d="M0 800h300v-100h500v-100h-800v200zM0 500h800v-450c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v450z" /> - <glyph glyph-name="6c" unicode="" -d="M150 800c83 0 150 -67 150 -150c0 -66 -41 -121 -100 -141v-118c15 5 33 9 50 9h200c28 0 50 22 50 50v59c-59 20 -100 75 -100 141c0 83 67 150 150 150s150 -67 150 -150c0 -66 -41 -121 -100 -141v-59c0 -82 -68 -150 -150 -150h-200c-14 0 -25 -7 -34 -16 -c50 -24 84 -74 84 -134c0 -83 -67 -150 -150 -150s-150 67 -150 150c0 66 41 121 100 141v218c-59 20 -100 75 -100 141c0 83 67 150 150 150z" /> - <glyph glyph-name="6d" unicode="" -d="M0 800h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400zM500 400l150 -150l150 150v-400h-400l150 150l-150 150z" /> - <glyph glyph-name="6e" unicode="" -d="M100 800l150 -150l150 150v-400h-400l150 150l-150 150zM400 400h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400z" /> - <glyph glyph-name="6f" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700c-56 0 -108 -17 -153 -44l22 -19c33 -18 13 -48 -13 -59c-30 -13 -77 10 -65 -41c13 -55 -27 -3 -47 -15c-42 -26 49 -152 31 -156l-59 34c-8 0 -13 -5 -16 -10 +s50 22 50 50v50h-50zM500 200v-50c0 -28 22 -50 50 -50s50 22 50 50s-22 50 -50 50h-50z"/> + <glyph glyph-name="47" unicode="" + d="M0 791c0 5 4 9 9 9h782c6 0 9 -4 9 -10v-790l-200 200h-591c-6 0 -9 3 -9 9v582z"/> + <glyph glyph-name="48" unicode="" + d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM600 600l-100 -300l-300 -100l100 300zM400 450c-28 0 -50 -22 -50 -50 +s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/> + <glyph glyph-name="49" unicode="" + d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700v-600c166 0 300 134 300 300s-134 300 -300 300z"/> + <glyph glyph-name="4a" unicode="" + d="M0 800h800v-100h-800v100zM0 600h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100zM750 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/> + <glyph glyph-name="4b" unicode="" + d="M25 700h750c14 0 25 -11 25 -25v-75h-800v75c0 14 11 25 25 25zM0 500h800v-375c0 -14 -11 -25 -25 -25h-750c-14 0 -25 11 -25 25v375zM100 300v-100h100v100h-100zM300 300v-100h100v100h-100z"/> + <glyph glyph-name="4c" unicode="" + d="M100 800h100v-100h450l100 100l50 -50l-100 -100v-450h100v-100h-100v-100h-100v100h-500v500h-100v100h100v100zM200 600v-350l350 350h-350zM600 550l-350 -350h350v350z"/> + <glyph glyph-name="4d" unicode="" + d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z +M200 452c0 20 15 42 34 48h3h3h8c12 0 28 -7 36 -16l91 -90l25 6c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100l6 25l-90 91c-9 8 -16 24 -16 36zM550 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/> + <glyph glyph-name="4e" unicode="" + d="M300 800h200v-300h200l-300 -300l-300 300h200v300zM0 100h800v-100h-800v100z"/> + <glyph glyph-name="4f" unicode="" + d="M0 800h800v-100h-800v100zM400 600l300 -300h-200v-300h-200v300h-200z"/> + <glyph glyph-name="50" unicode="" + d="M200 700h600v-600h-600l-200 300zM350 622l-72 -72l150 -150l-150 -150l72 -72l150 150l150 -150l72 72l-150 150l150 150l-72 72l-150 -150z"/> + <glyph glyph-name="51" unicode="" + d="M400 700c220 0 400 -180 400 -400h-100c0 166 -134 300 -300 300s-300 -134 -300 -300h-100c0 220 180 400 400 400zM341 491l59 -88l59 88c81 -25 141 -101 141 -191c0 -110 -90 -200 -200 -200s-200 90 -200 200c0 90 60 166 141 191z"/> + <glyph glyph-name="52" unicode="" + d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300zM100 600v-100h100v100h-100zM100 400v-100h100v100h-100zM100 200v-100h400v100h-400z"/> + <glyph glyph-name="53" unicode="" horiz-adv-x="600" + d="M200 700h100v-100h75c30 0 58 -6 81 -22s44 -44 44 -78v-100h-100v94c-4 3 -13 6 -25 6h-250c-14 0 -25 -11 -25 -25v-50c0 -15 20 -40 34 -44l257 -65c66 -16 109 -73 109 -141v-50c0 -68 -57 -125 -125 -125h-75v-100h-100v100h-75c-30 0 -58 6 -81 22s-44 44 -44 78 +v100h100v-94c4 -3 13 -6 25 -6h250c14 0 25 11 25 25v50c0 15 -20 40 -34 44l-257 65c-66 16 -109 73 -109 141v50c0 68 57 125 125 125h75v100z"/> + <glyph glyph-name="54" unicode="" + d="M0 700h300v-300l-300 -300v600zM500 700h300v-300l-300 -300v600z"/> + <glyph glyph-name="55" unicode="" + d="M300 700v-600h-300v300zM800 700v-600h-300v300z"/> + <glyph glyph-name="56" unicode="" + d="M300 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300zM800 700v-100c-111 0 -200 -89 -200 -200h200v-300h-300v300c0 165 135 300 300 300z"/> + <glyph glyph-name="57" unicode="" + d="M0 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300zM500 700h300v-300c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-200v300z"/> + <glyph glyph-name="58" unicode="" horiz-adv-x="600" + d="M300 800l34 -34c11 -11 266 -270 266 -488c0 -165 -135 -300 -300 -300s-300 135 -300 300c0 218 255 477 266 488zM150 328c-28 0 -50 -22 -50 -50c0 -110 90 -200 200 -200c28 0 50 22 50 50s-22 50 -50 50c-55 0 -100 45 -100 100c0 28 -22 50 -50 50z"/> + <glyph glyph-name="59" unicode="" + d="M400 800l400 -500h-800zM0 200h800v-200h-800v200z"/> + <glyph glyph-name="5a" unicode="" horiz-adv-x="600" + d="M300 800l300 -300h-600zM0 300h600l-300 -300z"/> + <glyph glyph-name="5b" unicode="" + d="M0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200z"/> + <glyph glyph-name="5c" unicode="" + d="M0 700h800v-100l-400 -200l-400 200v100zM0 500l400 -200l400 200v-400h-800v400z"/> + <glyph glyph-name="5d" unicode="" + d="M400 800l400 -200v-600h-800v600zM400 688l-300 -150v-188l300 -150l300 150v188zM200 500h400v-100l-200 -100l-200 100v100z"/> + <glyph glyph-name="5e" unicode="" + d="M600 700c69 0 134 -19 191 -50l-16 -106c-49 35 -109 56 -175 56c-131 0 -240 -84 -281 -200h331l-16 -100h-334c0 -36 8 -68 19 -100h297l-16 -100h-222c55 -61 133 -100 222 -100c78 0 147 30 200 78v-122c-59 -35 -127 -56 -200 -56c-147 0 -274 82 -344 200h-256 +l19 100h197c-8 32 -16 66 -16 100h-200l25 100h191c45 172 198 300 384 300z"/> + <glyph glyph-name="5f" unicode="" + d="M0 700h700v-100h-700v100zM0 500h500v-100h-500v100zM0 300h800v-100h-800v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100z"/> + <glyph glyph-name="60" unicode="" + d="M0 800h800v-100h-800v100zM200 600h400l-200 -200zM0 200h800v-200h-800v200z"/> + <glyph glyph-name="61" unicode="" + d="M0 800h100v-800h-100v800zM600 800h200v-800h-200v800zM200 600l200 -200l-200 -200v400z"/> + <glyph glyph-name="62" unicode="" + d="M0 800h200v-800h-200v800zM700 800h100v-800h-100v800zM600 600v-400l-200 200z"/> + <glyph glyph-name="63" unicode="" + d="M0 800h800v-200h-800v200zM400 400l200 -200h-400zM0 100h800v-100h-800v100z"/> + <glyph glyph-name="64" unicode="" + d="M0 800h200v-100h-100v-600h600v100h100v-200h-800v800zM400 800h400v-400l-150 150l-250 -250l-100 100l250 250z"/> + <glyph glyph-name="65" unicode="" + d="M403 700c247 0 397 -300 397 -300s-150 -300 -397 -300c-253 0 -403 300 -403 300s150 300 403 300zM400 600c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200zM400 500c10 0 19 -3 28 -6c-16 -8 -28 -24 -28 -44c0 -28 22 -50 50 -50 +c20 0 36 12 44 28c3 -9 6 -18 6 -28c0 -55 -45 -100 -100 -100s-100 45 -100 100s45 100 100 100z"/> + <glyph glyph-name="66" unicode="" horiz-adv-x="900" + d="M331 700h3h3c3 1 7 1 10 1c12 0 29 -8 37 -17l94 -93l66 65c57 57 155 57 212 0c58 -58 58 -154 0 -212l-65 -66l93 -94c10 -8 18 -25 18 -38c0 -28 -22 -50 -50 -50c-13 0 -32 9 -40 20l-62 65l-381 -381h-269v272l375 381l-63 63c-9 8 -16 24 -16 36c0 20 16 42 35 48z +M447 481l-313 -315l128 -132l316 316z"/> + <glyph glyph-name="67" unicode="" + d="M0 800h300v-400h400v-400h-700v800zM400 800l300 -300h-300v300z"/> + <glyph glyph-name="68" unicode="" + d="M200 800c0 0 200 -100 200 -300s-298 -302 -200 -500c0 0 -200 100 -200 300s300 300 200 500zM500 500c0 0 200 -100 200 -300c0 -150 -60 -200 -100 -200h-300c0 200 300 300 200 500z"/> + <glyph glyph-name="69" unicode="" + d="M0 800h100v-800h-100v800zM200 800h300v-100h300l-200 -203l200 -197h-400v100h-200v400z"/> + <glyph glyph-name="6a" unicode="" horiz-adv-x="400" + d="M150 800h150l-100 -200h200l-150 -300h150l-300 -300l-100 300h134l66 200h-200z"/> + <glyph glyph-name="6b" unicode="" + d="M0 800h300v-100h500v-100h-800v200zM0 500h800v-450c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v450z"/> + <glyph glyph-name="6c" unicode="" + d="M150 800c83 0 150 -67 150 -150c0 -66 -41 -121 -100 -141v-118c15 5 33 9 50 9h200c28 0 50 22 50 50v59c-59 20 -100 75 -100 141c0 83 67 150 150 150s150 -67 150 -150c0 -66 -41 -121 -100 -141v-59c0 -82 -68 -150 -150 -150h-200c-14 0 -25 -7 -34 -16 +c50 -24 84 -74 84 -134c0 -83 -67 -150 -150 -150s-150 67 -150 150c0 66 41 121 100 141v218c-59 20 -100 75 -100 141c0 83 67 150 150 150z"/> + <glyph glyph-name="6d" unicode="" + d="M0 800h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400zM500 400l150 -150l150 150v-400h-400l150 150l-150 150z"/> + <glyph glyph-name="6e" unicode="" + d="M100 800l150 -150l150 150v-400h-400l150 150l-150 150zM400 400h400l-150 -150l150 -150l-100 -100l-150 150l-150 -150v400z"/> + <glyph glyph-name="6f" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM400 700c-56 0 -108 -17 -153 -44l22 -19c33 -18 13 -48 -13 -59c-30 -13 -77 10 -65 -41c13 -55 -27 -3 -47 -15c-42 -26 49 -152 31 -156l-59 34c-8 0 -13 -5 -16 -10 c1 -30 10 -57 19 -84c28 -11 77 -2 100 -25c47 -28 97 -115 75 -159c34 -13 68 -22 106 -22c101 0 193 48 247 125c3 24 -8 44 -50 44c-69 0 -156 13 -153 97c2 46 101 108 66 143c-30 30 12 39 12 66c0 37 -65 32 -69 50s20 36 41 56c-30 10 -60 19 -94 19zM631 591 -c-38 -11 -94 -35 -87 -53c6 -15 52 -1 65 -13c11 -10 16 -59 44 -31l22 22v3c-11 26 -26 50 -44 72z" /> - <glyph glyph-name="70" unicode="" -d="M703 800l97 -100l-400 -400l-100 100l-200 -203l-100 100l300 303l100 -100zM0 100h800v-100h-800v100z" /> - <glyph glyph-name="71" unicode="" -d="M0 700h100v-100h-100v100zM200 700h100v-100h-100v100zM400 700h100v-100h-100v100zM600 700h100v-100h-100v100zM0 500h100v-100h-100v100zM200 500h100v-100h-100v100zM400 500h100v-100h-100v100zM600 500h100v-100h-100v100zM0 300h100v-100h-100v100zM200 300h100 -v-100h-100v100zM400 300h100v-100h-100v100zM600 300h100v-100h-100v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100zM600 100h100v-100h-100v100z" /> - <glyph glyph-name="72" unicode="" -d="M0 800h200v-200h-200v200zM300 800h200v-200h-200v200zM600 800h200v-200h-200v200zM0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200zM0 200h200v-200h-200v200zM300 200h200v-200h-200v200zM600 200h200v-200h-200v200z" /> - <glyph glyph-name="73" unicode="" -d="M0 800h300v-300h-300v300zM500 800h300v-300h-300v300zM0 300h300v-300h-300v300zM500 300h300v-300h-300v300z" /> - <glyph glyph-name="74" unicode="" -d="M19 800h662c11 0 19 -8 19 -19v-331c0 -28 -22 -50 -50 -50h-600c-28 0 -50 22 -50 50v331c0 11 8 19 19 19zM0 309c16 -6 32 -9 50 -9h600c18 0 34 3 50 9v-290c0 -11 -8 -19 -19 -19h-662c-11 0 -19 8 -19 19v290zM550 200c-28 0 -50 -22 -50 -50s22 -50 50 -50 -s50 22 50 50s-22 50 -50 50z" /> - <glyph glyph-name="75" unicode="" -d="M0 700h300v-100h-50c-28 0 -50 -22 -50 -50v-150h300v150c0 28 -22 50 -50 50h-50v100h300v-100h-50c-28 0 -50 -22 -50 -50v-400c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50v150h-300v-150c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50 -v400c0 28 -22 50 -50 50h-50v100z" /> - <glyph glyph-name="76" unicode="" -d="M400 700c165 0 300 -135 300 -300v-100h50c28 0 50 -22 50 -50v-200c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v350c0 111 -89 200 -200 200s-200 -89 -200 -200v-350c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v200c0 28 22 50 50 50h50v100 -c0 165 135 300 300 300z" /> - <glyph glyph-name="77" unicode="" -d="M0 500c0 109 91 200 200 200s200 -91 200 -200c0 109 91 200 200 200s200 -91 200 -200c0 -55 -23 -105 -59 -141l-341 -340l-341 340c-36 36 -59 86 -59 141z" /> - <glyph glyph-name="78" unicode="" -d="M400 700l400 -300l-100 3v-403h-200v200h-200v-200h-200v400h-100z" /> - <glyph glyph-name="79" unicode="" -d="M0 800h800v-800h-800v800zM100 700v-300l100 100l400 -400h100v100l-200 200l100 100l100 -100v300h-600z" /> - <glyph glyph-name="7a" unicode="" -d="M19 800h762c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-762c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 600v-300h100l100 -100h200l100 100h100v300h-600z" /> - <glyph glyph-name="7b" unicode="" -d="M200 600c80 0 142 -56 200 -122c58 66 119 122 200 122c131 0 200 -101 200 -200s-69 -200 -200 -200c-81 0 -142 56 -200 122c-58 -66 -121 -122 -200 -122c-131 0 -200 101 -200 200s69 200 200 200zM200 500c-74 0 -100 -54 -100 -100s26 -100 100 -100 -c42 0 88 47 134 100c-46 53 -92 100 -134 100zM600 500c-43 0 -88 -47 -134 -100c46 -53 91 -100 134 -100c74 0 100 54 100 100s-26 100 -100 100z" /> - <glyph glyph-name="7c" unicode="" horiz-adv-x="400" -d="M300 800c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100zM150 550c83 0 150 -69 150 -150c0 -66 -100 -214 -100 -250c0 -28 22 -50 50 -50s50 22 50 50h100c0 -83 -67 -150 -150 -150s-150 64 -150 150s100 222 100 250s-22 50 -50 50 -s-50 -22 -50 -50h-100c0 83 67 150 150 150z" /> - <glyph glyph-name="7d" unicode="" -d="M200 800h500v-100h-122c-77 -197 -156 -392 -234 -588l-6 -12h162v-100h-500v100h122c77 197 156 392 234 588l7 12h-163v100z" /> - <glyph glyph-name="7e" unicode="" -d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z" /> - <glyph glyph-name="7f" unicode="" -d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z" /> - <glyph glyph-name="80" unicode="" -d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z" /> - <glyph glyph-name="81" unicode="" -d="M550 800c138 0 250 -112 250 -250s-112 -250 -250 -250c-16 0 -32 0 -47 3l-3 -3v-100h-200v-200h-300v200l303 303c-3 15 -3 31 -3 47c0 138 112 250 250 250zM600 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z" /> - <glyph glyph-name="82" unicode="" -d="M134 600h3h4h4h5h500c28 0 50 -22 50 -50v-350h100v-150c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v150h100v350v2c0 20 15 42 34 48zM200 500v-300h100v-100h200v100h100v300h-400z" /> - <glyph glyph-name="83" unicode="" -d="M0 800h400v-400h-400v400zM500 600h100v-400h-400v100h300v300zM700 400h100v-400h-400v100h300v300z" /> - <glyph glyph-name="84" unicode="" horiz-adv-x="600" -d="M337 694c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-300 -150c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49zM437 544c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-400 -200c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50 +c-38 -11 -94 -35 -87 -53c6 -15 52 -1 65 -13c11 -10 16 -59 44 -31l22 22v3c-11 26 -26 50 -44 72z"/> + <glyph glyph-name="70" unicode="" + d="M703 800l97 -100l-400 -400l-100 100l-200 -203l-100 100l300 303l100 -100zM0 100h800v-100h-800v100z"/> + <glyph glyph-name="71" unicode="" + d="M0 700h100v-100h-100v100zM200 700h100v-100h-100v100zM400 700h100v-100h-100v100zM600 700h100v-100h-100v100zM0 500h100v-100h-100v100zM200 500h100v-100h-100v100zM400 500h100v-100h-100v100zM600 500h100v-100h-100v100zM0 300h100v-100h-100v100zM200 300h100 +v-100h-100v100zM400 300h100v-100h-100v100zM600 300h100v-100h-100v100zM0 100h100v-100h-100v100zM200 100h100v-100h-100v100zM400 100h100v-100h-100v100zM600 100h100v-100h-100v100z"/> + <glyph glyph-name="72" unicode="" + d="M0 800h200v-200h-200v200zM300 800h200v-200h-200v200zM600 800h200v-200h-200v200zM0 500h200v-200h-200v200zM300 500h200v-200h-200v200zM600 500h200v-200h-200v200zM0 200h200v-200h-200v200zM300 200h200v-200h-200v200zM600 200h200v-200h-200v200z"/> + <glyph glyph-name="73" unicode="" + d="M0 800h300v-300h-300v300zM500 800h300v-300h-300v300zM0 300h300v-300h-300v300zM500 300h300v-300h-300v300z"/> + <glyph glyph-name="74" unicode="" + d="M19 800h662c11 0 19 -8 19 -19v-331c0 -28 -22 -50 -50 -50h-600c-28 0 -50 22 -50 50v331c0 11 8 19 19 19zM0 309c16 -6 32 -9 50 -9h600c18 0 34 3 50 9v-290c0 -11 -8 -19 -19 -19h-662c-11 0 -19 8 -19 19v290zM550 200c-28 0 -50 -22 -50 -50s22 -50 50 -50 +s50 22 50 50s-22 50 -50 50z"/> + <glyph glyph-name="75" unicode="" + d="M0 700h300v-100h-50c-28 0 -50 -22 -50 -50v-150h300v150c0 28 -22 50 -50 50h-50v100h300v-100h-50c-28 0 -50 -22 -50 -50v-400c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50v150h-300v-150c0 -28 22 -50 50 -50h50v-100h-300v100h50c28 0 50 22 50 50 +v400c0 28 -22 50 -50 50h-50v100z"/> + <glyph glyph-name="76" unicode="" + d="M400 700c165 0 300 -135 300 -300v-100h50c28 0 50 -22 50 -50v-200c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v350c0 111 -89 200 -200 200s-200 -89 -200 -200v-350c0 -28 -22 -50 -50 -50h-100c-28 0 -50 22 -50 50v200c0 28 22 50 50 50h50v100 +c0 165 135 300 300 300z"/> + <glyph glyph-name="77" unicode="" + d="M0 500c0 109 91 200 200 200s200 -91 200 -200c0 109 91 200 200 200s200 -91 200 -200c0 -55 -23 -105 -59 -141l-341 -340l-341 340c-36 36 -59 86 -59 141z"/> + <glyph glyph-name="78" unicode="" + d="M400 700l400 -300l-100 3v-403h-200v200h-200v-200h-200v400h-100z"/> + <glyph glyph-name="79" unicode="" + d="M0 800h800v-800h-800v800zM100 700v-300l100 100l400 -400h100v100l-200 200l100 100l100 -100v300h-600z"/> + <glyph glyph-name="7a" unicode="" + d="M19 800h762c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-762c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 600v-300h100l100 -100h200l100 100h100v300h-600z"/> + <glyph glyph-name="7b" unicode="" + d="M200 600c80 0 142 -56 200 -122c58 66 119 122 200 122c131 0 200 -101 200 -200s-69 -200 -200 -200c-81 0 -142 56 -200 122c-58 -66 -121 -122 -200 -122c-131 0 -200 101 -200 200s69 200 200 200zM200 500c-74 0 -100 -54 -100 -100s26 -100 100 -100 +c42 0 88 47 134 100c-46 53 -92 100 -134 100zM600 500c-43 0 -88 -47 -134 -100c46 -53 91 -100 134 -100c74 0 100 54 100 100s-26 100 -100 100z"/> + <glyph glyph-name="7c" unicode="" horiz-adv-x="400" + d="M300 800c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100zM150 550c83 0 150 -69 150 -150c0 -66 -100 -214 -100 -250c0 -28 22 -50 50 -50s50 22 50 50h100c0 -83 -67 -150 -150 -150s-150 64 -150 150s100 222 100 250s-22 50 -50 50 +s-50 -22 -50 -50h-100c0 83 67 150 150 150z"/> + <glyph glyph-name="7d" unicode="" + d="M200 800h500v-100h-122c-77 -197 -156 -392 -234 -588l-6 -12h162v-100h-500v100h122c77 197 156 392 234 588l7 12h-163v100z"/> + <glyph glyph-name="7e" unicode="" + d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM100 100h600v-100h-600v100z"/> + <glyph glyph-name="7f" unicode="" + d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM0 100h600v-100h-600v100z"/> + <glyph glyph-name="80" unicode="" + d="M0 700h800v-100h-800v100zM0 500h800v-100h-800v100zM0 300h800v-100h-800v100zM200 100h600v-100h-600v100z"/> + <glyph glyph-name="81" unicode="" + d="M550 800c138 0 250 -112 250 -250s-112 -250 -250 -250c-16 0 -32 0 -47 3l-3 -3v-100h-200v-200h-300v200l303 303c-3 15 -3 31 -3 47c0 138 112 250 250 250zM600 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z"/> + <glyph glyph-name="82" unicode="" + d="M134 600h3h4h4h5h500c28 0 50 -22 50 -50v-350h100v-150c0 -28 -22 -50 -50 -50h-700c-28 0 -50 22 -50 50v150h100v350v2c0 20 15 42 34 48zM200 500v-300h100v-100h200v100h100v300h-400z"/> + <glyph glyph-name="83" unicode="" + d="M0 800h400v-400h-400v400zM500 600h100v-400h-400v100h300v300zM700 400h100v-400h-400v100h300v300z"/> + <glyph glyph-name="84" unicode="" horiz-adv-x="600" + d="M337 694c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-300 -150c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50c0 21 16 44 37 49zM437 544c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-400 -200c-8 -6 -21 -11 -31 -11c-28 0 -50 22 -50 50 c0 21 16 44 37 49zM437 344c6 4 12 7 21 7c28 0 50 -22 50 -50c0 -17 -12 -37 -27 -45l-106 -56c24 -4 43 -26 43 -50c0 -28 -23 -51 -51 -51c-2 0 -6 1 -8 1h-200c-26 1 -48 24 -48 50c0 16 12 36 26 44zM151 -50c0 23 20 50 46 50h3h4h5h100c28 0 50 -22 50 -50 -s-22 -50 -50 -50h-100c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z" /> - <glyph glyph-name="85" unicode="" -d="M199 800h100v-200h-200v100h100v100zM586 797h1c18 1 38 1 56 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-8 -13 -28 -24 -43 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0l-44 -44 +s-22 -50 -50 -50h-100c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z"/> + <glyph glyph-name="85" unicode="" + d="M199 800h100v-200h-200v100h100v100zM586 797h1c18 1 38 1 56 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-8 -13 -28 -24 -43 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0l-44 -44 c-8 -13 -27 -24 -42 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43l43 44c32 33 72 53 128 56zM208 490c4 5 14 16 22 16h3c2 0 6 1 8 1c28 0 50 -22 50 -50c0 -11 -6 -27 -14 -35l-150 -150c-40 -40 -39 -105 0 -144c41 -41 110 -34 144 0l44 44c8 13 27 24 42 24 -c28 0 50 -22 50 -50c0 -15 -11 -35 -24 -43l-43 -44c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281zM499 200h200v-100h-100v-100h-100v200z" /> - <glyph glyph-name="86" unicode="" -d="M586 797c18 1 39 1 57 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-62 -62 -132 -81 -182 -78s-69 17 -84 25s-26 27 -26 44c0 28 22 51 50 51c8 0 19 -3 26 -7c0 0 15 -11 41 -13s62 3 106 47l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0 +c28 0 50 -22 50 -50c0 -15 -11 -35 -24 -43l-43 -44c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281zM499 200h200v-100h-100v-100h-100v200z"/> + <glyph glyph-name="86" unicode="" + d="M586 797c18 1 39 1 57 -3c36 -8 69 -26 97 -54c78 -78 78 -203 0 -281l-150 -150c-62 -62 -132 -81 -182 -78s-69 17 -84 25s-26 27 -26 44c0 28 22 51 50 51c8 0 19 -3 26 -7c0 0 15 -11 41 -13s62 3 106 47l150 150c40 40 39 105 0 144c-41 41 -110 34 -144 0 c-8 -13 -28 -24 -43 -24c-28 0 -50 22 -50 50c0 15 11 35 24 43c32 33 72 53 128 56zM386 566c50 -2 64 -17 85 -22s37 -28 37 -49c0 -28 -22 -50 -50 -50c-10 0 -23 5 -31 11c0 0 -19 9 -47 10s-63 -4 -103 -44l-150 -150c-40 -40 -39 -105 0 -144c41 -41 110 -34 144 0 -c8 13 27 24 42 24c28 0 50 -22 50 -50c0 -15 -10 -35 -23 -43c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281l150 150c60 60 128 78 178 76z" /> - <glyph glyph-name="87" unicode="" -d="M0 700h300v-300h-300v300zM400 700h400v-100h-400v100zM400 500h300v-100h-300v100zM0 300h300v-300h-300v300zM400 300h400v-100h-400v100zM400 100h300v-100h-300v100z" /> - <glyph glyph-name="88" unicode="" -d="M50 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 700h600v-100h-600v100zM50 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 500h600v-100h-600v100zM50 300c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50 -s22 50 50 50zM200 300h600v-100h-600v100zM50 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 100h600v-100h-600v100z" /> - <glyph glyph-name="89" unicode="" -d="M800 800l-400 -800l-100 300l-300 100z" /> - <glyph glyph-name="8a" unicode="" horiz-adv-x="600" -d="M300 700c110 0 200 -90 200 -200v-100h100v-400h-600v400h100v100c0 110 90 200 200 200zM300 600c-56 0 -100 -44 -100 -100v-100h200v100c0 56 -44 100 -100 100z" /> - <glyph glyph-name="8b" unicode="" horiz-adv-x="600" -d="M300 800c110 0 200 -90 200 -200v-200h100v-400h-600v400h400v200c0 56 -44 100 -100 100s-100 -44 -100 -100h-100c0 110 90 200 200 200z" /> - <glyph glyph-name="8c" unicode="" -d="M400 700v-100c-111 0 -200 -89 -200 -200h100l-150 -200l-150 200h100c0 165 135 300 300 300zM650 600l150 -200h-100c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-100z" /> - <glyph glyph-name="8d" unicode="" -d="M100 800h600v-300h100l-150 -250l-150 250h100v200h-400v-100h-100v200zM150 550l150 -250h-100v-200h400v100h100v-200h-600v300h-100z" /> - <glyph glyph-name="8e" unicode="" -d="M600 700l200 -150l-200 -150v100h-500v-100h-100v100c0 55 45 100 100 100h500v100zM200 300v-100h500v100h100v-100c0 -55 -45 -100 -100 -100h-500v-100l-200 150z" /> - <glyph glyph-name="8f" unicode="" horiz-adv-x="900" -d="M350 800c193 0 350 -157 350 -350c0 -60 -17 -117 -44 -166c5 -3 12 -8 16 -12l100 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 100c-4 3 -9 9 -12 13c-49 -26 -107 -41 -166 -41c-193 0 -350 157 -350 350s157 350 350 350zM350 200 -c142 0 250 108 250 250c0 139 -111 250 -250 250s-250 -111 -250 -250s111 -250 250 -250z" /> - <glyph glyph-name="90" unicode="" horiz-adv-x="600" -d="M300 800c166 0 300 -134 300 -300c0 -200 -300 -500 -300 -500s-300 300 -300 500c0 166 134 300 300 300zM300 700c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200z" /> - <glyph glyph-name="91" unicode="" horiz-adv-x="900" -d="M0 800h800v-541c1 -3 1 -8 1 -11s0 -7 -1 -10v-238h-800v800zM495 250c0 26 22 50 50 50h5h150v400h-600v-600h600v100h-150h-5c-28 0 -50 22 -50 50zM350 600c83 0 150 -67 150 -150c0 -100 -150 -250 -150 -250s-150 150 -150 250c0 83 67 150 150 150zM350 500 -c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" /> - <glyph glyph-name="92" unicode="" horiz-adv-x="600" -d="M0 700h200v-600h-200v600zM400 700h200v-600h-200v600z" /> - <glyph glyph-name="93" unicode="" horiz-adv-x="600" -d="M0 700l600 -300l-600 -300v600z" /> - <glyph glyph-name="94" unicode="" horiz-adv-x="600" -d="M300 700c166 0 300 -134 300 -300s-134 -300 -300 -300s-300 134 -300 300s134 300 300 300z" /> - <glyph glyph-name="95" unicode="" -d="M400 700v-600l-400 300zM400 400l400 300v-600z" /> - <glyph glyph-name="96" unicode="" -d="M0 700l400 -300l-400 -300v600zM400 100v600l400 -300z" /> - <glyph glyph-name="97" unicode="" -d="M0 700h200v-600h-200v600zM200 400l500 300v-600z" /> - <glyph glyph-name="98" unicode="" -d="M0 700l500 -300l-500 -300v600zM500 100v600h200v-600h-200z" /> - <glyph glyph-name="99" unicode="" horiz-adv-x="600" -d="M0 700h600v-600h-600v600z" /> - <glyph glyph-name="9a" unicode="" -d="M200 800h400v-200h200v-400h-200v-200h-400v200h-200v400h200v200z" /> - <glyph glyph-name="9b" unicode="" -d="M0 700h800v-100h-800v100zM0 403h800v-100h-800v100zM0 103h800v-100h-800v100z" /> - <glyph glyph-name="9c" unicode="" horiz-adv-x="600" -d="M278 700c7 2 13 4 22 4c55 0 100 -45 100 -100v-4v-200c0 -55 -45 -100 -100 -100s-100 45 -100 100v200v2c0 44 35 88 78 98zM34 500h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-50c0 -111 89 -200 200 -200s200 89 200 200v50c0 28 22 50 50 50s50 -22 50 -50v-50 -c0 -148 -109 -270 -250 -294v-106h50c55 0 100 -45 100 -100h-400c0 55 45 100 100 100h50v106c-141 24 -250 146 -250 294v50v2c0 20 15 42 34 48z" /> - <glyph glyph-name="9d" unicode="" -d="M0 500h800v-200h-800v200z" /> - <glyph glyph-name="9e" unicode="" -d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-500c0 -28 -22 -50 -50 -50h-250v-100h100c55 0 100 -45 100 -100h-600c0 55 45 100 100 100h100v100h-250c-28 0 -50 22 -50 50v500v2c0 20 15 42 34 48zM100 600v-400h600v400h-600z" /> - <glyph glyph-name="9f" unicode="" -d="M272 700c-14 -40 -22 -83 -22 -128c0 -221 179 -400 400 -400c45 0 88 8 128 22c-53 -158 -202 -272 -378 -272c-221 0 -400 179 -400 400c0 176 114 325 272 378z" /> - <glyph glyph-name="a0" unicode="" -d="M350 700l150 -150h-100v-150h150v100l150 -150l-150 -150v100h-150v-150h100l-150 -150l-150 150h100v150h-150v-100l-150 150l150 150v-100h150v150h-100z" /> - <glyph glyph-name="a1" unicode="" -d="M800 800v-550c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v206c-201 -6 -327 -27 -400 -50v-397c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v409s100 100 600 100z" /> - <glyph glyph-name="a2" unicode="" horiz-adv-x="700" -d="M499 700c51 0 102 -20 141 -59c78 -78 78 -203 0 -281l-250 -244c-48 -48 -127 -48 -175 0s-48 127 0 175l96 97l69 -69l-90 -94l-7 -3c-10 -10 -10 -28 0 -38s28 -10 38 0l250 247c37 40 39 102 0 141s-104 40 -144 0l-278 -275c-66 -69 -68 -179 0 -247 -c69 -69 181 -69 250 0l9 12l116 113l69 -69l-125 -125c-107 -107 -281 -107 -388 0s-107 281 0 388l278 272c39 39 90 59 141 59z" /> - <glyph glyph-name="a3" unicode="" -d="M600 800l200 -200l-100 -100l-200 200zM400 600l200 -200l-400 -400h-200v200z" /> - <glyph glyph-name="a4" unicode="" -d="M550 800c83 0 150 -90 150 -200s-67 -200 -150 -200c-22 0 -40 8 -59 19c6 26 9 52 9 81c0 84 -27 158 -72 212c27 52 71 88 122 88zM250 700c83 0 150 -90 150 -200s-67 -200 -150 -200s-150 90 -150 200s67 200 150 200zM725 384c44 -22 75 -66 75 -118v-166h-200v66 -c0 50 -17 96 -44 134c66 2 126 33 169 84zM75 284c45 -53 106 -84 175 -84s130 31 175 84c44 -22 75 -66 75 -118v-166h-500v166c0 52 31 96 75 118z" /> - <glyph glyph-name="a5" unicode="" -d="M400 800c110 0 200 -112 200 -250s-90 -250 -200 -250s-200 112 -200 250s90 250 200 250zM191 300c54 -61 128 -100 209 -100s155 39 209 100c106 -5 191 -92 191 -200v-100h-800v100c0 108 85 195 191 200z" /> - <glyph glyph-name="a6" unicode="" horiz-adv-x="600" -d="M19 800h462c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-462c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 700v-500h300v500h-300zM250 150c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" /> - <glyph glyph-name="a7" unicode="" -d="M350 800c17 0 34 -1 50 -3v-397l-297 297c63 64 150 103 247 103zM500 694c169 -25 300 -168 300 -344c0 -193 -157 -350 -350 -350c-85 0 -161 31 -222 81l272 272v341zM91 562l237 -234l-212 -212c-70 55 -116 138 -116 234c0 84 35 158 91 212z" /> - <glyph glyph-name="a8" unicode="" -d="M92 650c0 23 20 50 46 50h3h4h5h400c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-200h100c55 0 100 -45 100 -100h-300v-300l-56 -100l-44 100v300h-300c0 55 45 100 100 100h100v200h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z" /> - <glyph glyph-name="a9" unicode="" -d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 600v-400l300 200z" /> - <glyph glyph-name="aa" unicode="" -d="M300 800h200v-300h300v-200h-300v-300h-200v300h-300v200h300v300z" /> - <glyph glyph-name="ab" unicode="" -d="M300 800h100v-400h-100v400zM172 656l62 -78l-40 -31c-58 -46 -94 -117 -94 -197c0 -139 111 -250 250 -250s250 111 250 250c0 80 -39 151 -97 197l-37 31l62 78l38 -31c82 -64 134 -164 134 -275c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 111 53 211 134 275z -" /> - <glyph glyph-name="ac" unicode="" -d="M200 800h400v-200h-400v200zM9 500h782c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-91v200h-600v-200h-91c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM200 300h400v-300h-400v300z" /> - <glyph glyph-name="ad" unicode="" -d="M0 700h100v-700h-100v700zM700 700h100v-700h-100v700zM200 600h200v-100h-200v100zM300 400h200v-100h-200v100zM400 200h200v-100h-200v100z" /> - <glyph glyph-name="ae" unicode="" -d="M325 700c42 -141 87 -280 131 -419c29 74 59 148 88 222c30 -57 58 -114 87 -172h169v-100h-231l-13 28c-37 -92 -74 -184 -112 -275c-38 129 -79 257 -119 385c-42 -133 -83 -267 -125 -400c-28 88 -56 175 -84 262h-116v100h188l9 -34l3 -6c42 137 83 273 125 409z" /> - <glyph glyph-name="af" unicode="" -d="M200 600c0 57 43 100 100 100s100 -43 100 -100c0 -28 -18 -48 -28 -72c-3 -6 -3 -16 -3 -28h231v-231c12 0 22 0 28 3c24 10 44 28 72 28c57 0 100 -43 100 -100s-43 -100 -100 -100c-28 0 -48 18 -72 28c-6 3 -16 3 -28 3v-231h-231c0 12 0 22 3 28c10 24 28 44 28 72 -c0 57 -43 100 -100 100s-100 -43 -100 -100c0 -28 18 -48 28 -72c3 -6 3 -16 3 -28h-231v600h231c0 12 0 22 -3 28c-10 24 -28 44 -28 72z" /> - <glyph glyph-name="b0" unicode="" horiz-adv-x="500" -d="M247 700c84 0 148 -20 191 -59s59 -93 59 -141c0 -117 -69 -181 -119 -225s-81 -67 -81 -150v-25h-100v25c0 117 65 181 115 225s85 67 85 150c0 25 -8 48 -28 66s-56 34 -122 34s-97 -18 -116 -37s-27 -43 -31 -69l-100 12c5 38 19 88 59 128s103 66 188 66zM197 0h100 -v-100h-100v100z" /> - <glyph glyph-name="b1" unicode="" -d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -69 -48 -127 -112 -144c-22 55 -75 94 -138 94c-20 0 -39 -5 -56 -12c-17 64 -75 112 -144 112s-127 -48 -144 -112c-17 7 -36 12 -56 12c-37 0 -71 -12 -97 -34c-33 36 -53 82 -53 134 +c8 13 27 24 42 24c28 0 50 -22 50 -50c0 -15 -10 -35 -23 -43c-22 -22 -48 -37 -75 -47c-70 -25 -151 -9 -207 47c-78 78 -78 203 0 281l150 150c60 60 128 78 178 76z"/> + <glyph glyph-name="87" unicode="" + d="M0 700h300v-300h-300v300zM400 700h400v-100h-400v100zM400 500h300v-100h-300v100zM0 300h300v-300h-300v300zM400 300h400v-100h-400v100zM400 100h300v-100h-300v100z"/> + <glyph glyph-name="88" unicode="" + d="M50 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 700h600v-100h-600v100zM50 500c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 500h600v-100h-600v100zM50 300c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50 +s22 50 50 50zM200 300h600v-100h-600v100zM50 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM200 100h600v-100h-600v100z"/> + <glyph glyph-name="89" unicode="" + d="M800 800l-400 -800l-100 300l-300 100z"/> + <glyph glyph-name="8a" unicode="" horiz-adv-x="600" + d="M300 700c110 0 200 -90 200 -200v-100h100v-400h-600v400h100v100c0 110 90 200 200 200zM300 600c-56 0 -100 -44 -100 -100v-100h200v100c0 56 -44 100 -100 100z"/> + <glyph glyph-name="8b" unicode="" horiz-adv-x="600" + d="M300 800c110 0 200 -90 200 -200v-200h100v-400h-600v400h400v200c0 56 -44 100 -100 100s-100 -44 -100 -100h-100c0 110 90 200 200 200z"/> + <glyph glyph-name="8c" unicode="" + d="M400 700v-100c-111 0 -200 -89 -200 -200h100l-150 -200l-150 200h100c0 165 135 300 300 300zM650 600l150 -200h-100c0 -165 -135 -300 -300 -300v100c111 0 200 89 200 200h-100z"/> + <glyph glyph-name="8d" unicode="" + d="M100 800h600v-300h100l-150 -250l-150 250h100v200h-400v-100h-100v200zM150 550l150 -250h-100v-200h400v100h100v-200h-600v300h-100z"/> + <glyph glyph-name="8e" unicode="" + d="M600 700l200 -150l-200 -150v100h-500v-100h-100v100c0 55 45 100 100 100h500v100zM200 300v-100h500v100h100v-100c0 -55 -45 -100 -100 -100h-500v-100l-200 150z"/> + <glyph glyph-name="8f" unicode="" horiz-adv-x="900" + d="M350 800c193 0 350 -157 350 -350c0 -60 -17 -117 -44 -166c5 -3 12 -8 16 -12l100 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 100c-4 3 -9 9 -12 13c-49 -26 -107 -41 -166 -41c-193 0 -350 157 -350 350s157 350 350 350zM350 200 +c142 0 250 108 250 250c0 139 -111 250 -250 250s-250 -111 -250 -250s111 -250 250 -250z"/> + <glyph glyph-name="90" unicode="" horiz-adv-x="600" + d="M300 800c166 0 300 -134 300 -300c0 -200 -300 -500 -300 -500s-300 300 -300 500c0 166 134 300 300 300zM300 700c-110 0 -200 -90 -200 -200s90 -200 200 -200s200 90 200 200s-90 200 -200 200z"/> + <glyph glyph-name="91" unicode="" horiz-adv-x="900" + d="M0 800h800v-541c1 -3 1 -8 1 -11s0 -7 -1 -10v-238h-800v800zM495 250c0 26 22 50 50 50h5h150v400h-600v-600h600v100h-150h-5c-28 0 -50 22 -50 50zM350 600c83 0 150 -67 150 -150c0 -100 -150 -250 -150 -250s-150 150 -150 250c0 83 67 150 150 150zM350 500 +c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/> + <glyph glyph-name="92" unicode="" horiz-adv-x="600" + d="M0 700h200v-600h-200v600zM400 700h200v-600h-200v600z"/> + <glyph glyph-name="93" unicode="" horiz-adv-x="600" + d="M0 700l600 -300l-600 -300v600z"/> + <glyph glyph-name="94" unicode="" horiz-adv-x="600" + d="M300 700c166 0 300 -134 300 -300s-134 -300 -300 -300s-300 134 -300 300s134 300 300 300z"/> + <glyph glyph-name="95" unicode="" + d="M400 700v-600l-400 300zM400 400l400 300v-600z"/> + <glyph glyph-name="96" unicode="" + d="M0 700l400 -300l-400 -300v600zM400 100v600l400 -300z"/> + <glyph glyph-name="97" unicode="" + d="M0 700h200v-600h-200v600zM200 400l500 300v-600z"/> + <glyph glyph-name="98" unicode="" + d="M0 700l500 -300l-500 -300v600zM500 100v600h200v-600h-200z"/> + <glyph glyph-name="99" unicode="" horiz-adv-x="600" + d="M0 700h600v-600h-600v600z"/> + <glyph glyph-name="9a" unicode="" + d="M200 800h400v-200h200v-400h-200v-200h-400v200h-200v400h200v200z"/> + <glyph glyph-name="9b" unicode="" + d="M0 700h800v-100h-800v100zM0 403h800v-100h-800v100zM0 103h800v-100h-800v100z"/> + <glyph glyph-name="9c" unicode="" horiz-adv-x="600" + d="M278 700c7 2 13 4 22 4c55 0 100 -45 100 -100v-4v-200c0 -55 -45 -100 -100 -100s-100 45 -100 100v200v2c0 44 35 88 78 98zM34 500h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-50c0 -111 89 -200 200 -200s200 89 200 200v50c0 28 22 50 50 50s50 -22 50 -50v-50 +c0 -148 -109 -270 -250 -294v-106h50c55 0 100 -45 100 -100h-400c0 55 45 100 100 100h50v106c-141 24 -250 146 -250 294v50v2c0 20 15 42 34 48z"/> + <glyph glyph-name="9d" unicode="" + d="M0 500h800v-200h-800v200z"/> + <glyph glyph-name="9e" unicode="" + d="M34 700h4h3h4h5h700c28 0 50 -22 50 -50v-500c0 -28 -22 -50 -50 -50h-250v-100h100c55 0 100 -45 100 -100h-600c0 55 45 100 100 100h100v100h-250c-28 0 -50 22 -50 50v500v2c0 20 15 42 34 48zM100 600v-400h600v400h-600z"/> + <glyph glyph-name="9f" unicode="" + d="M272 700c-14 -40 -22 -83 -22 -128c0 -221 179 -400 400 -400c45 0 88 8 128 22c-53 -158 -202 -272 -378 -272c-221 0 -400 179 -400 400c0 176 114 325 272 378z"/> + <glyph glyph-name="a0" unicode="" + d="M350 700l150 -150h-100v-150h150v100l150 -150l-150 -150v100h-150v-150h100l-150 -150l-150 150h100v150h-150v-100l-150 150l150 150v-100h150v150h-100z"/> + <glyph glyph-name="a1" unicode="" + d="M800 800v-550c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v206c-201 -6 -327 -27 -400 -50v-397c0 -83 -67 -150 -150 -150s-150 67 -150 150s67 150 150 150c17 0 35 -4 50 -9v409s100 100 600 100z"/> + <glyph glyph-name="a2" unicode="" horiz-adv-x="700" + d="M499 700c51 0 102 -20 141 -59c78 -78 78 -203 0 -281l-250 -244c-48 -48 -127 -48 -175 0s-48 127 0 175l96 97l69 -69l-90 -94l-7 -3c-10 -10 -10 -28 0 -38s28 -10 38 0l250 247c37 40 39 102 0 141s-104 40 -144 0l-278 -275c-66 -69 -68 -179 0 -247 +c69 -69 181 -69 250 0l9 12l116 113l69 -69l-125 -125c-107 -107 -281 -107 -388 0s-107 281 0 388l278 272c39 39 90 59 141 59z"/> + <glyph glyph-name="a3" unicode="" + d="M600 800l200 -200l-100 -100l-200 200zM400 600l200 -200l-400 -400h-200v200z"/> + <glyph glyph-name="a4" unicode="" + d="M550 800c83 0 150 -90 150 -200s-67 -200 -150 -200c-22 0 -40 8 -59 19c6 26 9 52 9 81c0 84 -27 158 -72 212c27 52 71 88 122 88zM250 700c83 0 150 -90 150 -200s-67 -200 -150 -200s-150 90 -150 200s67 200 150 200zM725 384c44 -22 75 -66 75 -118v-166h-200v66 +c0 50 -17 96 -44 134c66 2 126 33 169 84zM75 284c45 -53 106 -84 175 -84s130 31 175 84c44 -22 75 -66 75 -118v-166h-500v166c0 52 31 96 75 118z"/> + <glyph glyph-name="a5" unicode="" + d="M400 800c110 0 200 -112 200 -250s-90 -250 -200 -250s-200 112 -200 250s90 250 200 250zM191 300c54 -61 128 -100 209 -100s155 39 209 100c106 -5 191 -92 191 -200v-100h-800v100c0 108 85 195 191 200z"/> + <glyph glyph-name="a6" unicode="" horiz-adv-x="600" + d="M19 800h462c11 0 19 -8 19 -19v-762c0 -11 -8 -19 -19 -19h-462c-11 0 -19 8 -19 19v762c0 11 8 19 19 19zM100 700v-500h300v500h-300zM250 150c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/> + <glyph glyph-name="a7" unicode="" + d="M350 800c17 0 34 -1 50 -3v-397l-297 297c63 64 150 103 247 103zM500 694c169 -25 300 -168 300 -344c0 -193 -157 -350 -350 -350c-85 0 -161 31 -222 81l272 272v341zM91 562l237 -234l-212 -212c-70 55 -116 138 -116 234c0 84 35 158 91 212z"/> + <glyph glyph-name="a8" unicode="" + d="M92 650c0 23 20 50 46 50h3h4h5h400c28 0 50 -22 50 -50s-22 -50 -50 -50h-50v-200h100c55 0 100 -45 100 -100h-300v-300l-56 -100l-44 100v300h-300c0 55 45 100 100 100h100v200h-50c-2 0 -6 -1 -8 -1c-28 0 -50 23 -50 51z"/> + <glyph glyph-name="a9" unicode="" + d="M400 800c221 0 400 -179 400 -400s-179 -400 -400 -400s-400 179 -400 400s179 400 400 400zM300 600v-400l300 200z"/> + <glyph glyph-name="aa" unicode="" + d="M300 800h200v-300h300v-200h-300v-300h-200v300h-300v200h300v300z"/> + <glyph glyph-name="ab" unicode="" + d="M300 800h100v-400h-100v400zM172 656l62 -78l-40 -31c-58 -46 -94 -117 -94 -197c0 -139 111 -250 250 -250s250 111 250 250c0 80 -39 151 -97 197l-37 31l62 78l38 -31c82 -64 134 -164 134 -275c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 111 53 211 134 275z +"/> + <glyph glyph-name="ac" unicode="" + d="M200 800h400v-200h-400v200zM9 500h782c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-91v200h-600v-200h-91c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM200 300h400v-300h-400v300z"/> + <glyph glyph-name="ad" unicode="" + d="M0 700h100v-700h-100v700zM700 700h100v-700h-100v700zM200 600h200v-100h-200v100zM300 400h200v-100h-200v100zM400 200h200v-100h-200v100z"/> + <glyph glyph-name="ae" unicode="" + d="M325 700c42 -141 87 -280 131 -419c29 74 59 148 88 222c30 -57 58 -114 87 -172h169v-100h-231l-13 28c-37 -92 -74 -184 -112 -275c-38 129 -79 257 -119 385c-42 -133 -83 -267 -125 -400c-28 88 -56 175 -84 262h-116v100h188l9 -34l3 -6c42 137 83 273 125 409z"/> + <glyph glyph-name="af" unicode="" + d="M200 600c0 57 43 100 100 100s100 -43 100 -100c0 -28 -18 -48 -28 -72c-3 -6 -3 -16 -3 -28h231v-231c12 0 22 0 28 3c24 10 44 28 72 28c57 0 100 -43 100 -100s-43 -100 -100 -100c-28 0 -48 18 -72 28c-6 3 -16 3 -28 3v-231h-231c0 12 0 22 3 28c10 24 28 44 28 72 +c0 57 -43 100 -100 100s-100 -43 -100 -100c0 -28 18 -48 28 -72c3 -6 3 -16 3 -28h-231v600h231c0 12 0 22 -3 28c-10 24 -28 44 -28 72z"/> + <glyph glyph-name="b0" unicode="" horiz-adv-x="500" + d="M247 700c84 0 148 -20 191 -59s59 -93 59 -141c0 -117 -69 -181 -119 -225s-81 -67 -81 -150v-25h-100v25c0 117 65 181 115 225s85 67 85 150c0 25 -8 48 -28 66s-56 34 -122 34s-97 -18 -116 -37s-27 -43 -31 -69l-100 12c5 38 19 88 59 128s103 66 188 66zM197 0h100 +v-100h-100v100z"/> + <glyph glyph-name="b1" unicode="" + d="M450 800c138 0 250 -112 250 -250v-50c58 -21 100 -85 100 -150c0 -69 -48 -127 -112 -144c-22 55 -75 94 -138 94c-20 0 -39 -5 -56 -12c-17 64 -75 112 -144 112s-127 -48 -144 -112c-17 7 -36 12 -56 12c-37 0 -71 -12 -97 -34c-33 36 -53 82 -53 134 c0 110 90 200 200 200c23 114 129 200 250 200zM334 300h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-200c0 -28 -22 -50 -50 -50s-50 22 -50 50v200v2c0 20 15 42 34 48zM134 200h4h3c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-100c0 -28 -22 -50 -50 -50s-50 22 -50 50v100v2 -c0 20 15 42 34 48zM534 200h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-100c0 -28 -22 -50 -50 -50s-50 22 -50 50v100v2c0 20 15 42 34 48z" /> - <glyph glyph-name="b2" unicode="" -d="M600 800l200 -150l-200 -150v100h-50l-153 -191l175 -206l6 -3h22v100l200 -150l-200 -150v100h-25c-35 0 -56 12 -78 38l-166 190l-153 -190c-22 -27 -43 -38 -78 -38h-100v100h100l166 206l-163 191l-3 3h-100v100h100c34 0 56 -12 78 -38l153 -178l141 178 -c22 27 43 38 78 38h50v100z" /> - <glyph glyph-name="b3" unicode="" -d="M400 800c110 0 209 -47 281 -119l119 119v-300h-300l109 109c-54 55 -126 91 -209 91c-166 0 -300 -134 -300 -300s134 -300 300 -300c83 0 158 34 212 88l72 -72c-72 -72 -174 -116 -284 -116c-220 0 -400 180 -400 400s180 400 400 400z" /> - <glyph glyph-name="b4" unicode="" -d="M400 800h400v-400l-166 166l-400 -400l166 -166h-400v400l166 -166l400 400z" /> - <glyph glyph-name="b5" unicode="" horiz-adv-x="600" -d="M250 800l250 -300h-200v-200h200l-250 -300l-250 300h200v200h-200z" /> - <glyph glyph-name="b6" unicode="" -d="M300 600v-200h200v200l300 -250l-300 -250v200h-200v-200l-300 250z" /> - <glyph glyph-name="b7" unicode="" -d="M0 800c441 0 800 -359 800 -800h-200c0 333 -267 600 -600 600v200zM0 500c275 0 500 -225 500 -500h-200c0 167 -133 300 -300 300v200zM0 200c110 0 200 -90 200 -200h-200v200z" /> - <glyph glyph-name="b8" unicode="" -d="M100 800c386 0 700 -314 700 -700h-100c0 332 -268 600 -600 600v100zM100 600c276 0 500 -224 500 -500h-100c0 222 -178 400 -400 400v100zM100 400c165 0 300 -135 300 -300h-100c0 111 -89 200 -200 200v100zM100 200c55 0 100 -45 100 -100s-45 -100 -100 -100 -s-100 45 -100 100s45 100 100 100z" /> - <glyph glyph-name="b9" unicode="" -d="M300 800h400c55 0 100 -45 100 -100v-200h-400v150c0 28 -22 50 -50 50s-50 -22 -50 -50v-250h400v-300c0 -55 -45 -100 -100 -100h-500c-55 0 -100 45 -100 100v200h100v-150c0 -28 22 -50 50 -50s50 22 50 50v550c0 55 45 100 100 100z" /> - <glyph glyph-name="ba" unicode="" -d="M75 700h225v-100h-200v-500h400v100h100v-125c0 -41 -34 -75 -75 -75h-450c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM600 700l200 -200l-200 -200v100h-200c-94 0 -173 -65 -194 -153c23 199 189 353 394 353v100z" /> - <glyph glyph-name="bb" unicode="" -d="M500 700l300 -284l-300 -316v200h-100c-200 0 -348 -102 -400 -300c0 295 100 500 500 500v200z" /> - <glyph glyph-name="bc" unicode="" -d="M381 791l19 9l19 -9c127 -53 253 -108 381 -160v-31c0 -166 -67 -313 -147 -419c-40 -53 -83 -97 -125 -128s-82 -53 -128 -53s-86 22 -128 53s-85 75 -125 128c-80 107 -147 253 -147 419v31c128 52 254 107 381 160zM400 100v591l-294 -122c8 -126 58 -243 122 -328 -c35 -46 73 -86 106 -110s62 -31 66 -31z" /> - <glyph glyph-name="bd" unicode="" -d="M600 800h100v-800h-100v800zM400 700h100v-700h-100v700zM200 500h100v-500h-100v500zM0 300h100v-300h-100v300z" /> - <glyph glyph-name="be" unicode="" -d="M300 800h100v-200h200l100 -100l-100 -100h-200v-400h-100v500h-200l-100 100l100 100h200v100z" /> - <glyph glyph-name="bf" unicode="" -d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h200v-100h-200v100zM400 600h300v-100h-300v100zM400 400h400v-100h-400v100z" /> - <glyph glyph-name="c0" unicode="" -d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h400v-100h-400v100zM400 600h300v-100h-300v100zM400 400h200v-100h-200v100z" /> - <glyph glyph-name="c1" unicode="" -d="M75 700h650c41 0 75 -34 75 -75v-550c0 -41 -34 -75 -75 -75h-650c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM100 600v-100h100v100h-100zM300 600v-100h400v100h-400zM100 400v-100h100v100h-100zM300 400v-100h400v100h-400zM100 200v-100h100v100h-100zM300 200 -v-100h400v100h-400z" /> - <glyph glyph-name="c2" unicode="" -d="M400 800l100 -300h300l-250 -200l100 -300l-250 200l-250 -200l100 300l-250 200h300z" /> - <glyph glyph-name="c3" unicode="" -d="M400 800c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM150 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM650 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 600c110 0 200 -90 200 -200 +c0 20 15 42 34 48zM534 200h3h4c3 0 6 1 9 1c28 0 50 -22 50 -50v-1v-100c0 -28 -22 -50 -50 -50s-50 22 -50 50v100v2c0 20 15 42 34 48z"/> + <glyph glyph-name="b2" unicode="" + d="M600 800l200 -150l-200 -150v100h-50l-153 -191l175 -206l6 -3h22v100l200 -150l-200 -150v100h-25c-35 0 -56 12 -78 38l-166 190l-153 -190c-22 -27 -43 -38 -78 -38h-100v100h100l166 206l-163 191l-3 3h-100v100h100c34 0 56 -12 78 -38l153 -178l141 178 +c22 27 43 38 78 38h50v100z"/> + <glyph glyph-name="b3" unicode="" + d="M400 800c110 0 209 -47 281 -119l119 119v-300h-300l109 109c-54 55 -126 91 -209 91c-166 0 -300 -134 -300 -300s134 -300 300 -300c83 0 158 34 212 88l72 -72c-72 -72 -174 -116 -284 -116c-220 0 -400 180 -400 400s180 400 400 400z"/> + <glyph glyph-name="b4" unicode="" + d="M400 800h400v-400l-166 166l-400 -400l166 -166h-400v400l166 -166l400 400z"/> + <glyph glyph-name="b5" unicode="" horiz-adv-x="600" + d="M250 800l250 -300h-200v-200h200l-250 -300l-250 300h200v200h-200z"/> + <glyph glyph-name="b6" unicode="" + d="M300 600v-200h200v200l300 -250l-300 -250v200h-200v-200l-300 250z"/> + <glyph glyph-name="b7" unicode="" + d="M0 800c441 0 800 -359 800 -800h-200c0 333 -267 600 -600 600v200zM0 500c275 0 500 -225 500 -500h-200c0 167 -133 300 -300 300v200zM0 200c110 0 200 -90 200 -200h-200v200z"/> + <glyph glyph-name="b8" unicode="" + d="M100 800c386 0 700 -314 700 -700h-100c0 332 -268 600 -600 600v100zM100 600c276 0 500 -224 500 -500h-100c0 222 -178 400 -400 400v100zM100 400c165 0 300 -135 300 -300h-100c0 111 -89 200 -200 200v100zM100 200c55 0 100 -45 100 -100s-45 -100 -100 -100 +s-100 45 -100 100s45 100 100 100z"/> + <glyph glyph-name="b9" unicode="" + d="M300 800h400c55 0 100 -45 100 -100v-200h-400v150c0 28 -22 50 -50 50s-50 -22 -50 -50v-250h400v-300c0 -55 -45 -100 -100 -100h-500c-55 0 -100 45 -100 100v200h100v-150c0 -28 22 -50 50 -50s50 22 50 50v550c0 55 45 100 100 100z"/> + <glyph glyph-name="ba" unicode="" + d="M75 700h225v-100h-200v-500h400v100h100v-125c0 -41 -34 -75 -75 -75h-450c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM600 700l200 -200l-200 -200v100h-200c-94 0 -173 -65 -194 -153c23 199 189 353 394 353v100z"/> + <glyph glyph-name="bb" unicode="" + d="M500 700l300 -284l-300 -316v200h-100c-200 0 -348 -102 -400 -300c0 295 100 500 500 500v200z"/> + <glyph glyph-name="bc" unicode="" + d="M381 791l19 9l19 -9c127 -53 253 -108 381 -160v-31c0 -166 -67 -313 -147 -419c-40 -53 -83 -97 -125 -128s-82 -53 -128 -53s-86 22 -128 53s-85 75 -125 128c-80 107 -147 253 -147 419v31c128 52 254 107 381 160zM400 100v591l-294 -122c8 -126 58 -243 122 -328 +c35 -46 73 -86 106 -110s62 -31 66 -31z"/> + <glyph glyph-name="bd" unicode="" + d="M600 800h100v-800h-100v800zM400 700h100v-700h-100v700zM200 500h100v-500h-100v500zM0 300h100v-300h-100v300z"/> + <glyph glyph-name="be" unicode="" + d="M300 800h100v-200h200l100 -100l-100 -100h-200v-400h-100v500h-200l-100 100l100 100h200v100z"/> + <glyph glyph-name="bf" unicode="" + d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h200v-100h-200v100zM400 600h300v-100h-300v100zM400 400h400v-100h-400v100z"/> + <glyph glyph-name="c0" unicode="" + d="M200 800h100v-600h200l-250 -200l-250 200h200v600zM400 800h400v-100h-400v100zM400 600h300v-100h-300v100zM400 400h200v-100h-200v100z"/> + <glyph glyph-name="c1" unicode="" + d="M75 700h650c41 0 75 -34 75 -75v-550c0 -41 -34 -75 -75 -75h-650c-41 0 -75 34 -75 75v550c0 41 34 75 75 75zM100 600v-100h100v100h-100zM300 600v-100h400v100h-400zM100 400v-100h100v100h-100zM300 400v-100h400v100h-400zM100 200v-100h100v100h-100zM300 200 +v-100h400v100h-400z"/> + <glyph glyph-name="c2" unicode="" + d="M400 800l100 -300h300l-250 -200l100 -300l-250 200l-250 -200l100 300l-250 200h300z"/> + <glyph glyph-name="c3" unicode="" + d="M400 800c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM150 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM650 700c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 600c110 0 200 -90 200 -200 s-90 -200 -200 -200s-200 90 -200 200s90 200 200 200zM50 450c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM750 450c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM150 200c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50 -s22 50 50 50zM650 200c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z" /> - <glyph glyph-name="c4" unicode="" -d="M34 800h632c18 0 34 -16 34 -34v-732c0 -18 -16 -34 -34 -34h-632c-18 0 -34 16 -34 34v732c0 18 16 34 34 34zM100 700v-500h500v500h-500zM350 150c-38 0 -63 -42 -44 -75s69 -33 88 0s-6 75 -44 75z" /> - <glyph glyph-name="c5" unicode="" -d="M0 800h300l500 -500l-300 -300l-500 500v300zM200 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z" /> - <glyph glyph-name="c6" unicode="" -d="M0 600h200l300 -300l-200 -200l-300 300v200zM340 600h160l300 -300l-200 -200l-78 78l119 122zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" /> - <glyph glyph-name="c7" unicode="" -d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200 -s90 200 200 200zM400 500c-56 0 -100 -44 -100 -100s44 -100 100 -100s100 44 100 100s-44 100 -100 100z" /> - <glyph glyph-name="c8" unicode="" -d="M0 700h559l-100 -100h-359v-500h500v159l100 100v-359h-700v700zM700 700l100 -100l-400 -400l-200 200l100 100l100 -100z" /> - <glyph glyph-name="c9" unicode="" -d="M9 800h782c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM150 722l-72 -72l100 -100l-100 -100l72 -72l172 172zM400 500v-100h300v100h-300z" /> - <glyph glyph-name="ca" unicode="" -d="M0 800h800v-200h-50c0 55 -45 100 -100 100h-150v-550c0 -28 22 -50 50 -50h50v-100h-400v100h50c28 0 50 22 50 50v550h-150c-55 0 -100 -45 -100 -100h-50v200z" /> - <glyph glyph-name="cb" unicode="" -d="M0 700h100v-400h-100v400zM200 700h350c21 0 39 -13 47 -31c0 0 103 -291 103 -319s-22 -50 -50 -50h-150c-28 0 -50 -25 -50 -50s39 -158 47 -184s-5 -55 -31 -63s-52 5 -66 31s-109 219 -128 238s-44 28 -72 28v400z" /> - <glyph glyph-name="cc" unicode="" -d="M400 666c10 19 28 32 47 34l19 -3c26 -8 39 -37 31 -63s-47 -159 -47 -184s22 -50 50 -50h150c28 0 50 -22 50 -50s-103 -319 -103 -319c-8 -18 -26 -31 -47 -31h-350v400c28 0 53 9 72 28s114 212 128 238zM0 400h100v-400h-100v400z" /> - <glyph glyph-name="cd" unicode="" -d="M200 700h300v-100h-100v-6c25 -4 50 -8 72 -16l-34 -94c-28 11 -58 16 -88 16c-139 0 -250 -111 -250 -250s111 -250 250 -250s250 111 250 250c0 31 -5 60 -16 88l91 37c14 -38 25 -81 25 -125c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 176 130 323 300 347v3 -h-100v100zM700 584c0 0 -296 -348 -316 -368s-48 -20 -68 0s-20 48 0 68s384 300 384 300z" /> - <glyph glyph-name="ce" unicode="" -d="M600 700l200 -150l-200 -150v100h-600v100h600v100zM200 300v-100h600v-100h-600v-100l-200 150z" /> - <glyph glyph-name="cf" unicode="" -d="M300 800h100c55 0 100 -45 100 -100h100c55 0 100 -45 100 -100h-700c0 55 45 100 100 100h100c0 55 45 100 100 100zM100 500h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-481c0 -11 -8 -19 -19 -19h-462 -c-11 0 -19 8 -19 19v481z" /> - <glyph glyph-name="d0" unicode="" -d="M100 800h200v-400c0 -55 45 -100 100 -100s100 45 100 100v400h100v-400c0 -110 -90 -200 -200 -200h-50c-138 0 -250 90 -250 200v400zM0 100h700v-100h-700v100z" /> - <glyph glyph-name="d1" unicode="" -d="M9 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM609 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282 -c0 6 3 9 9 9zM0 100h800v-100h-800v100z" /> - <glyph glyph-name="d2" unicode="" -d="M10 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 4 9 10 9zM610 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 5 9 10 9zM310 600h181c6 0 9 -3 9 -9v-91h-200v91c0 6 4 9 10 9zM0 400h800v-100h-800v100zM0 200h200v-191c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v191zM300 200 -h200v-91c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v91zM600 200h200v-191c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v191z" /> - <glyph glyph-name="d3" unicode="" -d="M0 700h800v-100h-800v100zM9 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM609 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182 -c-6 0 -9 3 -9 9v482c0 6 3 9 9 9z" /> - <glyph glyph-name="d4" unicode="" -d="M50 600h500c28 0 50 -22 50 -50v-150l100 100h100v-300h-100l-100 100v-150c0 -28 -22 -50 -50 -50h-500c-28 0 -50 22 -50 50v400c0 28 22 50 50 50z" /> - <glyph glyph-name="d5" unicode="" -d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 600v100c26 0 52 -4 75 -10c130 -33 225 -150 225 -290s-95 -258 -225 -291h-3c-23 -6 -47 -9 -72 -9v100c17 0 34 2 50 6c86 22 150 100 150 194s-64 172 -150 194c-16 4 -33 6 -50 6zM500 500l25 -3 -c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z" /> - <glyph glyph-name="d6" unicode="" horiz-adv-x="600" -d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 500l25 -3c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z" /> - <glyph glyph-name="d7" unicode="" horiz-adv-x="400" -d="M334 800h66v-800h-66l-134 200h-200v400h200z" /> - <glyph glyph-name="d8" unicode="" -d="M309 800h82c6 0 10 -4 12 -9l294 -682l3 -19v-81c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v81l3 19l294 682c2 5 6 9 12 9zM300 500v-200h100v200h-100zM300 200v-100h100v100h-100z" /> - <glyph glyph-name="d9" unicode="" -d="M375 800c138 0 269 -39 378 -109l-53 -82c-93 60 -205 91 -325 91c-119 0 -229 -32 -322 -91l-53 82c109 70 237 109 375 109zM375 500c78 0 154 -23 216 -62l-53 -85c-46 30 -104 47 -163 47c-60 0 -112 -17 -159 -47l-54 85c62 40 134 62 213 62zM375 200 -c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z" /> - <glyph glyph-name="da" unicode="" horiz-adv-x="900" -d="M551 800c16 0 32 0 47 -3l-97 -97v-200h200l97 97c3 -15 3 -31 3 -47c0 -138 -112 -250 -250 -250c-32 0 -62 8 -90 19l-288 -291c-20 -20 -46 -28 -72 -28s-52 8 -72 28c-39 39 -39 105 0 144l291 287c-11 28 -19 59 -19 91c0 138 112 250 250 250zM101 150 -c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z" /> - <glyph glyph-name="db" unicode="" -d="M141 700c84 -84 169 -167 253 -250c82 83 167 165 247 250l143 -141l-253 -253c84 -82 167 -166 253 -247l-143 -143c-81 86 -165 169 -247 253l-253 -253l-141 143c85 80 167 164 250 247c-83 84 -166 169 -250 253z" /> - <glyph glyph-name="dc" unicode="" -d="M0 800h100l231 -300h38l231 300h100l-225 -300h225v-100h-300v-100h300v-100h-300v-200h-100v200h-300v100h300v100h-300v100h225z" /> - <glyph glyph-name="dd" unicode="" horiz-adv-x="900" -d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700 -c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM300 600h100v-100h100v-100h-100v-100h-100v100h-100v100h100v100z" /> - <glyph glyph-name="de" unicode="" horiz-adv-x="900" -d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700 -c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM200 500h300v-100h-300v100z" /> - </font> -</defs></svg> +s22 50 50 50zM650 200c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50zM400 100c28 0 50 -22 50 -50s-22 -50 -50 -50s-50 22 -50 50s22 50 50 50z"/> + <glyph glyph-name="c4" unicode="" + d="M34 800h632c18 0 34 -16 34 -34v-732c0 -18 -16 -34 -34 -34h-632c-18 0 -34 16 -34 34v732c0 18 16 34 34 34zM100 700v-500h500v500h-500zM350 150c-38 0 -63 -42 -44 -75s69 -33 88 0s-6 75 -44 75z"/> + <glyph glyph-name="c5" unicode="" + d="M0 800h300l500 -500l-300 -300l-500 500v300zM200 700c-55 0 -100 -45 -100 -100s45 -100 100 -100s100 45 100 100s-45 100 -100 100z"/> + <glyph glyph-name="c6" unicode="" + d="M0 600h200l300 -300l-200 -200l-300 300v200zM340 600h160l300 -300l-200 -200l-78 78l119 122zM150 500c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/> + <glyph glyph-name="c7" unicode="" + d="M400 800c220 0 400 -180 400 -400s-180 -400 -400 -400s-400 180 -400 400s180 400 400 400zM400 700c-166 0 -300 -134 -300 -300s134 -300 300 -300s300 134 300 300s-134 300 -300 300zM400 600c110 0 200 -90 200 -200s-90 -200 -200 -200s-200 90 -200 200 +s90 200 200 200zM400 500c-56 0 -100 -44 -100 -100s44 -100 100 -100s100 44 100 100s-44 100 -100 100z"/> + <glyph glyph-name="c8" unicode="" + d="M0 700h559l-100 -100h-359v-500h500v159l100 100v-359h-700v700zM700 700l100 -100l-400 -400l-200 200l100 100l100 -100z"/> + <glyph glyph-name="c9" unicode="" + d="M9 800h782c6 0 9 -3 9 -9v-782c0 -6 -3 -9 -9 -9h-782c-6 0 -9 3 -9 9v782c0 6 3 9 9 9zM150 722l-72 -72l100 -100l-100 -100l72 -72l172 172zM400 500v-100h300v100h-300z"/> + <glyph glyph-name="ca" unicode="" + d="M0 800h800v-200h-50c0 55 -45 100 -100 100h-150v-550c0 -28 22 -50 50 -50h50v-100h-400v100h50c28 0 50 22 50 50v550h-150c-55 0 -100 -45 -100 -100h-50v200z"/> + <glyph glyph-name="cb" unicode="" + d="M0 700h100v-400h-100v400zM200 700h350c21 0 39 -13 47 -31c0 0 103 -291 103 -319s-22 -50 -50 -50h-150c-28 0 -50 -25 -50 -50s39 -158 47 -184s-5 -55 -31 -63s-52 5 -66 31s-109 219 -128 238s-44 28 -72 28v400z"/> + <glyph glyph-name="cc" unicode="" + d="M400 666c10 19 28 32 47 34l19 -3c26 -8 39 -37 31 -63s-47 -159 -47 -184s22 -50 50 -50h150c28 0 50 -22 50 -50s-103 -319 -103 -319c-8 -18 -26 -31 -47 -31h-350v400c28 0 53 9 72 28s114 212 128 238zM0 400h100v-400h-100v400z"/> + <glyph glyph-name="cd" unicode="" + d="M200 700h300v-100h-100v-6c25 -4 50 -8 72 -16l-34 -94c-28 11 -58 16 -88 16c-139 0 -250 -111 -250 -250s111 -250 250 -250s250 111 250 250c0 31 -5 60 -16 88l91 37c14 -38 25 -81 25 -125c0 -193 -157 -350 -350 -350s-350 157 -350 350c0 176 130 323 300 347v3 +h-100v100zM700 584c0 0 -296 -348 -316 -368s-48 -20 -68 0s-20 48 0 68s384 300 384 300z"/> + <glyph glyph-name="ce" unicode="" + d="M600 700l200 -150l-200 -150v100h-600v100h600v100zM200 300v-100h600v-100h-600v-100l-200 150z"/> + <glyph glyph-name="cf" unicode="" + d="M300 800h100c55 0 100 -45 100 -100h100c55 0 100 -45 100 -100h-700c0 55 45 100 100 100h100c0 55 45 100 100 100zM100 500h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-350c0 -28 22 -50 50 -50s50 22 50 50v350h100v-481c0 -11 -8 -19 -19 -19h-462 +c-11 0 -19 8 -19 19v481z"/> + <glyph glyph-name="d0" unicode="" + d="M100 800h200v-400c0 -55 45 -100 100 -100s100 45 100 100v400h100v-400c0 -110 -90 -200 -200 -200h-50c-138 0 -250 90 -250 200v400zM0 100h700v-100h-700v100z"/> + <glyph glyph-name="d1" unicode="" + d="M9 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM609 700h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282 +c0 6 3 9 9 9zM0 100h800v-100h-800v100z"/> + <glyph glyph-name="d2" unicode="" + d="M10 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 4 9 10 9zM610 700h181c6 0 9 -3 9 -9v-191h-200v191c0 6 5 9 10 9zM310 600h181c6 0 9 -3 9 -9v-91h-200v91c0 6 4 9 10 9zM0 400h800v-100h-800v100zM0 200h200v-191c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v191zM300 200 +h200v-91c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v91zM600 200h200v-191c0 -6 -3 -9 -9 -9h-181c-6 0 -10 3 -10 9v191z"/> + <glyph glyph-name="d3" unicode="" + d="M0 700h800v-100h-800v100zM9 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v482c0 6 3 9 9 9zM309 500h182c6 0 9 -3 9 -9v-282c0 -6 -3 -9 -9 -9h-182c-6 0 -9 3 -9 9v282c0 6 3 9 9 9zM609 500h182c6 0 9 -3 9 -9v-482c0 -6 -3 -9 -9 -9h-182 +c-6 0 -9 3 -9 9v482c0 6 3 9 9 9z"/> + <glyph glyph-name="d4" unicode="" + d="M50 600h500c28 0 50 -22 50 -50v-150l100 100h100v-300h-100l-100 100v-150c0 -28 -22 -50 -50 -50h-500c-28 0 -50 22 -50 50v400c0 28 22 50 50 50z"/> + <glyph glyph-name="d5" unicode="" + d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 600v100c26 0 52 -4 75 -10c130 -33 225 -150 225 -290s-95 -258 -225 -291h-3c-23 -6 -47 -9 -72 -9v100c17 0 34 2 50 6c86 22 150 100 150 194s-64 172 -150 194c-16 4 -33 6 -50 6zM500 500l25 -3 +c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z"/> + <glyph glyph-name="d6" unicode="" horiz-adv-x="600" + d="M334 800h66v-800h-66l-134 200h-200v400h200zM500 500l25 -3c44 -11 75 -51 75 -97s-32 -86 -75 -97l-25 -3v200z"/> + <glyph glyph-name="d7" unicode="" horiz-adv-x="400" + d="M334 800h66v-800h-66l-134 200h-200v400h200z"/> + <glyph glyph-name="d8" unicode="" + d="M309 800h82c6 0 10 -4 12 -9l294 -682l3 -19v-81c0 -6 -3 -9 -9 -9h-682c-6 0 -9 3 -9 9v81l3 19l294 682c2 5 6 9 12 9zM300 500v-200h100v200h-100zM300 200v-100h100v100h-100z"/> + <glyph glyph-name="d9" unicode="" + d="M375 800c138 0 269 -39 378 -109l-53 -82c-93 60 -205 91 -325 91c-119 0 -229 -32 -322 -91l-53 82c109 70 237 109 375 109zM375 500c78 0 154 -23 216 -62l-53 -85c-46 30 -104 47 -163 47c-60 0 -112 -17 -159 -47l-54 85c62 40 134 62 213 62zM375 200 +c55 0 100 -45 100 -100s-45 -100 -100 -100s-100 45 -100 100s45 100 100 100z"/> + <glyph glyph-name="da" unicode="" horiz-adv-x="900" + d="M551 800c16 0 32 0 47 -3l-97 -97v-200h200l97 97c3 -15 3 -31 3 -47c0 -138 -112 -250 -250 -250c-32 0 -62 8 -90 19l-288 -291c-20 -20 -46 -28 -72 -28s-52 8 -72 28c-39 39 -39 105 0 144l291 287c-11 28 -19 59 -19 91c0 138 112 250 250 250zM101 150 +c-28 0 -50 -22 -50 -50s22 -50 50 -50s50 22 50 50s-22 50 -50 50z"/> + <glyph glyph-name="db" unicode="" + d="M141 700c84 -84 169 -167 253 -250c82 83 167 165 247 250l143 -141l-253 -253c84 -82 167 -166 253 -247l-143 -143c-81 86 -165 169 -247 253l-253 -253l-141 143c85 80 167 164 250 247c-83 84 -166 169 -250 253z"/> + <glyph glyph-name="dc" unicode="" + d="M0 800h100l231 -300h38l231 300h100l-225 -300h225v-100h-300v-100h300v-100h-300v-200h-100v200h-300v100h300v100h-300v100h225z"/> + <glyph glyph-name="dd" unicode="" horiz-adv-x="900" + d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700 +c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM300 600h100v-100h100v-100h-100v-100h-100v100h-100v100h100v100z"/> + <glyph glyph-name="de" unicode="" horiz-adv-x="900" + d="M350 800c193 0 350 -157 350 -350c0 -61 -17 -119 -44 -169c4 -2 10 -6 13 -9l103 -100c16 -16 30 -49 30 -72c0 -56 -46 -102 -102 -102c-23 0 -56 14 -72 30l-100 103c-3 3 -7 9 -9 13c-50 -28 -108 -44 -169 -44c-193 0 -350 157 -350 350s157 350 350 350zM350 700 +c-139 0 -250 -111 -250 -250s111 -250 250 -250c62 0 119 23 163 60c7 11 19 25 31 31l3 3c34 43 53 97 53 156c0 139 -111 250 -250 250zM200 500h300v-100h-300v100z"/> + </font> + </defs> +</svg> diff --git a/MatrixRoomUtils.Web/wwwroot/index.html b/MatrixRoomUtils.Web/wwwroot/index.html index eeac69b..f268ac4 100644 --- a/MatrixRoomUtils.Web/wwwroot/index.html +++ b/MatrixRoomUtils.Web/wwwroot/index.html @@ -3,27 +3,27 @@ <head> <meta charset="utf-8"/> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/> + <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/> <title>MatrixRoomUtils.Web</title> <base href="/"/> <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet"/> <link href="css/app.css" rel="stylesheet"/> - <link rel="icon" type="image/png" href="favicon.png"/> + <link href="favicon.png" rel="icon" type="image/png"/> <link href="MatrixRoomUtils.Web.styles.css" rel="stylesheet"/> </head> <body> <div id="app"> <svg class="loading-progress"> - <circle r="40%" cx="50%" cy="50%"/> - <circle r="40%" cx="50%" cy="50%"/> + <circle cx="50%" cy="50%" r="40%"/> + <circle cx="50%" cy="50%" r="40%"/> </svg> <div class="loading-progress-text"></div> </div> <div id="blazor-error-ui"> An unhandled error has occurred. - <a href="" class="reload">Reload</a> + <a class="reload" href="">Reload</a> <a class="dismiss">🗙</a> </div> <script> |