raw images :D

This commit is contained in:
Jamie 2021-10-19 20:48:05 -07:00
parent 600adc8fa9
commit 4aaef94a5b
16 changed files with 187 additions and 182 deletions

1
.env Normal file
View file

@ -0,0 +1 @@
OUT_DIR=""

View file

@ -49,7 +49,7 @@ fn build_swift_natives() {
if !Command::new("swift")
.args(&["build", "-c", &profile])
.current_dir("./swift")
.current_dir("./swift-lib")
.status()
.unwrap()
.success()
@ -65,11 +65,11 @@ fn build_swift_natives() {
println!("cargo:rustc-link-search=native={}", path);
});
println!(
"cargo:rustc-link-search=native=./swift/.build/{}/{}",
"cargo:rustc-link-search=native=./swift-lib/.build/{}/{}",
swift_target_info.target.unversioned_triple, profile
);
println!("cargo:rustc-link-lib=static=spacedrive");
println!("cargo:rerun-if-changed=swift/src/*.swift");
println!("cargo:rustc-link-lib=static=swift-lib");
println!("cargo:rerun-if-changed=swift-lib/src/*.swift");
println!(
"cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET={}",
MACOS_TARGET_VERSION
@ -77,10 +77,6 @@ fn build_swift_natives() {
}
fn main() {
// let target = env::var("CARGO_CFG_TARGET_OS").unwrap();
// if target == "macos" {
build_swift_natives();
// }
tauri_build::build();
}

View file

@ -1,5 +1,6 @@
use crate::db::entity::file;
use crate::filesystem::retrieve::Directory;
use crate::swift::get_file_thumbnail_base64;
use crate::{db, filesystem};
use anyhow::Result;
use once_cell::sync::OnceCell;
@ -32,6 +33,13 @@ pub async fn scan_dir(path: String) -> Result<(), String> {
Ok(())
}
#[tauri::command(async)]
pub async fn get_file_thumb(path: &str) -> Result<String, String> {
let path = &path.to_string();
let thumbnail_b46 = get_file_thumbnail_base64(path.into()).to_string();
Ok(thumbnail_b46)
}
#[tauri::command(async)]
pub async fn get_files(path: String) -> Result<Directory, String> {

View file

@ -8,76 +8,14 @@ mod crypto;
mod db;
mod device;
mod filesystem;
mod swift;
mod util;
use crate::app::menu;
use env_logger;
use futures::executor::block_on;
// use systemstat::{saturating_sub_bytes, Platform, System};
#[derive(Debug)]
#[repr(C)]
struct FFIString {
// _phantom: u8,
data: *const u8,
length: u64,
}
#[derive(Debug)]
#[repr(C)]
struct FFIData {
// _phantom: u8,
data: *const u8,
length: u64,
}
extern "C" {
fn get_file_thumbnail(ptr: *const u8, length: u64) -> FFIData;
fn test(ptr: *const u8, length: u64) -> FFIData;
}
fn main() {
let path = "/Users/jamie/Downloads/Audio Hijack.app";
// let string = FFIString {
// data: path.as_ptr(),
// length: path.len(),
// };
// let thumbnail = unsafe {
// println!("{:?}", string);
// get_file_thumbnail(&string)
// };
println!("Struct Data: {:?}", unsafe {
let res = test(path.as_ptr(), path.len() as u64);
let mut vec = Vec::<u8>::new();
let mut pointer_str = String::new();
for j in 8..16 {
let num = *(res.data.add(j));
vec.push(num);
pointer_str = format!("{:x}", num) + &pointer_str;
}
let pointer_num = u64::from_str_radix(&pointer_str, 16).unwrap();
let pointer = pointer_num as *const u8;
let mut length = 0;
for j in 16..24 {
let num = *(res.data.add(j));
length += num as usize * 256_usize.pow(j as u32 - 16_u32)
}
let mut data = Vec::new();
for i in 0..length {
data.push(*pointer.add(i));
}
res
});
// unsafe { get_icon("/Users/jamie/Downloads/Audio Hijack.app") }
// let mounts = device::volumes_c::get_mounts();
// println!("mounted drives: {:?}", &mounts);
// env_logger::builder()
@ -95,7 +33,8 @@ fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
commands::scan_dir,
commands::get_files
commands::get_files,
commands::get_file_thumb
])
.menu(menu::get_menu())
.run(tauri::generate_context!())

View file

@ -1,28 +0,0 @@
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "drive_mac",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "swift",
targets: ["swift"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "swift",
dependencies: []),
.testTarget(
name: "swiftTests",
dependencies: ["swift"]),
]
)

