@page "/profile" @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.Extensions.Configuration @attribute [Authorize] @inject ISessionStore SessionStore @inject AuthorizedSessionService AuthorizedSessionService @inject IConfiguration Configuration @inject NavigationManager Navigation Профиль — GM-Relay
@if (!string.IsNullOrWhiteSpace(errorMessage)) {
@errorMessage
} @if (!string.IsNullOrWhiteSpace(successMessage)) {
@successMessage
} @if (masterProfile is null) {
} else {

Публичный профиль мастера

Показывается в каталоге, опубликованных играх и публичных страницах клуба.

@(masterProfile.IsPublic ? "Публичный" : "Скрыт")
Латиница, цифры и дефисы, например "night-city-gm".
@if (PublicMasterProfileUrl is not null) { Открыть публичный профиль }
@if (PublicMasterProfileUrl is not null) { }
}

Связанные аккаунты

Аккаунты Telegram и Discord, привязанные к вашему профилю.

@if (identities is null) {
} else if (identities.Count == 0) {
Аккаунты не найдены

Привяжите Telegram или Discord, чтобы управлять профилем.

} else { }

Добавить аккаунт

Привяжите дополнительные платформы для входа.

@if (!HasLinkedPlatform("Discord")) { } else {

Discord уже привязан.

} @if (currentPlatform == "Discord" && !HasLinkedPlatform("Telegram")) { var botUsername = Configuration["Telegram__BotUsername"] ?? Configuration["Telegram:BotUsername"]; if (!string.IsNullOrWhiteSpace(botUsername)) { var authUrl = new Uri(new Uri(Navigation.BaseUri), "auth/telegram").ToString(); var widgetHtml = $"";
@((MarkupString)widgetHtml)
} }
@code { private List? identities; private MasterProfileSettings? masterProfile; private string? currentPlatform; private string? currentExternalUserId; private bool isUnlinking; private bool savingMasterProfile; private string? errorMessage; private string? successMessage; private MasterProfileEditModel masterProfileModel = new(); [CascadingParameter] private Task? AuthenticationStateTask { get; set; } [SupplyParameterFromQuery] public string? Linked { get; set; } [SupplyParameterFromQuery(Name = "link_error")] public string? LinkError { get; set; } protected override async Task OnInitializedAsync() { if (AuthenticationStateTask is not null) { var authState = await AuthenticationStateTask; var user = authState.User; if (user.TryGetPlatformIdentity(out var plat, out var extId)) { currentPlatform = plat; currentExternalUserId = extId; } } if (!string.IsNullOrWhiteSpace(Linked)) { successMessage = $"{Linked} аккаунт успешно привязан!"; } if (!string.IsNullOrWhiteSpace(LinkError)) { errorMessage = $"Ошибка привязки: {Uri.UnescapeDataString(LinkError)}"; } await LoadIdentities(); await LoadMasterProfile(); } private async Task LoadIdentities() { try { if (currentPlatform is not null && currentExternalUserId is not null) { identities = await SessionStore.GetLinkedIdentitiesAsync(currentPlatform, currentExternalUserId); } else { identities = []; } } catch (Exception ex) { errorMessage = $"Не удалось загрузить аккаунты: {ex.Message}"; } } private async Task LoadMasterProfile() { try { masterProfile = await AuthorizedSessionService.GetMasterProfileSettingsForCurrentUserAsync(); if (masterProfile is not null) { masterProfileModel = new MasterProfileEditModel { DisplayName = masterProfile.DisplayName, PublicSlug = masterProfile.PublicSlug ?? string.Empty, IsPublic = masterProfile.IsPublic, Bio = masterProfile.Bio ?? string.Empty }; } } catch (Exception ex) { errorMessage = $"Не удалось загрузить профиль мастера: {ex.Message}"; } } private string? PublicMasterProfileUrl => masterProfile?.IsPublic == true && !string.IsNullOrWhiteSpace(masterProfile.PublicSlug) ? Navigation.ToAbsoluteUri($"/gm/{masterProfile.PublicSlug}").ToString() : null; private async Task SaveMasterProfile() { savingMasterProfile = true; errorMessage = null; successMessage = null; try { await AuthorizedSessionService.UpdateMasterProfileSettingsForCurrentUserAsync( masterProfileModel.PublicSlug, masterProfileModel.IsPublic, masterProfileModel.DisplayName, masterProfileModel.Bio); successMessage = "Публичный профиль мастера обновлён."; await LoadMasterProfile(); } catch (Exception ex) { errorMessage = $"Не удалось сохранить профиль мастера: {ex.Message}"; } finally { savingMasterProfile = false; } } private bool HasLinkedPlatform(string platform) { return identities?.Any(i => i.Platform == platform) ?? false; } private async Task Unlink(string platform, string externalUserId) { isUnlinking = true; errorMessage = null; successMessage = null; try { if (currentPlatform is null || currentExternalUserId is null) { errorMessage = "Не удалось определить текущего пользователя."; return; } await SessionStore.UnlinkIdentityAsync(currentPlatform, currentExternalUserId, platform, externalUserId); successMessage = $"{platform} аккаунт отвязан."; await LoadIdentities(); } catch (InvalidOperationException ex) { errorMessage = $"Ошибка отвязки: {ex.Message}"; } catch (Exception ex) { errorMessage = $"Ошибка отвязки: {ex.Message}"; } finally { isUnlinking = false; } } private sealed class MasterProfileEditModel { public string DisplayName { get; set; } = string.Empty; public string PublicSlug { get; set; } = string.Empty; public bool IsPublic { get; set; } public string Bio { get; set; } = string.Empty; } }