8 changed files with 277 additions and 106 deletions
@ -1,74 +1,59 @@
@@ -1,74 +1,59 @@
|
||||
import { Controller } from '@hotwired/stimulus'; |
||||
|
||||
const LOADING_HTML = `<div class="nostr-preview__loading text-center my-2"><span class="nostr-preview__spinner" role="status" aria-label="Loading"></span><span class="nostr-preview__loading-text ms-2">Loading preview…</span></div>`; |
||||
const UNAVAILABLE_HTML = `<div class="alert alert-warning my-2" role="status">Preview unavailable.</div>`; |
||||
|
||||
export default class extends Controller { |
||||
static values = { |
||||
identifier: String, |
||||
type: String, |
||||
decoded: String, |
||||
fullMatch: String |
||||
} |
||||
fullMatch: String, |
||||
}; |
||||
|
||||
static targets = ['container'] |
||||
static targets = ['container']; |
||||
|
||||
async connect() { |
||||
await this.fetchPreview(); |
||||
connect() { |
||||
this.fetchPreview(); |
||||
} |
||||
|
||||
async fetchPreview() { |
||||
if (!this.hasContainerTarget) { |
||||
return; |
||||
} |
||||
this.containerTarget.innerHTML = LOADING_HTML; |
||||
try { |
||||
this.containerTarget.innerHTML = '<div class="nostr-preview__loading text-center my-2"><span class="nostr-preview__spinner" role="status" aria-label="Loading"></span><span class="nostr-preview__loading-text ms-2">Loading preview…</span></div>'; |
||||
if (this.typeValue === 'url' && this.fullMatchValue) { |
||||
// Fetch OG preview for plain URLs
|
||||
fetch("/og-preview/", { |
||||
method: "POST", |
||||
headers: { |
||||
"Content-Type": "application/json" |
||||
}, |
||||
body: JSON.stringify({ url: this.fullMatchValue }) |
||||
}) |
||||
.then(res => { |
||||
if (!res.ok) { |
||||
throw new Error(`HTTP error! status: ${res.status}`); |
||||
} |
||||
return res.text(); |
||||
}) |
||||
.then(data => { |
||||
this.containerTarget.innerHTML = data; |
||||
}) |
||||
.catch(error => { |
||||
console.error("Error:", error); |
||||
this.containerTarget.innerHTML = `<div class="alert alert-warning">Unable to load OG preview for ${this.fullMatchValue}</div>`; |
||||
const res = await fetch('/og-preview/', { |
||||
method: 'POST', |
||||
headers: { 'Content-Type': 'application/json' }, |
||||
body: JSON.stringify({ url: this.fullMatchValue }), |
||||
}); |
||||
} else { |
||||
// Fallback to Nostr preview
|
||||
const data = { |
||||
identifier: this.identifierValue, |
||||
type: this.typeValue, |
||||
decoded: this.decodedValue |
||||
}; |
||||
fetch("/preview/", { |
||||
method: "POST", |
||||
headers: { |
||||
"Content-Type": "application/json" |
||||
}, |
||||
body: JSON.stringify(data) |
||||
}) |
||||
.then(res => { |
||||
if (!res.ok) { |
||||
throw new Error(`HTTP error! status: ${res.status}`); |
||||
} |
||||
return res.text(); |
||||
}) |
||||
.then(data => { |
||||
this.containerTarget.innerHTML = data; |
||||
}) |
||||
.catch(error => { |
||||
console.error("Error:", error); |
||||
}); |
||||
if (!res.ok) { |
||||
throw new Error(`HTTP ${res.status}`); |
||||
} |
||||
this.containerTarget.innerHTML = await res.text(); |
||||
return; |
||||
} |
||||
const res = await fetch('/preview/', { |
||||
method: 'POST', |
||||
headers: { 'Content-Type': 'application/json' }, |
||||
body: JSON.stringify({ |
||||
identifier: this.identifierValue, |
||||
type: this.typeValue, |
||||
decoded: this.decodedValue, |
||||
}), |
||||
}); |
||||
if (!res.ok) { |
||||
throw new Error(`HTTP ${res.status}`); |
||||
} |
||||
} catch (error) { |
||||
console.error('Error fetching Nostr preview:', error); |
||||
this.containerTarget.innerHTML = `<div class="alert alert-warning">Unable to load preview for ${this.fullMatchValue}</div>`; |
||||
this.containerTarget.innerHTML = await res.text(); |
||||
} catch (e) { |
||||
// NetworkError / offline: avoid console.error noise; one inline fallback per block
|
||||
console.debug('nostr_preview: fetch failed', e); |
||||
this.containerTarget.innerHTML = this.typeValue === 'url' && this.fullMatchValue |
||||
? `<div class="alert alert-warning my-2" role="status">Unable to load link preview for ${this.fullMatchValue}.</div>` |
||||
: UNAVAILABLE_HTML; |
||||
} |
||||
} |
||||
} |
||||
|
||||
Loading…
Reference in new issue