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>
794 lines
30 KiB
JavaScript
794 lines
30 KiB
JavaScript
// 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));
|