show file sizes (basic version)

This commit is contained in:
2025-09-06 15:49:51 +02:00
parent cef77e86b7
commit 8c0d80d7fb
6 changed files with 71 additions and 37 deletions

View File

@@ -14,6 +14,7 @@ pub struct File {
name: FileName, name: FileName,
file_type: FileType, file_type: FileType,
mime_type: Option<FileMimeType>, mime_type: Option<FileMimeType>,
size: FileSize,
created_at: Option<u64>, created_at: Option<u64>,
} }
@@ -22,12 +23,14 @@ impl File {
name: FileName, name: FileName,
file_type: FileType, file_type: FileType,
mime_type: Option<FileMimeType>, mime_type: Option<FileMimeType>,
size: FileSize,
created_at: Option<u64>, created_at: Option<u64>,
) -> Self { ) -> Self {
Self { Self {
name, name,
file_type, file_type,
mime_type, mime_type,
size,
created_at, created_at,
} }
} }
@@ -44,6 +47,10 @@ impl File {
self.mime_type.as_ref() self.mime_type.as_ref()
} }
pub fn size(&self) -> FileSize {
self.size
}
pub fn created_at(&self) -> Option<u64> { pub fn created_at(&self) -> Option<u64> {
self.created_at self.created_at
} }
@@ -81,6 +88,21 @@ impl FileName {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
pub struct FileSize(u64);
impl FileSize {
pub fn new(value: u64) -> Self {
Self(value)
}
}
impl From<FileSize> for u64 {
fn from(value: FileSize) -> Self {
value.0
}
}
/// A valid file type /// A valid file type
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Display)] #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Display)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]

View File

@@ -55,6 +55,7 @@ pub struct WarrenFileElement {
name: String, name: String,
file_type: FileType, file_type: FileType,
mime_type: Option<String>, mime_type: Option<String>,
size: u64,
created_at: Option<u64>, created_at: Option<u64>,
} }
@@ -64,6 +65,7 @@ impl From<&File> for WarrenFileElement {
name: value.name().to_string(), name: value.name().to_string(),
file_type: value.file_type().to_owned(), file_type: value.file_type().to_owned(),
mime_type: value.mime_type().map(FileMimeType::to_string), mime_type: value.mime_type().map(FileMimeType::to_string),
size: value.size().into(),
created_at: value.created_at(), created_at: value.created_at(),
} }
} }

View File

@@ -20,10 +20,10 @@ use crate::{
models::{ models::{
file::{ file::{
AbsoluteFilePath, CatError, CatRequest, CpError, CpRequest, CpResponse, File, AbsoluteFilePath, CatError, CatRequest, CpError, CpRequest, CpResponse, File,
FileMimeType, FileName, FilePath, FileStream, FileType, LsError, LsRequest, FileMimeType, FileName, FilePath, FileSize, FileStream, FileType, LsError,
LsResponse, MkdirError, MkdirRequest, MvError, MvRequest, RelativeFilePath, LsRequest, LsResponse, MkdirError, MkdirRequest, MvError, MvRequest,
RmError, RmRequest, SaveError, SaveRequest, SaveResponse, StatError, StatRequest, RelativeFilePath, RmError, RmRequest, SaveError, SaveRequest, SaveResponse,
StatResponse, TouchError, TouchRequest, StatError, StatRequest, StatResponse, TouchError, TouchRequest,
}, },
warren::UploadFileStream, warren::UploadFileStream,
}, },
@@ -108,28 +108,8 @@ impl FileSystem {
let mut files = Vec::new(); let mut files = Vec::new();
let parent = if include_parent {
let dir_name = FileName::new(
&dir_path
.file_name()
.context("Failed to get directory name")?
.to_owned()
.into_string()
.ok()
.context("Failed to get directory name")?,
)?;
Some(File::new(
dir_name,
FileType::Directory,
None,
get_btime(&dir_path),
))
} else {
None
};
let mut dir = fs::read_dir(&dir_path).await?; let mut dir = fs::read_dir(&dir_path).await?;
let mut total_size = 0_u64;
while let Ok(Some(entry)) = dir.next_entry().await { while let Ok(Some(entry)) = dir.next_entry().await {
let name = entry let name = entry
@@ -149,6 +129,8 @@ impl FileSystem {
} }
}; };
let metadata = fs::metadata(entry.path()).await?;
let entry_size = metadata.size();
let created_at = get_btime(entry.path()); let created_at = get_btime(entry.path());
let mime_type = match file_type { let mime_type = match file_type {
@@ -156,14 +138,43 @@ impl FileSystem {
_ => None, _ => None,
}; };
total_size += entry_size;
files.push(File::new( files.push(File::new(
FileName::new(&name)?, FileName::new(&name)?,
file_type, file_type,
mime_type, mime_type,
FileSize::new(entry_size),
created_at, created_at,
)); ));
} }
tracing::info!("Parent size: {total_size}");
let parent = if include_parent {
let dir_name = FileName::new(
&dir_path
.file_name()
.context("Failed to get directory name")?
.to_owned()
.into_string()
.ok()
.context("Failed to get directory name")?,
)?;
let parent_size = FileSize::new(total_size);
Some(File::new(
dir_name,
FileType::Directory,
None,
parent_size,
get_btime(&dir_path),
))
} else {
None
};
Ok(LsResponse::new(files, parent)) Ok(LsResponse::new(files, parent))
} }
@@ -408,9 +419,10 @@ impl FileSystem {
_ => None, _ => None,
}; };
let file_size = FileSize::new(metadata.size());
let created_at = get_btime(&fs_path); let created_at = get_btime(&fs_path);
Ok(File::new(name, file_type, mime_type, created_at)) Ok(File::new(name, file_type, mime_type, file_size, created_at))
} }
} }

