Files
PS_Launcher/docs/_build_user.js
j.foucher f5f1fe4d36 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>
2026-05-02 12:11:35 +02:00

794 lines
30 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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));