ObsiGate 2.84.1 — HUB-18 : thème commun, barre v0.5.0 + initialisation thème Hub (fusion #132) #67
+7
-1
@@ -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).
|
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
|
> **En cours de développement** : les changements à venir sont listés dans la section
|
||||||
> [Unreleased](#unreleased). La dernière version livrée est **2.84.0**.
|
> [Unreleased](#unreleased). La dernière version livrée est **2.84.1**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -14,6 +14,12 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [2.84.1] — 2026-11-06
|
||||||
|
|
||||||
|
- **HUB-18 — Thème commun (fusion #132)** : barre commune re-vendangée **verbatim** en **v0.5.0** depuis dracodev-commons (branche `hub18-theme-commun`, PR commons #12) — `frontend/draco-barre.js` seul change côté barre (CSS et fragment inchangés). La barre apprend la préférence de thème du profil du Hub (`GET <hub>/api/profil/theme`, cookie draco ; `<hub>` = URL résolue de la barre, jamais figée) et l'applique à l'ouverture : cache `localStorage` `draco-theme-hub` (TTL 12 h) appliqué synchrone, puis fetch asynchrone non bloquant ; `sombre`/`clair` posent `data-theme`, `systeme` le retire (`prefers-color-scheme` décide). **Repli intégral** si le Hub ne répond pas, répond non-OK ou `theme: null` : le comportement actuel (choix local, puis système) reste seul maître. Initialisation propre à ObsiGate dans `frontend/app.js` : `initTheme()` écoute l'événement `draco:theme` de la barre et route le mode effectif par `applyTheme()` — icône et libellé du bouton de thème et feuilles highlight.js restent synchronisés, le mode appliqué devient le choix local mémorisé (`obsigate-theme`), et le bouton de bascule reste fonctionnel pour la session. Garde ajoutée à `tests/test_draco_barre.py`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [2.84.0] — 2026-11-06
|
## [2.84.0] — 2026-11-06
|
||||||
|
|
||||||
- **HUB-13 — API d'administration des comptes, machine-à-machine (fusion #127, #226)** : nouvelles routes `/api/admin/machine/comptes` (liste, profil étendu, création, modification, désactivation/réactivation, suppression, réinitialisation du mot de passe et du MFA), protégées par la clé machine dédiée `DRACO_ADMIN_MACHINE_KEY` (en-tête `X-Draco-Machine-Key`, distincte de `DRACO_SSO_MACHINE_KEY` ; aucune session utilisateur ne les ouvre ; API inerte si la clé n'est pas configurée). Le profil étendu expose nom d'utilisateur, nom affiché, langue, avatar (valeur + présence), rôle global, état actif, MFA activé oui/non — jamais le secret TOTP ni le haché du mot de passe. La désactivation arrête l'émission de nouveaux jetons et révoque les `jti` draco actifs : `draco_session` tient désormais un registre des émissions (`data/draco_issued.json`) et `revoke_all_for_user()` révoque via la liste existante ; le repère `password_changed_at` (BUG-028) est aussi avancé. Nouveau champ utilisateur `must_change_password` : posé à la création machine et à la réinitialisation du mot de passe, signalé par la connexion et `GET /api/auth/me`, effacé au changement effectif. Chaque action est journalisée dans `data/audit.log` (acteur = identité de service `X-Draco-Actor`, action, compte cible, horodatage). Fiche : `docs/features/hub-api-admin-comptes-226.md`. Tests : `tests/test_comptes_machine.py`.
|
- **HUB-13 — API d'administration des comptes, machine-à-machine (fusion #127, #226)** : nouvelles routes `/api/admin/machine/comptes` (liste, profil étendu, création, modification, désactivation/réactivation, suppression, réinitialisation du mot de passe et du MFA), protégées par la clé machine dédiée `DRACO_ADMIN_MACHINE_KEY` (en-tête `X-Draco-Machine-Key`, distincte de `DRACO_SSO_MACHINE_KEY` ; aucune session utilisateur ne les ouvre ; API inerte si la clé n'est pas configurée). Le profil étendu expose nom d'utilisateur, nom affiché, langue, avatar (valeur + présence), rôle global, état actif, MFA activé oui/non — jamais le secret TOTP ni le haché du mot de passe. La désactivation arrête l'émission de nouveaux jetons et révoque les `jti` draco actifs : `draco_session` tient désormais un registre des émissions (`data/draco_issued.json`) et `revoke_all_for_user()` révoque via la liste existante ; le repère `password_changed_at` (BUG-028) est aussi avancé. Nouveau champ utilisateur `must_change_password` : posé à la création machine et à la réinitialisation du mot de passe, signalé par la connexion et `GET /api/auth/me`, effacé au changement effectif. Chaque action est journalisée dans `data/audit.log` (acteur = identité de service `X-Draco-Actor`, action, compte cible, horodatage). Fiche : `docs/features/hub-api-admin-comptes-226.md`. Tests : `tests/test_comptes_machine.py`.
|
||||||
|
|||||||
+3
-3
@@ -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.
|
**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.
|
||||||
|
|
||||||
[]()
|
[]()
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
[](https://www.docker.com/)
|
[](https://www.docker.com/)
|
||||||
[](https://www.python.org/)
|
[](https://www.python.org/)
|
||||||
@@ -977,8 +977,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l
|
|||||||
|
|
||||||
## 📝 Changelog
|
## 📝 Changelog
|
||||||
|
|
||||||
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.84.0).
|
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.84.1).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Projet : ObsiGate | Version : 2.84.0 | Dernière mise à jour : Septembre 2026*
|
*Projet : ObsiGate | Version : 2.84.1 | Dernière mise à jour : Septembre 2026*
|
||||||
|
|||||||
@@ -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.
|
**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.
|
||||||
|
|
||||||
[]()
|
[]()
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
[](https://www.docker.com/)
|
[](https://www.docker.com/)
|
||||||
[](https://www.python.org/)
|
[](https://www.python.org/)
|
||||||
@@ -1152,8 +1152,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE)
|
|||||||
|
|
||||||
## 📝 Changelog
|
## 📝 Changelog
|
||||||
|
|
||||||
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.84.0).
|
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.84.1).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Project: ObsiGate | Version: 2.84.0 | Last updated: September 2026*
|
*Project: ObsiGate | Version: 2.84.1 | Last updated: September 2026*
|
||||||
|
|||||||
Generated
+1
-1
@@ -2626,7 +2626,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "obsigate-desktop"
|
name = "obsigate-desktop"
|
||||||
version = "2.84.0"
|
version = "2.84.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "obsigate-desktop"
|
name = "obsigate-desktop"
|
||||||
version = "2.84.0"
|
version = "2.84.1"
|
||||||
description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian"
|
description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian"
|
||||||
authors = ["Bruno Charest"]
|
authors = ["Bruno Charest"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json",
|
"$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json",
|
||||||
"productName": "ObsiGate",
|
"productName": "ObsiGate",
|
||||||
"version": "2.84.0",
|
"version": "2.84.1",
|
||||||
"identifier": "com.obsigate.desktop",
|
"identifier": "com.obsigate.desktop",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../frontend",
|
"frontendDist": "../frontend",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# ObsiGate — Roadmap
|
# ObsiGate — Roadmap
|
||||||
|
|
||||||
> **Version :** 2.84.0 | **Dernière mise à jour :** 2026-11-06
|
> **Version :** 2.84.1 | **Dernière mise à jour :** 2026-11-06
|
||||||
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
|
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
|
||||||
> vers les fonctionnalités livrées.
|
> vers les fonctionnalités livrées.
|
||||||
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
|
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
|
||||||
|
|||||||
@@ -1214,6 +1214,30 @@
|
|||||||
function initTheme() {
|
function initTheme() {
|
||||||
const saved = localStorage.getItem("obsigate-theme") || "dark";
|
const saved = localStorage.getItem("obsigate-theme") || "dark";
|
||||||
applyTheme(saved);
|
applyTheme(saved);
|
||||||
|
// Thème commun de la suite (HUB-18, fusion #132) : la barre
|
||||||
|
// commune (barre v0.5.0) applique la préférence du Hub
|
||||||
|
// (sombre/clair/système) à l'ouverture — directement sur
|
||||||
|
// data-theme, et via l'événement « draco:theme » pour que le
|
||||||
|
// mécanisme propre d'ObsiGate suive (icône et libellé du bouton,
|
||||||
|
// feuilles highlight.js). applyTheme mémorise le mode appliqué
|
||||||
|
// dans « obsigate-theme » : la préférence du Hub devient le
|
||||||
|
// choix local courant, et le bouton de bascule reste le maître
|
||||||
|
// pour la suite de la session (aucune ré-application de la barre
|
||||||
|
// après l'ouverture). « systeme » arrive déjà résolu en mode
|
||||||
|
// effectif (detail.mode) par la barre. Repli : si le Hub ne
|
||||||
|
// répond pas, aucun événement n'arrive et le choix local
|
||||||
|
// ci-dessus reste seul maître, comme avant.
|
||||||
|
document.addEventListener("draco:theme", (e) => {
|
||||||
|
const mode = e && e.detail && e.detail.mode;
|
||||||
|
if (mode === "dark" || mode === "light") applyTheme(mode);
|
||||||
|
});
|
||||||
|
// Si la barre s'est initialisée AVANT ce module (ordre des
|
||||||
|
// scripts defer/module selon la page), sa préférence déjà
|
||||||
|
// résolue depuis son cache est reprise ici.
|
||||||
|
const barre = window.DRACO_BAR;
|
||||||
|
if (barre && (barre.themeMode === "dark" || barre.themeMode === "light")) {
|
||||||
|
applyTheme(barre.themeMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyTheme(theme) {
|
function applyTheme(theme) {
|
||||||
|
|||||||
@@ -36,6 +36,12 @@
|
|||||||
* remplissage), aligné à gauche du libellé via .draco-menu-icone.
|
* remplissage), aligné à gauche du libellé via .draco-menu-icone.
|
||||||
* L'en-tête d'identité ne reçoit pas d'icône. Aucun changement de
|
* L'en-tête d'identité ne reçoit pas d'icône. Aucun changement de
|
||||||
* comportement : liens résolus et Déconnexion relayée inchangés.
|
* comportement : liens résolus et Déconnexion relayée inchangés.
|
||||||
|
* v0.5.0 (carte HUB-18, fusion #132) : thème commun de la suite —
|
||||||
|
* la barre apprend la préférence de thème du profil du Hub
|
||||||
|
* (GET <hub>/api/profil/theme, cookie draco) et l'applique à
|
||||||
|
* l'ouverture par le mécanisme data-theme des hôtes, avec cache
|
||||||
|
* local court et repli intégral sur le comportement actuel de
|
||||||
|
* l'hôte si le Hub ne répond pas. Voir « Thème commun » plus bas.
|
||||||
*
|
*
|
||||||
* Aucun gestionnaire inline : un seul écouteur délégué sur le document
|
* Aucun gestionnaire inline : un seul écouteur délégué sur le document
|
||||||
* (patron validé par le prototype — les onclick du HTML généré sont
|
* (patron validé par le prototype — les onclick du HTML généré sont
|
||||||
@@ -268,6 +274,131 @@
|
|||||||
}
|
}
|
||||||
var resolvedUrls = resolveUrls();
|
var resolvedUrls = resolveUrls();
|
||||||
|
|
||||||
|
/* ── Thème commun (v0.5.0, carte HUB-18, fusion #132) ────────────
|
||||||
|
* La préférence de thème de la suite vit dans le profil du Hub :
|
||||||
|
* GET <hub>/api/profil/theme → {"theme": "sombre"|"clair"|"systeme"|null}
|
||||||
|
* authentifié par le cookie draco (credentials: "include").
|
||||||
|
* <hub> est l'URL RÉSOLUE ci-dessus (explicite > dérivation -dev >
|
||||||
|
* défaut officiel) — jamais un nom figé de plus.
|
||||||
|
* Application par le mécanisme data-theme existant des hôtes :
|
||||||
|
* "sombre" → data-theme="dark", "clair" → data-theme="light",
|
||||||
|
* "systeme" → attribut RETIRÉ (prefers-color-scheme décide, garde
|
||||||
|
* html:not([data-theme]) du CSS de la barre comme des hôtes).
|
||||||
|
* L'événement draco:theme ({theme, mode} — mode = "dark"/"light"
|
||||||
|
* EFFECTIF) est ensuite dispatché pour les hôtes dont le mécanisme
|
||||||
|
* propre doit suivre (icônes et libellés, feuilles de style,
|
||||||
|
* palettes ShaarIt, attribut dédié de la console…) ; un hôte qui
|
||||||
|
* s'initialise après la barre lit la même information dans
|
||||||
|
* DRACO_BAR.themePref / DRACO_BAR.themeMode.
|
||||||
|
* Ordre d'application : 1) le cache local FRAIS est appliqué de
|
||||||
|
* façon SYNCHRONE à l'initialisation de la barre (script en defer
|
||||||
|
* chez tous les hôtes : avant DOMContentLoaded, donc avant le
|
||||||
|
* premier rendu dans le cas général) ; 2) un fetch ASYNCHRONE et
|
||||||
|
* NON BLOQUANT rafraîchit le cache et ré-applique si la préférence
|
||||||
|
* a changé. À la toute première visite (aucun cache), un bref
|
||||||
|
* flash du thème local de l'hôte reste possible le temps du fetch :
|
||||||
|
* c'est le prix du repli — l'état affiché transitoire est le thème
|
||||||
|
* que l'hôte aurait de toute façon choisi seul, jamais un état
|
||||||
|
* cassé, et les visites suivantes sont servies par le cache.
|
||||||
|
* Cache : localStorage "draco-theme-hub" ({theme, ts}), TTL 12 h
|
||||||
|
* (ordre de la journée) ; il ne contient QUE la préférence du Hub,
|
||||||
|
* jamais le choix local de l'hôte.
|
||||||
|
* REPLI INTÉGRAL : Hub injoignable, réponse non-OK (401…), JSON
|
||||||
|
* invalide, theme null ou valeur inconnue → RIEN n'est appliqué et
|
||||||
|
* RIEN n'est mis en cache ; un échec de fetch n'efface pas un cache
|
||||||
|
* existant. Le comportement actuel de l'hôte (son localStorage,
|
||||||
|
* puis le système) reste alors exactement le maître, comme avant
|
||||||
|
* la v0.5.0. Le sélecteur de thème LOCAL de chaque hôte reste
|
||||||
|
* fonctionnel : la barre n'applique qu'à l'ouverture (cache, puis
|
||||||
|
* fetch) ; elle ne ré-applique ensuite que sur changement du
|
||||||
|
* schéma système, et seulement tant que la préférence résolue est
|
||||||
|
* "systeme". */
|
||||||
|
var THEME_CACHE_CLE = "draco-theme-hub";
|
||||||
|
var THEME_CACHE_TTL_MS = 12 * 60 * 60 * 1000;
|
||||||
|
var themePref = null; /* "sombre"|"clair"|"systeme"|null (non résolue) */
|
||||||
|
var themeMode = null; /* "dark"|"light"|null : mode effectif appliqué */
|
||||||
|
|
||||||
|
function themeSystemeEstSombre() {
|
||||||
|
try {
|
||||||
|
return !!(window.matchMedia &&
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").matches);
|
||||||
|
} catch (e) { return false; }
|
||||||
|
}
|
||||||
|
function lireCacheTheme() {
|
||||||
|
try {
|
||||||
|
var brut = window.localStorage &&
|
||||||
|
window.localStorage.getItem(THEME_CACHE_CLE);
|
||||||
|
if (!brut) return null;
|
||||||
|
var c = JSON.parse(brut);
|
||||||
|
if (!c || typeof c.ts !== "number") return null;
|
||||||
|
if (Date.now() - c.ts > THEME_CACHE_TTL_MS) return null;
|
||||||
|
if (c.theme === "sombre" || c.theme === "clair" || c.theme === "systeme")
|
||||||
|
return c.theme;
|
||||||
|
} catch (e) { /* stockage indisponible ou corrompu : pas de cache */ }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
function ecrireCacheTheme(theme) {
|
||||||
|
try {
|
||||||
|
if (window.localStorage) {
|
||||||
|
window.localStorage.setItem(THEME_CACHE_CLE,
|
||||||
|
JSON.stringify({ theme: theme, ts: Date.now() }));
|
||||||
|
}
|
||||||
|
} catch (e) { /* stockage indisponible : le prochain fetch refera le travail */ }
|
||||||
|
}
|
||||||
|
function appliquerThemeCommun(theme) {
|
||||||
|
var root = document.documentElement;
|
||||||
|
if (!root) return;
|
||||||
|
if (theme === "sombre" || theme === "clair") {
|
||||||
|
themeMode = theme === "sombre" ? "dark" : "light";
|
||||||
|
root.setAttribute("data-theme", themeMode);
|
||||||
|
} else if (theme === "systeme") {
|
||||||
|
themeMode = themeSystemeEstSombre() ? "dark" : "light";
|
||||||
|
root.removeAttribute("data-theme");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
themePref = theme;
|
||||||
|
if (window.DRACO_BAR) {
|
||||||
|
window.DRACO_BAR.themePref = themePref;
|
||||||
|
window.DRACO_BAR.themeMode = themeMode;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
document.dispatchEvent(new CustomEvent("draco:theme",
|
||||||
|
{ detail: { theme: themePref, mode: themeMode } }));
|
||||||
|
} catch (e) { /* aucun écouteur hôte : data-theme suffit */ }
|
||||||
|
}
|
||||||
|
function initThemeCommun() {
|
||||||
|
var enCache = lireCacheTheme();
|
||||||
|
if (enCache) appliquerThemeCommun(enCache);
|
||||||
|
/* Suivi du schéma système tant que la préférence est "systeme" :
|
||||||
|
* sans data-theme, le CSS suit tout seul ; l'événement est
|
||||||
|
* re-dispatché pour les hôtes qui matérialisent le mode. */
|
||||||
|
try {
|
||||||
|
var mq = window.matchMedia &&
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
if (mq && mq.addEventListener) {
|
||||||
|
mq.addEventListener("change", function () {
|
||||||
|
if (themePref === "systeme") appliquerThemeCommun("systeme");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) { /* pas de matchMedia : pas de suivi */ }
|
||||||
|
if (typeof window.fetch !== "function") return;
|
||||||
|
var url = withSlash(resolvedUrls.hub || DEFAULT_URLS.hub) +
|
||||||
|
"api/profil/theme";
|
||||||
|
window.fetch(url, { credentials: "include" }).then(function (resp) {
|
||||||
|
if (!resp || !resp.ok) return null;
|
||||||
|
return resp.json();
|
||||||
|
}).then(function (data) {
|
||||||
|
if (!data) return;
|
||||||
|
var t = data.theme;
|
||||||
|
if (t === "sombre" || t === "clair" || t === "systeme") {
|
||||||
|
ecrireCacheTheme(t);
|
||||||
|
appliquerThemeCommun(t);
|
||||||
|
}
|
||||||
|
/* theme null ou inconnu : repli intégral, rien n'est touché. */
|
||||||
|
}).catch(function () { /* Hub injoignable : repli intégral */ });
|
||||||
|
}
|
||||||
|
|
||||||
function setCounts(counts) {
|
function setCounts(counts) {
|
||||||
Object.keys(counts || {}).forEach(function (k) {
|
Object.keys(counts || {}).forEach(function (k) {
|
||||||
/* Toutes les occurrences : l'onglet ET sa ligne dans le menu. */
|
/* Toutes les occurrences : l'onglet ET sa ligne dans le menu. */
|
||||||
@@ -695,6 +826,9 @@
|
|||||||
window.DRACO_BAR = {
|
window.DRACO_BAR = {
|
||||||
setCounts: setCounts, setCurrent: setCurrent, setDomain: setDomain,
|
setCounts: setCounts, setCurrent: setCurrent, setDomain: setDomain,
|
||||||
urls: resolvedUrls,
|
urls: resolvedUrls,
|
||||||
|
/* Thème commun (v0.5.0) : préférence du Hub résolue et mode
|
||||||
|
* effectif appliqué ; null tant que rien n'a été résolu (repli). */
|
||||||
|
themePref: null, themeMode: null,
|
||||||
setUrls: function (urls) {
|
setUrls: function (urls) {
|
||||||
cfg.urls = Object.assign({}, cfg.urls, urls || {});
|
cfg.urls = Object.assign({}, cfg.urls, urls || {});
|
||||||
resolvedUrls = resolveUrls();
|
resolvedUrls = resolveUrls();
|
||||||
@@ -709,6 +843,7 @@
|
|||||||
buildCompteMenu();
|
buildCompteMenu();
|
||||||
syncAvatar();
|
syncAvatar();
|
||||||
refreshCompteMenu();
|
refreshCompteMenu();
|
||||||
|
initThemeCommun();
|
||||||
if (cfg.current) setCurrent(cfg.current);
|
if (cfg.current) setCurrent(cfg.current);
|
||||||
if (cfg.domain) setDomain(cfg.domain);
|
if (cfg.domain) setDomain(cfg.domain);
|
||||||
if (cfg.counts) setCounts(cfg.counts);
|
if (cfg.counts) setCounts(cfg.counts);
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsigate",
|
"name": "obsigate",
|
||||||
"version": "2.84.0",
|
"version": "2.84.1",
|
||||||
"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.",
|
"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",
|
"main": "patch.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|||||||
@@ -239,3 +239,23 @@ def test_barre_v041_correctif_icones_espace_de_noms_svg():
|
|||||||
assert "createElementNS(SVG_NS, spec[0])" in js
|
assert "createElementNS(SVG_NS, spec[0])" in js
|
||||||
assert 'createElement("svg")' not in js
|
assert 'createElement("svg")' not in js
|
||||||
assert "createElement(spec[0])" not in js
|
assert "createElement(spec[0])" not in js
|
||||||
|
|
||||||
|
|
||||||
|
def test_barre_v050_theme_commun_hub18():
|
||||||
|
# v0.5.0 (HUB-18, fusion #132) : la barre apprend la préférence
|
||||||
|
# de thème du Hub et l'applique à l'ouverture. La vendange reste
|
||||||
|
# verbatim commons ; l'initialisation propre à ObsiGate vit dans
|
||||||
|
# app.js (écouteur draco:theme → applyTheme).
|
||||||
|
js = (FRONTEND / "draco-barre.js").read_text(encoding="utf-8")
|
||||||
|
assert "api/profil/theme" in js
|
||||||
|
assert 'credentials: "include"' in js
|
||||||
|
assert "draco-theme-hub" in js
|
||||||
|
assert "THEME_CACHE_TTL_MS" in js
|
||||||
|
assert 'CustomEvent("draco:theme"' in js
|
||||||
|
assert "themePref" in js and "themeMode" in js
|
||||||
|
# Aucun nom de Hub figé de plus que les défauts/dérivations
|
||||||
|
# documentés : l'URL du Hub reste la résolue de la barre.
|
||||||
|
assert "resolvedUrls.hub" in js
|
||||||
|
app = (FRONTEND / "app.js").read_text(encoding="utf-8")
|
||||||
|
assert 'addEventListener("draco:theme"' in app
|
||||||
|
assert "barre.themeMode" in app
|
||||||
|
|||||||
Reference in New Issue
Block a user