mirror of
https://github.com/kunkunsh/kunkun-ext-neohtop.git
synced 2025-04-11 17:29:45 +00:00
cleaning up the mess
This commit is contained in:
parent
7858f8b1e1
commit
9c6658e13b
23
package-lock.json
generated
23
package-lock.json
generated
@ -10,11 +10,9 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.6.0",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.6.0",
|
"@fortawesome/free-solid-svg-icons": "^6.6.0",
|
||||||
"@tauri-apps/api": "^2.0.3",
|
"@tauri-apps/api": "^2.0.3",
|
||||||
"@tauri-apps/plugin-shell": "^2",
|
"@tauri-apps/plugin-shell": "^2",
|
||||||
"lucide-svelte": "^0.454.0",
|
|
||||||
"svelte-fa": "^4.0.3"
|
"svelte-fa": "^4.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -453,18 +451,6 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fortawesome/free-regular-svg-icons": {
|
|
||||||
"version": "6.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.6.0.tgz",
|
|
||||||
"integrity": "sha512-Yv9hDzL4aI73BEwSEh20clrY8q/uLxawaQ98lekBx6t9dQKDHcDzzV1p2YtBGTtolYtNqcWdniOnhzB+JPnQEQ==",
|
|
||||||
"license": "(CC-BY-4.0 AND MIT)",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.6.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/free-solid-svg-icons": {
|
"node_modules/@fortawesome/free-solid-svg-icons": {
|
||||||
"version": "6.6.0",
|
"version": "6.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz",
|
||||||
@ -1333,15 +1319,6 @@
|
|||||||
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
|
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lucide-svelte": {
|
|
||||||
"version": "0.454.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.454.0.tgz",
|
|
||||||
"integrity": "sha512-TgW17HI7M8LeFZ3NpaDp1LwPGBGMVjx/x81TtK+AacEQvmJcqetqeJNeBT18NMEJP9+zi/Wt+Zc8mo44K5Uszw==",
|
|
||||||
"license": "ISC",
|
|
||||||
"peerDependencies": {
|
|
||||||
"svelte": "^3 || ^4 || ^5.0.0-next.42"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.12",
|
"version": "0.30.12",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
|
||||||
|
@ -14,11 +14,9 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.6.0",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.6.0",
|
"@fortawesome/free-solid-svg-icons": "^6.6.0",
|
||||||
"@tauri-apps/api": "^2.0.3",
|
"@tauri-apps/api": "^2.0.3",
|
||||||
"@tauri-apps/plugin-shell": "^2",
|
"@tauri-apps/plugin-shell": "^2",
|
||||||
"lucide-svelte": "^0.454.0",
|
|
||||||
"svelte-fa": "^4.0.3"
|
"svelte-fa": "^4.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -105,50 +105,6 @@ async fn kill_process(pid: u32, state: State<'_, AppState>) -> Result<bool, Stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn process_stop(pid: u32, state: State<'_, AppState>) -> Result<bool, String> {
|
|
||||||
let sys = state.sys.lock().map_err(|_| "Failed to lock system state")?;
|
|
||||||
if let Some(_process) = sys.process(sysinfo::Pid::from(pid as usize)) {
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
{
|
|
||||||
use std::process::Command;
|
|
||||||
Command::new("kill")
|
|
||||||
.args(["-STOP", &pid.to_string()])
|
|
||||||
.status()
|
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
|
||||||
{
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn process_continue(pid: u32, state: State<'_, AppState>) -> Result<bool, String> {
|
|
||||||
let sys = state.sys.lock().map_err(|_| "Failed to lock system state")?;
|
|
||||||
if let Some(_process) = sys.process(sysinfo::Pid::from(pid as usize)) {
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
{
|
|
||||||
use std::process::Command;
|
|
||||||
Command::new("kill")
|
|
||||||
.args(["-CONT", &pid.to_string()])
|
|
||||||
.status()
|
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
|
||||||
{
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.manage(AppState {
|
.manage(AppState {
|
||||||
@ -157,9 +113,7 @@ fn main() {
|
|||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
get_processes,
|
get_processes,
|
||||||
get_system_stats,
|
get_system_stats,
|
||||||
kill_process,
|
kill_process
|
||||||
process_stop,
|
|
||||||
process_continue
|
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
1832
src/App.svelte
1832
src/App.svelte
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if showInfo}
|
{#if showInfo}
|
||||||
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<div class="info-panel" on:mouseleave={() => (showInfo = false)}>
|
<div class="info-panel" on:mouseleave={() => (showInfo = false)}>
|
||||||
<div class="info-content">
|
<div class="info-content">
|
||||||
<pre class="ascii-art">{ASCII_ART}</pre>
|
<pre class="ascii-art">{ASCII_ART}</pre>
|
||||||
@ -162,28 +163,8 @@
|
|||||||
color: var(--text);
|
color: var(--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.link {
|
|
||||||
color: var(--blue);
|
|
||||||
text-decoration: none;
|
|
||||||
transition: color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link:hover {
|
|
||||||
color: var(--sky);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-row span {
|
.detail-row span {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--blue);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button class="btn-danger" on:click={onConfirm} disabled={isKilling}>
|
<button class="btn-danger" on:click={onConfirm} disabled={isKilling}>
|
||||||
{#if isKilling}
|
{#if isKilling}
|
||||||
<div class="spinner" />
|
<div class="spinner"></div>
|
||||||
<span>Ending...</span>
|
<span>Ending...</span>
|
||||||
{:else}
|
{:else}
|
||||||
End Process
|
End Process
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if show}
|
{#if show}
|
||||||
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<div class="modal-backdrop" on:click={onClose}>
|
<div class="modal-backdrop" on:click={onClose}>
|
||||||
<div class="modal" on:click|stopPropagation style="--max-width: {maxWidth}">
|
<div class="modal" on:click|stopPropagation style="--max-width: {maxWidth}">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -1,18 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Modal from "./Modal.svelte";
|
import Modal from "./Modal.svelte";
|
||||||
import { formatStatus } from "$lib/utils/processStatus";
|
import { formatStatus } from "$lib/utils";
|
||||||
|
import type { Process } from "$lib/types";
|
||||||
interface Process {
|
|
||||||
pid: number;
|
|
||||||
ppid: number;
|
|
||||||
name: string;
|
|
||||||
cpu_usage: number;
|
|
||||||
memory_usage: number;
|
|
||||||
status: string;
|
|
||||||
user: string;
|
|
||||||
command: string;
|
|
||||||
threads?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export let show = false;
|
export let show = false;
|
||||||
export let process: Process | null = null;
|
export let process: Process | null = null;
|
||||||
|
@ -5,33 +5,7 @@
|
|||||||
faXmark,
|
faXmark,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import Fa from "svelte-fa";
|
import Fa from "svelte-fa";
|
||||||
|
import type { Process, Column } from "$lib/types";
|
||||||
interface Process {
|
|
||||||
pid: number;
|
|
||||||
ppid: number;
|
|
||||||
name: string;
|
|
||||||
cpu_usage: number;
|
|
||||||
memory_usage: number;
|
|
||||||
status:
|
|
||||||
| "Running"
|
|
||||||
| "Sleeping"
|
|
||||||
| "Idle"
|
|
||||||
| "Zombie"
|
|
||||||
| "Unknown"
|
|
||||||
| "Stop"
|
|
||||||
| string;
|
|
||||||
user: string;
|
|
||||||
command: string;
|
|
||||||
threads?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Column {
|
|
||||||
id: keyof Process;
|
|
||||||
label: string;
|
|
||||||
visible: boolean;
|
|
||||||
required?: boolean;
|
|
||||||
format?: (value: any) => string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export let processes: Process[];
|
export let processes: Process[];
|
||||||
export let columns: Column[];
|
export let columns: Column[];
|
||||||
|
@ -5,53 +5,19 @@
|
|||||||
faMemory,
|
faMemory,
|
||||||
faServer,
|
faServer,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import type { SystemStats } from "$lib/types";
|
||||||
interface SystemStats {
|
import {
|
||||||
cpu_usage: number[];
|
formatUptime,
|
||||||
memory_total: number;
|
formatMemorySize,
|
||||||
memory_used: number;
|
formatPercentage,
|
||||||
memory_free: number;
|
getUsageClass,
|
||||||
memory_cached: number;
|
} from "$lib/utils";
|
||||||
uptime: number;
|
|
||||||
load_avg: [number, number, number];
|
|
||||||
}
|
|
||||||
|
|
||||||
export let systemStats: SystemStats | null = null;
|
export let systemStats: SystemStats | null = null;
|
||||||
|
|
||||||
function formatUptime(seconds: number): string {
|
|
||||||
const days = Math.floor(seconds / 86400);
|
|
||||||
const hours = Math.floor((seconds % 86400) / 3600);
|
|
||||||
const minutes = Math.floor((seconds % 3600) / 60);
|
|
||||||
return `${days}d ${hours}h ${minutes}m`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatMemorySize(bytes: number): string {
|
|
||||||
const gb = bytes / (1024 * 1024 * 1024);
|
|
||||||
return `${gb.toFixed(1)} GB`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatMemoryPercentage(): string {
|
|
||||||
if (!systemStats) return "0%";
|
|
||||||
return (
|
|
||||||
((systemStats.memory_used / systemStats.memory_total) * 100).toFixed(1) +
|
|
||||||
"%"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUsageClass(percentage: number): string {
|
|
||||||
if (percentage >= 90) return "critical";
|
|
||||||
if (percentage >= 60) return "high";
|
|
||||||
if (percentage >= 30) return "medium";
|
|
||||||
return "low";
|
|
||||||
}
|
|
||||||
|
|
||||||
$: memoryPercentage = systemStats
|
$: memoryPercentage = systemStats
|
||||||
? (systemStats.memory_used / systemStats.memory_total) * 100
|
? (systemStats.memory_used / systemStats.memory_total) * 100
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
function formatPercentage(value: number): string {
|
|
||||||
return `${value.toFixed(1)}%`;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="stats-bar">
|
<div class="stats-bar">
|
||||||
@ -109,11 +75,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="memory-row">
|
<div class="memory-row">
|
||||||
<span>Free:</span>
|
<span>Free:</span>
|
||||||
<span
|
<span>{formatMemorySize(systemStats.memory_free)}</span>
|
||||||
>{formatMemorySize(
|
</div>
|
||||||
systemStats.memory_total - systemStats.memory_used,
|
<div class="memory-row">
|
||||||
)}</span
|
<span>Cached:</span>
|
||||||
>
|
<span>{formatMemorySize(systemStats.memory_cached)}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { themeStore } from "$lib/stores/theme";
|
import { themeStore } from "$lib/stores";
|
||||||
import { themes } from "$lib/styles/themes";
|
import { themes } from "$lib/styles";
|
||||||
import { fade } from "svelte/transition";
|
import { fade } from "svelte/transition";
|
||||||
|
|
||||||
let showMenu = false;
|
let showMenu = false;
|
||||||
@ -33,12 +33,18 @@
|
|||||||
>
|
>
|
||||||
<div class="current-theme">
|
<div class="current-theme">
|
||||||
<div class="theme-preview" style:background={$themeStore.colors.base}>
|
<div class="theme-preview" style:background={$themeStore.colors.base}>
|
||||||
<div class="preview-color" style:background={$themeStore.colors.blue} />
|
<div
|
||||||
<div class="preview-color" style:background={$themeStore.colors.red} />
|
class="preview-color"
|
||||||
|
style:background={$themeStore.colors.blue}
|
||||||
|
></div>
|
||||||
|
<div
|
||||||
|
class="preview-color"
|
||||||
|
style:background={$themeStore.colors.red}
|
||||||
|
></div>
|
||||||
<div
|
<div
|
||||||
class="preview-color"
|
class="preview-color"
|
||||||
style:background={$themeStore.colors.green}
|
style:background={$themeStore.colors.green}
|
||||||
/>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
{$themeStore.label}
|
{$themeStore.label}
|
||||||
</div>
|
</div>
|
||||||
@ -46,6 +52,8 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if showMenu}
|
{#if showMenu}
|
||||||
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
|
<!-- svelte-ignore element_invalid_self_closing_tag -->
|
||||||
<div
|
<div
|
||||||
class="theme-menu"
|
class="theme-menu"
|
||||||
transition:fade={{ duration: 100 }}
|
transition:fade={{ duration: 100 }}
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="toolbar-spacer" />
|
<div class="toolbar-spacer"></div>
|
||||||
|
|
||||||
<div class="pagination-controls">
|
<div class="pagination-controls">
|
||||||
<select
|
<select
|
||||||
@ -104,6 +104,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if showColumnMenu}
|
{#if showColumnMenu}
|
||||||
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<div class="column-menu" on:mouseleave={() => (showColumnMenu = false)}>
|
<div class="column-menu" on:mouseleave={() => (showColumnMenu = false)}>
|
||||||
{#each columns as column}
|
{#each columns as column}
|
||||||
<label class="column-option">
|
<label class="column-option">
|
||||||
@ -119,8 +120,6 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="toolbar-spacer" /> -->
|
|
||||||
|
|
||||||
<AppInfo />
|
<AppInfo />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
import { themes, type Theme } from '$lib/styles';
|
||||||
|
|
||||||
|
function createThemeStore() {
|
||||||
|
// Get initial theme from localStorage or default to catppuccin
|
||||||
|
const storedTheme = typeof window !== 'undefined'
|
||||||
|
? localStorage.getItem('theme')
|
||||||
|
: 'catppuccin';
|
||||||
|
|
||||||
|
const { subscribe, set } = writable<Theme>(themes[storedTheme || 'catppuccin']);
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
setTheme: (themeName: string) => {
|
||||||
|
const theme = themes[themeName];
|
||||||
|
if (theme) {
|
||||||
|
localStorage.setItem('theme', themeName);
|
||||||
|
set(theme);
|
||||||
|
applyTheme(theme);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
init: () => {
|
||||||
|
const theme = themes[storedTheme || 'catppuccin'];
|
||||||
|
applyTheme(theme);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTheme(theme: Theme) {
|
||||||
|
const root = document.documentElement;
|
||||||
|
Object.entries(theme.colors).forEach(([key, value]) => {
|
||||||
|
root.style.setProperty(`--${key}`, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const themeStore = createThemeStore();
|
@ -1,36 +0,0 @@
|
|||||||
import { writable } from 'svelte/store';
|
|
||||||
import { themes, type Theme } from '$lib/styles/themes';
|
|
||||||
|
|
||||||
function createThemeStore() {
|
|
||||||
// Get initial theme from localStorage or default to catppuccin
|
|
||||||
const storedTheme = typeof window !== 'undefined'
|
|
||||||
? localStorage.getItem('theme')
|
|
||||||
: 'catppuccin';
|
|
||||||
|
|
||||||
const { subscribe, set } = writable<Theme>(themes[storedTheme || 'catppuccin']);
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe,
|
|
||||||
setTheme: (themeName: string) => {
|
|
||||||
const theme = themes[themeName];
|
|
||||||
if (theme) {
|
|
||||||
localStorage.setItem('theme', themeName);
|
|
||||||
set(theme);
|
|
||||||
applyTheme(theme);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
init: () => {
|
|
||||||
const theme = themes[storedTheme || 'catppuccin'];
|
|
||||||
applyTheme(theme);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyTheme(theme: Theme) {
|
|
||||||
const root = document.documentElement;
|
|
||||||
Object.entries(theme.colors).forEach(([key, value]) => {
|
|
||||||
root.style.setProperty(`--${key}`, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const themeStore = createThemeStore();
|
|
@ -0,0 +1,30 @@
|
|||||||
|
// Create a new types file to centralize interfaces
|
||||||
|
export interface Process {
|
||||||
|
pid: number;
|
||||||
|
ppid: number;
|
||||||
|
name: string;
|
||||||
|
cpu_usage: number;
|
||||||
|
memory_usage: number;
|
||||||
|
status: string;
|
||||||
|
user: string;
|
||||||
|
command: string;
|
||||||
|
threads?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SystemStats {
|
||||||
|
cpu_usage: number[];
|
||||||
|
memory_total: number;
|
||||||
|
memory_used: number;
|
||||||
|
memory_free: number;
|
||||||
|
memory_cached: number;
|
||||||
|
uptime: number;
|
||||||
|
load_avg: [number, number, number];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Column {
|
||||||
|
id: keyof Process;
|
||||||
|
label: string;
|
||||||
|
visible: boolean;
|
||||||
|
required?: boolean;
|
||||||
|
format?: (value: any) => string;
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
export interface ProcessStatus {
|
||||||
|
label: string;
|
||||||
|
emoji: string;
|
||||||
|
color: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const statusMap: Record<string, ProcessStatus> = {
|
||||||
|
"R": { // Running
|
||||||
|
label: "Running",
|
||||||
|
emoji: "🏃",
|
||||||
|
color: "var(--green)",
|
||||||
|
},
|
||||||
|
"S": { // Sleeping
|
||||||
|
label: "Sleeping",
|
||||||
|
emoji: "😴",
|
||||||
|
color: "var(--blue)",
|
||||||
|
},
|
||||||
|
"I": { // Idle
|
||||||
|
label: "Idle",
|
||||||
|
emoji: "⌛",
|
||||||
|
color: "var(--overlay0)",
|
||||||
|
},
|
||||||
|
"Z": { // Zombie
|
||||||
|
label: "Zombie",
|
||||||
|
emoji: "🧟",
|
||||||
|
color: "var(--red)",
|
||||||
|
},
|
||||||
|
"T": { // Stopped
|
||||||
|
label: "Stopped",
|
||||||
|
emoji: "⛔",
|
||||||
|
color: "var(--yellow)",
|
||||||
|
},
|
||||||
|
"X": { // Dead
|
||||||
|
label: "Dead",
|
||||||
|
emoji: "💀",
|
||||||
|
color: "var(--red)",
|
||||||
|
},
|
||||||
|
"Unknown": {
|
||||||
|
label: "Unknown",
|
||||||
|
emoji: "🤔",
|
||||||
|
color: "var(--overlay0)",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function formatStatus(status: string): string {
|
||||||
|
// Log the incoming status for debugging
|
||||||
|
console.log('Process status:', status);
|
||||||
|
|
||||||
|
const processStatus = statusMap[status] || statusMap.Unknown;
|
||||||
|
return `<span class="status-badge" style="--status-color: ${processStatus.color}">
|
||||||
|
<span class="status-emoji">${processStatus.emoji}</span>
|
||||||
|
${processStatus.label}
|
||||||
|
</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatMemorySize(bytes: number): string {
|
||||||
|
const gb = bytes / (1024 * 1024 * 1024);
|
||||||
|
return `${gb.toFixed(1)} GB`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatPercentage(value: number): string {
|
||||||
|
return `${value.toFixed(1)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatUptime(seconds: number): string {
|
||||||
|
const days = Math.floor(seconds / 86400);
|
||||||
|
const hours = Math.floor((seconds % 86400) / 3600);
|
||||||
|
const minutes = Math.floor((seconds % 3600) / 60);
|
||||||
|
return `${days}d ${hours}h ${minutes}m`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUsageClass(percentage: number): string {
|
||||||
|
if (percentage >= 90) return "critical";
|
||||||
|
if (percentage >= 60) return "high";
|
||||||
|
if (percentage >= 30) return "medium";
|
||||||
|
return "low";
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
export interface ProcessStatus {
|
|
||||||
label: string;
|
|
||||||
emoji: string;
|
|
||||||
color: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const statusMap: Record<string, ProcessStatus> = {
|
|
||||||
"R": { // Running
|
|
||||||
label: "Running",
|
|
||||||
emoji: "🏃",
|
|
||||||
color: "var(--green)",
|
|
||||||
},
|
|
||||||
"S": { // Sleeping
|
|
||||||
label: "Sleeping",
|
|
||||||
emoji: "😴",
|
|
||||||
color: "var(--blue)",
|
|
||||||
},
|
|
||||||
"I": { // Idle
|
|
||||||
label: "Idle",
|
|
||||||
emoji: "⌛",
|
|
||||||
color: "var(--overlay0)",
|
|
||||||
},
|
|
||||||
"Z": { // Zombie
|
|
||||||
label: "Zombie",
|
|
||||||
emoji: "🧟",
|
|
||||||
color: "var(--red)",
|
|
||||||
},
|
|
||||||
"T": { // Stopped
|
|
||||||
label: "Stopped",
|
|
||||||
emoji: "⛔",
|
|
||||||
color: "var(--yellow)",
|
|
||||||
},
|
|
||||||
"X": { // Dead
|
|
||||||
label: "Dead",
|
|
||||||
emoji: "💀",
|
|
||||||
color: "var(--red)",
|
|
||||||
},
|
|
||||||
"Unknown": {
|
|
||||||
label: "Unknown",
|
|
||||||
emoji: "🤔",
|
|
||||||
color: "var(--overlay0)",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export function formatStatus(status: string): string {
|
|
||||||
// Log the incoming status for debugging
|
|
||||||
console.log('Process status:', status);
|
|
||||||
|
|
||||||
const processStatus = statusMap[status] || statusMap.Unknown;
|
|
||||||
return `<span class="status-badge" style="--status-color: ${processStatus.color}">
|
|
||||||
<span class="status-emoji">${processStatus.emoji}</span>
|
|
||||||
${processStatus.label}
|
|
||||||
</span>`;
|
|
||||||
}
|
|
@ -6,37 +6,9 @@
|
|||||||
import ProcessTable from "$lib/components/ProcessTable.svelte";
|
import ProcessTable from "$lib/components/ProcessTable.svelte";
|
||||||
import ProcessDetailsModal from "$lib/components/ProcessDetailsModal.svelte";
|
import ProcessDetailsModal from "$lib/components/ProcessDetailsModal.svelte";
|
||||||
import KillProcessModal from "$lib/components/KillProcessModal.svelte";
|
import KillProcessModal from "$lib/components/KillProcessModal.svelte";
|
||||||
import { formatStatus } from "$lib/utils/processStatus";
|
import { formatStatus } from "$lib/utils";
|
||||||
import { themeStore } from "$lib/stores/theme";
|
import { themeStore } from "$lib/stores";
|
||||||
import ThemeSwitcher from "$lib/components/ThemeSwitcher.svelte";
|
import type { Process, SystemStats, Column } from "$lib/types";
|
||||||
|
|
||||||
interface Process {
|
|
||||||
pid: number;
|
|
||||||
ppid: number;
|
|
||||||
name: string;
|
|
||||||
cpu_usage: number;
|
|
||||||
memory_usage: number;
|
|
||||||
status: string;
|
|
||||||
user: string;
|
|
||||||
command: string;
|
|
||||||
threads?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SystemStats {
|
|
||||||
cpu_usage: number[];
|
|
||||||
memory_total: number;
|
|
||||||
memory_used: number;
|
|
||||||
uptime: number;
|
|
||||||
load_avg: [number, number, number];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Column {
|
|
||||||
id: keyof Process;
|
|
||||||
label: string;
|
|
||||||
visible: boolean;
|
|
||||||
required?: boolean;
|
|
||||||
format?: (value: any) => string;
|
|
||||||
}
|
|
||||||
|
|
||||||
let processes: Process[] = [];
|
let processes: Process[] = [];
|
||||||
let systemStats: SystemStats | null = null;
|
let systemStats: SystemStats | null = null;
|
||||||
@ -122,16 +94,24 @@
|
|||||||
try {
|
try {
|
||||||
processes = await invoke<Process[]>("get_processes");
|
processes = await invoke<Process[]>("get_processes");
|
||||||
error = null;
|
error = null;
|
||||||
} catch (e) {
|
} catch (e: unknown) {
|
||||||
error = e.toString();
|
if (e instanceof Error) {
|
||||||
|
error = e.message;
|
||||||
|
} else {
|
||||||
|
error = String(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSystemStats() {
|
async function getSystemStats() {
|
||||||
try {
|
try {
|
||||||
systemStats = await invoke<SystemStats>("get_system_stats");
|
systemStats = await invoke<SystemStats>("get_system_stats");
|
||||||
} catch (e) {
|
} catch (e: unknown) {
|
||||||
console.error("Failed to get system stats:", e);
|
if (e instanceof Error) {
|
||||||
|
error = e.message;
|
||||||
|
} else {
|
||||||
|
error = String(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,8 +121,12 @@
|
|||||||
if (success) {
|
if (success) {
|
||||||
await getProcesses();
|
await getProcesses();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e: unknown) {
|
||||||
error = e.toString();
|
if (e instanceof Error) {
|
||||||
|
error = e.message;
|
||||||
|
} else {
|
||||||
|
error = String(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,13 +194,15 @@
|
|||||||
{#if isLoading}
|
{#if isLoading}
|
||||||
<div class="loading-container">
|
<div class="loading-container">
|
||||||
<div class="loading-content">
|
<div class="loading-content">
|
||||||
<div class="spinner" />
|
<div class="spinner"></div>
|
||||||
<span class="loading-text">Loading processes...</span>
|
<span class="loading-text">Loading processes...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<main>
|
<main>
|
||||||
<StatsBar {systemStats} />
|
{#if systemStats}
|
||||||
|
<StatsBar {systemStats} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<ToolBar
|
<ToolBar
|
||||||
bind:searchTerm
|
bind:searchTerm
|
||||||
|
Loading…
x
Reference in New Issue
Block a user