View file

@ -0,0 +1,59 @@
#[derive(Debug)]
#[repr(C)]
struct SRArray<T> {
_nsobject_offset: u8,
data: *mut T,
length: usize,
}
impl<T> SRArray<T> {
fn into_slice(&self) -> &'static [T] {
unsafe { std::slice::from_raw_parts(self.data, self.length) }
}
}
#[derive(Debug)]
#[repr(C)]
struct SRData {
_nsobject_offset: u8,
data: *mut SRArray<u8>,
}
impl SRData {
pub fn into_slice(&self) -> &'static [u8] {
unsafe { (*self.data).into_slice() }
}
pub fn data(&self) -> &SRArray<u8> {
unsafe { &*(self.data) }
}
}
#[derive(Debug)]
#[repr(C)]
pub struct SRString(SRData);
impl SRString {
pub fn to_string(&self) -> String {
unsafe { std::str::from_utf8_unchecked(self.0.into_slice()) }.into()
}
}
impl From<&String> for &SRString {
fn from(string: &String) -> &'static SRString {
unsafe { allocate_string(string.as_ptr(), string.len()) }
}
}
extern "C" {
fn return_data() -> &'static SRData;
fn return_string() -> &'static SRString;
fn echo_string(string: &SRString);
fn allocate_string(data: *const u8, size: usize) -> &'static SRString;
#[link_name = "get_file_thumbnail_base64"]
fn get_file_thumbnail_base64_(path: &SRString) -> &'static SRString;
}
pub fn get_file_thumbnail_base64(path: &SRString) -> &'static SRString {
unsafe { get_file_thumbnail_base64_(path) }
}

View file

