22 * Copyright (c) Microsoft Corporation. All rights reserved.
33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
5- import React , { useCallback , useEffect , useState } from 'react' ;
5+ import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
66
77import { render } from 'react-dom' ;
88import { ChatInput } from './components/ChatInput' ;
99import { EmptyState } from './components/EmptyState' ;
10- import { FilterButton , FilterState } from './components/FilterButton' ;
1110import { GlobalSessionItem } from './components/GlobalSessionItem' ;
1211import { IssueItem } from './components/IssueItem' ;
1312import { LoadingState } from './components/LoadingState' ;
@@ -19,27 +18,11 @@ export function main() {
1918 render ( < Dashboard /> , document . getElementById ( 'app' ) ) ;
2019}
2120
22- // Check if a session is associated with a specific issue
23- function isSessionAssociatedWithIssue ( session : SessionData , issue : IssueData ) : boolean {
24- if ( session . isLocal ) return false ;
25-
26- // Use the same logic as findAssociatedSession
27- const sessionTitle = session . title . toLowerCase ( ) ;
28- const issueNumber = `#${ issue . number } ` ;
29- const issueTitle = issue . title . toLowerCase ( ) ;
30-
31- // Match by issue number reference or similar title
32- return sessionTitle . includes ( issueNumber ) ||
33- sessionTitle . includes ( issueTitle ) ||
34- issueTitle . includes ( sessionTitle ) ;
35- }
36-
3721function Dashboard ( ) {
3822 const [ dashboardState , setDashboardState ] = useState < DashboardState | null > ( null ) ;
3923 const [ refreshing , setRefreshing ] = useState ( false ) ;
4024 const [ issueSort , setIssueSort ] = useState < 'date-oldest' | 'date-newest' > ( 'date-oldest' ) ;
4125 const [ hoveredIssue , setHoveredIssue ] = useState < IssueData | null > ( null ) ;
42- const [ globalFilter , setGlobalFilter ] = useState < FilterState > ( { showTasks : true , showProjects : true } ) ;
4326 const [ chatInputValue , setChatInputValue ] = useState ( '' ) ;
4427 const [ focusTrigger , setFocusTrigger ] = useState ( 0 ) ;
4528
@@ -185,74 +168,61 @@ function Dashboard() {
185168 } , [ dashboardState ] ) ;
186169
187170 // Derived state from discriminated union with proper type narrowing
188- const isGlobal = dashboardState ?. isGlobal ;
189- const issueQuery = dashboardState && ! dashboardState . isGlobal ? ( dashboardState as DashboardReady ) . issueQuery || '' : '' ;
190- const milestoneIssues = dashboardState && ! dashboardState . isGlobal && dashboardState . state === 'ready' ? ( dashboardState as DashboardReady ) . milestoneIssues : [ ] ;
191- const activeSessions = dashboardState ?. state === 'ready' ? dashboardState . activeSessions : [ ] ;
192- const recentProjects = dashboardState && dashboardState . isGlobal && dashboardState . state === 'ready' ? ( dashboardState as GlobalDashboardReady ) . recentProjects : [ ] ;
193- const currentBranch = dashboardState && ! dashboardState . isGlobal && dashboardState . state === 'ready' ? ( dashboardState as DashboardReady ) . currentBranch : undefined ;
171+ const isGlobal = dashboardState ?. isGlobal ?? false ;
172+ const isReady = dashboardState ?. state === 'ready' ;
173+
174+ const readyState = ( isReady && ! isGlobal ) ? dashboardState as DashboardReady : null ;
175+ const globalReadyState = ( isReady && isGlobal ) ? dashboardState as GlobalDashboardReady : null ;
176+
177+ const issueQuery = readyState ?. issueQuery || '' ;
178+ const milestoneIssues = readyState ?. milestoneIssues || [ ] ;
179+ const activeSessions = isReady ? dashboardState . activeSessions : [ ] ;
180+ const recentProjects = globalReadyState ?. recentProjects || [ ] ;
181+ const currentBranch = readyState ?. currentBranch ;
194182
195183 // For global dashboards, create a mixed array of sessions and projects
196- const mixedItems = isGlobal ? ( ( ) => {
184+ const mixedItems = useMemo ( ( ) => {
185+ if ( ! isGlobal ) return [ ] ;
186+
197187 const mixed : Array < { type : 'session' , data : SessionData , index : number } | { type : 'project' , data : ProjectData } > = [ ] ;
198188
199- // Add sessions based on filter
200- if ( globalFilter . showTasks ) {
201- activeSessions . forEach ( ( session , index ) => {
202- mixed . push ( { type : 'session' , data : session , index } ) ;
203- } ) ;
204- }
189+ activeSessions . forEach ( ( session , index ) => {
190+ mixed . push ( { type : 'session' , data : session , index } ) ;
191+ } ) ;
205192
206- // Add projects based on filter
207- if ( globalFilter . showProjects ) {
208- recentProjects . forEach ( ( project : ProjectData ) => {
209- mixed . push ( { type : 'project' , data : project } ) ;
210- } ) ;
211- }
193+ recentProjects . forEach ( ( project : ProjectData ) => {
194+ mixed . push ( { type : 'project' , data : project } ) ;
195+ } ) ;
212196
213- function shuffle < T > ( array : T [ ] ) : T [ ] {
214- for ( let i = array . length - 1 ; i > 0 ; i -- ) {
215- const j = Math . floor ( Math . random ( ) * ( i + 1 ) ) ;
216- const tmp = array [ i ] ;
217- array [ i ] = array [ j ] ;
218- array [ j ] = tmp ;
219- }
220- return array ;
197+ // Simple shuffle algorithm
198+ for ( let i = mixed . length - 1 ; i > 0 ; i -- ) {
199+ const j = Math . floor ( Math . random ( ) * ( i + 1 ) ) ;
200+ [ mixed [ i ] , mixed [ j ] ] = [ mixed [ j ] , mixed [ i ] ] ;
221201 }
222202
223- shuffle ( mixed ) ;
224-
225- // Sort by recency - sessions first, then projects, but could be enhanced with actual timestamps
226203 return mixed ;
227- } ) ( ) : [ ] ;
204+ } , [ isGlobal , activeSessions , recentProjects ] ) ;
228205
229206 return (
230207 < div className = { `dashboard-container${ isGlobal ? ' global-dashboard' : '' } ` } >
231208 { ! isGlobal && (
232209 < div className = { `dashboard-header${ isGlobal ? ' global-header' : '' } ` } >
233- < h1 className = "dashboard-title" >
234- { isGlobal ? 'Visual Studio Code - Insiders' : 'My Tasks' }
235- </ h1 >
210+ < h1 className = "dashboard-title" > My Tasks</ h1 >
236211 < div className = "header-buttons" >
237- { dashboardState ?. state === 'ready' && ! dashboardState . isGlobal &&
238- ( ( dashboardState as DashboardReady ) . currentBranch ) &&
239- ( ( dashboardState as DashboardReady ) . currentBranch !== 'main' ) &&
240- ( ( dashboardState as DashboardReady ) . currentBranch !== 'master' ) && (
212+ { readyState ?. currentBranch &&
213+ readyState . currentBranch !== 'main' &&
214+ readyState . currentBranch !== 'master' && (
241215 < button
242216 className = "switch-to-main-button"
243217 onClick = { handleSwitchToMain }
244- title = { `Switch from ${ ( dashboardState as DashboardReady ) . currentBranch } to main` }
218+ title = { `Switch from ${ readyState . currentBranch } to main` }
245219 >
246220 < span className = "codicon codicon-git-branch" > </ span >
247221 < span > Switch to main</ span >
248222 </ button >
249223 ) }
250224 < button className = "refresh-button" onClick = { handleRefresh } disabled = { refreshing } title = "Refresh dashboard" >
251- { refreshing ? (
252- < span className = "codicon codicon-sync codicon-modifier-spin" > </ span >
253- ) : (
254- < span className = "codicon codicon-refresh" > </ span >
255- ) }
225+ < span className = { `codicon ${ refreshing ? 'codicon-sync codicon-modifier-spin' : 'codicon-refresh' } ` } > </ span >
256226 </ button >
257227 </ div >
258228 </ div >
@@ -274,11 +244,7 @@ function Dashboard() {
274244
275245 { /* Issues/Projects Area */ }
276246 < div className = "issues-area" >
277- { isGlobal ? (
278- < >
279- { /* Empty for now, everything moved to tasks area */ }
280- </ >
281- ) : (
247+ { ! isGlobal && (
282248 < >
283249 < div className = "area-header milestone-header" >
284250 < h3
@@ -287,14 +253,14 @@ function Dashboard() {
287253 >
288254 { issueQuery ? extractMilestoneFromQuery ( issueQuery ) : 'Issues' }
289255 </ h3 >
290- { dashboardState ?. state === 'ready' && (
256+ { isReady && (
291257 < SortDropdown
292258 issueSort = { issueSort }
293259 onSortChange = { setIssueSort }
294260 />
295261 ) }
296262 </ div >
297- { dashboardState ?. state === 'ready' && (
263+ { isReady && (
298264 < div
299265 className = "section-count clickable-count"
300266 onClick = { handleIssueCountClick }
@@ -306,9 +272,9 @@ function Dashboard() {
306272 < div className = "area-content" >
307273 { dashboardState ?. state === 'loading' ? (
308274 < LoadingState message = "Loading issues..." />
309- ) : dashboardState ?. state === 'ready' && ! milestoneIssues . length ? (
275+ ) : isReady && ! milestoneIssues . length ? (
310276 < EmptyState message = { `No issues found for ${ issueQuery ? extractMilestoneFromQuery ( issueQuery ) . toLowerCase ( ) : 'issues' } ` } />
311- ) : dashboardState ?. state === 'ready' ? (
277+ ) : isReady ? (
312278 getSortedIssues ( milestoneIssues ) . map ( ( issue ) => {
313279 const associatedSession = findAssociatedSession ( issue ) ;
314280 return (
@@ -339,24 +305,18 @@ function Dashboard() {
339305 < div className = "area-header-container" >
340306 < h2 className = "area-header" >
341307 { isGlobal ? 'Continue working on...' :
342- dashboardState ?. state === 'ready' ?
308+ isReady ?
343309 `${ activeSessions . length || 0 } active task${ activeSessions . length !== 1 ? 's' : '' } ` :
344310 'Active tasks'
345311 }
346312 </ h2 >
347- { isGlobal && (
348- < FilterButton
349- filterState = { globalFilter }
350- onFilterChange = { setGlobalFilter }
351- />
352- ) }
353313 </ div >
354314 < div className = "area-content" >
355315 { dashboardState ?. state === 'loading' ? (
356316 < LoadingState message = "Loading tasks..." />
357- ) : dashboardState ?. state === 'ready' && ! activeSessions . length && ( ! isGlobal || ! recentProjects . length ) ? (
317+ ) : isReady && ! activeSessions . length && ( ! isGlobal || ! recentProjects . length ) ? (
358318 < EmptyState message = "No active tasks found" />
359- ) : dashboardState ?. state === 'ready' ? (
319+ ) : isReady ? (
360320 < >
361321 { isGlobal ? (
362322 // Render mixed items for global dashboard
@@ -401,7 +361,7 @@ function Dashboard() {
401361 index = { index }
402362 onSessionClick = { ( ) => handleSessionClick ( session ) }
403363 onPullRequestClick = { handlePullRequestClick }
404- isHighlighted = { hoveredIssue !== null && isSessionAssociatedWithIssue ( session , hoveredIssue ) }
364+ isHighlighted = { hoveredIssue !== null && findAssociatedSession ( hoveredIssue ) ?. id === session . id }
405365 />
406366 ) )
407367 ) }
0 commit comments