feat: wire Cloud card on Home to real FileBrowser data

Add getUsage() method to filebrowser-client that fetches root directory
and returns total size and folder count. Home.vue Cloud card now shows
real storage used and folder count instead of hardcoded values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian 2026-03-05 07:05:14 +00:00
parent dfe96cdb6f
commit 37105e6be6
3 changed files with 51 additions and 4 deletions

View File

@ -40,7 +40,7 @@ After getting Claude Max OAuth working on the live server, hardening the deploy
- **Change**: Ensure tab bar element has `data-mobile-tab-bar` attribute so `useMobileBackButton` composable works. CloudFolder.vue already uses this correctly.
- **Verify**: CloudFolder on mobile — "Back to Cloud" button floats 8px above tab bar
### Task 7: Cloud homepage real data
### Task 7: Cloud homepage real data [DONE]
- **Files**: `neode-ui/src/views/Home.vue`, `neode-ui/src/api/filebrowser-client.ts`
- **Change**: Add `getUsage()` method to filebrowser-client. In Home.vue, replace hardcoded "2.4 GB" and "5" folders with real data from FileBrowser API. Add `formatBytes()` helper. Show loading state while fetching.
- **Verify**: Home Cloud card shows real storage numbers from FileBrowser

View File

@ -104,6 +104,23 @@ class FileBrowserClient {
if (!res.ok) throw new Error(`Delete failed: ${res.status}`)
}
async getUsage(): Promise<{ totalSize: number; folderCount: number; fileCount: number }> {
if (!this.isAuthenticated) {
const ok = await this.login()
if (!ok) return { totalSize: 0, folderCount: 0, fileCount: 0 }
}
const res = await fetch(`${this.baseUrl}/api/resources/`, {
headers: this.headers(),
})
if (!res.ok) return { totalSize: 0, folderCount: 0, fileCount: 0 }
const data: FileBrowserListResponse = await res.json()
const items = data.items || []
const folderCount = items.filter(i => i.isDir).length
const fileCount = items.filter(i => !i.isDir).length
const totalSize = items.reduce((sum, i) => sum + (i.size || 0), 0)
return { totalSize, folderCount, fileCount }
}
async rename(oldPath: string, newName: string): Promise<void> {
const safePath = oldPath.startsWith('/') ? oldPath : `/${oldPath}`
const dir = safePath.substring(0, safePath.lastIndexOf('/') + 1)

View File

@ -91,11 +91,11 @@
<div class="home-card-stats grid grid-cols-2 gap-4 mb-4 flex-1 min-h-0">
<div class="p-4 bg-white/5 rounded-lg">
<p class="text-xs text-white/60 mb-1">Storage Used</p>
<p class="text-2xl font-bold text-white">2.4 GB</p>
<p class="text-2xl font-bold text-white">{{ cloudStorageDisplay }}</p>
</div>
<div class="p-4 bg-white/5 rounded-lg">
<p class="text-xs text-white/60 mb-1">Folders</p>
<p class="text-2xl font-bold text-white">5</p>
<p class="text-2xl font-bold text-white">{{ cloudFolderDisplay }}</p>
</div>
</div>
<div class="home-card-buttons flex gap-2 mt-auto pt-4 shrink-0">
@ -275,7 +275,7 @@
</template>
<script setup lang="ts">
import { computed, ref, watch, onBeforeUnmount } from 'vue'
import { computed, ref, watch, onBeforeUnmount, onMounted } from 'vue'
import { RouterLink, useRouter } from 'vue-router'
import { useAppStore } from '../stores/app'
import { useAppLauncherStore } from '@/stores/appLauncher'
@ -285,6 +285,7 @@ import { PackageState } from '../types/api'
import { playTypingSound } from '@/composables/useLoginSounds'
import { GOALS } from '@/data/goals'
import EasyHome from '@/components/EasyHome.vue'
import { fileBrowserClient } from '@/api/filebrowser-client'
const router = useRouter()
const uiMode = useUIModeStore()
@ -402,6 +403,35 @@ function dismissQuickStart() {
loadQuickStartState()
// Cloud data
const cloudStorageUsed = ref<number | null>(null)
const cloudFolderCount = ref<number | null>(null)
function formatBytes(bytes: number): string {
if (bytes === 0) return '0 B'
const units = ['B', 'KB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(1024))
const val = bytes / Math.pow(1024, i)
return `${val < 10 ? val.toFixed(1) : Math.round(val)} ${units[i]}`
}
const cloudStorageDisplay = computed(() =>
cloudStorageUsed.value !== null ? formatBytes(cloudStorageUsed.value) : '...'
)
const cloudFolderDisplay = computed(() =>
cloudFolderCount.value !== null ? String(cloudFolderCount.value) : '...'
)
onMounted(async () => {
try {
const usage = await fileBrowserClient.getUsage()
cloudStorageUsed.value = usage.totalSize
cloudFolderCount.value = usage.folderCount
} catch {
// FileBrowser may not be running leave as loading
}
})
function uploadFiles() {
const pkg = packages.value['filebrowser']
if (pkg && pkg.state === PackageState.Running) {