diff --git a/index.html b/index.html
index ff93803..57071a9 100644
--- a/index.html
+++ b/index.html
@@ -1,10 +1,10 @@
-
+
- Tauri + React + Typescript
+ byte-me
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index df4051b..e2be1cd 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -343,6 +343,7 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
name = "byte-me"
version = "0.1.0"
dependencies = [
+ "ffprobe",
"serde",
"serde_json",
"tauri",
@@ -938,6 +939,16 @@ dependencies = [
"simd-adler32",
]
+[[package]]
+name = "ffprobe"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ffef835e1f9ac151db5bb2adbb95c9dfe1f315f987f011dd89cd655b4e9a52c"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "field-offset"
version = "0.3.6"
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 7a19f27..d808f48 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -22,4 +22,5 @@ tauri = { version = "2", features = [] }
tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
+ffprobe = "0.4.0"
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 4a277ef..d1319e6 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -1,14 +1,34 @@
-// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
+use std::path::Path;
+
#[tauri::command]
-fn greet(name: &str) -> String {
- format!("Hello, {}! You've been greeted from Rust!", name)
+fn has_streams(paths: Vec) -> Result, String> {
+ let mut results = Vec::with_capacity(paths.len());
+ for path_str in paths {
+ let path = Path::new(&path_str);
+ if !path.is_file() {
+ results.push(false);
+ continue;
+ }
+
+ match ffprobe::ffprobe(&path_str) {
+ Ok(info) => {
+ dbg!(info);
+ results.push(true);
+ },
+ Err(err) => {
+ eprintln!("Could not analyze file with ffprobe: {:?}", err);
+ results.push(false);
+ }
+ }
+ }
+ Ok(results)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
- .invoke_handler(tauri::generate_handler![greet])
+ .invoke_handler(tauri::generate_handler![has_streams])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
diff --git a/src/App.css b/src/App.css
deleted file mode 100644
index f7de85b..0000000
--- a/src/App.css
+++ /dev/null
@@ -1,109 +0,0 @@
-:root {
- font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
- font-size: 16px;
- line-height: 24px;
- font-weight: 400;
-
- color: #0f0f0f;
- background-color: #f6f6f6;
-
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- -webkit-text-size-adjust: 100%;
-}
-
-.container {
- margin: 0;
- padding-top: 10vh;
- display: flex;
- flex-direction: column;
- justify-content: center;
- text-align: center;
-}
-
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
- transition: 0.75s;
-}
-
-.logo.tauri:hover {
- filter: drop-shadow(0 0 2em #24c8db);
-}
-
-.row {
- display: flex;
- justify-content: center;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-
-a:hover {
- color: #535bf2;
-}
-
-h1 {
- text-align: center;
-}
-
-input,
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- color: #0f0f0f;
- background-color: #ffffff;
- transition: border-color 0.25s;
- box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
-}
-
-button {
- cursor: pointer;
-}
-
-button:hover {
- border-color: #396cd8;
-}
-button:active {
- border-color: #396cd8;
- background-color: #e8e8e8;
-}
-
-input,
-button {
- outline: none;
-}
-
-#greet-input {
- margin-right: 5px;
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- color: #f6f6f6;
- background-color: #2f2f2f;
- }
-
- a:hover {
- color: #24c8db;
- }
-
- input,
- button {
- color: #ffffff;
- background-color: #0f0f0f98;
- }
- button:active {
- background-color: #0f0f0f69;
- }
-}
diff --git a/src/App.tsx b/src/App.tsx
index 25f5c0c..e3a5d95 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,26 +1,26 @@
-import { ResponsiveLine } from "@nivo/line";
-import { formatBytes } from "./lib/format.js";
-
type Frame = {
id: string;
data: { x: string | number; y: number }[];
};
import { getCurrentWebview } from "@tauri-apps/api/webview";
-import { useEffect } from "react";
+import { useEffect, useRef, useState } from "react";
+import Graph from "./components/Graph.js";
+import DropOverlay from "./components/drop-overlay.js";
function App() {
const data: Frame[] = [];
+ const [paths, setPaths] = useState([]);
useEffect(() => {
const unlistenPromise = getCurrentWebview().onDragDropEvent(
- async (event) => {
- if (event.payload.type === "over") {
- console.log("User hovering", event.payload.position);
- } else if (event.payload.type === "drop") {
- console.log("User dropped", event.payload.paths);
- } else {
- console.log("File drop cancelled");
+ async ({ payload }) => {
+ if (payload.type === "enter") {
+ setPaths(payload.paths);
+ console.log("User hovering", payload);
+ } else if (payload.type === "leave" || payload.type === "drop") {
+ setPaths([]);
+ console.log("User left", payload);
}
}
);
@@ -34,106 +34,7 @@ function App() {
};
}, []);
- // const data: Frame[] = useMemo(() =>
- // // Array.from({ length: 4 }, (_, i) => {
- // // const d = Math.random();
- // // const g = Math.random();
- // // return {
- // // id: `file-${i}`,
- // // data: Array.from({ length: 500 }, (_, j) => {
- // // if (Math.random() < 0.5) return null;
- // // return {
- // // x: j,
- // // y: Math.random() * 256 * d + (1 - g) * 1024,
- // // };
- // // }).filter((i) => i !== null),
- // // };
- // // }),
- // []
- // );
-
- console.log(data);
-
- const graph = (
- formatBytes(v * 1024 * 53),
- }}
- pointSize={10}
- colors={[
- "#3e8faf",
- "#c4a7e7",
- "#f5c276",
- "#EA9B96",
- "#EB7092",
- "#9CCFD8",
- ]}
- // pointColor={{ modifiers: [["brighter", 1100]] }}
- pointBorderWidth={0}
- pointBorderColor={{ from: "seriesColor" }}
- pointLabelYOffset={-12}
- enableSlices={"x"}
- enableTouchCrosshair={true}
- useMesh={true}
- legends={[
- {
- anchor: "bottom-right",
- direction: "column",
- translateX: 100,
- itemWidth: 80,
- itemHeight: 22,
- symbolShape: "circle",
- },
- ]}
- />
- );
+ const graph = ;
return (
-
-
-
- Drag and Drop to Add
-
-
-
+
{graph}
);
diff --git a/src/components/drop-overlay.tsx b/src/components/drop-overlay.tsx
new file mode 100644
index 0000000..841cee4
--- /dev/null
+++ b/src/components/drop-overlay.tsx
@@ -0,0 +1,46 @@
+import { invoke } from "@tauri-apps/api/core";
+import { useEffect, useState } from "react";
+
+type DropOverlayProps = {
+ paths: string[];
+};
+
+type Status = "hidden" | "loading" | "ready" | "error";
+
+const DropOverlay = ({ paths }: DropOverlayProps) => {
+ const [status, setStatus] = useState("hidden");
+
+ useEffect(() => {
+ if (paths.length === 0) {
+ setStatus("hidden");
+ return;
+ }
+
+ setStatus("loading");
+ invoke("has_streams", { paths }).then((result) => {
+ setStatus(result ? "ready" : "error");
+ });
+ }, [paths]);
+
+ return (
+
+
+
+ {status === "loading"
+ ? "Loading..."
+ : status === "ready"
+ ? "Ready"
+ : status === "error"
+ ? "Error"
+ : "Hidden"}
+
+
+
+ );
+};
+
+export default DropOverlay;
diff --git a/src/components/graph.tsx b/src/components/graph.tsx
new file mode 100644
index 0000000..1ebe8ff
--- /dev/null
+++ b/src/components/graph.tsx
@@ -0,0 +1,85 @@
+import { ResponsiveLine } from "@nivo/line";
+import { formatBytes } from "../lib/format.js";
+
+type Frame = {
+ id: string;
+ data: { x: string | number; y: number }[];
+};
+
+type GraphProps = {
+ data: Frame[];
+};
+
+const Graph = ({ data }: GraphProps) => (
+ formatBytes(v * 1024 * 53),
+ }}
+ pointSize={10}
+ colors={["#3e8faf", "#c4a7e7", "#f5c276", "#EA9B96", "#EB7092", "#9CCFD8"]}
+ pointBorderWidth={0}
+ pointBorderColor={{ from: "seriesColor" }}
+ pointLabelYOffset={-12}
+ enableSlices={"x"}
+ enableTouchCrosshair={true}
+ useMesh={true}
+ legends={[
+ {
+ anchor: "bottom-right",
+ direction: "column",
+ translateX: 100,
+ itemWidth: 80,
+ itemHeight: 22,
+ symbolShape: "circle",
+ },
+ ]}
+ />
+);
+
+export default Graph;
diff --git a/src/global.css b/src/global.css
index 9df2d9b..cfcbf9c 100644
--- a/src/global.css
+++ b/src/global.css
@@ -37,16 +37,3 @@ body {
height: 100vh;
text-align: center;
}
-
-#drop-target {
- pointer-events: none;
- opacity: 0;
- background-color: rgb(0, 0, 0, 0.5) !important;
-}
-
-.wails-drop-target-active {
- #drop-target {
- pointer-events: auto;
- opacity: 1;
- }
-}