Skip to content

Commit

Permalink
Merge pull request #199 from kimlimjustin/feat/lnk
Browse files Browse the repository at this point in the history
feat: add support for `lnk` files
  • Loading branch information
kimlimjustin authored Dec 17, 2021
2 parents 0bd18e5 + 9852de2 commit c566774
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 28 deletions.
5 changes: 5 additions & 0 deletions lib/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -268,5 +268,10 @@
"type": "Yarn Package Manager",
"fileNames": [".yarnrc", "yarn.lock", ".yarnclean", ".yarn-integrity", "yarn-error.log", ".yarnrc.yml", ".yarnrc.yaml"],
"thumbnail": "extension/yarn.svg"
},
{
"extensions": ["lnk"],
"type": "Windows Shortcut",
"thumbnail": "extension/lnk.svg"
}
]
20 changes: 20 additions & 0 deletions src-tauri/Cargo.lock

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

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ lazy_static = "1.4.0"
font-loader = "0.11.0"
glob = "0.3.0"
tauri-plugin-vibrancy = { git = "https://github.com/amrbashir/tauri-plugin-vibrancy" }
parselnk = "0.1.0"

[dev-dependencies]
tokio = {version="1.14", features = ["full"] }
Expand Down
48 changes: 42 additions & 6 deletions src-tauri/src/files_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use glob::{glob_with, MatchOptions};
#[cfg(not(target_os = "macos"))]
use normpath::PathExt;
use notify::{raw_watcher, RawEvent, RecursiveMode, Watcher};
use parselnk::Lnk;
use std::convert::TryFrom;
use std::sync::mpsc::channel;
#[cfg(target_os = "windows")]
use tauri::api::path::local_data_dir;
Expand All @@ -20,7 +22,13 @@ use std::os::windows::prelude::*;
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;

#[derive(serde::Serialize, Clone)]
#[derive(serde::Serialize, Clone, Debug)]
pub struct LnkData {
file_path: String,
icon: String,
}

