Skip to content

Commit

Permalink
use reducer
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikmonsen committed Dec 18, 2024
1 parent 9d36a56 commit 2af74ee
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 82 deletions.
6 changes: 6 additions & 0 deletions src-tauri/capabilities/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
},
{
"path": "**/.thumbnails/**"
},
{
"path": "**/.previews"
},
{
"path": "**/.previews/**"
}
]
},
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/gen/schemas/capabilities.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"base":{"identifier":"base","description":"base permissions for the app","local":true,"windows":["main"],"permissions":["dialog:default","process:default","store:default","fs:default","fs:read-all",{"identifier":"fs:scope","allow":[{"path":"**"},{"path":"**/.thumbnails"},{"path":"**/.thumbnails/**"}]},"core:default","core:window:default","core:window:allow-show","core:window:allow-create","core:window:allow-close","core:window:allow-destroy","core:webview:default","core:webview:allow-create-webview","core:webview:allow-create-webview-window","core:webview:allow-get-all-webviews","core:webview:allow-internal-toggle-devtools","core:webview:allow-set-webview-focus","core:webview:allow-set-webview-position","core:webview:allow-set-webview-size","core:webview:allow-webview-close","core:webview:allow-webview-size","core:webview:allow-clear-all-browsing-data",{"identifier":"http:default","allow":[{"url":"http://localhost:8087/*"},{"url":"https://*.nb.no/*"}]},"store:default"]}}
{"base":{"identifier":"base","description":"base permissions for the app","local":true,"windows":["main"],"permissions":["dialog:default","process:default","store:default","fs:default","fs:read-all",{"identifier":"fs:scope","allow":[{"path":"**"},{"path":"**/.thumbnails"},{"path":"**/.thumbnails/**"},{"path":"**/.previews"},{"path":"**/.previews/**"}]},"core:default","core:window:default","core:window:allow-show","core:window:allow-create","core:window:allow-close","core:window:allow-destroy","core:webview:default","core:webview:allow-create-webview","core:webview:allow-create-webview-window","core:webview:allow-get-all-webviews","core:webview:allow-internal-toggle-devtools","core:webview:allow-set-webview-focus","core:webview:allow-set-webview-position","core:webview:allow-set-webview-size","core:webview:allow-webview-close","core:webview:allow-webview-size","core:webview:allow-clear-all-browsing-data",{"identifier":"http:default","allow":[{"url":"http://localhost:8087/*"},{"url":"https://*.nb.no/*"}]},"store:default"]}}
41 changes: 31 additions & 10 deletions src-tauri/src/image_converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use webp::{Encoder, WebPMemory};
use crate::error::ImageConversionError;

const THUMBNAIL_FOLDER_NAME: &str = ".thumbnails";
const PREVIEW_FOLDER_NAME: &str = ".previews";
const WEBP_EXTENSION: &str = "webp";
const WEBP_QUALITY: f32 = 25.0;

