Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ivangabriele committed Sep 15, 2024
1 parent 86ff329 commit 3fe2658
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 66 deletions.
5 changes: 5 additions & 0 deletions docs/contributors/tauri.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@
#### `path`

- `app_cache_dir()`:
- Linux: `~/.cache/com.clamav-desktop.app`
- Windows: `C:\Users\%USER%\AppData\Local\com.clamav-desktop.app`
- `app_config_dir()`:
- Linux: `~/.config/com.clamav-desktop.app`
- Windows: `C:\Users\%USER%\AppData\Roaming\com.clamav-desktop.app`
- `app_data_dir()`:
- Linux: `~/.local/share/com.clamav-desktop.app`
- Windows: `C:\Users\%USER%\AppData\Roaming\com.clamav-desktop.app`
- `app_local_data_dir()`:
- Linux: `~/.local/share/com.clamav-desktop.app`
- Windows: `C:\Users\%USER%\AppData\Local\com.clamav-desktop.app`
- `app_log_dir()`:
- Linux: `~/.config/com.clamav-desktop.app/logs`
- Windows: `C:\Users\%USER%\AppData\Roaming\com.clamav-desktop.app\logs`
1 change: 1 addition & 0 deletions src-tauri/src/libs/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use tokio::process::{Child, Command};
// }

