mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-06 00:47:09 +00:00
chore(control): add delete file and create folder action
This commit is contained in:
@@ -36,7 +36,7 @@ export async function show_html(ip: string, html: string) {
|
||||
await request_display(ip, '/showHTML', options);
|
||||
}
|
||||
|
||||
export async function get_file_data(ip: string, path: string): Promise<FolderElement[]> {
|
||||
export async function get_file_data(ip: string, path: string): Promise<FolderElement[] | null> {
|
||||
interface FileInfo {
|
||||
name: string;
|
||||
type: string;
|
||||
@@ -44,25 +44,20 @@ export async function get_file_data(ip: string, path: string): Promise<FolderEle
|
||||
created: string;
|
||||
}
|
||||
|
||||
const options = {
|
||||
method: 'PATCH',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
command: `cd ".${path}" && find . -maxdepth 1 -mindepth 1 -print0 | while IFS= read -r -d '' f; do
|
||||
typ=$(file -b --mime-type -- "$f")
|
||||
size=$(stat -c '%s' -- "$f")
|
||||
created=$(stat -c '%w' -- "$f")
|
||||
[ "$created" = "-" ] && created=$(stat -c '%y' -- "$f")
|
||||
jq -n --arg name "$f" --arg type "$typ" --arg size "$size" --arg created "$created" \
|
||||
'{name:$name, type:$type, size:($size|tostring), created:$created}' | tr -d '\n'
|
||||
echo
|
||||
done
|
||||
` })
|
||||
};
|
||||
const raw_response = await request_display(ip, '/shellCommand', options);
|
||||
if (!raw_response.ok || !raw_response.json) return [];
|
||||
const raw_response = await run_shell_command(ip, `cd ".${path}" && find . -maxdepth 1 -mindepth 1 -print0 | while IFS= read -r -d '' f; do
|
||||
typ=$(file -b --mime-type -- "$f")
|
||||
size=$(stat -c '%s' -- "$f")
|
||||
created=$(stat -c '%w' -- "$f")
|
||||
[ "$created" = "-" ] && created=$(stat -c '%y' -- "$f")
|
||||
jq -n --arg name "$f" --arg type "$typ" --arg size "$size" --arg created "$created" \
|
||||
'{name:$name, type:$type, size:($size|tostring), created:$created}' | tr -d '\n'
|
||||
echo
|
||||
done
|
||||
`);
|
||||
if (!raw_response.ok || !raw_response.json) return null;
|
||||
const json_response = raw_response.json as ShellCommandResponse;
|
||||
if (is_cd_directory_error(ip, json_response)) return [];
|
||||
if (json_response.exitCode === 0 && json_response.stdout.trim() === '') return [];
|
||||
if (is_cd_directory_error(ip, json_response)) return null;
|
||||
|
||||
const response: FileInfo[] = json_response.stdout.trim()
|
||||
.split("\n")
|
||||
@@ -94,14 +89,7 @@ done
|
||||
}
|
||||
|
||||
export async function get_file_tree_data(ip: string, path: string): Promise<TreeElement[] | null> {
|
||||
const options = {
|
||||
method: 'PATCH',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
command: `cd ".${path}" && tree -Js`
|
||||
})
|
||||
};
|
||||
const raw_response = await request_display(ip, '/shellCommand', options);
|
||||
const raw_response = await run_shell_command(ip, `cd ".${path}" && tree -Js`);
|
||||
|
||||
if (!raw_response.ok || !raw_response.json) return null;
|
||||
const json_response = raw_response.json as ShellCommandResponse;
|
||||
@@ -110,6 +98,25 @@ export async function get_file_tree_data(ip: string, path: string): Promise<Tree
|
||||
return (JSON.parse(json_response.stdout.trim()) as [TreeElement, any])[0].contents || null;
|
||||
}
|
||||
|
||||
export async function create_folders(ip: string, path: string, folder_names: string[]): Promise<void> {
|
||||
let command = `cd ".${path}"`;
|
||||
|
||||
for (const part of folder_names) {
|
||||
command += `&& mkdir "${part}" && cd "${part}/"`;
|
||||
}
|
||||
|
||||
await run_shell_command(ip, command);
|
||||
}
|
||||
|
||||
export async function delete_files(ip: string, current_path: string, file_names: string[]) {
|
||||
let del_string: string = '';
|
||||
for (const file_name of file_names) {
|
||||
del_string += `&& rm -r "${file_name}"`;
|
||||
}
|
||||
await run_shell_command(ip, `cd ".${current_path}" ${del_string}`);
|
||||
|
||||
}
|
||||
|
||||
|
||||
export async function show_blackscreen(ip: string): Promise<void> {
|
||||
const options = {
|
||||
@@ -122,19 +129,17 @@ export async function show_blackscreen(ip: string): Promise<void> {
|
||||
await request_display(ip, '/showHTML', options);
|
||||
}
|
||||
|
||||
|
||||
export async function ping_ip(ip: string): Promise<DisplayStatus> {
|
||||
const raw_response = await request_control(`/ping?ip=${ip}`, { method: 'GET' });
|
||||
if (!raw_response.ok || !raw_response.json) return null;
|
||||
return raw_response.json.status ? to_display_status(raw_response.json.status) : null;
|
||||
}
|
||||
|
||||
export async function get_thumbnail_blob(ip: string, path_to_file: string): Promise<Blob | null> {
|
||||
const raw_response = await request_display(ip, `/file/preview${path_to_file}`, { method: 'GET' }, [415]);
|
||||
if (!raw_response.ok || !raw_response.blob) return null
|
||||
return raw_response.blob;
|
||||
}
|
||||
|
||||
export async function ping_ip(ip: string): Promise<DisplayStatus> {
|
||||
const raw_response = await request_control(`/ping?ip=${ip}`, { method: 'GET' });
|
||||
if (!raw_response.ok || !raw_response.json) return null;
|
||||
return raw_response.json.status ? to_display_status(raw_response.json.status) : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -203,4 +208,15 @@ function is_cd_directory_error(ip: string, shell_response: ShellCommandResponse)
|
||||
}
|
||||
if (shell_response.stdout.trim() === '') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
async function run_shell_command(ip: string, command: string): Promise<RequestResponse> {
|
||||
const options = {
|
||||
method: 'PATCH',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
command: command
|
||||
})
|
||||
};
|
||||
return await request_display(ip, '/shellCommand', options);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import type { Display, FolderElement, TreeElement } from "../types";
|
||||
import { displays } from "./displays";
|
||||
import { selected_file_ids } from "./select";
|
||||
import { displays, get_display_by_id } from "./displays";
|
||||
import { selected_display_ids, selected_file_ids } from "./select";
|
||||
import { get_file_data, get_file_tree_data } from "../api_handler";
|
||||
import { notifications } from "./notification";
|
||||
import { CirclePoundSterling } from "lucide-svelte";
|
||||
@@ -45,8 +45,17 @@ export async function change_file_path(new_path: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function update_current_folder_on_selected_displays() {
|
||||
const current_path = get(current_file_path);
|
||||
for (const display_id of get(selected_display_ids)) {
|
||||
const display = get_display_by_id(display_id, get(displays));
|
||||
if (!display) continue;
|
||||
update_folder_elements_recursively(display, current_path);
|
||||
}
|
||||
}
|
||||
|
||||
export function get_display_ids_where_file_is_missing(path: string, file: FolderElement, selected_display_ids: string[], all_files: Record<string, Record<string, FolderElement[]>>): string[][] {
|
||||
if (!all_files.hasOwnProperty(path)) return [];
|
||||
if (!all_files.hasOwnProperty(path)) return [selected_display_ids, []];
|
||||
const missing: string[] = [];
|
||||
const colliding: string[] = [];
|
||||
Display:
|
||||
@@ -68,6 +77,17 @@ export function get_display_ids_where_file_is_missing(path: string, file: Folder
|
||||
return [missing, colliding];
|
||||
}
|
||||
|
||||
export function get_display_ids_where_path_does_not_exist(path: string, selected_display_ids: string[], all_files: Record<string, Record<string, FolderElement[]>>): string[] {
|
||||
if (!all_files.hasOwnProperty(path)) return selected_display_ids;
|
||||
const out: string[] = [];
|
||||
for (const selected_display_id of selected_display_ids) {
|
||||
if (!all_files[path].hasOwnProperty(selected_display_id)) {
|
||||
out.push(selected_display_id);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
async function get_changed_directory_paths(display: Display, file_path: string): Promise<string[] | null> {
|
||||
const current_folder = await get_file_tree_data(display.ip, file_path);
|
||||
if (current_folder === null) return [file_path];
|
||||
@@ -103,6 +123,7 @@ function get_recursive_changed_directory_paths(display: Display, current_file_pa
|
||||
|
||||
export async function update_folder_elements_recursively(display: Display, file_path: string = '/'): Promise<number> {
|
||||
const new_folder_elements = await get_file_data(display.ip, file_path);
|
||||
if (new_folder_elements === null) return 0;
|
||||
all_files.update((files: Record<string, Record<string, FolderElement[]>>) => {
|
||||
if (!files.hasOwnProperty(file_path)) {
|
||||
files[file_path] = {};
|
||||
@@ -223,8 +244,54 @@ function sort_files(files: FolderElement[]) {
|
||||
if (nameCompare !== 0) return nameCompare;
|
||||
|
||||
// Wenn name gleich, absteigend nach date_created
|
||||
if (!b.date_created || !a.date_created) return -1;
|
||||
return b.date_created.getTime() - a.date_created.getTime();
|
||||
});
|
||||
return files;
|
||||
}
|
||||
|
||||
export function get_file_from_id(file_id: string, all_files: Record<string, Record<string, FolderElement[]>>, current_file_path: string): FolderElement | null {
|
||||
const current_path_elements: Record<string, FolderElement[]> | undefined = all_files[current_file_path];
|
||||
if (!current_path_elements) return null;
|
||||
const all_folder_elements = Object.values(current_path_elements).flat();
|
||||
const found = all_folder_elements.find(el => el.id === file_id);
|
||||
if (!found) return null;
|
||||
return found
|
||||
}
|
||||
|
||||
export async function run_for_selected_files_on_selected_displays(action: (ip: string, file_names: string[]) => Promise<void>): Promise<void> {
|
||||
const files = get(all_files);
|
||||
const file_path = get(current_file_path);
|
||||
const folder_element_hashs: string[] = get(selected_file_ids)
|
||||
.map((file_id) => get_file_from_id(file_id, files, file_path))
|
||||
.filter((element) => element !== null)
|
||||
.map((folder_element) => folder_element.hash)
|
||||
.filter((hash) => hash !== null);
|
||||
|
||||
for (const display_id of get(selected_display_ids)) {
|
||||
if (!files[file_path].hasOwnProperty(display_id)) continue;
|
||||
const files_on_display = files[file_path][display_id];
|
||||
|
||||
const selected_file_names_on_display: string[] = files_on_display.filter((e) => e.hash && folder_element_hashs.includes(e.hash)).map((folder_element) => folder_element.name);
|
||||
if (selected_file_names_on_display.length === 0) continue;
|
||||
|
||||
const display = get_display_by_id(display_id, get(displays));
|
||||
if (!display) continue
|
||||
|
||||
await action(display.ip, selected_file_names_on_display);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function get_longest_existing_path_and_needed_parts(path: string, display_id: string, all_files: Record<string, Record<string, FolderElement[]>>): { existing: string; needed: string[] } {
|
||||
const path_parts = path.slice(0, path.length - 1).split('/');
|
||||
for (let i = path_parts.length; i > 1; i--) {
|
||||
const current_path = [...path_parts].splice(0, i).join('/') + '/';;
|
||||
if (all_files.hasOwnProperty(current_path)) {
|
||||
if (all_files[current_path].hasOwnProperty(display_id)) {
|
||||
return { existing: current_path, needed: [...path_parts].splice(i) };
|
||||
}
|
||||
}
|
||||
}
|
||||
return { existing: '/', needed: path_parts };
|
||||
}
|
||||
Reference in New Issue
Block a user