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

133 lines
3.7 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">
<div class="w-16 h-16 mx-auto bg-[var(--rebreak-primary)] rounded-xl flex items-center justify-center mb-4">
<UIcon name="i-heroicons-qr-code" class="w-8 h-8 text-white" />
</div>
<h1 class="text-2xl font-bold text-gray-900">
Schutz-Profil installieren
</h1>
<p class="text-gray-600 mt-2">
Scanne den QR-Code mit deinem iPhone und installiere das Schutz-Profil.
</p>
</div>
<UCard class="text-center">
<div class="space-y-4">
<UButton
v-if="!serverInfo"
size="lg"
color="primary"
block
:loading="starting"
@click="startServer"
>
QR-Code generieren
</UButton>
<div v-else class="space-y-4">
<div class="bg-white p-4 rounded-lg inline-block">
<img :src="qrCodeDataUrl" alt="QR Code" class="w-48 h-48">
</div>
<p class="text-sm text-gray-500 break-all">
{{ serverInfo.url }}
</p>
<UButton
size="sm"
color="neutral"
variant="ghost"
@click="stopServer"
>
Server stoppen
</UButton>
</div>
<p v-if="error" class="text-sm text-red-600">
{{ error }}
</p>
</div>
</UCard>
<div class="bg-blue-50 text-blue-800 text-sm p-4 rounded-lg">
<p class="font-semibold mb-1">So geht's:</p>
<ol class="list-decimal list-inside space-y-1">
<li>iPhone-Kamera öffnen und QR-Code scannen</li>
<li>Link in Safari öffnen</li>
<li>Einstellungen" → „Profil installieren" tippen</li>
<li>Geräte-Passcode eingeben und bestätigen</li>
</ol>
</div>
<div class="flex justify-between">
<UButton to="/supervise" variant="ghost" color="neutral">
Zurück
</UButton>
<UButton to="/enroll" variant="solid" color="primary" :disabled="!serverInfo">
Weiter
</UButton>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, onUnmounted } from "vue";
import QRCode from "qrcode";
import { useTauri, type LocalServerInfo } from "~/composables/useTauri";
import { useMagicSession } from "~/composables/useMagicState";
const { startLocalProfileServer, stopLocalProfileServer, downloadProfile } = useTauri();
const session = useMagicSession();
const starting = ref(false);
const serverInfo = ref<LocalServerInfo | null>(null);
const qrCodeDataUrl = ref("");
const error = ref<string | null>(null);
watch(
serverInfo,
async (info) => {
if (info) {
qrCodeDataUrl.value = await QRCode.toDataURL(info.qr_payload, {
width: 192,
margin: 2,
});
} else {
qrCodeDataUrl.value = "";
}
},
{ immediate: true },
);
onUnmounted(async () => {
if (serverInfo.value) {
await stopLocalProfileServer();
}
});
async function startServer() {
starting.value = true;
error.value = null;
try {
if (!session.value?.profileUrl) {
error.value = "Kein Profil verfügbar. Bitte zuerst das iPhone koppeln.";
return;
}
const profilePath = await downloadProfile(session.value.profileUrl);
serverInfo.value = await startLocalProfileServer(profilePath);
} catch (e: any) {
error.value = e?.message ?? "QR-Code konnte nicht erzeugt werden";
} finally {
starting.value = false;
}
}
async function stopServer() {
await stopLocalProfileServer();
serverInfo.value = null;
}
</script>