mirror of
https://github.com/kunkunsh/kunkun-ext-neohtop.git
synced 2025-04-11 17:29:45 +00:00
persistent config between sessions"
This commit is contained in:
parent
c0c989a2d9
commit
5634a8d355
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "macos-task-manager",
|
"name": "macos-task-manager",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "macos-task-manager",
|
"name": "macos-task-manager",
|
||||||
"version": "1.0.5",
|
"version": "1.0.8",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
"@fortawesome/fontawesome-svg-core": "^6.6.0",
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
faChevronDown,
|
faChevronDown,
|
||||||
faChevronRight,
|
faChevronRight,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { configStore } from "$lib/stores/config";
|
||||||
|
import type { AppConfig } from "$lib/types/config";
|
||||||
export let searchTerm: string;
|
export let searchTerm: string;
|
||||||
export let statusFilter: string = "all";
|
export let statusFilter: string = "all";
|
||||||
export let itemsPerPage: number;
|
export let itemsPerPage: number;
|
||||||
@ -46,6 +48,26 @@
|
|||||||
currentPage = page;
|
currentPage = page;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleColumnVisibilityChange(columnId: string, visible: boolean) {
|
||||||
|
configStore.updateConfig({
|
||||||
|
appearance: {
|
||||||
|
columnVisibility: {
|
||||||
|
...$configStore.appearance.columnVisibility,
|
||||||
|
[columnId]: visible,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBehaviorConfig(key: keyof AppConfig["behavior"], value: any) {
|
||||||
|
configStore.updateConfig({
|
||||||
|
behavior: {
|
||||||
|
...$configStore.behavior,
|
||||||
|
[key]: value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
@ -66,7 +88,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-group">
|
<div class="toolbar-group">
|
||||||
<select bind:value={statusFilter} class="select-input">
|
<select
|
||||||
|
bind:value={statusFilter}
|
||||||
|
on:change={() =>
|
||||||
|
updateBehaviorConfig("defaultStatusFilter", statusFilter)}
|
||||||
|
class="select-input"
|
||||||
|
>
|
||||||
{#each statusOptions as option}
|
{#each statusOptions as option}
|
||||||
<option value={option.value}>{option.label}</option>
|
<option value={option.value}>{option.label}</option>
|
||||||
{/each}
|
{/each}
|
||||||
@ -79,6 +106,7 @@
|
|||||||
<select
|
<select
|
||||||
class="select-input"
|
class="select-input"
|
||||||
bind:value={itemsPerPage}
|
bind:value={itemsPerPage}
|
||||||
|
on:change={() => updateBehaviorConfig("itemsPerPage", itemsPerPage)}
|
||||||
aria-label="Items per page"
|
aria-label="Items per page"
|
||||||
>
|
>
|
||||||
{#each itemsPerPageOptions as option}
|
{#each itemsPerPageOptions as option}
|
||||||
@ -146,8 +174,13 @@
|
|||||||
<label class="column-option">
|
<label class="column-option">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={column.visible}
|
checked={column.visible}
|
||||||
disabled={column.required}
|
disabled={column.required}
|
||||||
|
on:change={(e) =>
|
||||||
|
handleColumnVisibilityChange(
|
||||||
|
column.id,
|
||||||
|
e.currentTarget.checked,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<span>{column.label}</span>
|
<span>{column.label}</span>
|
||||||
</label>
|
</label>
|
||||||
@ -161,6 +194,7 @@
|
|||||||
<select
|
<select
|
||||||
class="select-input"
|
class="select-input"
|
||||||
bind:value={refreshRate}
|
bind:value={refreshRate}
|
||||||
|
on:change={() => updateBehaviorConfig("refreshRate", refreshRate)}
|
||||||
disabled={isFrozen}
|
disabled={isFrozen}
|
||||||
>
|
>
|
||||||
{#each refreshRateOptions as option}
|
{#each refreshRateOptions as option}
|
||||||
|
36
src/lib/stores/config.ts
Normal file
36
src/lib/stores/config.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
import type { AppConfig } from '$lib/types/config';
|
||||||
|
import { DEFAULT_CONFIG } from '$lib/types/config';
|
||||||
|
|
||||||
|
function createConfigStore() {
|
||||||
|
const { subscribe, set, update } = writable<AppConfig>(DEFAULT_CONFIG);
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
init: () => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
const stored = localStorage.getItem('neohtop_config');
|
||||||
|
if (stored) {
|
||||||
|
try {
|
||||||
|
const config = JSON.parse(stored);
|
||||||
|
set({ ...DEFAULT_CONFIG, ...config });
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to parse stored config:', e);
|
||||||
|
set(DEFAULT_CONFIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateConfig: (newConfig: Partial<AppConfig>) => {
|
||||||
|
update(config => {
|
||||||
|
const updated = { ...config, ...newConfig };
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
localStorage.setItem('neohtop_config', JSON.stringify(updated));
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const configStore = createConfigStore();
|
37
src/lib/types/config.ts
Normal file
37
src/lib/types/config.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
export interface AppConfig {
|
||||||
|
appearance: {
|
||||||
|
columnVisibility: Record<string, boolean>;
|
||||||
|
};
|
||||||
|
behavior: {
|
||||||
|
itemsPerPage: number;
|
||||||
|
refreshRate: number;
|
||||||
|
defaultStatusFilter: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_CONFIG: AppConfig = {
|
||||||
|
appearance: {
|
||||||
|
columnVisibility: {
|
||||||
|
name: true,
|
||||||
|
pid: true,
|
||||||
|
status: true,
|
||||||
|
user: true,
|
||||||
|
cpu_usage: true,
|
||||||
|
memory_usage: true,
|
||||||
|
virtual_memory: true,
|
||||||
|
disk_usage: true,
|
||||||
|
ppid: false,
|
||||||
|
root: false,
|
||||||
|
command: false,
|
||||||
|
environ: false,
|
||||||
|
session_id: false,
|
||||||
|
start_time: false,
|
||||||
|
run_time: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
behavior: {
|
||||||
|
itemsPerPage: 15,
|
||||||
|
refreshRate: 1000,
|
||||||
|
defaultStatusFilter: 'all'
|
||||||
|
}
|
||||||
|
};
|
@ -10,6 +10,7 @@
|
|||||||
import { themeStore } from "$lib/stores";
|
import { themeStore } from "$lib/stores";
|
||||||
import type { Process, SystemStats, Column } from "$lib/types";
|
import type { Process, SystemStats, Column } from "$lib/types";
|
||||||
import TitleBar from "$lib/components/TitleBar.svelte";
|
import TitleBar from "$lib/components/TitleBar.svelte";
|
||||||
|
import { configStore } from "$lib/stores/config";
|
||||||
|
|
||||||
let processes: Process[] = [];
|
let processes: Process[] = [];
|
||||||
let systemStats: SystemStats | null = null;
|
let systemStats: SystemStats | null = null;
|
||||||
@ -18,19 +19,16 @@
|
|||||||
let searchTerm = "";
|
let searchTerm = "";
|
||||||
let isLoading = true;
|
let isLoading = true;
|
||||||
let currentPage = 1;
|
let currentPage = 1;
|
||||||
let itemsPerPage = 15;
|
|
||||||
let pinnedProcesses: Set<string> = new Set();
|
let pinnedProcesses: Set<string> = new Set();
|
||||||
let selectedProcess: Process | null = null;
|
let selectedProcess: Process | null = null;
|
||||||
let showInfoModal = false;
|
let showInfoModal = false;
|
||||||
let showConfirmModal = false;
|
let showConfirmModal = false;
|
||||||
let processToKill: Process | null = null;
|
let processToKill: Process | null = null;
|
||||||
let isKilling = false;
|
let isKilling = false;
|
||||||
let statusFilter = "all";
|
|
||||||
let refreshRate = 1000;
|
|
||||||
let isFrozen = false;
|
let isFrozen = false;
|
||||||
let selectedProcessPid: number | null = null;
|
let selectedProcessPid: number | null = null;
|
||||||
|
|
||||||
let columns: Column[] = [
|
let columnDefinitions: Column[] = [
|
||||||
{ id: "name", label: "Process Name", visible: true, required: true },
|
{ id: "name", label: "Process Name", visible: true, required: true },
|
||||||
{ id: "pid", label: "PID", visible: true, required: false },
|
{ id: "pid", label: "PID", visible: true, required: false },
|
||||||
{
|
{
|
||||||
@ -90,6 +88,17 @@
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Merge column definitions with stored visibility
|
||||||
|
$: columns = columnDefinitions.map((col) => ({
|
||||||
|
...col,
|
||||||
|
visible:
|
||||||
|
col.required ||
|
||||||
|
($configStore.appearance.columnVisibility[col.id] ?? col.visible),
|
||||||
|
}));
|
||||||
|
$: itemsPerPage = $configStore.behavior.itemsPerPage;
|
||||||
|
$: refreshRate = $configStore.behavior.refreshRate;
|
||||||
|
$: statusFilter = $configStore.behavior.defaultStatusFilter;
|
||||||
|
|
||||||
let sortConfig = {
|
let sortConfig = {
|
||||||
field: "cpu_usage" as keyof Process,
|
field: "cpu_usage" as keyof Process,
|
||||||
direction: "desc" as "asc" | "desc",
|
direction: "desc" as "asc" | "desc",
|
||||||
@ -262,6 +271,7 @@
|
|||||||
isLoading = false;
|
isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configStore.init();
|
||||||
themeStore.init();
|
themeStore.init();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import { sveltekit } from "@sveltejs/kit/vite";
|
import { sveltekit } from "@sveltejs/kit/vite";
|
||||||
|
|
||||||
// @ts-expect-error process is a nodejs global
|
|
||||||
const host = process.env.TAURI_DEV_HOST;
|
const host = process.env.TAURI_DEV_HOST;
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user