File Property folders

This commit is contained in:
Robin Davies
2024-08-14 16:07:16 -04:00
parent 3ef263a16e
commit 508b7d2808
10 changed files with 559 additions and 47 deletions
+15 -1
View File
@@ -29,7 +29,7 @@ import createStyles from '@mui/styles/createStyles';
import withStyles from '@mui/styles/withStyles';
import { UiFileProperty } from './Lv2Plugin';
import Typography from '@mui/material/Typography';
import { PiPedalModel, PiPedalModelFactory, ListenHandle} from './PiPedalModel';
import { PiPedalModel, PiPedalModelFactory, ListenHandle,State} from './PiPedalModel';
import ButtonBase from '@mui/material/ButtonBase'
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
import {PedalboardItem} from './Pedalboard';
@@ -98,8 +98,18 @@ const FilePropertyControl =
value: "",
};
this.model = PiPedalModelFactory.getInstance();
this.onStateChanged = this.onStateChanged.bind(this);
}
onStateChanged(state: State) {
if (this.mounted)
{
if (state === State.Ready) {
this.subscribeToPatchProperty();
}
}
}
private propertyGetHandle?: ListenHandle;
monitorPropertyHandle?: ListenHandle;
@@ -119,6 +129,7 @@ const FilePropertyControl =
}
}
);
}
unsubscribeToPatchProperty() {
if (this.monitorPropertyHandle !== undefined)
@@ -126,15 +137,18 @@ const FilePropertyControl =
this.model.cancelMonitorPatchProperty(this.monitorPropertyHandle);
this.monitorPropertyHandle = undefined;
}
}
private mounted: boolean = false;
componentDidMount() {
this.model.state.addOnChangedHandler(this.onStateChanged);
this.mounted = true;
this.subscribeToPatchProperty();
}
componentWillUnmount() {
this.unsubscribeToPatchProperty();
this.mounted = false;
this.model.state.removeOnChangedHandler(this.onStateChanged);
}
componentDidUpdate(prevProps: Readonly<FilePropertyControlProps>, prevState: Readonly<FilePropertyControlState>, snapshot?: any): void {
if (prevProps.fileProperty.patchProperty !== this.props.fileProperty.patchProperty
+107 -21
View File
@@ -18,7 +18,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import React from 'react';
import { Theme, createStyles } from '@mui/material/styles';
import RenameDialog from './RenameDialog';
import Divider from '@mui/material/Divider';
import MenuItem from '@mui/material/MenuItem';
@@ -38,6 +38,8 @@ import DialogTitle from '@mui/material/DialogTitle';
import IconButton from '@mui/material/IconButton';
import OldDeleteIcon from './OldDeleteIcon';
import Toolbar from '@mui/material/Toolbar';
import { withStyles, WithStyles } from '@mui/styles';
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import { UiFileProperty } from './Lv2Plugin';
@@ -48,7 +50,18 @@ import UploadFileDialog from './UploadFileDialog';
import OkCancelDialog from './OkCancelDialog';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import HomeIcon from '@mui/icons-material/Home';
export interface FilePropertyDialogProps {
import FilePropertyDirectorySelectDialog from './FilePropertyDirectorySelectDialog';
const styles = (theme: Theme) => createStyles({
secondaryText: {
color: theme.palette.text.secondary
},
});
export interface FilePropertyDialogProps extends WithStyles<typeof styles> {
open: boolean,
fileProperty: UiFileProperty,
selectedFile: string,
@@ -70,6 +83,7 @@ export interface FilePropertyDialogState {
menuAnchorEl: null | HTMLElement;
newFolderDialogOpen: boolean;
renameDialogOpen: boolean;
moveDialogOpen: boolean;
};
function pathExtension(path: string)
@@ -85,7 +99,7 @@ function pathExtension(path: string)
return path.substring(dotPos); // include the '.'.
}
function concatPath(left: string, right: string) {
function pathConcat(left: string, right: string) {
if (left === "") return right;
if (right === "") return left;
if (left.endsWith('/')) {
@@ -123,7 +137,9 @@ export function pathFileName(path: string): string {
return path.substring(slashPos);
}
export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePropertyDialogProps, FilePropertyDialogState> {
export default withStyles(styles, { withTheme: true })(
class FilePropertyDialog extends ResizeResponsiveComponent<FilePropertyDialogProps, FilePropertyDialogState> {
getNavDirectoryFromFile(selectedFile: string, fileProperty: UiFileProperty): string {
@@ -160,7 +176,8 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
openConfirmDeleteDialog: false,
menuAnchorEl: null,
newFolderDialogOpen: false,
renameDialogOpen: false
renameDialogOpen: false,
moveDialogOpen: false
};
this.requestScroll = true;
}
@@ -250,7 +267,12 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
if (prevProps.open !== this.props.open || prevProps.fileProperty !== this.props.fileProperty || prevProps.selectedFile !== this.props.selectedFile) {
if (this.props.open) {
let navDirectory = this.getNavDirectoryFromFile(this.props.selectedFile, this.props.fileProperty);
this.setState({ selectedFile: this.props.selectedFile });
this.setState({
selectedFile: this.props.selectedFile,
newFolderDialogOpen: false,
renameDialogOpen: false,
moveDialogOpen: false
});
this.requestFiles(navDirectory)
this.requestScroll = true;
}
@@ -357,7 +379,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
let directories = this.state.navDirectory.split("/");
let target = "";
for (let i = 0; i < directories.length - 1; ++i) {
target = concatPath(target, directories[i]);
target = pathConcat(target, directories[i]);
let myTarget = target;
breadcrumbs.push((
<Link underline="hover" key={(i + 1).toString()}
@@ -369,7 +391,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
{
let lastdirectory = directories[directories.length - 1];
breadcrumbs.push((
<Typography key={directories.length.toString()} color="text.secondary"> {lastdirectory}</Typography>
<Typography noWrap key={directories.length.toString()} color="text.secondary"> {lastdirectory}</Typography>
));
}
@@ -380,13 +402,35 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
);
}
getDefaultPath(): string {
try {
let storage = window.localStorage;
let result = storage.getItem("fpDefaultPath");
if (result)
{
return result;
}
} catch (e)
{
}
return this.state.navDirectory;
}
setDefaultPath(path: string) {
try {
let storage = window.localStorage;
storage.setItem("fpDefaultPath",path);
} catch(e) {
}
}
hasSelectedFileOrFolder(): boolean {
return this.state.hasSelection && this.state.selectedFile !== "";
}
render() {
let classes = this.props.classes;
let columnWidth = this.state.columnWidth;
return this.props.open &&
(
<DialogEx onClose={() => this.props.onCancel()} open={this.props.open} tag="fileProperty" fullWidth maxWidth="xl" style={{ height: "90%" }}
@@ -403,7 +447,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
>
<ArrowBackIcon style={{ width: 24, height: 24 }} />
</IconButton>
<Typography component="div" sx={{ flexGrow: 1 }}>
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
{this.props.fileProperty.label}
</Typography>
<IconButton
@@ -432,7 +476,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
>
<MenuItem onClick={() => { this.handleMenuClose(); this.onNewFolder(); }}>New folder</MenuItem>
{this.hasSelectedFileOrFolder() && (<Divider />)}
{this.hasSelectedFileOrFolder() && (<MenuItem onClick={() => { this.handleMenuClose(); }}>Move</MenuItem>)}
{this.hasSelectedFileOrFolder() && (<MenuItem onClick={() => { this.handleMenuClose();this.onMove(); }}>Move</MenuItem>)}
{this.hasSelectedFileOrFolder() && (<MenuItem onClick={() => { this.handleMenuClose();this.onRename(); }}>Rename</MenuItem>)}
</Menu>
</Toolbar>
@@ -484,7 +528,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
) : (
<AudioFileIcon style={{ flex: "0 0 auto", opacity: 0.7, marginRight: 8, marginLeft: 8 }} />
))}
<Typography noWrap style={{ flex: "1 1 auto", textAlign: "left" }}>{displayValue}</Typography>
<Typography noWrap className={classes.secondaryText} variant="body2" style={{ flex: "1 1 auto", textAlign: "left" }}>{displayValue}</Typography>
</div>
</ButtonBase>
);
@@ -566,13 +610,36 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
)
}
{
this.state.moveDialogOpen && (
(
<FilePropertyDirectorySelectDialog
open={this.state.moveDialogOpen}
uiFileProperty={this.props.fileProperty}
defaultPath={this.getDefaultPath()}
excludeDirectory={
this.isDirectory(this.state.selectedFile)
? pathConcat(this.state.navDirectory,pathFileName(this.state.selectedFile)): ""}
onClose={() => {this.setState({moveDialogOpen: false});}}
onOk={
(path) => {
this.setState({moveDialogOpen: false});
this.setDefaultPath(path);
this.onExecuteMove(path);
}
}
/>
)
)
}
</DialogEx>
);
}
openSelectedFile(): void {
if (this.isDirectory(this.state.selectedFile)) {
let directoryName = pathFileNameOnly(this.state.selectedFile);
let navDirectory = concatPath(this.state.navDirectory, directoryName);
let navDirectory = pathConcat(this.state.navDirectory, directoryName);
this.requestFiles(navDirectory);
this.setState({ navDirectory: navDirectory });
} else {
@@ -590,6 +657,25 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
return pathFileNameOnly(name);
}
}
private onMove(): void {
this.setState({ moveDialogOpen: true });
}
private onExecuteMove(newDirectory: string)
{
let fileName = pathFileName(this.state.selectedFile);
let oldFilePath = pathConcat(this.state.navDirectory,fileName);
let newFilePath = pathConcat(newDirectory,fileName);
this.model.renameFilePropertyFile(oldFilePath,newFilePath,this.props.fileProperty)
.then(()=>{
this.requestFiles(this.state.navDirectory);
})
.catch((e)=>{
this.model.showAlert(e.toString());
});
}
private onRename(): void {
this.setState({ renameDialogOpen: true });
}
@@ -600,16 +686,16 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
{
let oldName = pathFileName(this.state.selectedFile);
if (oldName === newName) return;
oldPath = concatPath(this.state.navDirectory,oldName);
newPath = concatPath(this.state.navDirectory,newName);;
oldPath = pathConcat(this.state.navDirectory,oldName);
newPath = pathConcat(this.state.navDirectory,newName);;
} else {
let oldName = pathFileNameOnly(this.state.selectedFile);
if (oldName === newName) return;
let extension = pathExtension(this.state.selectedFile);
oldPath = concatPath(this.state.navDirectory,oldName+extension);
newPath = concatPath(this.state.navDirectory,newName + extension);
oldPath = pathConcat(this.state.navDirectory,oldName+extension);
newPath = pathConcat(this.state.navDirectory,newName + extension);
}
this.model.renameSampleFile(oldPath,newPath,this.props.fileProperty)
this.model.renameFilePropertyFile(oldPath,newPath,this.props.fileProperty)
.then((newPath)=>{
this.setState({selectedFile: newPath});
this.requestFiles(this.state.navDirectory);
@@ -626,7 +712,7 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
}
private onExecuteNewFolder(newName: string) {
this.model.createNewSampleDirectory(concatPath(this.state.navDirectory,newName), this.props.fileProperty)
this.model.createNewSampleDirectory(pathConcat(this.state.navDirectory,newName), this.props.fileProperty)
.then((newPath) => {
this.setState({selectedFile: newPath});
this.requestFiles(this.state.navDirectory);
@@ -637,4 +723,4 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
}
);
}
}
});
@@ -0,0 +1,347 @@
// Copyright (c) 2024 Robin Davies
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import React from 'react';
import Button from '@mui/material/Button';
import DialogEx from './DialogEx';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
import { UiFileProperty } from './Lv2Plugin';
import FilePropertyDirectoryTree from './FilePropertyDirectoryTree';
import ButtonBase from '@mui/material/ButtonBase';
import Typography from '@mui/material/Typography'
import Divider from '@mui/material/Divider';
import FolderIcon from '@mui/icons-material/Folder';
import HomeIcon from '@mui/icons-material/Home';
import { isDarkMode } from './DarkMode';
import IconButton from '@mui/material/IconButton';
function pathConcat(l: string, r: string): string
{
if (l.length === 0) return r;
if (r.length === 0) return l;
return l +'/' + r;
}
class DirectoryTree {
name: string = "";
path: string = "";
expanded: boolean = false;
children: DirectoryTree[] = [];
constructor(tree: FilePropertyDirectoryTree, parentTree: (DirectoryTree | null) = null) {
this.name = tree.directoryName;
if (parentTree) {
this.path = pathConcat(parentTree.path,tree.directoryName);
} else {
this.name = "Home";
this.path = tree.directoryName;
this.expanded = true;
}
for (var treeChild of tree.children) {
this.children.push(new DirectoryTree(treeChild, this));
}
}
canExpand(): boolean {
return this.children.length !== 0;
}
expand(path: string): void {
this.expanded = true;
let currentNode: DirectoryTree = this;
for (var segment of path.split('/')) {
let found = false;
for (var child of currentNode.children) {
if (child.name === segment) {
found = true;
if (child.children.length !== 0) {
child.expanded = true;
}
currentNode = child;
break;
}
}
if (!found) {
break;
}
}
}
private static remove_(directoryTree: DirectoryTree, path: string): boolean
{
for (let i = 0; i < directoryTree.children.length; ++i)
{
let child = directoryTree.children[i];
if (child.path === path)
{
directoryTree.children.splice(i,1)
return true;
}
if (DirectoryTree.remove_(child,path))
{
return true;
}
}
return false;
}
remove(path: string): boolean
{
return DirectoryTree.remove_(this,path);
}
find(path: string): DirectoryTree | null {
let currentNode: DirectoryTree = this;
for (var segment of path.split('/')) {
let found = false;
for (var child of currentNode.children) {
if (child.name === segment) {
found = true;
currentNode = child;
break;
}
}
if (!found) {
return null;
}
}
return currentNode;
}
}
export interface FilePropertyDirectorySelectDialogProps {
open: boolean,
uiFileProperty: UiFileProperty;
defaultPath: string,
excludeDirectory: string,
onOk: (path: string) => void,
onClose: () => void
};
export interface FilePropertyDirectorySelectDialogState {
fullScreen: boolean;
selectedPath: string;
directoryTree?: DirectoryTree;
hasSelection: boolean;
directoryTreeInvalidatecount: number;
};
export default class FilePropertyDirectorySelectDialog extends ResizeResponsiveComponent<FilePropertyDirectorySelectDialogProps, FilePropertyDirectorySelectDialogState> {
private model: PiPedalModel;
private refSelected: React.Ref<HTMLElement>;
constructor(props: FilePropertyDirectorySelectDialogProps) {
super(props);
this.model = PiPedalModelFactory.getInstance();
this.state = {
fullScreen: false,
selectedPath: props.defaultPath,
directoryTree: undefined,
hasSelection: false,
directoryTreeInvalidatecount: 0
};
this.refSelected = React.createRef<HTMLElement>();
this.requestDirectoryTree();
}
mounted: boolean = false;
onWindowSizeChanged(width: number, height: number): void {
this.setState({ fullScreen: height < 200 })
}
componentDidMount() {
super.componentDidMount();
this.mounted = true;
}
componentWillUnmount() {
super.componentWillUnmount();
this.mounted = false;
}
private requestScroll = true;
requestDirectoryTree() {
if (!this.props.open) return;
this.model.getFilePropertyDirectoryTree(this.props.uiFileProperty)
.then((filePropertyDirectoryTree) => {
let myTree = new DirectoryTree(filePropertyDirectoryTree);
if (this.props.excludeDirectory)
{
myTree.remove(this.props.excludeDirectory);
}
myTree.expand(this.state.selectedPath);
let hasSelection = myTree.find(this.state.selectedPath) != null;
this.setState({ directoryTree: myTree, hasSelection: hasSelection });
this.requestScroll = true;
})
.catch((e) => {
this.model.showAlert(e.toString());
this.setState({ hasSelection: false });
});
}
componentDidUpdate(prevProps: Readonly<FilePropertyDirectorySelectDialogProps>, prevState: Readonly<FilePropertyDirectorySelectDialogState>, snapshot: any): void {
super.componentDidUpdate?.(prevProps, prevState, snapshot);
if (prevProps.open !== this.props.open) {
if (this.props.open) {
this.setState({ selectedPath: this.props.defaultPath, hasSelection: false });
this.requestDirectoryTree();
this.requestScroll = true;
}
}
}
onOK() {
if (this.state.hasSelection) {
this.props.onOk(this.state.selectedPath);
}
}
onClose() {
this.props.onClose();
}
private onToggleExpand(directoryTree: DirectoryTree)
{
directoryTree.expanded = !directoryTree.expanded;
this.setState({directoryTreeInvalidatecount: this.state.directoryTreeInvalidatecount+1});
}
private onTreeClick(directoryTree: DirectoryTree) {
if (!this.state.directoryTree) return;
this.state.directoryTree.expand(directoryTree.path);
this.setState({ selectedPath: directoryTree.path, hasSelection: true, directoryTreeInvalidatecount: this.state.directoryTreeInvalidatecount + 1 });
}
private renderTree_(directoryTree: DirectoryTree) {
let ref: ((element: HTMLButtonElement | null) => void) | undefined = undefined;
let selected = directoryTree.path === this.state.selectedPath;
if (selected) {
ref = (element) => {
if (this.requestScroll) {
this.requestScroll = false;
}
}
}
let selectBg = selected ? "rgba(0,0,0,0.15)" : "rgba(0,0,0,0.0)";
if (isDarkMode()) {
selectBg = selected ? "rgba(255,255,255,0.10)" : "rgba(0,0,0,0.0)";
}
let showToggle = directoryTree.canExpand() && directoryTree.path.length !== 0;
return (
<div key={directoryTree.path} style={{flexGrow: 1}}>
<div style={{ width: "100%", display: "flex", flexFlow: "row", flexWrap: "nowrap", justifyContent: "flex-start", alignItems: "center" }}>
<IconButton onClick={()=>{ this.onToggleExpand(directoryTree); }}
style={{opacity: showToggle ? 1: 0}}
disabled={!showToggle}
>
{
directoryTree.expanded &&
(
<ArrowDropDownIcon />
)
}
{
!directoryTree.expanded &&
(
<ArrowRightIcon/>
)
}
</IconButton>
<ButtonBase ref={ref} style={{ flexGrow: 1, flexShrink: 1, position: "relative" }} onClick={() => { this.onTreeClick(directoryTree); }}>
<div style={{ position: "absolute", background: selectBg, width: "100%", height: "100%", borderRadius: 4 }} />
<div style={{ width: "100%", display: "flex", flexFlow: "row", flexWrap: "nowrap", justifyContent: "flex-start", alignItems: "center", paddingLeft: 8 }}>
{
directoryTree.path === "" ? (
<HomeIcon fontSize="small" />
) : (
<FolderIcon />
)
}
<Typography noWrap style={{ marginLeft: 8, marginTop: 8, marginBottom: 8, textAlign: "left", flexGrow: 1, flexShrink: 1 }} variant="body2">{directoryTree.name === "" ? "Home" : directoryTree.name}</Typography>
</div>
</ButtonBase>
</div>
{directoryTree.expanded
&& directoryTree.canExpand()
&& (
<div style={{ marginLeft: 32 }}>
{
directoryTree.children.map(
(child, index) => {
return this.renderTree_(child);
}
)
}
</div>
)
}
</div>
);
}
private renderTree() {
if (!this.state.directoryTree) { return undefined; }
return this.renderTree_(this.state.directoryTree);
}
render() {
return (
<DialogEx tag="fpDirectorySelect" open={this.props.open} fullWidth onClose={() => { this.onClose(); }} aria-labelledby="Rename-dialog-title"
fullScreen={this.state.fullScreen}
style={{ userSelect: "none" }}
PaperProps={{ style: { minHeight: "80%", maxHeight: "80%", minWidth: "75%", maxWidth: "75%", overflowY: "visible" } }}
>
<DialogTitle>
<Typography variant="body1">Select folder</Typography>
</DialogTitle>
<Divider />
<DialogContent style={{marginLeft: 0, paddingLeft: 0}} >
<div style={{ display: "flex", flexGrow: 1, flexShrink: 1, overflowY: "auto" }} >
{
this.renderTree()
}
</div>
</DialogContent>
<Divider />
<DialogActions>
<Button onClick={() => { this.onClose(); }} color="primary">
Cancel
</Button>
<Button onClick={() => { this.onOK(); }} color="secondary" disabled={!this.state.hasSelection} >
OK
</Button>
</DialogActions>
</DialogEx>
);
}
}
+39
View File
@@ -0,0 +1,39 @@
// Copyright (c) 2024 Robin Davies
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
export default class FilePropertyDirectoryTree {
deserialize(input: any) : FilePropertyDirectoryTree {
this.directoryName = input.directoryName;
this.children = FilePropertyDirectoryTree.deserialize_array(input.children);
return this;
}
static deserialize_array(input: any): FilePropertyDirectoryTree[] {
let result: FilePropertyDirectoryTree[] = [];
for (let i = 0; i < input.length; ++i)
{
result[i] = new FilePropertyDirectoryTree().deserialize(input[i]);
}
return result;
}
directoryName: string = "";
children: FilePropertyDirectoryTree[] = [];
}
+27 -4
View File
@@ -39,6 +39,7 @@ import WifiChannel from './WifiChannel';
import AlsaDeviceInfo from './AlsaDeviceInfo';
import { AndroidHostInterface, FakeAndroidHost } from './AndroidHost';
import {ColorTheme, getColorScheme,setColorScheme} from './DarkMode';
import FilePropertyDirectoryTree from './FilePropertyDirectoryTree';
export enum State {
@@ -657,6 +658,11 @@ export class PiPedalModel //implements PiPedalModel
}
onSocketConnectionLost() {
// remove all the events and subscriptions we have.
// yyy
this.vuSubscriptions = [];
this.monitorPatchPropertyListeners = [];
if (this.isAndroidHosted()) {
this.androidHost?.setDisconnected(true);
}
@@ -922,6 +928,7 @@ export class PiPedalModel //implements PiPedalModel
// MUST not allow reconnect until at least one complete load has finished.
this.webSocket.canReconnect = true;
}
this.setState(State.Ready);
return true;
})
.catch((error) => {
@@ -2064,10 +2071,10 @@ export class PiPedalModel //implements PiPedalModel
for (let i = 0; i < this.monitorPatchPropertyListeners.length; ++i) {
if (this.monitorPatchPropertyListeners[i].handle === listenHandle._handle) {
this.monitorPatchPropertyListeners.splice(i, 1);
this.webSocket?.send("cancelMonitorPatchProperty", listenHandle._handle);
break;
}
}
this.webSocket?.send("cancelMonitorPatchProperty", listenHandle._handle);
}
@@ -2300,7 +2307,24 @@ export class PiPedalModel //implements PiPedalModel
});
}
renameSampleFile(oldRelativePath: string, newRelativePath: string, uiFileProperty: UiFileProperty) : Promise<string>
getFilePropertyDirectoryTree(uiFileProperty: UiFileProperty) : Promise<FilePropertyDirectoryTree> {
return new Promise<FilePropertyDirectoryTree>((resolve, reject) => {
let ws = this.webSocket;
if (!ws) {
resolve(new FilePropertyDirectoryTree());
return;
}
ws.request<FilePropertyDirectoryTree>(
"getFilePropertyDirectoryTree",
uiFileProperty
).then((result)=> {
resolve(new FilePropertyDirectoryTree().deserialize(result));
}).catch((e) => {
reject(e);
});
});
}
renameFilePropertyFile(oldRelativePath: string, newRelativePath: string, uiFileProperty: UiFileProperty) : Promise<string>
{
return new Promise<string>((resolve, reject) => {
@@ -2310,7 +2334,7 @@ export class PiPedalModel //implements PiPedalModel
return;
}
ws.request<string>(
"renameSampleFile",
"renameFilePropertyFile",
{
oldRelativePath: oldRelativePath,
newRelativePath: newRelativePath,
@@ -2428,7 +2452,6 @@ export class PiPedalModel //implements PiPedalModel
.catch((err) => {
//resolve();
});
// yyy
resolve();
});