|
72 | 72 | function applyTheme(value) { |
73 | 73 | var c = categoryById(value); |
74 | 74 | document.body.setAttribute('data-theme', c.id); |
75 | | - els.locationTag.textContent = 'ARCHIVE / ' + c.label.toUpperCase(); |
| 75 | + els.locationTag.textContent = '酒場 / ' + c.label; |
76 | 76 | } |
77 | 77 | function renderFilters() { |
78 | 78 | var list = [ALL].concat(RULES,[OTHER]); |
|
99 | 99 | function renderRepos() { |
100 | 100 | var list = visibleRepos(); |
101 | 101 | state.selectedRow = Math.max(0, Math.min(state.selectedRow, Math.max(list.length-1,0))); |
102 | | - els.count.textContent = list.length + ' / ' + state.repos.length + ' RECORDS'; |
| 102 | + els.count.textContent = list.length + ' / ' + state.repos.length + ' 件'; |
103 | 103 | els.empty.hidden = list.length > 0; |
104 | 104 | els.grid.hidden = list.length === 0; |
105 | 105 | els.grid.innerHTML = list.map(function(repo,index){ |
106 | 106 | var s = summaryFor(repo) || {}; |
107 | 107 | var c = categoryOf(repo); |
108 | 108 | var selected = index === state.selectedRow; |
109 | 109 | var title = s.title || repo.name; |
110 | | - var desc = s.summary || repo.description || (repo.name + ' に関する公開記録。'); |
| 110 | + var desc = s.summary || repo.description || (repo.name + '――この件はまだ説明資料が少ない。'); |
111 | 111 | return '<button class="record-row'+(selected?' is-selected':'')+'" type="button" role="option" aria-selected="'+(selected?'true':'false')+'" data-repo="'+esc(repo.name)+'" data-index="'+index+'">'+ |
112 | 112 | '<span class="record-no"><span class="record-pointer" aria-hidden="true">☞</span><span>'+String(index+1).padStart(2,'0')+'</span></span>'+ |
113 | 113 | '<span class="record-main"><span class="record-titleline"><span class="record-title">'+esc(title)+'</span><span class="record-repo">'+esc(repo.name)+'</span></span><span class="record-summary">'+esc(desc)+'</span></span>'+ |
114 | | - '<span class="record-side"><span class="ai-mark">'+(s.summary?'COPILOT':'RAW')+'</span><strong>'+esc(c.label)+'</strong><span>'+esc(repo.language||'—')+' / '+esc(relDate(repo.pushed_at))+'</span></span></button>'; |
| 114 | + '<span class="record-side"><span class="ai-mark">'+(s.summary?'整理済':'原資料')+'</span><strong>'+esc(c.label)+'</strong><span>'+esc(repo.language||'—')+' / '+esc(relDate(repo.pushed_at))+'</span></span></button>'; |
115 | 115 | }).join(''); |
116 | 116 | } |
117 | 117 | function selectRow(n, focus) { |
|
123 | 123 | current.scrollIntoView({block:'nearest'}); |
124 | 124 | if (focus) current.focus({preventScroll:true}); |
125 | 125 | } |
| 126 | + function confidenceLabel(value) { |
| 127 | + if (value === 'high') return '高'; |
| 128 | + if (value === 'low') return '低'; |
| 129 | + return '中'; |
| 130 | + } |
126 | 131 | function meta(repo,s) { |
127 | 132 | var a=[]; |
128 | | - if (repo.language) a.push('LANG '+repo.language); |
129 | | - a.push('UPDATED '+fmtDate(repo.pushed_at)); |
130 | | - if (state.liveApi) a.push('STAR '+(repo.stargazers_count||0)); |
131 | | - a.push(repo.fork?'FORK':'ORIGINAL'); |
132 | | - if (repo.archived) a.push('ARCHIVED'); |
133 | | - if (s.status) a.push('STATUS '+s.status); |
134 | | - if (s.confidence) a.push('CONF '+String(s.confidence).toUpperCase()); |
| 133 | + if (repo.language) a.push('言語 '+repo.language); |
| 134 | + a.push('更新 '+fmtDate(repo.pushed_at)); |
| 135 | + if (state.liveApi) a.push('★ '+(repo.stargazers_count||0)); |
| 136 | + a.push(repo.fork?'派生':'原本'); |
| 137 | + if (repo.archived) a.push('保管済み'); |
| 138 | + if (s.status) a.push('状態 '+s.status); |
| 139 | + if (s.confidence) a.push('確度 '+confidenceLabel(s.confidence)); |
135 | 140 | els.detailMeta.innerHTML = a.map(function(x){return '<span class="meta-pill">'+esc(x)+'</span>';}).join(''); |
136 | 141 | } |
137 | 142 | function features(items) { |
|
153 | 158 | typingTimer=setInterval(function(){ i+=2; els.keeperText.textContent=text.slice(0,i); if(i>=text.length) clearInterval(typingTimer); },10); |
154 | 159 | } |
155 | 160 | function openPrompt(repo) { |
156 | | - var s=summaryFor(repo)||{}, c=categoryOf(repo); |
| 161 | + var s=summaryFor(repo)||{}, c=categoryOf(repo), title=s.title||repo.name; |
157 | 162 | state.pendingRepo=repo; applyTheme(c.id); |
158 | | - els.confirmCategory.textContent='ARCHIVE / '+c.label; |
159 | | - els.confirmTitle.textContent=s.title||repo.name; |
160 | | - els.confirmText.textContent=s.confidence==='low' ? '「'+(s.title||repo.name)+'か。資料は少ないが、確認できる範囲の記録はある。」' : '「'+(s.title||repo.name)+'か。記録は揃ってる。中身を見ていくか?」'; |
| 163 | + els.confirmCategory.textContent='情報棚 / '+c.label; |
| 164 | + els.confirmTitle.textContent=title; |
| 165 | + els.confirmText.textContent=s.confidence==='low' |
| 166 | + ? '「'+title+'ね。……その件は資料が少ない。確かなところまででいいなら見せるよ。」' |
| 167 | + : '「'+title+'ね。その情報ならある。公開分だけでよければ見せるよ。」'; |
161 | 168 | els.confirmStage.hidden=false; els.detailStage.hidden=true; |
162 | 169 | if (!els.dialog.open) els.dialog.showModal(); |
163 | 170 | setTimeout(function(){els.confirmYes.focus();},0); |
164 | 171 | } |
| 172 | + function keeperDetail(repo,s) { |
| 173 | + var base=s.detail||s.summary||repo.description||'この件は、まだ説明に使える資料がほとんどない。'; |
| 174 | + if (s.confidence==='low') return '「この件は資料が薄い。分かってるところだけ話す。\n'+base+'」'; |
| 175 | + var leads=['調べた限りじゃ、こういう記録だ。','要点だけ言うと、こうだ。','資料を追うと、こういう話になる。']; |
| 176 | + return '「'+leads[String(repo.name||'').length%leads.length]+'\n'+base+'」'; |
| 177 | + } |
165 | 178 | function showDetail(repo) { |
166 | 179 | var s=summaryFor(repo)||{}, c=categoryOf(repo), idx=state.repos.findIndex(function(x){return x.id===repo.id;})+1; |
167 | 180 | els.confirmStage.hidden=true; els.detailStage.hidden=false; |
168 | | - els.detailBreadcrumb.textContent='ARCHIVE / '+c.label+' / RECORD'; |
169 | | - els.detailNumber.textContent='RECORD No.'+String(Math.max(idx,1)).padStart(3,'0'); |
| 181 | + els.detailBreadcrumb.textContent='酒場 / '+c.label+' / 情報'; |
| 182 | + els.detailNumber.textContent='情報 No.'+String(Math.max(idx,1)).padStart(3,'0'); |
170 | 183 | els.detailTitle.textContent=s.title||repo.name; els.detailRepo.textContent=OWNER+'/'+repo.name; |
171 | 184 | els.repoLink.href=repo.html_url||('https://github.com/'+OWNER+'/'+repo.name); |
172 | | - els.pagesLink.hidden=!repo.homepage; if(repo.homepage) els.pagesLink.href=repo.homepage; |
| 185 | + els.pagesLink.hidden=true; |
| 186 | + els.pagesLink.removeAttribute('href'); |
173 | 187 | meta(repo,s); features(s.features); tech(repo,s); |
174 | | - els.summarySource.textContent=s.summary ? 'COPILOT ANALYSIS / '+fmtDate(s.generatedAt) : 'REPOSITORY METADATA'; |
175 | | - typeText('「'+(s.detail||s.summary||repo.description||'確認できる説明資料が少ない記録だ。')+'」'); |
| 188 | + els.summarySource.textContent=s.summary ? 'COPILOT整理 / '+fmtDate(s.generatedAt) : 'リポジトリ情報'; |
| 189 | + typeText(keeperDetail(repo,s)); |
176 | 190 | } |
177 | 191 | function closeDialog() { |
178 | 192 | if (typingTimer) clearInterval(typingTimer); |
|
181 | 195 | function status(label) { |
182 | 196 | var ai=state.repos.filter(function(r){return state.summaries[r.name]&&state.summaries[r.name].summary;}).length; |
183 | 197 | els.notice.classList.remove('is-error'); |
184 | | - els.noticeText.textContent=state.repos.length+'件の公開記録を確認 / COPILOT解析 '+ai+'件 / '+label; |
| 198 | + els.noticeText.textContent=state.repos.length+'件の情報を確認 / 整理済み '+ai+'件 / '+label; |
185 | 199 | } |
186 | 200 | function reposFromCache(data) { |
187 | 201 | var dict=data&&data.repositories?data.repositories:{}; |
|
221 | 235 | } |
222 | 236 | function init() { |
223 | 237 | try { validate(); document.documentElement.setAttribute('data-app-loaded','1'); applyTheme('all'); renderFilters(); els.grid.innerHTML='<div class="loading-row"></div>'.repeat(8); bind(); } |
224 | | - catch(err){ if(els.notice)els.notice.classList.add('is-error'); if(els.noticeText)els.noticeText.textContent='端末初期化エラー: '+err.message; return; } |
| 238 | + catch(err){ if(els.notice)els.notice.classList.add('is-error'); if(els.noticeText)els.noticeText.textContent='……端末の準備に失敗した: '+err.message; return; } |
225 | 239 |
|
226 | 240 | var liveError=null; |
227 | 241 | var livePromise=fetchLive().catch(function(e){liveError=e;return null;}); |
228 | 242 | fetchCache().then(function(data){ |
229 | | - state.summaries=data.repositories||{}; state.repos=reposFromCache(data); status('CACHE'); renderRepos(); |
| 243 | + state.summaries=data.repositories||{}; state.repos=reposFromCache(data); status('保存記録'); renderRepos(); |
230 | 244 | return livePromise; |
231 | 245 | }).then(function(live){ |
232 | | - if(live&&live.length){state.repos=live;state.liveApi=true;status('LIVE API');renderRepos();} |
233 | | - else if(state.repos.length){status(liveError&&liveError.name==='AbortError'?'API TIMEOUT / CACHE':'API UNAVAILABLE / CACHE');} |
| 246 | + if(live&&live.length){state.repos=live;state.liveApi=true;status('最新照合');renderRepos();} |
| 247 | + else if(state.repos.length){status(liveError&&liveError.name==='AbortError'?'API時間切れ / 保存記録':'API接続不可 / 保存記録');} |
234 | 248 | }).catch(function(err){ |
235 | 249 | livePromise.then(function(live){ |
236 | | - if(live&&live.length){state.repos=live;state.liveApi=true;status('LIVE API / SUMMARY unavailable');renderRepos();} |
237 | | - else {els.notice.classList.add('is-error');els.noticeText.textContent='記録を取得できませんでした: '+err.message;els.count.textContent='0 RECORDS';els.grid.innerHTML='';} |
| 250 | + if(live&&live.length){state.repos=live;state.liveApi=true;status('最新照合 / 整理情報なし');renderRepos();} |
| 251 | + else {els.notice.classList.add('is-error');els.noticeText.textContent='……悪い。記録棚を開けない: '+err.message;els.count.textContent='0 件';els.grid.innerHTML='';} |
238 | 252 | }); |
239 | 253 | }); |
240 | 254 | } |
|
0 commit comments