diff --git a/internal/api/dir_list.go b/internal/api/dir_list.go index e33c215a1..6342e6a38 100644 --- a/internal/api/dir_list.go +++ b/internal/api/dir_list.go @@ -4,6 +4,7 @@ import ( "io/fs" "os" "path/filepath" + "strings" "golang.org/x/text/collate" ) @@ -25,13 +26,27 @@ func (s dirLister) Bytes(i int) []byte { // listDir will return the contents of a given directory path as a string slice func listDir(col *collate.Collator, path string) ([]string, error) { var dirPaths []string + dirPath := path + files, err := os.ReadDir(path) if err != nil { - path = filepath.Dir(path) - files, err = os.ReadDir(path) + dirPath = filepath.Dir(path) + dirFiles, err := os.ReadDir(dirPath) if err != nil { return dirPaths, err } + + // Filter dir contents by last path fragment if the dir isn't an exact match + base := strings.ToLower(filepath.Base(path)) + if base != "." && base != string(filepath.Separator) { + for _, file := range dirFiles { + if strings.HasPrefix(strings.ToLower(file.Name()), base) { + files = append(files, file) + } + } + } else { + files = dirFiles + } } if col != nil { @@ -42,7 +57,7 @@ func listDir(col *collate.Collator, path string) ([]string, error) { if !file.IsDir() { continue } - dirPaths = append(dirPaths, filepath.Join(path, file.Name())) + dirPaths = append(dirPaths, filepath.Join(dirPath, file.Name())) } return dirPaths, nil } diff --git a/internal/api/resolver_query_configuration.go b/internal/api/resolver_query_configuration.go index 8ca863688..ec3e33c49 100644 --- a/internal/api/resolver_query_configuration.go +++ b/internal/api/resolver_query_configuration.go @@ -50,7 +50,7 @@ func getDir(path string) string { } func getParent(path string) *string { - isRoot := path[len(path)-1:] == "/" + isRoot := path == "/" if isRoot { return nil } else { diff --git a/ui/v2.5/src/components/List/Filters/PathFilter.tsx b/ui/v2.5/src/components/List/Filters/PathFilter.tsx index 2ac345cc4..b6f965d6b 100644 --- a/ui/v2.5/src/components/List/Filters/PathFilter.tsx +++ b/ui/v2.5/src/components/List/Filters/PathFilter.tsx @@ -37,9 +37,9 @@ export const PathFilter: React.FC = ({ ) : ( onValueChanged(v)} + onChangeDirectory={onValueChanged} collapsible - quoteSpaced + quotePath hideError defaultDirectories={libraryPaths} /> diff --git a/ui/v2.5/src/components/Settings/Tasks/DataManagementTasks.tsx b/ui/v2.5/src/components/Settings/Tasks/DataManagementTasks.tsx index cbcca94a1..57b276726 100644 --- a/ui/v2.5/src/components/Settings/Tasks/DataManagementTasks.tsx +++ b/ui/v2.5/src/components/Settings/Tasks/DataManagementTasks.tsx @@ -106,7 +106,7 @@ const CleanDialog: React.FC = ({ {pathSelection ? ( setCurrentDirectory(v)} + onChangeDirectory={setCurrentDirectory} defaultDirectories={libraryPaths} appendButton={ - - ) : null; + const topDirectory = currentDirectory && parent && ( +
  • + +
  • + ); return ( <> @@ -91,16 +78,16 @@ export const FolderSelect: React.FC = ({ ) => { + onChange={(e) => { setDebounced(e.currentTarget.value); }} value={currentDirectory} spellCheck={false} /> - {appendButton ? ( - {appendButton} - ) : undefined} - {collapsible ? ( + + {appendButton && {appendButton}} + + {collapsible && ( - ) : undefined} - {!data || !data.directory || loading ? ( + )} + + {(loading || error) && ( {loading ? ( - ) : !hideError ? ( - - ) : undefined} + ) : ( + !hideError && + )} - ) : undefined} + )} + {!hideError && error !== undefined && (
    Error: {error.message}
    )} +
      {topDirectory} - {selectableDirectories.map((path) => { - return ( -
    • - -
    • - ); - })} + {selectableDirectories.map((dir) => ( +
    • + +
    • + ))}
    diff --git a/ui/v2.5/src/components/Shared/FolderSelect/FolderSelectDialog.tsx b/ui/v2.5/src/components/Shared/FolderSelect/FolderSelectDialog.tsx index d82b4bc73..8da39d7e1 100644 --- a/ui/v2.5/src/components/Shared/FolderSelect/FolderSelectDialog.tsx +++ b/ui/v2.5/src/components/Shared/FolderSelect/FolderSelectDialog.tsx @@ -23,7 +23,7 @@ export const FolderSelectDialog: React.FC = ({
    setCurrentDirectory(v)} + onChangeDirectory={setCurrentDirectory} />
    diff --git a/ui/v2.5/src/components/Shared/FolderSelect/useDirectoryPaths.ts b/ui/v2.5/src/components/Shared/FolderSelect/useDirectoryPaths.ts new file mode 100644 index 000000000..07a75e85a --- /dev/null +++ b/ui/v2.5/src/components/Shared/FolderSelect/useDirectoryPaths.ts @@ -0,0 +1,16 @@ +import { useRef } from "react"; +import { useDirectory } from "src/core/StashService"; + +export const useDirectoryPaths = (path: string, hideError: boolean) => { + const { data, loading, error } = useDirectory(path); + const prevData = useRef(undefined); + + if (!loading) prevData.current = data; + + const currentData = loading ? prevData.current : data; + const directories = + error && hideError ? [] : currentData?.directory.directories; + const parent = currentData?.directory.parent; + + return { directories, parent, loading, error }; +}; diff --git a/ui/v2.5/src/components/Shared/styles.scss b/ui/v2.5/src/components/Shared/styles.scss index d9645d89c..da6aaa01d 100644 --- a/ui/v2.5/src/components/Shared/styles.scss +++ b/ui/v2.5/src/components/Shared/styles.scss @@ -80,10 +80,9 @@ } } -.folder-list { - margin-top: 0.5rem 0 0 0; - max-height: 30vw; - overflow-x: auto; +// z-index gets set on button groups for some reason +.multi-set .btn-group > button.btn { + z-index: auto; } .folder-item { @@ -92,14 +91,12 @@ } } -// z-index gets set on button groups for some reason -.multi-set .btn-group > button.btn { - z-index: auto; -} - .folder-list { list-style-type: none; margin: 0; + max-height: 30vw; + overflow-x: auto; + padding-bottom: 0.5rem; padding-top: 1rem; &-item { diff --git a/ui/v2.5/src/utils/text.ts b/ui/v2.5/src/utils/text.ts index 44027c120..b604f1aa8 100644 --- a/ui/v2.5/src/utils/text.ts +++ b/ui/v2.5/src/utils/text.ts @@ -455,6 +455,19 @@ const abbreviateCounter = (counter: number = 0) => { }; }; +/* + * Trims quotes if the text has leading/trailing quotes + */ +const stripQuotes = (text: string) => { + if (text.startsWith('"') && text.endsWith('"')) return text.slice(1, -1); + return text; +}; + +/* + * Wraps string in quotes + */ +const addQuotes = (text: string) => `"${text}"`; + const TextUtils = { fileSize, formatFileSizeUnit, @@ -478,6 +491,8 @@ const TextUtils = { formatDateTime, secondsAsTimeString, abbreviateCounter, + stripQuotes, + addQuotes, }; export default TextUtils;