Skip to content

Feat/theme: update some styles#7

Merged
awsl233777 merged 8 commits intoawsl-project:mainfrom
whhjdi:feat/theme
Jan 13, 2026
Merged

Feat/theme: update some styles#7
awsl233777 merged 8 commits intoawsl-project:mainfrom
whhjdi:feat/theme

Conversation

@whhjdi
Copy link
Contributor

@whhjdi whhjdi commented Jan 13, 2026

No description provided.

whhjdi and others added 6 commits January 13, 2026 13:28
style(console): 优化日志显示样式
style(requests): 调整请求标签样式
style(index): 更新全局样式以支持新间距变量
…iff functionality

- Implemented RequestDetailView component to display request details, including request, response, and metadata tabs.
- Created RequestHeader component for displaying request summary and stats.
- Added RequestSidebar for navigating between main request and upstream attempts.
- Introduced CopyButton and DiffButton components for copying content and viewing differences between client and upstream responses.
- Developed DiffModal for displaying the differences in a user-friendly format.
- Added EmptyState component for handling empty data scenarios.
- Organized components into a dedicated directory for better structure and maintainability.
…nd Sessions pages

- Updated class names for consistent styling in Requests and Retry Configs pages.
- Replaced `flex-shrink-0` with `shrink-0` for better readability.
- Simplified icon class names in RequestStatusBadge for clarity.
- Enhanced readability by formatting JSX elements in Retry Configs and Sessions pages.
- Improved loading and empty state messages for better user experience.
- Refactored event handling and state management in SessionDetailModal for clarity.
- 将 wails_broadcaster.go 拆分为两个文件:
  - wails_broadcaster_desktop.go (//go:build desktop) - 包含 Wails runtime
  - wails_broadcaster_http.go (//go:build !desktop) - 纯转发,无 Wails 依赖
- 更新 wails.json 添加 "tags": "desktop" 确保桌面构建使用正确标签
- 优化前端 Transport 检测:HTTP 模式直接创建 HttpTransport,跳过 Wails 等待
@awsl233777
Copy link
Collaborator

/review

1 similar comment
@awsl233777
Copy link
Collaborator

/review

@github-actions
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Code Complexity

The RequestDetailPage function has become quite large and complex, making it harder to maintain and understand. Consider breaking it into smaller components or functions to improve readability and maintainability.

export function RequestDetailPage() {
  const { id } = useParams<{ id: string }>()
  const navigate = useNavigate()
  const { data: request, isLoading, error } = useProxyRequest(Number(id))
  const { data: attempts } = useProxyUpstreamAttempts(Number(id))
  const { data: providers } = useProviders()
  const { data: projects } = useProjects()
  const { data: sessions } = useSessions()
  const { data: routes } = useRoutes()
  const [selection, setSelection] = useState<SelectionType>({
    type: 'request',
  })
  const [activeTab, setActiveTab] = useState<
    'request' | 'response' | 'metadata'
  >('request')

  useProxyRequestUpdates()

  // ESC 键返回列表
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        navigate('/requests')
      }
    }
    window.addEventListener('keydown', handleKeyDown)
    return () => window.removeEventListener('keydown', handleKeyDown)
  }, [navigate])

  // Create lookup map for provider names
  const providerMap = useMemo(() => {
    const map = new Map<number, string>()
    providers?.forEach(p => {
      map.set(p.id, p.name)
    })
    return map
  }, [providers])

  // Create lookup map for project names
  const projectMap = useMemo(() => {
    const map = new Map<number, string>()
    projects?.forEach(p => {
      map.set(p.id, p.name)
    })
    return map
  }, [projects])

  // Create lookup map for sessions by sessionID
  const sessionMap = useMemo(() => {
    const map = new Map<string, { clientType: string; projectID: number }>()
    sessions?.forEach(s => {
      map.set(s.sessionID, {
        clientType: s.clientType,
        projectID: s.projectID,
      })
    })
    return map
  }, [sessions])

  // Create lookup map for routes by routeID
  const routeMap = useMemo(() => {
    const map = new Map<number, { projectID: number }>()
    routes?.forEach(r => {
      map.set(r.id, { projectID: r.projectID })
    })
    return map
  }, [routes])

  if (isLoading) {
    return (
      <div className="flex h-full items-center justify-center bg-background">
        <Loader2 className="h-8 w-8 animate-spin text-accent" />
      </div>
    )
  }

  if (error || !request) {
    return (
      <div className="flex flex-col items-center justify-center h-full space-y-4 bg-background">
        <div className="p-4 bg-red-400/10 rounded-full">
          <AlertCircle className="h-12 w-12 text-red-400" />
        </div>
        <h3 className="text-lg font-semibold text-text-primary">
          Request Not Found
        </h3>
        <p className="text-sm text-text-secondary">
          The request you're looking for doesn't exist or has been deleted.
        </p>
      </div>
    )
  }

  return (
    <div className="flex flex-col h-screen overflow-hidden bg-background w-full ">
      {/* Header */}
      <RequestHeader request={request} onBack={() => navigate('/requests')} />

      {/* Error Banner */}
      {request.error && (
        <div className="shrink-0 bg-red-400/10 border-b border-red-400/20 px-6 py-3 flex items-start gap-3">
          <AlertCircle className="mt-0.5 h-4 w-4 shrink-0 text-red-400" />
          <div className="flex-1">
            <h4 className="text-sm font-medium text-red-400 mb-1">
              Request Failed
            </h4>
            <pre className="whitespace-pre-wrap wrap-break-words font-mono text-xs text-red-400/90 max-h-24 overflow-auto">
              {request.error}
            </pre>
          </div>
        </div>
      )}

      {/* Main Content - Resizable Split View */}
      <div className="flex-1 overflow-hidden">
        <ResizablePanelGroup direction="horizontal" id="request-detail-layout">
          {/* Left Panel: Sidebar */}
          <ResizablePanel defaultSize={20} minSize={20} maxSize={50}>
            <RequestSidebar
              request={request}
              attempts={attempts}
              selection={selection}
              onSelectionChange={setSelection}
              providerMap={providerMap}
              projectMap={projectMap}
              routeMap={routeMap}
            />
          </ResizablePanel>

          {/* Resizable Handle */}
          <ResizableHandle withHandle />

          {/* Right Panel: Detail View */}
          <ResizablePanel defaultSize={80} minSize={50}>
            <RequestDetailPanel
              request={request}
              selection={selection}
              attempts={attempts}
              activeTab={activeTab}
              setActiveTab={setActiveTab}
              providerMap={providerMap}
              projectMap={projectMap}
              sessionMap={sessionMap}
            />
          </ResizablePanel>
        </ResizablePanelGroup>
      </div>
    </div>
  )
}
Missing Error Handling

