Skip to content

Commit

Permalink
Merge pull request #59 from RickyDane/feature/duplicates
Browse files Browse the repository at this point in the history
Version 0.3.9 | find duplicates
  • Loading branch information
RickyDane committed Mar 2, 2024
2 parents b600308 + bd85122 commit e5d0b55
Show file tree
Hide file tree
Showing 10 changed files with 629 additions and 215 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
},
"name": "rdpfx",
"description": "[![publish](https://github.com/RickyDane/rdpFX/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/RickyDane/rdpFX/actions/workflows/main.yml)",
"version": "0.3.8",
"version": "0.3.9",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
Expand Down
12 changes: 11 additions & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "app"
version = "0.3.8"
version = "0.3.9"
description = "A simple file explorer"
authors = ["Ricky Dane Perlick"]
license = "none"
Expand Down Expand Up @@ -42,6 +42,7 @@ tauri-plugin-drag = "0.3.0"
walkdir = "2.4.0"
ini = "1.3.0"
window-shadows = "0.2.2"
substring = "1.4.5"
[target.'cfg(windows)'.dependencies]
winreg = "0.52"

Expand Down
Binary file modified src-tauri/icons/icon.icns
Binary file not shown.
130 changes: 108 additions & 22 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use std::io::{BufRead, BufReader, Read};
use std::{
env::{current_dir, set_current_dir},
fs::{copy, create_dir, remove_dir_all, remove_file, File},
path::PathBuf,
process::Command,
path::PathBuf
};
use stopwatch::Stopwatch;
use tauri::{
Expand All @@ -29,16 +28,19 @@ use unrar::Archive;
use zip_extensions::*;
mod utils;
use sysinfo::Disks;
use utils::{copy_to, count_entries, dbg_log, err_log, wng_log, COPY_COUNTER, TO_COPY_COUNTER};
use utils::{copy_to, count_entries, dbg_log, err_log, format_bytes, wng_log, DirWalker, DirWalkerEntry, COPY_COUNTER, TO_COPY_COUNTER};
#[allow(unused_imports)]
use rayon::prelude::*;
mod applications;
use applications::{open_file_with, get_apps};
use substring::Substring;

static mut HOSTNAME: String = String::new();
static mut USERNAME: String = String::new();
static mut PASSWORD: String = String::new();

static mut ISCANCELED: bool = false;

fn main() {
tauri::Builder::default()
.setup(|app| {
Expand Down Expand Up @@ -80,7 +82,9 @@ fn main() {
arr_delete_items,
arr_compress_items,
get_installed_apps,
open_with
open_with,
find_duplicates,
cancel_operation
])
.plugin(tauri_plugin_drag::init())
.run(tauri::generate_context!())
Expand Down Expand Up @@ -306,8 +310,8 @@ fn alert_not_found_dir(_x: std::io::Error) -> ReadDir {
}

#[tauri::command]
async fn open_dir(_path: String) -> Vec<FDir> {
let _ = set_current_dir(_path);
async fn open_dir(path: String) -> Vec<FDir> {
let _ = set_current_dir(&path);
return list_dirs().await;
}

Expand All @@ -330,7 +334,8 @@ async fn go_to_dir(directory: u8) -> Vec<FDir> {
};
if wanted_directory.is_err() {
err_log("Not a valid directory".into());
} else {
}
else {
dbg_log(format!("Current dir: {:?}", current_dir().unwrap()));
}
return list_dirs().await;
Expand Down Expand Up @@ -494,21 +499,9 @@ async fn get_current_connection() -> FtpStream {

#[tauri::command]
async fn open_in_terminal() {
#[cfg(target_os = "linux")]
// Open the terminal on linux
let _ = Command::new("gnome-terminal")
.arg(current_dir().unwrap())
.spawn();
#[cfg(target_os = "windows")]
// Open the terminal on windows
let _ = Command::new("cmd")
.arg("/c")
.arg("start")
.arg(current_dir().unwrap())
.spawn();
#[cfg(target_os = "macos")]
// Open the terminal on mac
let _ = Command::new("terminal").arg(current_dir().unwrap()).spawn();
// open terminal on macOS
// open terminal on linux
// open terminal on windows
}

#[tauri::command]
Expand Down Expand Up @@ -989,3 +982,96 @@ async fn get_installed_apps() -> Vec<(String, String)>{
async fn open_with(file_path: String, app_path: String) {
open_file_with(PathBuf::from(file_path), PathBuf::from(app_path));
}

#[tauri::command]
async fn find_duplicates(app_window: Window, path: String, depth: u32) -> Vec<Vec<DirWalkerEntry>> {
let files = DirWalker::new()
.depth(depth)
.run(&path)
.ext(vec![
"png", "jpg", "jpeg", "txt", "svg", "gif", "mp4", "mp3", "wav",
"pdf", "docx", "xlsx", "doc", "zip", "rar", "7z", "dmg", "iso",
"exe", "msi", "jar", "deb", "sh", "py", "htm", "html"
])
.get_items();
let mut seen_items: Vec<DirWalkerEntry> = Vec::new();
let mut duplicates: Vec<Vec<DirWalkerEntry>> = Vec::new();
for item in files.into_par_iter().collect::<Vec<DirWalkerEntry>>() {
let seen_item = seen_items.par_iter().find_any(|x| x.is_file == true && x.size == item.size && x.size > 0 && x.file_name.contains(&item.file_name.substring(0, item.file_name.len()-3)));
if *&seen_item.is_some() {
if duplicates.len() == 0 {
duplicates.push(vec![seen_item.unwrap().clone(), item.clone()]);
}
else {
let collection = duplicates.par_iter_mut().find_any(|x| x[0].size == seen_item.unwrap().size && x[0].size > 0 && x[0].file_name.contains(&item.file_name.substring(0, item.file_name.len()-3)));
if *&collection.is_some() {
collection.unwrap().push(item.clone());
}
else {
duplicates.push(vec![item.clone(), seen_item.unwrap().clone()]);
}
}
}
else {
seen_items.push(item);
}
}
for (idx, arr_duplicate) in duplicates.clone().iter().enumerate() {
let var_idx = &idx.clone().to_string();
let mut inner_html = String::new();
let mut js_query = String::new()+"
var duplicate"+var_idx+" = document.createElement('div');
duplicate"+var_idx+".setAttribute('itempaneside', '');
duplicate"+var_idx+".setAttribute('itemisdir', '0');
duplicate"+var_idx+".setAttribute('itemext', '');
duplicate"+var_idx+".setAttribute('isftp', '0');
duplicate"+var_idx+".className = 'list-item duplicate-item';
";
for (idx, item) in arr_duplicate.clone().iter().enumerate() {
inner_html.push_str(&(String::new()+"
<div style='display: flex; align-items: center; justify-content: space-between;'>
<div>
<h4>"+&item.file_name+"</h3>
<h4 class='text-2'>"+&item.path+"</h4>
<h4 class='text-2'>"+&format_bytes(item.size)+"</h4>
</div>
"));
if item.file_name.ends_with("jpg")
|| item.file_name.ends_with("jpeg")
|| item.file_name.ends_with("png")
|| item.file_name.ends_with("gif")
|| item.file_name.ends_with("svg")
|| item.file_name.ends_with("webp")
|| item.file_name.ends_with("jfif")
|| item.file_name.ends_with("tiff")
{
inner_html.push_str(&(String::new()+"
<img style='box-shadow: 0px 0px 10px 1px var(--transparentColorActive); border-radius: 5px;' width='64px' height='auto' src='asset://localhost/"+&item.path+"'>
</div>
"));
}
else {
inner_html.push_str(&(String::new()+"
</div>
"));
}
js_query.push_str(&(String::new()+"
duplicate"+var_idx+".setAttribute('"+&format!("itempath-{}", idx)+"', '"+&item.path+"');
"));
}
js_query.push_str(&(String::new()+"
duplicate"+var_idx+".innerHTML = `"+&inner_html+"`;
duplicate"+var_idx+".oncontextmenu = (e) => showExtraContextMenu(e, duplicate"+var_idx+");
document.querySelector('.duplicates-list').append(duplicate"+var_idx+");
"));
let _ = app_window.eval(&js_query);
}
duplicates
}

#[tauri::command]
async fn cancel_operation() {
unsafe {
ISCANCELED = true;
}
}
119 changes: 118 additions & 1 deletion src-tauri/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use std::{fs::{self, File}, io::{BufReader, BufWriter, Read, Write}};
use std::{fmt::Debug, fs::{self, File, Metadata}, io::{BufReader, BufWriter, Read, Write}};
use chrono::prelude::*;
use color_print::cprintln;
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator};
use serde::Serialize;
use stopwatch::Stopwatch;
use tauri::Window;

#[allow(unused_imports)]
use crate::ISCANCELED;

pub static mut COPY_COUNTER: f32 = 0.0;
pub static mut TO_COPY_COUNTER: f32 = 0.0;

Expand Down Expand Up @@ -113,3 +118,115 @@ pub fn update_progressbar_2(app_window: &Window, progress: f32, file_name: &str)
pub fn calc_transfer_speed(file_size: f64, time: f64) -> f64 {
(file_size / time) / 1024.0 / 1024.0
}

#[derive(Clone)]
#[derive(Debug)]
#[derive(Serialize)]
pub struct DirWalkerEntry {
pub file_name: String,
pub path: String,
pub depth: u32,
pub is_dir: bool,
pub is_file: bool,
pub size: u64
}

pub struct DirWalker {
pub items: Vec<DirWalkerEntry>,
pub depth: u32
}

impl DirWalker {
pub fn new() -> DirWalker {
DirWalker {
items: Vec::new(),
depth: 0
}
}

pub fn run(&mut self, path: &str) -> &mut Self {
self.walk(path, 0);
self
}

pub fn walk(&mut self, path: &str, depth: u32) {
if self.depth > 0 && depth > self.depth {
return;
}
for entry in fs::read_dir(path).unwrap() {
let item = entry.unwrap();
if item.file_name().to_str().unwrap().starts_with(".") {
continue;
}
let path = item.path();
if !fs::metadata(&path).is_ok() {
continue;
}
if path.is_dir() {
self.items.push(DirWalkerEntry {
file_name: item.file_name().to_str().unwrap().to_string(),
path: path.to_str().unwrap().to_string(),
depth: depth,
is_dir: true,
is_file: false,
size: 0
});
self.walk(path.to_str().unwrap(), depth + 1);
}
else {
self.items.push(DirWalkerEntry {
file_name: item.file_name().to_str().unwrap().to_string(),
path: path.to_str().unwrap().to_string(),
depth: depth,
is_dir: false,
is_file: true,
size: fs::metadata(&path).unwrap().len()
});
}
}
}

pub fn depth(&mut self, depth: u32) -> &mut Self {
self.depth = depth;
self
}

pub fn ext(&mut self, extensions: Vec<&str>) -> &mut Self {
self.items = self.items.clone().into_iter().filter(|item| {
for ext in &extensions {
if item.file_name.ends_with(ext) {
return true;
}
}
false
}).collect();
self
}

pub fn get_items(&self) -> Vec<DirWalkerEntry> {
(*self.items).to_vec()
}
}

pub fn format_bytes(bytes: u64) -> String {
let kb = bytes / 1024;
let mb = kb / 1024;
let gb = mb / 1024;
let tb = gb / 1024;

if tb > 0 {
format!("{:.2} TB", tb as f32)
}
else if gb > 0 {
format!("{:.2} GB", gb as f32)
}
else if mb > 0 {
format!("{:.2} MB", mb as f32)
}
else if kb > 0 {
format!("{:.2} KB", kb as f32)
}
else {
format!("{:.2} B", bytes as f32)
}
}
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"package": {
"productName": "rdpFX",
"version": "0.3.8"
"version": "0.3.9"
},
"tauri": {
"bundle": {
Expand Down

0 comments on commit e5d0b55

Please sign in to comment.