Skip to content

Commit 91fffda

Browse files
committed
Release v0.0.16
## What's New in v0.0.16 ### Improvements & Fixes - Fixed authentication redirect URL for packaged app - Fixed sidebar workspace timestamps updating on message send - Exclude session/plan files from changed files status bar - Reduced stop button icon size in send button
1 parent b011705 commit 91fffda

File tree

10 files changed

+109
-198
lines changed

10 files changed

+109
-198
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "21st-desktop",
3-
"version": "0.0.15",
3+
"version": "0.0.16",
44
"private": true,
55
"description": "1Code - UI for parallel work with AI agents",
66
"author": "21st.dev",

scripts/upload-release-wrangler.sh

Lines changed: 0 additions & 185 deletions
This file was deleted.

src/main/auth-manager.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { AuthStore, AuthData, AuthUser } from "./auth-store"
22
import { app, BrowserWindow } from "electron"
33

4-
// Auth API URL - use env variable for local testing, default to production
5-
const AUTH_API_URL = import.meta.env.MAIN_VITE_API_URL || "https://21st.dev"
4+
// Get API URL - in packaged app always use production, in dev allow override
5+
function getApiBaseUrl(): string {
6+
if (app.isPackaged) {
7+
return "https://21st.dev"
8+
}
9+
return import.meta.env.MAIN_VITE_API_URL || "https://21st.dev"
10+
}
611

