Commit 46307209 authored by Vignesh Mohankumar's avatar Vignesh Mohankumar Committed by GitHub

fix: handle addEventListener being unsupported on Safari <14 (#6426)

* fix: handle addEventListener being unsupported on Safari

* conditionally call

* Revert "conditionally call"

This reverts commit b6b7d2f0170caeca3aa8bf82ea97fd16a73cba44.

* comment

* fix

* callback

* add tests

* lint

* casting

* good pr comments

* fix
parent e73e1540
......@@ -5,6 +5,7 @@ import { atomWithStorage, useAtomValue, useUpdateAtom } from 'jotai/utils'
import ms from 'ms.macro'
import { useCallback, useEffect, useMemo } from 'react'
import { Moon, Sun } from 'react-feather'
import { addMediaQueryListener, removeMediaQueryListener } from 'utils/matchMedia'
import { Segment, SegmentedControl } from './SegmentedControl'
import { ThemedText } from './text'
......@@ -29,11 +30,17 @@ const themeModeAtom = atomWithStorage<ThemeMode>('interface_color_theme', ThemeM
export function SystemThemeUpdater() {
const setSystemTheme = useUpdateAtom(systemThemeAtom)
useEffect(() => {
DARKMODE_MEDIA_QUERY.addEventListener('change', (event) => {
const listener = useCallback(
(event: MediaQueryListEvent) => {
setSystemTheme(event.matches ? ThemeMode.DARK : ThemeMode.LIGHT)
})
}, [setSystemTheme])
},
[setSystemTheme]
)
useEffect(() => {
addMediaQueryListener(DARKMODE_MEDIA_QUERY, listener)
return () => removeMediaQueryListener(DARKMODE_MEDIA_QUERY, listener)
}, [setSystemTheme, listener])
return null
}
......
import { addMediaQueryListener, removeMediaQueryListener } from './matchMedia'
describe('addMediaQueryListener', () => {
test('adds event listener to media query', () => {
const mediaQuery = {
addEventListener: jest.fn(),
addListener: jest.fn(),
} as unknown as MediaQueryList
const listener = jest.fn()
addMediaQueryListener(mediaQuery, listener)
expect(mediaQuery.addEventListener).toHaveBeenCalledWith('change', listener)
expect(mediaQuery.addListener).not.toHaveBeenCalled()
})
test('falls back to addMediaQueryListener for older browsers', () => {
const mediaQuery = {
addListener: jest.fn(),
} as unknown as MediaQueryList
const listener = jest.fn()
addMediaQueryListener(mediaQuery, listener)
expect(mediaQuery.addListener).toHaveBeenCalledWith(listener)
})
})
describe('removeMediaQueryListener', () => {
test('removes event listener from media query', () => {
const mediaQuery = {
removeEventListener: jest.fn(),
removeListener: jest.fn(),
} as unknown as MediaQueryList
const listener = jest.fn()
removeMediaQueryListener(mediaQuery, listener)
expect(mediaQuery.removeEventListener).toHaveBeenCalledWith('change', listener)
expect(mediaQuery.removeListener).not.toHaveBeenCalled()
})
test('falls back to removeMediaQueryListener for older browsers', () => {
const mediaQuery = {
removeListener: jest.fn(),
} as unknown as MediaQueryList
const listener = jest.fn()
removeMediaQueryListener(mediaQuery, listener)
expect(mediaQuery.removeListener).toHaveBeenCalledWith(listener)
})
})
// Need to fallback to support older browsers (mainly, Safari < 14).
// See: https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList#browser_compatibility
export function addMediaQueryListener(mediaQuery: MediaQueryList, listener: (event: MediaQueryListEvent) => void) {
try {
mediaQuery.addEventListener('change', listener)
} catch (e) {
mediaQuery.addListener(listener)
}
}
export function removeMediaQueryListener(mediaQuery: MediaQueryList, listener: (event: MediaQueryListEvent) => void) {
try {
mediaQuery.removeEventListener('change', listener)
} catch (e) {
mediaQuery.removeListener(listener)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment