58 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			58 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
// Copyright 2022 Signal Messenger, LLC
 | 
						|
// SPDX-License-Identifier: AGPL-3.0-only
 | 
						|
 | 
						|
import { useState, useEffect } from 'react';
 | 
						|
 | 
						|
import { ThemeType } from '../types/Util';
 | 
						|
 | 
						|
// Note that this hook is used in non-main windows (e.g. "About" and
 | 
						|
// "Debug Log" windows), and thus can't access redux state.
 | 
						|
export const useTheme = (): ThemeType => {
 | 
						|
  const [theme, updateTheme] = useState(ThemeType.light);
 | 
						|
 | 
						|
  // Storybook support
 | 
						|
  const { SignalContext } = window;
 | 
						|
 | 
						|
  useEffect(() => {
 | 
						|
    const abortController = new AbortController();
 | 
						|
 | 
						|
    const { signal } = abortController;
 | 
						|
 | 
						|
    async function applyTheme() {
 | 
						|
      let newTheme = await SignalContext.Settings.themeSetting.getValue();
 | 
						|
      if (newTheme === 'system') {
 | 
						|
        newTheme = SignalContext.nativeThemeListener.getSystemTheme();
 | 
						|
      }
 | 
						|
 | 
						|
      if (signal.aborted) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      if (newTheme === 'dark') {
 | 
						|
        updateTheme(ThemeType.dark);
 | 
						|
      } else {
 | 
						|
        updateTheme(ThemeType.light);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    async function loop() {
 | 
						|
      while (!signal.aborted) {
 | 
						|
        // eslint-disable-next-line no-await-in-loop
 | 
						|
        await applyTheme();
 | 
						|
 | 
						|
        // eslint-disable-next-line no-await-in-loop
 | 
						|
        await SignalContext.Settings.waitForChange();
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    SignalContext.nativeThemeListener.subscribe(applyTheme);
 | 
						|
    void loop();
 | 
						|
 | 
						|
    return () => {
 | 
						|
      abortController.abort();
 | 
						|
      SignalContext.nativeThemeListener.unsubscribe(applyTheme);
 | 
						|
    };
 | 
						|
  }, [updateTheme, SignalContext.Settings, SignalContext.nativeThemeListener]);
 | 
						|
 | 
						|
  return theme;
 | 
						|
};
 |