mirror of
https://github.com/multipleof4/4ev.link.git
synced 2026-01-13 15:57:53 +00:00
Feat: Connect frontend to worker API for shortening
This commit is contained in:
14
index.html
14
index.html
@@ -67,7 +67,7 @@ a{color:inherit}
|
|||||||
|
|
||||||
<section class="hero">
|
<section class="hero">
|
||||||
<h1 class="h1">Short links, built to last</h1>
|
<h1 class="h1">Short links, built to last</h1>
|
||||||
<p class="sub">Clean, fast, privacy-first URL shortener. Free plan with randomized slugs only (e.g., 4ev.link/xY7zQ1). No custom slugs, no ads.</p>
|
<p class="sub">Clean, fast, privacy-first URL shortener. Free plan with randomized slugs only (e.g., ev.awww.workers.dev/aB3d). No custom slugs, no ads.</p>
|
||||||
<div class="form" @submit.prevent>
|
<div class="form" @submit.prevent>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<input class="input" x-model="url" type="url" inputmode="url" placeholder="Paste a long URL, e.g. https://example.com/very/long/link" aria-label="Long URL" @keydown.enter.prevent="shorten()">
|
<input class="input" x-model="url" type="url" inputmode="url" placeholder="Paste a long URL, e.g. https://example.com/very/long/link" aria-label="Long URL" @keydown.enter.prevent="shorten()">
|
||||||
@@ -159,15 +159,13 @@ a{color:inherit}
|
|||||||
<script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
|
<script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
|
||||||
<script src="https://unpkg.com/lucide@latest"></script>
|
<script src="https://unpkg.com/lucide@latest"></script>
|
||||||
<script>
|
<script>
|
||||||
const app=()=>({t:localStorage.getItem('theme')||(matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'),url:'',busy:0,short:'',links:JSON.parse(localStorage.getItem('4ev.links')||'[]'),base:'https://4ev.link',slugLen:6,msg:'',
|
const app=()=>({t:localStorage.getItem('theme')||(matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'),url:'',busy:0,short:'',links:JSON.parse(localStorage.getItem('4ev.links')||'[]'),base:'https://ev.awww.workers.dev',msg:'',
|
||||||
init(){document.documentElement.setAttribute('data-theme',this.t);this.freshIcons();},
|
init(){document.documentElement.setAttribute('data-theme',this.t);this.freshIcons()},
|
||||||
setTheme(v){this.t=v;localStorage.setItem('theme',v);document.documentElement.setAttribute('data-theme',v);this.freshIcons()},
|
setTheme(v){this.t=v;localStorage.setItem('theme',v);document.documentElement.setAttribute('data-theme',v);this.freshIcons()},
|
||||||
toggleTheme(){this.setTheme(this.t==='light'?'dark':'light')},
|
toggleTheme(){this.setTheme(this.t==='light'?'dark':'light')},
|
||||||
val(u){try{let x=new URL(u);return['http:','https:'].includes(x.protocol)}catch{return!1}},
|
val(u){try{new URL(u);return 1}catch(e){return 0}},
|
||||||
rand(n){let c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',s='';for(let i=0;i<n;i++)s+=c[(Math.random()*c.length)|0];return s},
|
async shorten(){if(this.busy||!this.val(this.url))return this.toast('Enter a valid URL');this.busy=1;try{const r=await fetch(this.base,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url:this.url.trim()})});if(!r.ok)throw'';const d=await r.json();this.short=d.shortUrl;this.links.unshift({slug:d.slug,target:d.target,created:Date.now()});this.links.splice(20);localStorage.setItem('4ev.links',JSON.stringify(this.links));this.url='';this.toast('Link created')}catch(e){this.toast('Failed to shorten link')}finally{this.busy=0;this.freshIcons()}},
|
||||||
uniqueSlug(){let s;do s=this.rand(this.slugLen);while(this.links.find(l=>l.slug===s));return s},
|
copy(txt){navigator.clipboard?.writeText(txt).then(()=>this.toast('Copied')).catch(()=>{let t=document.createElement('textarea');t.value=txt;document.body.appendChild(t);t.select();document.execCommand('copy');t.remove();this.toast('Copied')})},
|
||||||
shorten(){if(this.busy)return;if(!this.val(this.url))return this.toast('Enter a valid URL');this.busy=1;setTimeout(()=>{let slug=this.uniqueSlug(),t=this.url.trim();this.short=`${this.base}/${slug}`;this.links.unshift({slug:slug,target:t,created:Date.now()});this.links=this.links.slice(0,20);localStorage.setItem('4ev.links',JSON.stringify(this.links));this.url='';this.busy=0;this.toast('Link created');this.freshIcons()},450)},
|
|
||||||
copy(txt){navigator.clipboard?.writeText(txt).then(()=>this.toast('Copied')).catch(()=>{let ta=document.createElement('textarea');ta.value=txt;document.body.appendChild(ta);ta.select();document.execCommand('copy');ta.remove();this.toast('Copied')})},
|
|
||||||
toast(m){this.msg=m;this.freshIcons();clearTimeout(this._to);this._to=setTimeout(()=>this.msg='',2000)},
|
toast(m){this.msg=m;this.freshIcons();clearTimeout(this._to);this._to=setTimeout(()=>this.msg='',2000)},
|
||||||
del(i){this.links.splice(i,1);localStorage.setItem('4ev.links',JSON.stringify(this.links));this.freshIcons()},
|
del(i){this.links.splice(i,1);localStorage.setItem('4ev.links',JSON.stringify(this.links));this.freshIcons()},
|
||||||
freshIcons(){try{lucide&&lucide.createIcons()}catch(e){}}
|
freshIcons(){try{lucide&&lucide.createIcons()}catch(e){}}
|
||||||
|
|||||||
Reference in New Issue
Block a user