Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit 346cd52

Browse files
authored
Merge pull request #47 from tkr-sh/master
feat: file-explorer working example with v0.5
2 parents 0910da5 + eede59e commit 346cd52

File tree

9 files changed

+134
-105
lines changed

9 files changed

+134
-105
lines changed

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
members = [
33
"dog-app",
44
"ecommerce-site",
5-
"file-explorer",
65
"image_generator_open_ai",
76
"ios_demo",
87
"jsframework-benchmark",

file-explorer/.gitignore

+13-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,13 @@
1-
/target
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
/target/
4+
/dist/
5+
/static/
6+
/.dioxus/
7+
8+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
9+
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
10+
Cargo.lock
11+
12+
# These are backup files generated by rustfmt
13+
**/*.rs.bk

file-explorer/Cargo.toml

+13-16
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
[package]
22
name = "file-explorer"
3-
version = "0.1.1"
4-
edition = "2018"
5-
description = "File Explorer with Dioxus"
3+
edition = "2021"
4+
version = "0.1.0"
65

76
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
87

98
[dependencies]
10-
dioxus = { version = "0.4.0" }
11-
dioxus-desktop = { version = "0.4.0" }
12-
log = "0.4.14"
13-
open = "5.0.0"
14-
simple_logger = "4.2.0"
159

10+
dioxus = { version = "0.5", features = ["desktop"] }
11+
12+
# Debug
13+
log = "0.4.19"
14+
dioxus-logger = "0.4.1"
15+
open = "5.1.2"
1616

1717
[package.metadata.bundle]
1818
name = "Dioxus File Explorerer"
1919
identifier = "com.doe.exampleapplication"
2020
icon = ["32x32.png", "128x128.png", "[email protected]"]
21-
version = "1.0.0"
21+
version = "1.1.0"
22+
authors = ["tkr-sh <[email protected]>", "Jonathan Kelley <[email protected]>"]
2223
resources = ["assets", "images/**/*.png", "secrets/public_key.txt"]
2324
copyright = "Copyright (c) Jane Doe 2016. All rights reserved."
2425
category = "Developer Tool"
2526
short_description = "An example application."
26-
long_description = """
27-
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
28-
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
29-
enim ad minim veniam, quis nostrud exercitation ullamco laboris
30-
nisi ut aliquip ex ea commodo consequat.
31-
"""
32-
osx_frameworks = []
27+
28+
# This package is not part of the workspace to avoid dependancy resolution issues between dioxus 0.4 and 0.5
29+
[workspace]

file-explorer/Dioxus.toml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
[application]
2+
3+
# App (Project) Name
4+
name = "file-explorer"
5+
6+
# Dioxus App Default Platform
7+
# desktop, web
8+
default_platform = "desktop"
9+
10+
# `build` & `serve` dist path
11+
out_dir = "dist"
12+
13+
# assets file folder
14+
asset_dir = "assets"
15+
16+
[web.app]
17+
18+
# HTML title tag content
19+
title = "file-explorer"
20+
21+
[web.watcher]
22+
23+
# when watcher trigger, regenerate the `index.html`
24+
reload_html = true
25+
26+
# which files or dirs will be watcher monitoring
27+
watch_path = ["src", "assets"]
28+
29+
# include `assets` in web platform
30+
[web.resource]
31+
32+
# CSS style file
33+
34+
style = []
35+
36+
# Javascript code file
37+
script = []
38+
39+
[web.resource.dev]
40+
41+
# Javascript code file
42+
# serve: [dev-server] only
43+
script = []

file-explorer/README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
This example shows how a Dioxus App can directly leverage system calls and libraries to bridge native functionality with the WebView renderer.
44

5-
![example](./image.png)
5+
![example](./src/image.png)
66

77

88
## To run this example:
99

1010
```
11-
cargo run
11+
dx serve
1212
```
13+

file-explorer/assets/image.png

44.1 KB
Loading

file-explorer/src/style.css renamed to file-explorer/assets/main.css

-23
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,6 @@ body {
1010
padding-top: 77px;
1111
}
1212

13-
/* header {
14-
position: fixed;
15-
top: 0;
16-
left: 0;
17-
right: 0;
18-
z-index: 10;
19-
padding: 20px;
20-
background-color: #2196F3;
21-
color: white;
22-
}
23-
header h1 {
24-
float: left;
25-
font-size: 20px;
26-
font-weight: 400;
27-
}
28-
header .material-icons {
29-
float: right;
30-
cursor: pointer;
31-
}
32-
header .icon-menu {
33-
float: left;
34-
margin-right: 20px;
35-
} */
3613

3714
main {
3815
padding: 20px 50px;

file-explorer/image.png

-46.4 KB
Binary file not shown.

file-explorer/src/main.rs

+62-62
Original file line numberDiff line numberDiff line change
@@ -7,73 +7,71 @@
77
//! This example is interesting because it's mixing filesystem operations and GUI, which is typically hard for UI to do.
88
99
use dioxus::prelude::*;
10-
use dioxus_desktop::{Config, WindowBuilder};
11-
10+
use log::LevelFilter;
1211

1312
fn main() {
14-
// simple_logger::init_with_level(log::Level::Debug).unwrap();
15-
dioxus_desktop::launch_cfg(
16-
App,
17-
Config::default().with_window(WindowBuilder::new().with_resizable(true).with_inner_size(
18-
dioxus_desktop::wry::application::dpi::LogicalSize::new(400.0, 800.0),
19-
)),
20-
);
13+
// Init debug
14+
dioxus_logger::init(LevelFilter::Info).expect("failed to init logger");
15+
16+
dioxus::launch(App);
2117
}
2218

23-
fn App(cx: Scope) -> Element {
24-
let files = use_ref(cx, Files::new);
25-
26-
render!(div {
27-
link { href:"https://fonts.googleapis.com/icon?family=Material+Icons", rel:"stylesheet" }
28-
style { include_str!("./style.css") }
29-
header {
30-
i { class: "material-icons icon-menu", "menu" }
31-
h1 { "Files: " "{files.read().current()}" }
32-
span { }
33-
i { class: "material-icons", onclick: move |_| files.write().go_up(), "logout" }
34-
}
35-
main {
36-
files.read().path_names.iter().enumerate().map(|(dir_id, path)| {
37-
let path_end = path.split('/').last().unwrap_or(path.as_str());
38-
let icon_type = if path_end.contains('.') {
39-
"description"
40-
} else {
41-
"folder"
42-
};
43-
rsx! (
44-
div { class: "folder", key: "{path}",
19+
#[component]
20+
fn App() -> Element {
21+
// Build cool things ✌️
22+
let mut files = use_signal(|| Files::new());
23+
24+
rsx! {
25+
div {
26+
link { href: "https://fonts.googleapis.com/icon?family=Material+Icons", rel: "stylesheet" }
27+
link { rel: "stylesheet", href: "main.css" }
28+
header {
29+
i { class: "material-icons icon-menu", "menu" }
30+
h1 { "Files: {files.read().current()}" }
31+
span { }
32+
i { class: "material-icons", onclick: move |_| files.write().go_up(), "logout" }
33+
}
34+
main {
35+
for (dir_id, path) in files.read().path_names.iter().enumerate() {
36+
div {
37+
class: "folder", key: "{path.name}",
4538
i { class: "material-icons",
4639
onclick: move |_| files.write().enter_dir(dir_id),
47-
"{icon_type}"
40+
// Change the icon
41+
if path.is_directory { "folder" } else { "description" }
42+
// The tooltip
4843
p { class: "cooltip", "0 folders / 0 files" }
4944
}
50-
h1 { "{path_end}" }
45+
h1 { "{path.name}" }
5146
}
52-
)
53-
})
54-
files.read().err.as_ref().map(|err| {
55-
rsx! (
47+
}
48+
if let Some(err) = files.read().err.as_ref() {
5649
div {
5750
code { "{err}" }
5851
button { onclick: move |_| files.write().clear_err(), "x" }
5952
}
60-
)
61-
})
53+
}
54+
}
6255
}
56+
}
57+
}
6358

64-
})
59+
#[derive(Debug)]
60+
struct File {
61+
is_directory: bool,
62+
name: String,
6563
}
6664

6765
struct Files {
6866
path_stack: Vec<String>,
69-
path_names: Vec<String>,
67+
path_names: Vec<File>,
7068
err: Option<String>,
7169
}
7270

7371
impl Files {
7472
fn new() -> Self {
7573
let mut files = Self {
76-
path_stack: vec!["./".to_string()],
74+
path_stack: vec![".".to_string()],
7775
path_names: vec![],
7876
err: None,
7977
};
@@ -84,26 +82,24 @@ impl Files {
8482
}
8583

8684
fn reload_path_list(&mut self) {
87-
let cur_path = self.path_stack.last().unwrap();
85+
let cur_path = self.path_stack.join("/");
8886
log::info!("Reloading path list for {:?}", cur_path);
89-
let paths = match std::fs::read_dir(cur_path) {
87+
let paths = match std::fs::read_dir(&cur_path) {
9088
Ok(e) => e,
91-
Err(err) => { //Likely we're trying to open a file, so let's open it!
92-
match open::that(cur_path){
93-
Ok(_) => {
94-
log::info!("Opened file");
95-
return;
96-
},
97-
Err(err) => {
98-
let err = format!("An error occurred: {:?}", err);
99-
self.err = Some(err);
100-
self.path_stack.pop();
101-
return;
102-
}
89+
Err(err) => {
90+
// Likely we're trying to open a file, so let's open it!
91+
if let Ok(_) = open::that(cur_path) {
92+
log::info!("Opened file");
93+
return;
94+
} else {
95+
let err = format!("An error occurred: {:?}", err);
96+
self.err = Some(err);
97+
self.path_stack.pop();
98+
return;
10399
}
104-
105100
}
106101
};
102+
107103
let collected = paths.collect::<Vec<_>>();
108104
log::info!("Path list reloaded {:#?}", collected);
109105

@@ -112,8 +108,11 @@ impl Files {
112108
self.path_names.clear();
113109

114110
for path in collected {
115-
self.path_names
116-
.push(path.unwrap().path().display().to_string());
111+
let file = path.unwrap();
112+
self.path_names.push(File {
113+
name: file.file_name().to_str().unwrap().to_string(),
114+
is_directory: file.file_type().unwrap().is_dir(),
115+
});
117116
}
118117
log::info!("path names are {:#?}", self.path_names);
119118
}
@@ -127,13 +126,14 @@ impl Files {
127126

128127
fn enter_dir(&mut self, dir_id: usize) {
129128
let path = &self.path_names[dir_id];
130-
self.path_stack.push(path.clone());
129+
self.path_stack.push(path.name.to_string());
131130
self.reload_path_list();
132131
}
133132

134-
fn current(&self) -> &str {
135-
self.path_stack.last().unwrap()
133+
fn current(&self) -> String {
134+
self.path_stack.join("/")
136135
}
136+
137137
fn clear_err(&mut self) {
138138
self.err = None;
139139
}

0 commit comments

Comments
 (0)