View File

@@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import byteSize from 'byte-size';
import type { DirectoryEntry } from '~/shared/types'; import type { DirectoryEntry } from '~/shared/types';
const { entry } = defineProps<{ entry: DirectoryEntry }>(); const { entry } = defineProps<{ entry: DirectoryEntry }>();
@@ -28,12 +29,9 @@ const onDrop = onDirectoryEntryDrop(entry, true);
>({{ entry.name }})</span >({{ entry.name }})</span
></span ></span
> >
<NuxtTime <span class="text-muted-foreground w-full truncate text-sm">{{
v-if="entry.createdAt != null" byteSize(entry.size)
:datetime="entry.createdAt * 1000" }}</span>
class="text-muted-foreground w-full truncate text-sm"
relative
></NuxtTime>
</div> </div>
</button> </button>
</template> </template>

View File

@@ -7,6 +7,7 @@ import {
ContextMenuSeparator, ContextMenuSeparator,
} from '@/components/ui/context-menu'; } from '@/components/ui/context-menu';
import type { DirectoryEntry } from '#shared/types'; import type { DirectoryEntry } from '#shared/types';
import byteSize from 'byte-size';
const warrenStore = useWarrenStore(); const warrenStore = useWarrenStore();
const copyStore = useCopyStore(); const copyStore = useCopyStore();
@@ -111,12 +112,10 @@ function onClearCopy() {
class="flex w-full flex-col items-start justify-stretch gap-0 overflow-hidden text-left leading-6" class="flex w-full flex-col items-start justify-stretch gap-0 overflow-hidden text-left leading-6"
> >
<span class="w-full truncate">{{ entry.name }}</span> <span class="w-full truncate">{{ entry.name }}</span>
<NuxtTime <span
v-if="entry.createdAt != null"
:datetime="entry.createdAt * 1000"
class="text-muted-foreground w-full truncate text-sm" class="text-muted-foreground w-full truncate text-sm"
relative >{{ byteSize(entry.size) }}</span
></NuxtTime> >
</div> </div>
</button> </button>
</ContextMenuTrigger> </ContextMenuTrigger>

View File

@@ -9,6 +9,7 @@ export type DirectoryEntry = {
name: string; name: string;
fileType: FileType; fileType: FileType;
mimeType: string | null; mimeType: string | null;
size: number;
/// Timestamp in seconds /// Timestamp in seconds
createdAt: number | null; createdAt: number | null;
isParent: boolean; isParent: boolean;