mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-02-20 07:54:10 -05:00
222 lines
11 KiB
Plaintext
222 lines
11 KiB
Plaintext
@page "/welcome"
|
|
@inherits MainBase
|
|
@using AliasVault.Shared.Core.BrowserExtensions
|
|
@using AliasVault.Shared.Core.MobileApps
|
|
@using Microsoft.Extensions.Localization
|
|
|
|
<div class="bg-gray-100 dark:bg-gray-900 flex flex-col lg:items-center lg:justify-center">
|
|
<div class="w-full mt-4 lg:mt-16 mx-auto lg:max-w-4xl lg:bg-white lg:dark:bg-gray-800 lg:shadow-xl lg:rounded-lg lg:overflow-hidden flex flex-col">
|
|
<div class="flex flex-col flex-grow">
|
|
<div class="flex-grow p-6 pt-4 lg:pt-6 lg:pb-4">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<div class="flex-grow text-center">
|
|
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">@GetStepTitle(_currentStep)</h2>
|
|
</div>
|
|
</div>
|
|
|
|
@if (GetProgressPercentage() > 0)
|
|
{
|
|
<div class="w-full bg-gray-200 rounded-full h-2.5 mb-4 dark:bg-gray-700 mt-4">
|
|
<div class="bg-primary-600 h-2.5 rounded-full" style="width: @(GetProgressPercentage())%"></div>
|
|
</div>
|
|
}
|
|
|
|
@switch (_currentStep)
|
|
{
|
|
case TutorialStep.Welcome:
|
|
<div class="space-y-4">
|
|
<p class="text-gray-600 dark:text-gray-400">
|
|
@Localizer["WelcomeMessage"]
|
|
</p>
|
|
</div>
|
|
break;
|
|
|
|
case TutorialStep.HowAliasVaultWorks:
|
|
<div class="space-y-4">
|
|
<p class="text-gray-600 dark:text-gray-400">
|
|
@Localizer["HowItWorksIntro"]
|
|
</p>
|
|
<ol class="list-decimal list-inside space-y-2 text-gray-600 dark:text-gray-400">
|
|
<li>@Localizer["HowItWorksStep1"]</li>
|
|
<li>@Localizer["HowItWorksStep2"]</li>
|
|
<li>@Localizer["HowItWorksStep3"]</li>
|
|
<li>@Localizer["HowItWorksStep4"]</li>
|
|
</ol>
|
|
</div>
|
|
break;
|
|
|
|
case TutorialStep.Tips:
|
|
<div class="space-y-4">
|
|
<div class="space-y-3">
|
|
<div class="p-4 bg-gray-50 dark:bg-gray-700 rounded-lg">
|
|
<h4 class="font-semibold text-gray-900 dark:text-white">@Localizer["MasterPasswordTipTitle"]</h4>
|
|
<p class="text-gray-600 dark:text-gray-400">
|
|
@Localizer["MasterPasswordTipContent"]
|
|
</p>
|
|
</div>
|
|
<div class="p-4 bg-gray-50 dark:bg-gray-700 rounded-lg">
|
|
<h4 class="font-semibold text-gray-900 dark:text-white">@Localizer["TwoFactorTipTitle"]</h4>
|
|
<p class="text-gray-600 dark:text-gray-400">@Localizer["TwoFactorTipContent"]</p>
|
|
</div>
|
|
<div class="p-4 bg-gray-50 dark:bg-gray-700 rounded-lg">
|
|
<h4 class="font-semibold text-gray-900 dark:text-white">@Localizer["ExtensionsAppsTipTitle"]</h4>
|
|
<p class="text-gray-600 dark:text-gray-400 mb-4">@Localizer["ExtensionsAppsTipContent"]</p>
|
|
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3">
|
|
@foreach (var extension in AliasVault.Shared.Core.BrowserExtensions.Constants.Extensions.Where(x => x.Key != BrowserType.Unknown).Select(x => x.Value))
|
|
{
|
|
@if (extension.IsAvailable)
|
|
{
|
|
<a href="@extension.DownloadUrl"
|
|
target="_blank"
|
|
class="flex flex-col items-center p-3 rounded-lg bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 transition-colors">
|
|
<img src="@extension.IconPath" alt="@extension.Name" class="w-8 h-8 mb-2">
|
|
<span class="text-xs text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300">
|
|
@extension.Name
|
|
</span>
|
|
</a>
|
|
}
|
|
else
|
|
{
|
|
<div class="flex flex-col items-center p-3 rounded-lg bg-gray-200 dark:bg-gray-600">
|
|
<img src="@extension.IconPath" alt="@extension.Name" class="w-8 h-8 mb-2 opacity-50">
|
|
<span class="text-xs text-gray-500 dark:text-gray-400">
|
|
@Localizer["ComingSoonLabel"]
|
|
</span>
|
|
</div>
|
|
}
|
|
}
|
|
@foreach (var app in AliasVault.Shared.Core.MobileApps.Constants.MobileApps)
|
|
{
|
|
@if (app.IsAvailable)
|
|
{
|
|
<a href="@app.DownloadUrl"
|
|
target="_blank"
|
|
class="flex flex-col items-center p-3 rounded-lg bg-gray-200 dark:bg-gray-600 hover:bg-gray-300 dark:hover:bg-gray-500 transition-colors">
|
|
<img src="@app.IconPath" alt="@app.Name" class="w-8 h-8 mb-2">
|
|
<span class="text-xs text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300">
|
|
@app.Name
|
|
</span>
|
|
</a>
|
|
}
|
|
else
|
|
{
|
|
<div class="flex flex-col items-center p-3 rounded-lg bg-gray-200 dark:bg-gray-600">
|
|
<img src="@app.IconPath" alt="@app.Name" class="w-8 h-8 mb-2 opacity-50">
|
|
<span class="text-xs text-gray-500 dark:text-gray-400">
|
|
@app.Name @Localizer["SoonSuffix"]
|
|
</span>
|
|
</div>
|
|
}
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
break;
|
|
|
|
case TutorialStep.CreateFirstIdentity:
|
|
<div class="space-y-4">
|
|
<h3 class="text-2xl font-bold text-gray-900 dark:text-white">@Localizer["ReadyToStartTitle"]</h3>
|
|
<p class="text-gray-600 dark:text-gray-400">
|
|
@Localizer["ReadyToStartMessage"]
|
|
</p>
|
|
<div class="mt-4">
|
|
<button @onclick="CreateFirstIdentity"
|
|
class="w-full bg-primary-600 hover:bg-primary-700 text-white font-semibold py-3 px-4 rounded-lg transition duration-300">
|
|
@Localizer["CreateFirstIdentityButton"]
|
|
</button>
|
|
</div>
|
|
</div>
|
|
break;
|
|
}
|
|
</div>
|
|
|
|
<div class="fixed lg:relative bottom-0 left-0 right-0 p-4 bg-gray-100 dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 lg:bg-transparent lg:dark:bg-transparent lg:border-0">
|
|
@if (_currentStep != TutorialStep.Tips)
|
|
{
|
|
<button @onclick="GoNext"
|
|
class="w-full py-3 px-4 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition duration-300">
|
|
@Localizer["ContinueButton"]
|
|
</button>
|
|
}
|
|
else
|
|
{
|
|
<button @onclick="FinishTutorial"
|
|
class="w-full py-3 px-4 bg-green-600 hover:bg-green-700 text-white font-semibold rounded-lg transition duration-300">
|
|
@Localizer["GetStartedButton"]
|
|
</button>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@code {
|
|
private IStringLocalizer Localizer => LocalizerFactory.Create("Pages.Main.Welcome", "AliasVault.Client");
|
|
|
|
private TutorialStep _currentStep = TutorialStep.Welcome;
|
|
|
|
private enum TutorialStep
|
|
{
|
|
Welcome,
|
|
HowAliasVaultWorks,
|
|
Tips,
|
|
CreateFirstIdentity
|
|
}
|
|
|
|
private string GetStepTitle(TutorialStep step)
|
|
{
|
|
return step switch
|
|
{
|
|
TutorialStep.Welcome => Localizer["WelcomeStepTitle"],
|
|
TutorialStep.HowAliasVaultWorks => Localizer["HowAliasVaultWorksStepTitle"],
|
|
TutorialStep.Tips => Localizer["TipsStepTitle"],
|
|
TutorialStep.CreateFirstIdentity => Localizer["GetStartedStepTitle"],
|
|
_ => Localizer["TutorialStepTitle"]
|
|
};
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await base.OnInitializedAsync();
|
|
|
|
// If tutorial is already done, redirect to the home page.
|
|
if (DbService.Settings.TutorialDone)
|
|
{
|
|
NavigationManager.NavigateTo("/");
|
|
}
|
|
}
|
|
|
|
private async Task GoNext()
|
|
{
|
|
_currentStep = _currentStep switch
|
|
{
|
|
TutorialStep.Welcome => TutorialStep.HowAliasVaultWorks,
|
|
TutorialStep.HowAliasVaultWorks => TutorialStep.Tips,
|
|
TutorialStep.Tips => TutorialStep.CreateFirstIdentity,
|
|
_ => _currentStep
|
|
};
|
|
|
|
await JsInteropService.ScrollToTop();
|
|
}
|
|
|
|
private void CreateFirstIdentity()
|
|
{
|
|
NavigationManager.NavigateTo("items/create");
|
|
}
|
|
|
|
private async Task FinishTutorial()
|
|
{
|
|
GlobalLoadingSpinner.Show(Localizer["FinishingTutorialMessage"]);
|
|
await DbService.Settings.SetTutorialDoneAsync(true);
|
|
NavigationManager.NavigateTo("items");
|
|
GlobalLoadingSpinner.Hide();
|
|
}
|
|
|
|
private int GetProgressPercentage()
|
|
{
|
|
return (int)_currentStep * 100 / (Enum.GetValues(typeof(TutorialStep)).Length - 1);
|
|
}
|
|
}
|