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 tauri::State;
use std::sync::Mutex;
use std::time;
use std::collections::HashMap;
use std::time::Instant;
struct AppState {
sys: Mutex<System>,
process_cache: Mutex<HashMap<u32, ProcessStaticInfo>>,
last_update: Mutex<Instant>,
}
#[derive(Clone)]
@ -113,7 +110,6 @@ fn main() {
.manage(AppState {
sys: Mutex::new(System::new_all()),
process_cache: Mutex::new(HashMap::new()),
last_update: Mutex::new(Instant::now()),
})
.invoke_handler(tauri::generate_handler![
get_processes,

View File

@ -1,8 +1,6 @@
<script lang="ts">
import AppInfo from "./AppInfo.svelte";
import { statusMap } from "$lib/utils";
import Fa from "svelte-fa";
import { faFilter } from "@fortawesome/free-solid-svg-icons";
export let searchTerm: string;
export let statusFilter: string = "all";
@ -16,8 +14,10 @@
visible: 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;
const statusOptions = [
{ 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) {
if (page >= 1 && page <= totalPages) {
currentPage = page;
@ -139,6 +147,32 @@
{/if}
</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 />
</div>
</div>
@ -364,4 +398,49 @@
opacity: 0.5;
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>

View File

@ -20,51 +20,6 @@ export const statusMap: Record<string, ProcessStatus> = {
emoji: "⌛",
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": {
label: "Unknown",
emoji: "❓",

View File

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