The RequestSidebar component does not handle cases where the request or attempts data may be undefined or null. Implement error handling or fallback UI to ensure robustness.

interface RequestSidebarProps {
  request: ProxyRequest
  attempts: ProxyUpstreamAttempt[] | undefined
  selection: SelectionType
  onSelectionChange: (selection: SelectionType) => void
  providerMap: Map<number, string>
  projectMap: Map<number, string>
  routeMap: Map<number, { projectID: number }>
}

export function RequestSidebar({
  request,
  attempts,
  selection,
  onSelectionChange,
  providerMap,
  projectMap,
  routeMap,
}: RequestSidebarProps) {
Potential Performance Issue

The SidebarProvider component adds an event listener for keydown events without proper cleanup in all cases. Ensure that the cleanup function is correctly implemented to avoid memory leaks.

  window.addEventListener('keydown', handleKeyDown)
  return () => window.removeEventListener('keydown', handleKeyDown)
}, [toggleSidebar])

@awsl233777
Copy link
Collaborator

/improve

@github-actions
Copy link
Contributor

github-actions bot commented Jan 13, 2026

PR Code Suggestions ✨

CategorySuggestion                                                                                                                                    Impact
General
Enhance number representation for readability

Consider returning a more user-friendly representation of the number, such as using
a formatted string with commas for thousands, which enhances readability for larger
numbers.

