feat: add Peer Files UI for browsing and downloading federated content
- New PeerFiles.vue view shows federated peers and their shared catalogs - Peer Files card in Cloud.vue shows when federation peers exist - New content.download-peer RPC fetches content from peer via Tor - Route: /dashboard/cloud/peers Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Peer Files Card -->
|
||||
<div
|
||||
v-if="hasFederatedPeers"
|
||||
data-controller-container
|
||||
tabindex="0"
|
||||
class="glass-card p-6 cursor-pointer transition-all hover:-translate-y-1 hover:bg-white/10 mt-4"
|
||||
@click="router.push({ name: 'peer-files' })"
|
||||
>
|
||||
<div class="flex items-center gap-4 mb-4">
|
||||
<div class="flex-shrink-0 w-12 h-12 rounded-xl flex items-center justify-center bg-purple-500/15">
|
||||
<svg class="w-7 h-7 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="text-lg font-semibold text-white mb-0.5 truncate">Peer Files</h3>
|
||||
<p class="text-xs text-white/50">Browse files shared by federated nodes</p>
|
||||
</div>
|
||||
<svg class="w-5 h-5 text-white/30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 text-xs">
|
||||
<span class="inline-flex items-center gap-1.5 px-2 py-1 rounded-full bg-purple-500/15 text-purple-400">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-purple-400"></span>
|
||||
{{ peerCount }} peers
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Not Installed Hint -->
|
||||
<div v-if="!fileBrowserRunning" class="glass-card p-8 mt-6 text-center">
|
||||
<p class="text-white/60 mb-3">Install File Browser from the App Store to get started with your cloud storage.</p>
|
||||
@@ -73,11 +103,14 @@ import { computed, ref, onMounted } from 'vue'
|
||||
import { useRouter, RouterLink } from 'vue-router'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import { fileBrowserClient } from '@/api/filebrowser-client'
|
||||
import { rpcClient } from '@/api/rpc-client'
|
||||
|
||||
const router = useRouter()
|
||||
const store = useAppStore()
|
||||
const sectionCounts = ref<Record<string, number>>({})
|
||||
const countsLoading = ref(false)
|
||||
const peerCount = ref(0)
|
||||
const hasFederatedPeers = computed(() => peerCount.value > 0)
|
||||
|
||||
const APP_ALIASES: Record<string, string[]> = {
|
||||
immich: ['immich_server', 'immich-server'],
|
||||
@@ -182,7 +215,19 @@ async function loadCounts() {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => loadCounts())
|
||||
onMounted(() => {
|
||||
loadCounts()
|
||||
loadPeerCount()
|
||||
})
|
||||
|
||||
async function loadPeerCount() {
|
||||
try {
|
||||
const result = await rpcClient.federationListNodes()
|
||||
peerCount.value = result?.nodes?.length ?? 0
|
||||
} catch {
|
||||
peerCount.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
function openSection(section: ContentSection) {
|
||||
router.push({ name: 'cloud-folder', params: { folderId: section.id } })
|
||||
|
||||
Reference in New Issue
Block a user