Reubencf commited on
Commit
3c1a712
·
1 Parent(s): 7767652

FIx window dragging and opening

Browse files
.claude/settings.local.json CHANGED
@@ -22,7 +22,11 @@
22
  "Bash(git push:*)",
23
  "Bash(git filter-branch:*)",
24
  "Bash(git ls-tree:*)",
25
- "Bash(tree:*)"
 
 
 
 
26
  ],
27
  "deny": [],
28
  "ask": []
 
22
  "Bash(git push:*)",
23
  "Bash(git filter-branch:*)",
24
  "Bash(git ls-tree:*)",
25
+ "Bash(tree:*)",
26
+ "mcp__puppeteer__puppeteer_navigate",
27
+ "mcp__puppeteer__puppeteer_screenshot",
28
+ "mcp__puppeteer__puppeteer_click",
29
+ "mcp__puppeteer__puppeteer_evaluate"
30
  ],
31
  "deny": [],
32
  "ask": []
app/components/Calendar.tsx CHANGED
@@ -19,6 +19,8 @@ interface CalendarProps {
19
  onClose: () => void
20
  onMinimize?: () => void
21
  onMaximize?: () => void
 
 
22
  }
23
 
24
  interface CalendarEvent extends Holiday {
@@ -27,7 +29,7 @@ interface CalendarEvent extends Holiday {
27
 
28
  type ViewMode = 'day' | 'week' | 'month' | 'year'
29
 
30
- export function Calendar({ onClose, onMinimize, onMaximize }: CalendarProps) {
31
  const [currentDate, setCurrentDate] = useState(new Date())
32
  const [view, setView] = useState<ViewMode>('month')
33
  const [selectedDate, setSelectedDate] = useState<Date | null>(null)
@@ -205,6 +207,8 @@ export function Calendar({ onClose, onMinimize, onMaximize }: CalendarProps) {
205
  onClose={onClose}
206
  onMinimize={onMinimize}
207
  onMaximize={onMaximize}
 
 
208
  width={1100}
209
  height={750}
210
  x={50}
 
19
  onClose: () => void
20
  onMinimize?: () => void
21
  onMaximize?: () => void
22
+ onFocus?: () => void
23
+ zIndex?: number
24
  }
25
 
26
  interface CalendarEvent extends Holiday {
 
29
 
30
  type ViewMode = 'day' | 'week' | 'month' | 'year'
31
 
32
+ export function Calendar({ onClose, onMinimize, onMaximize, onFocus, zIndex }: CalendarProps) {
33
  const [currentDate, setCurrentDate] = useState(new Date())
34
  const [view, setView] = useState<ViewMode>('month')
35
  const [selectedDate, setSelectedDate] = useState<Date | null>(null)
 
207
  onClose={onClose}
208
  onMinimize={onMinimize}
209
  onMaximize={onMaximize}
210
+ onFocus={onFocus}
211
+ zIndex={zIndex}
212
  width={1100}
213
  height={750}
214
  x={50}
app/components/Clock.tsx CHANGED
@@ -7,9 +7,11 @@ interface ClockProps {
7
  onClose: () => void
8
  onMinimize?: () => void
9
  onMaximize?: () => void
 
 
10
  }
11
 
12
- export function Clock({ onClose, onMinimize, onMaximize }: ClockProps) {
13
  const [time, setTime] = useState(new Date())
14
  const [viewMode, setViewMode] = useState<'analog' | 'digital' | 'world'>('analog')
15
 
@@ -51,6 +53,8 @@ export function Clock({ onClose, onMinimize, onMaximize }: ClockProps) {
51
  onClose={onClose}
52
  onMinimize={onMinimize}
53
  onMaximize={onMaximize}
 
 
54
  width={380}
55
  height={480}
56
  x={window.innerWidth / 2 - 190}
 
7
  onClose: () => void
8
  onMinimize?: () => void
9
  onMaximize?: () => void
10
+ onFocus?: () => void
11
+ zIndex?: number
12
  }
13
 
14
+ export function Clock({ onClose, onMinimize, onMaximize, onFocus, zIndex }: ClockProps) {
15
  const [time, setTime] = useState(new Date())
16
  const [viewMode, setViewMode] = useState<'analog' | 'digital' | 'world'>('analog')
17
 
 
53
  onClose={onClose}
54
  onMinimize={onMinimize}
55
  onMaximize={onMaximize}
56
+ onFocus={onFocus}
57
+ zIndex={zIndex}
58
  width={380}
59
  height={480}
60
  x={window.innerWidth / 2 - 190}
app/components/Desktop.tsx CHANGED
@@ -82,12 +82,53 @@ export function Desktop() {
82
  const [latexEditorMinimized, setLaTeXEditorMinimized] = useState(false)
83
 
84
  const [powerState, setPowerState] = useState<'active' | 'sleep' | 'restart' | 'shutdown'>('active')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  const openFileManager = (path: string) => {
87
  console.log('Opening File Manager with path:', path)
88
  setCurrentPath(path)
89
  setFileManagerOpen(true)
90
  setFileManagerMinimized(false)
 
91
  }
92
 
93
  const closeFileManager = () => {
@@ -99,6 +140,7 @@ export function Desktop() {
99
  console.log('Opening Calendar')
100
  setCalendarOpen(true)
101
  setCalendarMinimized(false)
 
102
  }
103
 
104
  const closeCalendar = () => {
@@ -109,6 +151,7 @@ export function Desktop() {
109
  const openClock = () => {
110
  setClockOpen(true)
111
  setClockMinimized(false)
 
112
  }
113
 
114
  const closeClock = () => {
@@ -122,6 +165,7 @@ export function Desktop() {
122
  console.log('Opening Gemini Chat')
123
  setGeminiChatOpen(true)
124
  setGeminiChatMinimized(false)
 
125
  }
126
 
127
  const closeGeminiChat = () => {
@@ -134,6 +178,7 @@ export function Desktop() {
134
  const openSessionManager = () => {
135
  setSessionManagerOpen(true)
136
  setSessionManagerMinimized(false)
 
137
  }
138
 
139
  const closeSessionManager = () => {
@@ -145,6 +190,7 @@ export function Desktop() {
145
  setActiveFlutterApp(appFile)
146
  setFlutterRunnerOpen(true)
147
  setFlutterRunnerMinimized(false)
 
148
  }
149
 
150
  const closeFlutterRunner = () => {
@@ -156,6 +202,7 @@ export function Desktop() {
156
  const openResearchBrowser = () => {
157
  setResearchBrowserOpen(true)
158
  setResearchBrowserMinimized(false)
 
159
  }
160
 
161
  const closeResearchBrowser = () => {
@@ -166,6 +213,7 @@ export function Desktop() {
166
  const openFlutterCodeEditor = () => {
167
  setFlutterCodeEditorOpen(true)
168
  setFlutterCodeEditorMinimized(false)
 
169
  }
170
 
171
  const closeFlutterCodeEditor = () => {
@@ -176,6 +224,7 @@ export function Desktop() {
176
  const openLaTeXEditor = () => {
177
  setLaTeXEditorOpen(true)
178
  setLaTeXEditorMinimized(false)
 
179
  }
180
 
181
  const closeLaTeXEditor = () => {
@@ -566,6 +615,7 @@ export function Desktop() {
566
  onOpenCalendar={openCalendar}
567
  onOpenClock={openClock}
568
  onOpenGeminiChat={openGeminiChat}
 
569
  openApps={{
570
  files: fileManagerOpen,
571
  calendar: calendarOpen,
@@ -609,6 +659,7 @@ export function Desktop() {
609
  onDoubleClick={openClock}
610
  />
611
  </div>
 
612
  <div className="pointer-events-auto w-24 h-24">
613
  <DraggableDesktopIcon
614
  id="calendar"
@@ -630,6 +681,7 @@ export function Desktop() {
630
  onDoubleClick={() => openFileManager('')}
631
  />
632
  </div>
 
633
  <div className="pointer-events-auto w-24 h-24">
634
  <DraggableDesktopIcon
635
  id="sessions"
@@ -640,6 +692,7 @@ export function Desktop() {
640
  onDoubleClick={openSessionManager}
641
  />
642
  </div>
 
643
  <div className="pointer-events-auto w-24 h-24">
644
  <DraggableDesktopIcon
645
  id="research"
@@ -650,6 +703,7 @@ export function Desktop() {
650
  onDoubleClick={openResearchBrowser}
651
  />
652
  </div>
 
653
  <div className="pointer-events-auto w-24 h-24">
654
  <DraggableDesktopIcon
655
  id="flutter-editor"
@@ -660,6 +714,7 @@ export function Desktop() {
660
  onDoubleClick={openFlutterCodeEditor}
661
  />
662
  </div>
 
663
  <div className="pointer-events-auto w-24 h-24">
664
  <DraggableDesktopIcon
665
  id="latex-editor"
@@ -672,127 +727,132 @@ export function Desktop() {
672
  </div>
673
  </div>
674
 
675
- <AnimatePresence>
676
- {fileManagerOpen && !fileManagerMinimized && (
677
- <motion.div
678
- key="file-manager"
679
- initial={{ scale: 0.9, opacity: 0 }}
680
- animate={{
681
- scale: 1,
682
- opacity: 1,
683
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
684
- }}
685
- exit={{
686
- scale: 0.2,
687
- opacity: 0,
688
- y: "80vh",
689
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
690
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
691
- }}
692
- transition={{ duration: 0.3, ease: "easeOut" }}
693
- className="absolute"
694
- style={{
695
- transformOrigin: 'bottom center',
696
- pointerEvents: 'auto',
697
- zIndex: 1000
698
- }}
699
- >
700
- <FileManager
701
  currentPath={currentPath}
702
  onNavigate={setCurrentPath}
703
  onClose={closeFileManager}
704
  onOpenFlutterApp={openFlutterRunner}
705
- onMinimize={() => setFileManagerMinimized(true)}
706
- sessionId={userSession}
707
- onOpenApp={handleOpenApp}
708
- />
709
- </motion.div>
710
- )}
711
-
712
- {calendarOpen && !calendarMinimized && (
713
- <motion.div
714
- key="calendar"
715
- initial={{ scale: 0.9, opacity: 0 }}
716
- animate={{
717
- scale: 1,
718
- opacity: 1,
719
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
720
- }}
721
- exit={{
722
- scale: 0.2,
723
- opacity: 0,
724
- y: "80vh",
725
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
726
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
727
- }}
728
- transition={{ duration: 0.3, ease: "easeOut" }}
729
- className="absolute"
730
- style={{
731
- transformOrigin: 'bottom center',
732
- pointerEvents: 'auto',
733
- zIndex: 1000
734
- }}
735
- >
736
- <Calendar onClose={closeCalendar} onMinimize={() => setCalendarMinimized(true)} />
737
- </motion.div>
738
- )}
739
-
740
- {clockOpen && !clockMinimized && (
741
- <motion.div
742
- key="clock"
743
- initial={{ scale: 0.9, opacity: 0 }}
744
- animate={{
745
- scale: 1,
746
- opacity: 1,
747
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
748
- }}
749
- exit={{
750
- scale: 0.2,
751
- opacity: 0,
752
- y: "80vh",
753
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
754
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
755
- }}
756
- transition={{ duration: 0.3, ease: "easeOut" }}
757
- className="absolute"
758
- style={{
759
- transformOrigin: 'bottom center',
760
- pointerEvents: 'auto',
761
- zIndex: 1000
762
- }}
763
- >
764
- <Clock onClose={closeClock} onMinimize={() => setClockMinimized(true)} />
765
- </motion.div>
766
- )}
767
-
768
-
769
-
770
-
771
-
772
- {sessionManagerOpen && sessionInitialized && !sessionManagerMinimized && (
773
- <motion.div
774
- key="session-manager"
775
- initial={{ scale: 0.9, opacity: 0 }}
776
- animate={{
777
- scale: 1,
778
- opacity: 1,
779
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
780
- }}
781
- exit={{
782
- scale: 0.2,
783
- opacity: 0,
784
- y: "80vh",
785
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
786
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
787
- }}
788
- transition={{ duration: 0.3, ease: "easeOut" }}
789
- className="absolute"
790
- style={{
791
- transformOrigin: 'bottom center',
792
- pointerEvents: 'auto',
793
- zIndex: 1000
794
- }}
795
- >
 
 
 
 
 
 
 
 
 
 
 
796
  <SessionManagerWindow
797
  onClose={closeSessionManager}
798
  sessionId={userSession}
@@ -802,30 +862,22 @@ export function Desktop() {
802
  </motion.div>
803
  )}
804
 
805
- {flutterRunnerOpen && activeFlutterApp && !flutterRunnerMinimized && (
806
- <motion.div
807
- key="flutter-runner"
808
- initial={{ scale: 0.9, opacity: 0 }}
809
- animate={{
810
- scale: 1,
811
- opacity: 1,
812
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
813
- }}
814
- exit={{
815
- scale: 0.2,
816
- opacity: 0,
817
- y: "80vh",
818
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
819
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
820
- }}
821
- transition={{ duration: 0.3, ease: "easeOut" }}
822
- className="absolute"
823
- style={{
824
- transformOrigin: 'bottom center',
825
- pointerEvents: 'auto',
826
- zIndex: 1000
827
- }}
828
- >
829
  <FlutterRunner
830
  initialCode={activeFlutterApp?.dartCode}
831
  sessionId={userSession}
@@ -838,28 +890,20 @@ export function Desktop() {
838
  </motion.div>
839
  )}
840
 
841
- {researchBrowserOpen && !researchBrowserMinimized && (
842
  <motion.div
843
  key="research-browser"
844
- initial={{ scale: 0.9, opacity: 0 }}
845
  animate={{
846
- scale: 1,
847
- opacity: 1,
848
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
849
- }}
850
- exit={{
851
- scale: 0.2,
852
- opacity: 0,
853
- y: "80vh",
854
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
855
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
856
  }}
857
- transition={{ duration: 0.3, ease: "easeOut" }}
858
- className="absolute"
859
  style={{
860
- transformOrigin: 'bottom center',
861
- pointerEvents: 'auto',
862
- zIndex: 1000
863
  }}
864
  >
865
  <ResearchBrowser
@@ -869,90 +913,47 @@ export function Desktop() {
869
  </motion.div>
870
  )}
871
 
872
- {flutterCodeEditorOpen && !flutterCodeEditorMinimized && (
873
  <motion.div
874
  key="flutter-code-editor"
875
- initial={{ scale: 0.9, opacity: 0 }}
876
  animate={{
877
- scale: 1,
878
- opacity: 1,
879
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
880
  }}
881
- exit={{
882
- scale: 0.2,
883
- opacity: 0,
884
- y: "80vh",
885
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
886
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
887
- }}
888
- transition={{ duration: 0.3, ease: "easeOut" }}
889
- className="absolute"
890
  style={{
891
- transformOrigin: 'bottom center',
892
- pointerEvents: 'auto',
893
- zIndex: 1000
894
  }}
895
  >
896
  <FlutterCodeEditor onClose={closeFlutterCodeEditor} onMinimize={() => setFlutterCodeEditorMinimized(true)} />
897
  </motion.div>
898
  )}
899
 
900
- {latexEditorOpen && !latexEditorMinimized && (
901
  <motion.div
902
  key="latex-editor"
903
- initial={{ scale: 0.9, opacity: 0 }}
904
  animate={{
905
- scale: 1,
906
- opacity: 1,
907
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
908
- }}
909
- exit={{
910
- scale: 0.2,
911
- opacity: 0,
912
- y: "80vh",
913
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
914
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
915
  }}
916
- transition={{ duration: 0.3, ease: "easeOut" }}
917
- className="absolute"
918
  style={{
919
- transformOrigin: 'bottom center',
920
- pointerEvents: 'auto',
921
- zIndex: 1000
922
  }}
923
  >
924
  <LaTeXEditor onClose={closeLaTeXEditor} sessionId={userSession} onMinimize={() => setLaTeXEditorMinimized(true)} />
925
  </motion.div>
926
  )}
927
- {geminiChatOpen && !geminiChatMinimized && (
928
- <motion.div
929
- key="gemini"
930
- initial={{ scale: 0.9, opacity: 0 }}
931
- animate={{
932
- scale: 1,
933
- opacity: 1,
934
- clipPath: "polygon(0 0, 100% 0, 100% 100%, 0% 100%)",
935
- }}
936
- exit={{
937
- scale: 0.2,
938
- opacity: 0,
939
- y: "80vh",
940
- clipPath: "polygon(45% 100%, 55% 100%, 60% 0%, 40% 0%)",
941
- transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] }
942
- }}
943
- transition={{ duration: 0.3, ease: "easeOut" }}
944
- className="absolute"
945
- style={{
946
- transformOrigin: 'bottom center',
947
- pointerEvents: 'auto',
948
- zIndex: 1000
949
- }}
950
- >
951
- <GeminiChat onClose={closeGeminiChat} onMinimize={() => setGeminiChatMinimized(true)} />
952
- </motion.div>
953
- )}
954
  </AnimatePresence>
955
-
956
  </div>
957
 
958
  {/* Spotlight Search */}
 
82
  const [latexEditorMinimized, setLaTeXEditorMinimized] = useState(false)
83
 
84
  const [powerState, setPowerState] = useState<'active' | 'sleep' | 'restart' | 'shutdown'>('active')
85
+ const [globalZIndex, setGlobalZIndex] = useState(1000)
86
+ const [windowZIndices, setWindowZIndices] = useState<{[key: string]: number}>({})
87
+
88
+ const getNextZIndex = () => {
89
+ const nextZ = globalZIndex + 1
90
+ setGlobalZIndex(nextZ)
91
+ return nextZ
92
+ }
93
+
94
+ const bringWindowToFront = (windowId: string) => {
95
+ setWindowZIndices(prev => ({ ...prev, [windowId]: getNextZIndex() }))
96
+ }
97
+
98
+ const closeAllApps = () => {
99
+ // Close all apps
100
+ setFileManagerOpen(false)
101
+ setCalendarOpen(false)
102
+ setClockOpen(false)
103
+ setGeminiChatOpen(false)
104
+ setSessionManagerOpen(false)
105
+ setFlutterRunnerOpen(false)
106
+ setResearchBrowserOpen(false)
107
+ setFlutterCodeEditorOpen(false)
108
+ setLaTeXEditorOpen(false)
109
+
110
+ // Reset all minimized states
111
+ setFileManagerMinimized(false)
112
+ setCalendarMinimized(false)
113
+ setClockMinimized(false)
114
+ setGeminiChatMinimized(false)
115
+ setSessionManagerMinimized(false)
116
+ setFlutterRunnerMinimized(false)
117
+ setResearchBrowserMinimized(false)
118
+ setFlutterCodeEditorMinimized(false)
119
+ setLaTeXEditorMinimized(false)
120
+
121
+ // Reset window z-indices
122
+ setWindowZIndices({})
123
+ setGlobalZIndex(1000)
124
+ }
125
 
126
  const openFileManager = (path: string) => {
127
  console.log('Opening File Manager with path:', path)
128
  setCurrentPath(path)
129
  setFileManagerOpen(true)
130
  setFileManagerMinimized(false)
131
+ setWindowZIndices(prev => ({ ...prev, fileManager: getNextZIndex() }))
132
  }
133
 
134
  const closeFileManager = () => {
 
140
  console.log('Opening Calendar')
141
  setCalendarOpen(true)
142
  setCalendarMinimized(false)
143
+ setWindowZIndices(prev => ({ ...prev, calendar: getNextZIndex() }))
144
  }
145
 
146
  const closeCalendar = () => {
 
151
  const openClock = () => {
152
  setClockOpen(true)
153
  setClockMinimized(false)
154
+ setWindowZIndices(prev => ({ ...prev, clock: getNextZIndex() }))
155
  }
156
 
157
  const closeClock = () => {
 
165
  console.log('Opening Gemini Chat')
166
  setGeminiChatOpen(true)
167
  setGeminiChatMinimized(false)
168
+ setWindowZIndices(prev => ({ ...prev, gemini: getNextZIndex() }))
169
  }
170
 
171
  const closeGeminiChat = () => {
 
178
  const openSessionManager = () => {
179
  setSessionManagerOpen(true)
180
  setSessionManagerMinimized(false)
181
+ setWindowZIndices(prev => ({ ...prev, sessionManager: getNextZIndex() }))
182
  }
183
 
184
  const closeSessionManager = () => {
 
190
  setActiveFlutterApp(appFile)
191
  setFlutterRunnerOpen(true)
192
  setFlutterRunnerMinimized(false)
193
+ setWindowZIndices(prev => ({ ...prev, flutterRunner: getNextZIndex() }))
194
  }
195
 
196
  const closeFlutterRunner = () => {
 
202
  const openResearchBrowser = () => {
203
  setResearchBrowserOpen(true)
204
  setResearchBrowserMinimized(false)
205
+ setWindowZIndices(prev => ({ ...prev, researchBrowser: getNextZIndex() }))
206
  }
207
 
208
  const closeResearchBrowser = () => {
 
213
  const openFlutterCodeEditor = () => {
214
  setFlutterCodeEditorOpen(true)
215
  setFlutterCodeEditorMinimized(false)
216
+ setWindowZIndices(prev => ({ ...prev, flutterCodeEditor: getNextZIndex() }))
217
  }
218
 
219
  const closeFlutterCodeEditor = () => {
 
224
  const openLaTeXEditor = () => {
225
  setLaTeXEditorOpen(true)
226
  setLaTeXEditorMinimized(false)
227
+ setWindowZIndices(prev => ({ ...prev, latexEditor: getNextZIndex() }))
228
  }
229
 
230
  const closeLaTeXEditor = () => {
 
615
  onOpenCalendar={openCalendar}
616
  onOpenClock={openClock}
617
  onOpenGeminiChat={openGeminiChat}
618
+ onCloseAllApps={closeAllApps}
619
  openApps={{
620
  files: fileManagerOpen,
621
  calendar: calendarOpen,
 
659
  onDoubleClick={openClock}
660
  />
661
  </div>
662
+
663
  <div className="pointer-events-auto w-24 h-24">
664
  <DraggableDesktopIcon
665
  id="calendar"
 
681
  onDoubleClick={() => openFileManager('')}
682
  />
683
  </div>
684
+
685
  <div className="pointer-events-auto w-24 h-24">
686
  <DraggableDesktopIcon
687
  id="sessions"
 
692
  onDoubleClick={openSessionManager}
693
  />
694
  </div>
695
+
696
  <div className="pointer-events-auto w-24 h-24">
697
  <DraggableDesktopIcon
698
  id="research"
 
703
  onDoubleClick={openResearchBrowser}
704
  />
705
  </div>
706
+
707
  <div className="pointer-events-auto w-24 h-24">
708
  <DraggableDesktopIcon
709
  id="flutter-editor"
 
714
  onDoubleClick={openFlutterCodeEditor}
715
  />
716
  </div>
717
+
718
  <div className="pointer-events-auto w-24 h-24">
719
  <DraggableDesktopIcon
720
  id="latex-editor"
 
727
  </div>
728
  </div>
729
 
730
+ {/* Windows Container */}
731
+ <div className="fixed inset-0 top-8 pointer-events-none" style={{ position: 'fixed', top: '32px', left: 0, right: 0, bottom: 0 }}>
732
+ <AnimatePresence>
733
+ {fileManagerOpen && (
734
+ <motion.div
735
+ key="file-manager"
736
+ initial={{ opacity: 0, scale: 0.95 }}
737
+ animate={{
738
+ opacity: fileManagerMinimized ? 0 : 1,
739
+ scale: fileManagerMinimized ? 0.9 : 1,
740
+ y: fileManagerMinimized ? 100 : 0,
741
+ }}
742
+ exit={{ opacity: 0, scale: 0.95 }}
743
+ transition={{ duration: 0.2 }}
744
+ style={{
745
+ pointerEvents: fileManagerMinimized ? 'none' : 'auto',
746
+ display: fileManagerMinimized ? 'none' : 'block'
747
+ }}
748
+ >
749
+ <FileManager
 
 
 
 
 
 
750
  currentPath={currentPath}
751
  onNavigate={setCurrentPath}
752
  onClose={closeFileManager}
753
  onOpenFlutterApp={openFlutterRunner}
754
+ onMinimize={() => setFileManagerMinimized(true)}
755
+ onFocus={() => bringWindowToFront('fileManager')}
756
+ zIndex={windowZIndices.fileManager || 1000}
757
+ sessionId={userSession}
758
+ onOpenApp={handleOpenApp}
759
+ />
760
+ </motion.div>
761
+ )}
762
+
763
+ {calendarOpen && (
764
+ <motion.div
765
+ key="calendar"
766
+ initial={{ opacity: 0, scale: 0.95 }}
767
+ animate={{
768
+ opacity: calendarMinimized ? 0 : 1,
769
+ scale: calendarMinimized ? 0.9 : 1,
770
+ y: calendarMinimized ? 100 : 0,
771
+ }}
772
+ exit={{ opacity: 0, scale: 0.95 }}
773
+ transition={{ duration: 0.2 }}
774
+ style={{
775
+ pointerEvents: calendarMinimized ? 'none' : 'auto',
776
+ display: calendarMinimized ? 'none' : 'block'
777
+ }}
778
+ >
779
+ <Calendar
780
+ onClose={closeCalendar}
781
+ onMinimize={() => setCalendarMinimized(true)}
782
+ onFocus={() => bringWindowToFront('calendar')}
783
+ zIndex={windowZIndices.calendar || 1000}
784
+ />
785
+ </motion.div>
786
+ )}
787
+
788
+ {clockOpen && (
789
+ <motion.div
790
+ key="clock"
791
+ initial={{ opacity: 0, scale: 0.95 }}
792
+ animate={{
793
+ opacity: clockMinimized ? 0 : 1,
794
+ scale: clockMinimized ? 0.9 : 1,
795
+ y: clockMinimized ? 100 : 0,
796
+ }}
797
+ exit={{ opacity: 0, scale: 0.95 }}
798
+ transition={{ duration: 0.2 }}
799
+ style={{
800
+ pointerEvents: clockMinimized ? 'none' : 'auto',
801
+ display: clockMinimized ? 'none' : 'block'
802
+ }}
803
+ >
804
+ <Clock
805
+ onClose={closeClock}
806
+ onMinimize={() => setClockMinimized(true)}
807
+ onFocus={() => bringWindowToFront('clock')}
808
+ zIndex={windowZIndices.clock || 1000}
809
+ />
810
+ </motion.div>
811
+ )}
812
+
813
+
814
+
815
+ {geminiChatOpen && (
816
+ <motion.div
817
+ key="gemini"
818
+ initial={{ opacity: 0, scale: 0.95 }}
819
+ animate={{
820
+ opacity: geminiChatMinimized ? 0 : 1,
821
+ scale: geminiChatMinimized ? 0.9 : 1,
822
+ y: geminiChatMinimized ? 100 : 0,
823
+ }}
824
+ exit={{ opacity: 0, scale: 0.95 }}
825
+ transition={{ duration: 0.2 }}
826
+ style={{
827
+ pointerEvents: geminiChatMinimized ? 'none' : 'auto',
828
+ display: geminiChatMinimized ? 'none' : 'block'
829
+ }}
830
+ >
831
+ <GeminiChat
832
+ onClose={closeGeminiChat}
833
+ onMinimize={() => setGeminiChatMinimized(true)}
834
+ onFocus={() => bringWindowToFront('gemini')}
835
+ zIndex={windowZIndices.gemini || 1000}
836
+ />
837
+ </motion.div>
838
+ )}
839
+
840
+ {sessionManagerOpen && sessionInitialized && (
841
+ <motion.div
842
+ key="session-manager"
843
+ initial={{ opacity: 0, scale: 0.95 }}
844
+ animate={{
845
+ opacity: sessionManagerMinimized ? 0 : 1,
846
+ scale: sessionManagerMinimized ? 0.9 : 1,
847
+ y: sessionManagerMinimized ? 100 : 0,
848
+ }}
849
+ exit={{ opacity: 0, scale: 0.95 }}
850
+ transition={{ duration: 0.2 }}
851
+ style={{
852
+ pointerEvents: sessionManagerMinimized ? 'none' : 'auto',
853
+ display: sessionManagerMinimized ? 'none' : 'block'
854
+ }}
855
+ >
856
  <SessionManagerWindow
857
  onClose={closeSessionManager}
858
  sessionId={userSession}
 
862
  </motion.div>
863
  )}
864
 
865
+ {flutterRunnerOpen && activeFlutterApp && (
866
+ <motion.div
867
+ key="flutter-runner"
868
+ initial={{ opacity: 0, scale: 0.95 }}
869
+ animate={{
870
+ opacity: flutterRunnerMinimized ? 0 : 1,
871
+ scale: flutterRunnerMinimized ? 0.9 : 1,
872
+ y: flutterRunnerMinimized ? 100 : 0,
873
+ }}
874
+ exit={{ opacity: 0, scale: 0.95 }}
875
+ transition={{ duration: 0.2 }}
876
+ style={{
877
+ pointerEvents: flutterRunnerMinimized ? 'none' : 'auto',
878
+ display: flutterRunnerMinimized ? 'none' : 'block'
879
+ }}
880
+ >
 
 
 
 
 
 
 
 
881
  <FlutterRunner
882
  initialCode={activeFlutterApp?.dartCode}
883
  sessionId={userSession}
 
890
  </motion.div>
891
  )}
892
 
893
+ {researchBrowserOpen && (
894
  <motion.div
895
  key="research-browser"
896
+ initial={{ opacity: 0, scale: 0.95 }}
897
  animate={{
898
+ opacity: researchBrowserMinimized ? 0 : 1,
899
+ scale: researchBrowserMinimized ? 0.9 : 1,
900
+ y: researchBrowserMinimized ? 100 : 0,
 
 
 
 
 
 
 
901
  }}
902
+ exit={{ opacity: 0, scale: 0.95 }}
903
+ transition={{ duration: 0.2 }}
904
  style={{
905
+ pointerEvents: researchBrowserMinimized ? 'none' : 'auto',
906
+ display: researchBrowserMinimized ? 'none' : 'block'
 
907
  }}
908
  >
909
  <ResearchBrowser
 
913
  </motion.div>
914
  )}
915
 
916
+ {flutterCodeEditorOpen && (
917
  <motion.div
918
  key="flutter-code-editor"
919
+ initial={{ opacity: 0, scale: 0.95 }}
920
  animate={{
921
+ opacity: flutterCodeEditorMinimized ? 0 : 1,
922
+ scale: flutterCodeEditorMinimized ? 0.9 : 1,
923
+ y: flutterCodeEditorMinimized ? 100 : 0,
924
  }}
925
+ exit={{ opacity: 0, scale: 0.95 }}
926
+ transition={{ duration: 0.2 }}
 
 
 
 
 
 
 
927
  style={{
928
+ pointerEvents: flutterCodeEditorMinimized ? 'none' : 'auto',
929
+ display: flutterCodeEditorMinimized ? 'none' : 'block'
 
930
  }}
931
  >
932
  <FlutterCodeEditor onClose={closeFlutterCodeEditor} onMinimize={() => setFlutterCodeEditorMinimized(true)} />
933
  </motion.div>
934
  )}
935
 
936
+ {latexEditorOpen && (
937
  <motion.div
938
  key="latex-editor"
939
+ initial={{ opacity: 0, scale: 0.95 }}
940
  animate={{
941
+ opacity: latexEditorMinimized ? 0 : 1,
942
+ scale: latexEditorMinimized ? 0.9 : 1,
943
+ y: latexEditorMinimized ? 100 : 0,
 
 
 
 
 
 
 
944
  }}
945
+ exit={{ opacity: 0, scale: 0.95 }}
946
+ transition={{ duration: 0.2 }}
947
  style={{
948
+ pointerEvents: latexEditorMinimized ? 'none' : 'auto',
949
+ display: latexEditorMinimized ? 'none' : 'block'
 
950
  }}
951
  >
952
  <LaTeXEditor onClose={closeLaTeXEditor} sessionId={userSession} onMinimize={() => setLaTeXEditorMinimized(true)} />
953
  </motion.div>
954
  )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
955
  </AnimatePresence>
956
+ </div>
957
  </div>
958
 
959
  {/* Spotlight Search */}
app/components/Dock.tsx CHANGED
@@ -31,6 +31,7 @@ interface DockProps {
31
  onOpenClock: () => void
32
 
33
  onOpenGeminiChat: () => void
 
34
  openApps: { [key: string]: boolean }
35
  minimizedApps?: MinimizedApp[]
36
  }
@@ -82,6 +83,7 @@ export function Dock({
82
  onOpenClock,
83
 
84
  onOpenGeminiChat,
 
85
  openApps,
86
  minimizedApps = []
87
  }: DockProps) {
@@ -173,7 +175,7 @@ export function Dock({
173
  </div>
174
  }
175
  label="Trash"
176
- onClick={() => { }}
177
  className=""
178
  mouseX={mouseX}
179
  />
 
31
  onOpenClock: () => void
32
 
33
  onOpenGeminiChat: () => void
34
+ onCloseAllApps?: () => void
35
  openApps: { [key: string]: boolean }
36
  minimizedApps?: MinimizedApp[]
37
  }
 
83
  onOpenClock,
84
 
85
  onOpenGeminiChat,
86
+ onCloseAllApps,
87
  openApps,
88
  minimizedApps = []
89
  }: DockProps) {
 
175
  </div>
176
  }
177
  label="Trash"
178
+ onClick={() => onCloseAllApps?.()}
179
  className=""
180
  mouseX={mouseX}
181
  />
app/components/Window.tsx CHANGED
@@ -10,11 +10,13 @@ interface WindowProps {
10
  onClose: () => void;
11
  onMinimize?: () => void;
12
  onMaximize?: () => void;
 
13
  children: ReactNode;
14
  width?: number | string;
15
  height?: number | string;
16
  x?: number;
17
  y?: number;
 
18
  resizable?: boolean;
19
  className?: string;
20
  headerClassName?: string;
@@ -28,23 +30,24 @@ const Window: React.FC<WindowProps> = ({
28
  onClose,
29
  onMinimize,
30
  onMaximize,
 
31
  children,
32
  width = 800,
33
  height = 600,
34
  x = 100,
35
  y = 100,
 
36
  resizable = true,
37
  className = '',
38
  headerClassName = '',
39
  darkMode = false,
40
  }) => {
41
  const [isMaximized, setIsMaximized] = React.useState(false);
42
- const [previousSize, setPreviousSize] = React.useState({ width, height, x, y });
43
- const [currentPosition, setCurrentPosition] = React.useState({ x, y });
44
  const [currentSize, setCurrentSize] = React.useState({ width, height });
45
  const [isMobile, setIsMobile] = React.useState(false);
46
  const [isDraggingOrResizing, setIsDraggingOrResizing] = React.useState(false);
47
- const [zIndex, setZIndex] = React.useState(1000);
48
 
49
  // Detect mobile device
50
  useEffect(() => {
@@ -99,17 +102,19 @@ const Window: React.FC<WindowProps> = ({
99
  if (onMaximize) onMaximize();
100
  };
101
 
102
- // Global z-index counter
103
  const bringToFront = () => {
104
- // Increment z-index when window is clicked or dragged
105
- setZIndex(Date.now());
 
 
106
  };
107
 
108
  // Calculate Rnd props based on state
109
  const rndProps = isMaximized ? {
110
- position: { x: 0, y: 40 }, // 40px for TopBar offset
111
  size: { width: typeof window !== 'undefined' ? window.innerWidth : '100vw',
112
- height: typeof window !== 'undefined' ? window.innerHeight - 40 : 'calc(100vh - 40px)' },
113
  disableDragging: true,
114
  enableResizing: false
115
  } : {
@@ -124,7 +129,6 @@ const Window: React.FC<WindowProps> = ({
124
  {...rndProps}
125
  minWidth={400}
126
  minHeight={300}
127
- bounds="parent"
128
  dragHandleClassName="window-drag-handle"
129
  enableResizing={!isMaximized && resizable}
130
  disableDragging={isMaximized}
@@ -133,9 +137,19 @@ const Window: React.FC<WindowProps> = ({
133
  setIsDraggingOrResizing(true);
134
  bringToFront();
135
  }}
 
 
 
 
 
 
136
  onDragStop={(e, d) => {
137
  setIsDraggingOrResizing(false);
138
- if (!isMaximized) setCurrentPosition({ x: d.x, y: d.y });
 
 
 
 
139
  }}
140
  onResizeStart={() => {
141
  setIsDraggingOrResizing(true);
@@ -148,14 +162,17 @@ const Window: React.FC<WindowProps> = ({
148
  width: ref.offsetWidth,
149
  height: ref.offsetHeight,
150
  });
151
- setCurrentPosition(position);
 
 
152
  }
153
  }}
154
  className="absolute"
155
- style={{ zIndex }}
156
  >
157
  <div
158
  className={`h-full macos-window flex flex-col ${className} ${windowClass}`}
 
159
  >
160
  <div
161
  className={`window-drag-handle h-10 flex items-center px-4 space-x-4 border-b cursor-move ${headerClass} ${headerClassName}`}
 
10
  onClose: () => void;
11
  onMinimize?: () => void;
12
  onMaximize?: () => void;
13
+ onFocus?: () => void;
14
  children: ReactNode;
15
  width?: number | string;
16
  height?: number | string;
17
  x?: number;
18
  y?: number;
19
+ zIndex?: number;
20
  resizable?: boolean;
21
  className?: string;
22
  headerClassName?: string;
 
30
  onClose,
31
  onMinimize,
32
  onMaximize,
33
+ onFocus,
34
  children,
35
  width = 800,
36
  height = 600,
37
  x = 100,
38
  y = 100,
39
+ zIndex = 1000,
40
  resizable = true,
41
  className = '',
42
  headerClassName = '',
43
  darkMode = false,
44
  }) => {
45
  const [isMaximized, setIsMaximized] = React.useState(false);
46
+ const [previousSize, setPreviousSize] = React.useState({ width, height, x, y: Math.max(y, 32) });
47
+ const [currentPosition, setCurrentPosition] = React.useState({ x, y: Math.max(y, 32) });
48
  const [currentSize, setCurrentSize] = React.useState({ width, height });
49
  const [isMobile, setIsMobile] = React.useState(false);
50
  const [isDraggingOrResizing, setIsDraggingOrResizing] = React.useState(false);
 
51
 
52
  // Detect mobile device
53
  useEffect(() => {
 
102
  if (onMaximize) onMaximize();
103
  };
104
 
105
+ // Bring window to front
106
  const bringToFront = () => {
107
+ // Call onFocus to bring window to front
108
+ if (onFocus) {
109
+ onFocus();
110
+ }
111
  };
112
 
113
  // Calculate Rnd props based on state
114
  const rndProps = isMaximized ? {
115
+ position: { x: 0, y: 32 }, // 32px for TopBar offset (h-8 = 32px)
116
  size: { width: typeof window !== 'undefined' ? window.innerWidth : '100vw',
117
+ height: typeof window !== 'undefined' ? window.innerHeight - 32 : 'calc(100vh - 32px)' },
118
  disableDragging: true,
119
  enableResizing: false
120
  } : {
 
129
  {...rndProps}
130
  minWidth={400}
131
  minHeight={300}
 
132
  dragHandleClassName="window-drag-handle"
133
  enableResizing={!isMaximized && resizable}
134
  disableDragging={isMaximized}
 
137
  setIsDraggingOrResizing(true);
138
  bringToFront();
139
  }}
140
+ onDrag={(e, d) => {
141
+ // Prevent dragging above TopBar during drag
142
+ if (d.y < 32) {
143
+ return false;
144
+ }
145
+ }}
146
  onDragStop={(e, d) => {
147
  setIsDraggingOrResizing(false);
148
+ if (!isMaximized) {
149
+ // Ensure window doesn't go above TopBar
150
+ const newY = Math.max(d.y, 32);
151
+ setCurrentPosition({ x: d.x, y: newY });
152
+ }
153
  }}
154
  onResizeStart={() => {
155
  setIsDraggingOrResizing(true);
 
162
  width: ref.offsetWidth,
163
  height: ref.offsetHeight,
164
  });
165
+ // Ensure window doesn't go above TopBar after resize
166
+ const newY = Math.max(position.y, 32);
167
+ setCurrentPosition({ ...position, y: newY });
168
  }
169
  }}
170
  className="absolute"
171
+ style={{ zIndex: zIndex || 1000 }}
172
  >
173
  <div
174
  className={`h-full macos-window flex flex-col ${className} ${windowClass}`}
175
+ onMouseDown={bringToFront}
176
  >
177
  <div
178
  className={`window-drag-handle h-10 flex items-center px-4 space-x-4 border-b cursor-move ${headerClass} ${headerClassName}`}