#[derive(serde::Serialize, Clone, Debug)]
pub struct FileMetaData {
file_path: String,
basename: String,
Expand Down Expand Up @@ -61,6 +69,7 @@ pub struct FolderInformation {
number_of_files: u16,
files: Vec<FileMetaData>,
skipped_files: Vec<String>,
lnk_files: Vec<LnkData>,
}

#[derive(serde::Serialize)]
Expand Down Expand Up @@ -242,26 +251,53 @@ pub async fn read_directory(dir: &Path) -> Result<FolderInformation, String> {
let mut number_of_files: u16 = 0;
let mut files = Vec::new();
let mut skipped_files = Vec::new();
let mut lnk_files: Vec<LnkData> = Vec::new();
for path in paths {
number_of_files += 1;
let file_name = path.unwrap().path().display().to_string();
let file_info = get_file_properties(file_name.clone()).await;
let file_path = path.unwrap().path().display().to_string();
let file_info = get_file_properties(file_path.clone()).await;
if file_info.is_err() {
skipped_files.push(file_name);
skipped_files.push(file_path);
continue;
} else {
let file_info = file_info.unwrap();
if hide_system_files && file_info.is_system {
skipped_files.push(file_name);
skipped_files.push(file_path);
continue;
}
files.push(file_info)
if file_info.file_type == "Windows Shortcut" {
let path = std::path::Path::new(&file_info.file_path);
let lnk = Lnk::try_from(path).unwrap();
let lnk_icon = lnk.string_data.icon_location;
let lnk_icon = match lnk_icon {
Some(icon) => {
let icon = icon.into_os_string().into_string().unwrap();
let icon_type = file_lib::get_type(icon.clone(), false).await;
if icon_type == "Image" {
icon
} else if icon_type == "Executable" {
extract_icon(icon).await.unwrap_or("".to_string())
} else {
"".to_string()
}
}
None => "".to_string(),
};
lnk_files.push(LnkData {
file_path: file_path,
icon: lnk_icon,
});
files.push(file_info)
} else {
files.push(file_info)
}
};
}
Ok(FolderInformation {
number_of_files,
files,
skipped_files,
lnk_files,
})
}

Expand Down
2 changes: 2 additions & 0 deletions src/Api/directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { invoke } from '@tauri-apps/api';
import type FileMetaData from '../Typings/fileMetaData';
import { getCurrent } from '@tauri-apps/api/window';
import { UnlistenFn } from '@tauri-apps/api/event';
import { LnkData } from '../Typings/fileMetaData';
let listener: UnlistenFn;
let searchListener: UnlistenFn;
interface DirectoryData {
files: FileMetaData[];
number_of_files: number;
skipped_files: string[];
lnk_files: LnkData[];
}
/**
* Invoke Rust command to read information of a directory
Expand Down
21 changes: 17 additions & 4 deletions src/Components/Open/displayFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { Select } from '../Files/File Operation/select';
import normalizeSlash from '../Functions/path/normalizeSlash';
import joinPath from '../Functions/path/joinPath';
import getDefaultSort from './defaultSort';
import { LnkData } from '../../Typings/fileMetaData';
/**
* Display files into Xplorer main section
* @param {fileData[]} files - array of files of a directory
* @param {string} dir - directory base path
* @param {HTMLElement} onElement - element to append files element
* @param {{reveal: boolean, revealDir: boolean}} options - options
* @param {boolean} isSearch - if true, files are searched
* @param {LnkData[]} lnk_files - array of lnk files
*
* @returns {Promise<HTMLElement>}
*/
Expand All @@ -21,7 +23,8 @@ const displayFiles = async (
dir: string,
onElement?: HTMLElement,
options?: { reveal: boolean; revealDir: string },
isSearch?: boolean
isSearch?: boolean,
lnk_files?: LnkData[]
): Promise<HTMLElement> => {
const FilesElement = onElement ?? document.createElement('div');
const preference = await Storage.get('preference');
Expand Down Expand Up @@ -76,8 +79,6 @@ const displayFiles = async (
const imageAsThumbnail =
(appearance?.imageAsThumbnail ?? 'smalldir') === 'smalldir' ? files.length < 100 : appearance?.imageAsThumbnail === 'yes';
for (const file of files) {
const fileType = file.file_type;
const preview = await fileThumbnail(file.file_path, file.is_dir ? 'folder' : 'file', true, imageAsThumbnail);
const fileGrid = document.createElement('div');
fileGrid.className = 'file-grid grid-hover-effect file';
let displayName: string;
Expand Down Expand Up @@ -114,6 +115,18 @@ const displayFiles = async (
fileGrid.dataset.isdir = String(file.is_dir);
if (file.time_deleted) fileGrid.dataset.trashDeletionDate = String(file.time_deleted);
if (file.is_trash) fileGrid.dataset.realPath = escape(joinPath(file.original_parent, file.basename));
let preview: string;
if (file.file_type === 'Windows Shortcut') {
fileGrid.dataset.isLnk = 'true';
for (const lnk of lnk_files) {
if (file.file_path === lnk.file_path) {
preview = await fileThumbnail(lnk.icon, 'file', true, true);
break;
}
}
} else {
preview = await fileThumbnail(file.file_path, file.is_dir ? 'folder' : 'file', true, imageAsThumbnail);
}

fileGrid.dataset.path = escape(normalizeSlash(file.file_path));
fileGrid.dataset.isSystem = String(file.is_system);
Expand All @@ -136,7 +149,7 @@ const displayFiles = async (
)}</span>`
: `<span class="file-size" id="file-size"></span>`
}
<span class="file-type">${fileType}</span>
<span class="file-type">${file.file_type}</span>
`;
FilesElement.appendChild(fileGrid);
}
Expand Down
42 changes: 24 additions & 18 deletions src/Components/Open/open.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,25 +108,31 @@ const OpenDir = async (dir: string, reveal?: boolean, forceOpen = false): Promis
stopLoading();
return;
}
directoryInfo.getFiles().then(async (files) => {
UpdateInfo('number-of-files', `${files.number_of_files - files.skipped_files.length} files`);
if (!files.files.length) {
MAIN_ELEMENT.classList.add('empty-dir-notification');
MAIN_ELEMENT.innerText = 'This folder is empty.';
stopLoading();
} else {
await displayFiles(files.files, dir, MAIN_ELEMENT, {
const files = await directoryInfo.getFiles();
UpdateInfo('number-of-files', `${files.number_of_files - files.skipped_files.length} files`);
if (!files.files.length) {
MAIN_ELEMENT.classList.add('empty-dir-notification');
MAIN_ELEMENT.innerText = 'This folder is empty.';
stopLoading();
} else {
await displayFiles(
files.files,
dir,
MAIN_ELEMENT,
{
reveal,
revealDir: normalizeSlash(dir),
});
stopLoading();
updateTheme('grid');
LOAD_IMAGE();
changeWindowTitle(getBasename(getDirname(dir)));
console.timeEnd(dir);
if (!isReload) directoryInfo.listen(() => reload());
}
});
},
null,
files.lnk_files
);
stopLoading();
updateTheme('grid');
LOAD_IMAGE();
changeWindowTitle(getBasename(getDirname(dir)));
console.timeEnd(dir);
if (!isReload) directoryInfo.listen(() => reload());
}
} else {
directoryInfo = new DirectoryAPI(dir);
if (!(await directoryInfo.exists())) {
Expand All @@ -141,7 +147,7 @@ const OpenDir = async (dir: string, reveal?: boolean, forceOpen = false): Promis
MAIN_ELEMENT.innerText = 'This folder is empty.';
stopLoading();
} else {
await displayFiles(files.files, dir, MAIN_ELEMENT);
await displayFiles(files.files, dir, MAIN_ELEMENT, null, null, files.lnk_files);
stopLoading();
updateTheme('grid');
LOAD_IMAGE();
Expand Down
1 change: 1 addition & 0 deletions src/Icon/extension/lnk.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/Typings/fileMetaData.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ interface FileMetaData {
last_accessed?: SystemTime;
created?: SystemTime;
}

export interface LnkData {
file_path: string;
icon: string;
}
export default FileMetaData;

1 comment on commit c566774

@vercel
Copy link

@vercel vercel bot commented on c566774 Dec 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.