/* * Copyright (c) 2019 - 2020 Arnaud Vergnet. * * This file is part of Campus INSAT. * * Campus INSAT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Campus INSAT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Campus INSAT. If not, see . */ import { DarkTheme, DefaultTheme } from 'react-native-paper'; import { Appearance } from 'react-native-appearance'; import AsyncStorageManager from './AsyncStorageManager'; import AprilFoolsManager from './AprilFoolsManager'; const colorScheme = Appearance.getColorScheme(); declare global { namespace ReactNativePaper { interface ThemeColors { primary: string; accent: string; border: string; tabIcon: string; card: string; dividerBackground: string; ripple: string; textDisabled: string; icon: string; subtitle: string; success: string; warning: string; danger: string; // Calendar/Agenda agendaBackgroundColor: string; agendaDayTextColor: string; // PROXIWASH proxiwashFinishedColor: string; proxiwashReadyColor: string; proxiwashRunningColor: string; proxiwashRunningNotStartedColor: string; proxiwashRunningBgColor: string; proxiwashBrokenColor: string; proxiwashErrorColor: string; proxiwashUnknownColor: string; // Screens planningColor: string; proximoColor: string; proxiwashColor: string; menuColor: string; tutorinsaColor: string; // Tetris tetrisBackground: string; tetrisScore: string; tetrisI: string; tetrisO: string; tetrisT: string; tetrisS: string; tetrisZ: string; tetrisJ: string; tetrisL: string; gameGold: string; gameSilver: string; gameBronze: string; // Mascot Popup mascotMessageArrow: string; } } } const CustomWhiteTheme: ReactNativePaper.Theme = { ...DefaultTheme, colors: { ...DefaultTheme.colors, primary: '#be1522', accent: '#be1522', border: '#e2e2e2', tabIcon: '#929292', card: '#fff', dividerBackground: '#e2e2e2', ripple: 'rgba(0,0,0,0.2)', textDisabled: '#c1c1c1', icon: '#5d5d5d', subtitle: '#707070', success: '#5cb85c', warning: '#f0ad4e', danger: '#d9534f', // Calendar/Agenda agendaBackgroundColor: '#f3f3f4', agendaDayTextColor: '#636363', // PROXIWASH proxiwashFinishedColor: '#a5dc9d', proxiwashReadyColor: 'transparent', proxiwashRunningColor: '#a0ceff', proxiwashRunningNotStartedColor: '#c9e0ff', proxiwashRunningBgColor: '#c7e3ff', proxiwashBrokenColor: '#ffa8a2', proxiwashErrorColor: '#ffa8a2', proxiwashUnknownColor: '#b6b6b6', // Screens planningColor: '#d9b10a', proximoColor: '#ec5904', proxiwashColor: '#1fa5ee', menuColor: '#e91314', tutorinsaColor: '#f93943', // Tetris tetrisBackground: '#f0f0f0', tetrisScore: '#e2bd33', tetrisI: '#3cd9e6', tetrisO: '#ffdd00', tetrisT: '#a716e5', tetrisS: '#09c528', tetrisZ: '#ff0009', tetrisJ: '#2a67e3', tetrisL: '#da742d', gameGold: '#ffd610', gameSilver: '#7b7b7b', gameBronze: '#a15218', // Mascot Popup mascotMessageArrow: '#dedede', }, }; const CustomDarkTheme: ReactNativePaper.Theme = { ...DarkTheme, colors: { ...DarkTheme.colors, primary: '#be1522', accent: '#be1522', border: '#222222', tabIcon: '#6d6d6d', card: 'rgb(18,18,18)', dividerBackground: '#222222', ripple: 'rgba(255,255,255,0.2)', textDisabled: '#5b5b5b', icon: '#b3b3b3', subtitle: '#aaaaaa', success: '#5cb85c', warning: '#f0ad4e', danger: '#d9534f', // Calendar/Agenda agendaBackgroundColor: '#171717', agendaDayTextColor: '#6d6d6d', // PROXIWASH proxiwashFinishedColor: '#31682c', proxiwashReadyColor: 'transparent', proxiwashRunningColor: '#213c79', proxiwashRunningNotStartedColor: '#1e263e', proxiwashRunningBgColor: '#1a2033', proxiwashBrokenColor: '#7e2e2f', proxiwashErrorColor: '#7e2e2f', proxiwashUnknownColor: '#535353', // Screens planningColor: '#d99e09', proximoColor: '#ec5904', proxiwashColor: '#1fa5ee', menuColor: '#b81213', tutorinsaColor: '#f93943', // Tetris tetrisBackground: '#181818', tetrisScore: '#e2d707', tetrisI: '#30b3be', tetrisO: '#c1a700', tetrisT: '#9114c7', tetrisS: '#08a121', tetrisZ: '#b50008', tetrisJ: '#0f37b9', tetrisL: '#b96226', gameGold: '#ffd610', gameSilver: '#7b7b7b', gameBronze: '#a15218', // Mascot Popup mascotMessageArrow: '#323232', }, }; /** * Singleton class used to manage themes */ export default class ThemeManager { static instance: ThemeManager | null = null; updateThemeCallback: null | (() => void); constructor() { this.updateThemeCallback = null; } /** * Get this class instance or create one if none is found * * @returns {ThemeManager} */ static getInstance(): ThemeManager { if (ThemeManager.instance == null) { ThemeManager.instance = new ThemeManager(); } return ThemeManager.instance; } /** * Gets night mode status. * If Follow System Preferences is enabled, will first use system theme. * If disabled or not available, will use value stored din preferences * * @returns {boolean} Night mode state */ static getNightMode(): boolean { return ( (AsyncStorageManager.getBool( AsyncStorageManager.PREFERENCES.nightMode.key ) && (!AsyncStorageManager.getBool( AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key ) || colorScheme === 'no-preference')) || (AsyncStorageManager.getBool( AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key ) && colorScheme === 'dark') ); } /** * Get the current theme based on night mode and events * * @returns {ReactNativePaper.Theme} The current theme */ static getCurrentTheme(): ReactNativePaper.Theme { if (AprilFoolsManager.getInstance().isAprilFoolsEnabled()) { return AprilFoolsManager.getAprilFoolsTheme(CustomWhiteTheme); } return ThemeManager.getBaseTheme(); } /** * Get the theme based on night mode * * @return {ReactNativePaper.Theme} The theme */ static getBaseTheme(): ReactNativePaper.Theme { if (ThemeManager.getNightMode()) { return CustomDarkTheme; } return CustomWhiteTheme; } /** * Sets the function to be called when the theme is changed (allows for general reload of the app) * * @param callback Function to call after theme change */ setUpdateThemeCallback(callback: () => void) { this.updateThemeCallback = callback; } /** * Set night mode and save it to preferences * * @param isNightMode True to enable night mode, false to disable */ setNightMode(isNightMode: boolean) { AsyncStorageManager.set( AsyncStorageManager.PREFERENCES.nightMode.key, isNightMode ); if (this.updateThemeCallback != null) { this.updateThemeCallback(); } } }