refresh rate select + play|pause button

This commit is contained in:
Abdenasser 2024-11-05 00:27:31 +01:00
parent d151579da5
commit a8eb80f992
4 changed files with 96 additions and 58 deletions

View File

@ -3,14 +3,11 @@
use sysinfo::{CpuExt, SystemExt, ProcessExt, System, PidExt, ProcessStatus}; use sysinfo::{CpuExt, SystemExt, ProcessExt, System, PidExt, ProcessStatus};
use tauri::State; use tauri::State;
use std::sync::Mutex; use std::sync::Mutex;
use std::time;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::Instant;
struct AppState { struct AppState {
sys: Mutex<System>, sys: Mutex<System>,
process_cache: Mutex<HashMap<u32, ProcessStaticInfo>>, process_cache: Mutex<HashMap<u32, ProcessStaticInfo>>,
last_update: Mutex<Instant>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -113,7 +110,6 @@ fn main() {
.manage(AppState { .manage(AppState {
sys: Mutex::new(System::new_all()), sys: Mutex::new(System::new_all()),
process_cache: Mutex::new(HashMap::new()), process_cache: Mutex::new(HashMap::new()),
last_update: Mutex::new(Instant::now()),
}) })
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
get_processes, get_processes,

View File

@ -1,8 +1,6 @@
<script lang="ts"> <script lang="ts">
import AppInfo from "./AppInfo.svelte"; import AppInfo from "./AppInfo.svelte";
import { statusMap } from "$lib/utils"; import { statusMap } from "$lib/utils";
import Fa from "svelte-fa";
import { faFilter } from "@fortawesome/free-solid-svg-icons";
export let searchTerm: string; export let searchTerm: string;
export let statusFilter: string = "all"; export let statusFilter: string = "all";
@ -16,8 +14,10 @@
visible: boolean; visible: boolean;
required?: boolean; required?: boolean;
}>; }>;
export let refreshRate: number;
export let isFrozen: boolean;
const itemsPerPageOptions = [25, 50, 100, 250, 500]; const itemsPerPageOptions = [15, 25, 50, 100, 250, 500];
let showColumnMenu = false; let showColumnMenu = false;
const statusOptions = [ const statusOptions = [
{ value: "all", label: "All Statuses" }, { value: "all", label: "All Statuses" },
@ -27,6 +27,14 @@
})), })),
]; ];
const refreshRateOptions = [
{ value: 1000, label: "1s" },
{ value: 2000, label: "2s" },
{ value: 5000, label: "5s" },
{ value: 10000, label: "10s" },
{ value: 30000, label: "30s" },
];
function changePage(page: number) { function changePage(page: number) {
if (page >= 1 && page <= totalPages) { if (page >= 1 && page <= totalPages) {
currentPage = page; currentPage = page;
@ -139,6 +147,32 @@
{/if} {/if}
</div> </div>
<div class="toolbar-group">
<div class="refresh-controls">
<select
class="select-input"
bind:value={refreshRate}
disabled={isFrozen}
>
{#each refreshRateOptions as option}
<option value={option.value}>{option.label} refresh</option>
{/each}
</select>
<button
class="btn-action"
class:frozen={isFrozen}
on:click={() => (isFrozen = !isFrozen)}
title={isFrozen ? "Resume Updates" : "Pause Updates"}
>
{#if isFrozen}
{:else}
{/if}
</button>
</div>
</div>
<AppInfo /> <AppInfo />
</div> </div>
</div> </div>
@ -364,4 +398,49 @@
opacity: 0.5; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;
} }
.refresh-controls {
display: flex;
gap: 8px;
align-items: center;
}
.btn-action {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border: none;
background: var(--surface0);
color: var(--text);
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-action:hover {
background: var(--surface1);
}
.btn-action.frozen {
background: var(--blue);
color: var(--base);
}
.select-input {
height: 28px;
padding: 0 8px;
border: 1px solid var(--surface1);
border-radius: 6px;
background: var(--surface0);
color: var(--text);
font-size: 13px;
cursor: pointer;
}
.select-input:disabled {
opacity: 0.7;
cursor: not-allowed;
}
</style> </style>

View File

@ -20,51 +20,6 @@ export const statusMap: Record<string, ProcessStatus> = {
emoji: "⌛", emoji: "⌛",
color: "var(--overlay0)", color: "var(--overlay0)",
}, },
"Stopped": {
label: "Stopped",
emoji: "🛑",
color: "var(--red)",
},
"Zombie": {
label: "Zombie",
emoji: "🧟",
color: "var(--red)",
},
"Tracing": {
label: "Tracing",
emoji: "🔍",
color: "var(--yellow)",
},
"Dead": {
label: "Dead",
emoji: "💀",
color: "var(--red)",
},
"Wakekill": {
label: "Wake Kill",
emoji: "🔪",
color: "var(--red)",
},
"Waking": {
label: "Waking",
emoji: "🔄",
color: "var(--yellow)",
},
"Parked": {
label: "Parked",
emoji: "🫥",
color: "var(--overlay0)",
},
"LockBlocked": {
label: "Lock Blocked",
emoji: "🔒",
color: "var(--red)",
},
"UninterruptibleDiskSleep": {
label: "Disk Sleep",
emoji: "💤",
color: "var(--overlay0)",
},
"Unknown": { "Unknown": {
label: "Unknown", label: "Unknown",
emoji: "❓", emoji: "❓",

View File

@ -17,7 +17,7 @@
let searchTerm = ""; let searchTerm = "";
let isLoading = true; let isLoading = true;
let currentPage = 1; let currentPage = 1;
let itemsPerPage = 50; let itemsPerPage = 15;
let pinnedProcesses: Set<number> = new Set(); let pinnedProcesses: Set<number> = new Set();
let selectedProcess: Process | null = null; let selectedProcess: Process | null = null;
let showInfoModal = false; let showInfoModal = false;
@ -25,6 +25,8 @@
let processToKill: Process | null = null; let processToKill: Process | null = null;
let isKilling = false; let isKilling = false;
let statusFilter = "all"; let statusFilter = "all";
let refreshRate = 5000;
let isFrozen = false;
let columns: Column[] = [ let columns: Column[] = [
{ id: "name", label: "Process Name", visible: true, required: true }, { id: "name", label: "Process Name", visible: true, required: true },
@ -48,7 +50,6 @@
visible: true, visible: true,
format: (v) => (v / (1024 * 1024)).toFixed(1) + " MB", format: (v) => (v / (1024 * 1024)).toFixed(1) + " MB",
}, },
{ id: "threads", label: "Threads", visible: false },
{ id: "command", label: "Command", visible: false }, { id: "command", label: "Command", visible: false },
{ id: "ppid", label: "Parent PID", visible: false }, { id: "ppid", label: "Parent PID", visible: false },
]; ];
@ -100,6 +101,15 @@
} }
} }
$: {
if (intervalId) clearInterval(intervalId);
if (!isFrozen) {
intervalId = setInterval(() => {
getProcesses();
}, refreshRate);
}
}
async function getProcesses() { async function getProcesses() {
try { try {
const result = await invoke<[Process[], SystemStats]>("get_processes"); const result = await invoke<[Process[], SystemStats]>("get_processes");
@ -178,10 +188,6 @@
isLoading = false; isLoading = false;
} }
intervalId = setInterval(() => {
getProcesses();
}, 2000);
themeStore.init(); themeStore.init();
}); });
@ -208,6 +214,8 @@
bind:statusFilter bind:statusFilter
bind:itemsPerPage bind:itemsPerPage
bind:currentPage bind:currentPage
bind:refreshRate
bind:isFrozen
{totalPages} {totalPages}
totalResults={filteredProcesses.length} totalResults={filteredProcesses.length}
bind:columns bind:columns