@@ -7,9 +7,28 @@ import Loading from "../../components/common/loading";
77
88const LECTURE_CALENDAR_FEED_URL =
99 "https://www.gpumode.com/api/events/calendar.ics" ;
10- const GOOGLE_CALENDAR_SUBSCRIBE_URL = `https://calendar.google.com/calendar/r?cid=${ encodeURIComponent (
11- LECTURE_CALENDAR_FEED_URL ,
12- ) } `;
10+ const GOOGLE_CALENDAR_ADD_BY_URL =
11+ "https://calendar.google.com/calendar/r/settings/addbyurl" ;
12+
13+ async function copyCalendarFeedUrl ( ) : Promise < void > {
14+ if ( navigator . clipboard ?. writeText ) {
15+ await navigator . clipboard . writeText ( LECTURE_CALENDAR_FEED_URL ) ;
16+ return ;
17+ }
18+
19+ const textarea = document . createElement ( "textarea" ) ;
20+ textarea . value = LECTURE_CALENDAR_FEED_URL ;
21+ textarea . style . position = "fixed" ;
22+ textarea . style . opacity = "0" ;
23+ document . body . appendChild ( textarea ) ;
24+ textarea . select ( ) ;
25+ const copied = document . execCommand ( "copy" ) ;
26+ document . body . removeChild ( textarea ) ;
27+
28+ if ( ! copied ) {
29+ throw new Error ( "Unable to copy calendar feed URL" ) ;
30+ }
31+ }
1332
1433const styles = {
1534 container : {
@@ -326,6 +345,16 @@ export default function Lectures() {
326345 const [ events , setEvents ] = useState < DiscordEvent [ ] > ( [ ] ) ;
327346 const [ loading , setLoading ] = useState ( true ) ;
328347 const [ error , setError ] = useState < string | null > ( null ) ;
348+ const [ calendarCopyError , setCalendarCopyError ] = useState ( false ) ;
349+
350+ const openGoogleCalendarSubscription = async ( ) => {
351+ try {
352+ await copyCalendarFeedUrl ( ) ;
353+ window . location . assign ( GOOGLE_CALENDAR_ADD_BY_URL ) ;
354+ } catch {
355+ setCalendarCopyError ( true ) ;
356+ }
357+ } ;
329358
330359 useEffect ( ( ) => {
331360 fetchEvents ( )
@@ -412,16 +441,25 @@ export default function Lectures() {
412441 .
413442 </ Typography >
414443 < Button
415- component = "a"
416- href = { GOOGLE_CALENDAR_SUBSCRIBE_URL }
417- target = "_blank"
418- rel = "noopener noreferrer"
444+ onClick = { openGoogleCalendarSubscription }
419445 variant = "outlined"
420446 size = "small"
421- sx = { { marginBottom : "16px" , textTransform : "none" } }
447+ sx = { { textTransform : "none" } }
422448 >
423- Subscribe in Google Calendar
449+ Copy URL and open Google Calendar
424450 </ Button >
451+ < Typography
452+ sx = { {
453+ color : calendarCopyError ? "error.main" : "text.secondary" ,
454+ fontSize : "0.8rem" ,
455+ marginTop : "8px" ,
456+ marginBottom : "16px" ,
457+ } }
458+ >
459+ { calendarCopyError
460+ ? `Copy ${ LECTURE_CALENDAR_FEED_URL } , then open Google Calendar → Other calendars → From URL.`
461+ : "Paste the copied URL into “URL of calendar,” then click Add calendar. You only need to do this once." }
462+ </ Typography >
425463 { loading ? (
426464 < Loading />
427465 ) : error ? (
0 commit comments