diff --git a/.env b/.env index 3967bc09..27929cde 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -VERSION=1.1 \ No newline at end of file +VERSION=1.1.1 \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 8940ef8c..c4510ae9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import React from "react" import {Homepage} from "@/apps/Homepage/Homepage.tsx" -import {SSH} from "@/apps/SSH/Terminal/SSH.tsx" +import {Terminal} from "@/apps/SSH/Terminal/Terminal.tsx" import {SSHTunnel} from "@/apps/SSH/Tunnel/SSHTunnel.tsx"; import {ConfigEditor} from "@/apps/SSH/Config Editor/ConfigEditor.tsx"; import {SSHManager} from "@/apps/SSH/Manager/SSHManager.tsx" @@ -35,7 +35,7 @@ function App() { )} {mountedViews.has("terminal") && (
- +
)} {mountedViews.has("tunnel") && ( diff --git a/src/apps/Homepage/Homepage.tsx b/src/apps/Homepage/Homepage.tsx index 470168b5..9efe1e67 100644 --- a/src/apps/Homepage/Homepage.tsx +++ b/src/apps/Homepage/Homepage.tsx @@ -3,6 +3,7 @@ import React, {useEffect, useState} from "react"; import {HomepageAuth} from "@/apps/Homepage/HomepageAuth.tsx"; import axios from "axios"; import {HomepageUpdateLog} from "@/apps/Homepage/HompageUpdateLog.tsx"; +import {HomepageWelcomeCard} from "@/apps/Homepage/HomepageWelcomeCard.tsx"; interface HomepageProps { onSelectView: (view: string) => void; @@ -32,9 +33,12 @@ export function Homepage({onSelectView}: HomepageProps): React.ReactElement { const [username, setUsername] = useState(null); const [authLoading, setAuthLoading] = useState(true); const [dbError, setDbError] = useState(null); + const [showWelcomeCard, setShowWelcomeCard] = useState(true); useEffect(() => { const jwt = getCookie("jwt"); + const welcomeHidden = getCookie("welcome_hidden"); + if (jwt) { setAuthLoading(true); Promise.all([ @@ -46,6 +50,7 @@ export function Homepage({onSelectView}: HomepageProps): React.ReactElement { setIsAdmin(!!meRes.data.is_admin); setUsername(meRes.data.username || null); setDbError(null); + setShowWelcomeCard(welcomeHidden !== "true"); }) .catch((err) => { setLoggedIn(false); @@ -64,6 +69,11 @@ export function Homepage({onSelectView}: HomepageProps): React.ReactElement { } }, []); + const handleHideWelcomeCard = () => { + setShowWelcomeCard(false); + setCookie("welcome_hidden", "true", 365 * 10); + }; + return ( + + {loggedIn && !authLoading && showWelcomeCard && ( +
+ +
+ )}
); diff --git a/src/apps/Homepage/HomepageWelcomeCard.tsx b/src/apps/Homepage/HomepageWelcomeCard.tsx new file mode 100644 index 00000000..4ef52ce3 --- /dev/null +++ b/src/apps/Homepage/HomepageWelcomeCard.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import {Card, CardContent, CardFooter, CardHeader, CardTitle} from "@/components/ui/card"; +import {Button} from "@/components/ui/button"; + +interface HomepageWelcomeCardProps { + onHidePermanently: () => void; +} + +export function HomepageWelcomeCard({onHidePermanently}: HomepageWelcomeCardProps): React.ReactElement { + return ( + + + + The Future of Termix + + + +

+ Please checkout the linked survey{" "} + + here + + . The purpose of this survey is to gather feedback from users on what the future UI of Termix could + look like to optimize server management. Please take a minute or two to read the survey questions + and answer them to the best of your ability. Thank you! +

+

+ A special thanks to those in Asia who recently joined Termix through various forum posts, keep + sharing it! A Chinese translation is planned for Termix, but since I don’t speak Chinese, I’ll need + to hire someone to help with the translation. If you’d like to support me financially, you can do + so{" "} + + here. + +

+
+ + + +
+ ); +} diff --git a/src/apps/SSH/Terminal/SSH.tsx b/src/apps/SSH/Terminal/Terminal.tsx similarity index 97% rename from src/apps/SSH/Terminal/SSH.tsx rename to src/apps/SSH/Terminal/Terminal.tsx index 002be4ca..e6e92600 100644 --- a/src/apps/SSH/Terminal/SSH.tsx +++ b/src/apps/SSH/Terminal/Terminal.tsx @@ -1,9 +1,10 @@ import React, {useState, useRef, useEffect} from "react"; -import {SSHSidebar} from "@/apps/SSH/Terminal/SSHSidebar.tsx"; -import {SSHTerminal} from "./SSHTerminal.tsx"; -import {SSHTopbar} from "@/apps/SSH/Terminal/SSHTopbar.tsx"; +import {TerminalSidebar} from "@/apps/SSH/Terminal/TerminalSidebar.tsx"; +import {TerminalComponent} from "./TerminalComponent.tsx"; +import {TerminalTopbar} from "@/apps/SSH/Terminal/TerminalTopbar.tsx"; import {ResizablePanelGroup, ResizablePanel, ResizableHandle} from '@/components/ui/resizable.tsx'; import * as ResizablePrimitive from "react-resizable-panels"; +import {ChevronDown, ChevronRight} from "lucide-react"; interface ConfigEditorProps { onSelectView: (view: string) => void; @@ -16,7 +17,7 @@ type Tab = { terminalRef: React.RefObject; }; -export function SSH({onSelectView}: ConfigEditorProps): React.ReactElement { +export function Terminal({onSelectView}: ConfigEditorProps): React.ReactElement { const [allTabs, setAllTabs] = useState([]); const [currentTab, setCurrentTab] = useState(null); const [allSplitScreenTab, setAllSplitScreenTab] = useState([]); @@ -25,7 +26,7 @@ export function SSH({onSelectView}: ConfigEditorProps): React.ReactElement { const [isSidebarOpen, setIsSidebarOpen] = useState(true); const [isTopbarOpen, setIsTopbarOpen] = useState(true); const SIDEBAR_WIDTH = 256; - const HANDLE_THICKNESS = 6; + const HANDLE_THICKNESS = 10; const [panelRects, setPanelRects] = useState>({}); const panelRefs = useRef>({}); @@ -160,7 +161,7 @@ export function SSH({onSelectView}: ConfigEditorProps): React.ReactElement { const isVisible = !!layoutStyles[tab.id]; return (
- - {/* Sidebar (collapsible) */}
- - + title="Show top bar"> + +
)} - {/* Main terminal area (height adapts to topbar) */}
- {/* Sidebar reopen handle */} {!isSidebarOpen && (
setIsSidebarOpen(true)} @@ -769,9 +771,13 @@ export function SSH({onSelectView}: ConfigEditorProps): React.ReactElement { background: '#222224', cursor: 'pointer', zIndex: 20, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', }} - title="Show sidebar" - /> + title="Show sidebar"> + +
)}
); diff --git a/src/apps/SSH/Terminal/SSHTerminal.tsx b/src/apps/SSH/Terminal/TerminalComponent.tsx similarity index 99% rename from src/apps/SSH/Terminal/SSHTerminal.tsx rename to src/apps/SSH/Terminal/TerminalComponent.tsx index 74089981..c69ac609 100644 --- a/src/apps/SSH/Terminal/SSHTerminal.tsx +++ b/src/apps/SSH/Terminal/TerminalComponent.tsx @@ -13,7 +13,7 @@ interface SSHTerminalProps { splitScreen?: boolean; } -export const SSHTerminal = forwardRef(function SSHTerminal( +export const TerminalComponent = forwardRef(function SSHTerminal( {hostConfig, isVisible, splitScreen = false}, ref ) { diff --git a/src/apps/SSH/Terminal/SSHSidebar.tsx b/src/apps/SSH/Terminal/TerminalSidebar.tsx similarity index 99% rename from src/apps/SSH/Terminal/SSHSidebar.tsx rename to src/apps/SSH/Terminal/TerminalSidebar.tsx index e92dbae5..90318520 100644 --- a/src/apps/SSH/Terminal/SSHSidebar.tsx +++ b/src/apps/SSH/Terminal/TerminalSidebar.tsx @@ -74,7 +74,7 @@ export interface SidebarProps { onOpenChange?: (open: boolean) => void; } -export function SSHSidebar({ +export function TerminalSidebar({ onSelectView, onHostConnect, allTabs, diff --git a/src/apps/SSH/Terminal/SSHTabList.tsx b/src/apps/SSH/Terminal/TerminalTabList.tsx similarity index 98% rename from src/apps/SSH/Terminal/SSHTabList.tsx rename to src/apps/SSH/Terminal/TerminalTabList.tsx index b60bfbb5..2e52d865 100644 --- a/src/apps/SSH/Terminal/SSHTabList.tsx +++ b/src/apps/SSH/Terminal/TerminalTabList.tsx @@ -16,7 +16,7 @@ interface SSHTabListProps { setCloseTab: (tab: number) => void; } -export function SSHTabList({ +export function TerminalTabList({ allTabs, currentTab, setActiveTab, diff --git a/src/apps/SSH/Terminal/SSHTopbar.tsx b/src/apps/SSH/Terminal/TerminalTopbar.tsx similarity index 94% rename from src/apps/SSH/Terminal/SSHTopbar.tsx rename to src/apps/SSH/Terminal/TerminalTopbar.tsx index 30d4c910..036ae622 100644 --- a/src/apps/SSH/Terminal/SSHTopbar.tsx +++ b/src/apps/SSH/Terminal/TerminalTopbar.tsx @@ -1,4 +1,4 @@ -import {SSHTabList} from "@/apps/SSH/Terminal/SSHTabList.tsx"; +import {TerminalTabList} from "@/apps/SSH/Terminal/TerminalTabList.tsx"; import React from "react"; import {ChevronUp} from "lucide-react"; @@ -17,7 +17,7 @@ interface SSHTopbarProps { onHideTopbar?: () => void; } -export function SSHTopbar({ +export function TerminalTopbar({ allTabs, currentTab, setActiveTab, @@ -38,7 +38,7 @@ export function SSHTopbar({ }}>
-