fix(输入法): 优化双端联想排序并消除文字刷新闪烁
这个提交包含在:
1 父节点
bce6f8083b
当前提交
b95e7caae7
31 个文件已更改
+504
-124
没有与搜索条件相匹配的文件
@@ -30,6 +30,7 @@ p.choose({...hello});check(p.text==='你好'&&!p.composition,'candidate event pa
|
||||
p.finish();check(closed.at(-1).accepted&&closed.at(-1).text==='你好','finish returns text')
|
||||
p=page({initial:'unchanged'});p.insert('!');p.cancel();check(closed.at(-1).accepted===false,'cancel does not return edited text')
|
||||
p=page({inputType:'password',initial:'😀secret'});p.toggleLearning();check(!p.learning&&!p.display.includes('secret'),'password masked and cannot learn');p.onHide();check(!p.text&&!p.initial&&!p.original,'password clears on hide')
|
||||
p=page({inputType:'password',revealSecret:true,initial:'Visible123!'});check(p.display.includes('Visible123!')&&p.secret&&!p.learning,'explicit password reveal preserves private input');p.toggleLearning();check(!p.learning,'revealed password cannot enable learning');p.onHide();check(!p.text&&!p.initial&&!p.original,'revealed password clears on hide')
|
||||
p=page({initial:'你😀好'});p.cursor=2;p.backspace();check(p.text==='你好','UI Unicode deletion')
|
||||
p.startDelete();check(p.repeatDelay!==null,'delete hold delay starts');p.onHide();check(p.repeatDelay===null&&p.repeatTimer===null,'hide stops repeat timers')
|
||||
p=page();let resolve;p.dictionary={lookup:()=>new Promise(yes=>resolve=yes)};p.composition='64';const pending=p.query(p.requestId);p.onHide();resolve([{word:'你',consume:2,pinyin:'ni'}]);await pending;check(p.total===0,'late dictionary response cannot update hidden page')
|
||||
@@ -43,4 +44,15 @@ p.english();p.english();check(p.keyRows.flat().some(x=>x.value==='Z'),'uppercase
|
||||
p=page({initial:'test'});p.clearText();check(p.text==='test'&&p.clearArmed,'destructive clear needs second tap');p.clearText();check(p.text==='','confirmed clear')
|
||||
p.composition='shi';p.schedule();const owned=p.lookupTimer;p.onDestroy();check(!timers.has(owned)&&p.lookupTimer===null,'destroy releases owned lookup timer')
|
||||
p=page();p.learning=true;p.composition='64';p.allCandidates=[{word:'你',pinyin:'ni',consume:2}];storageFails=true;p.choose(p.allCandidates[0]);check(p.text==='你'&&!p.composition&&!p.learning,'storage failure cannot duplicate committed candidate');p.toggleLearning();check(!p.learning,'storage failure leaves learning off');storageFails=false
|
||||
p=page();p.mode='py';p.composition='niha';await p.query(p.requestId)
|
||||
p.choose(p.bar[0]);p.invalidate();await p.query(p.requestId)
|
||||
check(p.text==='你好'&&p.prediction&&p.bar[0].word==='世界','partial spelling commits once and offers context continuation')
|
||||
p.choose(p.bar[0]);check(p.text==='你好世界'&&!p.composition,'continuation appends only the next word')
|
||||
p=page();p.mode='py';p.composition='shi';await p.query(p.requestId)
|
||||
const steadyBar=p.bar,steadyText=p.display;p.composition='shij';p.schedule()
|
||||
check(p.busy&&p.bar===steadyBar&&p.display===steadyText,'pending lookup retains candidate and preview nodes instead of clearing visible text')
|
||||
const beforeStale=p.text;p.choose(steadyBar[0]);check(p.text===beforeStale,'retained candidates cannot commit while their replacement is pending')
|
||||
p=page({initial:'你好'});p.composition='';await p.query(p.requestId);p.space();check(p.text==='你好 '&&!p.text.includes('世界')&&!p.prediction&&!p.bar.length,'space ends the prediction context without auto-committing or leaving stale suggestions')
|
||||
p=page({initial:'你好'});p.composition='';await p.query(p.requestId);p.newline();check(p.text==='你好\n'&&!p.prediction&&!p.bar.length,'newline ends the prediction context and clears stale suggestions')
|
||||
p=page({inputType:'password',initial:'你好'});check(p.inputContext()==='','password content is never used as predictive context')
|
||||
console.log(JSON.stringify({suite:'ime-client',assertions:count,status:'passed'}))
|
||||
@@ -56,4 +56,14 @@ check(edit('你好',2,'世界',3).limited,'maximum length enforced')
|
||||
check(!preview('my-secret',5,true).includes('secret'),'secret preview masked')
|
||||
check(chars('😀').length===1,'Unicode length counts codepoints')
|
||||
dictionary.clear();check(dictionary.cacheSize===0,'cache release')
|
||||
check((await dictionary.lookup('niha',false,{}))[0].word==='你好','unfinished pinyin completes a real word before shorter fallback')
|
||||
check((await dictionary.lookup(digitsOf('niha'),true,{}))[0].word==='你好','unfinished T9 shares the completion policy')
|
||||
check((await dictionary.lookup(code14Of('niha'),'14',{})).some(x=>x.word==='你好'&&x.consume===4&&x.completion),'14-key completion consumes only the actual input tokens')
|
||||
check((await dictionary.lookup('beij',false,{}))[0].word==='北京','word frequency places common completion before rare homophones')
|
||||
const continuation=await dictionary.predict('你好')
|
||||
check(continuation[0].word==='世界'&&continuation.every(x=>x.consume===0)&&continuation.length<=8,'post-commit continuations use the longest context with bounded results')
|
||||
check((await dictionary.predict('你好。')).length===0&&(await dictionary.predict('secret123')).length===0,'punctuation and non-Chinese contexts end prediction')
|
||||
check((await dictionary.predict('前文你好'))[0].word==='世界','prediction uses only the bounded suffix before the cursor')
|
||||
check((await dictionary.lookup('shijie',false,{}))[0].word==='世界','common full-pinyin homophone is ranked by licensed word frequency')
|
||||
check(dictionary.cacheSize<=4,'prediction and completion retain the bounded cache')
|
||||
console.log(JSON.stringify({suite:'ime-engine',assertions:count,keys:meta.keys,candidates:meta.candidates,status:'passed'}))
|
||||
@@ -50,6 +50,8 @@ def main():
|
||||
run('auto-open',"await tc.getByClass('document').click();await tc.wait(.4);p=router.getPage(1);check(router.getLength()===2&&p.mode==='t9','field opens full screen T9');root.editText();check(router.getLength()===2,'duplicate opener guarded');")
|
||||
run('t9-phrase',"for(var label of ['MNO','GHI','GHI','ABC','MNO'])await click(label);await ready();check(p.bar[0].word==='你好','frequency ranks common phrase first');await click('你好');check(p.text==='你好'&&!p.composition,'native candidate commits phrase');")
|
||||
run('continuous',"reset();p.mode='py';p.renderKeys();p.composition='nihaoshijie';p.schedule();await ready();check(p.allCandidates.some(x=>x.word==='你好'&&x.consume===5),'prefix phrase retained');await click('你好');await ready();check(p.composition==='shijie','only matched pinyin consumed');await click('世界');check(p.text==='你好世界'&&!p.composition,'remaining syllables compose');")
|
||||
run('completion-prediction',"reset();p.mode='py';p.renderKeys();for(var letter of ['n','i','h','a'])await click(letter);await ready();check(p.bar[0].word==='你好'&&p.bar[0].consume===4,'unfinished spelling completes a real phrase');await click('你好');await ready();check(p.prediction&&p.bar[0].word==='世界','committed word offers bounded context continuation');await click('世界');check(p.text==='你好世界'&&!p.composition,'prediction appends once without repeating the prefix');")
|
||||
run('steady-candidates',"reset();p.mode='py';p.renderKeys();p.composition='shi';p.schedule();await ready();var previous=p.bar[0].word,previewBefore=p.display;p.press('j');check(p.busy&&p.bar[0].word===previous&&p.display===previewBefore,'pending result retains preview and candidates');p.choose(p.bar[0]);check(!p.text,'stale retained candidate cannot commit');await ready();")
|
||||
run('complete-candidates',"reset();p.mode='py';p.renderKeys();p.composition='shi';p.schedule();await ready();var total=p.total;await click('更多');check(p.visibleCandidates.length===16&&p.candidateRows.length===4&&p.pageCount>1,'full list paginated');for(var i=1;i<p.pageCount;i++)await click('下一页');check(p.candidatePage===p.pageCount-1,'last candidate page accessible');")
|
||||
run('candidate-select',"var last=p.visibleCandidates[p.visibleCandidates.length-1];await click(last.word);check(p.text===last.word,'last original candidate can commit');")
|
||||
run('full-pinyin',"reset();await click('26键');check(p.keyRows.map(row=>row.map(key=>key.value).join('')).join('/')==='qwertyuiop/asdfghjkl/zxcvbnm','standard 10-9-7 QWERTY order');for(var letter of ['s','h','u','r','u','f','a'])await click(letter);await ready();check(p.bar.some(x=>x.word==='输入法'),'long phrase in full dictionary');await click('输入法');check(p.text==='输入法','native full pinyin commit');")
|
||||
|
||||
在新工单中引用
屏蔽一个用户