712
export class AuthManager {
813
private store: AuthStore
@@ -29,7 +34,7 @@ export class AuthManager {
2934
}
3035

3136
private getApiUrl(): string {
32-
return AUTH_API_URL
37+
return getApiBaseUrl()
3338
}
3439

3540
/**

src/main/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,12 @@ if (app.isPackaged && !IS_DEV) {
5656
}
5757

5858
// URL configuration (exported for use in other modules)
59-
// Uses MAIN_VITE_API_URL from .env if set, otherwise defaults to production
59+
// In packaged app, ALWAYS use production URL to prevent localhost leaking into releases
60+
// In dev mode, allow override via MAIN_VITE_API_URL env variable
6061
export function getBaseUrl(): string {
62+
if (app.isPackaged) {
63+
return "https://21st.dev"
64+
}
6165
return import.meta.env.MAIN_VITE_API_URL || "https://21st.dev"
6266
}
6367

src/main/lib/config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
/**
22
* Shared configuration for the desktop app
33
*/
4+
import { app } from "electron"
45

56
const IS_DEV = !!process.env.ELECTRON_RENDERER_URL
67

78
/**
89
* Get the API base URL
9-
* Uses MAIN_VITE_API_URL from .env if set, otherwise defaults to production
10+
* In packaged app, ALWAYS use production URL to prevent localhost leaking into releases
11+
* In dev mode, allow override via MAIN_VITE_API_URL env variable
1012
*/
1113
export function getApiUrl(): string {
14+
if (app.isPackaged) {
15+
return "https://21st.dev"
16+
}
1217
return import.meta.env.MAIN_VITE_API_URL || "https://21st.dev"
1318
}
1419

src/renderer/contexts/TRPCProvider.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@ interface TRPCProviderProps {
88
children: React.ReactNode
99
}
1010

11+
// Global query client instance for use outside React components
12+
let globalQueryClient: QueryClient | null = null
13+
14+
export function getQueryClient(): QueryClient | null {
15+
return globalQueryClient
16+
}
17+
1118
export function TRPCProvider({ children }: TRPCProviderProps) {
1219
const [queryClient] = useState(() => {
13-
return new QueryClient({
20+
const client = new QueryClient({
1421
defaultOptions: {
1522
queries: {
1623
staleTime: 5000,
@@ -24,6 +31,8 @@ export function TRPCProvider({ children }: TRPCProviderProps) {
2431
},
2532
},
2633
})
34+
globalQueryClient = client
35+
return client
2736
})
2837

2938
const [trpcClient] = useState(() => {

src/renderer/features/agents/components/agent-send-button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export function AgentSendButton({
6363
const getIcon = () => {
6464
if (isStreaming) {
6565
return (
66-
<div className="w-3 h-3 bg-current rounded-[2px] flex-shrink-0 mx-auto" />
66+
<div className="w-2.5 h-2.5 bg-current rounded-[2px] flex-shrink-0 mx-auto" />
6767
)
6868
}
6969
if (isSubmitting) {
@@ -111,7 +111,7 @@ export function AgentSendButton({
111111

112112
// Mode-specific styling (agent=foreground, plan=orange)
113113
const modeClass = isPlanMode
114-
? "!bg-plan-mode hover:!bg-plan-mode/90 !text-plan-mode-foreground !shadow-none"
114+
? "!bg-plan-mode hover:!bg-plan-mode/90 !text-background !shadow-none"
115115
: "!bg-foreground hover:!bg-foreground/90 !text-background !shadow-none"
116116

117117
return (

src/renderer/features/agents/hooks/use-changed-files-tracking.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ export function useChangedFilesTracking(
8989
const wasStreamingRef = useRef(false)
9090
const isInitializedRef = useRef(false)
9191

92+
// Check if a file path is a session/plan file that should be excluded
93+
const isSessionFile = useCallback((filePath: string): boolean => {
94+
// Exclude files in claude-sessions (plan files stored in app's local storage)
95+
if (filePath.includes("claude-sessions")) return true
96+
// Exclude files in Application Support directory
97+
if (filePath.includes("Application Support")) return true
98+
return false
99+
}, [])
100+
92101
// Calculate changed files from messages
93102
const calculateChangedFiles = useCallback(() => {
94103
// Track file states: originalContent (first old_string) and currentContent (latest new_string)
@@ -108,6 +117,9 @@ export function useChangedFilesTracking(
108117
const filePath = part.input?.file_path
109118
if (!filePath) continue
110119

120+
// Skip session/plan files stored in local app storage
121+
if (isSessionFile(filePath)) continue
122+
111123
const oldString = part.input?.old_string || ""
112124
const newString = part.input?.new_string || part.input?.content || ""
113125

@@ -148,7 +160,7 @@ export function useChangedFilesTracking(
148160
}
149161

150162
return result
151-
}, [messages, getDisplayPath, calculateDiffStats])
163+
}, [messages, getDisplayPath, calculateDiffStats, isSessionFile])
152164

153165
// Only recalculate when streaming ends (transition from true to false)
154166
// Also calculate on initial mount if not streaming

src/renderer/features/agents/main/active-chat.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import { soundNotificationsEnabledAtom } from "../../../lib/atoms"
7070
import { appStore } from "../../../lib/jotai-store"
7171
import { api } from "../../../lib/mock-api"
7272
import { trpc, trpcClient } from "../../../lib/trpc"
73+
import { getQueryClient } from "../../../contexts/TRPCProvider"
7374
import { cn } from "../../../lib/utils"
7475
import { getShortcutKey, isDesktopApp } from "../../../lib/utils/platform"
7576
import { terminalSidebarOpenAtom } from "../../terminal/atoms"
@@ -1727,6 +1728,32 @@ function ChatViewInner({
17271728
})
17281729
}
17291730

1731+
// Desktop app: Optimistic update for chats.list to update sidebar immediately
1732+
const queryClient = getQueryClient()
1733+
if (queryClient) {
1734+
const now = new Date()
1735+
const queries = queryClient.getQueryCache().getAll()
1736+
const chatsListQuery = queries.find(q =>
1737+
Array.isArray(q.queryKey) &&
1738+
Array.isArray(q.queryKey[0]) &&
1739+
q.queryKey[0][0] === 'chats' &&
1740+
q.queryKey[0][1] === 'list'
1741+
)
1742+
if (chatsListQuery) {
1743+
queryClient.setQueryData(chatsListQuery.queryKey, (old: any[] | undefined) => {
1744+
if (!old) return old
1745+
// Update the timestamp and sort by updatedAt descending
1746+
const updated = old.map((c: any) =>
1747+
c.id === parentChatId ? { ...c, updatedAt: now } : c,
1748+
)
1749+
return updated.sort(
1750+
(a: any, b: any) =>
1751+
new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),
1752+
)
1753+
})
1754+
}
1755+
}
1756+
17301757
// Optimistically update sub-chat timestamp to move it to top
17311758
useAgentSubChatStore.getState().updateSubChatTimestamp(subChatId)
17321759

@@ -3852,6 +3879,9 @@ export function ChatView({
38523879

38533880
// Refresh diff stats after agent finishes making changes
38543881
fetchDiffStatsRef.current()
3882+
3883+
// Note: sidebar timestamp update is handled via optimistic update in handleSend
3884+
// No need to refetch here as it would overwrite the optimistic update with stale data
38553885
},
38563886
})
38573887

@@ -3971,6 +4001,9 @@ export function ChatView({
39714001

39724002
// Refresh diff stats after agent finishes making changes
39734003
fetchDiffStatsRef.current()
4004+
4005+
// Note: sidebar timestamp update is handled via optimistic update in handleSend
4006+
// No need to refetch here as it would overwrite the optimistic update with stale data
39744007
},
39754008
})
39764009
agentChatStore.set(newId, newChat, chatId)

0 commit comments

Comments
 (0)