mirror of
https://github.com/multipleof4/sune.git
synced 2026-02-04 10:08:00 +00:00
Fix: Persist synced status to localforage after push
This commit is contained in:
@@ -111,11 +111,11 @@ const htmlTabs={index:['htmlTab_index','htmlEditor'],extension:['htmlTab_extensi
|
||||
el.htmlTab_index.textContent='index.html';el.htmlTab_extension.textContent='extension.html';
|
||||
el.htmlTab_index.onclick=()=>showHtmlTab('index');el.htmlTab_extension.onclick=()=>showHtmlTab('extension');
|
||||
const ghApi=async(path,method='GET',body=null)=>{const t=USER.githubToken;if(!t)throw new Error('No GH token');const r=await fetch(`https://api.github.com/repos/${path}`,{method,headers:{'Authorization':`token ${t}`,'Accept':'application/vnd.github.v3+json','Content-Type':'application/json'},body:body?JSON.stringify(body):null});if(!r.ok&&r.status!==404)throw new Error(`GH API ${r.status}`);return r.status===404?null:r.json()};
|
||||
const parseGhUrl=u=>{const p=u.substring(5).split('/'),owner=p[0],repoPart=p[1]||'',branch=repoPart.includes('@')?repoPart.split('@')[1]:'main',repo=repoPart.split('@')[0],path=p.slice(2).join('/');const dirPath=path?path+'/':'';return{owner,repo,branch,path,full:`${owner}/${repo}/contents/${dirPath}index.json?ref=${branch}`,dir:`${owner}/${repo}/contents/${dirPath}`}};
|
||||
const parseGhUrl=u=>{const p=u.substring(5).split('/'),owner=p[0],repoPart=p[1]||'',branch=repoPart.includes('@')?repoPart.split('@')[1]:'main',repo=repoPart.split('@')[0],path=p.slice(2).join('/');const dirPath=path?path+'/':'';return{owner,repo,branch,path,full:`${owner}/${repo}/contents/${dirPath}index.json?ref=${branch}`,dir:`${owner}/${repo}/contents/${dirPath}index.json?ref=${branch}`.replace('index.json?ref=','').split('?')[0].split('/').slice(0,-1).join('/')+'/'}};
|
||||
$(el.threadRepoInput).on('change',async()=>{const u=el.threadRepoInput.value.trim();localStorage.setItem('thread_repo_url',u);if(state.currentThreadId){state.currentThreadId=null;clearChat()}el.threadFolderBtn.classList.toggle('hidden',!u.startsWith('gh://'));el.threadBackBtn.classList.toggle('hidden',!u.startsWith('gh://')||u.split('/').length<=3);await THREAD.load();await renderThreads()});
|
||||
$(el.threadBackBtn).on('click',()=>{const u=el.threadRepoInput.value.trim();if(!u.startsWith('gh://'))return;const p=u.split('/');if(p.length>3){p.pop();el.threadRepoInput.value=p.join('/');el.threadRepoInput.dispatchEvent(new Event('change'))}});
|
||||
$(el.threadFolderBtn).on('click',async()=>{const n=prompt('Folder name:');if(!n)return;THREAD.list.unshift({id:n.trim(),title:n.trim(),type:'folder',updatedAt:Date.now()});await THREAD.save();await renderThreads()});
|
||||
$(el.threadSyncBtn).on('click',async()=>{const u=el.threadRepoInput.value.trim();if(!u.startsWith('gh://'))return;const mode=confirm('Sync Threads:\nOK = Upload (Push)\nCancel = Download (Pull)');const info=parseGhUrl(u);try{if(mode){const idxFile=await ghApi(info.full),sha=idxFile?.sha,toRemove=[];for(const t of THREAD.list){if(t.type!=='thread')continue;const fPath=`${info.dir}${t.id}.json`;if(t.status==='deleted'){const ex=await ghApi(fPath+'?ref='+info.branch);if(ex?.sha)await ghApi(fPath,'DELETE',{message:`Delete thread ${t.id}`,sha:ex.sha,branch:info.branch});await localforage.removeItem('rem_t_'+t.id);toRemove.push(t.id)}else if(t.status==='modified'||t.status==='new'){const msgs=await localforage.getItem('rem_t_'+t.id),ex=await ghApi(fPath+'?ref='+info.branch);await ghApi(fPath,'PUT',{message:`Sync thread ${t.id}`,content:utob(JSON.stringify(msgs,null,2)),branch:info.branch,sha:ex?.sha});t.status='synced'}}THREAD.list=THREAD.list.filter(x=>!toRemove.includes(x.id));await ghApi(info.full,'PUT',{message:'Update index.json',content:utob(JSON.stringify(THREAD.list,null,2)),branch:info.branch,sha});alert('Pushed to GitHub.')}else{const idxFile=await ghApi(info.full);if(!idxFile){THREAD.list=[];await THREAD.save();alert('Remote is empty. Local list cleared.')}else{const remoteList=JSON.parse(btou(idxFile.content));THREAD.list=remoteList.map(t=>({...t,status:'synced'}));await THREAD.save();alert('Pulled from GitHub.')}}await renderThreads()}catch(e){alert('Sync failed: '+e.message)}});
|
||||
$(el.threadSyncBtn).on('click',async()=>{const u=el.threadRepoInput.value.trim();if(!u.startsWith('gh://'))return;const mode=confirm('Sync Threads:\nOK = Upload (Push)\nCancel = Download (Pull)');const info=parseGhUrl(u);try{if(mode){const idxFile=await ghApi(info.full),sha=idxFile?.sha,toRemove=[];for(const t of THREAD.list){if(t.type!=='thread')continue;const fPath=`${info.dir}${t.id}.json`;if(t.status==='deleted'){const ex=await ghApi(fPath+'?ref='+info.branch);if(ex?.sha)await ghApi(fPath,'DELETE',{message:`Delete thread ${t.id}`,sha:ex.sha,branch:info.branch});await localforage.removeItem('rem_t_'+t.id);toRemove.push(t.id)}else if(t.status==='modified'||t.status==='new'){const msgs=await localforage.getItem('rem_t_'+t.id),ex=await ghApi(fPath+'?ref='+info.branch);await ghApi(fPath,'PUT',{message:`Sync thread ${t.id}`,content:utob(JSON.stringify(msgs,null,2)),branch:info.branch,sha:ex?.sha});t.status='synced'}}THREAD.list=THREAD.list.filter(x=>!toRemove.includes(x.id));await ghApi(info.full,'PUT',{message:'Update index.json',content:utob(JSON.stringify(THREAD.list,null,2)),branch:info.branch,sha});await THREAD.save();alert('Pushed to GitHub.')}else{const idxFile=await ghApi(info.full);if(!idxFile){THREAD.list=[];await THREAD.save();alert('Remote is empty. Local list cleared.')}else{const remoteList=JSON.parse(btou(idxFile.content));THREAD.list=remoteList.map(t=>({...t,status:'synced'}));await THREAD.save();alert('Pulled from GitHub.')}}await renderThreads()}catch(e){alert('Sync failed: '+e.message)}});
|
||||
init()
|
||||
const accountTabs={General:['accountTabGeneral','accountPanelGeneral'],API:['accountTabAPI','accountPanelAPI'],User:['accountTabUser','accountPanelUser']};function showAccountTab(key){Object.entries(accountTabs).forEach(([k,[tb,pn]])=>{el[tb].classList.toggle('border-black',k===key);el[pn].classList.toggle('hidden',k!==key)})}
|
||||
function openAccountSettings(){el.set_provider.value=USER.provider||'openrouter';el.set_api_key_or.value=USER.apiKeyOpenRouter||'';el.set_api_key_oai.value=USER.apiKeyOpenAI||'';el.set_api_key_g.value=USER.apiKeyGoogle||'';el.set_api_key_claude.value=USER.apiKeyClaude||'';el.set_api_key_cf.value=USER.apiKeyCloudflare||'';el.set_master_prompt.value=USER.masterPrompt||'';el.set_title_model.value=USER.titleModel;el.set_gh_token.value=USER.githubToken||'';const sa=USER.gcpSA;el.gcpSAUploadBtn.textContent=sa&&sa.project_id?`Uploaded: ${sa.project_id}`:'Upload .json';el.set_user_name.value=USER.name;el.userAvatarPreview.src=USER.avatar||'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';el.userAvatarPreview.classList.toggle('bg-gray-200',!USER.avatar);el.set_donor.checked=USER.donor;const updateProv=()=>{const d=el.set_donor.checked;Array.from(el.set_provider.options).forEach(o=>{if(o.value!=='openrouter'){o.disabled=!d;if(!d)o.hidden=true;else o.hidden=false}});if(!d&&el.set_provider.value!=='openrouter')el.set_provider.value='openrouter'};updateProv();el.set_donor.onchange=updateProv;showAccountTab('General');el.accountSettingsModal.classList.remove('hidden')}
|
||||
|
||||
Reference in New Issue
Block a user