hlassiege/darylpublic Fork
⑂ 54ac456
Commits
⬇ Clone ▾
git clone https://git.rickub.com/hlassiege/daryl.git
git clone ssh://git@rickub.com/hlassiege/daryl.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

feat(publish): insert chapters and links above the default description

Keeps the shared block at the bottom of the description.
hlassiege committed 2026-10-13T16:24:55+02:00 Browse files
54ac456 parent: 2739efc
modified web/src/project/steps/DescriptionStep.vue +18 -3
@@ -3,9 +3,11 @@
33 * Description : titre, description et tags de chaque vidéo (la longue et les shorts de la sélection).
44 * La vidéo longue a aussi sa vignette, son test A/B (jusqu'à 3 couples titre + vignette) et ses
55 * chapitres, tirés des marqueurs du montage ; un short montre son passage et peut renvoyer à la longue.
6+ * Ce qu'on insère (chapitres, lien) se place au-dessus de la description par défaut des réglages.
67 */
7-import { computed, ref } from "vue";
8+import { computed, onMounted, ref } from "vue";
89 import { useI18n } from "vue-i18n";
10+import { api } from "../../lib/api";
911 import { usePref } from "../../lib/composables";
1012 import { contentText, contentTextAll, loadChannelLanguage } from "../../lib/content";
1113 import { mmss } from "../../lib/format";
@@ -56,12 +58,25 @@ const removeTag = (t: string) => set({ tags: sel.value!.meta.tags.filter((x) =>
5658 // les textes insérés dans la description sont dans la langue de la chaîne
5759 loadChannelLanguage();
5860
61+// --- la description par défaut (réglages) : le bloc commun, qu'on garde en bas
62+const footer = ref("");
63+onMounted(async () => {
64+ footer.value = (await api<{ description: string }>("/api/settings/publish").catch(() => ({ description: "" }))).description;
65+});
66+/** Ajoute un bloc à la description : juste au-dessus du bloc commun s'il y est, sinon à la fin. */
67+function insert(desc: string, block: string): string {
68+ const at = footer.value ? desc.lastIndexOf(footer.value) : -1;
69+ if (at < 0) return `${desc.trimEnd()}${desc.trim() ? "\n\n" : ""}${block}`;
70+ const head = desc.slice(0, at).trimEnd();
71+ return `${head}${head ? "\n\n" : ""}${block}\n\n${desc.slice(at)}`;
72+}
73+
5974 // --- chapitres (vidéo longue)
6075 const chaptersText = computed(() => (sel.value?.chapters ?? []).map((c) => `${c.t} ${c.label}`).join("\n"));
6176 function insertChapters() {
6277 const m = sel.value!.meta;
6378 if (m.desc.includes("00:00")) return toast(tr("details.chaptersAlready"));
64- set({ desc: `${m.desc.trimEnd()}${m.desc.trim() ? "\n\n" : ""}${contentText("chapters")}\n${chaptersText.value}` });
79+ set({ desc: insert(m.desc, `${contentText("chapters")}\n${chaptersText.value}`) });
6580 toast(tr("details.chaptersInserted"));
6681 }
6782
@@ -74,7 +89,7 @@ function addLongLink() {
7489 const line = `${prefix} ${url || P.longTitle.value}`;
7590 // déjà là, même ajouté quand la chaîne avait une autre langue
7691 if (contentTextAll("fullVideo").some((p) => m.desc.includes(p))) return toast(tr("details.linkAlready"));
77- set({ desc: `${m.desc.trimEnd()}\n\n${line}` });
92+ set({ desc: insert(m.desc, line) });
7893 toast(url ? tr("details.linkAdded") : tr("details.linkPending"));
7994 }
8095
@@ -3,9 +3,11 @@
3 * Description : titre, description et tags de chaque vidéo (la longue et les shorts de la sélection).3 * Description : titre, description et tags de chaque vidéo (la longue et les shorts de la sélection).
4 * La vidéo longue a aussi sa vignette, son test A/B (jusqu'à 3 couples titre + vignette) et ses4 * La vidéo longue a aussi sa vignette, son test A/B (jusqu'à 3 couples titre + vignette) et ses
5 * chapitres, tirés des marqueurs du montage ; un short montre son passage et peut renvoyer à la longue.5 * chapitres, tirés des marqueurs du montage ; un short montre son passage et peut renvoyer à la longue.
6+ * Ce qu'on insère (chapitres, lien) se place au-dessus de la description par défaut des réglages.
6 */7 */
7-import { computed, ref } from "vue";8+import { computed, onMounted, ref } from "vue";
8 import { useI18n } from "vue-i18n";9 import { useI18n } from "vue-i18n";
10+import { api } from "../../lib/api";
9 import { usePref } from "../../lib/composables";11 import { usePref } from "../../lib/composables";
10 import { contentText, contentTextAll, loadChannelLanguage } from "../../lib/content";12 import { contentText, contentTextAll, loadChannelLanguage } from "../../lib/content";
11 import { mmss } from "../../lib/format";13 import { mmss } from "../../lib/format";
@@ -56,12 +58,25 @@ const removeTag = (t: string) => set({ tags: sel.value!.meta.tags.filter((x) =>
56 // les textes insérés dans la description sont dans la langue de la chaîne58 // les textes insérés dans la description sont dans la langue de la chaîne
57 loadChannelLanguage();59 loadChannelLanguage();
58 60
61+// --- la description par défaut (réglages) : le bloc commun, qu'on garde en bas
62+const footer = ref("");
63+onMounted(async () => {
64+ footer.value = (await api<{ description: string }>("/api/settings/publish").catch(() => ({ description: "" }))).description;
65+});
66+/** Ajoute un bloc à la description : juste au-dessus du bloc commun s'il y est, sinon à la fin. */
67+function insert(desc: string, block: string): string {
68+ const at = footer.value ? desc.lastIndexOf(footer.value) : -1;
69+ if (at < 0) return `${desc.trimEnd()}${desc.trim() ? "\n\n" : ""}${block}`;
70+ const head = desc.slice(0, at).trimEnd();
71+ return `${head}${head ? "\n\n" : ""}${block}\n\n${desc.slice(at)}`;
72+}
73+
59 // --- chapitres (vidéo longue)74 // --- chapitres (vidéo longue)
60 const chaptersText = computed(() => (sel.value?.chapters ?? []).map((c) => `${c.t} ${c.label}`).join("\n"));75 const chaptersText = computed(() => (sel.value?.chapters ?? []).map((c) => `${c.t} ${c.label}`).join("\n"));
61 function insertChapters() {76 function insertChapters() {
62 const m = sel.value!.meta;77 const m = sel.value!.meta;
63 if (m.desc.includes("00:00")) return toast(tr("details.chaptersAlready"));78 if (m.desc.includes("00:00")) return toast(tr("details.chaptersAlready"));
64- set({ desc: `${m.desc.trimEnd()}${m.desc.trim() ? "\n\n" : ""}${contentText("chapters")}\n${chaptersText.value}` });79+ set({ desc: insert(m.desc, `${contentText("chapters")}\n${chaptersText.value}`) });
65 toast(tr("details.chaptersInserted"));80 toast(tr("details.chaptersInserted"));
66 }81 }
67 82
@@ -74,7 +89,7 @@ function addLongLink() {
74 const line = `${prefix} ${url || P.longTitle.value}`;89 const line = `${prefix} ${url || P.longTitle.value}`;
75 // déjà là, même ajouté quand la chaîne avait une autre langue90 // déjà là, même ajouté quand la chaîne avait une autre langue
76 if (contentTextAll("fullVideo").some((p) => m.desc.includes(p))) return toast(tr("details.linkAlready"));91 if (contentTextAll("fullVideo").some((p) => m.desc.includes(p))) return toast(tr("details.linkAlready"));
77- set({ desc: `${m.desc.trimEnd()}\n\n${line}` });92+ set({ desc: insert(m.desc, line) });
78 toast(url ? tr("details.linkAdded") : tr("details.linkPending"));93 toast(url ? tr("details.linkAdded") : tr("details.linkPending"));
79 }94 }
80 95