web/src/pages/client-routes/components/provider-row.tsx [34-35]

-+  return count.toString()
++  return count.toLocaleString()
Suggestion importance[1-10]: 7

__

Why: Using toLocaleString() improves the readability of large numbers by adding commas, which is a valuable enhancement for user experience.

Medium
Validate token count formatting

Ensure that the return value is properly formatted for edge cases, such as when
count is negative. Consider adding validation to handle unexpected input gracefully.

web/src/pages/providers/components/provider-row.tsx [24]

 ...
-return `${(count / 1_000_000).toFixed(1)}M`
+return count >= 0 ? `${(count / 1_000_000).toFixed(1)}M` : 'Invalid count'
 ...
Suggestion importance[1-10]: 7

__

Why: The suggestion improves the robustness of the code by handling negative counts, which is a valid concern for input validation.

Medium
Add max-height for scrollable content

Ensure that the overflow-auto class is applied correctly to prevent content overflow
issues. Consider adding a max-height to ensure the content is scrollable if it
exceeds the available space.

web/src/pages/requests/detail/RequestDetailView.tsx [94]

 ...
-<div className="flex-1 rounded-lg border border-border bg-muted/50 dark:bg-muted/30 p-4 overflow-auto shadow-inner relative group min-h-0">
+<div className="flex-1 rounded-lg border border-border bg-muted/50 dark:bg-muted/30 p-4 overflow-auto shadow-inner relative group min-h-0 max-h-[400px]">
 ...
Suggestion importance[1-10]: 6

__

Why: Adding a max-height ensures that the content remains scrollable, improving user experience when dealing with large amounts of data.

Low
Improve number formatting for clarity

Ensure that the returned string is properly formatted for readability. Consider
adding a space between the number and the unit for better clarity, e.g., "1.0 M"
instead of "1.0M".

web/src/pages/client-routes/components/provider-row.tsx [29-30]

-+    return `${(count / 1_000_000).toFixed(1)}M`
++    return `${(count / 1_000_000).toFixed(1)} M`
Suggestion importance[1-10]: 5

__

Why: The suggestion to add a space between the number and the unit improves readability, but it is a minor change that does not significantly impact functionality.

Low
Make header height responsive

Ensure that the height of the header is responsive and does not cause layout shifts
on different screen sizes. Consider using a more flexible height approach.

web/src/pages/requests/detail/RequestHeader.tsx [54]

 ...
-<div className="h-[73px] border-b border-border bg-surface-primary px-6 flex items-center">
+<div className="h-auto min-h-[73px] border-b border-border bg-surface-primary px-6 flex items-center">
 ...
Suggestion importance[1-10]: 5

__

Why: While making the header responsive is beneficial, the impact on layout shifts may be minimal, hence a moderate score.

Low
Possible issue
Initialize selection state correctly

Ensure that the selection state is initialized correctly to avoid potential runtime
errors. Consider adding a default value for attemptId in case the selection type is
'attempt'.

web/src/pages/requests/detail.tsx [36-38]

 const [selection, setSelection] = useState<SelectionType>({
-type: 'request',
+  type: 'request',
+  attemptId: 0, // Default value for attemptId
 })
Suggestion importance[1-10]: 5

__

Why: The suggestion addresses a potential issue with the selection state initialization, but the proposed default value for attemptId may not be appropriate without further context on its expected usage.

Low

@awsl233777 awsl233777 merged commit b1ca7df into awsl-project:main Jan 13, 2026
@whhjdi whhjdi deleted the feat/theme branch January 14, 2026 05:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants