GameLiftPlugin/Source/GameLiftPlugin/Private/SMenu/Containers/SSetupECRRepositorySection.cpp (341 lines of code) (raw):

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "SSetupECRRepositorySection.h" #include <Async/Async.h> #include <iostream> #include "SWidgets/SOnlineHyperlink.h" #include "SWidgets/SNamedRow.h" #include "SWidgets/SSelectionComboBox.h" #include "SWidgets/SInputTextBox.h" #include "IGameLiftCoreModule.h" #include "Settings/UGameLiftSettings.h" #include "Settings/UGameLiftContainersStatus.h" #include "Types/EBootstrapMessageState.h" #include "Types/EContainersDeploymentScenario.h" #include "GameLiftPluginConstants.h" #include "GameLiftPluginStyle.h" #include "SMenu/SGameLiftSettingsAwsAccountMenu.h" #include "SMenu/Containers/SControlBarSection.h" #define LOCTEXT_NAMESPACE "SSetupECRRepositorySection" void SSetupECRRepositorySection::Construct(const FArguments& InArgs) { OnECRUpdateDelegate = InArgs._OnECRUpdateDelegate; ChildSlot [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .Padding(SPadding::Right2x) .AutoWidth() [ SAssignNew(ProgressBar, SProgressBar) ] + SHorizontalBox::Slot() .FillWidth(1.0f) .Padding(SPadding::Bottom5x + SPadding::Right2x) [ SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() [ SNew(SWidgetSwitcher) .WidgetIndex_Lambda([&]() { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return ContainersStatus->DeploymentScenario == (int)EContainersDeploymentScenario::NoContainerImageNoExistingEcrRepo || ContainersStatus->DeploymentScenario == (int)EContainersDeploymentScenario::HaveContainerImageInDocker ? 0 : 1; }) + SWidgetSwitcher::Slot() [ SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() .Padding(SPadding::SectionTitleTopPadding) [ SNew(STextBlock) .Text(Menu::DeployContainers::kCreateECRRepositoryHeader) .AutoWrapText(true) .TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kTitleStyleName) ] + SVerticalBox::Slot() .AutoHeight() .Padding(SPadding::Top3x) [ SNew(STextBlock) .Text(Menu::DeployContainers::kCreateECRRepositoryDescription) .AutoWrapText(true) .TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kParagraph) ] ] + SWidgetSwitcher::Slot() [ SNew(SVerticalBox) + SVerticalBox::Slot() .AutoHeight() .Padding(SPadding::SectionTitleTopPadding) [ SNew(STextBlock) .Text(Menu::DeployContainers::kSetupECRRepositoryHeader) .AutoWrapText(true) .TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kTitleStyleName) ] + SVerticalBox::Slot() .AutoHeight() .Padding(SPadding::Top3x) [ SNew(STextBlock) .Text(Menu::DeployContainers::kSetupECRRepositoryDescription) .AutoWrapText(true) .TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kParagraph) ] ] ] // External links + SVerticalBox::Slot() .AutoHeight() .Padding(SPadding::Top2x) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .HAlign(HAlign_Left) [ SNew(SOnlineHyperlink) .Text(Menu::DeployContainers::kLearnMoreAboutPrivateRepositoryLabel) .Link(Url::kAmazonECRUserGuideLinkUrl) ] ] // Error text box + SVerticalBox::Slot() .AutoHeight() .Padding(SPadding::Top2x) [ CreateShowErrorUI() ] // Repository name row + SVerticalBox::Slot() .AutoHeight() .HAlign(HAlign_Fill) .Padding(SPadding::Top2x) [ SAssignNew(RepoNameRow, SNamedRow) .NameText(Menu::DeployContainers::kRepositoryNameTitle) .RowWidget( SAssignNew(RepoNameTextBlock, STextBlock) .AutoWrapText(true) .TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kParagraph) ) .SecondaryColumnLeftPadding(true) .Visibility(EVisibility::Collapsed) ] // Retry button + SVerticalBox::Slot() .AutoHeight() .HAlign(HAlign_Left) [ SNew(SBox) .Padding(SPadding::Top3x) .Visibility_Lambda([&]() -> EVisibility { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return ContainersStatus->ErrorCreatingECRRepo ? EVisibility::Visible : EVisibility::Collapsed; }) [ SNew(SButton) .OnClicked_Lambda([&]() { ResetUIToNotStarted(); StartSectionWorkflow(); return FReply::Handled(); }) .Content() [ SNew(SBox) .HAlign(HAlign_Center) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() .HAlign(HAlign_Left) .VAlign(VAlign_Center) .Padding(SPadding::Right) [ SNew(SBox) .WidthOverride(Style::kResetIconSize) .HeightOverride(Style::kResetIconSize) [ SNew(SImage) .Image(FGameLiftPluginStyle::Get().GetBrush(Style::Brush::kResetIconName)) ] ] + SHorizontalBox::Slot() .AutoWidth() .HAlign(HAlign_Center) .VAlign(VAlign_Center) [ SNew(STextBlock) .Text(Menu::DeployContainers::kRetryButtonLabel) .TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kButtonNormal) ] ] ] ] ] ] ]; SGameLiftSettingsAwsAccountMenu::OnProfileSelectionChangedMultiDelegate.AddSP(this, &SSetupECRRepositorySection::OnBootstrapStatusChanged); UpdateUIBasedOnCurrentState(); } TSharedRef<SWidget> SSetupECRRepositorySection::CreateShowErrorUI() { TSharedPtr<SHorizontalBox> RowWidget = SNew(SHorizontalBox); RowWidget->AddSlot() .HAlign(HAlign_Left) .VAlign(VAlign_Center) [ SNew(SBox) .WidthOverride(Style::kMessageTextBoxWidth) [ SAssignNew(ErrorTextBlock, STextBlock) .TextStyle(FGameLiftPluginStyle::Get(), Style::Text::kParagraph) .AutoWrapText(true) ] ]; return SNew(SSetupMessage) .Visibility_Lambda([&]() -> EVisibility { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return ContainersStatus->ErrorCreatingECRRepo ? EVisibility::Visible : EVisibility::Collapsed; }) .FailureRowWidget(RowWidget) .SetState(ESetupMessageState::FailureMessage); } void SSetupECRRepositorySection::OnBootstrapStatusChanged(const SGameLiftSettingsAwsAccountMenu* /* Sender */) { UGameLiftSettings* Settings = GetMutableDefault<UGameLiftSettings>(); EBootstrapMessageState BootstrapState = EBootstrapMessageStateFromInt(Settings->BootstrapStatus); if (BootstrapState == EBootstrapMessageState::NoBootstrappedMessage || BootstrapState == EBootstrapMessageState::ActiveMessage) { ProgressBar->ChangeProgressBarUIState(SProgressBar::EProgressBarUIState::NotStart); } } void SSetupECRRepositorySection::UpdateUIBasedOnCurrentState() { FText ECRRepoNameToDisplay = GetECRRepoNameToDisplay(); UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); if (ScenarioNoContainerImageNoExistingEcrRepoNotFinished() || ScenarioNoContainerImageUseExistingEcrRepoNotFinished()) { ProgressBar->ChangeProgressBarUIState(SProgressBar::EProgressBarUIState::NotStart); } else if (ContainersStatus->ErrorCreatingECRRepo) { RepoNameTextBlock->SetText(ECRRepoNameToDisplay); ErrorTextBlock->SetText(ContainersStatus->ErrorMessageCreatingECRRepo); RepoNameRow->SetVisibility(EVisibility::Visible); ProgressBar->ChangeProgressBarUIState(SProgressBar::EProgressBarUIState::ProgressError); } else if (ContainersStatus->IsSetupECRRepoStepFinished) { RepoNameTextBlock->SetText(ECRRepoNameToDisplay); RepoNameRow->SetVisibility(EVisibility::Visible); ProgressBar->ChangeProgressBarUIState(SProgressBar::EProgressBarUIState::ProgressComplete); } else { ResetUIToNotStarted(); } } FText SSetupECRRepositorySection::GetECRRepoNameToDisplay() { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); if (ContainersStatus->DeploymentScenario == (int)EContainersDeploymentScenario::NoContainerImageNoExistingEcrRepo || ContainersStatus->DeploymentScenario == (int)EContainersDeploymentScenario::NoContainerImageUseExistingEcrRepo) { return FText::FromString(ContainersStatus->ECRRepoName); } else { return FText::FromString("gamelift_container_fleet"); } } bool SSetupECRRepositorySection::ScenarioNoContainerImageFinished() { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return ContainersStatus->IsContainerFolderSetup; } bool SSetupECRRepositorySection::IsScenario(int Scenario) { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return ContainersStatus->DeploymentScenario == Scenario; } bool SSetupECRRepositorySection::ScenarioNoContainerImageNoExistingEcrRepoNotFinished() { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return IsScenario((int)EContainersDeploymentScenario::NoContainerImageNoExistingEcrRepo) && !ScenarioNoContainerImageFinished(); } bool SSetupECRRepositorySection::ScenarioNoContainerImageUseExistingEcrRepoNotFinished() { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return IsScenario((int)EContainersDeploymentScenario::NoContainerImageUseExistingEcrRepo) && !ScenarioNoContainerImageFinished(); } bool SSetupECRRepositorySection::ScenarioNoContainerImageNoExistingEcrRepoFinished() { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return IsScenario((int)EContainersDeploymentScenario::NoContainerImageNoExistingEcrRepo) && ScenarioNoContainerImageFinished(); } bool SSetupECRRepositorySection::ScenarioNoContainerImageUseExistingEcrRepoFinished() { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); return IsScenario((int)EContainersDeploymentScenario::NoContainerImageUseExistingEcrRepo) && ScenarioNoContainerImageFinished(); } TTuple<bool, FString> SSetupECRRepositorySection::CreateRepository(FString RepositoryName) { IGameLiftContainersHandler& Handler = IGameLiftCoreModule::Get().GetGameLiftContainersHandler(); UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); GameLiftECRCreateRepositoryResult CreateRepoResult = Handler.CreateRepository(RepositoryName); if (CreateRepoResult.bIsSuccessful) { ContainersStatus->ECRRepoUri = CreateRepoResult.RepoUri; ContainersStatus->ECRRepoName = CreateRepoResult.RepositoryName; ContainersStatus->SaveConfig(); return MakeTuple(true, TEXT("")); } else if (CreateRepoResult.ErrorMessage.Contains("RepositoryAlreadyExistsException")) { GameLiftECRDescribeRepositoriesResult result = Handler.DescribeRepositories(); FString ECRRegistryUrl; FString FirstRepo; result.Repos[0].RepositoryUri.Split(TEXT("/"), &ECRRegistryUrl, &FirstRepo); ECRRegistryUrl += "/"; ECRRegistryUrl += RepositoryName; ContainersStatus->ECRRepoUri = ECRRegistryUrl; ContainersStatus->ECRRepoName = RepositoryName; ContainersStatus->SaveConfig(); return MakeTuple(true, TEXT("")); } else { return MakeTuple(false, CreateRepoResult.ErrorMessage); } } void SSetupECRRepositorySection::StartSectionWorkflow() { FText ECRRepoNameToDisplay = GetECRRepoNameToDisplay(); RepoNameTextBlock->SetText(ECRRepoNameToDisplay); RepoNameRow->SetVisibility(EVisibility::Visible); TTuple<bool, FString> result = CreateRepository(ECRRepoNameToDisplay.ToString()); if (result.Get<0>()) { HandleSetupRepoSucceed(ECRRepoNameToDisplay); } else { HandleSetupRepoFailed(ECRRepoNameToDisplay, result.Get<1>()); } } void SSetupECRRepositorySection::HandleSetupRepoSucceed(FText ECRRepoNameToDisplay) { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); RepoNameTextBlock->SetText(ECRRepoNameToDisplay); RepoNameRow->SetVisibility(EVisibility::Visible); ContainersStatus->IsSetupECRRepoStepFinished = true; ContainersStatus->ErrorCreatingECRRepo = false; ContainersStatus->ErrorMessageCreatingECRRepo = FText::GetEmpty(); ContainersStatus->SaveConfig(); ProgressBar->ChangeProgressBarUIState(SProgressBar::EProgressBarUIState::ProgressComplete); OnECRUpdateDelegate.ExecuteIfBound(); } void SSetupECRRepositorySection::HandleSetupRepoFailed(FText ECRRepoNameToDisplay, FString ErrorMessage) { UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); RepoNameTextBlock->SetText(ECRRepoNameToDisplay); RepoNameRow->SetVisibility(EVisibility::Visible); ContainersStatus->IsSetupECRRepoStepFinished = false; ContainersStatus->ErrorCreatingECRRepo = true; ContainersStatus->ErrorMessageCreatingECRRepo = FText::FromString(ErrorMessage); ContainersStatus->SaveConfig(); ErrorTextBlock->SetText(FText::FromString(ErrorMessage)); ProgressBar->ChangeProgressBarUIState(SProgressBar::EProgressBarUIState::ProgressError); } void SSetupECRRepositorySection::ResetUIToNotStarted() { ProgressBar->ChangeProgressBarUIState(SProgressBar::EProgressBarUIState::NotStart); UGameLiftContainersStatus* ContainersStatus = GetMutableDefault<UGameLiftContainersStatus>(); ContainersStatus->ErrorCreatingECRRepo = false; RepoNameRow->SetVisibility(EVisibility::Collapsed); ContainersStatus->SaveConfig(); } #undef LOCTEXT_NAMESPACE