docs: PowerPoint deck for internal admin + end-user guide, embedded in installer

Two presentations generated from pptxgenjs scripts in docs/, both using
the launcher's dark palette (black bg, #161B23 cards, #3B82F6 blue
accent for internal, #16A34A green accent for the user guide):

- PS_Launcher-Documentation-Interne.pptx (17 slides)
  Cover, sommaire, architecture client/serveur/MySQL, setup OVH initial,
  config.php, génération secrets, backoffice (Dashboard / Licenses /
  Versions / Launcher / Audit), workflow release Proserve, workflow
  release launcher, security (Ed25519 / HMAC / DPAPI), file locations
  + logs, troubleshooting, closing.

- PS_Launcher-Guide-Utilisateur.pptx (14 slides)
  Cover, présentation du launcher, prérequis Windows, installation
  setup.exe (avec gestion SmartScreen), activation license PRSRV-,
  bibliothèque (featured + autres), lancer une version, installer une
  nouvelle version, suivi du DL avec resume, menu ⋯ par version,
  paramètres ⚙, auto-update du launcher, FAQ (license expirée /
  offline / changement PC / SHA-256 KO), support.

Both decks use cards with colored left-accent strips, numbered step
flows, code blocks (Consolas on #0A0E14), and consistent footer
branding "© 2026 ASTERION VR".

installer/PSLauncher.iss now copies the user guide into {app}\docs\
and creates a "Guide utilisateur" Start Menu shortcut next to the
launcher. The internal doc stays in the repo, never shipped to clients.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 12:11:35 +02:00
parent 2dc9c98d1e
commit f5f1fe4d36
6 changed files with 1802 additions and 0 deletions

793
docs/_build_user.js Normal file
View File

@@ -0,0 +1,793 @@
// Generates PS_Launcher-Guide-Utilisateur.pptx
const pptxgen = require("pptxgenjs");
const COL = {
bg: "000000",
card: "161B23",
elev: "1E2632",
border: "2A2F3A",
text: "F2F2F2",
muted: "A0A0A8",
accent: "3B82F6",
accentDk: "1F3A66",
green: "16A34A",
greenDk: "0E2A1B",
amber: "F59E0B",
amberDk: "3A2A0E",
red: "EF4444",
redDk: "2A1414",
codeBg: "0A0E14",
};
const F_TITLE = "Calibri";
const F_BODY = "Calibri";
const F_CODE = "Consolas";
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.author = "ASTERION VR";
pres.title = "PROSERVE Launcher — Guide Utilisateur";
pres.company = "ASTERION VR";
const W = 10, H = 5.625;
// ---- helpers (same as internal but kept local to avoid module fuss) ----
function fillBg(slide) { slide.background = { color: COL.bg }; }
function addHeader(slide, title, kicker) {
slide.addShape(pres.shapes.RECTANGLE, {
x: 0, y: 0, w: W, h: 0.06, fill: { color: COL.green }, line: { type: "none" }
});
if (kicker) {
slide.addText(kicker.toUpperCase(), {
x: 0.5, y: 0.25, w: W - 1, h: 0.3,
fontFace: F_BODY, fontSize: 11, bold: true,
color: COL.green, charSpacing: 4, margin: 0
});
}
slide.addText(title, {
x: 0.5, y: kicker ? 0.55 : 0.35, w: W - 1, h: 0.7,
fontFace: F_TITLE, fontSize: 32, bold: true,
color: COL.text, margin: 0
});
slide.addShape(pres.shapes.LINE, {
x: 0.5, y: kicker ? 1.3 : 1.15, w: 1.2, h: 0,
line: { color: COL.green, width: 2 }
});
}
function addFooter(slide, page) {
slide.addText("PROSERVE Launcher • Guide Utilisateur • ASTERION VR", {
x: 0.5, y: H - 0.35, w: W - 2, h: 0.25,
fontFace: F_BODY, fontSize: 9, color: COL.muted, margin: 0
});
if (page) {
slide.addText(String(page), {
x: W - 1, y: H - 0.35, w: 0.5, h: 0.25,
fontFace: F_BODY, fontSize: 9, color: COL.muted, align: "right", margin: 0
});
}
}
function addCard(slide, x, y, w, h, options = {}) {
slide.addShape(pres.shapes.RECTANGLE, {
x, y, w, h,
fill: { color: options.fill || COL.card },
line: { color: options.border || COL.border, width: 1 },
});
}
function addAccentCard(slide, x, y, w, h, accentColor) {
addCard(slide, x, y, w, h);
slide.addShape(pres.shapes.RECTANGLE, {
x, y, w: 0.08, h,
fill: { color: accentColor }, line: { type: "none" }
});
}
function addCodeBlock(slide, x, y, w, h, lines) {
slide.addShape(pres.shapes.RECTANGLE, {
x, y, w, h, fill: { color: COL.codeBg }, line: { color: COL.border, width: 1 }
});
const text = (Array.isArray(lines) ? lines : [lines]).map((line, i, arr) => ({
text: line,
options: { breakLine: i < arr.length - 1 }
}));
slide.addText(text, {
x: x + 0.15, y: y + 0.1, w: w - 0.3, h: h - 0.2,
fontFace: F_CODE, fontSize: 11, color: COL.text, margin: 0,
valign: "top"
});
}
function addBullets(slide, x, y, w, h, items, opts = {}) {
const fontSize = opts.fontSize || 14;
const color = opts.color || COL.text;
const arr = items.map((it, i) => ({
text: it,
options: { bullet: { code: "25A0" }, breakLine: i < items.length - 1, color }
}));
slide.addText(arr, {
x, y, w, h, fontFace: F_BODY, fontSize, color, margin: 0,
paraSpaceAfter: 6
});
}
// ===================== SLIDE 1: COVER =====================
{
const s = pres.addSlide();
fillBg(s);
// Big band on left
s.addShape(pres.shapes.RECTANGLE, {
x: 0, y: 0, w: 3.5, h: H, fill: { color: COL.greenDk }, line: { type: "none" }
});
s.addShape(pres.shapes.RECTANGLE, {
x: 3.45, y: 0, w: 0.05, h: H, fill: { color: COL.green }, line: { type: "none" }
});
// Brand
s.addText("ASTERION VR", {
x: 0.4, y: 0.5, w: 3, h: 0.4,
fontFace: F_BODY, fontSize: 13, bold: true,
color: COL.green, charSpacing: 8, margin: 0
});
// Big right title
s.addText("PROSERVE", {
x: 3.9, y: 1.3, w: 6, h: 1,
fontFace: F_TITLE, fontSize: 60, bold: true,
color: COL.text, margin: 0
});
s.addText("Launcher", {
x: 3.9, y: 2.1, w: 6, h: 0.7,
fontFace: F_TITLE, fontSize: 40, bold: true,
color: COL.muted, margin: 0
});
s.addText("Guide utilisateur", {
x: 3.9, y: 3.0, w: 6, h: 0.5,
fontFace: F_TITLE, fontSize: 22,
color: COL.green, margin: 0
});
s.addText("Installation, activation et utilisation", {
x: 3.9, y: 3.5, w: 6, h: 0.4,
fontFace: F_BODY, fontSize: 14, italic: true,
color: COL.muted, margin: 0
});
// Left band content
s.addText("v0.8", {
x: 0.4, y: 2, w: 3, h: 1,
fontFace: F_TITLE, fontSize: 56, bold: true,
color: COL.text, align: "center", margin: 0
});
s.addText("Mai 2026", {
x: 0.4, y: 2.95, w: 3, h: 0.3,
fontFace: F_BODY, fontSize: 13,
color: COL.muted, align: "center", margin: 0
});
// Bottom strip
s.addShape(pres.shapes.RECTANGLE, {
x: 0, y: H - 0.5, w: W, h: 0.5, fill: { color: COL.card }, line: { type: "none" }
});
s.addText("© 2026 ASTERION VR — Tous droits réservés", {
x: 0.5, y: H - 0.45, w: W - 1, h: 0.4,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
}
// ===================== SLIDE 2: WHAT IS IT =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Qu'est-ce que PROSERVE Launcher ?", "introduction");
addFooter(s, 2);
s.addText("Une application Windows qui te permet de :", {
x: 0.5, y: 1.4, w: W - 1, h: 0.4,
fontFace: F_BODY, fontSize: 16, color: COL.text, margin: 0
});
const features = [
["📦", "Installer", "Télécharge et déploie chaque nouvelle version de Proserve sur ta machine en quelques clics."],
["▶", "Lancer", "Démarre la version de ton choix. Plusieurs versions peuvent cohabiter sur le même PC."],
["🔄", "Mettre à jour", "Détecte automatiquement les nouvelles versions disponibles côté serveur ASTERION et propose la mise à jour."],
["🔑", "License", "Vérifie ta license en ligne (ou via cache local 7 jours en cas de coupure réseau)."],
];
let y = 2.0;
features.forEach(([icon, title, desc]) => {
addCard(s, 0.5, y, W - 1, 0.7);
s.addText(icon, {
x: 0.7, y: y + 0.13, w: 0.6, h: 0.45,
fontFace: F_TITLE, fontSize: 20, color: COL.green, align: "center", margin: 0
});
s.addText(title, {
x: 1.4, y: y + 0.07, w: 2, h: 0.3,
fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
});
s.addText(desc, {
x: 1.4, y: y + 0.34, w: W - 1.9, h: 0.35,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
y += 0.78;
});
}
// ===================== SLIDE 3: PREREQUISITES =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Pré-requis", "avant de commencer");
addFooter(s, 3);
const prereqs = [
["💻", "Windows 10 ou 11", "Édition 64-bit. Pas de version macOS / Linux pour l'instant."],
["🌐", "Connexion internet", "Requise pour activer la license et télécharger les versions. Le launcher fonctionne hors-ligne pendant 7 jours après la dernière validation."],
["💾", "Espace disque", "Prévoir ~14 Go par version installée + ~14 Go de cache temporaire pendant le téléchargement."],
["🔑", "Une clé license", "Format PRSRV-XXXX-XXXX-XXXX-XXXX, fournie par ASTERION VR."],
];
let y = 1.5;
prereqs.forEach(([icon, title, desc]) => {
addAccentCard(s, 0.5, y, W - 1, 0.85, COL.green);
s.addText(icon, {
x: 0.75, y: y + 0.18, w: 0.7, h: 0.5,
fontFace: F_TITLE, fontSize: 22, color: COL.green, align: "center", margin: 0
});
s.addText(title, {
x: 1.5, y: y + 0.12, w: 6, h: 0.3,
fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
});
s.addText(desc, {
x: 1.5, y: y + 0.42, w: W - 2, h: 0.4,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
y += 0.95;
});
}
// ===================== SLIDE 4: INSTALLATION =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Installation", "première fois");
addFooter(s, 4);
const steps = [
["1", "Télécharge le setup", "Tu reçois un fichier nommé PSLauncher-Setup-X.Y.Z.exe (~80 Mo) — par email, lien WeTransfer, ou via le site ASTERION."],
["2", "Double-clique pour lancer", "Windows peut afficher un avertissement SmartScreen « Éditeur inconnu ».\nClique « Informations complémentaires » → « Exécuter quand même »."],
["3", "Suis l'assistant", "Choisis la langue, valide les chemins par défaut. Le launcher s'installe dans ton profil utilisateur — pas besoin de droits administrateur."],
["4", "Lance PROSERVE Launcher", "Un raccourci apparaît sur le bureau et dans le menu Démarrer."],
];
let y = 1.5;
steps.forEach(([num, title, desc]) => {
addCard(s, 0.5, y, W - 1, 0.85);
s.addShape(pres.shapes.OVAL, {
x: 0.7, y: y + 0.2, w: 0.45, h: 0.45,
fill: { color: COL.green }, line: { type: "none" }
});
s.addText(num, {
x: 0.7, y: y + 0.2, w: 0.45, h: 0.45,
fontFace: F_TITLE, fontSize: 16, bold: true,
color: "FFFFFF", align: "center", valign: "middle", margin: 0
});
s.addText(title, {
x: 1.4, y: y + 0.1, w: W - 2, h: 0.3,
fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
});
s.addText(desc, {
x: 1.4, y: y + 0.4, w: W - 2, h: 0.4,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
y += 0.95;
});
}
// ===================== SLIDE 5: ACTIVATE LICENSE =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Activer ta license", "premier démarrage");
addFooter(s, 5);
s.addText("Au premier lancement, le badge en haut au centre de la fenêtre indique « 🔒 Aucune license » en rouge.", {
x: 0.5, y: 1.4, w: W - 1, h: 0.45,
fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
});
// Badge mockup
addAccentCard(s, 0.5, 1.95, 4.5, 1.6, COL.red);
s.addText("🔒 Aucune license", {
x: 0.7, y: 2.05, w: 4, h: 0.4,
fontFace: F_TITLE, fontSize: 16, bold: true, color: COL.red, margin: 0
});
s.addText("Visible dans la barre du haut au centre", {
x: 0.7, y: 2.4, w: 4, h: 0.3,
fontFace: F_BODY, fontSize: 11, italic: true, color: COL.muted, margin: 0
});
s.addText("👉 Clique dessus !", {
x: 0.7, y: 2.85, w: 4, h: 0.5,
fontFace: F_TITLE, fontSize: 16, bold: true, color: COL.green, margin: 0
});
// Then
addAccentCard(s, 5.2, 1.95, 4.3, 1.6, COL.green);
s.addText("Dialog d'activation", {
x: 5.4, y: 2.05, w: 4, h: 0.3,
fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
});
addBullets(s, 5.4, 2.4, 4, 1.1, [
"Colle ta clé PRSRV-…",
"Clique « Activer »",
"Le badge passe en vert ✓",
], { fontSize: 11 });
// Result
addCard(s, 0.5, 3.85, W - 1, 1.0);
s.addText("Une fois activée :", {
x: 0.7, y: 3.95, w: 4, h: 0.3,
fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.green, margin: 0
});
s.addText("La barre indique le nom du client + la date de validité. Tu peux maintenant télécharger les versions de Proserve auxquelles ta license te donne accès.", {
x: 0.7, y: 4.25, w: W - 1.4, h: 0.6,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
}
// ===================== SLIDE 6: LIBRARY OVERVIEW =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "La fenêtre principale", "ta bibliothèque");
addFooter(s, 6);
// Hero card simulated
addAccentCard(s, 0.5, 1.4, W - 1, 1.2, COL.green);
s.addText("VERSION COURANTE", {
x: 0.75, y: 1.5, w: 4, h: 0.3,
fontFace: F_BODY, fontSize: 10, bold: true, color: COL.muted, charSpacing: 4, margin: 0
});
s.addText("Proserve v1.4.7", {
x: 0.75, y: 1.78, w: 5, h: 0.5,
fontFace: F_TITLE, fontSize: 24, bold: true, color: COL.text, margin: 0
});
s.addText("● Installée • Sortie le 29/04/2026 • 14 Go", {
x: 0.75, y: 2.25, w: 5, h: 0.3,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
// Big launcher button mockup
s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
x: 7.4, y: 1.7, w: 1.8, h: 0.6,
fill: { color: COL.green }, line: { type: "none" }, rectRadius: 0.05
});
s.addText("▶ LANCER", {
x: 7.4, y: 1.7, w: 1.8, h: 0.6,
fontFace: F_TITLE, fontSize: 16, bold: true,
color: "FFFFFF", align: "center", valign: "middle", margin: 0
});
// Section header
s.addText("AUTRES VERSIONS", {
x: 0.5, y: 2.85, w: 3, h: 0.3,
fontFace: F_BODY, fontSize: 10, bold: true, color: COL.muted, charSpacing: 4, margin: 0
});
// Other rows
const rowY1 = 3.2, rowY2 = 4.0;
addAccentCard(s, 0.5, rowY1, W - 1, 0.7, COL.green);
s.addText("v1.4.6 ● Installée", {
x: 0.75, y: rowY1 + 0.1, w: 5, h: 0.3,
fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
});
s.addText("14 Go • 15/04/2026", {
x: 0.75, y: rowY1 + 0.4, w: 5, h: 0.3,
fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
});
s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
x: 8.3, y: rowY1 + 0.18, w: 1.05, h: 0.4,
fill: { color: COL.green }, line: { type: "none" }, rectRadius: 0.05
});
s.addText("▶ Lancer", {
x: 8.3, y: rowY1 + 0.18, w: 1.05, h: 0.4,
fontFace: F_BODY, fontSize: 11, bold: true, color: "FFFFFF", align: "center", valign: "middle", margin: 0
});
addAccentCard(s, 0.5, rowY2, W - 1, 0.7, COL.accent);
s.addText("v1.4.5 ○ Disponible", {
x: 0.75, y: rowY2 + 0.1, w: 5, h: 0.3,
fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
});
s.addText("448 Mo • 15/04/2026", {
x: 0.75, y: rowY2 + 0.4, w: 5, h: 0.3,
fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
});
s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
x: 8.1, y: rowY2 + 0.18, w: 1.25, h: 0.4,
fill: { color: COL.accent }, line: { type: "none" }, rectRadius: 0.05
});
s.addText("⬇ Installer", {
x: 8.1, y: rowY2 + 0.18, w: 1.25, h: 0.4,
fontFace: F_BODY, fontSize: 11, bold: true, color: "FFFFFF", align: "center", valign: "middle", margin: 0
});
}
// ===================== SLIDE 7: LAUNCH A VERSION =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Lancer une version", "▶ jouer");
addFooter(s, 7);
s.addText("Deux possibilités :", {
x: 0.5, y: 1.4, w: W - 1, h: 0.3,
fontFace: F_BODY, fontSize: 14, color: COL.text, margin: 0
});
addAccentCard(s, 0.5, 1.85, 4.5, 2.5, COL.green);
s.addText("LA PLUS RÉCENTE", {
x: 0.7, y: 1.95, w: 4, h: 0.3,
fontFace: F_BODY, fontSize: 11, bold: true, color: COL.green, charSpacing: 3, margin: 0
});
s.addText("Le gros bouton vert dans la carte « Version courante » lance la version la plus récente que tu as installée.", {
x: 0.7, y: 2.3, w: 4, h: 1.2,
fontFace: F_BODY, fontSize: 12, color: COL.text, margin: 0
});
s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
x: 0.7, y: 3.55, w: 4, h: 0.6,
fill: { color: COL.green }, line: { type: "none" }, rectRadius: 0.05
});
s.addText("▶ LANCER", {
x: 0.7, y: 3.55, w: 4, h: 0.6,
fontFace: F_TITLE, fontSize: 16, bold: true,
color: "FFFFFF", align: "center", valign: "middle", margin: 0
});
addAccentCard(s, 5.2, 1.85, 4.3, 2.5, COL.green);
s.addText("UNE VERSION ANCIENNE", {
x: 5.4, y: 1.95, w: 4, h: 0.3,
fontFace: F_BODY, fontSize: 11, bold: true, color: COL.green, charSpacing: 3, margin: 0
});
s.addText("Dans la section « Autres versions », chaque ligne installée a son propre bouton ▶ Lancer pour démarrer cette version précisément.", {
x: 5.4, y: 2.3, w: 4, h: 1.5,
fontFace: F_BODY, fontSize: 12, color: COL.text, margin: 0
});
// Behavior
addCard(s, 0.5, 4.55, W - 1, 0.7);
s.addText("", {
x: 0.7, y: 4.65, w: 0.5, h: 0.5,
fontFace: F_TITLE, fontSize: 18, bold: true, color: COL.accent, align: "center", margin: 0
});
s.addText("La fenêtre du launcher se réduit automatiquement dans la barre des tâches pour laisser la place à Proserve.", {
x: 1.2, y: 4.7, w: W - 1.7, h: 0.5,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
}
// ===================== SLIDE 8: INSTALL NEW VERSION =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Installer une nouvelle version", "📦 télécharger");
addFooter(s, 8);
const steps = [
["1", "Vérifie les MAJ", "Bouton « 🔄 Vérifier les MAJ » en bas à gauche.\nLe launcher contacte le serveur et liste les nouvelles versions."],
["2", "Repère la ligne bleue", "Une ligne « ○ Disponible » apparaît avec un bouton bleu « ⬇ Installer X.Y.Z »."],
["3", "Clique « ⬇ Installer »", "Une fenêtre s'ouvre avec les notes de version (Markdown). Lis et clique « Télécharger » pour confirmer."],
["4", "Patience pendant le DL", "La barre de progression en bas montre la vitesse, l'avancement, l'ETA. Tu peux mettre en pause ou annuler."],
["5", "Installation auto", "Une fois le ZIP vérifié (SHA-256), il est extrait dans le dossier d'install à côté des autres versions."],
];
let y = 1.45;
steps.forEach(([num, title, desc]) => {
addCard(s, 0.5, y, W - 1, 0.7);
s.addShape(pres.shapes.OVAL, {
x: 0.7, y: y + 0.13, w: 0.4, h: 0.4,
fill: { color: COL.accent }, line: { type: "none" }
});
s.addText(num, {
x: 0.7, y: y + 0.13, w: 0.4, h: 0.4,
fontFace: F_TITLE, fontSize: 14, bold: true,
color: "FFFFFF", align: "center", valign: "middle", margin: 0
});
s.addText(title, {
x: 1.3, y: y + 0.07, w: 8, h: 0.27,
fontFace: F_TITLE, fontSize: 12, bold: true, color: COL.text, margin: 0
});
s.addText(desc, {
x: 1.3, y: y + 0.32, w: 8, h: 0.4,
fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
});
y += 0.78;
});
}
// ===================== SLIDE 9: PROGRESS / RESUME =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Suivre un téléchargement", "barre du bas");
addFooter(s, 9);
// Mock footer
addCard(s, 0.5, 1.5, W - 1, 0.7);
s.addText("⬇ v1.4.7 : 4,2 / 14,0 Go • 38 Mo/s • ETA 4 min", {
x: 0.75, y: 1.6, w: 7.5, h: 0.3,
fontFace: F_CODE, fontSize: 12, color: COL.muted, margin: 0
});
// Progress bar
s.addShape(pres.shapes.RECTANGLE, {
x: 0.75, y: 1.95, w: 7.5, h: 0.1, fill: { color: "2A2A30" }, line: { type: "none" }
});
s.addShape(pres.shapes.RECTANGLE, {
x: 0.75, y: 1.95, w: 2.25, h: 0.1, fill: { color: COL.accent }, line: { type: "none" }
});
// Cancel button
s.addShape(pres.shapes.ROUNDED_RECTANGLE, {
x: 8.5, y: 1.62, w: 0.85, h: 0.4,
fill: { color: "3A3A40" }, line: { type: "none" }, rectRadius: 0.05
});
s.addText("Annuler", {
x: 8.5, y: 1.62, w: 0.85, h: 0.4,
fontFace: F_BODY, fontSize: 11, color: COL.text, align: "center", valign: "middle", margin: 0
});
// Features
s.addText("Ce que tu peux faire pendant le DL", {
x: 0.5, y: 2.5, w: W - 1, h: 0.3,
fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.text, margin: 0
});
addBullets(s, 0.5, 2.85, W - 1, 1.1, [
"Annuler à tout moment (le ZIP partiel est conservé pour reprendre plus tard)",
"Fermer le launcher : la prochaine ouverture proposera de reprendre",
"Couper le réseau : le launcher attend (retry exponentiel) puis reprend automatiquement",
], { fontSize: 12 });
// Resume callout
addAccentCard(s, 0.5, 4.15, W - 1, 0.95, COL.amber);
s.addText("↻ Reprendre", {
x: 0.75, y: 4.25, w: 2, h: 0.35,
fontFace: F_TITLE, fontSize: 14, bold: true, color: COL.amber, margin: 0
});
s.addText("Un DL interrompu apparaît avec un bouton « ↻ Reprendre (X%) » à la place de « Installer ». Le téléchargement reprend là où il s'était arrêté — pas besoin de tout recommencer.", {
x: 0.75, y: 4.55, w: W - 1.5, h: 0.6,
fontFace: F_BODY, fontSize: 11, color: COL.muted, margin: 0
});
}
// ===================== SLIDE 10: VERSION MENU =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Menu d'une version", "bouton ⋯");
addFooter(s, 10);
s.addText("Le bouton « ⋯ » à droite de chaque ligne ouvre un menu contextuel.", {
x: 0.5, y: 1.4, w: W - 1, h: 0.4,
fontFace: F_BODY, fontSize: 13, color: COL.muted, italic: true, margin: 0
});
// Menu mockup
addCard(s, 0.5, 1.95, 4.5, 2.4);
s.addText("📜 Voir les release notes", {
x: 0.75, y: 2.1, w: 4, h: 0.4,
fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
});
s.addShape(pres.shapes.LINE, {
x: 0.75, y: 2.5, w: 4, h: 0,
line: { color: COL.border, width: 0.5 }
});
s.addText("📁 Ouvrir le dossier", {
x: 0.75, y: 2.6, w: 4, h: 0.4,
fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
});
s.addShape(pres.shapes.LINE, {
x: 0.75, y: 3.0, w: 4, h: 0,
line: { color: COL.border, width: 0.5 }
});
s.addText("🗑 Supprimer cette version…", {
x: 0.75, y: 3.1, w: 4, h: 0.4,
fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
});
// Description
addBullets(s, 5.3, 2.1, 4.2, 2.4, [
"Release notes : disponibles aussi sur les versions non installées",
"Ouvrir le dossier : utile pour vérifier l'installation",
"Supprimer : libère l'espace disque (≈ 14 Go) avec confirmation. Garde tes anciennes versions tant que tu veux pouvoir y revenir.",
], { fontSize: 11 });
// Tip
addAccentCard(s, 0.5, 4.55, W - 1, 0.65, COL.green);
s.addText("✓ Aucune suppression automatique : c'est toujours toi qui décides quand effacer une vieille version.", {
x: 0.75, y: 4.65, w: W - 1.5, h: 0.5,
fontFace: F_BODY, fontSize: 11, color: COL.text, margin: 0
});
}
// ===================== SLIDE 11: SETTINGS =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Paramètres ⚙", "bouton en haut à droite");
addFooter(s, 11);
const sections = [
["🔑", "License", "Statut, propriétaire, date d'expiration. Identifiant machine anonyme (à communiquer à ASTERION en cas de souci de slot machine)."],
["🌐", "Serveur", "URL de l'API ASTERION. À ne changer que si tu y es invité par le support."],
["📁", "Installation", "Dossier où sont posées les versions de Proserve. Par défaut C:\\ASTERION_VR. Bouton « Parcourir » pour changer."],
["💾", "Cache", "Taille du cache de téléchargements. Bouton « Vider » pour libérer de l'espace si besoin."],
["📋", "Logs", "Dossier des logs (.log) — utile en cas de souci, à transmettre au support."],
];
let y = 1.4;
sections.forEach(([icon, title, desc]) => {
addCard(s, 0.5, y, W - 1, 0.7);
s.addText(icon, {
x: 0.7, y: y + 0.12, w: 0.5, h: 0.45,
fontFace: F_TITLE, fontSize: 18, color: COL.green, align: "center", margin: 0
});
s.addText(title, {
x: 1.25, y: y + 0.07, w: 2, h: 0.3,
fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
});
s.addText(desc, {
x: 1.25, y: y + 0.33, w: W - 1.7, h: 0.4,
fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
});
y += 0.78;
});
}
// ===================== SLIDE 12: AUTO-UPDATE =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "Mises à jour du launcher", "🔄 automatiques");
addFooter(s, 12);
s.addText("Le launcher se met à jour tout seul quand ASTERION pousse une nouvelle version.", {
x: 0.5, y: 1.4, w: W - 1, h: 0.4,
fontFace: F_BODY, fontSize: 13, color: COL.text, margin: 0
});
const flow = [
["1", "Détection", "Au démarrage et à chaque clic « Vérifier les MAJ », le launcher contacte le serveur."],
["2", "Notification", "Si une nouvelle version du launcher existe, une popup t'informe et propose de mettre à jour."],
["3", "Téléchargement", "Quelques secondes (le launcher fait ~80 Mo)."],
["4", "Redémarrage automatique", "L'application se ferme, est remplacée, puis se relance avec la nouvelle version."],
];
let y = 1.95;
flow.forEach(([num, title, desc]) => {
addCard(s, 0.5, y, W - 1, 0.65);
s.addShape(pres.shapes.OVAL, {
x: 0.7, y: y + 0.12, w: 0.4, h: 0.4,
fill: { color: COL.green }, line: { type: "none" }
});
s.addText(num, {
x: 0.7, y: y + 0.12, w: 0.4, h: 0.4,
fontFace: F_TITLE, fontSize: 14, bold: true,
color: "FFFFFF", align: "center", valign: "middle", margin: 0
});
s.addText(title, {
x: 1.3, y: y + 0.07, w: 8, h: 0.27,
fontFace: F_TITLE, fontSize: 12, bold: true, color: COL.text, margin: 0
});
s.addText(desc, {
x: 1.3, y: y + 0.32, w: 8, h: 0.32,
fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
});
y += 0.73;
});
addAccentCard(s, 0.5, 4.95, W - 1, 0.5, COL.green);
s.addText("✓ Tu peux toujours refuser et reporter — clique « Plus tard ».", {
x: 0.75, y: 5.0, w: W - 1.5, h: 0.4,
fontFace: F_BODY, fontSize: 11, color: COL.text, margin: 0
});
}
// ===================== SLIDE 13: FAQ =====================
{
const s = pres.addSlide();
fillBg(s);
addHeader(s, "FAQ", "questions fréquentes");
addFooter(s, 13);
const qs = [
["❓", "Ma license est expirée. Que se passe-t-il ?",
"Tu peux toujours utiliser les versions déjà installées. Seul le téléchargement de nouvelles versions est bloqué jusqu'à renouvellement.",
COL.amber],
["❓", "Pas de connexion internet — le launcher marche-t-il ?",
"Oui, pendant 7 jours après la dernière validation en ligne. Au-delà, la license est considérée comme à revérifier.",
COL.accent],
["❓", "Comment changer de PC ?",
"Désactive ta license sur l'ancien (Settings → bouton Désactiver), puis active-la sur le nouveau avec la même clé.",
COL.green],
["❓", "Le téléchargement échoue avec « SHA-256 invalide » ?",
"Réseau bruité ou ZIP modifié côté serveur entre-temps. Le partial est jeté ; le DL recommence proprement au prochain clic.",
COL.red],
];
let y = 1.5;
qs.forEach(([icon, q, a, color]) => {
addAccentCard(s, 0.5, y, W - 1, 0.85, color);
s.addText(icon, {
x: 0.7, y: y + 0.18, w: 0.4, h: 0.45,
fontFace: F_TITLE, fontSize: 16, color, align: "center", margin: 0
});
s.addText(q, {
x: 1.2, y: y + 0.1, w: W - 1.7, h: 0.3,
fontFace: F_TITLE, fontSize: 12, bold: true, color: COL.text, margin: 0
});
s.addText(a, {
x: 1.2, y: y + 0.4, w: W - 1.7, h: 0.45,
fontFace: F_BODY, fontSize: 10, color: COL.muted, margin: 0
});
y += 0.95;
});
}
// ===================== SLIDE 14: SUPPORT =====================
{
const s = pres.addSlide();
fillBg(s);
// Big band
s.addShape(pres.shapes.RECTANGLE, {
x: 0, y: 1.3, w: W, h: 1.3, fill: { color: COL.greenDk }, line: { type: "none" }
});
s.addShape(pres.shapes.RECTANGLE, {
x: 0, y: 1.3, w: W, h: 0.05, fill: { color: COL.green }, line: { type: "none" }
});
s.addText("Besoin d'aide ?", {
x: 0.5, y: 1.55, w: W - 1, h: 0.6,
fontFace: F_TITLE, fontSize: 32, bold: true, color: COL.text, margin: 0
});
s.addText("Contacte ASTERION VR avec ces infos pour un support efficace :", {
x: 0.5, y: 2.1, w: W - 1, h: 0.4,
fontFace: F_BODY, fontSize: 14, italic: true, color: COL.muted, margin: 0
});
// Three cards
const ix = 0.5, iy = 3.05, iw = 3.0, gap = 0.15;
const refs = [
["🔑", "Ta clé license", "PRSRV-XXXX-XXXX-XXXX-XXXX", COL.green],
["💻", "Ton ID machine", "Settings → License\nbouton 📋 Copier", COL.accent],
["📋", "Tes logs", "Settings → Logs\nbouton 📁 Ouvrir", COL.amber],
];
refs.forEach(([icon, title, body, color], i) => {
const x = ix + i * (iw + gap);
addAccentCard(s, x, iy, iw, 1.7, color);
s.addText(icon, {
x: x + 0.2, y: iy + 0.15, w: iw - 0.4, h: 0.45,
fontFace: F_TITLE, fontSize: 22, color, margin: 0
});
s.addText(title, {
x: x + 0.2, y: iy + 0.65, w: iw - 0.4, h: 0.3,
fontFace: F_TITLE, fontSize: 13, bold: true, color: COL.text, margin: 0
});
s.addText(body, {
x: x + 0.2, y: iy + 0.95, w: iw - 0.4, h: 0.7,
fontFace: F_CODE, fontSize: 10, color: COL.muted, margin: 0
});
});
// Footer brand
s.addShape(pres.shapes.RECTANGLE, {
x: 0, y: H - 0.5, w: W, h: 0.5, fill: { color: COL.card }, line: { type: "none" }
});
s.addText("© 2026 ASTERION VR — Tous droits réservés", {
x: 0.5, y: H - 0.45, w: W - 1, h: 0.4,
fontFace: F_BODY, fontSize: 11, color: COL.muted, align: "center", margin: 0
});
}
pres.writeFile({ fileName: "C:\\ASTERION\\GIT\\PS_Launcher\\docs\\PS_Launcher-Guide-Utilisateur.pptx" })
.then(f => console.log("Generated:", f));