Oomox.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <?php
  2. declare(strict_types = 1);
  3. // {{{ License
  4. // This file is part of GNU social - https://www.gnu.org/software/social
  5. //
  6. // GNU social is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU Affero 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. // GNU social 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 Affero General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU Affero General Public License
  17. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  18. // }}}
  19. namespace Plugin\Oomox\Controller;
  20. use App\Core\Cache;
  21. use App\Core\DB\DB;
  22. use App\Core\Form;
  23. use function App\Core\I18n\_m;
  24. use App\Util\Common;
  25. use App\Util\Exception\ClientException;
  26. use App\Util\Exception\NoLoggedInUser;
  27. use App\Util\Exception\RedirectException;
  28. use App\Util\Exception\ServerException;
  29. use App\Util\Formatting;
  30. use Plugin\Oomox\Entity\Oomox as EntityOomox;
  31. use Plugin\Oomox\Oomox as PluginOomox;
  32. use Symfony\Component\Form\Extension\Core\Type\ColorType;
  33. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  34. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  35. use Symfony\Component\Form\FormInterface;
  36. use Symfony\Component\Form\SubmitButton;
  37. use Symfony\Component\HttpFoundation\Request;
  38. use Symfony\Component\HttpFoundation\Response;
  39. /**
  40. * Oomox controller
  41. *
  42. * @package GNUsocial
  43. * @category Oomox
  44. *
  45. * @author Eliseu Amaro <mail@eliseuama.ro>
  46. * @copyright 2020 Free Software Foundation, Inc http://www.fsf.org
  47. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  48. */
  49. class Oomox
  50. {
  51. /**
  52. * Generates a FormInterface depending on current theme settings and system-wide colour preference.
  53. * Receives the user's Oomox entity, and wether or not its intended for dark of light theme to change its behaviour accordingly.
  54. *
  55. * @throws ServerException
  56. */
  57. public static function getOomoxForm(?EntityOomox $current_oomox_settings, bool $is_light): FormInterface
  58. {
  59. $theme = $is_light ? 'light' : 'dark';
  60. $foreground = 'colour_foreground_' . $theme;
  61. $background_hard = 'colour_background_hard_' . $theme;
  62. $background_card = 'colour_background_card_' . $theme;
  63. $border = 'colour_border_' . $theme;
  64. $accent = 'colour_accent_' . $theme;
  65. $reset = 'colour_reset_' . $theme;
  66. $save = 'save_oomox_colours_' . $theme;
  67. if (isset($current_oomox_settings)) {
  68. if ($is_light) {
  69. $current_foreground = $current_oomox_settings->getColourForegroundLight() ?: '#09090d';
  70. $current_background_hard = $current_oomox_settings->getColourBackgroundHardLight() ?: '#ebebeb';
  71. $current_background_card = $current_oomox_settings->getColourBackgroundCardLight() ?: '#f0f0f0';
  72. $current_border = $current_oomox_settings->getColourBorderLight() ?: '#C2C2C2';
  73. $current_accent = $current_oomox_settings->getColourAccentLight() ?: '#a22430';
  74. } else {
  75. $current_foreground = $current_oomox_settings->getColourForegroundDark() ?: '#eff0f1';
  76. $current_background_hard = $current_oomox_settings->getColourBackgroundHardDark() ?: '#0E0E0F';
  77. $current_background_card = $current_oomox_settings->getColourBackgroundCardDark() ?: '#0E0E0F';
  78. $current_border = $current_oomox_settings->getColourBorderDark() ?: '#26262C';
  79. $current_accent = $current_oomox_settings->getColourAccentDark() ?: '#5ddbcf';
  80. }
  81. } else {
  82. $current_foreground = $is_light ? '#09090d' : '#eff0f1';
  83. $current_background_hard = $is_light ? '#ebebeb' : '#0E0E0F';
  84. $current_background_card = $is_light ? '#f0f0f0' : '#0E0E0F';
  85. $current_border = $is_light ? '#C2C2C2' : '#26262C';
  86. $current_accent = $is_light ? '#a22430' : '#5ddbcf';
  87. }
  88. return Form::create([
  89. [$foreground, ColorType::class, [
  90. 'html5' => true,
  91. 'data' => $current_foreground,
  92. 'label' => _m('Foreground colour'),
  93. 'help' => _m('Choose the foreground colour'), ],
  94. ],
  95. [$background_hard, ColorType::class, [
  96. 'html5' => true,
  97. 'data' => $current_background_hard,
  98. 'label' => _m('Background colour'),
  99. 'help' => _m('Choose the background colour'), ],
  100. ],
  101. [$background_card, ColorType::class, [
  102. 'html5' => true,
  103. 'data' => $current_background_card,
  104. 'label' => _m('Card background colour'),
  105. 'help' => _m('Choose the card background colour'), ],
  106. ],
  107. [$border, ColorType::class, [
  108. 'html5' => true,
  109. 'data' => $current_border,
  110. 'label' => _m('Border colour'),
  111. 'help' => _m('Choose the borders accents'), ],
  112. ],
  113. [$accent, ColorType::class, [
  114. 'html5' => true,
  115. 'data' => $current_accent,
  116. 'label' => _m('Accent colour'),
  117. 'help' => _m('Choose the accent colour'), ],
  118. ],
  119. ['hidden', HiddenType::class, []],
  120. [$reset, SubmitType::class, ['label' => _m('Reset colours to default')]],
  121. [$save, SubmitType::class, ['label' => _m('Submit')]],
  122. ]);
  123. }
  124. /**
  125. * Handles Light theme settings tab
  126. *
  127. * @throws NoLoggedInUser
  128. * @throws RedirectException
  129. * @throws ServerException
  130. */
  131. public static function oomoxSettingsLight(Request $request): array
  132. {
  133. $user = Common::ensureLoggedIn();
  134. $actor_id = $user->getId();
  135. $current_oomox_settings = PluginOomox::getEntity($user);
  136. $form_light = self::getOomoxForm($current_oomox_settings, true);
  137. $form_light->handleRequest($request);
  138. if ($form_light->isSubmitted() && $form_light->isValid()) {
  139. /** @var SubmitButton $reset_button */
  140. $reset_button = $form_light->get('colour_reset_light');
  141. if ($reset_button->isClicked()) {
  142. $current_oomox_settings?->resetTheme(true);
  143. } else {
  144. $data = $form_light->getData();
  145. $current_oomox_settings = EntityOomox::create(
  146. [
  147. 'actor_id' => $actor_id,
  148. 'colour_foreground_light' => $data['colour_foreground_light'],
  149. 'colour_background_hard_light' => $data['colour_background_hard_light'],
  150. 'colour_background_card_light' => $data['colour_background_card_light'],
  151. 'colour_border_light' => $data['colour_border_light'],
  152. 'colour_accent_light' => $data['colour_accent_light'],
  153. ],
  154. );
  155. }
  156. if ($current_oomox_settings) {
  157. if ($reset_button->isClicked()) {
  158. DB::remove(EntityOomox::getByPK($actor_id));
  159. } else {
  160. DB::merge($current_oomox_settings);
  161. }
  162. DB::flush();
  163. }
  164. throw new RedirectException();
  165. }
  166. return ['_template' => 'oomox/oomoxSettingsLight.html.twig', 'oomoxLight' => $form_light->createView()];
  167. }
  168. /**
  169. * Handles the Dark theme settings tab
  170. *
  171. * @throws NoLoggedInUser
  172. * @throws RedirectException
  173. * @throws ServerException
  174. */
  175. public static function oomoxSettingsDark(Request $request): array
  176. {
  177. $user = Common::ensureLoggedIn();
  178. $actor_id = $user->getId();
  179. $current_oomox_settings = PluginOomox::getEntity($user);
  180. $form_dark = self::getOomoxForm($current_oomox_settings, false);
  181. $form_dark->handleRequest($request);
  182. if ($form_dark->isSubmitted() && $form_dark->isValid()) {
  183. $reset_button = $form_dark->get('colour_reset_dark');
  184. /** @var SubmitButton $reset_button */
  185. if ($reset_button->isClicked()) {
  186. $current_oomox_settings?->resetTheme(false);
  187. } else {
  188. $data = $form_dark->getData();
  189. $current_oomox_settings = EntityOomox::create(
  190. [
  191. 'actor_id' => $actor_id,
  192. 'colour_foreground_dark' => $data['colour_foreground_dark'],
  193. 'colour_background_hard_dark' => $data['colour_background_hard_dark'],
  194. 'colour_background_card_dark' => $data['colour_background_card_dark'],
  195. 'colour_border_dark' => $data['colour_border_dark'],
  196. 'colour_accent_dark' => $data['colour_accent_dark'],
  197. ],
  198. );
  199. }
  200. if ($current_oomox_settings) {
  201. if ($reset_button->isClicked()) {
  202. DB::remove(EntityOomox::getByPK($actor_id));
  203. } else {
  204. DB::merge($current_oomox_settings);
  205. }
  206. DB::flush();
  207. }
  208. Cache::delete(PluginOomox::cacheKey($user));
  209. throw new RedirectException();
  210. }
  211. return ['_template' => 'oomox/oomoxSettingsDark.html.twig', 'oomoxDark' => $form_dark->createView()];
  212. }
  213. /**
  214. * Renders the resulting CSS file from user options, serves that file as a response
  215. *
  216. * @throws ClientException
  217. * @throws NoLoggedInUser
  218. * @throws ServerException
  219. */
  220. public function oomoxCSS(): Response
  221. {
  222. $user = Common::ensureLoggedIn();
  223. $oomox_table = PluginOomox::getEntity($user);
  224. if (\is_null($oomox_table)) {
  225. throw new ClientException(_m('No custom colours defined', 404));
  226. }
  227. $content = Formatting::twigRenderFile('/oomox/root_override.css.twig', ['oomox' => $oomox_table]);
  228. return new Response($content, status: 200, headers: ['content-type' => 'text/css', 'rel' => 'stylesheet']);
  229. }
  230. }