diff --git a/CHANGELOG.md b/CHANGELOG.md index a8ea87d..633206a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/), et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). > **En cours de développement** : les changements à venir sont listés dans la section -> [Unreleased](#unreleased). La dernière version livrée est **2.28.5**. +> [Unreleased](#unreleased). La dernière version livrée est **2.28.6**. --- @@ -14,6 +14,10 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [2.28.6] — 2026-09-26 + +--- + ## [2.28.5] — 2026-09-26 --- diff --git a/README.fr.md b/README.fr.md index 8c0c9ac..ae27164 100644 --- a/README.fr.md +++ b/README.fr.md @@ -4,7 +4,7 @@ **Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive. -[![Version](https://img.shields.io/badge/Version-2.28.5-blue.svg)]() +[![Version](https://img.shields.io/badge/Version-2.28.6-blue.svg)]() [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/) [![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/) @@ -976,8 +976,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l ## 📝 Changelog -Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.28.5). +Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.28.6). --- -*Projet : ObsiGate | Version : 2.28.5 | Dernière mise à jour : Septembre 2026* +*Projet : ObsiGate | Version : 2.28.6 | Dernière mise à jour : Septembre 2026* diff --git a/README.md b/README.md index d112293..8847bc4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface. -[![Version](https://img.shields.io/badge/Version-2.28.5-blue.svg)]() +[![Version](https://img.shields.io/badge/Version-2.28.6-blue.svg)]() [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker](https://img.shields.io/badge/Docker-Ready-blue.svg)](https://www.docker.com/) [![Python](https://img.shields.io/badge/Python-3.11+-green.svg)](https://www.python.org/) @@ -1151,8 +1151,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) ## 📝 Changelog -See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.28.5). +See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.28.6). --- -*Project: ObsiGate | Version: 2.28.5 | Last updated: September 2026* +*Project: ObsiGate | Version: 2.28.6 | Last updated: September 2026* diff --git a/VERSION b/VERSION index cb5e764..759bcf0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.28.5 +2.28.6 diff --git a/desktop/Cargo.lock b/desktop/Cargo.lock index 44e084f..35b5272 100644 --- a/desktop/Cargo.lock +++ b/desktop/Cargo.lock @@ -2626,7 +2626,7 @@ dependencies = [ [[package]] name = "obsigate-desktop" -version = "2.28.5" +version = "2.28.6" dependencies = [ "chrono", "env_logger", diff --git a/desktop/Cargo.toml b/desktop/Cargo.toml index 6d15abd..55e3feb 100644 --- a/desktop/Cargo.toml +++ b/desktop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "obsigate-desktop" -version = "2.28.5" +version = "2.28.6" description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian" authors = ["Bruno Charest"] edition = "2021" diff --git a/desktop/tauri.conf.json b/desktop/tauri.conf.json index 454e0ec..a498aa1 100644 --- a/desktop/tauri.conf.json +++ b/desktop/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json", "productName": "ObsiGate", - "version": "2.28.5", + "version": "2.28.6", "identifier": "com.obsigate.desktop", "build": { "frontendDist": "../frontend", diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 9a9e354..ffb6032 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -1,6 +1,6 @@ # ObsiGate — Roadmap -> **Version :** 2.28.5 | **Dernière mise à jour :** 2026-09-26 +> **Version :** 2.28.6 | **Dernière mise à jour :** 2026-09-26 > **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact > vers les fonctionnalités livrées. > - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)** diff --git a/frontend/index.html b/frontend/index.html index d0b1558..95730a8 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1576,17 +1576,6 @@ class="help-search-clear" id="config-search-clear" title="Effacer" - onclick=" - var s = - document.getElementById( - 'config-nav-search', - ); - if (s) { - s.value = ''; - s.dispatchEvent(new Event('input')); - s.focus(); - } - " > X @@ -1698,7 +1687,7 @@ - + @@ -3005,14 +2994,6 @@ id="help-hamburger" title="Sommaire" aria-label="Afficher le sommaire" - onclick=" - var n = document.getElementById('help-nav'); - if (n) { - var d = n.style.display; - n.style.display = - d === 'none' || d === '' ? 'flex' : 'none'; - } - " > ✕ diff --git a/frontend/js/auth.js b/frontend/js/auth.js index d538e7c..2b841d1 100644 --- a/frontend/js/auth.js +++ b/frontend/js/auth.js @@ -1305,8 +1305,7 @@ async function _startMfaSetup() { // secret when the backend has no QR generator available. const qrImg = data.qr_data_url ? `QR Code` + src="${data.qr_data_url}">` : ""; const fallbackStyle = data.qr_data_url ? "display:none" : ""; flowArea.innerHTML = ` @@ -1335,6 +1334,17 @@ async function _startMfaSetup() { codeInput.value = codeInput.value.replace(/[^0-9]/g, ""); }); + // QR fallback (#87, ex-onerror inline) : si l'image ne charge pas, + // afficher la saisie manuelle du secret. + const qrImgEl = document.getElementById("mfa-qr-img"); + if (qrImgEl) { + qrImgEl.addEventListener("error", () => { + qrImgEl.style.display = "none"; + const fallback = document.getElementById("mfa-qr-fallback"); + if (fallback) fallback.style.display = "block"; + }); + } + document.getElementById("mfa-confirm-btn").addEventListener("click", async () => { const code = codeInput.value.trim(); if (code.length !== 6) return; diff --git a/frontend/js/config.js b/frontend/js/config.js index b49a0cc..e1b5f85 100644 --- a/frontend/js/config.js +++ b/frontend/js/config.js @@ -363,6 +363,27 @@ function initHelpModal() { } }); + // Help TOC hamburger + search clear (#87, ex-onclick inline in index.html). + var helpHamburger = document.getElementById("help-hamburger"); + if (helpHamburger) { + helpHamburger.addEventListener("click", function() { + var n = document.getElementById("help-nav"); + if (n) { + var d = n.style.display; + n.style.display = d === "none" || d === "" ? "flex" : "none"; + } + }); + } + var helpSearch = document.getElementById("help-nav-search"); + var helpSearchClear = document.getElementById("help-search-clear"); + if (helpSearchClear && helpSearch) { + helpSearchClear.addEventListener("click", function() { + helpSearch.value = ""; + helpSearch.dispatchEvent(new Event("input")); + helpSearch.focus(); + }); + } + document.addEventListener("keydown", (e) => { if (e.key === "Escape" && modal.classList.contains("active")) { closeHelpModal(); @@ -883,7 +904,7 @@ function initConfigModal() { }); } - // Logout button — handled inline in index.html (onclick) + // Logout button — wired here with addEventListener (#87, no inline onclick) // Config nav search var cfgSearch = document.getElementById("config-nav-search"); @@ -901,6 +922,16 @@ function initConfigModal() { }); } + // Config search clear button (#87, ex-onclick inline). + var cfgSearchClear = document.getElementById("config-search-clear"); + if (cfgSearchClear && cfgSearch) { + cfgSearchClear.addEventListener("click", function() { + cfgSearch.value = ""; + cfgSearch.dispatchEvent(new Event("input")); + cfgSearch.focus(); + }); + } + // BUG-071/#114: mobile table of contents. #config-nav shares the .help-nav // rule that hides it below 768px, but — unlike the help modal — the config // modal had no toggle to reveal it, leaving mobile users with no way to @@ -1575,13 +1606,15 @@ export async function openShareDialog(vault, path) {

${escapeHtml(vault)}/${escapeHtml(path)}

${expiresInfo}

${existingShare.access_count} vue(s)

- +
`; + const shareUrlInput = div.querySelector(".share-url-input"); + if (shareUrlInput) shareUrlInput.addEventListener("click", function() { shareUrlInput.select(); }); div.querySelector(".share-copy-btn").addEventListener("click", async () => { try { await navigator.clipboard.writeText(url); @@ -2525,7 +2558,10 @@ function initProfile() { } catch(e) {} }); - // Logout button — handled inline in index.html (onclick) + // Logout button (#87, ex-onclick inline in index.html). + if (logoutBtn && window.handleLogout) { + logoutBtn.addEventListener('click', function() { window.handleLogout(); }); + } // ── Avatar (#113) ──────────────────────────────────────────────── var avatarField = document.getElementById('profile-avatar-field'); diff --git a/frontend/js/plugins.js b/frontend/js/plugins.js index a514e49..fdbc566 100644 --- a/frontend/js/plugins.js +++ b/frontend/js/plugins.js @@ -478,8 +478,8 @@ function openTemplateModal() { '' + '' + '' + ''; @@ -487,11 +487,11 @@ function openTemplateModal() { modal.querySelector('.modal-close')?.addEventListener('click', () => modal.remove()); modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); }); - - window.copyTemplate = () => { + modal.querySelector('.btn-modal-close')?.addEventListener('click', () => modal.remove()); + modal.querySelector('.btn-copy-template')?.addEventListener('click', () => { navigator.clipboard.writeText(JSON.stringify(template, null, 2)); showToast('Template copied to clipboard', 'success'); - }; + }); }); } @@ -508,12 +508,13 @@ function openCodeModal(name, code) { '
' + escapeHtml(code) + '
' + '' + '' + ''; document.body.appendChild(modal); modal.querySelector('.modal-close')?.addEventListener('click', () => modal.remove()); + modal.querySelector('.btn-modal-close')?.addEventListener('click', () => modal.remove()); modal.addEventListener('click', (e) => { if (e.target === modal) modal.remove(); }); } diff --git a/frontend/js/sync.js b/frontend/js/sync.js index 5d53a1b..2df2a23 100644 --- a/frontend/js/sync.js +++ b/frontend/js/sync.js @@ -543,10 +543,16 @@ function showUpdateNotification() { message.innerHTML = `
Une nouvelle version d'ObsiGate est disponible ! - - + +
`; + message.querySelector(".pwa-update-btn").addEventListener("click", function() { + window.location.reload(); + }); + message.querySelector(".pwa-update-dismiss").addEventListener("click", function() { + message.remove(); + }); document.body.appendChild(message); // Auto-dismiss after 30 seconds diff --git a/frontend/js/viewer.js b/frontend/js/viewer.js index dc421e1..be78043 100644 --- a/frontend/js/viewer.js +++ b/frontend/js/viewer.js @@ -1140,10 +1140,10 @@ export function renderFile(data) {
PDF — ${pages} pages - -
@@ -1152,6 +1152,11 @@ export function renderFile(data) {
`; + area.querySelectorAll('.pdf-toolbar .btn-action').forEach((btn) => { + btn.addEventListener('click', () => { + window.open(btn.dataset.pdfUrl || btn.dataset.downloadUrl, '_blank'); + }); + }); area.querySelectorAll('.pdf-toc a[data-page]').forEach((link) => { link.addEventListener('click', (e) => { e.preventDefault(); diff --git a/package.json b/package.json index 66b9fec..4774019 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsigate", - "version": "2.28.5", + "version": "2.28.6", "description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.", "main": "patch.js", "directories": {