132 lines
3.7 KiB
TypeScript
132 lines
3.7 KiB
TypeScript
import { useEffect, useState, useCallback } from 'react'
|
|
import { getAlbyService } from '@/lib/alby'
|
|
|
|
interface AlbyInstallerProps {
|
|
onInstalled?: () => void
|
|
}
|
|
|
|
function InfoIcon() {
|
|
return (
|
|
<svg
|
|
className="h-5 w-5 text-blue-400"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 20 20"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
fillRule="evenodd"
|
|
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
|
|
clipRule="evenodd"
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
interface InstallerActionsProps {
|
|
onInstalled?: () => void
|
|
markInstalled: () => void
|
|
}
|
|
|
|
function InstallerActions({ onInstalled, markInstalled }: InstallerActionsProps) {
|
|
const connect = useCallback(() => {
|
|
const alby = getAlbyService()
|
|
void alby.enable().then(() => {
|
|
markInstalled()
|
|
onInstalled?.()
|
|
})
|
|
}, [markInstalled, onInstalled])
|
|
|
|
return (
|
|
<div className="mt-4">
|
|
<div className="flex flex-col sm:flex-row gap-2">
|
|
<a
|
|
href="https://getalby.com/"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
>
|
|
Install Alby
|
|
</a>
|
|
<button
|
|
onClick={() => {
|
|
void connect()
|
|
}}
|
|
className="inline-flex items-center justify-center px-4 py-2 border border-blue-300 text-sm font-medium rounded-md text-blue-700 bg-white hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
>
|
|
Already installed? Connect
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function InstallerBody({ onInstalled, markInstalled }: InstallerActionsProps) {
|
|
return (
|
|
<div className="ml-3 flex-1">
|
|
<h3 className="text-sm font-medium text-blue-800">Alby Extension Required</h3>
|
|
<div className="mt-2 text-sm text-blue-700">
|
|
<p>To make Lightning payments, please install the Alby browser extension.</p>
|
|
</div>
|
|
<InstallerActions
|
|
markInstalled={markInstalled}
|
|
{...(onInstalled ? { onInstalled } : {})}
|
|
/>
|
|
<div className="mt-3 text-xs text-blue-600">
|
|
<p>Alby is a Lightning wallet that enables instant Bitcoin payments in your browser.</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function useAlbyStatus(onInstalled?: () => void) {
|
|
const [isInstalled, setIsInstalled] = useState(false)
|
|
const [isChecking, setIsChecking] = useState(true)
|
|
|
|
useEffect(() => {
|
|
const checkAlby = () => {
|
|
try {
|
|
const alby = getAlbyService()
|
|
const installed = alby.isEnabled()
|
|
setIsInstalled(installed)
|
|
if (installed) {
|
|
onInstalled?.()
|
|
}
|
|
} catch (e) {
|
|
console.error('Error checking Alby:', e)
|
|
setIsInstalled(false)
|
|
} finally {
|
|
setIsChecking(false)
|
|
}
|
|
}
|
|
checkAlby()
|
|
}, [onInstalled])
|
|
|
|
const markInstalled = () => {
|
|
setIsInstalled(true)
|
|
}
|
|
|
|
return { isInstalled, isChecking, markInstalled }
|
|
}
|
|
|
|
export function AlbyInstaller({ onInstalled }: AlbyInstallerProps) {
|
|
const { isInstalled, isChecking, markInstalled } = useAlbyStatus(onInstalled)
|
|
|
|
if (isChecking || isInstalled) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4">
|
|
<div className="flex items-start">
|
|
<div className="flex-shrink-0">
|
|
<InfoIcon />
|
|
</div>
|
|
<InstallerBody
|
|
markInstalled={markInstalled}
|
|
{...(onInstalled ? { onInstalled } : {})}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|