General bug fixes in terminal and file manager and fixed credential errors in production

This commit is contained in:
LukeGus
2025-09-28 23:54:12 -05:00
parent 63e776f183
commit 144171d1fa
15 changed files with 139 additions and 41 deletions
@@ -86,7 +86,9 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
const [currentHost, setCurrentHost] = useState<SSHHost | null>(
initialHost || null,
);
const [currentPath, setCurrentPath] = useState("/");
const [currentPath, setCurrentPath] = useState(
initialHost?.defaultPath || "/"
);
const [files, setFiles] = useState<FileItem[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [sshSessionId, setSshSessionId] = useState<string | null>(null);
@@ -754,8 +756,14 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
await recordRecentFile(file);
const windowCount = Date.now() % 10;
const offsetX = 120 + windowCount * 30;
const offsetY = 120 + windowCount * 30;
const baseOffsetX = 120 + windowCount * 30;
const baseOffsetY = 120 + windowCount * 30;
const maxOffsetX = Math.max(0, window.innerWidth - 800 - 100);
const maxOffsetY = Math.max(0, window.innerHeight - 600 - 100);
const offsetX = Math.min(baseOffsetX, maxOffsetX);
const offsetY = Math.min(baseOffsetY, maxOffsetY);
const windowTitle = file.name;
@@ -332,7 +332,7 @@ export function DraggableWindow({
</div>
<div
className="flex-1 overflow-auto"
className="flex-1 overflow-hidden"
style={{ height: "calc(100% - 40px)" }}
>
{children}
@@ -90,6 +90,7 @@ interface FileViewerProps {
isEditable?: boolean;
onContentChange?: (content: string) => void;
onSave?: (content: string) => void;
onRevert?: () => void;
onDownload?: () => void;
onMediaDimensionsChange?: (dimensions: {
width: number;
@@ -304,6 +305,7 @@ export function FileViewer({
isEditable = false,
onContentChange,
onSave,
onRevert,
onDownload,
onMediaDimensionsChange,
}: FileViewerProps) {
@@ -352,7 +354,12 @@ export function FileViewer({
} else {
setShowLargeFileWarning(false);
}
}, [content, savedContent, fileTypeInfo.type, isLargeFile, forceShowAsText]);
if (fileTypeInfo.type === "image" && file.name.toLowerCase().endsWith('.svg') && content) {
setImageLoading(false);
setImageLoadError(false);
}
}, [content, savedContent, fileTypeInfo.type, isLargeFile, forceShowAsText, file.name]);
const handleContentChange = (newContent: string) => {
setEditedContent(newContent);
@@ -365,9 +372,12 @@ export function FileViewer({
};
const handleRevert = () => {
setEditedContent(savedContent);
setHasChanges(false);
onContentChange?.(savedContent);
if (onRevert) {
onRevert();
} else {
setEditedContent(savedContent);
setHasChanges(false);
}
};
useEffect(() => {
@@ -696,6 +706,16 @@ export function FileViewer({
</Button>
)}
</div>
) : file.name.toLowerCase().endsWith('.svg') ? (
<div
className="max-w-full max-h-full flex items-center justify-center"
style={{ maxHeight: "calc(100vh - 200px)" }}
dangerouslySetInnerHTML={{ __html: content }}
onLoad={() => {
setImageLoading(false);
setImageLoadError(false);
}}
/>
) : (
<PhotoProvider maskOpacity={0.7}>
<PhotoView src={`data:image/*;base64,${content}`}>
@@ -211,6 +211,37 @@ export function FileWindow({
loadFileContent();
}, [file, sshSessionId, sshHost]);
const handleRevert = async () => {
const loadFileContent = async () => {
if (file.type !== "file") return;
try {
setIsLoading(true);
await ensureSSHConnection();
const response = await readSSHFile(sshSessionId, file.path);
const fileContent = response.content || "";
setContent(fileContent);
setPendingContent("");
if (!file.size) {
const contentSize = new Blob([fileContent]).size;
file.size = contentSize;
}
} catch (error: any) {
console.error("Failed to load file content:", error);
toast.error(
`${t("fileManager.failedToLoadFile")}: ${error.message || t("fileManager.unknownError")}`,
);
} finally {
setIsLoading(false);
}
};
loadFileContent();
};
const handleSave = async (newContent: string) => {
try {
setIsLoading(true);
@@ -252,17 +283,20 @@ export function FileWindow({
if (autoSaveTimerRef.current) {
clearTimeout(autoSaveTimerRef.current);
autoSaveTimerRef.current = null;
}
autoSaveTimerRef.current = setTimeout(async () => {
try {
await handleSave(newContent);
toast.success(t("fileManager.fileAutoSaved"));
} catch (error) {
console.error("Auto-save failed:", error);
toast.error(t("fileManager.autoSaveFailed"));
}
}, 60000);
if (newContent !== content) {
autoSaveTimerRef.current = setTimeout(async () => {
try {
await handleSave(newContent);
toast.success(t("fileManager.fileAutoSaved"));
} catch (error) {
console.error("Auto-save failed:", error);
toast.error(t("fileManager.autoSaveFailed"));
}
}, 60000);
}
};
useEffect(() => {
@@ -363,6 +397,7 @@ export function FileWindow({
content={pendingContent || content}
savedContent={content}
isLoading={isLoading}
onRevert={handleRevert}
isEditable={isEditable}
onContentChange={handleContentChange}
onSave={(newContent) => handleSave(newContent)}
@@ -79,7 +79,6 @@ export function TerminalWindow({
minWidth={600}
minHeight={400}
onClose={handleClose}
onMinimize={handleMinimize}
onMaximize={handleMaximize}
onFocus={handleFocus}
isMaximized={currentWindow.isMaximized}
@@ -40,9 +40,15 @@ export function WindowManager({ children }: WindowManagerProps) {
const id = `window-${++windowCounter.current}`;
const zIndex = ++nextZIndex.current;
const offset = (windows.length % 5) * 30;
const adjustedX = windowData.x + offset;
const adjustedY = windowData.y + offset;
const offset = (windows.length % 5) * 20;
let adjustedX = windowData.x + offset;
let adjustedY = windowData.y + offset;
const maxX = Math.max(0, window.innerWidth - windowData.width - 20);
const maxY = Math.max(0, window.innerHeight - windowData.height - 20);
adjustedX = Math.max(20, Math.min(adjustedX, maxX));
adjustedY = Math.max(20, Math.min(adjustedY, maxY));
const newWindow: WindowInstance = {
...windowData,
@@ -75,10 +75,6 @@ export function useFileSelection() {
}, [selectedFiles]);
const setSelection = useCallback((files: FileItem[]) => {
console.log(
"Setting selection to:",
files.map((f) => f.name),
);
setSelectedFiles(files);
}, []);