Compare commits

..

10 Commits

9 changed files with 277 additions and 229 deletions
@@ -2,9 +2,10 @@ import { db } from './database';
import { get_display_by_id } from './stores/displays'; import { get_display_by_id } from './stores/displays';
import { import {
get_current_folder_elements, get_current_folder_elements,
create_path_on_all_selected_displays,
get_file_by_id, get_file_by_id,
remove_all_files_without_display, remove_all_files_without_display,
remove_file_from_display remove_file_from_display_recusively
} from './stores/files'; } from './stores/files';
import { notifications } from './stores/notification'; import { notifications } from './stores/notification';
import { generate_thumbnail } from './stores/thumbnails'; import { generate_thumbnail } from './stores/thumbnails';
@@ -28,6 +29,8 @@ export async function add_upload(
) { ) {
if (file_list.length === 0) return console.warn('Upload canceled: no selected files'); if (file_list.length === 0) return console.warn('Upload canceled: no selected files');
await create_path_on_all_selected_displays(current_file_path, selected_display_ids);
const used_file_names: string[] = await ( const used_file_names: string[] = await (
await get_current_folder_elements(current_file_path, selected_display_ids) await get_current_folder_elements(current_file_path, selected_display_ids)
).map((e) => e.name); ).map((e) => e.name);
@@ -414,11 +417,11 @@ async function show_error(task: FileTransferTask, error: ProgressEvent | string)
`Datei: "${task.file_name}", Display-IP: ${task.display.ip}\nFehler: ${error}` `Datei: "${task.file_name}", Display-IP: ${task.display.ip}\nFehler: ${error}`
); );
if (task_data.type === 'upload') { if (task_data.type === 'upload') {
await remove_file_from_display(task.display.id, task.file_primary_key); await remove_file_from_display_recusively(task.display.id, task.file_primary_key);
await remove_all_files_without_display(); await remove_all_files_without_display();
} else if (task_data.type === 'sync') { } else if (task_data.type === 'sync') {
for (const display_id of task_data.destination_displays.map((e) => e.id)) { for (const display_id of task_data.destination_displays.map((e) => e.id)) {
await remove_file_from_display(display_id, task.file_primary_key); await remove_file_from_display_recusively(display_id, task.file_primary_key);
} }
await remove_all_files_without_display(); await remove_all_files_without_display();
} }
+31 -5
View File
@@ -42,16 +42,35 @@ export async function delete_and_deselect_unique_files_from_display(display_id:
.equals(display_id) .equals(display_id)
.toArray(); .toArray();
for (const file of files_on_display) { for (const file of files_on_display) {
await remove_file_from_display(display_id, file.file_primary_key); await remove_file_from_display_recusively(display_id, file.file_primary_key);
} }
await remove_all_files_without_display(); await remove_all_files_without_display();
} }
export async function remove_file_from_display(display_id: string, file_primary_key: string) { export async function remove_file_from_display_recusively(display_id: string, file_primary_key: string) {
const found = await db.files_on_display.get([display_id, file_primary_key]); const found = await db.files_on_display.get([display_id, file_primary_key]);
if (!found) return; if (!found) return;
select(selected_file_ids, file_primary_key, 'deselect'); select(selected_file_ids, file_primary_key, 'deselect');
await db.files_on_display.delete([display_id, file_primary_key]); await db.files_on_display.delete([display_id, file_primary_key]);
const inode_element = await get_file_by_id(found.file_primary_key);
if (!inode_element) return;
if (inode_element.type === 'inode/directory') {
const path_inside_folder = inode_element.path + inode_element.name + `/`;
const primary_file_keys_in_folder = (
await db.files.where('path').equals(path_inside_folder).toArray()
).map((e) => get_file_primary_key(e));
const primary_file_keys_in_folder_on_display = (
await db.files_on_display
.where('file_primary_key')
.anyOf(primary_file_keys_in_folder)
.filter((file) => file.display_id === display_id)
.toArray()
).map((e) => e.file_primary_key);
for (const file_key of primary_file_keys_in_folder_on_display) {
await remove_file_from_display_recusively(display_id, file_key);
}
}
} }
export async function remove_all_files_without_display() { export async function remove_all_files_without_display() {
@@ -272,7 +291,7 @@ export async function update_folder_elements_recursively(
if (diff.deleted.length > 0) { if (diff.deleted.length > 0) {
// Remove old Folder-Elements // Remove old Folder-Elements
for (const old_element of diff.deleted) { for (const old_element of diff.deleted) {
remove_file_from_display(display.id, get_file_primary_key(old_element)); remove_file_from_display_recusively(display.id, get_file_primary_key(old_element));
} }
await remove_all_files_without_display(); await remove_all_files_without_display();
} }
@@ -377,6 +396,14 @@ export async function create_folder_on_all_selected_displays(
path: string, path: string,
selected_display_ids: string[] selected_display_ids: string[]
): Promise<void> { ): Promise<void> {
const path_with_folder_name = (path += folder_name + '/');
await create_path_on_all_selected_displays(path_with_folder_name, selected_display_ids);
}
export async function create_path_on_all_selected_displays(
path: string,
selected_display_ids: string[]
) {
const path_parts = path const path_parts = path
.slice(1, path.length - 1) .slice(1, path.length - 1)
.split('/') .split('/')
@@ -397,9 +424,8 @@ export async function create_folder_on_all_selected_displays(
const displays = await getDisplaysForPath(currentPath); const displays = await getDisplaysForPath(currentPath);
if (!displays.length) continue; if (!displays.length) continue;
const folders_to_create = [...path_parts.slice(depth), folder_name];
for (const display of displays) { for (const display of displays) {
await create_folders(display.ip, currentPath, folders_to_create); await create_folders(display.ip, currentPath, path_parts.slice(depth));
remaining_display_ids = remaining_display_ids.filter((id) => id !== display.id); remaining_display_ids = remaining_display_ids.filter((id) => id !== display.id);
} }
} }
+1 -4
View File
@@ -75,6 +75,7 @@
title: 'Neuen Bildschirm hinzufügen', title: 'Neuen Bildschirm hinzufügen',
title_icon: Monitor, title_icon: Monitor,
title_class: '!text-xl', title_class: '!text-xl',
window_class: 'w-3xl',
closable: true closable: true
}; };
}; };
@@ -231,10 +232,6 @@
icon: Plus, icon: Plus,
name: 'Neuen Bildschirm hinzufügen', name: 'Neuen Bildschirm hinzufügen',
on_select: show_new_display_popup on_select: show_new_display_popup
},
{
icon: Settings,
name: 'Weitere Einstellungen'
} }
]} ]}
> >
@@ -66,12 +66,6 @@
is_selected: () => editor_state.editor?.isActive('strike') ?? false, is_selected: () => editor_state.editor?.isActive('strike') ?? false,
title: 'Durchgestrichen', title: 'Durchgestrichen',
icon: Strikethrough icon: Strikethrough
},
{
onclick: () => {},
is_selected: () => false,
title: 'QR-Code anfügen',
icon: QrCode
} }
], ],
[ [
+3 -3
View File
@@ -216,6 +216,6 @@ module.exports = {
'active:bg-red-500', 'active:bg-red-500',
'hover:bg-stone-600/70', 'hover:bg-stone-600/70',
'active:bg-stone-500/80', 'active:bg-stone-500/80'
], ]
} };
+12 -1
View File
@@ -116,7 +116,7 @@
after = ["network-online.target"]; after = ["network-online.target"];
wants = ["network-online.target"]; wants = ["network-online.target"];
path = config.environment.systemPackages; path = config.environment.systemPackages;
script = "nu ${./update.sh}"; script = "nu ${./update.nu}";
serviceConfig = { serviceConfig = {
WorkingDirectory = "/home/mudics/mudics"; WorkingDirectory = "/home/mudics/mudics";
User = "mudics"; User = "mudics";
@@ -152,6 +152,17 @@
}; };
}; };
systemd.services.enable-wol = {
wantedBy = ["multi-user.target"];
after = ["network.target"];
path = with pkgs; [ethtool nushell];
script = "nu ${./wol.nu}";
serviceConfig = {
Type = "oneshot";
User = "root";
};
};
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d /home/mudics/mudics 0755 mudics - -" "d /home/mudics/mudics 0755 mudics - -"
]; ];
View File
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env nu
ls /sys/class/net | get name | path basename | where $it != "lo" | each {|iface|
print $"Enabling WoL on ($iface)..."
try {
ethtool -s $iface wol g
print $"Successfully enabled WoL on ($iface)"
} catch {
print $"Failed to enable WoL on ($iface). It might not be supported."
}
}
+9 -3
View File
@@ -5,16 +5,22 @@ import (
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
) )
func OpenBrowserWindow(url string, fullscreen bool) error { func OpenBrowserWindow(url string, fullscreen bool) error {
bins := []string{"chromium", "chromium-browser"} bins := []string{"chromium", "chromium-browser"}
tempDirPath, err := os.MkdirTemp("", "plg-mudics-browser-") home, err := os.UserHomeDir()
if err != nil { if err != nil {
return err return fmt.Errorf("unable to determine user home directory: %w", err)
} }
args := []string{fmt.Sprintf("--app=%s", url), "--autoplay-policy=no-user-gesture-required", fmt.Sprintf("--user-data-dir=%s", tempDirPath)} browserProfileDirPath := filepath.Join(home, ".local", "share", "plg-mudics", "browser")
if err := os.MkdirAll(browserProfileDirPath, os.ModePerm); err != nil {
return fmt.Errorf("failed to create local config directory: %w", err)
}
args := []string{fmt.Sprintf("--app=%s", url), "--autoplay-policy=no-user-gesture-required", fmt.Sprintf("--user-data-dir=%s", browserProfileDirPath)}
if fullscreen { if fullscreen {
args = append(args, "--start-fullscreen") args = append(args, "--start-fullscreen")
} }