mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
Search Fixes (#84)
This change: - now clears the search box when entering a new directory - fixes some styling issues - adds a .. to the path - uses the correct path (except on the initial start of the directory widget)
This commit is contained in:
parent
76c909114e
commit
23e1c8797d
@ -1,8 +1,6 @@
|
|||||||
// Copyright 2024, Command Line Inc.
|
// Copyright 2024, Command Line Inc.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { getBackendHostPort } from "@/app/store/global";
|
|
||||||
import * as keyutil from "@/util/keyutil";
|
|
||||||
import * as electron from "electron";
|
import * as electron from "electron";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import * as child_process from "node:child_process";
|
import * as child_process from "node:child_process";
|
||||||
@ -10,7 +8,9 @@ import os from "os";
|
|||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as readline from "readline";
|
import * as readline from "readline";
|
||||||
import { debounce } from "throttle-debounce";
|
import { debounce } from "throttle-debounce";
|
||||||
|
import { getBackendHostPort } from "../frontend/app/store/global";
|
||||||
import * as services from "../frontend/app/store/services";
|
import * as services from "../frontend/app/store/services";
|
||||||
|
import * as keyutil from "../frontend/util/keyutil";
|
||||||
|
|
||||||
const electronApp = electron.app;
|
const electronApp = electron.app;
|
||||||
const isDev = process.env.WAVETERM_DEV;
|
const isDev = process.env.WAVETERM_DEV;
|
||||||
|
@ -51,11 +51,31 @@
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
&.focused {
|
&.focused {
|
||||||
background-color: var(--accent-color);
|
background-color: rgb(from var(--accent-color) r g b / 0.7);
|
||||||
|
color: var(--main-text-color);
|
||||||
|
|
||||||
|
.dir-table-body-cell {
|
||||||
|
.dir-table-lastmod,
|
||||||
|
.dir-table-modestr,
|
||||||
|
.dir-table-size,
|
||||||
|
.dir-table-type {
|
||||||
|
color: var(--main-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: var(--accent-color);
|
background-color: rgb(from var(--accent-color) r g b / 0.7);
|
||||||
|
color: var(--main-text-color);
|
||||||
|
|
||||||
|
.dir-table-body-cell {
|
||||||
|
.dir-table-lastmod,
|
||||||
|
.dir-table-modestr,
|
||||||
|
.dir-table-size,
|
||||||
|
.dir-table-type {
|
||||||
|
color: var(--main-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover:not(:focus):not(.focused) {
|
&:hover:not(:focus):not(.focused) {
|
||||||
|
@ -26,6 +26,7 @@ interface DirectoryTableProps {
|
|||||||
enter: boolean;
|
enter: boolean;
|
||||||
setFocusIndex: (_: number) => void;
|
setFocusIndex: (_: number) => void;
|
||||||
setFileName: (_: string) => void;
|
setFileName: (_: string) => void;
|
||||||
|
setSearch: (_: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<FileInfo>();
|
const columnHelper = createColumnHelper<FileInfo>();
|
||||||
@ -154,7 +155,7 @@ function cleanMimetype(input: string): string {
|
|||||||
return truncated.trim();
|
return truncated.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function DirectoryTable({ data, cwd, focusIndex, enter, setFocusIndex, setFileName }: DirectoryTableProps) {
|
function DirectoryTable({ data, cwd, focusIndex, enter, setFocusIndex, setFileName, setSearch }: DirectoryTableProps) {
|
||||||
let settings = jotai.useAtomValue(atoms.settingsConfigAtom);
|
let settings = jotai.useAtomValue(atoms.settingsConfigAtom);
|
||||||
const getIconFromMimeType = React.useCallback(
|
const getIconFromMimeType = React.useCallback(
|
||||||
(mimeType: string): string => {
|
(mimeType: string): string => {
|
||||||
@ -190,8 +191,8 @@ function DirectoryTable({ data, cwd, focusIndex, enter, setFocusIndex, setFileNa
|
|||||||
size: 25,
|
size: 25,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor("path", {
|
columnHelper.accessor("name", {
|
||||||
cell: (info) => <span className="dir-table-path">{info.getValue()}</span>,
|
cell: (info) => <span className="dir-table-name">{info.getValue()}</span>,
|
||||||
header: () => <span>Name</span>,
|
header: () => <span>Name</span>,
|
||||||
sortingFn: "alphanumeric",
|
sortingFn: "alphanumeric",
|
||||||
}),
|
}),
|
||||||
@ -222,6 +223,7 @@ function DirectoryTable({ data, cwd, focusIndex, enter, setFocusIndex, setFileNa
|
|||||||
header: () => <span>Type</span>,
|
header: () => <span>Type</span>,
|
||||||
sortingFn: "alphanumeric",
|
sortingFn: "alphanumeric",
|
||||||
}),
|
}),
|
||||||
|
columnHelper.accessor("path", {}),
|
||||||
],
|
],
|
||||||
[settings]
|
[settings]
|
||||||
);
|
);
|
||||||
@ -232,13 +234,17 @@ function DirectoryTable({ data, cwd, focusIndex, enter, setFocusIndex, setFileNa
|
|||||||
columnResizeMode: "onChange",
|
columnResizeMode: "onChange",
|
||||||
getSortedRowModel: getSortedRowModel(),
|
getSortedRowModel: getSortedRowModel(),
|
||||||
getCoreRowModel: getCoreRowModel(),
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
|
||||||
initialState: {
|
initialState: {
|
||||||
sorting: [
|
sorting: [
|
||||||
{
|
{
|
||||||
id: "path",
|
id: "name",
|
||||||
desc: false,
|
desc: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
columnVisibility: {
|
||||||
|
path: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
enableMultiSort: false,
|
enableMultiSort: false,
|
||||||
enableSortingRemoval: false,
|
enableSortingRemoval: false,
|
||||||
@ -289,6 +295,7 @@ function DirectoryTable({ data, cwd, focusIndex, enter, setFocusIndex, setFileNa
|
|||||||
enter={enter}
|
enter={enter}
|
||||||
setFileName={setFileName}
|
setFileName={setFileName}
|
||||||
setFocusIndex={setFocusIndex}
|
setFocusIndex={setFocusIndex}
|
||||||
|
setSearch={setSearch}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<TableBody
|
<TableBody
|
||||||
@ -298,6 +305,7 @@ function DirectoryTable({ data, cwd, focusIndex, enter, setFocusIndex, setFileNa
|
|||||||
enter={enter}
|
enter={enter}
|
||||||
setFileName={setFileName}
|
setFileName={setFileName}
|
||||||
setFocusIndex={setFocusIndex}
|
setFocusIndex={setFocusIndex}
|
||||||
|
setSearch={setSearch}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -311,16 +319,17 @@ interface TableBodyProps {
|
|||||||
enter: boolean;
|
enter: boolean;
|
||||||
setFocusIndex: (_: number) => void;
|
setFocusIndex: (_: number) => void;
|
||||||
setFileName: (_: string) => void;
|
setFileName: (_: string) => void;
|
||||||
|
setSearch: (_: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableBody({ table, cwd, focusIndex, enter, setFocusIndex, setFileName }: TableBodyProps) {
|
function TableBody({ table, cwd, focusIndex, enter, setFocusIndex, setFileName, setSearch }: TableBodyProps) {
|
||||||
let [refresh, setRefresh] = React.useState(false);
|
let [refresh, setRefresh] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const selected = (table.getSortedRowModel()?.flatRows[focusIndex]?.getValue("path") as string) ?? null;
|
const selected = (table.getSortedRowModel()?.flatRows[focusIndex]?.getValue("path") as string) ?? null;
|
||||||
if (selected != null) {
|
if (selected != null) {
|
||||||
const fullPath = cwd.concat("/", selected);
|
setFileName(selected);
|
||||||
setFileName(fullPath);
|
setSearch("");
|
||||||
}
|
}
|
||||||
}, [enter]);
|
}, [enter]);
|
||||||
|
|
||||||
@ -333,11 +342,11 @@ function TableBody({ table, cwd, focusIndex, enter, setFocusIndex, setFileName }
|
|||||||
key={row.id}
|
key={row.id}
|
||||||
onDoubleClick={() => {
|
onDoubleClick={() => {
|
||||||
const newFileName = row.getValue("path") as string;
|
const newFileName = row.getValue("path") as string;
|
||||||
const fullPath = cwd.concat("/", newFileName);
|
setFileName(newFileName);
|
||||||
setFileName(fullPath);
|
setSearch("");
|
||||||
}}
|
}}
|
||||||
onClick={() => setFocusIndex(idx)}
|
onClick={() => setFocusIndex(idx)}
|
||||||
onContextMenu={(e) => handleFileContextMenu(e, cwd.concat("/", row.getValue("path") as string))}
|
onContextMenu={(e) => handleFileContextMenu(e, row.getValue("path") as string)}
|
||||||
>
|
>
|
||||||
{row.getVisibleCells().map((cell) => {
|
{row.getVisibleCells().map((cell) => {
|
||||||
return (
|
return (
|
||||||
@ -378,7 +387,7 @@ function DirectoryPreview({ fileNameAtom }: DirectoryPreviewProps) {
|
|||||||
const serializedContent = util.base64ToString(file?.data64);
|
const serializedContent = util.base64ToString(file?.data64);
|
||||||
let content: FileInfo[] = JSON.parse(serializedContent);
|
let content: FileInfo[] = JSON.parse(serializedContent);
|
||||||
let filtered = content.filter((fileInfo) => {
|
let filtered = content.filter((fileInfo) => {
|
||||||
return fileInfo.path.toLowerCase().includes(searchText);
|
return fileInfo.name.toLowerCase().includes(searchText);
|
||||||
});
|
});
|
||||||
setContent(filtered);
|
setContent(filtered);
|
||||||
};
|
};
|
||||||
@ -432,6 +441,7 @@ function DirectoryPreview({ fileNameAtom }: DirectoryPreviewProps) {
|
|||||||
onChange={(e) => setSearchText(e.target.value.toLowerCase())}
|
onChange={(e) => setSearchText(e.target.value.toLowerCase())}
|
||||||
maxLength={400}
|
maxLength={400}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
|
value={searchText}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<DirectoryTable
|
<DirectoryTable
|
||||||
@ -441,6 +451,7 @@ function DirectoryPreview({ fileNameAtom }: DirectoryPreviewProps) {
|
|||||||
enter={enter}
|
enter={enter}
|
||||||
setFileName={setFileName}
|
setFileName={setFileName}
|
||||||
setFocusIndex={setFocusIndex}
|
setFocusIndex={setFocusIndex}
|
||||||
|
setSearch={setSearchText}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
3
frontend/types/gotypes.d.ts
vendored
3
frontend/types/gotypes.d.ts
vendored
@ -61,7 +61,7 @@ declare global {
|
|||||||
|
|
||||||
// wshutil.BlockInputCommand
|
// wshutil.BlockInputCommand
|
||||||
type BlockInputCommand = {
|
type BlockInputCommand = {
|
||||||
blockid?: string;
|
blockid: string;
|
||||||
command: "controller:input";
|
command: "controller:input";
|
||||||
inputdata64?: string;
|
inputdata64?: string;
|
||||||
signame?: string;
|
signame?: string;
|
||||||
@ -139,6 +139,7 @@ declare global {
|
|||||||
// fileservice.FileInfo
|
// fileservice.FileInfo
|
||||||
type FileInfo = {
|
type FileInfo = {
|
||||||
path: string;
|
path: string;
|
||||||
|
name: string;
|
||||||
notfound?: boolean;
|
notfound?: boolean;
|
||||||
size: number;
|
size: number;
|
||||||
mode: number;
|
mode: number;
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
@ -25,6 +26,7 @@ type FileService struct{}
|
|||||||
|
|
||||||
type FileInfo struct {
|
type FileInfo struct {
|
||||||
Path string `json:"path"` // cleaned path
|
Path string `json:"path"` // cleaned path
|
||||||
|
Name string `json:"name"`
|
||||||
NotFound bool `json:"notfound,omitempty"`
|
NotFound bool `json:"notfound,omitempty"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
Mode os.FileMode `json:"mode"`
|
Mode os.FileMode `json:"mode"`
|
||||||
@ -51,6 +53,7 @@ func (fs *FileService) StatFile(path string) (*FileInfo, error) {
|
|||||||
mimeType := utilfn.DetectMimeType(cleanedPath)
|
mimeType := utilfn.DetectMimeType(cleanedPath)
|
||||||
return &FileInfo{
|
return &FileInfo{
|
||||||
Path: cleanedPath,
|
Path: cleanedPath,
|
||||||
|
Name: finfo.Name(),
|
||||||
Size: finfo.Size(),
|
Size: finfo.Size(),
|
||||||
Mode: finfo.Mode(),
|
Mode: finfo.Mode(),
|
||||||
ModeStr: finfo.Mode().String(),
|
ModeStr: finfo.Mode().String(),
|
||||||
@ -80,6 +83,13 @@ func (fs *FileService) ReadFile(path string) (*FullFile, error) {
|
|||||||
innerFilesEntries = innerFilesEntries[:1000]
|
innerFilesEntries = innerFilesEntries[:1000]
|
||||||
}
|
}
|
||||||
var innerFilesInfo []FileInfo
|
var innerFilesInfo []FileInfo
|
||||||
|
parent := filepath.Dir(finfo.Path)
|
||||||
|
parentFileInfo, err := fs.StatFile(parent)
|
||||||
|
if err == nil && parent != finfo.Path {
|
||||||
|
log.Printf("adding parent")
|
||||||
|
parentFileInfo.Name = ".."
|
||||||
|
innerFilesInfo = append(innerFilesInfo, *parentFileInfo)
|
||||||
|
}
|
||||||
for _, innerFileEntry := range innerFilesEntries {
|
for _, innerFileEntry := range innerFilesEntries {
|
||||||
innerFileInfoInt, _ := innerFileEntry.Info()
|
innerFileInfoInt, _ := innerFileEntry.Info()
|
||||||
mimeType := utilfn.DetectMimeType(filepath.Join(finfo.Path, innerFileInfoInt.Name()))
|
mimeType := utilfn.DetectMimeType(filepath.Join(finfo.Path, innerFileInfoInt.Name()))
|
||||||
@ -90,7 +100,8 @@ func (fs *FileService) ReadFile(path string) (*FullFile, error) {
|
|||||||
fileSize = innerFileInfoInt.Size()
|
fileSize = innerFileInfoInt.Size()
|
||||||
}
|
}
|
||||||
innerFileInfo := FileInfo{
|
innerFileInfo := FileInfo{
|
||||||
Path: innerFileInfoInt.Name(),
|
Path: filepath.Join(finfo.Path, innerFileInfoInt.Name()),
|
||||||
|
Name: innerFileInfoInt.Name(),
|
||||||
Size: fileSize,
|
Size: fileSize,
|
||||||
Mode: innerFileInfoInt.Mode(),
|
Mode: innerFileInfoInt.Mode(),
|
||||||
ModeStr: innerFileInfoInt.Mode().String(),
|
ModeStr: innerFileInfoInt.Mode().String(),
|
||||||
|
@ -68,7 +68,7 @@ func getSettingsConfigDefaults() SettingsConfigType {
|
|||||||
"audio": {Icon: "file-audio"},
|
"audio": {Icon: "file-audio"},
|
||||||
"application/pdf": {Icon: "file-pdf"},
|
"application/pdf": {Icon: "file-pdf"},
|
||||||
"application/json": {Icon: "file-lines"},
|
"application/json": {Icon: "file-lines"},
|
||||||
"directory": {Icon: "folder", Color: "#2e62d2"},
|
"directory": {Icon: "folder", Color: "var(--term-bright-blue)"},
|
||||||
"font": {Icon: "book-font"},
|
"font": {Icon: "book-font"},
|
||||||
"image": {Icon: "file-image"},
|
"image": {Icon: "file-image"},
|
||||||
"text": {Icon: "file-lines"},
|
"text": {Icon: "file-lines"},
|
||||||
|
Loading…
Reference in New Issue
Block a user