mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-08 09:32:49 +00:00
Magic bytes 🪄
Co-authored-by: Brendan Allan <brendonovich@outlook.com>
This commit is contained in:
parent
d27ff3cd80
commit
5ab432ae46
|
@ -10,6 +10,7 @@ davidmytton
|
||||||
deel
|
deel
|
||||||
elon
|
elon
|
||||||
encryptor
|
encryptor
|
||||||
|
Flac
|
||||||
haden
|
haden
|
||||||
haoyuan
|
haoyuan
|
||||||
haris
|
haris
|
||||||
|
|
|
@ -51,6 +51,8 @@ impl Node {
|
||||||
|
|
||||||
fs::create_dir_all(&data_dir).await?;
|
fs::create_dir_all(&data_dir).await?;
|
||||||
|
|
||||||
|
// dbg!(get_object_kind_from_extension("png"));
|
||||||
|
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
.with(
|
.with(
|
||||||
EnvFilter::from_default_env()
|
EnvFilter::from_default_env()
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/// Object Kind
|
||||||
|
///
|
||||||
|
/// https://www.garykessler.net/library/file_sigs.html
|
||||||
|
/// https://github.com/bojand/infer/
|
||||||
|
///
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Display, Formatter},
|
fmt::{Display, Formatter},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
@ -8,6 +13,8 @@ use rspc::Type;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
|
use crate::prisma::file_path;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Type, IntEnum)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Type, IntEnum)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ObjectKind {
|
pub enum ObjectKind {
|
||||||
|
@ -47,19 +54,39 @@ pub enum ObjectKind {
|
||||||
Album = 16,
|
Album = 16,
|
||||||
// Its like a folder, but appears like a stack of files, designed for burst photos / associated groups of files
|
// Its like a folder, but appears like a stack of files, designed for burst photos / associated groups of files
|
||||||
Collection = 17,
|
Collection = 17,
|
||||||
|
// You know, text init
|
||||||
|
Font = 18,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct the extensions enum
|
||||||
macro_rules! extension_enum {
|
macro_rules! extension_enum {
|
||||||
(
|
(
|
||||||
Extension {
|
Extension {
|
||||||
$( $variant:ident($type:ident), )*
|
$( $variant:ident($type:ident), )*
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
// construct enum
|
||||||
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub enum Extension {
|
pub enum Extension {
|
||||||
$( $variant($type), )*
|
$( $variant($type), )*
|
||||||
}
|
}
|
||||||
// convert extension to object kind
|
impl Extension {
|
||||||
|
pub fn from_str(s: &str) -> Option<ExtensionPossibility> {
|
||||||
|
let mut exts = [$(
|
||||||
|
$type::from_str(s).ok().map(Self::$variant)
|
||||||
|
),*]
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|s| s)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
match exts {
|
||||||
|
_ if exts.len() == 0 => None,
|
||||||
|
_ if exts.len() == 1 => Some(ExtensionPossibility::Known(exts.swap_remove(0))),
|
||||||
|
_ => Some(ExtensionPossibility::Conflicts(exts))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// convert Extension to ObjectKind
|
||||||
impl From<Extension> for ObjectKind {
|
impl From<Extension> for ObjectKind {
|
||||||
fn from(ext: Extension) -> Self {
|
fn from(ext: Extension) -> Self {
|
||||||
match ext {
|
match ext {
|
||||||
|
@ -67,6 +94,7 @@ macro_rules! extension_enum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
impl Display for Extension {
|
impl Display for Extension {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -77,9 +105,67 @@ macro_rules! extension_enum {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extension_from_str() {
|
||||||
|
// single extension match
|
||||||
|
assert_eq!(
|
||||||
|
Extension::from_str("jpg"),
|
||||||
|
Some(ExtensionPossibility::Known(Extension::Image(
|
||||||
|
ImageExtension::Jpg
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
// with conflicts
|
||||||
|
assert_eq!(
|
||||||
|
Extension::from_str("ts"),
|
||||||
|
Some(ExtensionPossibility::Conflicts(vec![
|
||||||
|
Extension::Video(VideoExtension::Ts),
|
||||||
|
Extension::Text(TextExtension::Ts)
|
||||||
|
]))
|
||||||
|
);
|
||||||
|
// invalid case
|
||||||
|
assert_eq!(Extension::from_str("jeff"), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl file_path::Data {
|
||||||
|
// fn extension(&self, magic_bytes: Option<&[u8]>) -> Option<ExtensionPossibility>V {
|
||||||
|
// let ext = match self.extension {
|
||||||
|
// Some(ext) => ext.as_str(),
|
||||||
|
// None => return Ok(Extension::Unknown("".to_string())),
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // if let Ok(ex) = VideoExtension::from_str(ext) {
|
||||||
|
// // // .ts files can be video or text
|
||||||
|
// // match ex {
|
||||||
|
// // VideoExtension::Ts => {
|
||||||
|
// // // double check if it is a video=
|
||||||
|
// // }
|
||||||
|
// // _ => Extension::Video(ex),
|
||||||
|
// // }
|
||||||
|
// // //
|
||||||
|
// // } else if let Ok(ex) = ImageExtension::from_str(ext) {
|
||||||
|
// // return Extension::Image(ex);
|
||||||
|
// // //
|
||||||
|
// // } else if let Ok(ex) = AudioExtension::from_str(ext) {
|
||||||
|
// // return Extension::Audio(ex);
|
||||||
|
// // //
|
||||||
|
// // } else {
|
||||||
|
// // return Extension::Unknown(ext);
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn object_kind(&self, magic_bytes: Option<&[u8]>) -> ObjectKind {
|
||||||
|
// let extension = self.extension(magic_bytes);
|
||||||
|
// extension.into()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
extension_enum! {
|
extension_enum! {
|
||||||
Extension {
|
Extension {
|
||||||
Unknown(String),
|
|
||||||
Video(VideoExtension),
|
Video(VideoExtension),
|
||||||
Image(ImageExtension),
|
Image(ImageExtension),
|
||||||
Audio(AudioExtension),
|
Audio(AudioExtension),
|
||||||
|
@ -88,19 +174,50 @@ extension_enum! {
|
||||||
Text(TextExtension),
|
Text(TextExtension),
|
||||||
Encrypted(EncryptedExtension),
|
Encrypted(EncryptedExtension),
|
||||||
Key(KeyExtension),
|
Key(KeyExtension),
|
||||||
|
Font(FontExtension),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum ExtensionPossibility {
|
||||||
|
Known(Extension),
|
||||||
|
Conflicts(Vec<Extension>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MagicBytes: Sized {
|
||||||
|
fn from_magic_bytes_buf(buf: &[u8]) -> Option<Self>;
|
||||||
|
fn magic_bytes_len(&self) -> usize;
|
||||||
|
fn magic_bytes_offset(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! magic_byte_value {
|
||||||
|
(_) => {
|
||||||
|
0 as u8
|
||||||
|
};
|
||||||
|
($val:literal) => {{
|
||||||
|
$val as u8
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! magic_byte_offset {
|
||||||
|
() => {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
($val:literal) => {
|
||||||
|
$val
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Define a public enum with static array of all possible variants
|
/// Define a public enum with static array of all possible variants
|
||||||
/// including implementations to convert to/from string
|
/// including implementations to convert to/from string
|
||||||
macro_rules! enum_with_variants {
|
macro_rules! extension_category_enum {
|
||||||
(
|
(
|
||||||
$(#[$enum_attr:meta])*
|
$(#[$enum_attr:meta])*
|
||||||
$enum_name:ident $static_array_name:ident {
|
$enum_name:ident $static_array_name:ident {
|
||||||
$($(#[$variant_attr:meta])* $variant:ident, )*
|
$($(#[$variant_attr:meta])* $variant:ident $(= [$($magic_bytes:tt),*] $(+ $offset:literal)?)? ,)*
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
$(#[$enum_attr])*
|
$(#[$enum_attr])*
|
||||||
// construct enum
|
// construct enum
|
||||||
|
@ -111,6 +228,7 @@ macro_rules! enum_with_variants {
|
||||||
pub static $static_array_name: &[$enum_name] = &[
|
pub static $static_array_name: &[$enum_name] = &[
|
||||||
$( $enum_name::$variant, )*
|
$( $enum_name::$variant, )*
|
||||||
];
|
];
|
||||||
|
extension_category_enum!(@magic_bytes; $enum_name ( $($(#[$variant_attr])* $variant $(= [$($magic_bytes),*] $(+ $offset)?)? ),* ));
|
||||||
// convert from string
|
// convert from string
|
||||||
impl FromStr for $enum_name {
|
impl FromStr for $enum_name {
|
||||||
type Err = serde_json::Error;
|
type Err = serde_json::Error;
|
||||||
|
@ -124,115 +242,141 @@ macro_rules! enum_with_variants {
|
||||||
write!(f, "{}", serde_json::to_string(self).unwrap()) // SAFETY: This is safe
|
write!(f, "{}", serde_json::to_string(self).unwrap()) // SAFETY: This is safe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
(@magic_bytes; $enum_name:ident ($($(#[$variant_attr:meta])* $variant:ident = [$($magic_bytes:tt),*] $(+ $offset:literal)? ),*)) => {
|
||||||
|
impl MagicBytes for $enum_name {
|
||||||
|
fn from_magic_bytes_buf(buf: &[u8]) -> Option<Self> {
|
||||||
|
match buf {
|
||||||
|
$( &[$($magic_bytes),*] => Some($enum_name::$variant),)*
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn magic_bytes_len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
$( $enum_name::$variant => (&[$(magic_byte_value!($magic_bytes)),*] as &[u8]).len() ),*,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn magic_bytes_offset(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
$( $enum_name::$variant => magic_byte_offset!($($offset)?)),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(@magic_bytes; $enum_name:ident ($($(#[$variant_attr:meta])* $variant:ident),*)) => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// video extensions
|
// video extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
VideoExtension ALL_VIDEO_EXTENSIONS {
|
VideoExtension ALL_VIDEO_EXTENSIONS {
|
||||||
Avi,
|
Avi = [0x52, 0x49, 0x46, 0x46, _, _, _, _, 0x41, 0x56, 0x49, 0x20],
|
||||||
Asf,
|
Mpeg = [0x47],
|
||||||
Mpeg,
|
Mts = [0x47, 0x41, 0x39, 0x34],
|
||||||
Mts,
|
Mpg = [],
|
||||||
Mpg,
|
Mpe = [],
|
||||||
Mpe,
|
Qt = [0x71, 0x74, 0x20, 0x20],
|
||||||
Qt,
|
Mov = [0x66, 0x74, 0x79, 0x70, 0x71, 0x74, 0x20, 0x20] + 4,
|
||||||
Mov,
|
Swf = [0x5A, 0x57, 0x53],
|
||||||
Swf,
|
Mjpeg = [],
|
||||||
Mjpeg,
|
Ts = [0x47],
|
||||||
Ts,
|
Mxf = [0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02],
|
||||||
Mxf,
|
M2v = [0x00, 0x00, 0x01, 0xBA],
|
||||||
M2v,
|
M2ts = [],
|
||||||
M2ts,
|
Flv = [0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x56, 0x20] + 4,
|
||||||
Flv,
|
Wm = [],
|
||||||
Wm,
|
|
||||||
#[serde(rename = "3gp")]
|
#[serde(rename = "3gp")]
|
||||||
_3gp,
|
_3gp = [],
|
||||||
M4v,
|
M4v = [0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34, 0x32] + 4,
|
||||||
Wmv,
|
Wmv = [0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C],
|
||||||
Mp4,
|
Asf = [0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C],
|
||||||
Webm,
|
Wma = [0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C],
|
||||||
|
Mp4 = [],
|
||||||
|
Webm = [0x1A, 0x45, 0xDF, 0xA3],
|
||||||
|
Mkv = [0x1A, 0x45, 0xDF, 0xA3],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// image extensions
|
// image extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
ImageExtension _ALL_IMAGE_EXTENSIONS {
|
ImageExtension _ALL_IMAGE_EXTENSIONS {
|
||||||
Jpg,
|
Jpg = [0xFF, 0xD8],
|
||||||
Jpeg,
|
Jpeg = [0xFF, 0xD8],
|
||||||
Png,
|
Png = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A],
|
||||||
Gif,
|
Gif = [0x47, 0x49, 0x46, 0x38, _, 0x61],
|
||||||
Bmp,
|
Bmp = [0x42, 0x4D],
|
||||||
Tiff,
|
Tiff = [0x49, 0x49, 0x2A, 0x00],
|
||||||
Webp,
|
Webp = [0x52, 0x49, 0x46, 0x46, _, _, _, _, 0x57, 0x45, 0x42, 0x50],
|
||||||
Svg,
|
Svg = [0x3C, 0x73, 0x76, 0x67],
|
||||||
Ico,
|
Ico = [0x00, 0x00, 0x01, 0x00],
|
||||||
Heic,
|
Heic = [0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x68, 0x65, 0x69, 0x63],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// audio extensions
|
// audio extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
AudioExtension _ALL_AUDIO_EXTENSIONS {
|
AudioExtension _ALL_AUDIO_EXTENSIONS {
|
||||||
Mp3,
|
Mp3 = [0x49, 0x44, 0x33],
|
||||||
M4a,
|
M4a = [0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20] + 4,
|
||||||
Wav,
|
Wav = [0x52, 0x49, 0x46, 0x46, _, _, _, _, 0x57, 0x41, 0x56, 0x45],
|
||||||
Aiff,
|
Aiff = [0x46, 0x4F, 0x52, 0x4D, _, _, _, _, 0x41, 0x49, 0x46, 0x46],
|
||||||
Aif,
|
Aif = [0x46, 0x4F, 0x52, 0x4D, _, _, _, _, 0x41, 0x49, 0x46, 0x46],
|
||||||
Flac,
|
Flac = [0x66, 0x4C, 0x61, 0x43],
|
||||||
Ogg,
|
Ogg = [0x4F, 0x67, 0x67, 0x53],
|
||||||
Opus,
|
Opus = [0x4F, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// archive extensions
|
// archive extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
ArchiveExtension _ALL_ARCHIVE_EXTENSIONS {
|
ArchiveExtension _ALL_ARCHIVE_EXTENSIONS {
|
||||||
Zip,
|
Zip = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Rar,
|
Rar = [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00],
|
||||||
Tar,
|
Tar = [0x75, 0x73, 0x74, 0x61, 0x72],
|
||||||
Gz,
|
Gz = [0x1F, 0x8B, 0x08],
|
||||||
Bz2,
|
Bz2 = [0x42, 0x5A, 0x68],
|
||||||
SevenZip,
|
#[serde(rename = "7z")]
|
||||||
|
_7z = [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C],
|
||||||
|
Xz = [0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// executable extensions
|
// executable extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
ExecutableExtension _ALL_EXECUTABLE_EXTENSIONS {
|
ExecutableExtension _ALL_EXECUTABLE_EXTENSIONS {
|
||||||
Exe,
|
Exe = [],
|
||||||
App,
|
App = [],
|
||||||
Apk,
|
Apk = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Deb,
|
Deb = [],
|
||||||
Dmg,
|
Dmg = [],
|
||||||
Pkg,
|
Pkg = [],
|
||||||
Rpm,
|
Rpm = [],
|
||||||
Msi,
|
Msi = [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// document extensions
|
// document extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
DocumentExtension _ALL_DOCUMENT_EXTENSIONS {
|
DocumentExtension _ALL_DOCUMENT_EXTENSIONS {
|
||||||
Pdf,
|
Pdf = [0x25, 0x50, 0x44, 0x46, 0x2D],
|
||||||
Key,
|
Key = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Pages,
|
Pages = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Numbers,
|
Numbers = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Doc,
|
Doc = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1],
|
||||||
Docx,
|
Docx = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Xls,
|
Xls = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1],
|
||||||
Xlsx,
|
Xlsx = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Ppt,
|
Ppt = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1],
|
||||||
Pptx,
|
Pptx = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Odt,
|
Odt = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Ods,
|
Ods = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Odp,
|
Odp = [0x50, 0x4B, 0x03, 0x04],
|
||||||
Ics,
|
Ics = [0x42, 0x45, 0x47, 0x49, 0x4E, 0x3A, 0x56, 0x43, 0x41, 0x52, 0x44],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// text file extensions
|
// text file extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
TextExtension _ALL_TEXT_EXTENSIONS {
|
TextExtension _ALL_TEXT_EXTENSIONS {
|
||||||
Txt,
|
Txt,
|
||||||
Rtf,
|
Rtf,
|
||||||
|
@ -243,19 +387,23 @@ enum_with_variants! {
|
||||||
Yaml,
|
Yaml,
|
||||||
Xml,
|
Xml,
|
||||||
Md,
|
Md,
|
||||||
|
Ts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// encrypted file extensions
|
// encrypted file extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
EncryptedExtension _ALL_ENCRYPTED_EXTENSIONS {
|
EncryptedExtension _ALL_ENCRYPTED_EXTENSIONS {
|
||||||
Bit, // Spacedrive encrypted file
|
Bit,
|
||||||
Box, // Spacedrive container
|
Box,
|
||||||
Block,// Spacedrive block storage,
|
Block,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Spacedrive encrypted file
|
||||||
|
// Spacedrive container
|
||||||
|
// Spacedrive block storage,
|
||||||
|
|
||||||
// key extensions
|
// key extensions
|
||||||
enum_with_variants! {
|
extension_category_enum! {
|
||||||
KeyExtension _ALL_KEY_EXTENSIONS {
|
KeyExtension _ALL_KEY_EXTENSIONS {
|
||||||
Pgp,
|
Pgp,
|
||||||
Pub,
|
Pub,
|
||||||
|
@ -265,3 +413,11 @@ enum_with_variants! {
|
||||||
Keychain,
|
Keychain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// font extensions
|
||||||
|
extension_category_enum! {
|
||||||
|
FontExtension _ALL_FONT_EXTENSIONS {
|
||||||
|
Ttf = [0x00, 0x01, 0x00, 0x00, 0x00],
|
||||||
|
Otf = [0x4F, 0x54, 0x54, 0x4F, 0x00],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ export const Inspector = (props: Props) => {
|
||||||
<div className="">
|
<div className="">
|
||||||
{!!props.data && (
|
{!!props.data && (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-center w-full overflow-hidden rounded-md ">
|
<div className="flex items-center justify-center w-full py-4 overflow-hidden rounded-md">
|
||||||
<FileThumb
|
<FileThumb
|
||||||
iconClassNames="!my-10"
|
iconClassNames="!my-10"
|
||||||
size={230}
|
size={230}
|
||||||
|
|
|
@ -21,7 +21,8 @@ export const SidebarLink = (props: NavLinkProps & { children: React.ReactNode })
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'max-w mb-[2px] text-gray-550 dark:text-gray-300 rounded px-2 py-1 flex flex-row flex-grow items-center font-medium text-sm',
|
'max-w mb-[2px] text-gray-550 dark:text-gray-300 rounded px-2 py-1 flex flex-row flex-grow items-center font-medium text-sm',
|
||||||
{
|
{
|
||||||
'!bg-primary !text-white hover:bg-primary dark:hover:bg-primary': isActive
|
'!bg-gray-400 !bg-opacity-10 !text-white hover:bg-gray-400 dark:hover:bg-gray-400':
|
||||||
|
isActive
|
||||||
},
|
},
|
||||||
props.className
|
props.className
|
||||||
)}
|
)}
|
||||||
|
@ -85,13 +86,14 @@ function LibraryScopedSection() {
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'max-w mb-[2px] text-gray-550 dark:text-gray-150 rounded px-2 py-1 gap-2 flex flex-row flex-grow items-center truncate text-sm',
|
'max-w mb-[2px] text-gray-550 dark:text-gray-150 rounded px-2 py-1 gap-2 flex flex-row flex-grow items-center truncate text-sm',
|
||||||
{
|
{
|
||||||
'!bg-primary !text-white hover:bg-primary dark:hover:bg-primary': isActive
|
'!bg-gray-400 !bg-opacity-10 !text-white hover:bg-gray-400 dark:hover:bg-gray-400':
|
||||||
|
isActive
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="-mt-0.5 flex-grow-0 flex-shrink-0">
|
<div className="-mt-0.5 flex-grow-0 flex-shrink-0">
|
||||||
<Folder size={18} className={clsx(!isActive && 'hidden')} white />
|
{/* <Folder size={18} className={clsx(!isActive && 'hidden')} white /> */}
|
||||||
<Folder size={18} className={clsx(isActive && 'hidden')} />
|
<Folder size={18} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span className="flex-grow flex-shrink-0">{location.name}</span>
|
<span className="flex-grow flex-shrink-0">{location.name}</span>
|
||||||
|
|
|
@ -102,7 +102,7 @@ const SearchBar = forwardRef<HTMLInputElement, DefaultProps>((props, forwardedRe
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'space-x-1 absolute top-[2px] right-1 peer-focus:invisible pointer-events-none',
|
'space-x-1 absolute top-[1px] right-1 peer-focus:invisible pointer-events-none',
|
||||||
isDirty && 'hidden'
|
isDirty && 'hidden'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -12,10 +12,10 @@ export const Shortcut: React.FC<ShortcutProps> = (props) => {
|
||||||
return (
|
return (
|
||||||
<kbd
|
<kbd
|
||||||
className={clsx(
|
className={clsx(
|
||||||
`px-1 py-0.5 border border-b-2`,
|
`px-1 border border-b-2`,
|
||||||
`rounded-lg text-xs font-bold`,
|
`rounded-lg text-xs font-bold`,
|
||||||
`text-gray-400 bg-gray-200 border-gray-300`,
|
`text-gray-400 bg-gray-200 border-gray-300`,
|
||||||
`dark:text-gray-400 dark:bg-gray-600 dark:border-gray-500`,
|
`dark:text-gray-400 dark:bg-transparent dark:border-transparent`,
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
|
Loading…
Reference in a new issue