mirror of
https://github.com/sune-org/store.git
synced 2026-01-13 16:17:58 +00:00
1 line
8.9 KiB
JSON
1 line
8.9 KiB
JSON
[{"id":"brlgiz7","name":"TODO","pinned":false,"avatar":"data:image/webp;base64,UklGRmwFAABXRUJQVlA4WAoAAAAgAAAAfwAAQgAASUNDUMgBAAAAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADZWUDggfgMAABAVAJ0BKoAAQwA+bS6SRiQiqKEsGZvREA2JZw3BpZEohLADxpNHavLHD6EOdT6a9gLo7ehL+lYaoBdrkVjC3AzrKyhBsYU0tymgdHMPEfiWme7jghgk0Zj8Mq/axQ4YzeDGPZgqMjZT3KBBZ+D/iE83x1qhBroXOLHIIgjVszDsuCGBEK674c7OBFQy4cfZ5AU+f/4wOtgF18rdPERQkrrv25vS8epyDm37GUiS3LxN6AD+/YwMmV2nsThO6Lj1+FCKyoe7QVO3HgahceVDV3Rwf+LUVDR7nsX083O7hV3ClXHUidIQR2MgvxJcKal6moJ9DCKHUwry9XqGal+LtpkD+fA2G8jGqQK7+vdy7jTHS95KVhs2AMjhbklKV6zITrgKSdytOJrqlW1x2IXTsxGBYr6+R6Q8s6yIpIsbbEgj9dAILlXax/uvQ3MlGMP8FHYdBMcALpTDZsBeIcYjNm8+Pb3O1AA018RPwhktRxFPgGkiLFFr6xfw99izlmtKKjwCctkavloPrzP6QUEFi7pLXcNULts9g2Z9hPneetDtdGF44EE3FziLiCYg+dDGjeTrEfcbewDQjXeztu6sLBMzxG69pvnSbhDuvOKI2VuYposYNDLnW1d0e/tHa7l2hAPaJTe7iofeMef5YFyPxbmRsipj988QcFJWf8N9ReLUqZ1sRS/3mAvdzX9B+b1Gf7sl+ngDOL2ZaMjofHLCLJsda2dhL8F+CoIL28tjq9r7AAlOk+ybHeQV21zQ556MoKbRvmfZs4sqcIBLwzIxo6dIyApjWWcZtzRXYQdie3zNUbHv4yEntL3if20t13WvsG+VJb/8gz7vHeKZCCeYKPdSeoFDa4zxbF/+8kQMsmHvJvUAmM+5HVAT8Gf+2RMAZTgeentmVcNtlVR/fZm66ucNKpH0xg7rH6/jNz5nSECKv7o8jhy3vIbc40dkbSyOlktPUyLAVw+EuGd42VmDobu9JwIdfWy/p7w0m0DIB1KrnWCnyVyiM4Wp1tkiLerLlyWNN8A9DG+6QfUcseFyHKJxtS/doMYya4X8v/f8LY+N9Z3vXQAu+ltJ+d5QDPLcsZj1+JzyCio8SgU8wgFkko6DiIIBQGhYPeVRK/krP4FKyd6eFDCmdo6BtVx2InLeAY6Jxq2cUXtJKgJp1dCxZgERmeGVOpVw4QITUQAAAA==","url":"gh://sune-org/store/TODO.sune","updatedAt":1757210105988,"settings":{"model":"openai/gpt-5-chat","temperature":"","top_p":"","top_k":"","frequency_penalty":"","presence_penalty":"","repetition_penalty":"","min_p":"","top_a":"","max_tokens":"","verbosity":"","reasoning_effort":"default","system_prompt":"","html":"<!-- TODO Sune v0.3.3 -->\n<div id=\"todo-sune\" class=\"relative\">\n <!-- Aurora blob -->\n <div class=\"pointer-events-none absolute inset-0 -z-10 overflow-hidden\">\n <div class=\"absolute -top-24 -right-24 h-72 w-72 rounded-full bg-gradient-to-br from-fuchsia-500 via-cyan-400 to-indigo-500 opacity-30 blur-3xl\"></div>\n <div class=\"absolute -bottom-24 -left-24 h-72 w-72 rounded-full bg-gradient-to-tr from-violet-500 via-sky-400 to-emerald-500 opacity-20 blur-3xl\"></div>\n </div>\n\n <div class=\"mx-auto max-w-md p-4\">\n <div class=\"rounded-2xl border border-gray-200 bg-white/80 shadow-xl backdrop-blur\">\n <div class=\"flex items-center gap-2 p-3\">\n <div class=\"flex items-center gap-2\">\n <span class=\"text-lg font-semibold\">TODO</span>\n <span class=\"rounded-lg bg-gray-100 px-2 py-0.5 text-[10px] font-medium text-gray-600\">v0.3.3</span>\n </div>\n <div class=\"ml-auto flex items-center gap-1 rounded-xl border border-gray-200 bg-gray-50 p-1\">\n <button data-f=\"all\" class=\"rounded-lg px-2 py-1 text-xs text-gray-600 hover:bg-gray-100\">All</button>\n <button data-f=\"active\" class=\"rounded-lg px-2 py-1 text-xs text-gray-600 hover:bg-gray-100\">Active</button>\n <button data-f=\"done\" class=\"rounded-lg px-2 py-1 text-xs text-gray-600 hover:bg-gray-100\">Done</button>\n </div>\n </div>\n\n <form id=\"tF\" class=\"flex gap-2 px-3 pb-3\">\n <input id=\"tI\" class=\"peer h-11 flex-1 rounded-xl border border-gray-200 bg-white/70 px-3 text-[14px] placeholder:text-gray-400 focus:border-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-200\" placeholder=\"What will you do today, Master?\" enterkeyhint=\"done\" autocomplete=\"off\"/>\n <button type=\"submit\" class=\"h-11 w-11 shrink-0 rounded-xl bg-black text-white hover:bg-black/90 active:scale-[.98] transition inline-flex items-center justify-center\">\n <i data-lucide=\"plus\" class=\"h-5 w-5\"></i>\n </button>\n </form>\n\n <ul id=\"tL\" class=\"divide-y divide-gray-100\"></ul>\n\n <div class=\"flex items-center gap-2 p-3 text-xs text-gray-600\">\n <span id=\"tC\" class=\"truncate\">0 left</span>\n <div class=\"ml-auto flex items-center gap-1\">\n <button id=\"tClr\" class=\"rounded-lg px-2 py-1 hover:bg-gray-100\">Clear done</button>\n <button id=\"tExp\" class=\"rounded-lg px-2 py-1 hover:bg-gray-100\" title=\"Export\"><i data-lucide=\"download\" class=\"h-4 w-4\"></i></button>\n <button id=\"tImp\" class=\"rounded-lg px-2 py-1 hover:bg-gray-100\" title=\"Import\"><i data-lucide=\"upload\" class=\"h-4 w-4\"></i></button>\n <input id=\"tUp\" type=\"file\" class=\"hidden\" accept=\"application/json,.json\"/>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<script>\n(()=>{const ver='0.3.3',r=document.getElementById('todo-sune');if(!r||r.dataset.i)return;r.dataset.i=1;\nconst id=(window.SUNE&&SUNE.id)||'default',k='todo@'+id,$=s=>r.querySelector(s),A=s=>[...r.querySelectorAll(s)],\nI=$('#tI'),L=$('#tL'),C=$('#tC'),F=$('#tF'),\nesc=s=>String(s).replace(/[&<>\"']/g,c=>({\"&\":\"&\",\"<\":\"<\",\">\":\">\",\"\\\"\":\""\",\"'\":\"'\"}[c]));\nlet S;try{S=JSON.parse(localStorage.getItem(k)||'{}')}catch{S={}};\nlet items=Array.isArray(S.items)?S.items:[],f=S.f||'all';I.value=S.draft||'';\nconst sv=()=>localStorage.setItem(k,JSON.stringify({v:ver,items,f,draft:I.value}));\nconst fil=a=>f==='active'?a.filter(x=>!x.d):f==='done'?a.filter(x=>x.d):a;\nconst row=t=>`<li class=\"group flex items-center gap-2 px-3 py-2\">\n <button data-a=\"tog\" data-id=\"${t.id}\" class=\"h-6 w-6 rounded-full border ${t.d?'bg-emerald-500 text-white border-emerald-500':'border-gray-300 text-gray-400'} flex items-center justify-center hover:scale-105 transition\">\n ${t.d?'<i data-lucide=\"check\" class=\"h-4 w-4\"></i>':'<i data-lucide=\"circle\" class=\"h-4 w-4\"></i>'}\n </button>\n <div class=\"min-w-0 flex-1 ${t.d?'text-gray-400 line-through':''} text-[14px]\">${esc(t.t)}</div>\n <button data-a=\"edit\" data-id=\"${t.id}\" class=\"invisible group-hover:visible rounded-lg p-1 hover:bg-gray-100\" title=\"Edit\"><i data-lucide=\"edit-3\" class=\"h-4 w-4\"></i></button>\n <button data-a=\"del\" data-id=\"${t.id}\" class=\"invisible group-hover:visible rounded-lg p-1 hover:bg-red-50 text-red-600\" title=\"Delete\"><i data-lucide=\"trash-2\" class=\"h-4 w-4\"></i></button>\n</li>`;\nfunction paint(){\n L.innerHTML=fil(items).map(row).join('')||'<li class=\"px-3 py-6 text-center text-sm text-gray-400\">No tasks yet. Add one above, Master.</li>';\n C.textContent=`${items.filter(x=>!x.d).length} left • ${items.filter(x=>x.d).length} done`;\n A('[data-f]').forEach(b=>{const on=b.dataset.f===f;b.classList.toggle('bg-gray-200',on);b.classList.toggle('text-gray-900',on);b.classList.toggle('shadow-sm',on);b.classList.toggle('ring-1',on);b.classList.toggle('ring-gray-200',on);b.classList.toggle('text-gray-600',!on)});\n (window.icons&&icons())||(window.lucide&&lucide.createIcons&&lucide.createIcons())\n}\npaint(); // intentionally no auto-focus to avoid opening the keyboard on mobile\n\nF.addEventListener('submit',e=>{e.preventDefault();const t=(I.value||'').trim();if(!t)return;\n items.unshift({id:Date.now().toString(36)+Math.random().toString(36).slice(2,6),t,d:false,ts:Date.now()});\n I.value='';sv();paint()\n});\nI.addEventListener('input',()=>sv());\nr.addEventListener('click',e=>{\n const fb=e.target.closest('[data-f]');if(fb){f=fb.dataset.f;sv();paint();return}\n const b=e.target.closest('[data-a]');if(!b)return;const i=items.findIndex(v=>v.id===b.dataset.id);if(i<0)return;\n const a=b.dataset.a;if(a==='tog')items[i].d=!items[i].d;else if(a==='del')items.splice(i,1);else if(a==='edit'){const nv=prompt('Edit task:',items[i].t);if(nv!=null)items[i].t=nv.trim()||items[i].t}\n sv();paint()\n});\n$('#tClr').onclick=()=>{if(items.some(x=>x.d)){items=items.filter(x=>!x.d);sv();paint()}};\n$('#tExp').onclick=()=>{const d={v:ver,items,f};const n=`todo-${id}-${new Date().toISOString().replace(/\\D+/g,'').slice(0,14)}.json`;\n const u=URL.createObjectURL(new Blob([JSON.stringify(d)],{type:'application/json'}));const a=document.createElement('a');a.href=u;a.download=n;document.body.appendChild(a);a.click();a.remove();URL.revokeObjectURL(u)\n};\n$('#tImp').onclick=()=>$('#tUp').click();\n$('#tUp').onchange=e=>{const file=e.target.files?.[0];if(!file)return;file.text().then(t=>{try{\n const j=JSON.parse(t||'{}');if(Array.isArray(j.items))items=j.items;if(j.f)f=j.f;sv();paint()\n}catch{}finally{e.target.value=''}})}\n})();\n</script>\n","extension_html":"<sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/sync.sune' private />","hide_composer":true},"storage":{}}] |