feat: ajouter système de filtres visuels pour notes avec 8 effets CSS (glassmorphism, vignette, ligné, quadrillé, noise, points, rayures), intégration dans Background Studio avec palette dédiée, support thème clair/sombre, et synchronisation complète avec tags notefilter- pour persistance
This commit is contained in:
parent
97f3bbca45
commit
7bd618fe38
@ -1557,4 +1557,177 @@ body.view-notes .content-container {
|
|||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center bottom;
|
background-position: center bottom;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================
|
||||||
|
Note Filter Effects (8 CSS filters)
|
||||||
|
========================================= */
|
||||||
|
|
||||||
|
/* 1. Glassmorphism - Effet verre givré */
|
||||||
|
.note-card.note-filter-glass,
|
||||||
|
.note-modal.note-filter-glass,
|
||||||
|
.link-outer.note-filter-glass {
|
||||||
|
background: rgba(255, 255, 255, 0.25) !important;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .note-card.note-filter-glass,
|
||||||
|
[data-theme="dark"] .note-modal.note-filter-glass,
|
||||||
|
[data-theme="dark"] .link-outer.note-filter-glass {
|
||||||
|
background: rgba(0, 0, 0, 0.35) !important;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. Vignette - Coins sombres */
|
||||||
|
.note-card.note-filter-vignette::after,
|
||||||
|
.note-modal.note-filter-vignette::after,
|
||||||
|
.link-outer.note-filter-vignette::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: inherit;
|
||||||
|
pointer-events: none;
|
||||||
|
background: radial-gradient(circle, transparent 50%, rgba(0, 0, 0, 0.4) 100%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-card.note-filter-vignette,
|
||||||
|
.note-modal.note-filter-vignette,
|
||||||
|
.link-outer.note-filter-vignette {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3. Ligné - Papier ligné */
|
||||||
|
.note-card.note-filter-lined,
|
||||||
|
.note-modal.note-filter-lined,
|
||||||
|
.link-outer.note-filter-lined {
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
transparent,
|
||||||
|
transparent 29px,
|
||||||
|
rgba(0, 0, 0, 0.1) 30px
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .note-card.note-filter-lined,
|
||||||
|
[data-theme="dark"] .note-modal.note-filter-lined,
|
||||||
|
[data-theme="dark"] .link-outer.note-filter-lined {
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
transparent,
|
||||||
|
transparent 29px,
|
||||||
|
rgba(255, 255, 255, 0.1) 30px
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4. Quadrillé - Grid */
|
||||||
|
.note-card.note-filter-grid,
|
||||||
|
.note-modal.note-filter-grid,
|
||||||
|
.link-outer.note-filter-grid {
|
||||||
|
background-image:
|
||||||
|
linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px) !important;
|
||||||
|
background-size: 20px 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .note-card.note-filter-grid,
|
||||||
|
[data-theme="dark"] .note-modal.note-filter-grid,
|
||||||
|
[data-theme="dark"] .link-outer.note-filter-grid {
|
||||||
|
background-image:
|
||||||
|
linear-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(255, 255, 255, 0.1) 1px, transparent 1px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 5. Noise - Texture granuleuse */
|
||||||
|
.note-card.note-filter-noise,
|
||||||
|
.note-modal.note-filter-noise,
|
||||||
|
.link-outer.note-filter-noise {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-card.note-filter-noise::before,
|
||||||
|
.note-modal.note-filter-noise::before,
|
||||||
|
.link-outer.note-filter-noise::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: inherit;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
||||||
|
mix-blend-mode: overlay;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 6. Points - Bullet journal dotted */
|
||||||
|
.note-card.note-filter-dots,
|
||||||
|
.note-modal.note-filter-dots,
|
||||||
|
.link-outer.note-filter-dots {
|
||||||
|
background-image: radial-gradient(rgba(0, 0, 0, 0.2) 1px, transparent 1px) !important;
|
||||||
|
background-size: 20px 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .note-card.note-filter-dots,
|
||||||
|
[data-theme="dark"] .note-modal.note-filter-dots,
|
||||||
|
[data-theme="dark"] .link-outer.note-filter-dots {
|
||||||
|
background-image: radial-gradient(rgba(255, 255, 255, 0.2) 1px, transparent 1px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 7. Rayures - Stripes diagonales */
|
||||||
|
.note-card.note-filter-stripes,
|
||||||
|
.note-modal.note-filter-stripes,
|
||||||
|
.link-outer.note-filter-stripes {
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
45deg,
|
||||||
|
transparent,
|
||||||
|
transparent 10px,
|
||||||
|
rgba(0, 0, 0, 0.05) 10px,
|
||||||
|
rgba(0, 0, 0, 0.05) 20px
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .note-card.note-filter-stripes,
|
||||||
|
[data-theme="dark"] .note-modal.note-filter-stripes,
|
||||||
|
[data-theme="dark"] .link-outer.note-filter-stripes {
|
||||||
|
background-image: repeating-linear-gradient(
|
||||||
|
45deg,
|
||||||
|
transparent,
|
||||||
|
transparent 10px,
|
||||||
|
rgba(255, 255, 255, 0.05) 10px,
|
||||||
|
rgba(255, 255, 255, 0.05) 20px
|
||||||
|
) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================
|
||||||
|
Filter-specific row layout for palette
|
||||||
|
========================================= */
|
||||||
|
.palette-row-filters {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 28px);
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.palette-btn-filter,
|
||||||
|
.palette-btn-filter-none {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: rgba(15, 23, 42, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.palette-btn-filter i,
|
||||||
|
.palette-btn-filter-none i {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-color, #334155);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .palette-btn-filter,
|
||||||
|
[data-theme="dark"] .palette-btn-filter-none {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .palette-btn-filter i,
|
||||||
|
[data-theme="dark"] .palette-btn-filter-none i {
|
||||||
|
color: #e8eaed;
|
||||||
}
|
}
|
||||||
@ -119,6 +119,18 @@ const NOTE_COLOR_OPTIONS = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const NOTE_FILTER_OPTIONS = [
|
||||||
|
{ key: "none", label: "Aucun", icon: "mdi-close-circle-outline" },
|
||||||
|
{ key: "glass", label: "Glass", icon: "mdi-blur" },
|
||||||
|
{ key: "vignette", label: "Vignette", icon: "mdi-vignette" },
|
||||||
|
{ key: "lined", label: "Ligné", icon: "mdi-format-align-justify" },
|
||||||
|
{ key: "grid", label: "Quadrillé", icon: "mdi-grid" },
|
||||||
|
{ key: "noise", label: "Noise", icon: "mdi-grain" },
|
||||||
|
{ key: "dots", label: "Points", icon: "mdi-dots-grid" },
|
||||||
|
{ key: "stripes", label: "Rayures", icon: "mdi-slash-forward" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const NOTE_FILTER_TAG_PREFIX = "notefilter-";
|
||||||
const NOTE_BACKGROUND_TAG_PREFIX = "notebg-";
|
const NOTE_BACKGROUND_TAG_PREFIX = "notebg-";
|
||||||
|
|
||||||
function resolveThemeAssetBasePath() {
|
function resolveThemeAssetBasePath() {
|
||||||
@ -361,11 +373,25 @@ function getElementVisualBackground(element) {
|
|||||||
return normalizedBackground || "none";
|
return normalizedBackground || "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshNoteBackgroundVisuals() {
|
function normalizeFilterKey(key) {
|
||||||
|
if (typeof key !== "string") return "none";
|
||||||
|
const normalized = key.trim().toLowerCase();
|
||||||
|
if (NOTE_FILTER_OPTIONS.some((opt) => opt.key === normalized)) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElementVisualFilter(element) {
|
||||||
|
if (!element) return "none";
|
||||||
|
return normalizeFilterKey(element.dataset.filter || "");
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshNoteFilterVisuals() {
|
||||||
document.querySelectorAll(".note-card, .note-modal, .link-outer").forEach((element) => {
|
document.querySelectorAll(".note-card, .note-modal, .link-outer").forEach((element) => {
|
||||||
applyNoteVisualState(element, {
|
applyNoteVisualState(element, {
|
||||||
color: getElementVisualColor(element),
|
color: getElementVisualColor(element),
|
||||||
background: getElementVisualBackground(element),
|
filter: getElementVisualFilter(element),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -566,8 +592,9 @@ function ensureBackgroundStudioPanel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action === "set-filter") {
|
if (action === "set-filter") {
|
||||||
panelEl.dataset.filter = actionBtn.dataset.filter || "all";
|
const filterKey = actionBtn.dataset.filter || "none";
|
||||||
renderBackgroundStudioPanel(panelEl);
|
if (mode === "modal") setModalNoteFilter(filterKey);
|
||||||
|
else setNoteFilter(entityId, filterKey, editUrl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,10 +609,10 @@ function ensureBackgroundStudioPanel() {
|
|||||||
if (action === "set-defaults") {
|
if (action === "set-defaults") {
|
||||||
if (mode === "modal") {
|
if (mode === "modal") {
|
||||||
setModalNoteColor("default");
|
setModalNoteColor("default");
|
||||||
setModalNoteBackground("none");
|
setModalNoteFilter("none");
|
||||||
} else {
|
} else {
|
||||||
setNoteColor(entityId, "default", editUrl);
|
setNoteColor(entityId, "default", editUrl);
|
||||||
setNoteBackground(entityId, "none", editUrl);
|
setNoteFilter(entityId, "none", editUrl);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -680,6 +707,7 @@ function openBackgroundStudioPanel({
|
|||||||
entityId,
|
entityId,
|
||||||
editUrl,
|
editUrl,
|
||||||
currentColor,
|
currentColor,
|
||||||
|
currentFilter,
|
||||||
currentBackground,
|
currentBackground,
|
||||||
title,
|
title,
|
||||||
}) {
|
}) {
|
||||||
@ -691,8 +719,8 @@ function openBackgroundStudioPanel({
|
|||||||
panel.dataset.entityId = entityId || "";
|
panel.dataset.entityId = entityId || "";
|
||||||
panel.dataset.editUrl = editUrl || "";
|
panel.dataset.editUrl = editUrl || "";
|
||||||
panel.dataset.color = currentColor || "default";
|
panel.dataset.color = currentColor || "default";
|
||||||
|
panel.dataset.filter = normalizeFilterKey(currentFilter || "") || "none";
|
||||||
panel.dataset.background = normalizeBackgroundKey(currentBackground || "") || "none";
|
panel.dataset.background = normalizeBackgroundKey(currentBackground || "") || "none";
|
||||||
panel.dataset.filter = panel.dataset.filter || "all";
|
|
||||||
panel.dataset.query = panel.dataset.query || "";
|
panel.dataset.query = panel.dataset.query || "";
|
||||||
panel.dataset.title = title || "Mes images & couleurs";
|
panel.dataset.title = title || "Mes images & couleurs";
|
||||||
panel.__anchorEl = anchorEl || null;
|
panel.__anchorEl = anchorEl || null;
|
||||||
@ -813,37 +841,22 @@ function renderBackgroundStudioPanel(panel) {
|
|||||||
|
|
||||||
const title = panel.dataset.title || "Mes images & couleurs";
|
const title = panel.dataset.title || "Mes images & couleurs";
|
||||||
const color = panel.dataset.color || "default";
|
const color = panel.dataset.color || "default";
|
||||||
const background = normalizeBackgroundKey(panel.dataset.background || "") || "none";
|
const currentFilter = panel.dataset.filter || "none";
|
||||||
const filter = panel.dataset.filter || "all";
|
|
||||||
const query = normalizeSearchText(panel.dataset.query || "");
|
const query = normalizeSearchText(panel.dataset.query || "");
|
||||||
|
|
||||||
const { colors, backgrounds } = getBackgroundStudioItems();
|
const { colors, backgrounds } = getBackgroundStudioItems();
|
||||||
|
|
||||||
const filterMatch = (item) => {
|
// Filter backgrounds based on search query
|
||||||
if (filter === "all") return true;
|
const filteredBackgrounds = backgrounds.filter((b) => {
|
||||||
if (filter === "color") return item.type === "color";
|
|
||||||
if (item.type !== "background") return false;
|
|
||||||
if (filter === "solid") return item.category === "solid";
|
|
||||||
if (filter === "gradient") return item.category === "gradient";
|
|
||||||
if (filter === "grid") return item.category === "grid";
|
|
||||||
if (filter === "image") return item.category === "image";
|
|
||||||
if (filter === "texture") return item.category === "texture";
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryMatch = (item) => {
|
|
||||||
if (!query) return true;
|
if (!query) return true;
|
||||||
const hay = normalizeSearchText([item.label, ...(item.keywords || [])].join(" "));
|
const hay = normalizeSearchText([b.label, b.key, "image", "background"].join(" "));
|
||||||
return hay.includes(query);
|
return hay.includes(query);
|
||||||
};
|
});
|
||||||
|
|
||||||
const galleryItems = backgrounds
|
// Generate gallery HTML for backgrounds
|
||||||
.filter((b) => filterMatch(b) && queryMatch(b))
|
const galleryHtml = filteredBackgrounds
|
||||||
.map((b) => ({ ...b, kind: "background" }));
|
|
||||||
|
|
||||||
const galleryHtml = galleryItems
|
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
const isActive = background === item.key;
|
const isActive = panel.dataset.background === item.key;
|
||||||
const common = `class="bg-studio-thumb ${isActive ? "is-active" : ""}" type="button"`;
|
const common = `class="bg-studio-thumb ${isActive ? "is-active" : ""}" type="button"`;
|
||||||
const thumb =
|
const thumb =
|
||||||
item.key === "none"
|
item.key === "none"
|
||||||
@ -864,17 +877,11 @@ function renderBackgroundStudioPanel(panel) {
|
|||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
const filterBtn = (key, icon, label) => {
|
const filterBtn = (key, icon, label) => {
|
||||||
const active = filter === key;
|
const active = currentFilter === key;
|
||||||
return `<button class="bg-studio-filter-btn ${active ? "is-active" : ""}" type="button" data-bg-studio-action="set-filter" data-filter="${key}" title="${label}" aria-label="${label}" aria-pressed="${active}"><i class="mdi ${icon}" aria-hidden="true"></i></button>`;
|
return `<button class="bg-studio-filter-btn ${active ? "is-active" : ""}" type="button" data-bg-studio-action="set-filter" data-filter="${key}" title="${label}" aria-label="${label}" aria-pressed="${active}"><i class="mdi ${icon}" aria-hidden="true"></i></button>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const filtersHtml = [
|
const filtersHtml = NOTE_FILTER_OPTIONS.map((f) => filterBtn(f.key, f.icon, f.label)).join("");
|
||||||
filterBtn("solid", "mdi-checkbox-blank-outline", "Couleur unie"),
|
|
||||||
filterBtn("gradient", "mdi-gradient-horizontal", "Dégradé"),
|
|
||||||
filterBtn("grid", "mdi-grid", "Motif grille"),
|
|
||||||
filterBtn("image", "mdi-image-outline", "Image personnalisée"),
|
|
||||||
filterBtn("texture", "mdi-checkerboard", "Texture"),
|
|
||||||
].join("");
|
|
||||||
|
|
||||||
const showClear = !!(panel.dataset.query || "").trim();
|
const showClear = !!(panel.dataset.query || "").trim();
|
||||||
|
|
||||||
@ -893,13 +900,13 @@ function renderBackgroundStudioPanel(panel) {
|
|||||||
<div class="bg-studio-swatches" role="list">${colorsRowHtml}</div>
|
<div class="bg-studio-swatches" role="list">${colorsRowHtml}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-studio-row">
|
<div class="bg-studio-row">
|
||||||
<div class="bg-studio-row-label">Backgrounds:</div>
|
<div class="bg-studio-row-label">Filtres:</div>
|
||||||
<div class="bg-studio-filters">${filtersHtml}</div>
|
<div class="bg-studio-filters">${filtersHtml}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-studio-search">
|
<div class="bg-studio-search">
|
||||||
<i class="mdi mdi-magnify" aria-hidden="true"></i>
|
<i class="mdi mdi-magnify" aria-hidden="true"></i>
|
||||||
<input class="bg-studio-search-input" type="search" placeholder="Rechercher mes images… (filtrer par couleur ou background)" value="${panel.dataset.query || ""}" />
|
<input class="bg-studio-search-input" type="search" placeholder="Rechercher mes images… (filtrer par couleur ou filtre)" value="${panel.dataset.query || ""}" />
|
||||||
<button class="bg-studio-clear" type="button" data-bg-studio-action="set-query" title="Effacer" aria-label="Effacer" style="${showClear ? "" : "display:none"}"><i class="mdi mdi-close-circle-outline" aria-hidden="true"></i></button>
|
<button class="bg-studio-clear" type="button" data-bg-studio-action="set-query" title="Effacer" aria-label="Effacer" style="${showClear ? "" : "display:none"}"><i class="mdi mdi-close-circle-outline" aria-hidden="true"></i></button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -929,13 +936,18 @@ function applyNoteVisualState(element, note) {
|
|||||||
const color = resolvedColorOption ? resolvedColorOption.key : "default";
|
const color = resolvedColorOption ? resolvedColorOption.key : "default";
|
||||||
const colorValue = getThemeColorValue(resolvedColorOption);
|
const colorValue = getThemeColorValue(resolvedColorOption);
|
||||||
const foregroundColor = getReadableForegroundForBackground(colorValue);
|
const foregroundColor = getReadableForegroundForBackground(colorValue);
|
||||||
|
const filter = normalizeFilterKey(note.filter || "none");
|
||||||
const normalizedBackground = normalizeBackgroundKey(note.background || "");
|
const normalizedBackground = normalizeBackgroundKey(note.background || "");
|
||||||
const background = normalizedBackground || "none";
|
const background = normalizedBackground || "none";
|
||||||
|
|
||||||
element.classList.forEach((cls) => {
|
element.classList.forEach((cls) => {
|
||||||
if (cls.startsWith("note-color-")) element.classList.remove(cls);
|
if (cls.startsWith("note-color-")) element.classList.remove(cls);
|
||||||
|
if (cls.startsWith("note-filter-")) element.classList.remove(cls);
|
||||||
});
|
});
|
||||||
element.classList.add(`note-color-${color}`);
|
element.classList.add(`note-color-${color}`);
|
||||||
|
if (filter !== "none") {
|
||||||
|
element.classList.add(`note-filter-${filter}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (colorValue) {
|
if (colorValue) {
|
||||||
element.style.backgroundColor = colorValue;
|
element.style.backgroundColor = colorValue;
|
||||||
@ -966,6 +978,7 @@ function applyNoteVisualState(element, note) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
element.dataset.color = color;
|
element.dataset.color = color;
|
||||||
|
element.dataset.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractNoteVisualStateFromTags(tags) {
|
function extractNoteVisualStateFromTags(tags) {
|
||||||
@ -980,6 +993,15 @@ function extractNoteVisualStateFromTags(tags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let filter = "none";
|
||||||
|
const foundFilterTag = safeTags.find((t) => typeof t === "string" && t.startsWith(NOTE_FILTER_TAG_PREFIX));
|
||||||
|
if (foundFilterTag) {
|
||||||
|
const candidate = normalizeFilterKey(foundFilterTag.substring(NOTE_FILTER_TAG_PREFIX.length));
|
||||||
|
if (candidate && candidate !== "none") {
|
||||||
|
filter = candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let background = "none";
|
let background = "none";
|
||||||
const foundBgTag = safeTags.find((t) => typeof t === "string" && t.startsWith(NOTE_BACKGROUND_TAG_PREFIX));
|
const foundBgTag = safeTags.find((t) => typeof t === "string" && t.startsWith(NOTE_BACKGROUND_TAG_PREFIX));
|
||||||
if (foundBgTag) {
|
if (foundBgTag) {
|
||||||
@ -989,7 +1011,7 @@ function extractNoteVisualStateFromTags(tags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { color, background };
|
return { color, filter, background };
|
||||||
}
|
}
|
||||||
|
|
||||||
function initBookmarkPaletteButtons() {
|
function initBookmarkPaletteButtons() {
|
||||||
@ -1001,8 +1023,8 @@ function initBookmarkPaletteButtons() {
|
|||||||
if (!cardId) return;
|
if (!cardId) return;
|
||||||
|
|
||||||
const tags = Array.from(card.querySelectorAll(".link-tag a")).map((a) => (a.textContent || "").trim());
|
const tags = Array.from(card.querySelectorAll(".link-tag a")).map((a) => (a.textContent || "").trim());
|
||||||
const { color, background } = extractNoteVisualStateFromTags(tags);
|
const { color, filter, background } = extractNoteVisualStateFromTags(tags);
|
||||||
applyNoteVisualState(card, { color, background });
|
applyNoteVisualState(card, { color, filter, background });
|
||||||
|
|
||||||
const actions = card.querySelector(".link-actions");
|
const actions = card.querySelector(".link-actions");
|
||||||
if (!actions) return;
|
if (!actions) return;
|
||||||
@ -1042,6 +1064,7 @@ function initBookmarkPaletteButtons() {
|
|||||||
entityId: cardId,
|
entityId: cardId,
|
||||||
editUrl,
|
editUrl,
|
||||||
currentColor: getElementVisualColor(card),
|
currentColor: getElementVisualColor(card),
|
||||||
|
currentFilter: getElementVisualFilter(card),
|
||||||
currentBackground: getElementVisualBackground(card),
|
currentBackground: getElementVisualBackground(card),
|
||||||
title: "Mes images & couleurs",
|
title: "Mes images & couleurs",
|
||||||
});
|
});
|
||||||
@ -1055,29 +1078,29 @@ function initBookmarkPaletteButtons() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateBookmarkPaletteButtons(bookmarkId, editUrl, currentColor, currentBackground) {
|
function generateBookmarkPaletteButtons(bookmarkId, editUrl, currentColor, currentFilter) {
|
||||||
return generateUnifiedPaletteMenu({
|
return generateUnifiedPaletteMenu({
|
||||||
entityId: bookmarkId,
|
entityId: bookmarkId,
|
||||||
editUrl,
|
editUrl,
|
||||||
currentColor,
|
currentColor,
|
||||||
currentBackground,
|
currentFilter,
|
||||||
mode: "entity",
|
mode: "entity",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateUnifiedPaletteMenu({ entityId, editUrl, currentColor, currentBackground, mode }) {
|
function generateUnifiedPaletteMenu({ entityId, editUrl, currentColor, currentFilter, mode }) {
|
||||||
const color = currentColor || "default";
|
const color = currentColor || "default";
|
||||||
const background = normalizeBackgroundKey(currentBackground || "") || "none";
|
const filter = normalizeFilterKey(currentFilter || "") || "none";
|
||||||
|
|
||||||
const onColorClick =
|
const onColorClick =
|
||||||
mode === "modal"
|
mode === "modal"
|
||||||
? (c) => `setModalNoteColor('${c}')`
|
? (c) => `setModalNoteColor('${c}')`
|
||||||
: (c) => `setNoteColor('${entityId}', '${c}', '${editUrl}')`;
|
: (c) => `setNoteColor('${entityId}', '${c}', '${editUrl}')`;
|
||||||
|
|
||||||
const onBackgroundClick =
|
const onFilterClick =
|
||||||
mode === "modal"
|
mode === "modal"
|
||||||
? (k) => `setModalNoteBackground('${k}')`
|
? (k) => `setModalNoteFilter('${k}')`
|
||||||
: (k) => `setNoteBackground('${entityId}', '${k}', '${editUrl}')`;
|
: (k) => `setNoteFilter('${entityId}', '${k}', '${editUrl}')`;
|
||||||
|
|
||||||
const colorButtons = [
|
const colorButtons = [
|
||||||
`<button class="palette-btn palette-btn-default ${color === "default" ? "is-active" : ""}" type="button" title="Par défaut" aria-label="Par défaut" aria-pressed="${color === "default"}" onclick="${onColorClick("default")}"><i class="mdi mdi-format-color-reset" aria-hidden="true"></i></button>`,
|
`<button class="palette-btn palette-btn-default ${color === "default" ? "is-active" : ""}" type="button" title="Par défaut" aria-label="Par défaut" aria-pressed="${color === "default"}" onclick="${onColorClick("default")}"><i class="mdi mdi-format-color-reset" aria-hidden="true"></i></button>`,
|
||||||
@ -1087,11 +1110,10 @@ function generateUnifiedPaletteMenu({ entityId, editUrl, currentColor, currentBa
|
|||||||
}),
|
}),
|
||||||
].join("");
|
].join("");
|
||||||
|
|
||||||
const backgroundButtons = [
|
const filterButtons = [
|
||||||
`<button class="palette-btn palette-btn-bg-none ${background === "none" ? "is-active" : ""}" type="button" title="Sans image" aria-label="Sans image" aria-pressed="${background === "none"}" onclick="${onBackgroundClick("none")}"><i class="mdi mdi-image-off-outline" aria-hidden="true"></i></button>`,
|
`<button class="palette-btn palette-btn-filter-none ${filter === "none" ? "is-active" : ""}" type="button" title="Aucun" aria-label="Aucun" aria-pressed="${filter === "none"}" onclick="${onFilterClick("none")}"><i class="mdi mdi-close-circle-outline" aria-hidden="true"></i></button>`,
|
||||||
...getAvailableBackgroundOptionsForMode().map((bg) => {
|
...NOTE_FILTER_OPTIONS.filter((opt) => opt.key !== "none").map((opt) => {
|
||||||
const bgUrl = getNoteBackgroundUrl(bg.key);
|
return `<button class="palette-btn palette-btn-filter ${filter === opt.key ? "is-active" : ""}" type="button" title="${opt.label}" aria-label="${opt.label}" aria-pressed="${filter === opt.key}" onclick="${onFilterClick(opt.key)}"><i class="mdi ${opt.icon}" aria-hidden="true"></i></button>`;
|
||||||
return `<button class="palette-btn palette-btn-bg ${background === bg.key ? "is-active" : ""}" type="button" title="${bg.label}" aria-label="${bg.label}" aria-pressed="${background === bg.key}" onclick="${onBackgroundClick(bg.key)}" style="background-image:url('${bgUrl}')"></button>`;
|
|
||||||
}),
|
}),
|
||||||
].join("");
|
].join("");
|
||||||
|
|
||||||
@ -1102,8 +1124,8 @@ function generateUnifiedPaletteMenu({ entityId, editUrl, currentColor, currentBa
|
|||||||
</div>
|
</div>
|
||||||
<div class="palette-divider"></div>
|
<div class="palette-divider"></div>
|
||||||
<div class="palette-section">
|
<div class="palette-section">
|
||||||
<div class="palette-section-title">Images</div>
|
<div class="palette-section-title">Filtres</div>
|
||||||
<div class="palette-row palette-row-backgrounds">${backgroundButtons}</div>
|
<div class="palette-row palette-row-filters">${filterButtons}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -1116,6 +1138,9 @@ function syncNoteFromCardElement(note, card) {
|
|||||||
note.color = colorClass.replace("note-color-", "") || "default";
|
note.color = colorClass.replace("note-color-", "") || "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const filter = card.dataset.filter;
|
||||||
|
note.filter = filter && filter !== "none" ? filter : "none";
|
||||||
|
|
||||||
const background = card.dataset.background;
|
const background = card.dataset.background;
|
||||||
note.background = background && background !== "none" ? background : "none";
|
note.background = background && background !== "none" ? background : "none";
|
||||||
}
|
}
|
||||||
@ -1470,6 +1495,7 @@ function initNoteView(linkList, container) {
|
|||||||
entityId: modalCard ? modalCard.dataset.noteId || "" : "",
|
entityId: modalCard ? modalCard.dataset.noteId || "" : "",
|
||||||
editUrl: modalCard ? modalCard.dataset.editUrl || "" : "",
|
editUrl: modalCard ? modalCard.dataset.editUrl || "" : "",
|
||||||
currentColor: modalCard ? getElementVisualColor(modalCard) : "default",
|
currentColor: modalCard ? getElementVisualColor(modalCard) : "default",
|
||||||
|
currentFilter: modalCard ? getElementVisualFilter(modalCard) : "none",
|
||||||
currentBackground: modalCard ? getElementVisualBackground(modalCard) : "none",
|
currentBackground: modalCard ? getElementVisualBackground(modalCard) : "none",
|
||||||
title: "Mes images & couleurs",
|
title: "Mes images & couleurs",
|
||||||
});
|
});
|
||||||
@ -1587,6 +1613,7 @@ function parseNoteFromLink(linkEl) {
|
|||||||
|
|
||||||
const tags = [];
|
const tags = [];
|
||||||
let color = "default";
|
let color = "default";
|
||||||
|
let filter = "none";
|
||||||
let background = "none";
|
let background = "none";
|
||||||
linkEl.querySelectorAll(".link-tag-list a").forEach((tag) => {
|
linkEl.querySelectorAll(".link-tag-list a").forEach((tag) => {
|
||||||
const t = tag.textContent.trim();
|
const t = tag.textContent.trim();
|
||||||
@ -1599,6 +1626,8 @@ function parseNoteFromLink(linkEl) {
|
|||||||
} else {
|
} else {
|
||||||
tags.push(t);
|
tags.push(t);
|
||||||
}
|
}
|
||||||
|
} else if (t.startsWith(NOTE_FILTER_TAG_PREFIX)) {
|
||||||
|
filter = normalizeFilterKey(t.substring(NOTE_FILTER_TAG_PREFIX.length)) || "none";
|
||||||
} else if (t.startsWith(NOTE_BACKGROUND_TAG_PREFIX)) {
|
} else if (t.startsWith(NOTE_BACKGROUND_TAG_PREFIX)) {
|
||||||
background = normalizeBackgroundKey(t.substring(NOTE_BACKGROUND_TAG_PREFIX.length)) || "none";
|
background = normalizeBackgroundKey(t.substring(NOTE_BACKGROUND_TAG_PREFIX.length)) || "none";
|
||||||
} else {
|
} else {
|
||||||
@ -1616,7 +1645,7 @@ function parseNoteFromLink(linkEl) {
|
|||||||
// User requested "availability of the tag 'shaarli-pin' as the main source"
|
// User requested "availability of the tag 'shaarli-pin' as the main source"
|
||||||
const isPinned = tags.includes("shaarli-pin");
|
const isPinned = tags.includes("shaarli-pin");
|
||||||
|
|
||||||
return { id, title, descHtml, descText, coverImage, url, tags, color, background, editUrl, deleteUrl, pinUrl, isPinned };
|
return { id, title, descHtml, descText, coverImage, url, tags, color, filter, background, editUrl, deleteUrl, pinUrl, isPinned };
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderNotes(container, notes, viewMode) {
|
function renderNotes(container, notes, viewMode) {
|
||||||
@ -1726,6 +1755,7 @@ function renderNotes(container, notes, viewMode) {
|
|||||||
entityId: note.id,
|
entityId: note.id,
|
||||||
editUrl: note.editUrl,
|
editUrl: note.editUrl,
|
||||||
currentColor: getElementVisualColor(card),
|
currentColor: getElementVisualColor(card),
|
||||||
|
currentFilter: getElementVisualFilter(card),
|
||||||
currentBackground: getElementVisualBackground(card),
|
currentBackground: getElementVisualBackground(card),
|
||||||
title: "Mes images & couleurs",
|
title: "Mes images & couleurs",
|
||||||
});
|
});
|
||||||
@ -1817,7 +1847,7 @@ function generateModalPaletteButtons(note) {
|
|||||||
entityId: note && note.id ? note.id : "",
|
entityId: note && note.id ? note.id : "",
|
||||||
editUrl: note && note.editUrl ? note.editUrl : "",
|
editUrl: note && note.editUrl ? note.editUrl : "",
|
||||||
currentColor: note && note.color ? note.color : "default",
|
currentColor: note && note.color ? note.color : "default",
|
||||||
currentBackground: note && note.background ? note.background : "none",
|
currentFilter: note && note.filter ? note.filter : "none",
|
||||||
mode: "modal",
|
mode: "modal",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1843,15 +1873,15 @@ window.setModalNoteColor = function (color) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.setModalNoteBackground = function (backgroundKey) {
|
window.setModalNoteFilter = function (filterKey) {
|
||||||
const modal = document.querySelector(".note-modal-overlay");
|
const modal = document.querySelector(".note-modal-overlay");
|
||||||
if (!modal || !modal.currentNote) return;
|
if (!modal || !modal.currentNote) return;
|
||||||
|
|
||||||
const currentNote = modal.currentNote;
|
const currentNote = modal.currentNote;
|
||||||
const normalizedBackgroundKey = backgroundKey === "none" ? "none" : normalizeBackgroundKey(backgroundKey) || "none";
|
const normalizedFilterKey = normalizeFilterKey(filterKey) || "none";
|
||||||
setNoteBackground(currentNote.id, normalizedBackgroundKey, currentNote.editUrl);
|
setNoteFilter(currentNote.id, normalizedFilterKey, currentNote.editUrl);
|
||||||
|
|
||||||
currentNote.background = normalizedBackgroundKey;
|
currentNote.filter = normalizedFilterKey;
|
||||||
const modalCard = modal.querySelector(".note-modal");
|
const modalCard = modal.querySelector(".note-modal");
|
||||||
if (modalCard) {
|
if (modalCard) {
|
||||||
applyNoteVisualState(modalCard, currentNote);
|
applyNoteVisualState(modalCard, currentNote);
|
||||||
@ -1870,7 +1900,7 @@ function generatePaletteButtons(note) {
|
|||||||
entityId: note && note.id ? note.id : "",
|
entityId: note && note.id ? note.id : "",
|
||||||
editUrl: note && note.editUrl ? note.editUrl : "",
|
editUrl: note && note.editUrl ? note.editUrl : "",
|
||||||
currentColor: note && note.color ? note.color : "default",
|
currentColor: note && note.color ? note.color : "default",
|
||||||
currentBackground: note && note.background ? note.background : "none",
|
currentFilter: note && note.filter ? note.filter : "none",
|
||||||
mode: "entity",
|
mode: "entity",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1879,17 +1909,17 @@ window.setNoteColor = function (noteId, color, editUrl) {
|
|||||||
// 1. Visual Update (Immediate feedback)
|
// 1. Visual Update (Immediate feedback)
|
||||||
const card = document.querySelector(`.note-card[data-id="${noteId}"]`);
|
const card = document.querySelector(`.note-card[data-id="${noteId}"]`);
|
||||||
if (card) {
|
if (card) {
|
||||||
const background = card.dataset.background || "none";
|
const filter = card.dataset.filter || "none";
|
||||||
applyNoteVisualState(card, { color, background });
|
applyNoteVisualState(card, { color, filter });
|
||||||
}
|
}
|
||||||
|
|
||||||
const bookmarkCard = document.querySelector(`.link-outer[data-id="${noteId}"]`);
|
const bookmarkCard = document.querySelector(`.link-outer[data-id="${noteId}"]`);
|
||||||
if (bookmarkCard) {
|
if (bookmarkCard) {
|
||||||
const background = bookmarkCard.dataset.background || "none";
|
const filter = bookmarkCard.dataset.filter || "none";
|
||||||
applyNoteVisualState(bookmarkCard, { color, background });
|
applyNoteVisualState(bookmarkCard, { color, filter });
|
||||||
const palettePopup = bookmarkCard.querySelector(".bookmark-palette .palette-popup");
|
const palettePopup = bookmarkCard.querySelector(".bookmark-palette .palette-popup");
|
||||||
if (palettePopup) {
|
if (palettePopup) {
|
||||||
palettePopup.innerHTML = generateBookmarkPaletteButtons(noteId, editUrl, color, background);
|
palettePopup.innerHTML = generateBookmarkPaletteButtons(noteId, editUrl, color, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1969,6 +1999,90 @@ window.setNoteColor = function (noteId, color, editUrl) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.setNoteFilter = function (noteId, filterKey, editUrl) {
|
||||||
|
const normalizedFilterKey = normalizeFilterKey(filterKey) || "none";
|
||||||
|
|
||||||
|
const card = document.querySelector(`.note-card[data-id="${noteId}"]`);
|
||||||
|
if (card) {
|
||||||
|
const colorClass = Array.from(card.classList).find((cls) => cls.startsWith("note-color-"));
|
||||||
|
const color = colorClass ? colorClass.replace("note-color-", "") : card.dataset.color || "default";
|
||||||
|
applyNoteVisualState(card, { color, filter: normalizedFilterKey });
|
||||||
|
}
|
||||||
|
|
||||||
|
const bookmarkCard = document.querySelector(`.link-outer[data-id="${noteId}"]`);
|
||||||
|
if (bookmarkCard) {
|
||||||
|
const colorClass = Array.from(bookmarkCard.classList).find((cls) => cls.startsWith("note-color-"));
|
||||||
|
const color = colorClass ? colorClass.replace("note-color-", "") : bookmarkCard.dataset.color || "default";
|
||||||
|
applyNoteVisualState(bookmarkCard, { color, filter: normalizedFilterKey });
|
||||||
|
const palettePopup = bookmarkCard.querySelector(".bookmark-palette .palette-popup");
|
||||||
|
if (palettePopup) {
|
||||||
|
palettePopup.innerHTML = generateBookmarkPaletteButtons(noteId, editUrl, color, normalizedFilterKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal = document.querySelector(".note-modal-overlay");
|
||||||
|
if (modal && modal.currentNote && String(modal.currentNote.id) === String(noteId)) {
|
||||||
|
modal.currentNote.filter = normalizedFilterKey;
|
||||||
|
const modalCard = modal.querySelector(".note-modal");
|
||||||
|
if (modalCard) {
|
||||||
|
applyNoteVisualState(modalCard, modal.currentNote);
|
||||||
|
}
|
||||||
|
const modalColorPopup = modal.querySelector("#note-modal-color-popup");
|
||||||
|
if (modalColorPopup) {
|
||||||
|
modalColorPopup.innerHTML = generateModalPaletteButtons(modal.currentNote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(editUrl)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((html) => {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString(html, "text/html");
|
||||||
|
const form = doc.querySelector('form[name="linkform"]');
|
||||||
|
|
||||||
|
if (!form) throw new Error("Could not find edit form");
|
||||||
|
|
||||||
|
const formData = new URLSearchParams();
|
||||||
|
const inputs = form.querySelectorAll("input, textarea");
|
||||||
|
|
||||||
|
inputs.forEach((input) => {
|
||||||
|
if (input.type === "checkbox") {
|
||||||
|
if (input.checked) formData.append(input.name, input.value || "on");
|
||||||
|
} else if (input.name) {
|
||||||
|
formData.append(input.name, input.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let currentTags = formData.get("lf_tags") || "";
|
||||||
|
let tagsArray = currentTags.split(/[\s,]+/).filter((t) => t.trim() !== "");
|
||||||
|
|
||||||
|
tagsArray = tagsArray.filter((t) => !t.startsWith(NOTE_FILTER_TAG_PREFIX));
|
||||||
|
if (normalizedFilterKey && normalizedFilterKey !== "none") {
|
||||||
|
tagsArray.push(`${NOTE_FILTER_TAG_PREFIX}${normalizedFilterKey}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
formData.set("lf_tags", tagsArray.join(" "));
|
||||||
|
formData.append("save_edit", "1");
|
||||||
|
|
||||||
|
return fetch(form.action, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: formData.toString(),
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to save filter");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Error saving note filter:", err);
|
||||||
|
alert("Erreur lors de la sauvegarde du filtre. Veuillez rafraîchir la page.");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
window.setNoteBackground = function (noteId, backgroundKey, editUrl) {
|
window.setNoteBackground = function (noteId, backgroundKey, editUrl) {
|
||||||
const normalizedBackgroundKey = backgroundKey === "none" ? "none" : normalizeBackgroundKey(backgroundKey) || "none";
|
const normalizedBackgroundKey = backgroundKey === "none" ? "none" : normalizeBackgroundKey(backgroundKey) || "none";
|
||||||
|
|
||||||
@ -1976,18 +2090,16 @@ window.setNoteBackground = function (noteId, backgroundKey, editUrl) {
|
|||||||
if (card) {
|
if (card) {
|
||||||
const colorClass = Array.from(card.classList).find((cls) => cls.startsWith("note-color-"));
|
const colorClass = Array.from(card.classList).find((cls) => cls.startsWith("note-color-"));
|
||||||
const color = colorClass ? colorClass.replace("note-color-", "") : card.dataset.color || "default";
|
const color = colorClass ? colorClass.replace("note-color-", "") : card.dataset.color || "default";
|
||||||
applyNoteVisualState(card, { color, background: normalizedBackgroundKey });
|
const filter = card.dataset.filter || "none";
|
||||||
|
applyNoteVisualState(card, { color, filter, background: normalizedBackgroundKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
const bookmarkCard = document.querySelector(`.link-outer[data-id="${noteId}"]`);
|
const bookmarkCard = document.querySelector(`.link-outer[data-id="${noteId}"]`);
|
||||||
if (bookmarkCard) {
|
if (bookmarkCard) {
|
||||||
const colorClass = Array.from(bookmarkCard.classList).find((cls) => cls.startsWith("note-color-"));
|
const colorClass = Array.from(bookmarkCard.classList).find((cls) => cls.startsWith("note-color-"));
|
||||||
const color = colorClass ? colorClass.replace("note-color-", "") : bookmarkCard.dataset.color || "default";
|
const color = colorClass ? colorClass.replace("note-color-", "") : bookmarkCard.dataset.color || "default";
|
||||||
applyNoteVisualState(bookmarkCard, { color, background: normalizedBackgroundKey });
|
const filter = bookmarkCard.dataset.filter || "none";
|
||||||
const palettePopup = bookmarkCard.querySelector(".bookmark-palette .palette-popup");
|
applyNoteVisualState(bookmarkCard, { color, filter, background: normalizedBackgroundKey });
|
||||||
if (palettePopup) {
|
|
||||||
palettePopup.innerHTML = generateBookmarkPaletteButtons(noteId, editUrl, color, normalizedBackgroundKey);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const modal = document.querySelector(".note-modal-overlay");
|
const modal = document.querySelector(".note-modal-overlay");
|
||||||
@ -2053,6 +2165,28 @@ window.setNoteBackground = function (noteId, backgroundKey, editUrl) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.setModalNoteBackground = function (backgroundKey) {
|
||||||
|
const modal = document.querySelector(".note-modal-overlay");
|
||||||
|
if (!modal || !modal.currentNote) return;
|
||||||
|
|
||||||
|
const currentNote = modal.currentNote;
|
||||||
|
const normalizedBackgroundKey = backgroundKey === "none" ? "none" : normalizeBackgroundKey(backgroundKey) || "none";
|
||||||
|
setNoteBackground(currentNote.id, normalizedBackgroundKey, currentNote.editUrl);
|
||||||
|
|
||||||
|
currentNote.background = normalizedBackgroundKey;
|
||||||
|
const modalCard = modal.querySelector(".note-modal");
|
||||||
|
if (modalCard) {
|
||||||
|
applyNoteVisualState(modalCard, currentNote);
|
||||||
|
}
|
||||||
|
|
||||||
|
const modalColorPopup = modal.querySelector("#note-modal-color-popup");
|
||||||
|
if (modalColorPopup) {
|
||||||
|
modalColorPopup.innerHTML = generateModalPaletteButtons(currentNote);
|
||||||
|
modalColorPopup.classList.add("open");
|
||||||
|
positionPalettePopup(modalColorPopup);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function addTagToNote(editUrl, tag) {
|
function addTagToNote(editUrl, tag) {
|
||||||
return fetch(editUrl)
|
return fetch(editUrl)
|
||||||
.then((response) => response.text())
|
.then((response) => response.text())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user