You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
5.5 KiB
233 lines
5.5 KiB
<script lang="ts"> |
|
import { createEventDispatcher } from 'svelte'; |
|
import { goto } from '$app/navigation'; |
|
import { nip19 } from 'nostr-tools'; |
|
import type { NostrEvent } from '$lib/types/nostr.js'; |
|
|
|
const dispatch = createEventDispatcher(); |
|
|
|
type TransferData = { |
|
eventId: string; |
|
fromPubkey: string; |
|
toPubkey: string; |
|
repoTag: string; |
|
repoName: string; |
|
originalOwner: string; |
|
timestamp: number; |
|
createdAt: string; |
|
event: NostrEvent; |
|
}; |
|
|
|
let { transfer }: { transfer: TransferData } = $props(); |
|
|
|
let closing = $state(false); |
|
|
|
function handleCompleteTransfer() { |
|
// Parse repo info from repoTag (kind:pubkey:repo) |
|
const currentTransfer = transfer; |
|
const parts = currentTransfer.repoTag.split(':'); |
|
if (parts.length < 3) { |
|
alert('Invalid repository tag format'); |
|
return; |
|
} |
|
|
|
const originalOwnerPubkey = parts[1]; |
|
const repoName = parts[2]; |
|
|
|
// Convert original owner pubkey to npub |
|
let originalOwnerNpub: string; |
|
try { |
|
originalOwnerNpub = nip19.npubEncode(originalOwnerPubkey); |
|
} catch { |
|
alert('Invalid owner pubkey format'); |
|
return; |
|
} |
|
|
|
// Navigate to signup page with transfer data |
|
const params = new URLSearchParams({ |
|
transfer: 'true', |
|
transferEventId: currentTransfer.eventId, |
|
originalOwner: originalOwnerNpub, |
|
repo: repoName, |
|
repoTag: currentTransfer.repoTag |
|
}); |
|
|
|
goto(`/signup?${params.toString()}`); |
|
} |
|
|
|
function handleDismiss() { |
|
closing = true; |
|
const currentTransfer = transfer; |
|
dispatch('dismiss', { eventId: currentTransfer.eventId }); |
|
setTimeout(() => { |
|
// Component will be removed by parent |
|
}, 300); |
|
} |
|
|
|
// Format timestamp |
|
const formattedDate = $derived(new Date(transfer.createdAt).toLocaleDateString()); |
|
</script> |
|
|
|
<div class="transfer-notification" class:closing> |
|
<div class="notification-content"> |
|
<div class="notification-header"> |
|
<h3>Repository Ownership Transfer</h3> |
|
<button class="close-button" onclick={handleDismiss} aria-label="Dismiss"> |
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
|
<line x1="18" y1="6" x2="6" y2="18"></line> |
|
<line x1="6" y1="6" x2="18" y2="18"></line> |
|
</svg> |
|
</button> |
|
</div> |
|
<div class="notification-body"> |
|
<p> |
|
You have been named as the new owner of the repository: <strong>{transfer.repoName}</strong> |
|
</p> |
|
<p class="notification-details"> |
|
Transfer initiated on {formattedDate} |
|
</p> |
|
<p class="notification-instruction"> |
|
Please complete the transfer by publishing a new repo announcement. |
|
</p> |
|
</div> |
|
<div class="notification-actions"> |
|
<button class="button-primary" onclick={handleCompleteTransfer}> |
|
Complete Transfer |
|
</button> |
|
<button class="button-secondary" onclick={handleDismiss}> |
|
Dismiss |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<style> |
|
.transfer-notification { |
|
position: fixed; |
|
top: 20px; |
|
right: 20px; |
|
z-index: 1000; |
|
max-width: 500px; |
|
background: var(--bg-primary, #fff); |
|
border: 2px solid var(--border-color, #ddd); |
|
border-radius: 8px; |
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
|
animation: slideIn 0.3s ease-out; |
|
transition: opacity 0.3s ease-out, transform 0.3s ease-out; |
|
} |
|
|
|
.transfer-notification.closing { |
|
opacity: 0; |
|
transform: translateX(100%); |
|
} |
|
|
|
@keyframes slideIn { |
|
from { |
|
opacity: 0; |
|
transform: translateX(100%); |
|
} |
|
to { |
|
opacity: 1; |
|
transform: translateX(0); |
|
} |
|
} |
|
|
|
.notification-content { |
|
padding: 20px; |
|
} |
|
|
|
.notification-header { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
margin-bottom: 16px; |
|
} |
|
|
|
.notification-header h3 { |
|
margin: 0; |
|
font-size: 1.2em; |
|
color: var(--text-primary, #333); |
|
} |
|
|
|
.close-button { |
|
background: none; |
|
border: none; |
|
cursor: pointer; |
|
padding: 4px; |
|
color: var(--text-secondary, #666); |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
border-radius: 4px; |
|
transition: background-color 0.2s; |
|
} |
|
|
|
.close-button:hover { |
|
background-color: var(--bg-secondary, #f0f0f0); |
|
} |
|
|
|
.notification-body { |
|
margin-bottom: 16px; |
|
} |
|
|
|
.notification-body p { |
|
margin: 8px 0; |
|
color: var(--text-primary, #333); |
|
line-height: 1.5; |
|
} |
|
|
|
.notification-details { |
|
font-size: 0.9em; |
|
color: var(--text-secondary, #666); |
|
} |
|
|
|
.notification-instruction { |
|
font-weight: 500; |
|
color: var(--text-primary, #333); |
|
} |
|
|
|
.notification-actions { |
|
display: flex; |
|
gap: 12px; |
|
justify-content: flex-end; |
|
} |
|
|
|
.button-primary, |
|
.button-secondary { |
|
padding: 10px 20px; |
|
border: none; |
|
border-radius: 4px; |
|
cursor: pointer; |
|
font-size: 1em; |
|
font-weight: 500; |
|
transition: background-color 0.2s, transform 0.1s; |
|
} |
|
|
|
.button-primary { |
|
background-color: var(--primary-color, #007bff); |
|
color: white; |
|
} |
|
|
|
.button-primary:hover { |
|
background-color: var(--primary-hover, #0056b3); |
|
transform: translateY(-1px); |
|
} |
|
|
|
.button-secondary { |
|
background-color: var(--bg-secondary, #f0f0f0); |
|
color: var(--text-primary, #333); |
|
} |
|
|
|
.button-secondary:hover { |
|
background-color: var(--bg-tertiary, #e0e0e0); |
|
} |
|
|
|
@media (max-width: 600px) { |
|
.transfer-notification { |
|
top: 10px; |
|
right: 10px; |
|
left: 10px; |
|
max-width: none; |
|
} |
|
} |
|
</style>
|
|
|