#[cfg(not(tarpaulin_include))]
#[allow(dead_code)]
pub async fn run(binary_path: String, args: Vec<String>) -> Child {
Command::new(binary_path)
.args(args)
Expand Down
22 changes: 11 additions & 11 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ fn main() {
let config_binding = app_handle.config();
let config = config_binding.as_ref();

// let app_cache_dir = api::path::app_cache_dir(config).expect("Could not get cache directory.");
// println!("Cache directory: {:?}", app_cache_dir);
// let app_config_dir = api::path::app_config_dir(config).expect("Could not get config directory.");
// println!("Config directory: {:?}", app_config_dir);
// let app_data_dir = api::path::app_data_dir(config).expect("Could not get data directory.");
// println!("Data directory: {:?}", app_data_dir);
// let app_local_data_dir =
// api::path::app_local_data_dir(config).expect("Could not get local data directory.");
// println!("Local data directory: {:?}", app_local_data_dir);
// let app_log_dir = api::path::app_log_dir(config).expect("Could not get log directory.");
// println!("Log directory: {:?}", app_log_dir);
let app_cache_dir = api::path::app_cache_dir(config).expect("Could not get cache directory.");
println!("Cache directory: {:?}", app_cache_dir);
let app_config_dir = api::path::app_config_dir(config).expect("Could not get config directory.");
println!("Config directory: {:?}", app_config_dir);
let app_data_dir = api::path::app_data_dir(config).expect("Could not get data directory.");
println!("Data directory: {:?}", app_data_dir);
let app_local_data_dir =
api::path::app_local_data_dir(config).expect("Could not get local data directory.");
println!("Local data directory: {:?}", app_local_data_dir);
let app_log_dir = api::path::app_log_dir(config).expect("Could not get log directory.");
println!("Log directory: {:?}", app_log_dir);

let mut config_directory_path = globals::CONFIG_DIRECTORY_PATH.lock().await;
*config_directory_path =
Expand Down
45 changes: 24 additions & 21 deletions src-tauri/src/modules/scanner/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub async fn start_scanner(app_handle: AppHandle, paths: Vec<String>) -> Result<
let args: Vec<String> = vec![
// "clamscan".to_string(),
"-rv".to_string(),
format!("--database={}", "~/.local/share/com.clamav-desktop.app").to_string(),
"--follow-dir-symlinks=0".to_string(),
"--follow-file-symlinks=0".to_string(),
// "--gen-json=yes".to_string(),
Expand All @@ -52,6 +53,7 @@ pub async fn start_scanner(app_handle: AppHandle, paths: Vec<String>) -> Result<
.into_iter()
.chain(paths.to_owned().into_iter())
.collect();
println!("{:?}", args);

state::set_public_state(
&app_handle,
Expand Down Expand Up @@ -88,22 +90,6 @@ pub async fn start_scanner(app_handle: AppHandle, paths: Vec<String>) -> Result<
.spawn()
.expect("Failed to spawn sidecar");

// tauri::async_runtime::spawn(async move {
// // read events such as stdout
// while let Some(event) = rx.recv().await {
// if let CommandEvent::Stdout(line) = event {
// window
// .emit("message", Some(format!("'{}'", line)))
// .expect("failed to emit event");
// // write to stdin
// child.write("message from Rust\n".as_bytes()).unwrap();
// }
// }
// });

// let child = libs::cli::run(String::from("clamscan"), args).await;
// child.pid();

// Attach child ID to private state
let mut child_id_mutex_guard = app_handle
.state::<state::ScannerSharedState>()
Expand All @@ -125,17 +111,34 @@ pub async fn start_scanner(app_handle: AppHandle, paths: Vec<String>) -> Result<
.await;
*child_mutex_guard = Some(child);

let app_handle_clone_for_log = app_handle.clone();
// tokio::spawn(utils::handle_scanner_output(app_handle_clone_for_log, total_file_count));
let app_handle_traveller = app_handle.clone();
// tokio::spawn(utils::handle_scanner_output(app_handle_traveller, total_file_count));
tauri::async_runtime::spawn(async move {
let mut file_index: usize = 0;
while let Some(event) = rx.recv().await {
if let CommandEvent::Stdout(line) = event {
debug!("handle_scanner_output()", "Output: `{}`.", line);
if let CommandEvent::Stdout(ref line) = event {
#[cfg(debug_assertions)]
{
println!("[CommandEvent::Stdout] {}", line);
}

if utils::filter_log(line.to_owned()) {
let next_public_state = utils::get_status_from_log(line.to_owned(), file_index, total_file_count);
state::set_public_state(&app_handle_traveller, next_public_state).await;

file_index += 1;
}
}

if let CommandEvent::Stderr(ref line) = event {
#[cfg(debug_assertions)]
{
println!("[CommandEvent::Stderr] {}", line);
}

if utils::filter_log(line.to_owned()) {
let next_public_state = utils::get_status_from_log(line.to_owned(), file_index, total_file_count);
state::set_public_state(&app_handle_clone_for_log, next_public_state).await;
state::set_public_state(&app_handle_traveller, next_public_state).await;

file_index += 1;
}
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/modules/scanner/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct ScannerPublicState {
pub step: ScannerStatusStep,
}
impl ScannerPublicState {
#[allow(dead_code)]
pub fn patch(&mut self, patch: ScannerPublicStatePatch) {
if let Some(current_path) = patch.current_path {
self.current_path = current_path;
Expand Down Expand Up @@ -76,6 +77,7 @@ pub async fn broadcast_state(app_handle: &AppHandle) {
.unwrap();
}

#[allow(dead_code)]
pub async fn patch_public_state(app_handle: &AppHandle, patch: ScannerPublicStatePatch) {
let mut public_state_mutex_guard = app_handle.state::<ScannerSharedState>().inner().0.public.lock().await;

Expand Down
3 changes: 0 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useCoreStateHub } from '@libs/CoreStateHub/useCoreStateHub'
import { Dashboard } from '@screens/Dashboard'
import { LoaderScreen } from '@screens/Loader'
import { Scanner } from '@screens/Scanner'
Expand All @@ -12,8 +11,6 @@ export function App() {
const [isCoreReady, setIsCoreReady] = useState(true)
const [screen, setScreen] = useState<Screen>(Screen.Dashboard)

useCoreStateHub(isCoreReady)

const disableIsLoading = () => {
setIsCoreReady(false)
}
Expand Down
11 changes: 11 additions & 0 deletions src/core/Scanner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { invoke } from '@tauri-apps/api'

export const ScannerModule = {
startScanner: async (paths: string[]): Promise<void> => {
return await invoke<void>('start_scanner', { paths })
},

stopScanner: async (): Promise<void> => {
return await invoke<void>('stop_scanner')
},
}
22 changes: 18 additions & 4 deletions src/core/Scanner/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import type { Core } from '../types'

export namespace Scanner {
export interface State {
currently_scanned_file_path: string | undefined
module_status: Core.ModuleStatus
current_path: string | null
progress: number | null
step: ScannerStatusStep
}

export enum ScannerStatusStep {
/** Counting the files to scan. */
Counting = 'Counting',
/** Default step (= waiting for a new job). */
Idle = 'Idle',
/** Listing the files to scan. */
Listing = 'Listing',
/** Scanning the files. */
Running = 'Running',
/** Starting (= has called `clamscan` CLI command). */
Starting = 'Starting',
/** Stopping (= has called `clamscan` CLI command). */
Stopping = 'Stopping',
}
}
47 changes: 39 additions & 8 deletions src/libs/CoreStateHub/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
import { listen } from '@tauri-apps/api/event'
import { listen, type Event } from '@tauri-apps/api/event'
import type { Scanner } from '../../core/Scanner/types'
import { invoke } from '@tauri-apps/api'
import type { CoreStateListener, CoreStateStore, CoreStateStoreKey } from './types'

/**
* Listen to all Core states changes and keep track of them.
*/
export class CoreStateHub {
#scannerState: Scanner.State | undefined
#store: CoreStateStore

get scannerState() {
return this.#scannerState
constructor() {
this.#store = {
scanner: {
listeners: [],
state: undefined,
},
}

this.#init()
}

get store() {
return this.#store
}

addListener<K extends CoreStateStoreKey>(key: K, callback: CoreStateListener<K>) {
this.#store[key].listeners.push(callback)
}

removeListener<K extends CoreStateStoreKey>(key: K, callback: CoreStateListener<K>) {
this.#store[key].listeners = this.#store[key].listeners.filter(listener => listener !== callback)
}

#init() {
listen<Scanner.State>('scanner:state', this.#initScannerState.bind(this))

invoke('get_scanner_state')
}

init() {
listen<Scanner.State>('scanner:state', event => {
this.#scannerState = event.payload
})
#initScannerState(event: Event<Scanner.State>) {
this.#store.scanner.state = event.payload

for (const listener of this.#store.scanner.listeners) {
listener(event.payload)
}
}
}

export const coreStateHub = new CoreStateHub()
12 changes: 12 additions & 0 deletions src/libs/CoreStateHub/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Scanner } from '@core/Scanner/types'

export interface CoreStateStore {
scanner: {
listeners: Array<(nextState: Scanner.State) => void>
state: Scanner.State | undefined
}
}

export type CoreStateStoreKey = keyof CoreStateStore

export type CoreStateListener<K extends CoreStateStoreKey> = (nextState: CoreStateStore[K]['state']) => void
18 changes: 8 additions & 10 deletions src/libs/CoreStateHub/useCoreStateHub.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { useEffect, useRef } from 'react'
import { CoreStateHub } from '.'
import { useEffect, useState } from 'react'
import { coreStateHub } from '.'
import type { CoreStateStore, CoreStateStoreKey } from './types'

/**
* Hook to initialize the CoreStateHub once the Core is ready.
*/
export function useCoreStateHub(isCoreReady: boolean): void {
const coreStateHubRef = useRef<CoreStateHub | undefined>(undefined)
export function useCoreStateHub<K extends CoreStateStoreKey>(key: K): CoreStateStore[K]['state'] {
const [state, setState] = useState<CoreStateStore[K]['state']>(undefined)

useEffect(() => {
if (!isCoreReady || coreStateHubRef.current) {
return
}
coreStateHub.addListener<K>(key, setState)
}, [key])

coreStateHubRef.current = new CoreStateHub()
coreStateHubRef.current.init()
}, [isCoreReady])
return state
}
2 changes: 1 addition & 1 deletion src/screens/Dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function Dashboard() {
}, [])

useEffect(() => {
invoke('get_dashboard_state')
// invoke('get_dashboard_state')

listen<Core.DashboardState>('dashboard:state', event => {
setState(event.payload)
Expand Down
10 changes: 6 additions & 4 deletions src/screens/Scanner/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Card } from '@components/Card'
import type { CardAction } from '@components/Card/types'
import { FileExplorer } from '@components/FileExplorer'
import type { FileManager } from '@core/FileManager/types'
import type { Scanner } from '@core/Scanner/types'
import { Core } from '@core/types'
import { Scanner } from '@core/Scanner/types'
import { ScanningSpinner } from '@elements/ScanningSpinner'
import { ScreenBox } from '@layouts/ScreenBox'
import { MdClose, MdVerifiedUser } from 'react-icons/md'
Expand All @@ -28,7 +27,10 @@ export function ScannerScreenComponent({
onScanStop,
scannerState,
}: ScannerScreenComponentProps) {
if (scannerState?.module_status === Core.ModuleStatus.Running) {
if (
scannerState &&
[Scanner.ScannerStatusStep.Counting, Scanner.ScannerStatusStep.Running].includes(scannerState.step)
) {
return (
<ScreenBox isCentered>
<ScanningCancelButton onClick={onScanStop}>
Expand All @@ -37,7 +39,7 @@ export function ScannerScreenComponent({

<ScanningSpinner size={128} />
<ScanningStepText>Scanning files...</ScanningStepText>
<ScanningTargetText>{scannerState.currently_scanned_file_path}</ScanningTargetText>
<ScanningTargetText>{scannerState.current_path}</ScanningTargetText>
</ScreenBox>
)
}
Expand Down
19 changes: 15 additions & 4 deletions src/screens/Scanner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { FileManagerModule } from '@core/FileManager'
import type { FileManager } from '@core/FileManager/types'
import { noop } from '@utils/noop'
import { useCallback, useEffect, useState } from 'react'
import { ScannerScreenComponent } from './Component'
import { ScannerModule } from '@core/Scanner'
import { useCoreStateHub } from '@libs/CoreStateHub/useCoreStateHub'

export function Scanner() {
const scannerState = useCoreStateHub('scanner')

const [fileExplorerRootFilePaths, setFileExplorerRootFilePaths] = useState<FileManager.FilePath[] | undefined>(
undefined,
)
Expand All @@ -20,6 +23,14 @@ export function Scanner() {
setFileExplorerRootFilePaths(coreFilePaths)
}, [getDirectoryFilePaths])

const startScanner = useCallback(() => {
ScannerModule.startScanner(fileExplorerSelectedPaths)
}, [fileExplorerSelectedPaths])

const stopScanner = useCallback(() => {
ScannerModule.stopScanner()
}, [])

useEffect(() => {
initialize()
}, [initialize])
Expand All @@ -30,9 +41,9 @@ export function Scanner() {
fileExplorerRootPaths={fileExplorerRootFilePaths}
onFileExporerChange={setFileExplorerSelectedPaths}
onFileExporerExpand={getDirectoryFilePaths}
onScanStart={noop}
onScanStop={noop}
scannerState={undefined}
onScanStart={startScanner}
onScanStop={stopScanner}
scannerState={scannerState}
/>
)
}

0 comments on commit 3fe2658

Please sign in to comment.