fix: ghost text visible (innerHTML + span) + IA flexible mot/phrase/bloc
- showGhost utilise innerHTML avec span.ghost-prediction (etait invisible) - Prompt intelligent: mid-word = complete le mot, sinon complete 1-2 phrases - Seuil reduit: 1 caractere minimum (au lieu de 3) - Detection doublon amelioree (trimStart) - Timeout reduit: 800ms → 600ms
This commit is contained in:
@@ -1788,14 +1788,15 @@ body { font-family: var(--sans); background: var(--bg); color: var(--text); heig
|
|||||||
|
|
||||||
function clearGhost() {
|
function clearGhost() {
|
||||||
_ghostText = '';
|
_ghostText = '';
|
||||||
ghostOverlay.textContent = '';
|
ghostOverlay.innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function showGhost(prediction) {
|
function showGhost(prediction) {
|
||||||
if (!prediction) { clearGhost(); return; }
|
if (!prediction) { clearGhost(); return; }
|
||||||
_ghostText = prediction;
|
_ghostText = prediction;
|
||||||
var before = ta.value.slice(0, ta.selectionStart);
|
var before = ta.value.slice(0, ta.selectionStart);
|
||||||
ghostOverlay.textContent = before + prediction;
|
// Show: existing text (transparent) + prediction (visible faded)
|
||||||
|
ghostOverlay.innerHTML = escHtml(before) + '<span class="ghost-prediction">' + escHtml(prediction) + '</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function acceptGhost() {
|
function acceptGhost() {
|
||||||
@@ -1814,16 +1815,25 @@ body { font-family: var(--sans); background: var(--bg); color: var(--text); heig
|
|||||||
|
|
||||||
function requestGhostCompletion() {
|
function requestGhostCompletion() {
|
||||||
var text = ta.value.slice(0, ta.selectionStart);
|
var text = ta.value.slice(0, ta.selectionStart);
|
||||||
if (text.trim().length < 3) return;
|
if (text.trim().length < 1) return;
|
||||||
|
// Smart prompt: detect if mid-word, mid-phrase, or new block
|
||||||
|
var lastChar = text.slice(-1);
|
||||||
|
var midWord = /[a-zA-Z0-9]$/.test(lastChar);
|
||||||
|
var prompt = midWord
|
||||||
|
? 'Complete ONLY the current word being typed. Return ONLY the completion (no extra text):\n\n' + text
|
||||||
|
: 'Complete this text naturally in 1-2 short phrases. Return ONLY the new text (no repetition):\n\n' + text;
|
||||||
|
|
||||||
fetch('/api/ai/inline-complete', {
|
fetch('/api/ai/inline-complete', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ text: text, provider: 'ollama' })
|
body: JSON.stringify({ text: prompt, provider: 'ollama' })
|
||||||
})
|
})
|
||||||
.then(function(r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })
|
.then(function(r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
var prediction = (data.result || '').trim();
|
var prediction = (data.result || '').trim();
|
||||||
if (prediction && !ta.value.slice(ta.selectionStart).startsWith(prediction.slice(0, 10))) {
|
// Only show if prediction adds something new
|
||||||
|
var alreadyThere = ta.value.slice(ta.selectionStart).trimStart();
|
||||||
|
if (prediction && prediction.length > 1 && !alreadyThere.startsWith(prediction.slice(0, Math.min(8, prediction.length)))) {
|
||||||
showGhost(prediction);
|
showGhost(prediction);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1834,7 +1844,7 @@ body { font-family: var(--sans); background: var(--bg); color: var(--text); heig
|
|||||||
ta.addEventListener('input', function() {
|
ta.addEventListener('input', function() {
|
||||||
clearGhost();
|
clearGhost();
|
||||||
if (_ghostTimer) clearTimeout(_ghostTimer);
|
if (_ghostTimer) clearTimeout(_ghostTimer);
|
||||||
_ghostTimer = setTimeout(requestGhostCompletion, 800);
|
_ghostTimer = setTimeout(requestGhostCompletion, 600);
|
||||||
});
|
});
|
||||||
|
|
||||||
function escHtml(s) { return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); }
|
function escHtml(s) { return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); }
|
||||||
|
|||||||
Reference in New Issue
Block a user