chahinebrini 2919ce45b8 feat(magic): sync current ReBreak Magic app state
Include recent Magic app work: Tauri native shell, iOS device detection
via supervise-magic sidecar, MDM client, local HTTP server, new pages
(detect, enroll, supervise, sideload, pair, preflight, configure, done),
and updated device section/status UI.
2026-06-18 05:23:26 +02:00

132 lines
3.5 KiB
Vue

<template>
<div class="min-h-screen flex flex-col items-center justify-center bg-gray-50 p-6">
<div class="max-w-md w-full space-y-6">
<div class="text-center">
<h1 class="text-2xl font-bold text-gray-900">Pairing-Code</h1>
<p class="text-gray-600 mt-2">
Erstelle in der ReBreak-App einen 6-stelligen Pairing-Code.
</p>
</div>
<UCard>
<div class="space-y-6">
<div class="flex justify-center">
<UPinInput
v-model="code"
:length="6"
type="numeric"
otp
autofocus
placeholder="0"
class="font-mono text-lg"
:disabled="loading"
@complete="redeem"
/>
</div>
<UButton
color="primary"
block
:loading="loading"
:disabled="codeString.length < 6 || loading"
@click="redeem"
>
{{ loading ? "Wird geladen…" : "Koppeln" }}
</UButton>
<div v-if="loading && loadingMessage" class="flex items-center justify-center gap-2 text-sm text-gray-600">
<UIcon name="i-heroicons-arrow-path" class="w-4 h-4 animate-spin text-[var(--rebreak-primary)]" />
<span>{{ loadingMessage }}</span>
</div>
<p v-else-if="error" class="text-sm text-center text-red-600">
{{ error }}
</p>
</div>
</UCard>
<UButton to="/" variant="ghost" color="neutral" block :disabled="loading">
Zurück
</UButton>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from "vue";
import { useTauri } from "~/composables/useTauri";
import { useMagicSession, useMagicDevices } from "~/composables/useMagicState";
const {
redeemPairingCode,
getPlatform,
getHardwareId,
registerDevice,
fetchMe,
getMagicDevices,
getMagicStatus,
} = useTauri();
const session = useMagicSession();
const devices = useMagicDevices();
// UPinInput can return either a string or an array of characters
const code = ref<string | string[]>("");
const loading = ref(false);
const error = ref<string | null>(null);
const loadingMessage = ref<string | null>(null);
const codeString = computed(() => {
if (Array.isArray(code.value)) {
return code.value.join("");
}
return code.value;
});
async function redeem() {
const value = codeString.value;
if (value.length < 6) return;
loading.value = true;
loadingMessage.value = "Pairing-Code wird eingelöst…";
error.value = null;
try {
await redeemPairingCode(value);
loadingMessage.value = "Registriere dieses Gerät…";
const [platformInfo, hardwareId] = await Promise.all([
getPlatform(),
getHardwareId(),
]);
const registered = await registerDevice(platformInfo.platform, platformInfo.version);
session.value = {
deviceId: registered.deviceId,
hardwareId,
dnsToken: registered.dnsToken,
profileUrl: registered.profileUrl,
};
loadingMessage.value = "Lade Profil und Geräte…";
const [_, deviceList] = await Promise.all([
fetchMe(),
getMagicDevices(),
]);
devices.value = deviceList;
loadingMessage.value = "Prüfe Schutzstatus…";
await getMagicStatus(registered.dnsToken);
await navigateTo("/status");
} catch (e: any) {
error.value = e?.message ?? "Koppeln fehlgeschlagen";
loadingMessage.value = null;
} finally {
loading.value = false;
}
}
</script>