Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ThemeManager.ts 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Copyright (c) 2019 - 2020 Arnaud Vergnet.
  3. *
  4. * This file is part of Campus INSAT.
  5. *
  6. * Campus INSAT is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Campus INSAT is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. import {DarkTheme, DefaultTheme} from 'react-native-paper';
  20. import {Appearance} from 'react-native-appearance';
  21. import AsyncStorageManager from './AsyncStorageManager';
  22. import AprilFoolsManager from './AprilFoolsManager';
  23. const colorScheme = Appearance.getColorScheme();
  24. declare global {
  25. namespace ReactNativePaper {
  26. interface ThemeColors {
  27. primary: string;
  28. accent: string;
  29. border: string;
  30. tabIcon: string;
  31. card: string;
  32. dividerBackground: string;
  33. ripple: string;
  34. textDisabled: string;
  35. icon: string;
  36. subtitle: string;
  37. success: string;
  38. warning: string;
  39. danger: string;
  40. // Calendar/Agenda
  41. agendaBackgroundColor: string;
  42. agendaDayTextColor: string;
  43. // PROXIWASH
  44. proxiwashFinishedColor: string;
  45. proxiwashReadyColor: string;
  46. proxiwashRunningColor: string;
  47. proxiwashRunningNotStartedColor: string;
  48. proxiwashRunningBgColor: string;
  49. proxiwashBrokenColor: string;
  50. proxiwashErrorColor: string;
  51. proxiwashUnknownColor: string;
  52. // Screens
  53. planningColor: string;
  54. proximoColor: string;
  55. proxiwashColor: string;
  56. menuColor: string;
  57. tutorinsaColor: string;
  58. // Tetris
  59. tetrisBackground: string;
  60. tetrisScore: string;
  61. tetrisI: string;
  62. tetrisO: string;
  63. tetrisT: string;
  64. tetrisS: string;
  65. tetrisZ: string;
  66. tetrisJ: string;
  67. tetrisL: string;
  68. gameGold: string;
  69. gameSilver: string;
  70. gameBronze: string;
  71. // Mascot Popup
  72. mascotMessageArrow: string;
  73. }
  74. }
  75. }
  76. const CustomWhiteTheme: ReactNativePaper.Theme = {
  77. ...DefaultTheme,
  78. colors: {
  79. ...DefaultTheme.colors,
  80. primary: '#be1522',
  81. accent: '#be1522',
  82. border: '#e2e2e2',
  83. tabIcon: '#929292',
  84. card: '#fff',
  85. dividerBackground: '#e2e2e2',
  86. ripple: 'rgba(0,0,0,0.2)',
  87. textDisabled: '#c1c1c1',
  88. icon: '#5d5d5d',
  89. subtitle: '#707070',
  90. success: '#5cb85c',
  91. warning: '#f0ad4e',
  92. danger: '#d9534f',
  93. // Calendar/Agenda
  94. agendaBackgroundColor: '#f3f3f4',
  95. agendaDayTextColor: '#636363',
  96. // PROXIWASH
  97. proxiwashFinishedColor: '#a5dc9d',
  98. proxiwashReadyColor: 'transparent',
  99. proxiwashRunningColor: '#a0ceff',
  100. proxiwashRunningNotStartedColor: '#c9e0ff',
  101. proxiwashRunningBgColor: '#c7e3ff',
  102. proxiwashBrokenColor: '#ffa8a2',
  103. proxiwashErrorColor: '#ffa8a2',
  104. proxiwashUnknownColor: '#b6b6b6',
  105. // Screens
  106. planningColor: '#d9b10a',
  107. proximoColor: '#ec5904',
  108. proxiwashColor: '#1fa5ee',
  109. menuColor: '#e91314',
  110. tutorinsaColor: '#f93943',
  111. // Tetris
  112. tetrisBackground: '#f0f0f0',
  113. tetrisScore: '#e2bd33',
  114. tetrisI: '#3cd9e6',
  115. tetrisO: '#ffdd00',
  116. tetrisT: '#a716e5',
  117. tetrisS: '#09c528',
  118. tetrisZ: '#ff0009',
  119. tetrisJ: '#2a67e3',
  120. tetrisL: '#da742d',
  121. gameGold: '#ffd610',
  122. gameSilver: '#7b7b7b',
  123. gameBronze: '#a15218',
  124. // Mascot Popup
  125. mascotMessageArrow: '#dedede',
  126. },
  127. };
  128. const CustomDarkTheme: ReactNativePaper.Theme = {
  129. ...DarkTheme,
  130. colors: {
  131. ...DarkTheme.colors,
  132. primary: '#be1522',
  133. accent: '#be1522',
  134. border: '#222222',
  135. tabIcon: '#6d6d6d',
  136. card: 'rgb(18,18,18)',
  137. dividerBackground: '#222222',
  138. ripple: 'rgba(255,255,255,0.2)',
  139. textDisabled: '#5b5b5b',
  140. icon: '#b3b3b3',
  141. subtitle: '#aaaaaa',
  142. success: '#5cb85c',
  143. warning: '#f0ad4e',
  144. danger: '#d9534f',
  145. // Calendar/Agenda
  146. agendaBackgroundColor: '#171717',
  147. agendaDayTextColor: '#6d6d6d',
  148. // PROXIWASH
  149. proxiwashFinishedColor: '#31682c',
  150. proxiwashReadyColor: 'transparent',
  151. proxiwashRunningColor: '#213c79',
  152. proxiwashRunningNotStartedColor: '#1e263e',
  153. proxiwashRunningBgColor: '#1a2033',
  154. proxiwashBrokenColor: '#7e2e2f',
  155. proxiwashErrorColor: '#7e2e2f',
  156. proxiwashUnknownColor: '#535353',
  157. // Screens
  158. planningColor: '#d99e09',
  159. proximoColor: '#ec5904',
  160. proxiwashColor: '#1fa5ee',
  161. menuColor: '#b81213',
  162. tutorinsaColor: '#f93943',
  163. // Tetris
  164. tetrisBackground: '#181818',
  165. tetrisScore: '#e2d707',
  166. tetrisI: '#30b3be',
  167. tetrisO: '#c1a700',
  168. tetrisT: '#9114c7',
  169. tetrisS: '#08a121',
  170. tetrisZ: '#b50008',
  171. tetrisJ: '#0f37b9',
  172. tetrisL: '#b96226',
  173. gameGold: '#ffd610',
  174. gameSilver: '#7b7b7b',
  175. gameBronze: '#a15218',
  176. // Mascot Popup
  177. mascotMessageArrow: '#323232',
  178. },
  179. };
  180. /**
  181. * Singleton class used to manage themes
  182. */
  183. export default class ThemeManager {
  184. static instance: ThemeManager | null = null;
  185. updateThemeCallback: null | (() => void);
  186. constructor() {
  187. this.updateThemeCallback = null;
  188. }
  189. /**
  190. * Get this class instance or create one if none is found
  191. *
  192. * @returns {ThemeManager}
  193. */
  194. static getInstance(): ThemeManager {
  195. if (ThemeManager.instance == null) {
  196. ThemeManager.instance = new ThemeManager();
  197. }
  198. return ThemeManager.instance;
  199. }
  200. /**
  201. * Gets night mode status.
  202. * If Follow System Preferences is enabled, will first use system theme.
  203. * If disabled or not available, will use value stored din preferences
  204. *
  205. * @returns {boolean} Night mode state
  206. */
  207. static getNightMode(): boolean {
  208. return (
  209. (AsyncStorageManager.getBool(
  210. AsyncStorageManager.PREFERENCES.nightMode.key,
  211. ) &&
  212. (!AsyncStorageManager.getBool(
  213. AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key,
  214. ) ||
  215. colorScheme === 'no-preference')) ||
  216. (AsyncStorageManager.getBool(
  217. AsyncStorageManager.PREFERENCES.nightModeFollowSystem.key,
  218. ) &&
  219. colorScheme === 'dark')
  220. );
  221. }
  222. /**
  223. * Get the current theme based on night mode and events
  224. *
  225. * @returns {ReactNativePaper.Theme} The current theme
  226. */
  227. static getCurrentTheme(): ReactNativePaper.Theme {
  228. if (AprilFoolsManager.getInstance().isAprilFoolsEnabled()) {
  229. return AprilFoolsManager.getAprilFoolsTheme(CustomWhiteTheme);
  230. }
  231. return ThemeManager.getBaseTheme();
  232. }
  233. /**
  234. * Get the theme based on night mode
  235. *
  236. * @return {ReactNativePaper.Theme} The theme
  237. */
  238. static getBaseTheme(): ReactNativePaper.Theme {
  239. if (ThemeManager.getNightMode()) {
  240. return CustomDarkTheme;
  241. }
  242. return CustomWhiteTheme;
  243. }
  244. /**
  245. * Sets the function to be called when the theme is changed (allows for general reload of the app)
  246. *
  247. * @param callback Function to call after theme change
  248. */
  249. setUpdateThemeCallback(callback: () => void) {
  250. this.updateThemeCallback = callback;
  251. }
  252. /**
  253. * Set night mode and save it to preferences
  254. *
  255. * @param isNightMode True to enable night mode, false to disable
  256. */
  257. setNightMode(isNightMode: boolean) {
  258. AsyncStorageManager.set(
  259. AsyncStorageManager.PREFERENCES.nightMode.key,
  260. isNightMode,
  261. );
  262. if (this.updateThemeCallback != null) {
  263. this.updateThemeCallback();
  264. }
  265. }
  266. }