mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-15 04:32:42 +00:00
Fixes #14173, other modular computer file manager improvements
This commit is contained in:
committed by
CHOMPStation2
parent
fb1b9498ad
commit
71da50bf43
@@ -291,4 +291,10 @@
|
|||||||
if(autorun.stored_data == program)
|
if(autorun.stored_data == program)
|
||||||
autorun.stored_data = null
|
autorun.stored_data = null
|
||||||
else
|
else
|
||||||
autorun.stored_data = program
|
autorun.stored_data = program
|
||||||
|
|
||||||
|
/obj/item/modular_computer/proc/find_file_by_uid(var/uid)
|
||||||
|
if(hard_drive)
|
||||||
|
. = hard_drive.find_file_by_uid(uid)
|
||||||
|
if(portable_drive && !.)
|
||||||
|
. = portable_drive.find_file_by_uid(uid)
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
switch(action)
|
switch(action)
|
||||||
if("PRG_openfile")
|
if("PRG_openfile")
|
||||||
open_file = params["name"]
|
open_file = params["uid"]
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_newtextfile")
|
if("PRG_newtextfile")
|
||||||
if(!HDD)
|
if(!HDD)
|
||||||
@@ -33,19 +33,20 @@
|
|||||||
var/newname = sanitize(tgui_input_text(usr, "Enter file name or leave blank to cancel:", "File rename"))
|
var/newname = sanitize(tgui_input_text(usr, "Enter file name or leave blank to cancel:", "File rename"))
|
||||||
if(!newname)
|
if(!newname)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/data/F = new/datum/computer_file/data()
|
if(HDD.find_file_by_name(newname))
|
||||||
|
error = "I/O error: File already exists."
|
||||||
|
return
|
||||||
|
var/datum/computer_file/data/F = new/datum/computer_file/data/text()
|
||||||
F.filename = newname
|
F.filename = newname
|
||||||
F.filetype = "TXT"
|
|
||||||
HDD.store_file(F)
|
HDD.store_file(F)
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_closefile")
|
if("PRG_closefile")
|
||||||
open_file = null
|
open_file = null
|
||||||
error = null
|
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_clone")
|
if("PRG_clone")
|
||||||
if(!HDD)
|
if(!HDD)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/F = HDD.find_file_by_name(params["name"])
|
var/datum/computer_file/F = HDD.find_file_by_uid(params["uid"])
|
||||||
if(!F || !istype(F))
|
if(!F || !istype(F))
|
||||||
return
|
return
|
||||||
var/datum/computer_file/C = F.clone(1)
|
var/datum/computer_file/C = F.clone(1)
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
return
|
return
|
||||||
if(!open_file)
|
if(!open_file)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
|
var/datum/computer_file/data/F = computer.find_file_by_uid(open_file)
|
||||||
if(!F || !istype(F))
|
if(!F || !istype(F))
|
||||||
return
|
return
|
||||||
if(F.do_not_edit && (tgui_alert(usr, "WARNING: This file is not compatible with editor. Editing it may result in permanently corrupted formatting or damaged data consistency. Edit anyway?", "Incompatible File", list("No", "Yes")) == "No"))
|
if(F.do_not_edit && (tgui_alert(usr, "WARNING: This file is not compatible with editor. Editing it may result in permanently corrupted formatting or damaged data consistency. Edit anyway?", "Incompatible File", list("No", "Yes")) == "No"))
|
||||||
@@ -65,82 +66,86 @@
|
|||||||
var/oldtext = html_decode(F.stored_data)
|
var/oldtext = html_decode(F.stored_data)
|
||||||
oldtext = replacetext(oldtext, "\[br\]", "\n")
|
oldtext = replacetext(oldtext, "\[br\]", "\n")
|
||||||
|
|
||||||
var/newtext = sanitize(replacetext(tgui_input_text(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", oldtext, MAX_TEXTFILE_LENGTH, TRUE, prevent_enter = TRUE), "\n", "\[br\]"), MAX_TEXTFILE_LENGTH)
|
var/newtext = sanitize(replacetext(tgui_input_text(usr, "Editing file [F.filename].[F.filetype]. You may use most tags used in paper formatting:", "Text Editor", oldtext, MAX_TEXTFILE_LENGTH, TRUE, prevent_enter = TRUE), "\n", "\[br\]"), MAX_TEXTFILE_LENGTH)
|
||||||
if(!newtext)
|
if(!newtext)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(F)
|
if(F)
|
||||||
var/datum/computer_file/data/backup = F.clone()
|
var/datum/computer_file/data/backup = F.clone()
|
||||||
HDD.remove_file(F)
|
F.holder.remove_file(F)
|
||||||
F.stored_data = newtext
|
F.stored_data = newtext
|
||||||
F.calculate_size()
|
F.calculate_size()
|
||||||
// We can't store the updated file, it's probably too large. Print an error and restore backed up version.
|
// We can't store the updated file, it's probably too large. Print an error and restore backed up version.
|
||||||
// This is mostly intended to prevent people from losing texts they spent lot of time working on due to running out of space.
|
// This is mostly intended to prevent people from losing texts they spent lot of time working on due to running out of space.
|
||||||
// They will be able to copy-paste the text from error screen and store it in notepad or something.
|
// They will be able to copy-paste the text from error screen and store it in notepad or something.
|
||||||
if(!HDD.store_file(F))
|
if(!F.holder.store_file(F))
|
||||||
error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:<br><br>[html_decode(F.stored_data)]<br><br>"
|
error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:<br><br>[html_decode(F.stored_data)]<br><br>"
|
||||||
HDD.store_file(backup)
|
F.holder.store_file(backup)
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_printfile")
|
if("PRG_printfile")
|
||||||
if(!HDD)
|
if(!HDD)
|
||||||
return
|
return
|
||||||
if(!open_file)
|
if(!open_file)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/data/F = HDD.find_file_by_name(open_file)
|
var/datum/computer_file/data/F = computer.find_file_by_uid(open_file)
|
||||||
if(!F || !istype(F))
|
if(!F || !istype(F))
|
||||||
return
|
return
|
||||||
if(!computer.nano_printer)
|
if(!computer.nano_printer)
|
||||||
error = "Missing Hardware: Your computer does not have required hardware to complete this operation."
|
error = "Missing Hardware: Your computer does not have required hardware to complete this operation."
|
||||||
return
|
return TRUE
|
||||||
if(!computer.nano_printer.print_text(pencode2html(F.stored_data)))
|
if(!computer.nano_printer.print_text(pencode2html(F.stored_data)))
|
||||||
error = "Hardware error: Printer was unable to print the file. It may be out of paper."
|
error = "Hardware error: Printer was unable to print the file. It may be out of paper."
|
||||||
return
|
return TRUE
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_deletefile")
|
if("PRG_deletefile")
|
||||||
if(!HDD)
|
if(!HDD)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/file = HDD.find_file_by_name(params["name"])
|
var/datum/computer_file/file = computer.find_file_by_uid(params["uid"])
|
||||||
if(!file || file.undeletable)
|
if(!file || file.undeletable)
|
||||||
return
|
return
|
||||||
HDD.remove_file(file)
|
file.holder.remove_file(file)
|
||||||
return TRUE
|
|
||||||
if("PRG_usbdeletefile")
|
|
||||||
if(!RHDD)
|
|
||||||
return
|
|
||||||
var/datum/computer_file/file = RHDD.find_file_by_name(params["name"])
|
|
||||||
if(!file || file.undeletable)
|
|
||||||
return
|
|
||||||
RHDD.remove_file(file)
|
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_rename")
|
if("PRG_rename")
|
||||||
if(!HDD)
|
if(!HDD)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/file = HDD.find_file_by_name(params["name"])
|
var/datum/computer_file/file = computer.find_file_by_uid(params["uid"])
|
||||||
if(!file)
|
if(!file)
|
||||||
return
|
return
|
||||||
var/newname = params["new_name"]
|
var/newname = params["new_name"]
|
||||||
if(!newname)
|
if(!newname)
|
||||||
return
|
return
|
||||||
|
if(file.holder.find_file_by_name(newname))
|
||||||
|
error = "I/O error: File already exists."
|
||||||
|
return TRUE
|
||||||
file.filename = newname
|
file.filename = newname
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_copytousb")
|
if("PRG_copytousb")
|
||||||
if(!HDD || !RHDD)
|
if(!HDD || !RHDD)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/F = HDD.find_file_by_name(params["name"])
|
var/datum/computer_file/F = HDD.find_file_by_uid(params["uid"])
|
||||||
if(!F)
|
if(!F)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/C = F.clone(FALSE)
|
var/datum/computer_file/C = F.clone(FALSE)
|
||||||
|
if(!RHDD.try_store_file(C))
|
||||||
|
error = "I/O error: File already exists or insufficient space on drive."
|
||||||
|
return TRUE
|
||||||
RHDD.store_file(C)
|
RHDD.store_file(C)
|
||||||
return TRUE
|
return TRUE
|
||||||
if("PRG_copyfromusb")
|
if("PRG_copyfromusb")
|
||||||
if(!HDD || !RHDD)
|
if(!HDD || !RHDD)
|
||||||
return
|
return
|
||||||
var/datum/computer_file/F = RHDD.find_file_by_name(params["name"])
|
var/datum/computer_file/F = RHDD.find_file_by_uid(params["uid"])
|
||||||
if(!F || !istype(F))
|
if(!F || !istype(F))
|
||||||
return
|
return
|
||||||
var/datum/computer_file/C = F.clone(FALSE)
|
var/datum/computer_file/C = F.clone(FALSE)
|
||||||
|
if(!HDD.try_store_file(C))
|
||||||
|
error = "I/O error: File already exists or insufficient space on drive."
|
||||||
|
return TRUE
|
||||||
HDD.store_file(C)
|
HDD.store_file(C)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
if("PRG_clearerror")
|
||||||
|
error = null
|
||||||
|
return TRUE
|
||||||
|
|
||||||
/datum/computer_file/program/filemanager/tgui_data(mob/user)
|
/datum/computer_file/program/filemanager/tgui_data(mob/user)
|
||||||
var/list/data = get_header_data()
|
var/list/data = get_header_data()
|
||||||
@@ -163,10 +168,10 @@
|
|||||||
if(open_file)
|
if(open_file)
|
||||||
var/datum/computer_file/data/file
|
var/datum/computer_file/data/file
|
||||||
|
|
||||||
if(!computer || !computer.hard_drive)
|
if(!computer || (!computer.hard_drive && computer.portable_drive))
|
||||||
data["error"] = "I/O ERROR: Unable to access hard drive."
|
data["error"] = "I/O ERROR: Unable to access hard drive."
|
||||||
else
|
else
|
||||||
file = HDD.find_file_by_name(open_file)
|
file = computer.find_file_by_uid(open_file)
|
||||||
if(!istype(file))
|
if(!istype(file))
|
||||||
data["error"] = "I/O ERROR: Unable to open file."
|
data["error"] = "I/O ERROR: Unable to open file."
|
||||||
else
|
else
|
||||||
@@ -178,6 +183,7 @@
|
|||||||
files += list(list(
|
files += list(list(
|
||||||
"name" = F.filename,
|
"name" = F.filename,
|
||||||
"type" = F.filetype,
|
"type" = F.filetype,
|
||||||
|
"uid" = F.uid,
|
||||||
"size" = F.size,
|
"size" = F.size,
|
||||||
"undeletable" = F.undeletable
|
"undeletable" = F.undeletable
|
||||||
))
|
))
|
||||||
@@ -189,6 +195,7 @@
|
|||||||
usbfiles += list(list(
|
usbfiles += list(list(
|
||||||
"name" = F.filename,
|
"name" = F.filename,
|
||||||
"type" = F.filetype,
|
"type" = F.filetype,
|
||||||
|
"uid" = F.uid,
|
||||||
"size" = F.size,
|
"size" = F.size,
|
||||||
"undeletable" = F.undeletable
|
"undeletable" = F.undeletable
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -161,6 +161,21 @@
|
|||||||
return F
|
return F
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
// Tries to find the file by unique ID. Returns null on failure
|
||||||
|
/obj/item/weapon/computer_hardware/hard_drive/proc/find_file_by_uid(var/uid)
|
||||||
|
if(!check_functionality())
|
||||||
|
return null
|
||||||
|
|
||||||
|
if(!uid)
|
||||||
|
return null
|
||||||
|
|
||||||
|
if(!stored_files)
|
||||||
|
return null
|
||||||
|
|
||||||
|
for(var/datum/computer_file/F in stored_files)
|
||||||
|
if(F.uid == uid)
|
||||||
|
return F
|
||||||
|
|
||||||
/obj/item/weapon/computer_hardware/hard_drive/Destroy()
|
/obj/item/weapon/computer_hardware/hard_drive/Destroy()
|
||||||
if(holder2 && (holder2.hard_drive == src))
|
if(holder2 && (holder2.hard_drive == src))
|
||||||
holder2.hard_drive = null
|
holder2.hard_drive = null
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint react/no-danger: "off" */
|
/* eslint react/no-danger: "off" */
|
||||||
import { Fragment } from 'inferno';
|
import { Fragment } from 'inferno';
|
||||||
import { useBackend } from '../backend';
|
import { useBackend } from '../backend';
|
||||||
import { Button, Section, Table } from '../components';
|
import { Button, Section, Table, Flex } from '../components';
|
||||||
import { NtosWindow } from '../layouts';
|
import { NtosWindow } from '../layouts';
|
||||||
|
|
||||||
export const NtosFileManager = (props, context) => {
|
export const NtosFileManager = (props, context) => {
|
||||||
@@ -10,7 +10,7 @@ export const NtosFileManager = (props, context) => {
|
|||||||
return (
|
return (
|
||||||
<NtosWindow resizable theme={PC_device_theme}>
|
<NtosWindow resizable theme={PC_device_theme}>
|
||||||
<NtosWindow.Content scrollable>
|
<NtosWindow.Content scrollable>
|
||||||
{((filename || error) && (
|
{(filename && (
|
||||||
<Section
|
<Section
|
||||||
title={'Viewing File ' + filename}
|
title={'Viewing File ' + filename}
|
||||||
buttons={
|
buttons={
|
||||||
@@ -20,7 +20,6 @@ export const NtosFileManager = (props, context) => {
|
|||||||
<Button icon="times" content="Close" onClick={() => act('PRG_closefile')} />
|
<Button icon="times" content="Close" onClick={() => act('PRG_closefile')} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}>
|
}>
|
||||||
{error || null}
|
|
||||||
{/* This dangerouslySetInnerHTML is only ever passed data that has passed through pencode2html
|
{/* This dangerouslySetInnerHTML is only ever passed data that has passed through pencode2html
|
||||||
* It should be safe enough to support pencode in this way.
|
* It should be safe enough to support pencode in this way.
|
||||||
*/}
|
*/}
|
||||||
@@ -32,16 +31,16 @@ export const NtosFileManager = (props, context) => {
|
|||||||
<FileTable
|
<FileTable
|
||||||
files={files}
|
files={files}
|
||||||
usbconnected={usbconnected}
|
usbconnected={usbconnected}
|
||||||
onUpload={(file) => act('PRG_copytousb', { name: file })}
|
onUpload={(file) => act('PRG_copytousb', { uid: file })}
|
||||||
onDelete={(file) => act('PRG_deletefile', { name: file })}
|
onDelete={(file) => act('PRG_deletefile', { uid: file })}
|
||||||
onOpen={(file) => act('PRG_openfile', { name: file })}
|
onOpen={(file) => act('PRG_openfile', { uid: file })}
|
||||||
onRename={(file, newName) =>
|
onRename={(file, newName) =>
|
||||||
act('PRG_rename', {
|
act('PRG_rename', {
|
||||||
name: file,
|
uid: file,
|
||||||
new_name: newName,
|
new_name: newName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onDuplicate={(file) => act('PRG_clone', { file: file })}
|
onDuplicate={(file) => act('PRG_clone', { uid: file })}
|
||||||
/>
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
{(usbconnected && (
|
{(usbconnected && (
|
||||||
@@ -50,15 +49,16 @@ export const NtosFileManager = (props, context) => {
|
|||||||
usbmode
|
usbmode
|
||||||
files={usbfiles}
|
files={usbfiles}
|
||||||
usbconnected={usbconnected}
|
usbconnected={usbconnected}
|
||||||
onUpload={(file) => act('PRG_copyfromusb', { name: file })}
|
onUpload={(file) => act('PRG_copyfromusb', { uid: file })}
|
||||||
onDelete={(file) => act('PRG_deletefile', { name: file })}
|
onDelete={(file) => act('PRG_deletefile', { uid: file })}
|
||||||
|
onOpen={(file) => act('PRG_openfile', { uid: file })}
|
||||||
onRename={(file, newName) =>
|
onRename={(file, newName) =>
|
||||||
act('PRG_rename', {
|
act('PRG_rename', {
|
||||||
name: file,
|
uid: file,
|
||||||
new_name: newName,
|
new_name: newName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onDuplicate={(file) => act('PRG_clone', { file: file })}
|
onDuplicate={(file) => act('PRG_clone', { uid: file })}
|
||||||
/>
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
)) ||
|
)) ||
|
||||||
@@ -70,6 +70,18 @@ export const NtosFileManager = (props, context) => {
|
|||||||
</Section>
|
</Section>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
{error && (
|
||||||
|
<Flex wrap="wrap" position="fixed" bottom="5px">
|
||||||
|
<Flex.Item>
|
||||||
|
<Section>
|
||||||
|
<Button bottom="0" left="0" icon="ban" onClick={() => act('PRG_clearerror')} />
|
||||||
|
</Section>
|
||||||
|
</Flex.Item>
|
||||||
|
<Section>
|
||||||
|
<Flex.Item grow>{error}</Flex.Item>
|
||||||
|
</Section>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
</NtosWindow.Content>
|
</NtosWindow.Content>
|
||||||
</NtosWindow>
|
</NtosWindow>
|
||||||
);
|
);
|
||||||
@@ -94,9 +106,9 @@ const FileTable = (props) => {
|
|||||||
content={file.name}
|
content={file.name}
|
||||||
currentValue={file.name}
|
currentValue={file.name}
|
||||||
tooltip="Rename"
|
tooltip="Rename"
|
||||||
onCommit={(e, value) => onRename(file.name, value)}
|
onCommit={(e, value) => onRename(file.uid, value)}
|
||||||
/>
|
/>
|
||||||
<Button content="Open" onClick={() => onOpen(file.name)} />
|
<Button content="Open" onClick={() => onOpen(file.uid)} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : (
|
) : (
|
||||||
file.name
|
file.name
|
||||||
@@ -112,13 +124,13 @@ const FileTable = (props) => {
|
|||||||
confirmIcon="times"
|
confirmIcon="times"
|
||||||
confirmContent=""
|
confirmContent=""
|
||||||
tooltip="Delete"
|
tooltip="Delete"
|
||||||
onClick={() => onDelete(file.name)}
|
onClick={() => onDelete(file.uid)}
|
||||||
/>
|
/>
|
||||||
{!!usbconnected &&
|
{!!usbconnected &&
|
||||||
(usbmode ? (
|
(usbmode ? (
|
||||||
<Button icon="download" tooltip="Download" onClick={() => onUpload(file.name)} />
|
<Button icon="download" tooltip="Download" onClick={() => onUpload(file.uid)} />
|
||||||
) : (
|
) : (
|
||||||
<Button icon="upload" tooltip="Upload" onClick={() => onUpload(file.name)} />
|
<Button icon="upload" tooltip="Upload" onClick={() => onUpload(file.uid)} />
|
||||||
))}
|
))}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user