show file sizes (basic version)
This commit is contained in:
@@ -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")]
|
||||||
|
|||||||
@@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user