Expand All @@ -28,10 +29,10 @@ pub fn convert_directory_to_webp<P: AsRef<Path>>(
already_converted: 0,
};
for file in files {
if check_if_webp_exists(&file)? {
if check_if_preview_exists(&file)? {
count.already_converted += 1;
} else {
convert_to_webp(&file)?;
convert_to_webp(&file, false)?;
count.converted += 1;
}
}
Expand Down Expand Up @@ -59,17 +60,25 @@ fn directory_exists<P: AsRef<Path>>(path: P) -> bool {
.unwrap_or(false)
}

pub fn convert_to_webp<P: AsRef<Path>>(image_path: P) -> Result<PathBuf, ImageConversionError> {
pub fn convert_to_webp<P: AsRef<Path>>(image_path: P, high_res: bool) -> Result<PathBuf, ImageConversionError> {
let path_reference = image_path.as_ref();
let image: image::DynamicImage = ImageReader::open(path_reference)?
.with_guessed_format()?
.decode()?;

let image = image.resize(
image.width() / 8,
image.height() / 8,
image::imageops::FilterType::Nearest,
);
let image = if high_res {
image.resize(
image.width() / 4,
image.height() / 4,
image::imageops::FilterType::Nearest,
)
} else {
image.resize(
image.width() / 8,
image.height() / 8,
image::imageops::FilterType::Nearest,
)
};

let encoder: Encoder =
Encoder::from_image(&image).map_err(|e| ImageConversionError::StrError(e.to_string()))?;
Expand All @@ -79,7 +88,7 @@ pub fn convert_to_webp<P: AsRef<Path>>(image_path: P) -> Result<PathBuf, ImageCo
let filename_original_image = get_file_name(path_reference)?;

let mut path = parent_directory.to_owned();
path.push(THUMBNAIL_FOLDER_NAME);
path.push(if high_res { PREVIEW_FOLDER_NAME } else { THUMBNAIL_FOLDER_NAME });

if !directory_exists(&path) {
fs::create_dir_all(&path)?;
Expand All @@ -93,7 +102,7 @@ pub fn convert_to_webp<P: AsRef<Path>>(image_path: P) -> Result<PathBuf, ImageCo
Ok(path)
}

pub fn check_if_webp_exists<P: AsRef<Path>>(image_path: P) -> Result<bool, ImageConversionError> {
pub fn check_if_thumbnail_exists<P: AsRef<Path>>(image_path: P) -> Result<bool, ImageConversionError> {
let path_reference = image_path.as_ref();
let parent_directory = get_parent_directory(path_reference)?;
let filename_original_image = get_file_name(path_reference)?;
Expand All @@ -105,6 +114,18 @@ pub fn check_if_webp_exists<P: AsRef<Path>>(image_path: P) -> Result<bool, Image
Ok(path.exists())
}

pub fn check_if_preview_exists<P: AsRef<Path>>(image_path: P) -> Result<bool, ImageConversionError> {
let path_reference = image_path.as_ref();
let parent_directory = get_parent_directory(path_reference)?;
let filename_original_image = get_file_name(path_reference)?;

let mut path = parent_directory.to_owned();
path.push(PREVIEW_FOLDER_NAME);
path.push(filename_original_image);
path.set_extension(WEBP_EXTENSION);
Ok(path.exists())
}

fn get_parent_directory(path_reference: &Path) -> Result<&Path, ImageConversionError> {
path_reference.parent().ok_or_else(|| {
ImageConversionError::FailedToGetParentDirectoryError(format!(
Expand Down
28 changes: 24 additions & 4 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ async fn refresh_token(refresh_token: String) -> AuthenticationResponse {
}

#[tauri::command]
async fn convert_to_webp(file_path: String) -> Result<(), String> {
match image_converter::check_if_webp_exists(&file_path) {
async fn create_thumbnail_webp(file_path: String) -> Result<(), String> {
match image_converter::check_if_thumbnail_exists(&file_path) {
Ok(exists) => {
if exists {
return Ok(());
Expand All @@ -72,7 +72,26 @@ async fn convert_to_webp(file_path: String) -> Result<(), String> {
}
}

match image_converter::convert_to_webp(file_path) {
match image_converter::convert_to_webp(file_path, false) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}

#[tauri::command]
async fn create_preview_webp(file_path: String) -> Result<(), String> {
match image_converter::check_if_preview_exists(&file_path) {
Ok(exists) => {
if exists {
return Ok(());
}
}
Err(e) => {
e.to_string();
}
}

match image_converter::convert_to_webp(file_path, true) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
Expand Down Expand Up @@ -192,7 +211,8 @@ pub fn run() {
get_secret_variables,
log_in,
refresh_token,
convert_to_webp,
create_thumbnail_webp,
create_preview_webp,
convert_directory_to_webp,
delete_dir,
pick_directory,
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/tests/image_converter_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn test_convert_to_webp_creates_webp_of_original_in_thumbnails_directory() {
#[test]
fn test_check_if_webp_exists_returns_false_if_webp_doesnt_exist() {
setup_temp_dir(|tmp_img_path| {
let webp_exists = check_if_webp_exists(tmp_img_path).unwrap();
let webp_exists = check_if_preview_exists(tmp_img_path).unwrap();

assert!(!webp_exists);
});
Expand All @@ -44,7 +44,7 @@ fn test_check_if_webp_exists_returns_true_if_webp_exists() {
setup_temp_dir(|tmp_img_path| {
convert_to_webp(tmp_img_path.clone()).unwrap();

let webp_exists = check_if_webp_exists(tmp_img_path).unwrap();
let webp_exists = check_if_preview_exists(tmp_img_path).unwrap();

assert!(webp_exists);
});
Expand Down
25 changes: 19 additions & 6 deletions src/context/trokk-files-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import { invoke } from '@tauri-apps/api/core';
import { ConversionResult } from '../model/thumbnail';
import { documentDir, sep } from '@tauri-apps/api/path';

interface TrokkFilesState {
export interface TrokkFilesState {
basePath: string;
fileTrees: FileTree[];
treeIndex: Map<string, FileTree>;
current: FileTree | undefined;
preview: FileTree | undefined;
}

interface InitializeState {
Expand All @@ -40,13 +41,15 @@ type TrokkFilesAction =
| { type: 'SET_CURRENT'; payload: FileTree | undefined }
| { type: 'SET_CURRENT_AND_EXPAND_PARENTS'; payload: FileTree }
| { type: 'RESET' }
| { type: 'UPDATE_STORE' };
| { type: 'UPDATE_STORE' }
| { type: 'UPDATE_PREVIEW'; payload: FileTree | undefined };

const initialState: TrokkFilesState = {
basePath: await documentDir(),
fileTrees: [],
treeIndex: new Map<string, FileTree>(),
current: undefined
current: undefined,
preview: undefined
};

const TrokkFilesContext = createContext<{
Expand Down Expand Up @@ -75,7 +78,7 @@ const setCurrentAndExpandParents = (state: TrokkFilesState, fileTree: FileTree):
const newFileTrees = [...state.fileTrees];
updateFileTree(newFileTrees, fileTree);

return { ...state, fileTrees: newFileTrees, current: fileTree };
return { ...state, fileTrees: newFileTrees, current: fileTree, preview: undefined };
};

const createThumbnailsFromDirectory = async (directoryPath: string) => {
Expand All @@ -86,12 +89,19 @@ const createThumbnailsFromDirectory = async (directoryPath: string) => {
};

const createThumbnail = async (filePath: string) => {
invoke('convert_to_webp', { filePath: filePath })
invoke('create_thumbnail_webp', { filePath: filePath })
.catch((err) => {
console.error(err);
});
};

const createPreview = async (filePath: string) => {
invoke('create_preview_webp', { filePath: filePath, preview: true })
.catch((err) => {
console.error(err);
});
}

// Populate the map with existing tree nodes
const populateIndex = (fileTrees: FileTree[]): Map<string, FileTree> => {
const treeIndex = new Map<string, FileTree>();
Expand Down Expand Up @@ -327,7 +337,7 @@ const trokkFilesReducer = (state: TrokkFilesState, action: TrokkFilesAction): Tr
if (action.payload) {
void createThumbnailsFromDirectory(action.payload.path);
}
return { ...state, current: action.payload };
return { ...state, current: action.payload, preview: undefined };
}
case 'SET_CURRENT_AND_EXPAND_PARENTS': {
void createThumbnailsFromDirectory(action.payload.path);
Expand All @@ -337,6 +347,9 @@ const trokkFilesReducer = (state: TrokkFilesState, action: TrokkFilesAction): Tr
return initialState;
case 'UPDATE_STORE':
return { ...state };
case 'UPDATE_PREVIEW':
createPreview(action.payload?.path ?? '');
return { ...state, preview: action.payload };
default:
return state;
}
Expand Down
23 changes: 18 additions & 5 deletions src/features/detailed-image-view/detailed-image-view.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useEffect } from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { convertFileSrc } from '@tauri-apps/api/core';
import { FileTree } from '../../model/file-tree.ts';
import {useEffect} from 'react';
import {ChevronLeft, ChevronRight} from 'lucide-react';
import {FileTree} from '../../model/file-tree.ts';
import {getPreviewURIFromTree} from '../../util/file-utils.ts';
import {useTrokkFiles} from '../../context/trokk-files-context.tsx';

interface DetailedImageViewProps {
onClose: () => void;
Expand All @@ -11,6 +12,13 @@ interface DetailedImageViewProps {
}

export default function DetailedImageView({ onClose, images, currentIndex, setCurrentIndex }: DetailedImageViewProps) {
const {state, dispatch} = useTrokkFiles();

useEffect(() => {
const currentImage = images[currentIndex];
dispatch({ type: 'UPDATE_PREVIEW', payload: currentImage });
}, []);

const handleKeyPress = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
onClose();
Expand Down Expand Up @@ -40,6 +48,11 @@ export default function DetailedImageView({ onClose, images, currentIndex, setCu
};
}, [currentIndex, images]);

const getImageSrc = () => {
const image = images[currentIndex];
return getPreviewURIFromTree(image, state);
};

return (
<div className="relative">
<p className="text-center pt-4">Viser bilde {currentIndex + 1} av {images.length}</p>
Expand All @@ -57,7 +70,7 @@ export default function DetailedImageView({ onClose, images, currentIndex, setCu
>
x
</button>
<img src={convertFileSrc(images[currentIndex].path)} alt="Image in full size"
<img src={getImageSrc()} alt="Forhåndsvisning av bilde"
className="p-2.5 max-h-screen w-full object-contain" />
</div>
);
Expand Down
27 changes: 13 additions & 14 deletions src/features/files-container/files-container.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
import React, { useEffect, useState } from 'react';
import { convertFileSrc } from '@tauri-apps/api/core';
import { Folder } from 'lucide-react';
import { useTrokkFiles } from '../../context/trokk-files-context.tsx';
import React, {useState} from 'react';
import {Folder} from 'lucide-react';
import {useTrokkFiles} from '../../context/trokk-files-context.tsx';
import DetailedImageView from '../detailed-image-view/detailed-image-view.tsx';
import Thumbnail from '../thumbnail/thumbnail.tsx';

const FilesContainer: React.FC = () => {
const { state, dispatch } = useTrokkFiles();
const [selectedImgSrc, setSelectedImgSrc] = useState<string | undefined>(undefined);
const [currentIndex, setCurrentIndex] = useState<number>(0);

useEffect(() => {
setSelectedImgSrc(undefined);
}, [state.current]);

const files = state.current?.children?.filter(child => !child.isDirectory) || [];

const handleIndexChange = (index: number) => {
setCurrentIndex(index);
dispatch({ type: 'UPDATE_PREVIEW', payload: files[index] });
};

return (
<div className="flex flex-wrap overflow-y-auto h-[calc(96%)] justify-start content-start ml-4">
{state.current && state.current.children ? (
<>
{selectedImgSrc && (
{state.preview && (
<div className="w-full bg-gray-200 bg-opacity-25 dark:bg-gray-700 dark:bg-opacity-25">
<DetailedImageView
onClose={() => setSelectedImgSrc(undefined)}
onClose={() => dispatch({ type: 'UPDATE_PREVIEW', payload: undefined })}
images={files}
currentIndex={currentIndex}
setCurrentIndex={setCurrentIndex}
setCurrentIndex={handleIndexChange}
/>
</div>
)}
{state.current.children.length !== 0 ? (
state.current.children.map((child) => (
!child.name.startsWith('.thumbnails') && child.isDirectory ? (
!(child.name.startsWith('.thumbnails') || child.name.startsWith('.previews')) && child.isDirectory ? (
<button
key={child.path}
className="max-w-[150px]"
Expand All @@ -48,7 +47,7 @@ const FilesContainer: React.FC = () => {
<Thumbnail
key={child.name}
onClick={() => {
setSelectedImgSrc(convertFileSrc(child.path));
dispatch({ type: 'UPDATE_PREVIEW', payload: child });
setCurrentIndex(files.indexOf(child));
}}
fileTree={child}
Expand Down
Loading

0 comments on commit 2af74ee

Please sign in to comment.