1- import { useEffect , useState } from "react" ;
1+ import { useCallback , useEffect , useState } from "react" ;
22import { createRoot } from "react-dom/client" ;
3- import { Button } from "./components/Button" ;
43import browser from "webextension-polyfill" ;
4+ import { Button } from "./components/Button" ;
5+ import { icsToJson } from "./utils/icsToJson" ;
6+
7+ interface CalendarEvent {
8+ summary : string ;
9+ description : string | null ;
10+ location : string | null ;
11+ startDate : string ;
12+ endDate : string ;
13+ status : string ;
14+ }
15+
16+ interface CalendarSource {
17+ url : string ;
18+ cacheTimestamp : string ;
19+ events : CalendarEvent [ ] ;
20+ }
521
622function Options ( ) {
723 const [ calendarUrls , setCalendarUrls ] = useState < string [ ] > ( [ "" ] ) ;
@@ -14,6 +30,9 @@ function Options() {
1430 "right-top" | "right-bottom" | "left-top" | "left-bottom"
1531 > ( "right-top" ) ;
1632 const [ minimalMode , setMinimalMode ] = useState ( false ) ;
33+ const [ debugMode , setDebugMode ] = useState ( false ) ;
34+ const [ calendarData , setCalendarData ] = useState < CalendarSource [ ] > ( [ ] ) ;
35+ const [ isLoading , setIsLoading ] = useState ( false ) ;
1736
1837 useEffect ( ( ) => {
1938 // Listen for changes in storage
@@ -68,6 +87,7 @@ function Options() {
6887 "enforceWorkingHours" ,
6988 "buttonPosition" ,
7089 "minimalMode" ,
90+ "icsCache" ,
7191 ] ) ;
7292
7393 if ( result . calendarUrls ) {
@@ -146,6 +166,75 @@ function Options() {
146166 } ) ;
147167 } ;
148168
169+ const loadCalendarData = useCallback ( async ( ) => {
170+ console . log ( "Loading calendar data..." ) ;
171+ setIsLoading ( true ) ;
172+ try {
173+ const { icsCache } = await browser . storage . local . get ( "icsCache" ) ;
174+ console . log ( "Retrieved icsCache:" , icsCache ) ;
175+
176+ if ( ! icsCache ) {
177+ console . log ( "No icsCache found, setting empty data" ) ;
178+ setCalendarData ( [ ] ) ;
179+ return ;
180+ }
181+
182+ const allEvents : CalendarSource [ ] = [ ] ;
183+
184+ for ( const [ url , cacheData ] of Object . entries ( icsCache ) ) {
185+ const cache = cacheData as { data : string ; timestamp : number } ;
186+ try {
187+ const events = icsToJson ( cache . data ) ;
188+ console . log ( `Parsed ${ events . length } events for ${ url } ` ) ;
189+ allEvents . push ( {
190+ url,
191+ cacheTimestamp : new Date ( cache . timestamp ) . toLocaleString ( ) ,
192+ events,
193+ } ) ;
194+ } catch ( error ) {
195+ console . error ( `Error parsing ICS data for ${ url } :` , error ) ;
196+ }
197+ }
198+
199+ console . log ( "Setting calendar data:" , allEvents ) ;
200+ setCalendarData ( allEvents ) ;
201+ } catch ( error ) {
202+ console . error ( "Error loading calendar data:" , error ) ;
203+ alert ( `Error loading calendar data: ${ error } ` ) ;
204+ } finally {
205+ setIsLoading ( false ) ;
206+ }
207+ } , [ ] ) ;
208+
209+ // watch icsCache changes in real-time
210+ useEffect ( ( ) => {
211+ if ( ! debugMode ) return ;
212+
213+ const handleIcsCacheChange = (
214+ changes : { [ key : string ] : browser . Storage . StorageChange } ,
215+ areaName : string
216+ ) => {
217+ if ( areaName !== "local" ) return ;
218+
219+ if ( changes . icsCache ) {
220+ loadCalendarData ( ) ;
221+ }
222+ } ;
223+
224+ browser . storage . onChanged . addListener ( handleIcsCacheChange ) ;
225+
226+ // when debug mode is enabled, load the initial data
227+ loadCalendarData ( ) ;
228+
229+ return ( ) => {
230+ browser . storage . onChanged . removeListener ( handleIcsCacheChange ) ;
231+ } ;
232+ } , [ debugMode , loadCalendarData ] ) ;
233+
234+ const handleDebugToggle = ( ) => {
235+ setDebugMode ( ! debugMode ) ;
236+ } ;
237+
149238 return (
150239 < div style = { { padding : "20px" , maxWidth : "600px" , margin : "0 auto" } } >
151240 < h1 > Google Calendar Tonton - Settings</ h1 >
@@ -351,6 +440,120 @@ function Options() {
351440 Use minimal button mode (icon only)
352441 </ label >
353442 </ div >
443+ < div style = { { marginBottom : "20px" } } >
444+ < label style = { { display : "flex" , alignItems : "center" , gap : "8px" } } >
445+ < input
446+ type = "checkbox"
447+ checked = { debugMode }
448+ onChange = { handleDebugToggle }
449+ />
450+ Debug Mode (Show Calendar Data)
451+ </ label >
452+ </ div >
453+ { debugMode && (
454+ < div style = { { marginBottom : "20px" } } >
455+ < h2 > Calendar Debug Information</ h2 >
456+ < div style = { { marginBottom : "16px" } } >
457+ < button
458+ type = "button"
459+ onClick = { ( ) => {
460+ console . log ( "Refresh button clicked" ) ;
461+ loadCalendarData ( ) ;
462+ } }
463+ disabled = { isLoading }
464+ style = { {
465+ marginRight : "10px" ,
466+ padding : "8px 16px" ,
467+ borderRadius : "4px" ,
468+ border : "1px solid #ccc" ,
469+ background : isLoading ? "#e0e0e0" : "#f5f5f5" ,
470+ cursor : isLoading ? "not-allowed" : "pointer" ,
471+ opacity : isLoading ? 0.6 : 1 ,
472+ } }
473+ >
474+ { isLoading ? "Loading..." : "Refresh Calendar Data" }
475+ </ button >
476+ < span style = { { fontSize : "12px" , color : "#666" } } >
477+ { isLoading
478+ ? "Updating..."
479+ : `Last updated: ${ new Date ( ) . toLocaleTimeString ( ) } ` }
480+ </ span >
481+ </ div >
482+ { calendarData . length === 0 ? (
483+ < p > No calendar data found in cache.</ p >
484+ ) : (
485+ calendarData . map ( ( calendarSource ) => (
486+ < div
487+ key = { calendarSource . url }
488+ style = { {
489+ marginBottom : "24px" ,
490+ padding : "16px" ,
491+ border : "1px solid #ddd" ,
492+ borderRadius : "4px" ,
493+ background : "#f9f9f9" ,
494+ } }
495+ >
496+ < h3 > Calendar Source</ h3 >
497+ < p style = { { overflowWrap : "anywhere" } } >
498+ < strong > URL:</ strong > { calendarSource . url }
499+ </ p >
500+ < p >
501+ < strong > Cache Updated:</ strong > { " " }
502+ { calendarSource . cacheTimestamp }
503+ </ p >
504+ < p >
505+ < strong > Events Found:</ strong > { calendarSource . events . length }
506+ </ p >
507+
508+ { calendarSource . events . length > 0 && (
509+ < div style = { { marginTop : "16px" } } >
510+ < h4 > Events:</ h4 >
511+ < div style = { { maxHeight : "300px" , overflowY : "auto" } } >
512+ { calendarSource . events . map ( ( event ) => (
513+ < div
514+ key = { `${ event . startDate } -${ event . summary } ` }
515+ style = { {
516+ marginBottom : "12px" ,
517+ padding : "12px" ,
518+ border : "1px solid #ccc" ,
519+ borderRadius : "4px" ,
520+ background : "#fff" ,
521+ } }
522+ >
523+ < p >
524+ < strong > Title:</ strong > { event . summary }
525+ </ p >
526+ < p >
527+ < strong > Start:</ strong > { " " }
528+ { new Date ( event . startDate ) . toLocaleString ( ) }
529+ </ p >
530+ < p >
531+ < strong > End:</ strong > { " " }
532+ { new Date ( event . endDate ) . toLocaleString ( ) }
533+ </ p >
534+ < p >
535+ < strong > Status:</ strong > { event . status }
536+ </ p >
537+ { event . location && (
538+ < p >
539+ < strong > Location:</ strong > { event . location }
540+ </ p >
541+ ) }
542+ { event . description && (
543+ < p >
544+ < strong > Description:</ strong > { event . description }
545+ </ p >
546+ ) }
547+ </ div >
548+ ) ) }
549+ </ div >
550+ </ div >
551+ ) }
552+ </ div >
553+ ) )
554+ ) }
555+ </ div >
556+ ) }
354557 < div style = { { display : "flex" , alignItems : "center" } } >
355558 < Button onClick = { handleSave } variant = "other" >
356559 Save
0 commit comments