v4
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/* DONA_FILES_V91 — panneau autonome et réactif */
|
||||
.df-overlay[hidden],.df-current[hidden],.df-preview[hidden]{display:none!important}
|
||||
.df-overlay{position:fixed;inset:0;z-index:12700;background:rgba(7,11,20,.86);backdrop-filter:blur(13px);display:grid;place-items:center;padding:12px;color:#ecf5ff}
|
||||
.df-panel{box-sizing:border-box;width:min(810px,100%);max-height:calc(100dvh - 24px);overflow:auto;padding:clamp(14px,2.7vw,26px);background:linear-gradient(150deg,#1a2a3b,#111925);border:1px solid #476075;border-radius:20px;box-shadow:0 15px 65px #000a;font:15px/1.5 system-ui,sans-serif;color:#f2f7ff}
|
||||
.df-panel *{box-sizing:border-box}.df-panel button,.df-panel textarea{font:inherit}.df-head{display:flex;align-items:flex-start;justify-content:space-between;gap:15px}.df-head h2{font-size:23px;line-height:1.25;margin:4px 0 10px}.df-eyebrow{font-size:11px;letter-spacing:.15em;color:#a5d2e9}.df-close{cursor:pointer;color:#fff;background:#2d4051;border:1px solid #5b7689;border-radius:50%;font-size:24px;width:41px;height:41px;flex-shrink:0}
|
||||
.df-hint{color:#a2bccc;font-size:12px;margin:9px 0 13px}.df-drop{display:grid;justify-items:center;gap:8px;padding:17px;border:2px dashed #65859c;border-radius:14px;background:#172b3d;text-align:center;margin:12px 0}.df-drop.df-over{border-color:#a1f2e6;background:#24465a}.df-file{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}.df-upload-icon{font-size:28px}.df-button{border:1px solid #587a98;border-radius:11px;color:#edfaff;background:#2e4960;padding:9px 14px;cursor:pointer}.df-button:hover,.df-chip:hover{filter:brightness(1.18)}.df-primary{background:#126b82;border-color:#299dc4}.df-button:disabled{opacity:.55;cursor:wait}.df-current{padding:8px 12px;border:1px solid #3d617a;border-radius:12px;margin-bottom:9px}.df-filename{font-weight:600;overflow-wrap:anywhere;margin:6px 0}.df-preview{display:block;max-height:185px;max-width:100%;object-fit:contain;border-radius:9px;margin:8px 0}.df-del{font-size:12px;background:#5b303c}.df-label{display:block;font-weight:600;margin:13px 0 7px}.df-question{display:block;width:100%;background:#111f2e;color:#fff;border:1px solid #68859a;border-radius:10px;padding:12px;resize:vertical;min-height:85px}.df-examples{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0}.df-chip{padding:7px 11px;background:#273c53;color:#e9f5ff;border:1px solid #496b85;border-radius:18px;cursor:pointer}.df-run{margin:6px 0}.df-status{min-height:20px;color:#a4d8eb;font-size:13px;margin:10px 0}.df-answer{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.65;background:rgba(14,27,42,.85);border:1px solid #34566c;border-radius:12px;padding:16px;margin-top:10px;min-height:50px}.df-launch{cursor:pointer}
|
||||
@media(max-width:650px){.df-overlay{padding:0}.df-panel{height:100dvh;max-height:100dvh;border-radius:0;padding:13px}.df-head h2{font-size:20px}.df-drop{padding:12px}}
|
||||
|
||||
/* DONA_FILES_V911_COMPOSE : bouton 📎 après Envoyer, dans la barre Écrire à Dona. */
|
||||
body.dona-family-v1 .dona-compose-row #dfOpen.df-compose-attach{
|
||||
flex:0 0 48px;
|
||||
width:48px;
|
||||
min-width:48px;
|
||||
height:48px;
|
||||
min-height:48px;
|
||||
padding:0!important;
|
||||
display:grid;
|
||||
place-items:center;
|
||||
border-radius:50%!important;
|
||||
background:rgba(255,255,255,.1)!important;
|
||||
border:1px solid rgba(255,204,165,.55)!important;
|
||||
color:#ffe3ca!important;
|
||||
font-size:23px!important;
|
||||
font-weight:500!important;
|
||||
cursor:pointer;
|
||||
}
|
||||
body.dona-family-v1 .dona-compose-row #dfOpen.df-compose-attach:hover{
|
||||
background:rgba(255,195,139,.24)!important;
|
||||
}
|
||||
body.dona-family-v1 .dona-compose-row #dfOpen.df-compose-attach:focus-visible{
|
||||
outline:2px solid #ffce92;
|
||||
outline-offset:2px;
|
||||
}
|
||||
@media(max-width:700px){
|
||||
body.dona-family-v1 .dona-compose-row #dfOpen.df-compose-attach{
|
||||
width:46px;min-width:46px;flex-basis:46px;height:46px;min-height:46px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* DONA_LEARNING_V93 — discreet feedback, separate editor */
|
||||
.dl93-dock[hidden],.dl93-overlay[hidden],.dl93-toast[hidden],.dl93-transcript[hidden]{display:none!important}
|
||||
.dl93-dock{position:fixed;z-index:1200;left:50%;bottom:18px;transform:translateX(-50%);display:flex;gap:9px;align-items:center;padding:9px 12px;background:rgba(29,25,35,.94);backdrop-filter:blur(18px);border:1px solid rgba(209,175,160,.35);border-radius:20px;box-shadow:0 10px 40px #0005;max-width:min(95vw,760px);color:#f1eaf3}
|
||||
.dl93-context{font:500 12px/1.4 system-ui,sans-serif;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:320px;opacity:.85}
|
||||
.dl93-tool,.dl93-button,.dl93-close{cursor:pointer;font-family:inherit;border:1px solid rgba(231,208,202,.28);border-radius:11px;background:#222332;color:#fbf7fa;min-height:36px;padding:7px 11px;font-size:14px}
|
||||
.dl93-tool:hover,.dl93-button:hover,.dl93-close:hover{background:#373344}.dl93-tool:focus-visible,.dl93-button:focus-visible,.dl93-close:focus-visible{outline:2px solid #e9b89c}
|
||||
.dl93-tool:first-of-type,.dl93-tool:nth-of-type(2){font-size:19px;min-width:42px}
|
||||
.dl93-overlay{position:fixed;inset:0;z-index:2500;background:rgba(8,9,14,.76);display:flex;align-items:center;justify-content:center;padding:18px;color:#f6f2f7;overflow:auto}
|
||||
.dl93-sheet{width:min(100%,640px);max-height:92dvh;overflow:auto;border:1px solid rgba(240,214,196,.3);border-radius:22px;background:#211c29;box-shadow:0 18px 65px #000a;padding:20px;box-sizing:border-box;font:14px/1.5 system-ui,sans-serif}
|
||||
.dl93-history{width:min(100%,790px)}.dl93-top{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:10px}.dl93-top h3{font-size:21px;margin:0}.dl93-close{font-size:22px;min-width:40px}
|
||||
.dl93-summary{background:#181b27;border-radius:12px;padding:10px 13px;margin:12px 0;overflow-wrap:anywhere}.dl93-summary p{margin:5px 0}
|
||||
.dl93-field{display:grid;gap:6px;margin:12px 0;color:#f6eef8;font-size:14px}.dl93-field select,.dl93-field textarea{background:#121521;color:#fff;border:1px solid #6a5b6b;padding:11px;border-radius:10px;font:14px/1.5 system-ui,sans-serif;width:100%;box-sizing:border-box;resize:vertical}
|
||||
.dl93-hint,.dl93-small{font-size:12px;color:#d4c8d9}.dl93-hint{margin:12px 0}.dl93-small{overflow-wrap:anywhere;margin:7px 0}.dl93-actions{display:flex;flex-wrap:wrap;gap:9px;margin:14px 0}.dl93-button{background:#654a60}.dl93-neutral{background:#272634}.dl93-error{color:#ffb4ae!important}.dl93-state{min-height:12px;font-size:13px}
|
||||
.dl93-panel-body{display:grid;gap:10px}.dl93-panel-body h4{margin:12px 0 2px}.dl93-record{background:#161824;border:1px solid rgba(224,209,224,.15);border-radius:14px;padding:12px}.dl93-record-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.dl93-chip{font-size:11px;padding:4px 7px;border-radius:7px;background:#383142;color:#ece6ec}.dl93-rule{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:8px;border-bottom:1px solid #444;overflow-wrap:anywhere}.dl93-rule span{flex:1}
|
||||
.dl93-toast{position:fixed;right:15px;top:16px;z-index:2600;padding:12px;border-radius:12px;background:#221d2a;color:#fff;box-shadow:0 10px 30px #0008}.dl93-transcript{position:fixed;z-index:1100;top:85px;left:15px;padding:8px 12px;background:#242432;color:#f5e9f6;border-radius:9px;font:13px system-ui,sans-serif;max-width:60vw}
|
||||
@media(max-width:700px){.dl93-dock{left:10px;right:10px;bottom:7px;transform:none;max-width:none;justify-content:center;padding:7px}.dl93-context{display:none}.dl93-sheet{padding:14px}.dl93-overlay{padding:8px}.dl93-rule{flex-direction:column;align-items:start}}
|
||||
@@ -0,0 +1,90 @@
|
||||
/* DONA_UI_V921_CLOSE — La grille et son éditeur ne recouvrent plus le bouton Raccourcis. */
|
||||
body.dona-family-v1 .dona-tools-tray { isolation: isolate; }
|
||||
body.dona-family-v1 .dona-tools-tray > summary {
|
||||
position:relative;
|
||||
z-index: 4;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray > .dv92-shortcut-toolbar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 61px;
|
||||
width: min(690px, 90vw);
|
||||
box-sizing: border-box;
|
||||
height: 55px !important;
|
||||
min-height: 55px !important;
|
||||
padding: 7px 12px !important;
|
||||
flex-wrap: nowrap !important;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(246,189,171,.30);
|
||||
border-radius: 0 0 17px 17px;
|
||||
background: rgba(37,25,45,.96);
|
||||
backdrop-filter: blur(20px);
|
||||
z-index: 2;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray .dv92-shortcut-toolbar .dv92-edit-open {
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
min-height: 37px;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray .dv92-shortcut-toolbar .dv92-shortcut-status {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray:not([open]) > .dv92-shortcut-toolbar {
|
||||
display: none !important;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray .av-shortcuts {
|
||||
bottom: 116px !important;
|
||||
box-sizing: border-box;
|
||||
max-height: min(54vh, 450px);
|
||||
overflow-y: auto !important;
|
||||
overscroll-behavior: contain;
|
||||
align-content: start;
|
||||
border-radius: 18px 18px 0 0;
|
||||
z-index: 2;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray .dv921-tray-heading {
|
||||
grid-column: 1 / -1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
color: #ffe9dc;
|
||||
min-height: 38px;
|
||||
border-bottom: 1px solid rgba(255,255,255,.15);
|
||||
padding: 0 2px 7px;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray .av-shortcuts .dv921-tray-close {
|
||||
position: relative;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
flex: 0 0 34px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
min-height: 34px !important;
|
||||
border: 1px solid rgba(255,255,255,.3);
|
||||
border-radius: 50%;
|
||||
background: rgba(255,255,255,.12);
|
||||
color: #fff;
|
||||
font-size: 26px;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray .av-shortcuts .dv921-tray-close:hover {
|
||||
background: rgba(255,255,255,.23);
|
||||
}
|
||||
@media (max-width: 620px) {
|
||||
body.dona-family-v1 .dona-tools-tray > .dv92-shortcut-toolbar,
|
||||
body.dona-family-v1 .dona-tools-tray .av-shortcuts {
|
||||
width: min(690px, calc(100vw - 28px));
|
||||
}
|
||||
body.dona-family-v1 .dona-tools-tray .av-shortcuts {
|
||||
max-height: min(46vh, 390px);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/* DONA_UI_V92 — Barre d'outils épurée + éditeur de raccourcis */
|
||||
body.dona-family-v1 #alfredMainV1 .av-head-actions > :not(#avTopMic):not(#dv92Hamburger){display:none!important}
|
||||
body.dona-family-v1 #alfredMainV1 .av-head-actions{display:flex!important;align-items:center!important;gap:10px!important}
|
||||
body.dona-family-v1 #alfredMainV1 #dv92Hamburger{display:grid!important;place-items:center!important;font-family:Arial,sans-serif;font-size:27px;line-height:1;font-weight:400;color:#f5f5ff;cursor:pointer}
|
||||
body.dona-family-v1 #alfredMainV1 #avTopMic{display:grid!important;visibility:visible!important}
|
||||
body.dona-family-v1 #alfredMainV1 .dona-child-link{display:grid!important;visibility:visible!important}
|
||||
.dv92-menu[hidden],.dv92-editor-overlay[hidden]{display:none!important}
|
||||
.dv92-menu{position:fixed;z-index:9000;width:min(310px,calc(100vw - 16px));max-height:min(70vh,580px);overflow:auto;padding:12px;border-radius:18px;background:rgba(23,24,35,.97);border:1px solid rgba(243,214,201,.25);box-shadow:0 16px 56px rgba(0,0,0,.5);color:#f9f7fa;backdrop-filter:blur(16px)}
|
||||
.dv92-menu-heading{font-size:13px;letter-spacing:.08em;color:#f4c9ae;text-transform:uppercase;padding:4px 9px 10px}
|
||||
.dv92-menu-entry{display:flex;width:100%;align-items:center;gap:13px;text-align:left;cursor:pointer;color:#f9f7fa;background:transparent;border:0;border-radius:10px;padding:11px;font-size:15px;font-family:inherit}
|
||||
.dv92-menu-entry:hover,.dv92-menu-entry:focus-visible{background:rgba(255,255,255,.11);outline:0}
|
||||
.dv92-menu-entry svg{width:21px;height:21px;flex:0 0 21px;fill:none;stroke:currentColor}
|
||||
.dv92-menu-symbol{font-size:20px;width:21px;display:inline-flex;justify-content:center}
|
||||
.dv92-menu-rule{border-top:1px solid rgba(255,255,255,.14);margin:9px 0}
|
||||
.dv92-menu-edit{color:#ffdec1;font-weight:650}
|
||||
body.dona-family-v1 #alfredMainV1 .av-shortcuts>[data-av-action="more"]{display:none!important}
|
||||
body.dona-family-v1 #alfredMainV1 .av-shortcuts .dv92-shortcut{display:inline-flex;gap:7px;align-items:center;justify-content:center}
|
||||
.dv92-symbol{display:inline-grid;place-items:center;font-size:20px;line-height:1;min-width:22px;flex:0 0 22px}
|
||||
.dv92-shortcut-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 1px 10px}
|
||||
.dv92-edit-open{background:rgba(252,207,174,.12);border:1px solid rgba(252,207,174,.35);border-radius:11px;color:#ffe4ca;padding:9px 13px;cursor:pointer;font:inherit;font-size:13px}
|
||||
.dv92-edit-open:hover{background:rgba(252,207,174,.23)}
|
||||
.dv92-shortcut-status{color:#eed6c7;font-size:12px;overflow-wrap:anywhere}
|
||||
.dv92-shortcut-empty{color:#cec6cd;font-size:14px;padding:8px}
|
||||
.dv92-editor-overlay{position:fixed;inset:0;z-index:9500;display:flex;justify-content:center;align-items:center;padding:14px;background:rgba(3,5,12,.82);backdrop-filter:blur(9px)}
|
||||
.dv92-editor{width:min(800px,100%);max-height:min(94vh,980px);overflow:auto;overscroll-behavior:contain;border:1px solid rgba(255,208,171,.3);border-radius:23px;padding:22px;color:#f8f5f8;background:#1d202e;box-shadow:0 24px 90px rgba(0,0,0,.65);font-family:inherit}
|
||||
.dv92-editor-header{display:flex;align-items:start;justify-content:space-between;gap:10px;margin-bottom:8px}
|
||||
.dv92-editor-header h2{font-size:26px;margin:4px 0;color:#fff}
|
||||
.dv92-editor-header small{letter-spacing:.14em;color:#edc6a9;font-size:11px}
|
||||
.dv92-close{border:1px solid rgba(255,255,255,.23);border-radius:100%;background:#343748;color:white;width:43px;height:43px;font-size:28px;cursor:pointer}
|
||||
.dv92-help{font-size:13px;color:#c5c4d1;line-height:1.5;margin:4px 0 12px}
|
||||
.dv92-count{text-align:right;font-size:12px;color:#d5cad0;margin-bottom:8px}
|
||||
.dv92-editor-list{display:grid;gap:9px;max-height:min(58vh,580px);overflow:auto;padding:1px 5px 1px 1px}
|
||||
.dv92-edit-item{border:1px solid rgba(255,255,255,.16);border-radius:13px;background:#282b3b;overflow:hidden}
|
||||
.dv92-item-summary{cursor:pointer;display:flex;align-items:center;gap:12px;padding:13px;list-style:none}
|
||||
.dv92-item-summary::-webkit-details-marker{display:none}
|
||||
.dv92-item-summary:after{content:'⌄';font-size:19px;opacity:.8;margin-left:5px}
|
||||
.dv92-edit-item[open] .dv92-item-summary:after{content:'⌃'}
|
||||
.dv92-summary-name{flex:1;min-width:0;overflow-wrap:anywhere;font-size:14px}
|
||||
.dv92-summary-mode{font-size:11px;color:#ffd2ad}
|
||||
.dv92-edit-item[open]{padding-bottom:14px}
|
||||
.dv92-inline-controls{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin:0 13px 13px}
|
||||
.dv92-check{display:flex;align-items:center;gap:6px;font-size:12px;margin-right:auto}
|
||||
.dv92-check input{width:18px;height:18px;accent-color:#eea76f}
|
||||
.dv92-small{border:1px solid rgba(255,255,255,.25);border-radius:7px;color:#f6e6df;background:#393d51;cursor:pointer;padding:6px 12px;font-size:12px;min-height:34px}
|
||||
.dv92-small:disabled{opacity:.4;cursor:not-allowed}
|
||||
.dv92-danger{color:#ffb9bc}
|
||||
.dv92-field{display:grid;gap:6px;margin:9px 13px;font-size:12px;color:#ead7cd}
|
||||
.dv92-input,.dv92-textarea{display:block;width:100%;min-width:0;box-sizing:border-box;background:#171a25!important;color:#fff!important;border:1px solid #58586c!important;border-radius:9px!important;padding:10px 12px!important;font:inherit!important;font-size:14px!important;line-height:1.5!important}
|
||||
.dv92-textarea{resize:vertical;min-height:85px}
|
||||
.dv92-edit-item .dv92-help{margin:10px 13px 0}
|
||||
.dv92-editor-actions{display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap;padding-top:14px}
|
||||
.dv92-btn{border:1px solid rgba(255,255,255,.2);border-radius:9px;padding:11px 14px;min-height:43px;cursor:pointer;font:inherit;font-size:13px}
|
||||
.dv92-primary{background:#e9a775;color:#16151b;font-weight:700;border-color:#ffc99c}
|
||||
.dv92-secondary{background:#323549;color:#fff}
|
||||
.dv92-btn:disabled{opacity:.5;cursor:not-allowed}
|
||||
.dv92-feedback{font-size:13px;color:#ffd2c3;min-height:1.2em;padding-top:8px}
|
||||
@media(max-width:650px){.dv92-editor{padding:13px;border-radius:14px}.dv92-editor-header h2{font-size:21px}.dv92-summary-mode{display:none}.dv92-editor-list{max-height:65vh}.dv92-menu{max-height:80vh}}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* DONA_VISION_V95 : panneau discret, compatible avec le hamburger V9.2 */
|
||||
.dv95-overlay[hidden],.dv95-toast[hidden],#dv95Feed[hidden],#dv95Stop[hidden],#dv95Start[hidden]{display:none!important}
|
||||
.dv95-overlay{position:fixed;inset:0;z-index:9800;background:rgba(3,5,12,.85);backdrop-filter:blur(9px);display:flex;align-items:center;justify-content:center;padding:12px;box-sizing:border-box}
|
||||
.dv95-frame{width:min(1000px,100%);max-height:95vh;overflow:auto;color:#faf8fb;background:#191c29;border:1px solid rgba(250,199,158,.32);border-radius:22px;padding:20px;box-sizing:border-box;box-shadow:0 20px 90px rgba(0,0,0,.6);font-family:inherit}
|
||||
.dv95-head{display:flex;align-items:start;justify-content:space-between;gap:15px;border-bottom:1px solid rgba(255,255,255,.14);padding-bottom:10px}.dv95-head h2{margin:0;font-size:22px}.dv95-muted{font-size:12px;color:#c1c7d5;line-height:1.45;margin:7px 0}
|
||||
.dv95-close{color:white;background:#353849;border:1px solid #6e7181;border-radius:50%;width:44px;height:44px;font-size:28px;cursor:pointer;flex:none}
|
||||
.dv95-body{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:20px;padding-top:15px}.dv95-column{min-width:0;display:flex;flex-direction:column;align-items:stretch;gap:9px}
|
||||
.dv95-column h3{font-size:15px;margin:12px 0 0;color:#ffe1c6}.dv95-preview{background:#090b12;border:1px solid rgba(255,255,255,.2);border-radius:12px;aspect-ratio:16/9;display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative}
|
||||
.dv95-preview img{width:100%;height:100%;object-fit:contain;position:absolute;inset:0}.dv95-preview .dv95-muted{text-align:center;padding:12px}.dv95-controls{display:flex;gap:8px;flex-wrap:wrap}.dv95-btn{border:1px solid rgba(255,255,255,.27);background:#303548;color:white;min-height:40px;padding:9px 13px;border-radius:10px;cursor:pointer;font-size:13px}.dv95-primary{background:#d89e73;color:#17161d;border-color:#ffbf91;font-weight:700}.dv95-stop{color:#ffcbc8}.dv95-btn:disabled{opacity:.45;cursor:wait}
|
||||
.dv95-choice{display:flex;gap:10px;align-items:center;font-size:13px}.dv95-choice input{width:19px;height:19px;accent-color:#e9af82}.dv95-status{font-size:13px;color:#e8c5aa;overflow-wrap:anywhere}.dv95-pills{display:flex;gap:7px;flex-wrap:wrap;min-height:32px}.dv95-pill{padding:6px 9px;font-size:12px;border-radius:16px;background:#383d52}.dv95-question{border:1px solid #565d78;background:#121723;color:#fff;border-radius:9px;padding:11px;min-height:82px;font:inherit;font-size:14px;resize:vertical;box-sizing:border-box;width:100%}.dv95-answer{white-space:pre-wrap;overflow-wrap:anywhere;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.14);border-radius:12px;min-height:70px;max-height:240px;overflow:auto;padding:13px;font-size:13px;line-height:1.55}.dv95-history{list-style:none;margin:0;padding:0;max-height:200px;overflow:auto}.dv95-history li{border-bottom:1px solid #43485b;padding:8px 0;font-size:13px}.dv95-history li p{color:#c7cbd8;font-size:12px;margin:5px 0}.dv95-toast{position:fixed;z-index:9950;bottom:24px;left:50%;transform:translateX(-50%);width:min(420px,calc(100vw - 35px));border:1px solid rgba(255,204,150,.5);background:rgba(26,28,40,.97);border-radius:14px;color:#fff;box-shadow:0 10px 45px #0009;padding:15px;display:grid;gap:5px;font-size:13px;pointer-events:none}
|
||||
@media(max-width:760px){.dv95-frame{padding:13px;border-radius:13px}.dv95-body{grid-template-columns:1fr;gap:14px}.dv95-head h2{font-size:19px}.dv95-preview{max-height:230px}}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* DONA_FILES_V91 — documents et images, contenu affiché exclusivement avec textContent. */
|
||||
(()=>{
|
||||
'use strict';
|
||||
if(window.DonaFilesV91)return;
|
||||
const $=id=>document.getElementById(id);
|
||||
const el=(tag,cls,text)=>{const n=document.createElement(tag);if(cls)n.className=cls;if(text!==undefined)n.textContent=String(text);return n;};
|
||||
const button=(text,fn,cls='df-button')=>{const b=el('button',cls,text);b.type='button';b.addEventListener('click',fn);return b;};
|
||||
let active=null, busy=false, previewURL=null;
|
||||
function status(text){if($('dfStatus'))$('dfStatus').textContent=String(text||'');}
|
||||
function setBusy(val){busy=val;for(const id of ['dfUpload','dfAnalyze','dfDrop','dfDelete']){const n=$(id);if(n)n.disabled=val;}}
|
||||
async function postJson(path,data){const response=await fetch(path,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-Alfred-Request':'1'},body:JSON.stringify(data)});const obj=await response.json().catch(()=>({}));if(!response.ok||obj.ok===false)throw Error(obj.error||'Erreur HTTP '+response.status);return obj;}
|
||||
function open(){if(!$('donaFilesV91'))init();$('donaFilesV91').hidden=false;document.body.classList.add('df-open');}
|
||||
function close(){if(busy)return;$('donaFilesV91').hidden=true;document.body.classList.remove('df-open');}
|
||||
function showAttachment(info,file){active=info;$('dfName').textContent=info.filename+' · '+(Math.round(info.size/1024))+' Ko';$('dfCurrent').hidden=false;$('dfEmpty').hidden=true;$('dfAnswer').textContent='';$('dfQuestion').value=info.kind==='image'?'Que vois-tu sur cette image ?':'Fais un résumé clair de ce document.';
|
||||
if(previewURL){URL.revokeObjectURL(previewURL);previewURL=null;}const picture=$('dfPreview');picture.hidden=true;picture.removeAttribute('src');
|
||||
if(info.kind==='image'&&file){previewURL=URL.createObjectURL(file);picture.src=previewURL;picture.hidden=false;}status('Fichier prêt. Tu peux demander une analyse.');}
|
||||
async function upload(file){if(!file||busy)return;if(file.size>10*1024*1024){status('Taille maximale : 10 Mo.');return;}setBusy(true);status('Téléversement…');try{const form=new FormData();form.append('file',file,file.name);const response=await fetch('/api/dona/files/upload',{method:'POST',credentials:'same-origin',headers:{'X-Alfred-Request':'1'},body:form});const obj=await response.json().catch(()=>({}));if(!response.ok||obj.ok===false)throw Error(obj.error||'Téléversement impossible.');const previous=active;showAttachment(obj,file);if(previous&&previous.id!==obj.id)postJson('/api/dona/files/delete',{id:previous.id}).catch(()=>{});}catch(e){status('Erreur : '+e.message);}finally{setBusy(false);}}
|
||||
async function analyze(){if(!active||busy){status('Ajoute d’abord un fichier.');return;}const question=String($('dfQuestion').value||'').trim();if(!question){status('Saisis une question.');return;}setBusy(true);status('Hermes analyse le fichier…');$('dfAnswer').textContent='';try{const result=await postJson('/api/dona/files/analyze',{id:active.id,question});$('dfAnswer').textContent=result.answer||'Aucune réponse.';status('Analyse terminée.');}catch(e){status('Erreur : '+e.message);}finally{setBusy(false);}}
|
||||
async function remove(){if(!active||busy)return;setBusy(true);try{await postJson('/api/dona/files/delete',{id:active.id});active=null;$('dfCurrent').hidden=true;$('dfEmpty').hidden=false;$('dfAnswer').textContent='';$('dfName').textContent='';$('dfInput').value='';status('Fichier effacé.');if(previewURL){URL.revokeObjectURL(previewURL);previewURL=null;}}catch(e){status(e.message);}finally{setBusy(false);}}
|
||||
function init(){if($('donaFilesV91'))return;const overlay=el('div','df-overlay');overlay.id='donaFilesV91';overlay.hidden=true;const panel=el('section','df-panel');panel.setAttribute('role','dialog');panel.setAttribute('aria-modal','true');panel.setAttribute('aria-label','Analyser un fichier avec Dona');
|
||||
const head=el('div','df-head');const heading=el('div');heading.append(el('span','df-eyebrow','DONA · PIÈCES JOINTES'),el('h2','','Analyser un document ou une photo'));head.append(heading,button('×',close,'df-close'));panel.append(head);
|
||||
const help=el('p','df-hint','PDF, Word (.docx), texte, Markdown, JPEG, PNG et WebP · 10 Mo max · Conservation temporaire 30 minutes · Pas d’indexation automatique.');panel.append(help);
|
||||
const zone=el('div','df-drop');zone.id='dfDrop';zone.setAttribute('role','group');zone.append(el('span','df-upload-icon','📎'),el('strong','','Dépose ton fichier ici ou sélectionne-le'));
|
||||
const fileInput=el('input','df-file');fileInput.type='file';fileInput.id='dfInput';fileInput.accept='.pdf,.docx,.txt,.md,.jpg,.jpeg,.png,.webp';fileInput.addEventListener('change',()=>{if(fileInput.files?.[0])upload(fileInput.files[0]);});zone.append(fileInput);
|
||||
const choose=button('Choisir un fichier',()=>fileInput.click(),'df-button df-primary');choose.id='dfUpload';zone.append(choose);zone.addEventListener('dragover',e=>{e.preventDefault();zone.classList.add('df-over');});zone.addEventListener('dragleave',()=>zone.classList.remove('df-over'));zone.addEventListener('drop',e=>{e.preventDefault();zone.classList.remove('df-over');if(e.dataTransfer.files?.[0])upload(e.dataTransfer.files[0]);});panel.append(zone);
|
||||
const empty=el('p','df-hint','Aucun fichier sélectionné.');empty.id='dfEmpty';panel.append(empty);
|
||||
const current=el('div','df-current');current.id='dfCurrent';current.hidden=true;const filename=el('div','df-filename');filename.id='dfName';const preview=el('img','df-preview');preview.id='dfPreview';preview.alt='Aperçu du fichier image sélectionné';preview.hidden=true;current.append(filename,preview);const del=button('Supprimer cette pièce jointe',remove,'df-button df-del');del.id='dfDelete';current.append(del);panel.append(current);
|
||||
const label=el('label','df-label','Que veux-tu savoir ?');label.setAttribute('for','dfQuestion');panel.append(label);const question=el('textarea','df-question');question.id='dfQuestion';question.rows=3;question.maxLength=1200;question.placeholder='Résume ce document, explique les points importants, analyse cette photo…';panel.append(question);
|
||||
const examples=el('div','df-examples');[['Résumé','Fais un résumé clair de ce document.'],['Points clés','Quels sont les points importants à retenir ?'],['Analyser','Analyse ce fichier et explique-moi ce qu’il contient.'],['Explication','Explique le contenu simplement.']].forEach(([name,q])=>examples.append(button(name,()=>{question.value=q;},'df-chip')));panel.append(examples);
|
||||
const run=button('Analyser avec Hermes',analyze,'df-button df-primary df-run');run.id='dfAnalyze';panel.append(run);
|
||||
const msg=el('p','df-status');msg.id='dfStatus';msg.setAttribute('role','status');panel.append(msg);
|
||||
const result=el('div','df-answer');result.id='dfAnswer';result.setAttribute('aria-live','polite');panel.append(result);
|
||||
panel.append(el('p','df-hint','Dona garde les fichiers en RAM 30 min ; Hermes peut conserver des traces de session. Le fournisseur IA utilisé dépend de la configuration Hermes. Vérifie-la avant d’envoyer des documents confidentiels. Les PDF scannés sans texte ne sont pas encore pris en charge.'));
|
||||
overlay.append(panel);document.body.append(overlay);overlay.addEventListener('click',e=>{if(e.target===overlay)close();});document.addEventListener('keydown',e=>{if(e.key==='Escape'&&!overlay.hidden)close();});
|
||||
// DONA_FILES_V911_COMPOSE : 📎 à droite du bouton d'envoi de « Écrire à Dona ».
|
||||
// Bouton de type button pour ne jamais soumettre le formulaire lors de son activation.
|
||||
function mountComposeAttachment(){
|
||||
const send=$('donaComposeSend');
|
||||
if(!send || !send.closest('.dona-compose-row'))return false;
|
||||
let launch=$('dfOpen');
|
||||
if(!launch){launch=button('📎',open,'df-compose-attach');launch.id='dfOpen';}
|
||||
launch.type='button';
|
||||
launch.classList.remove('av-round','df-launch');
|
||||
launch.classList.add('df-compose-attach');
|
||||
launch.title='Joindre un fichier à Dona';
|
||||
launch.setAttribute('aria-label','Joindre un document ou une photo');
|
||||
send.insertAdjacentElement('afterend',launch);
|
||||
return true;
|
||||
}
|
||||
if(!mountComposeAttachment()){
|
||||
let count=0;
|
||||
const timer=setInterval(()=>{
|
||||
if(mountComposeAttachment() || ++count>100)clearInterval(timer);
|
||||
},150);
|
||||
}
|
||||
const v9quick=document.querySelector('#donaSuiteV9 .dv9-quick');if(v9quick)v9quick.append(button('📎 Analyser un fichier',()=>{if(window.DonaSuiteV9?.close)window.DonaSuiteV9.close();open();},'dv9-chip'));
|
||||
window.alfredSocket?.on('dona_files_v91_result',result=>{if(result?.answer&&active?.id===result.id){$('dfAnswer').textContent=result.answer;status('Analyse vocale terminée.');}});
|
||||
}
|
||||
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init,{once:true});else init();
|
||||
window.DonaFilesV91={open,close};
|
||||
})();
|
||||
@@ -0,0 +1,82 @@
|
||||
/* DONA_LEARNING_V93 : feedback explicite, corrections modérées, aucun entraînement implicite. */
|
||||
(()=>{
|
||||
'use strict';
|
||||
if(window.DonaLearningV93)return;
|
||||
const el=(tag,cls,txt)=>{const e=document.createElement(tag);if(cls)e.className=cls;if(txt!==undefined)e.textContent=String(txt);return e;};
|
||||
const btn=(label,click,cls='dl93-button')=>{const b=el('button',cls,label);b.type='button';b.addEventListener('click',click);return b;};
|
||||
const field=(label,input)=>{const x=el('label','dl93-field');x.append(el('span','',label),input);return x;};
|
||||
const txt=(text,n=120)=>{const s=String(text||'');return s.length>n?s.slice(0,n)+'…':s;};
|
||||
const api=async(url,body)=>{const o=body===undefined?{cache:'no-store',credentials:'same-origin'}:{method:'POST',headers:{'Content-Type':'application/json','X-Alfred-Request':'1'},credentials:'same-origin',body:JSON.stringify(body)};const r=await fetch(url,o);const data=await r.json().catch(()=>({}));if(!r.ok||!data.ok)throw Error(data.error||'Erreur HTTP '+r.status);return data;};
|
||||
let last=null,dock,panel,dialog,menuTick=0,socketBound=false,submitting=false;
|
||||
function notify(message,bad=false){const n=document.getElementById('dl93Status');if(n){n.textContent=message||'';n.classList.toggle('dl93-error',bad);}}
|
||||
function showDock(){if(!last||!last.token)return;dock.hidden=false;dock.querySelector('.dl93-context').textContent=txt(last.heard||'Dernière demande',90);}
|
||||
function setTurn(d){if(!d||!d.token)return;last={token:d.token,heard:String(d.heard||''),answer:String(d.answer||''),source:d.source||'voice'};showDock();notify('');}
|
||||
function labelBtn(name,fn){return btn(name,fn,'dl93-tool');}
|
||||
function createDock(){dock=el('div','dl93-dock');dock.id='dl93Dock';dock.hidden=true;dock.setAttribute('role','region');dock.setAttribute('aria-label','Évaluer la dernière réponse de Dona');
|
||||
dock.append(el('span','dl93-context','Dernière réponse de Dona'),labelBtn('👍',()=>rateUp()),labelBtn('👎',()=>openCorrection()),labelBtn('Historique',()=>openPanel()));
|
||||
const close=labelBtn('×',()=>{dock.hidden=true;});close.title='Masquer les évaluations';close.setAttribute('aria-label','Masquer les évaluations');dock.append(close);document.body.append(dock);
|
||||
}
|
||||
async function rateUp(){if(!last||submitting)return;submitting=true;try{await api('/api/dona/v93/learning/feedback',{token:last.token,rating:'up'});dock.hidden=true;last=null;openToast('👍 Réponse enregistrée.');}catch(e){openToast(e.message,true);}finally{submitting=false;}}
|
||||
function openToast(message,bad=false){let box=document.getElementById('dl93Toast');if(!box){box=el('div','dl93-toast');box.id='dl93Toast';document.body.append(box);}box.textContent=message;box.classList.toggle('dl93-error',bad);box.hidden=false;setTimeout(()=>{box.hidden=true;},5500);}
|
||||
function makeDialog(){dialog=el('div','dl93-overlay');dialog.id='dl93Correction';dialog.hidden=true;dialog.setAttribute('role','dialog');dialog.setAttribute('aria-modal','true');dialog.setAttribute('aria-label','Corriger une réponse Dona');
|
||||
const sheet=el('div','dl93-sheet');
|
||||
const h=el('div','dl93-top');h.append(el('h3','', 'Corriger Dona'),btn('×',()=>closeCorrection(),'dl93-close'));sheet.append(h);
|
||||
const summary=el('div','dl93-summary');summary.id='dl93Summary';sheet.append(summary);
|
||||
const kind=document.createElement('select');kind.id='dl93Kind';[['transcription','Vosk a mal transcrit'],['comprehension','Hermes a mal compris'],['execution','Mauvaise action / erreur d’outil']].forEach(([v,l])=>{const opt=el('option','',l);opt.value=v;kind.append(opt);});
|
||||
sheet.append(field('Type d’erreur',kind));
|
||||
const correction=document.createElement('textarea');correction.id='dl93CorrectionText';correction.maxLength=1800;correction.rows=4;
|
||||
sheet.append(field('Ce que j’ai dit / ce qui était attendu',correction));
|
||||
const explanation=document.createElement('textarea');explanation.id='dl93Note';explanation.rows=2;explanation.maxLength=800;explanation.placeholder='Précision facultative';sheet.append(field('Commentaire',explanation));
|
||||
const note=el('p','dl93-hint','La correction restera en attente dans Apprentissage. Après validation : Vosk utilisera la correction pour la même phrase exacte ; Hermes recevra une indication pour cette demande précise. Aucune commande ne sera relancée automatiquement.');sheet.append(note);
|
||||
kind.addEventListener('change',()=>{correction.placeholder=kind.value==='transcription'?'Écris exactement les mots que tu avais prononcés…':kind.value==='comprehension'?'Explique ce que Dona devait comprendre / faire…':'Indique la bonne action ou l’équipement visé…';note.textContent=kind.value==='execution'?'Ce signalement sera conservé dans l’historique. Aucune règle d’exécution ne sera appliquée automatiquement.':'La correction restera en attente jusqu’à sa validation dans Apprentissage. Seules les formulations identiques seront corrigées.';});
|
||||
const actions=el('div','dl93-actions');actions.append(btn('Annuler',closeCorrection,'dl93-button dl93-neutral'),btn('Enregistrer 👎',submitBad));sheet.append(actions);
|
||||
const state=el('p','dl93-state');state.id='dl93CorrectionStatus';state.setAttribute('role','status');sheet.append(state);
|
||||
dialog.append(sheet);document.body.append(dialog);dialog.addEventListener('pointerdown',e=>{if(e.target===dialog)closeCorrection();});
|
||||
}
|
||||
function openCorrection(){if(!last){openToast('Aucune réponse récente.');return;}dialog.hidden=false;const raw=last.heard||'Transcription indisponible';document.getElementById('dl93Summary').replaceChildren(el('p','','Dona a entendu : '+txt(raw,500)),el('p','','Réponse : '+txt(last.answer,500)));const kind=document.getElementById('dl93Kind');kind.value='transcription';const c=document.getElementById('dl93CorrectionText');c.value='';c.placeholder='Écris exactement les mots que tu avais prononcés…';document.getElementById('dl93Note').value='';document.getElementById('dl93CorrectionStatus').textContent='';kind.dispatchEvent(new Event('change'));c.focus();}
|
||||
function closeCorrection(){if(dialog)dialog.hidden=true;}
|
||||
async function submitBad(){if(!last||submitting)return;const kind=document.getElementById('dl93Kind').value;const correction=document.getElementById('dl93CorrectionText').value;const note=document.getElementById('dl93Note').value;const error=document.getElementById('dl93CorrectionStatus');submitting=true;
|
||||
try{await api('/api/dona/v93/learning/feedback',{token:last.token,rating:'down',kind,correction,note});closeCorrection();last=null;dock.hidden=true;openToast('👎 Correction enregistrée. Valide-la dans Apprentissage pour l’activer.');}
|
||||
catch(e){error.textContent=e.message;error.classList.add('dl93-error');}
|
||||
finally{submitting=false;}}
|
||||
function makePanel(){panel=el('div','dl93-overlay');panel.id='dl93Panel';panel.hidden=true;panel.setAttribute('role','dialog');panel.setAttribute('aria-modal','true');panel.setAttribute('aria-label','Historique des corrections Dona');
|
||||
const sheet=el('div','dl93-sheet dl93-history');const top=el('div','dl93-top');top.append(el('h3','','Apprentissage de Dona'),btn('×',closePanel,'dl93-close'));sheet.append(top);
|
||||
const intro=el('p','dl93-hint','Historique local des réponses évaluées. Aucun son enregistré. Les règles doivent être approuvées manuellement et peuvent être retirées à tout moment.');sheet.append(intro);
|
||||
const content=el('div','dl93-panel-body');content.id='dl93PanelContent';sheet.append(content);
|
||||
const foot=el('div','dl93-actions');foot.append(btn('Actualiser',loadPanel,'dl93-button dl93-neutral'),btn('Fermer',closePanel));sheet.append(foot);
|
||||
const state=el('p','dl93-state');state.id='dl93Status';state.setAttribute('role','status');sheet.append(state);panel.append(sheet);document.body.append(panel);panel.addEventListener('pointerdown',e=>{if(e.target===panel)closePanel();});
|
||||
}
|
||||
async function openPanel(){panel.hidden=false;await loadPanel();}
|
||||
function closePanel(){if(panel)panel.hidden=true;}
|
||||
function prettyKind(k){return({transcription:'Vosk / transcription',comprehension:'Compréhension Hermes',execution:'Exécution'})[k]||'Avis';}
|
||||
function chip(s){const v={approved:'Règle active',pending:'À valider',recorded:'Enregistré',rejected:'Rejeté',revoked:'Règle retirée'};return el('span','dl93-chip',v[s]||s);}
|
||||
function itemRow(item,content){const card=el('article','dl93-record');const top=el('div','dl93-record-head');top.append(el('strong','',item.rating==='up'?'👍 Correct':'👎 '+prettyKind(item.kind)),chip(item.status));card.append(top);
|
||||
card.append(el('p','dl93-small','Entendu : '+txt(item.heard,260)));if(item.answer)card.append(el('p','dl93-small','Réponse : '+txt(item.answer,180)));
|
||||
if(item.correction)card.append(el('p','dl93-small','Correction : '+txt(item.correction,260)));
|
||||
if(item.note)card.append(el('p','dl93-small','Note : '+txt(item.note,180)));
|
||||
if(item.status==='pending'){
|
||||
const actions=el('div','dl93-actions');
|
||||
actions.append(btn('✓ Valider la règle',async()=>{if(!confirm('Appliquer cette correction aux prochaines demandes identiques ?'))return;await change('/api/dona/v93/learning/'+item.id+'/approve');},'dl93-button'));
|
||||
actions.append(btn('Rejeter',async()=>{await change('/api/dona/v93/learning/'+item.id+'/reject');},'dl93-button dl93-neutral'));card.append(actions);
|
||||
}
|
||||
const remove=btn('Supprimer cette évaluation',async()=>{if(confirm('Supprimer cette évaluation et sa règle éventuelle ?'))await change('/api/dona/v93/learning/'+item.id+'/delete');},'dl93-button dl93-neutral');card.append(remove);
|
||||
content.append(card);}
|
||||
async function change(url){try{await api(url,{});await loadPanel();}catch(e){notify(e.message,true);}}
|
||||
async function loadPanel(){const content=document.getElementById('dl93PanelContent');if(!content)return;content.replaceChildren(el('p','','Chargement…'));notify('');try{
|
||||
const data=await api('/api/dona/v93/learning');content.replaceChildren();content.append(el('h4','','Évaluations : '+data.stats.positive+' 👍 · '+data.stats.negative+' 👎'));
|
||||
if(data.rules.length){const rules=el('section','dl93-rules');rules.append(el('h4','','Règles actives ('+data.rules.length+')'));
|
||||
for(const r of data.rules){const row=el('div','dl93-rule');row.append(el('span','',prettyKind(r.kind)+' : '+txt(r.original,90)+' → '+txt(r.replacement,90)),btn('Retirer',async()=>{if(confirm('Supprimer cette règle ?'))await change('/api/dona/v93/learning/rules/'+r.id+'/remove');},'dl93-button dl93-neutral'));rules.append(row);}content.append(rules);}
|
||||
if(!data.history.length)content.append(el('p','dl93-small','Aucune réponse évaluée pour le moment.'));
|
||||
data.history.forEach(f=>itemRow(f,content));
|
||||
}catch(e){content.replaceChildren(el('p','dl93-error',e.message));}}
|
||||
function attachMenu(){const m=document.getElementById('dv92ToolsMenu');if(!m||m.hidden||m.querySelector('#dl93MenuEntry'))return;const b=btn('🎓 Apprentissage et corrections',()=>{m.hidden=true;document.getElementById('dv92Hamburger')?.setAttribute('aria-expanded','false');openPanel();},'dv92-menu-entry');b.id='dl93MenuEntry';m.append(b);}
|
||||
function init(){if(document.getElementById('dl93Dock'))return;createDock();makeDialog();makePanel();document.addEventListener('click',e=>{if(e.target.closest('#dv92Hamburger'))window.setTimeout(attachMenu,10);});document.addEventListener('keydown',e=>{if(e.key==='Escape'){closeCorrection();closePanel();}});
|
||||
const waitForSocket=()=>{const sock=window.alfredSocket;if(!sock?.on){if(++menuTick<80)setTimeout(waitForSocket,150);return;}if(socketBound)return;socketBound=true;
|
||||
sock.on('dona_learning_turn',setTurn);
|
||||
sock.on('dona_learning_stt',data=>{const n=document.getElementById('dl93Transcript');if(n){n.textContent='Vosk : '+data.raw+' → Correction : '+data.used;n.hidden=false;}});
|
||||
sock.on('alfred_state',state=>{if(state?.mode==='thinking'){if(dock)dock.hidden=true;if(document.getElementById('dl93Transcript'))document.getElementById('dl93Transcript').hidden=true;}});
|
||||
};waitForSocket();
|
||||
const t=el('div','dl93-transcript');t.id='dl93Transcript';t.hidden=true;document.body.append(t);
|
||||
window.DonaLearningV93={openPanel,openCorrection};}
|
||||
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init,{once:true});else init();
|
||||
})();
|
||||
@@ -0,0 +1,59 @@
|
||||
/* DONA_UI_V921_CLOSE — Répare le panneau Raccourcis V9.2. */
|
||||
(() => {
|
||||
'use strict';
|
||||
if (window.DonaUIV921Close) return;
|
||||
let attempts = 0;
|
||||
function init() {
|
||||
const root = document.getElementById('alfredMainV1');
|
||||
const tray = root?.querySelector('.dona-tools-tray');
|
||||
const grid = tray?.querySelector('.av-shortcuts');
|
||||
const toolbar = tray?.querySelector('.dv92-shortcut-toolbar');
|
||||
if (!grid || !toolbar || !root?.querySelector('#dv92Hamburger')) {
|
||||
if (++attempts < 80) window.setTimeout(init, 150);
|
||||
return;
|
||||
}
|
||||
if (tray.dataset.dv921Close === 'ready') return;
|
||||
tray.dataset.dv921Close = 'ready';
|
||||
const closeTray = () => { tray.open = false; };
|
||||
const heading = document.createElement('div');
|
||||
heading.className = 'dv921-tray-heading';
|
||||
const label = document.createElement('span');
|
||||
label.textContent = 'Raccourcis';
|
||||
const close = document.createElement('button');
|
||||
close.type = 'button';
|
||||
close.className = 'dv921-tray-close';
|
||||
close.textContent = '×';
|
||||
close.title = 'Fermer les raccourcis';
|
||||
close.setAttribute('aria-label', 'Fermer les raccourcis');
|
||||
close.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
closeTray();
|
||||
});
|
||||
heading.append(label, close);
|
||||
// V9.2 régénère la grille après une modification : réinstaller l'entête.
|
||||
const ensureHeading = () => {
|
||||
if (grid.firstElementChild !== heading) grid.prepend(heading);
|
||||
};
|
||||
ensureHeading();
|
||||
new MutationObserver(ensureHeading).observe(grid, { childList: true });
|
||||
// Fermer sur clic à l'extérieur, sans bloquer les autres commandes.
|
||||
document.addEventListener('pointerdown', (event) => {
|
||||
if (tray.open && !tray.contains(event.target)) closeTray();
|
||||
});
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Escape' && tray.open) closeTray();
|
||||
});
|
||||
// Fermer aussi lorsqu'un raccourci est lancé.
|
||||
grid.addEventListener('click', (event) => {
|
||||
if (event.target.closest('button.dv92-shortcut')) closeTray();
|
||||
});
|
||||
// L'éditeur ne nécessite pas que le panneau reste ouvert derrière lui.
|
||||
toolbar.addEventListener('click', (event) => {
|
||||
if (event.target.closest('.dv92-edit-open')) closeTray();
|
||||
});
|
||||
window.DonaUIV921Close = { close: closeTray };
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init, { once: true });
|
||||
} else init();
|
||||
})();
|
||||
@@ -0,0 +1,143 @@
|
||||
/* DONA_UI_V92 — Hamburger + raccourcis éditables, sans dupliquer les contrôleurs. */
|
||||
(()=>{
|
||||
'use strict';
|
||||
if(window.DonaUIV92)return;
|
||||
const $=id=>document.getElementById(id);
|
||||
const create=(tag,cls,text)=>{const el=document.createElement(tag);if(cls)el.className=cls;if(text!==undefined)el.textContent=String(text);return el;};
|
||||
const button=(text,fn,cls='dv92-btn')=>{const b=create('button',cls,text);b.type='button';b.addEventListener('click',fn);return b;};
|
||||
const icons={clock:'◷','cloud-sun':'☀','house':'⌂',server:'▤','shield-check':'⬡',image:'▧','chef-hat':'♨','calendar-days':'▦',sun:'☼',lightbulb:'♧','list-checks':'☷',music:'♫',youtube:'▶',map:'⌖',camera:'▣','book-open':'▤',sparkles:'✦',brain:'✧',settings:'⚙',bell:'♧',zap:'ϟ',star:'☆','file-text':'▤',terminal:'⌘'};
|
||||
const labels={clock:'Horloge','cloud-sun':'Météo',house:'Maison',server:'Serveur','shield-check':'Sécurité',image:'Image','chef-hat':'Cuisine','calendar-days':'Agenda',sun:'Soleil',lightbulb:'Lumière','list-checks':'Liste',music:'Musique',youtube:'YouTube',map:'Carte',camera:'Caméra','book-open':'Livre',sparkles:'Étoile',brain:'IA',settings:'Réglages',bell:'Notification',zap:'Éclair',star:'Favori','file-text':'Document',terminal:'Terminal'};
|
||||
const builtins=new Set(['time','weather','house','proxmox','wazuh','comfyui']);
|
||||
const builtinTitles={time:'Quelle heure est-il ?',weather:'Météo',house:'État de la maison',proxmox:'Vérifier Proxmox',wazuh:'Alertes Wazuh',comfyui:'Créer une image'};
|
||||
const fallback=['time','weather','house','proxmox','wazuh','comfyui'].map((id,i)=>({id,title:builtinTitles[id],icon:['clock','cloud-sun','house','server','shield-check','image'][i],prompt:builtinTitles[id],visible:true,mode:'native',action:id}));
|
||||
let items=fallback.map(x=>({...x}));let editing=false,draft=[];let sending=false;
|
||||
let header,bar,menu,burger,editDialog,tray,shortcutHost,status;
|
||||
function msg(text){if(status)status.textContent=String(text||'');}
|
||||
function request(url,body){return fetch(url,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-Alfred-Request':'1'},body:JSON.stringify(body)}).then(async r=>{let data=await r.json().catch(()=>({}));if(!r.ok||data.ok===false)throw Error(data.error||'Erreur '+r.status);return data;});}
|
||||
function icon(key){return create('span','dv92-symbol',icons[key]||'✦');}
|
||||
function closeMenu(){if(!menu)return;menu.hidden=true;burger?.setAttribute('aria-expanded','false');}
|
||||
function positionMenu(){if(!menu||menu.hidden)return;const rect=burger.getBoundingClientRect();let left=Math.min(rect.right-menu.offsetWidth,window.innerWidth-menu.offsetWidth-8);left=Math.max(8,left);let top=rect.bottom+9;if(top+menu.offsetHeight>window.innerHeight-8)top=Math.max(8,rect.top-menu.offsetHeight-9);menu.style.left=left+'px';menu.style.top=top+'px';}
|
||||
function showMenu(){menu.hidden=!menu.hidden;burger.setAttribute('aria-expanded',String(!menu.hidden));if(!menu.hidden){renderMenu();positionMenu();}}
|
||||
function renderMenu(){
|
||||
menu.replaceChildren(create('div','dv92-menu-heading','Outils Dona'));
|
||||
const controls=Array.from(bar.children).filter(x=>x!==burger&&x.id!=='avTopMic');
|
||||
for(const original of controls){
|
||||
const title=(original.getAttribute('aria-label')||original.title||original.textContent||'Outil').trim();
|
||||
const proxy=button('',()=>{closeMenu();original.click();},'dv92-menu-entry');
|
||||
const ico=original.querySelector('svg');
|
||||
if(ico){const svg=ico.cloneNode(true);svg.removeAttribute('id');svg.setAttribute('aria-hidden','true');proxy.append(svg);}
|
||||
else proxy.append(create('span','dv92-menu-symbol',(original.textContent||'•').trim().slice(0,2)));
|
||||
proxy.append(create('span','',title));menu.append(proxy);
|
||||
}
|
||||
menu.append(create('div','dv92-menu-rule'));
|
||||
menu.append(button('✎ Modifier les raccourcis',()=>{closeMenu();openEditor();},'dv92-menu-entry dv92-menu-edit'));
|
||||
}
|
||||
function initHeader(root){
|
||||
bar=root.querySelector('.av-head-actions');if(!bar)return;
|
||||
burger=button('☰',showMenu,'av-round dv92-hamburger');burger.id='dv92Hamburger';burger.setAttribute('aria-label','Ouvrir le menu des outils');burger.setAttribute('aria-expanded','false');burger.setAttribute('aria-controls','dv92ToolsMenu');burger.title='Menu des outils';
|
||||
bar.append(burger);
|
||||
menu=create('div','dv92-menu');menu.id='dv92ToolsMenu';menu.hidden=true;menu.setAttribute('role','group');menu.setAttribute('aria-label','Outils Dona');document.body.append(menu);
|
||||
renderMenu();
|
||||
const observer=new MutationObserver(()=>{if(!menu.hidden){renderMenu();positionMenu();}});observer.observe(bar,{childList:true});
|
||||
window.addEventListener('resize',positionMenu,{passive:true});window.addEventListener('scroll',positionMenu,{passive:true});
|
||||
document.addEventListener('pointerdown',e=>{if(!menu.hidden&&!menu.contains(e.target)&&!burger.contains(e.target))closeMenu();});
|
||||
document.addEventListener('keydown',e=>{if(e.key==='Escape'){closeMenu();closeEditor();}});
|
||||
}
|
||||
async function submitPrompt(prompt){
|
||||
if(sending)return;sending=true;msg('Transmission à Dona…');
|
||||
try{const x=await request('/api/dona/texte',{message:prompt});msg(x.message||'Demande transmise à Dona.');}
|
||||
catch(e){msg('Erreur : '+e.message);}
|
||||
finally{sending=false;}
|
||||
}
|
||||
function drawShortcuts(){
|
||||
if(!shortcutHost)return;
|
||||
shortcutHost.replaceChildren();
|
||||
for(const item of items.filter(x=>x.visible)){
|
||||
const b=button('',()=>{},'dv92-shortcut');b.replaceChildren(icon(item.icon),create('span','',item.title));b.title=item.mode==='prompt'?item.prompt:item.title;
|
||||
if(item.mode==='native'&&builtins.has(item.id)){
|
||||
b.dataset.avAction=item.action;
|
||||
// The original delegated handler on #alfredMainV1 handles native actions.
|
||||
}else{
|
||||
b.addEventListener('click',e=>{e.stopPropagation();submitPrompt(item.prompt);});
|
||||
}
|
||||
shortcutHost.append(b);
|
||||
}
|
||||
if(!shortcutHost.children.length)shortcutHost.append(create('p','dv92-shortcut-empty','Aucun raccourci visible. Clique sur Modifier pour en ajouter.'));
|
||||
}
|
||||
function editorButton(){
|
||||
tray=shortcutHost.closest('.dona-tools-tray');if(!tray)return;
|
||||
const tools=create('div','dv92-shortcut-toolbar');tools.append(button('✎ Modifier les raccourcis',openEditor,'dv92-edit-open'));status=create('span','dv92-shortcut-status');status.setAttribute('role','status');status.setAttribute('aria-live','polite');tools.append(status);
|
||||
shortcutHost.before(tools);
|
||||
}
|
||||
function openEditor(){
|
||||
if(!editDialog)return;
|
||||
draft=items.map(x=>({...x}));editing=true;drawEditor();editDialog.hidden=false;document.body.classList.add('dv92-editing');
|
||||
}
|
||||
function closeEditor(){if(!editDialog||!editing)return;editing=false;editDialog.hidden=true;document.body.classList.remove('dv92-editing');}
|
||||
function editorFields(item,index,host){
|
||||
const summary=create('summary','dv92-item-summary');summary.append(icon(item.icon),create('strong','dv92-summary-name',item.title),create('span','dv92-summary-mode',item.mode==='native'?'Action intégrée':'Texte personnalisé'));
|
||||
const detail=create('details','dv92-edit-item');detail.append(summary);
|
||||
const controls=create('div','dv92-inline-controls');
|
||||
const up=button('↑',()=>move(index,-1),'dv92-small');up.title='Monter';up.disabled=index===0;
|
||||
const down=button('↓',()=>move(index,1),'dv92-small');down.title='Descendre';down.disabled=index===draft.length-1;
|
||||
const visible=create('label','dv92-check');const check=create('input');check.type='checkbox';check.checked=item.visible;check.addEventListener('change',()=>{item.visible=check.checked;});visible.append(check,create('span','', 'Afficher'));
|
||||
const del=button('Supprimer',()=>{if(confirm('Supprimer ce raccourci ?')){draft.splice(index,1);drawEditor();}},'dv92-small dv92-danger');
|
||||
controls.append(visible,up,down,del);detail.append(controls);
|
||||
function field(labelText,control){const box=create('label','dv92-field');box.append(create('span','',labelText),control);return box;}
|
||||
const title=create('input','dv92-input');title.type='text';title.maxLength=70;title.value=item.title;title.required=true;title.addEventListener('input',()=>{item.title=title.value;summary.querySelector('.dv92-summary-name').textContent=title.value;});
|
||||
detail.append(field('Nom affiché',title));
|
||||
const pick=create('select','dv92-input');for(const [key,label] of Object.entries(labels)){const o=create('option','',`${icons[key]} ${label}`);o.value=key;o.selected=key===item.icon;pick.append(o);}pick.addEventListener('change',()=>{item.icon=pick.value;summary.querySelector('.dv92-symbol').textContent=icons[pick.value];});
|
||||
detail.append(field('Icône',pick));
|
||||
const how=create('select','dv92-input');const nativeOption=create('option','', 'Action intégrée (fonctionnement d’origine)');nativeOption.value='native';const promptOption=create('option','', 'Envoyer mon texte à Dona / Hermes');promptOption.value='prompt';if(builtins.has(item.id))how.append(nativeOption);how.append(promptOption);how.value=item.mode;
|
||||
how.addEventListener('change',()=>{item.mode=how.value;summary.querySelector('.dv92-summary-mode').textContent=how.value==='native'?'Action intégrée':'Texte personnalisé';});
|
||||
detail.append(field('Quand je touche ce raccourci',how));
|
||||
const prompt=create('textarea','dv92-textarea');prompt.rows=3;prompt.maxLength=1600;prompt.value=item.prompt;prompt.addEventListener('input',()=>{item.prompt=prompt.value;if(item.mode==='native'){item.mode='prompt';how.value='prompt';summary.querySelector('.dv92-summary-mode').textContent='Texte personnalisé';}});
|
||||
detail.append(field('Texte exact envoyé à Dona',prompt));
|
||||
detail.append(create('p','dv92-help', 'Modifier ce texte active automatiquement le mode « Texte personnalisé ». Les commandes passent par le formulaire écrit de Dona, sans synthèse vocale.'));
|
||||
host.append(detail);
|
||||
}
|
||||
function move(i,d){const j=i+d;if(j<0||j>=draft.length)return;[draft[i],draft[j]]=[draft[j],draft[i]];drawEditor();}
|
||||
function drawEditor(){const target=$('dv92EditorRows');if(!target)return;target.replaceChildren();draft.forEach((item,i)=>editorFields(item,i,target));$('dv92EditorCount').textContent=draft.length+' / 35';}
|
||||
async function saveEditor(){
|
||||
const save=$('dv92Save');save.disabled=true;
|
||||
try{const data=await request('/api/dona/v92/shortcuts',{items:draft});items=data.items;drawShortcuts();closeEditor();msg('Raccourcis enregistrés.');}
|
||||
catch(e){$('dv92EditorStatus').textContent='Erreur : '+e.message;}
|
||||
finally{save.disabled=false;}
|
||||
}
|
||||
async function resetEditor(){
|
||||
if(!confirm('Restaurer les raccourcis d’origine ? Tes modifications seront perdues.'))return;
|
||||
try{const data=await request('/api/dona/v92/shortcuts/reset',{});items=data.items;draft=items.map(x=>({...x}));drawEditor();drawShortcuts();$('dv92EditorStatus').textContent='Raccourcis réinitialisés.';}
|
||||
catch(e){$('dv92EditorStatus').textContent='Erreur : '+e.message;}
|
||||
}
|
||||
function addShortcut(){
|
||||
if(draft.length>=35){$('dv92EditorStatus').textContent='Maximum de 35 raccourcis.';return;}
|
||||
const uniq=()=>('user_'+Math.random().toString(36).slice(2,12)+Date.now().toString(36));
|
||||
draft.push({id:uniq(),title:'Nouveau raccourci',icon:'sparkles',prompt:'Dona, ',visible:true,mode:'prompt',action:''});drawEditor();
|
||||
const last=$('dv92EditorRows').lastElementChild;last.open=true;last.querySelector('.dv92-input')?.focus();
|
||||
}
|
||||
function initEditor(){
|
||||
editDialog=create('div','dv92-editor-overlay');editDialog.id='dv92Editor';editDialog.hidden=true;
|
||||
const panel=create('section','dv92-editor');panel.setAttribute('role','dialog');panel.setAttribute('aria-modal','true');panel.setAttribute('aria-label','Modifier les raccourcis Dona');
|
||||
const heading=create('div','dv92-editor-header');const title=create('div');title.append(create('small','', 'DONA · PERSONNALISATION'),create('h2','', 'Mes raccourcis'));
|
||||
heading.append(title,button('×',closeEditor,'dv92-close'));panel.append(heading);
|
||||
panel.append(create('p','dv92-help','Renomme, classe ou masque tes raccourcis. Modifie « Texte exact envoyé à Dona » pour personnaliser leur commande.'));
|
||||
const counter=create('div','dv92-count');counter.id='dv92EditorCount';panel.append(counter);
|
||||
const list=create('div','dv92-editor-list');list.id='dv92EditorRows';panel.append(list);
|
||||
const bottom=create('div','dv92-editor-actions');bottom.append(button('+ Ajouter un raccourci',addShortcut,'dv92-btn dv92-secondary'),button('↺ Réinitialiser',resetEditor,'dv92-btn dv92-secondary'),button('Annuler',closeEditor,'dv92-btn dv92-secondary'));
|
||||
const save=button('Enregistrer',saveEditor,'dv92-btn dv92-primary');save.id='dv92Save';bottom.append(save);panel.append(bottom);
|
||||
const message=create('div','dv92-feedback');message.id='dv92EditorStatus';message.setAttribute('role','status');panel.append(message);editDialog.append(panel);document.body.append(editDialog);
|
||||
editDialog.addEventListener('pointerdown',e=>{if(e.target===editDialog)closeEditor();});
|
||||
}
|
||||
async function loadShortcuts(){
|
||||
try{const response=await fetch('/api/dona/v92/shortcuts',{credentials:'same-origin',cache:'no-store'});const data=await response.json();if(!response.ok||!data.ok)throw Error(data.error||'Erreur de lecture');items=data.items;drawShortcuts();}
|
||||
catch(e){drawShortcuts();msg('Raccourcis par défaut. Configuration indisponible : '+e.message);}
|
||||
}
|
||||
function init(){
|
||||
const root=$('alfredMainV1');if(!root||!root.querySelector('.av-head-actions')||!root.querySelector('.av-shortcuts'))return false;
|
||||
shortcutHost=root.querySelector('.av-shortcuts');
|
||||
initHeader(root);editorButton();initEditor();loadShortcuts();
|
||||
window.DonaUIV92={openEditor};return true;
|
||||
}
|
||||
let tries=0;function ready(){if(!init()&&tries++<80)setTimeout(ready,150);}
|
||||
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',ready,{once:true});else ready();
|
||||
})();
|
||||
@@ -0,0 +1,67 @@
|
||||
/* DONA_VISION_V95 : YOLOv8 local opt-in et image Hermes sur demande. */
|
||||
(()=>{'use strict';if(window.DonaVisionV95)return;
|
||||
const $=id=>document.getElementById(id);
|
||||
const el=(tag,cls,text)=>{const n=document.createElement(tag);if(cls)n.className=cls;if(text!==undefined)n.textContent=String(text);return n};
|
||||
const btn=(text,action,cls)=>{const n=el('button',cls||'dv95-btn',text);n.type='button';n.addEventListener('click',action);return n};
|
||||
let opened=false,busy=false,monitoring=false,toastTimer;
|
||||
async function request(url,data){const r=await fetch(url,{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-Alfred-Request':'1'},body:JSON.stringify(data)});const out=await r.json().catch(()=>({}));if(!r.ok||out.ok===false)throw Error(out.error||'Erreur '+r.status);return out}
|
||||
async function getStatus(){const r=await fetch('/api/dona/vision/v95/status',{credentials:'same-origin'});if(!r.ok)throw Error('État indisponible');return r.json()}
|
||||
function message(value){const n=$('dv95Status');if(n)n.textContent=String(value||'')}
|
||||
function render(data){monitoring=!!data.running;$('dv95Start').hidden=monitoring;$('dv95Stop').hidden=!monitoring;$('dv95People').disabled=monitoring;$('dv95Objects').disabled=monitoring;
|
||||
message((data.message||'')+(data.ultralytics_installed?'':' · YOLOv8 à installer')+(data.model_ready?'':' · modèle absent'));
|
||||
$('dv95Model').textContent='Modèle : '+(data.model||'yolov8n.pt')+' · balayage '+(data.interval||2.5)+' s';
|
||||
const objects=$('dv95Detections');objects.replaceChildren();(data.latest||[]).slice(0,10).forEach(x=>objects.append(el('span','dv95-pill',x.label+' · '+Math.round(x.confidence*100)+' %')));
|
||||
if(!objects.children.length)objects.append(el('span','dv95-muted','Aucune détection récente.'));
|
||||
const history=$('dv95History');history.replaceChildren();(data.events||[]).forEach(x=>{const n=el('li');n.append(el('strong','',x.time+' · '+x.title),el('p','',x.detail));history.append(n)});
|
||||
if(!history.children.length)history.append(el('li','dv95-muted','Aucun événement pour cette session.'));
|
||||
}
|
||||
async function refresh(){try{render(await getStatus())}catch(e){message(e.message)}}
|
||||
async function setMonitor(enabled){if(busy)return;busy=true;message(enabled?'Démarrage YOLOv8…':'Arrêt en cours…');
|
||||
try{const x=await request('/api/dona/vision/v95/monitor',{enabled,person:$('dv95People').checked,objects:$('dv95Objects').checked});render(x)}catch(e){message(e.message)}finally{busy=false}}
|
||||
async function analyze(){if(busy)return;busy=true;$('dv95Analyze').disabled=true;const question=$('dv95Question').value.trim()||'Décris ce que tu vois devant toi.';
|
||||
$('dv95Answer').textContent='Analyse de la capture par Hermes en cours…';
|
||||
try{const x=await request('/api/dona/vision/v95/analyze',{question});$('dv95Answer').textContent=x.answer||'Pas de description.'}
|
||||
catch(e){$('dv95Answer').textContent=e.message}finally{busy=false;$('dv95Analyze').disabled=false}}
|
||||
function startPreview(){const img=$('dv95Feed');if(img.src)return;img.src='/api/camera/stream?v=95&t='+Date.now();img.hidden=false;$('dv95PreviewHint').textContent='L’aperçu est local et non enregistré. Si la caméra est déjà utilisée ailleurs, ferme l’autre aperçu.';}
|
||||
function stopPreview(){const img=$('dv95Feed');img.removeAttribute('src');img.hidden=true;$('dv95PreviewHint').textContent='Aperçu coupé.'}
|
||||
function open(){opened=true;$('dv95Modal').hidden=false;refresh()}
|
||||
function close(){opened=false;$('dv95Modal').hidden=true;stopPreview()}
|
||||
function toast(evt){let box=$('dv95Toast');if(!box)return;box.replaceChildren(el('strong','',evt.title||'Vision Dona'),el('span','',evt.detail||''));box.hidden=false;clearTimeout(toastTimer);toastTimer=setTimeout(()=>{box.hidden=true},8500)}
|
||||
function init(){const modal=el('div','dv95-overlay');modal.id='dv95Modal';modal.hidden=true;modal.setAttribute('role','dialog');modal.setAttribute('aria-modal','true');modal.setAttribute('aria-label','Vision intelligente');
|
||||
const frame=el('section','dv95-frame');const head=el('header','dv95-head');const h=el('div');h.append(el('h2','','◉ Vision intelligente'),el('p','dv95-muted','Détection locale YOLOv8 · analyse ponctuelle Hermes'));
|
||||
head.append(h,btn('×',close,'dv95-close'));frame.append(head);
|
||||
const content=el('div','dv95-body');const left=el('div','dv95-column');const right=el('div','dv95-column');
|
||||
const video=el('div','dv95-preview');const img=el('img');img.id='dv95Feed';img.alt='Aperçu caméra locale';img.hidden=true;const info=el('p','dv95-muted','Aperçu caméra arrêté.');info.id='dv95PreviewHint';video.append(img,info);left.append(video);
|
||||
const previewBtns=el('div','dv95-controls');previewBtns.append(btn('Afficher la caméra',startPreview),btn('Couper l’aperçu',stopPreview));left.append(previewBtns);
|
||||
left.append(el('h3','','Surveillance des événements'));
|
||||
const c1=el('label','dv95-choice');const p=el('input');p.type='checkbox';p.id='dv95People';p.checked=true;c1.append(p,el('span','','Apparition d’une personne'));
|
||||
const c2=el('label','dv95-choice');const o=el('input');o.type='checkbox';o.id='dv95Objects';o.checked=true;c2.append(o,el('span','','Objet visible au centre de la caméra'));
|
||||
left.append(c1,c2);
|
||||
const run=el('div','dv95-controls');const start=btn('▶ Activer YOLOv8',()=>setMonitor(true),'dv95-btn dv95-primary');start.id='dv95Start';const stop=btn('■ Arrêter YOLOv8',()=>setMonitor(false),'dv95-btn dv95-stop');stop.id='dv95Stop';stop.hidden=true;run.append(start,stop);left.append(run);
|
||||
const status=el('p','dv95-status','Surveillance désactivée.');status.id='dv95Status';left.append(status);const model=el('p','dv95-muted','');model.id='dv95Model';left.append(model);
|
||||
const detections=el('div','dv95-pills');detections.id='dv95Detections';left.append(el('h3','','Dernières détections'),detections);
|
||||
right.append(el('h3','','Demander à Hermes ce que voit Dona'));
|
||||
const question=el('textarea','dv95-question');question.id='dv95Question';question.rows=3;question.maxLength=600;question.value='Décris les objets et les personnes visibles. Ne devine pas leur identité.';right.append(question);
|
||||
const analyzeBtn=btn('◉ Analyser une capture',analyze,'dv95-btn dv95-primary');analyzeBtn.id='dv95Analyze';right.append(analyzeBtn);
|
||||
const answer=el('div','dv95-answer','L’analyse est déclenchée uniquement sur demande.');answer.id='dv95Answer';right.append(answer);
|
||||
right.append(btn('◎ Identifier une personne (MCP facial)',()=>{close();const face=$('donaFaceButton');if(face)face.click();else message('Le MCP facial V7 est indisponible.');}));
|
||||
right.append(el('h3','','Événements récents'));const history=el('ul','dv95-history');history.id='dv95History';right.append(history);
|
||||
right.append(el('p','dv95-muted','Aucune image n’est conservée par ce module. Les événements ne déclenchent ni reconnaissance faciale ni action domotique. Les images demandées à Hermes suivent la configuration de son fournisseur IA.'));
|
||||
content.append(left,right);frame.append(content);modal.append(frame);document.body.append(modal);
|
||||
modal.addEventListener('pointerdown',e=>{if(e.target===modal)close()});document.addEventListener('keydown',e=>{if(e.key==='Escape'&&opened)close()});
|
||||
const toastNode=el('div','dv95-toast');toastNode.id='dv95Toast';toastNode.hidden=true;toastNode.setAttribute('role','status');document.body.append(toastNode);
|
||||
// V9.2 génère le menu hamburger à partir des boutons originaux de l'en-tête.
|
||||
const mount=()=>{const root=$('alfredMainV1');const bar=root?.querySelector('.av-head-actions');if(!bar)return false;if($('dv95Launch'))return true;
|
||||
const action=btn('◉',open,'av-round dv95-launch');action.id='dv95Launch';action.title='Vision intelligente · YOLOv8';action.setAttribute('aria-label','Vision intelligente · YOLOv8');bar.append(action);return true};
|
||||
if(!mount()){let attempts=0;const timer=setInterval(()=>{if(mount()||++attempts>100)clearInterval(timer)},150)}
|
||||
const socket=window.socket||window.alfredSocket||null;
|
||||
// Si la Socket.IO de l'application n'est pas exposée globalement, client dédié.
|
||||
try{const listener=(socket&&typeof socket.on==='function')?socket:(typeof window.io==='function'?window.io({transports:['websocket','polling']}):null);
|
||||
listener?.on('dona_vision_event_v95',event=>{toast(event);if(opened)refresh()});
|
||||
listener?.on('dona_vision_status_v95',()=>{if(opened)refresh()});
|
||||
}catch(e){console.debug('Vision : événements non disponibles',e)}
|
||||
setInterval(()=>{if(opened)refresh()},6000);
|
||||
window.DonaVisionV95={open,close,refresh};
|
||||
}
|
||||
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init,{once:true});else init();
|
||||
})();
|
||||
Reference in New Issue
Block a user