@ -4,16 +4,16 @@
import PackageDescription
let package = Package(
name: "spacedrive",
name: "swift-lib",
platforms: [
.macOS(.v11),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "spacedrive",
name: "swift-lib",
type: .static,
targets: ["spacedrive"]),
targets: ["swift-lib"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
@ -23,7 +23,7 @@ let package = Package(
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "spacedrive",
name: "swift-lib",
dependencies: [],
path: "src")
]

View file

@ -0,0 +1,78 @@
import Foundation
import AppKit
// Size: 24 bytes
public class SRArray<T>: NSObject {
var pointer: UnsafePointer<T>
var length: Int
init(_ data: [T]) {
let mut_data = UnsafeMutablePointer<T>.allocate(capacity: data.count)
mut_data.initialize(from: data, count: data.count)
self.pointer = UnsafePointer(mut_data)
self.length = data.count
}
}
// Size: 16 bytes
public class SRData: NSObject {
var data: SRArray<UInt8>
init(_ data: [UInt8]) {
self.data = SRArray(data)
}
func to_data() -> Data {
return Data(bytes: self.data.pointer, count: self.data.length)
}
}
// Size: 16 bytes
public class SRString: SRData {
init(_ string: String) {
super.init(Array(string.utf8))
}
func to_string() -> String {
return String(bytes: self.to_data(), encoding: .utf8)!
}
}
@_cdecl("return_data")
public func returnData() -> SRData {
return SRData([1,2,3])
}
@_cdecl("return_string")
public func returnString() -> SRString {
return SRString("123456")
}
@_cdecl("echo_string")
public func echoString(string: SRString) {
print(string.to_string())
}
// SRstring pointer is passed to rust correctly
// data pointer is passed to rust correctly
// guessing that the type of SRArray isn't the same
@_cdecl("allocate_string")
public func allocate_string(data: UnsafePointer<UInt8>, size: Int) -> SRString {
let buffer = UnsafeBufferPointer(start: data, count: size)
let string = String(bytes: buffer, encoding: .utf8)!;
let SRstring = SRString(string);
return SRstring
}
@_cdecl("get_file_thumbnail_base64")
public func getFileThumbnailBase64(path: SRString) -> SRString {
let path = path.to_string();
let image = NSWorkspace.shared.icon(forFile: path)
let bitmap = NSBitmapImageRep(data: image.tiffRepresentation!)!.representation(using: .png, properties: [:])!
return SRString(bitmap.base64EncodedString())
}

View file

@ -1,3 +0,0 @@
# spacedive_swift
A description of this package.

View file

@ -1,62 +0,0 @@
import Foundation
import AppKit
public class FFIString: NSObject {
var data: UnsafePointer<CChar>
var length: UInt64
init(data: UnsafePointer<CChar>, length: UInt64) {
self.data = data
self.length = length
}
}
public class FFIData: NSObject {
var data: UnsafePointer<UInt8>
var length: UInt64
init(data: UnsafePointer<UInt8>, length: UInt64) {
self.data = data
self.length = length
}
}
@_cdecl("get_file_thumbnail")
public func getFileThumbnail(path_ptr: UnsafePointer<CChar>, path_length: UInt64) -> FFIData {
print(path_length)
let path = String(data: Data(bytes: path_ptr, count: Int(path_length)), encoding: String.Encoding.utf8)!
print(path)
let image = NSWorkspace.shared.icon(forFile: path)
let bitmap = NSBitmapImageRep(data: image.tiffRepresentation!)!.representation(using: .png, properties: [:])!
let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: bitmap.count)
bitmap.copyBytes(to: pointer, count: bitmap.count)
return FFIData(data: UnsafePointer(pointer), length: UInt64(bitmap.count))
}
@_cdecl("test")
public func test(path_ptr: UnsafePointer<CChar>, path_length: UInt64) -> FFIString {
let path = String(data: Data(bytes: path_ptr, count: Int(path_length)), encoding: String.Encoding.utf8)!
print(path)
let image = NSWorkspace.shared.icon(forFile: path)
let bitmap = NSBitmapImageRep(data: image.tiffRepresentation!)!.representation(using: .png, properties: [:])!
let pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: bitmap.count)
bitmap.copyBytes(to: pointer, count: bitmap.count)
let data = UnsafePointer<UInt8>(pointer);
let length = UInt64(bitmap.count)
print(data)
print(length)
let ret = FFIString(
data: UnsafePointer<CChar>(strdup(path)!),
length: UInt64(path.lengthOfBytes(using: .utf8))
)
print(ret)
return ret
}

View file

