mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-12-16 09:06:23 +00:00
Update AppImage
This commit is contained in:
@@ -14,9 +14,8 @@ import {
|
|||||||
Lightbulb,
|
Lightbulb,
|
||||||
Terminal,
|
Terminal,
|
||||||
Plus,
|
Plus,
|
||||||
LayoutGrid,
|
Split,
|
||||||
Columns,
|
Grid2X2,
|
||||||
Rows,
|
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
@@ -170,12 +169,8 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setIsSearching(true)
|
setIsSearching(true)
|
||||||
setUseOnline(true)
|
|
||||||
|
|
||||||
// Format query: replace spaces with + for cheat.sh API
|
|
||||||
const formattedQuery = query.trim().replace(/\s+/g, "+")
|
const formattedQuery = query.trim().replace(/\s+/g, "+")
|
||||||
|
|
||||||
// Use ?QT options: Q=no comments (code only), T=no syntax highlighting
|
|
||||||
const url = `https://cht.sh/${formattedQuery}?QT`
|
const url = `https://cht.sh/${formattedQuery}?QT`
|
||||||
|
|
||||||
console.log("[v0] Fetching from cheat.sh:", url)
|
console.log("[v0] Fetching from cheat.sh:", url)
|
||||||
@@ -183,7 +178,7 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
|||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
signal: AbortSignal.timeout(10000),
|
signal: AbortSignal.timeout(10000),
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": "curl/7.68.0", // cheat.sh works better with curl user agent
|
"User-Agent": "curl/7.68.0",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -199,15 +194,13 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
|||||||
throw new Error("No results found")
|
throw new Error("No results found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split by double newlines to get separate examples
|
|
||||||
const blocks = text.split(/\n\s*\n/).filter((block) => block.trim())
|
const blocks = text.split(/\n\s*\n/).filter((block) => block.trim())
|
||||||
const examples: string[] = []
|
const examples: string[] = []
|
||||||
|
|
||||||
for (const block of blocks) {
|
for (const block of blocks) {
|
||||||
const lines = block.split("\n").filter((line) => {
|
const lines = block.split("\n").filter((line) => {
|
||||||
const trimmed = line.trim()
|
const trimmed = line.trim()
|
||||||
// Filter out URLs, metadata, and empty lines
|
return trimmed && !trimmed.startsWith("http") && !trimmed.includes("cheat.sh") && !trimmed.includes("[")
|
||||||
return trimmed && !trimmed.startsWith("http") && !trimmed.includes("cheat.sh") && !trimmed.includes("[") // Remove attribution lines like [user] [source]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (lines.length > 0) {
|
if (lines.length > 0) {
|
||||||
@@ -221,11 +214,12 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
|||||||
console.log("[v0] Parsed examples:", examples.length)
|
console.log("[v0] Parsed examples:", examples.length)
|
||||||
|
|
||||||
if (examples.length > 0) {
|
if (examples.length > 0) {
|
||||||
|
setUseOnline(true)
|
||||||
setSearchResults([
|
setSearchResults([
|
||||||
{
|
{
|
||||||
command: query,
|
command: query,
|
||||||
description: `Results from cheat.sh for "${query}"`,
|
description: `Results from cheat.sh for "${query}"`,
|
||||||
examples: examples.slice(0, 8), // Show up to 8 examples
|
examples: examples.slice(0, 8),
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
@@ -247,13 +241,15 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
|||||||
}
|
}
|
||||||
|
|
||||||
const debounce = setTimeout(() => {
|
const debounce = setTimeout(() => {
|
||||||
if (searchQuery) {
|
if (searchQuery && searchQuery.length >= 2) {
|
||||||
|
// Only search if query is at least 2 characters
|
||||||
searchCheatSh(searchQuery)
|
searchCheatSh(searchQuery)
|
||||||
} else {
|
} else {
|
||||||
setSearchResults([])
|
setSearchResults([])
|
||||||
setFilteredCommands(proxmoxCommands)
|
setFilteredCommands(proxmoxCommands)
|
||||||
|
setUseOnline(true) // Reset to online when query is cleared
|
||||||
}
|
}
|
||||||
}, 500)
|
}, 800) // Increased debounce to 800ms to avoid premature requests
|
||||||
|
|
||||||
return () => clearTimeout(debounce)
|
return () => clearTimeout(debounce)
|
||||||
}, [searchQuery])
|
}, [searchQuery])
|
||||||
@@ -486,19 +482,10 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
|||||||
<div className="flex items-center justify-between px-4 py-2 bg-zinc-900 border-b border-zinc-800">
|
<div className="flex items-center justify-between px-4 py-2 bg-zinc-900 border-b border-zinc-800">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Activity className="h-5 w-5 text-blue-500" />
|
<Activity className="h-5 w-5 text-blue-500" />
|
||||||
<Badge
|
<div
|
||||||
variant="outline"
|
className={`w-2 h-2 rounded-full ${activeTerminal?.isConnected ? "bg-green-500" : "bg-red-500"}`}
|
||||||
className={`text-xs ${
|
title={activeTerminal?.isConnected ? "Connected" : "Disconnected"}
|
||||||
activeTerminal?.isConnected
|
></div>
|
||||||
? "border-green-500 text-green-500 bg-green-500/10"
|
|
||||||
: "border-red-500 text-red-500 bg-red-500/10"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`w-1.5 h-1.5 rounded-full mr-1.5 ${activeTerminal?.isConnected ? "bg-green-500" : "bg-red-500"}`}
|
|
||||||
></div>
|
|
||||||
{activeTerminal?.isConnected ? "Connected" : "Disconnected"}
|
|
||||||
</Badge>
|
|
||||||
<span className="text-xs text-zinc-500">{terminals.length} / 4 terminals</span>
|
<span className="text-xs text-zinc-500">{terminals.length} / 4 terminals</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -509,31 +496,26 @@ export const TerminalPanel: React.FC<TerminalPanelProps> = ({ websocketUrl, onCl
|
|||||||
onClick={() => setLayout("vertical")}
|
onClick={() => setLayout("vertical")}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className={`h-8 px-2 ${layout === "vertical" ? "bg-zinc-700" : ""}`}
|
className={`h-8 px-2 ${layout === "vertical" ? "bg-blue-500/20 border-blue-500" : ""}`}
|
||||||
title="Split Vertical"
|
|
||||||
>
|
>
|
||||||
<Columns className="h-4 w-4" />
|
<Split className="h-4 w-4 rotate-90" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setLayout("horizontal")}
|
onClick={() => setLayout("horizontal")}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className={`h-8 px-2 ${layout === "horizontal" ? "bg-zinc-700" : ""}`}
|
className={`h-8 px-2 ${layout === "horizontal" ? "bg-blue-500/20 border-blue-500" : ""}`}
|
||||||
title="Split Horizontal"
|
|
||||||
>
|
>
|
||||||
<Rows className="h-4 w-4" />
|
<Split className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => setLayout("grid")}
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
className={`h-8 px-2 ${layout === "grid" ? "bg-blue-500/20 border-blue-500" : ""}`}
|
||||||
|
>
|
||||||
|
<Grid2X2 className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
{terminals.length >= 3 && (
|
|
||||||
<Button
|
|
||||||
onClick={() => setLayout("grid")}
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
className={`h-8 px-2 ${layout === "grid" ? "bg-zinc-700" : ""}`}
|
|
||||||
title="Grid Layout"
|
|
||||||
>
|
|
||||||
<LayoutGrid className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ def terminal_websocket(ws):
|
|||||||
stdout=slave_fd,
|
stdout=slave_fd,
|
||||||
stderr=slave_fd,
|
stderr=slave_fd,
|
||||||
preexec_fn=os.setsid,
|
preexec_fn=os.setsid,
|
||||||
cwd='/',
|
cwd='/root',
|
||||||
env=dict(os.environ, TERM='xterm-256color', PS1='\\u@\\h:\\w\\$ ')
|
env=dict(os.environ, TERM='xterm-256color', PS1='\\u@\\h:\\w\\$ ')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user