mirror of
https://github.com/kunkunsh/kunkun-ext-neohtop.git
synced 2025-04-11 17:29:45 +00:00
refresh rate select + play|pause button
This commit is contained in:
parent
d151579da5
commit
a8eb80f992
@ -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,
|
||||||
|
@ -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>
|
||||||
|
@ -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: "❓",
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user