@ -5,6 +5,7 @@ import { TopBar } from './components/layout/TopBar';
import { useInputState } from './hooks/useInputState';
import { SettingsScreen } from './screens/Settings';
import { ExplorerScreen } from './screens/Explorer';
import { invoke } from '@tauri-apps/api';
export default function App() {
return (

View file

@ -1,6 +1,6 @@
import { DocumentIcon, DotsVerticalIcon, FilmIcon, FolderIcon } from '@heroicons/react/solid';
import clsx from 'clsx';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { IFile } from '../../types';
import byteSize from 'pretty-bytes';
import { useKey } from 'rooks';
@ -100,6 +100,16 @@ export const FileList: React.FC<{}> = (props) => {
};
const RenderRow: React.FC<{ row: IFile; rowIndex: number }> = ({ row, rowIndex }) => {
const [image, setImage] = useState<string | undefined>();
useEffect(() => {
if (row.uri)
invoke('get_file_thumb', { path: row.uri }).then((imageData) => {
console.log({ imageData: (imageData as string).slice(1, 50) });
setImage(imageData as string);
});
}, [row.uri]);
const [collectDir, selectedRow, setSelectedRow] = useExplorerStore((state) => [
state.collectDir,
state.selected,
@ -136,16 +146,20 @@ const RenderRow: React.FC<{ row: IFile; rowIndex: number }> = ({ row, rowIndex }
className="table-body-cell px-4 py-2 flex items-center pr-2"
style={{ width: col.width }}
>
<RenderCell row={row} colKey={col?.key} />
<RenderCell image={image} row={row} colKey={col?.key} />
</div>
))}
</div>
),
[isActive]
[isActive, image]
);
};
const RenderCell: React.FC<{ colKey?: ColumnKey; row?: IFile }> = ({ colKey, row }) => {
const RenderCell: React.FC<{ colKey?: ColumnKey; row?: IFile; image?: string }> = ({
colKey,
row,
image
}) => {
if (!row || !colKey || !row[colKey]) return <></>;
const value = row[colKey];
@ -153,7 +167,8 @@ const RenderCell: React.FC<{ colKey?: ColumnKey; row?: IFile }> = ({ colKey, row
case 'name':
return (
<div className="flex flex-row items-center overflow-hidden">
{colKey == 'name' &&
{!!image && <img src={'data:image/png;base64, ' + image} className="w-6 h-6 mr-2" />}
{/* {colKey == 'name' &&
(() => {
switch (row.extension.toLowerCase()) {
case 'mov' || 'mp4':
@ -164,7 +179,7 @@ const RenderCell: React.FC<{ colKey?: ColumnKey; row?: IFile }> = ({ colKey, row
return <FolderIcon className="w-5 h-5 mr-3 flex-shrink-0 text-gray-300" />;
return <DocumentIcon className="w-5 h-5 mr-3 flex-shrink-0 text-gray-300" />;
}
})()}
})()} */}
<span className="truncate text-xs">{row[colKey]}</span>
</div>
);

View file

@ -33,9 +33,9 @@ export const Inspector = () => {
leaveFrom="translate-x-0"
leaveTo="translate-x-64"
>
<div className="h-full w-52 absolute right-0 top-0 m-1">
<div className="flex flex-col overflow-hidden h-full rounded-md bg-gray-800 shadow-xl select-text">
<div className="h-32 bg-gray-950 w-full" />
<div className="h-full w-60 absolute right-0 top-0 m-2">
<div className="flex flex-col overflow-hidden h-full rounded-lg bg-gray-700 shadow-lg select-text">
<div className="h-32 bg-gray-750 w-full" />
<h3 className="font-bold p-3 text-base">{selectedFile?.name}</h3>
<MetaItem title="Checksum" value={selectedFile?.meta_checksum as string} />
<Divider />

View file

@ -24,11 +24,12 @@ interface SidebarProps extends DefaultProps {}
export const Sidebar: React.FC<SidebarProps> = (props) => {
return (
<div className="w-46 flex flex-col flex-wrap flex-shrink-0 min-h-full bg-gray-50 dark:bg-gray-850 border-gray-100 border-r dark:border-gray-700 px-3 space-y-0.5">
<div className="w-46 flex flex-col flex-wrap flex-shrink-0 min-h-full bg-gray-50 dark:bg-gray-650 border-gray-100 border-r dark:border-gray-700 px-3 space-y-0.5">
<Dropdown
buttonProps={{
justifyLeft: true,
className: 'mb-1 shadow flex-shrink-0 w-[175px] dark:bg-gray-650',
className:
'mb-1 shadow flex-shrink-0 w-[175px] dark:bg-gray-550 dark:hover:!bg-gray-500 dark:hover:!border-gray-450',
variant: 'gray'
}}
buttonText="Jamie's Library"

View file

@ -51,7 +51,7 @@ export const TopBar: React.FC<TopBarProps> = (props) => {
<>
<div
data-tauri-drag-region
className="flex flex-shrink-0 h-10 max-w items-center border-b bg-gray-100 dark:bg-gray-650 border-gray-100 dark:border-gray-900 shadow-sm "
className="flex flex-shrink-0 h-10 max-w items-center border-b bg-gray-100 dark:bg-gray-650 border-gray-100 dark:border-gray-900 shadow-sm"
>
<div className="mr-32 ml-1 ">
<TrafficLights className="p-1.5" />
@ -67,7 +67,7 @@ export const TopBar: React.FC<TopBarProps> = (props) => {
<div className="relative flex h-7">
<Input
placeholder="Search"
className="placeholder-gray-600 bg-gray-50 zdark:bg-gray-600 dark:hover:bg-gray-600 text-xs w-32 focus:w-52 transition-all"
className="placeholder-gray-600 bg-gray-50 dark:bg-gray-600 dark:hover:!bg-gray-600 dark:focus:hover:!bg-gray-800 text-xs w-32 focus:w-52 transition-all"
/>
<div className="space-x-1 absolute top-[1px] right-1">
<Shortcut chars="⌘" />