implement onboarding

This commit is contained in:
marlon-erler
2026-09-29 21:15:11 +02:00
parent fbc40b5e3e
commit 7a532bbf5c
13 changed files with 687 additions and 281 deletions
+1 -3
View File
@@ -615,9 +615,7 @@ function DataReceptionModal(
<div class="flex-row width-100">
<button
class="flex"
on:click={
fileTransferViewModel.correctTransferData
}
on:click={fileTransferViewModel.correctTransferData}
toggle:disabled={
fileTransferViewModel.cannotExitReception
}
+262 -208
View File
@@ -1,222 +1,275 @@
import { ViewController } from "../viewController";
import * as React from "../../react";
import OnboardingViewModel, {
OnboardingModals,
} from "../../ViewModel/Global/onboardingViewModel";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import OnboardingViewModel, {OnboardingModals} from "../../ViewModel/Global/onboardingViewModel";
import {ViewController} from "../viewController";
// MAIN
export function OnboardingModalWrapper(coreViewModel: CoreViewModel, onboardingViewModel: OnboardingViewModel) {
return <div>
{ConnectionModal(coreViewModel, onboardingViewModel)}
{TransferModal(coreViewModel, onboardingViewModel)}
{NameModal(coreViewModel, onboardingViewModel)}
{TransferDataModal(coreViewModel, onboardingViewModel)}
</div>
export function OnboardingModalWrapper(
coreViewModel: CoreViewModel,
onboardingViewModel: OnboardingViewModel,
) {
return (
<div>
{ConnectionModal(coreViewModel, onboardingViewModel)}
{TransferModal(coreViewModel, onboardingViewModel)}
{NameModal(coreViewModel, onboardingViewModel)}
{TransferDataModal(coreViewModel, onboardingViewModel)}
</div>
);
}
function ConnectionModal(coreViewModel: CoreViewModel, onboardingViewModel: OnboardingViewModel) {
function ConnectionModal(
coreViewModel: CoreViewModel,
onboardingViewModel: OnboardingViewModel,
) {
const isPresented = React.createProxyState(
[onboardingViewModel.presentedModal],
() =>
onboardingViewModel.presentedModal.value ==
OnboardingModals.Connection
[onboardingViewModel.presentedModal],
() =>
onboardingViewModel.presentedModal.value ==
OnboardingModals.Connection,
);
const connectionViewModel = onboardingViewModel.connectionViewmodel;
const nextButton = React.createProxyState([connectionViewModel.isConnected], ()=>coreViewModel.translations.onboarding.connectionNextButton(connectionViewModel.isConnected.value));
return <div
class="modal"
toggle:open={isPresented}
>
<div>
<main>
<h2>{coreViewModel.translations.onboarding.connectionHeadline}</h2>
<p class="secondary width-input">{coreViewModel.translations.onboarding.connectionDescription}</p>
<hr></hr>
<label class="tile flex-no">
<span class="icon">cell_tower</span>
<div>
<span>
{coreViewModel.translations.homePage.serverAddress}
</span>
<input
placeholder={
coreViewModel.translations.homePage
.serverAddressPlaceholder
}
bind:value={connectionViewModel.serverAddressInput}
on:enter={connectionViewModel.connect}
></input>
</div>
</label>
<div class="flex-row width-input justify-end">
<button
class="standard width-50"
on:click={connectionViewModel.connect}
toggle:disabled={connectionViewModel.cannotConnect}
>
{coreViewModel.translations.onboarding.connectButton}
</button>
</div>
</main>
<div class="flex-row justify-end">
<button
class="primary width-50"
on:click={onboardingViewModel.showTransferOption}
>
<span
subscribe:innerText={nextButton}
></span>
<span class="icon">
arrow_forward
</span>
</button>
</div>
</div>
</div>
}
function TransferModal(coreViewModel: CoreViewModel, onboardingViewModel: OnboardingViewModel) {
const isPresented = React.createProxyState(
[onboardingViewModel.presentedModal],
() =>
onboardingViewModel.presentedModal.value ==
OnboardingModals.TransferOrNew
const nextButton = React.createProxyState(
[connectionViewModel.isConnected],
() =>
coreViewModel.translations.onboarding.connectionNextButton(
connectionViewModel.isConnected.value,
),
);
return <div
class="modal"
toggle:open={isPresented}
>
<div>
<main>
<h2>{coreViewModel.translations.onboarding.transferOptionsHeadline}</h2>
<p class="secondary width-input">{coreViewModel.translations.onboarding.transferOptionsDescription}</p>
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.onboarding
.connectionHeadline
}
</h2>
<p class="secondary width-input">
{
coreViewModel.translations.onboarding
.connectionDescription
}
</p>
<hr></hr>
<hr></hr>
<div class="flex-column gap">
<button
class="tile"
on:click={onboardingViewModel.showTransferData}
toggle:disabled={onboardingViewModel.cannotTransfer}
>
<div>
{coreViewModel.translations.onboarding.transferOptionTransfer}
</div>
<span class="icon">
arrow_forward
</span>
</button>
<button
class="tile"
on:click={onboardingViewModel.setupNew}
>
<div>
{coreViewModel.translations.onboarding.transferOptionNew}
</div>
<span class="icon">
arrow_forward
</span>
</button>
</div>
</main>
<div class="flex-row">
<button
class="standard width-50"
on:click={onboardingViewModel.open}
>
{coreViewModel.translations.general.backButton}
</button>
</div>
</div>
</div>
<label class="tile flex-no">
<span class="icon">cell_tower</span>
<div>
<span>
{
coreViewModel.translations.homePage
.serverAddress
}
</span>
<input
placeholder={
coreViewModel.translations.homePage
.serverAddressPlaceholder
}
bind:value={
connectionViewModel.serverAddressInput
}
on:enter={connectionViewModel.connect}
></input>
</div>
</label>
<div class="flex-row width-input justify-end">
<button
class="standard width-50"
on:click={connectionViewModel.connect}
toggle:disabled={connectionViewModel.cannotConnect}
>
{
coreViewModel.translations.onboarding
.connectButton
}
</button>
</div>
</main>
<div class="flex-row justify-end">
<button
class="primary width-50"
on:click={onboardingViewModel.showTransferOption}
>
<span subscribe:innerText={nextButton}></span>
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
);
}
function NameModal(coreViewModel: CoreViewModel, onboardingViewModel: OnboardingViewModel) {
function TransferModal(
coreViewModel: CoreViewModel,
onboardingViewModel: OnboardingViewModel,
) {
const isPresented = React.createProxyState(
[onboardingViewModel.presentedModal],
() =>
onboardingViewModel.presentedModal.value ==
OnboardingModals.Name
[onboardingViewModel.presentedModal],
() =>
onboardingViewModel.presentedModal.value ==
OnboardingModals.TransferOrNew,
);
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{
coreViewModel.translations.onboarding
.transferOptionsHeadline
}
</h2>
<p class="secondary width-input">
{
coreViewModel.translations.onboarding
.transferOptionsDescription
}
</p>
<hr></hr>
<div class="flex-column gap">
<button
class="tile"
on:click={onboardingViewModel.showTransferData}
toggle:disabled={onboardingViewModel.cannotTransfer}
>
<div>
{
coreViewModel.translations.onboarding
.transferOptionTransfer
}
</div>
<span class="icon">arrow_forward</span>
</button>
<button
class="tile"
on:click={onboardingViewModel.setupNew}
>
<div>
{
coreViewModel.translations.onboarding
.transferOptionNew
}
</div>
<span class="icon">arrow_forward</span>
</button>
</div>
</main>
<div class="flex-row">
<button
class="standard width-50"
on:click={onboardingViewModel.open}
>
{coreViewModel.translations.general.backButton}
</button>
</div>
</div>
</div>
);
}
function NameModal(
coreViewModel: CoreViewModel,
onboardingViewModel: OnboardingViewModel,
) {
const isPresented = React.createProxyState(
[onboardingViewModel.presentedModal],
() => onboardingViewModel.presentedModal.value == OnboardingModals.Name,
);
const settingsViewModel = onboardingViewModel.settingsViewModel;
return <div
class="modal"
toggle:open={isPresented}
>
<div>
<main>
<h2>{coreViewModel.translations.onboarding.nameHeadline}</h2>
<p class="secondary width-input">{coreViewModel.translations.onboarding.nameDescription}</p>
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{coreViewModel.translations.onboarding.nameHeadline}
</h2>
<p class="secondary width-input">
{coreViewModel.translations.onboarding.nameDescription}
</p>
<hr></hr>
<hr></hr>
<label class="tile flex-no">
<span class="icon">account_circle</span>
<div>
<span>
{
coreViewModel.translations.settings.account
.yourNameLabel
}
</span>
<input
placeholder={
coreViewModel.translations.settings.account
.yourNamePlaceholder
}
bind:value={settingsViewModel.usernameInput}
></input>
</div>
</label>
</main>
<div class="flex-row">
<button
class="standard width-50"
on:click={onboardingViewModel.showTransferOption}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary width-50"
on:click={onboardingViewModel.finish}
>
{coreViewModel.translations.general.setButton}
<span class="icon">
arrow_forward
</span>
</button>
</div>
</div>
</div>
<label class="tile flex-no">
<span class="icon">account_circle</span>
<div>
<span>
{
coreViewModel.translations.settings.account
.yourNameLabel
}
</span>
<input
placeholder={
coreViewModel.translations.settings.account
.yourNamePlaceholder
}
bind:value={settingsViewModel.usernameInput}
></input>
</div>
</label>
</main>
<div class="flex-row">
<button
class="standard width-50"
on:click={onboardingViewModel.showTransferOption}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary width-50"
on:click={onboardingViewModel.finish}
>
{coreViewModel.translations.general.setButton}
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
);
}
function TransferDataModal(coreViewModel: CoreViewModel, onboardingViewModel: OnboardingViewModel) {
function TransferDataModal(
coreViewModel: CoreViewModel,
onboardingViewModel: OnboardingViewModel,
) {
const isPresented = React.createProxyState(
[onboardingViewModel.presentedModal],
() =>
onboardingViewModel.presentedModal.value ==
OnboardingModals.Transfer
[onboardingViewModel.presentedModal],
() =>
onboardingViewModel.presentedModal.value ==
OnboardingModals.Transfer,
);
const fileTransferViewModel = onboardingViewModel.fileTransferViewModel;
return <div
class="modal"
toggle:open={isPresented}
>
<div>
<main>
<h2>{coreViewModel.translations.onboarding.transferHeadline}</h2>
<p class="secondary width-input">{coreViewModel.translations.onboarding.transferDescription}</p>
return (
<div class="modal" toggle:open={isPresented}>
<div>
<main>
<h2>
{coreViewModel.translations.onboarding.transferHeadline}
</h2>
<p class="secondary width-input">
{
coreViewModel.translations.onboarding
.transferDescription
}
</p>
<hr></hr>
<hr></hr>
<div class="flex-column gap content-margin-bottom">
<label class="tile">
@@ -262,25 +315,26 @@ function TransferDataModal(coreViewModel: CoreViewModel, onboardingViewModel: On
</div>
</label>
</div>
</main>
<div class="flex-row">
<button
class="standard width-50"
on:click={onboardingViewModel.showTransferOption}
toggle:disabled={fileTransferViewModel.cannotExitReception}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary width-50"
on:click={onboardingViewModel.transferData}
>
{coreViewModel.translations.onboarding.transferButton}
<span class="icon">
check
</span>
</button>
</div>
</div>
</div>
</main>
<div class="flex-row">
<button
class="standard width-50"
on:click={onboardingViewModel.showTransferOption}
toggle:disabled={
fileTransferViewModel.cannotExitReception
}
>
{coreViewModel.translations.general.backButton}
</button>
<button
class="primary width-50"
on:click={onboardingViewModel.transferData}
>
{coreViewModel.translations.onboarding.transferButton}
<span class="icon">arrow_forward</span>
</button>
</div>
</div>
</div>
);
}
+85 -19
View File
@@ -113,28 +113,33 @@ const englishTranslations = {
},
onboarding: {
connectionHeadline: "Connect to UDN",
connectionDescription: "To transfer files and send messages, connect to the Universal Decentralized Network (UDN).",
connectButton: "Connect",
connectionNextButton: (isConnected: boolean) => isConnected ? "Continue" : "Continue without UDN",
connectionHeadline: "Connect to UDN",
connectionDescription:
"To transfer files and send messages, connect to the Universal Decentralized Network (UDN).",
connectButton: "Connect",
connectionNextButton: (isConnected: boolean): string =>
isConnected ? "Continue" : "Set up without UDN",
///
transferOptionsHeadline: "Copy Your Data",
transferOptionsDescription: "If you already use the Coordination Tool on another device, copy your identity here. You can use both devices at the same time.",
transferOptionTransfer: "Copy here",
transferOptionNew: "Set up as new device",
///
//
nameHeadline: "Your Name",
nameDescription: "This is what others see when you send messages. You can always change your name in settings.",
transferOptionsHeadline: "Copy Your Data",
transferOptionsDescription:
"If you already use the Coordination Tool on another device, copy your identity here. You can use both devices at the same time.",
transferOptionTransfer: "Copy my data here",
transferOptionNew: "Set up as new device",
//
transferHeadline: "Data Transfer",
transferDescription: 'On your other device, prepare to transfer your identity and personal data alongside any chats you wish to copy. Then, enter the displayed data here.',
transferButton: "Copy data",
//
nameHeadline: "Your Name",
nameDescription:
"This is what others see when you send messages. You can always change your name in settings.",
//
transferHeadline: "Data Transfer",
transferDescription:
"On your other device, prepare to transfer your identity and personal data alongside any chats you wish to copy. Then, enter the displayed data here. You can find the data transfer on the home screen of the other device.",
transferButton: "Copy data",
},
connectionModal: {
@@ -487,6 +492,36 @@ export const allTranslations: {
},
},
onboarding: {
connectionHeadline: "Mit UDN verbinden",
connectionDescription:
"Um Daten und Nachichten zu verschicken, verbinde dich mit dem Universellen Dezentralen Netzwerk (UDN).",
connectButton: "Verbinden",
connectionNextButton: (isConnected: boolean) =>
isConnected ? "Weiter" : "Ohne UDN einrichten",
///
transferOptionsHeadline: "Deine Daten kopieren",
transferOptionsDescription:
"Wenn du Coordination Tool bereits auf einem anderen Gerät verwendest, kopiere deine Kontodaten. Du kannst beide Geräte gleichzeitig verwenden.",
transferOptionTransfer: "Daten übertragen",
transferOptionNew: "Als neues Gerät enrichten",
//
nameHeadline: "Dein Name",
nameDescription:
"Diesen Namen sehen andere, wenn du Nachrichten versendest. Du kannst deinen Namen jederzeit in den Einstellungen ändern.",
//
transferHeadline: "Datenübertragung",
transferDescription:
"Verwende die Funktion zur Datenübertragung auf deinem anderen Getät, um deine Identität und persönlichen Daten zu kopieren. Gib die dazu angezeigten Daten unten ein. Du findest die Datenübertragung auf der Startseite des anderen Geräts.",
transferButton: "Daten kopieren",
},
connectionModal: {
connectionModalHeadline: "Verbindungen verwalten",
@@ -804,6 +839,37 @@ export const allTranslations: {
checkUpdatesButton: "Buscar actualisaciones",
},
},
onboarding: {
connectionHeadline: "Conectar al UDN",
connectionDescription:
"Para transferir datos y enviar mensajes, conéctate a la Red Descentralizada Universal (UDN).",
connectButton: "Conectar",
connectionNextButton: (isConnected: boolean): string =>
isConnected ? "Continuar" : "Configurar sin UDN",
///
transferOptionsHeadline: "Copiar tus datos",
transferOptionsDescription:
"Si ya usas el Coordination Tool en otro disposistivo, copia tu idantidad aquí. Puedes usar ambos dispositivos al mismo tiempo.",
transferOptionTransfer: "Copiar mis datos aquí",
transferOptionNew: "Configurar como dispositivo nuevo",
//
nameHeadline: "Tu nombre",
nameDescription:
"Esto es lo que ven otros cuando envías menajes. Siempre lo puedes cambiar en las ajustes.",
//
transferHeadline: "Transferencia de datos",
transferDescription:
"En el otro dispositivo, prepara la transferencia de tu identidad y datos personales. Ingresa los datos que se muestran a continuación. La opción de la transferencia de datos se encuentra en la pantalla inicial en el otro dispositivo.",
transferButton: "Copiar datos",
},
connectionModal: {
connectionModalHeadline: "Gestionar Conexiones",