diff --git a/plugins/Oomox/Controller/Oomox.php b/plugins/Oomox/Controller/Oomox.php new file mode 100644 index 0000000000..378fb9b652 --- /dev/null +++ b/plugins/Oomox/Controller/Oomox.php @@ -0,0 +1,132 @@ +. + +// }}} + +namespace Plugin\Oomox\Controller; + +use App\Core\DB\DB; +use App\Core\Form; +use function App\Core\I18n\_m; +use App\Util\Common; +use App\Util\Exception\RedirectException; +use App\Util\Exception\ServerException; +use Plugin\ProfileColor\Entity; +use Symfony\Component\Form\Extension\Core\Type\ColorType; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\HttpFoundation\Request; + +/** + * Oomox controller + * + * @package GNUsocial + * @category Oomox + * + * @author Eliseu Amaro + * @copyright 2020 Free Software Foundation, Inc http://www.fsf.org + * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later + */ +class Oomox +{ + /** + * Change theme colours + * + * @throws RedirectException + * @throws ServerException + */ + public static function oomoxSettings(Request $request): array + { + $actor = Common::actor(); + $actor_id = $actor->getId(); + + $current_oomox_settings = DB::find('profile_color', ['actor_id' => $actor_id]); + + $form = Form::create([ + ['colour_foreground', ColorType::class, [ + 'html5' => true, + 'data' => $current_oomox_settings ? $current_oomox_settings->getColourForeground() : '#09090d', + 'label' => _m('Profile background color'), + 'help' => _m('Choose your Profile background color'), ], + ], + ['colour_background_hard', ColorType::class, [ + 'html5' => true, + 'data' => $current_oomox_settings ? $current_oomox_settings->getColourBackgroundHard() : '#ebebeb', + 'label' => _m('Profile foreground color'), + 'help' => _m('Choose your Profile foreground color'), ], + ], + ['colour_background_card', ColorType::class, [ + 'html5' => true, + 'data' => $current_oomox_settings ? $current_oomox_settings->getColourBackgroundCard() : '#f0f0f0', + 'label' => _m('Profile background color'), + 'help' => _m('Choose your Profile background color'), ], + ], + ['colour_border', ColorType::class, [ + 'html5' => true, + 'data' => $current_oomox_settings ? $current_oomox_settings->getColourBorder() : '#d5d5d5', + 'label' => _m('Profile foreground color'), + 'help' => _m('Choose your Profile foreground color'), ], + ], + ['colour_accent', ColorType::class, [ + 'html5' => true, + 'data' => $current_oomox_settings ? $current_oomox_settings->getColourAccent() : '#a22430', + 'label' => _m('Profile foreground color'), + 'help' => _m('Choose your Profile foreground color'), ], + ], + ['colour_shadow', ColorType::class, [ + 'html5' => true, + 'data' => $current_oomox_settings ? $current_oomox_settings->getColourShadow() : '#24243416', + 'label' => _m('Profile foreground color'), + 'help' => _m('Choose your Profile foreground color'), ], + ], + ['hidden', HiddenType::class, []], + ['save_oomox_colours', SubmitType::class, ['label' => _m('Submit')]], + ]); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + if ($current_oomox_settings !== null) { + DB::remove($current_oomox_settings); + DB::flush(); + } + + $data = $form->getData(); + $current_oomox_settings = Entity\Oomox::create( + [ + 'actor_id' => $actor_id, + 'colour_foreground' => $data['colour_foreground'], + 'colour_background_hard' => $data['colour_background_hard'], + 'colour_background_card' => $data['colour_background_card'], + 'colour_border' => $data['colour_border'], + 'colour_accent' => $data['colour_accent'], + 'colour_shadow' => $data['colour_shadow'], + ] + ); + DB::persist($current_oomox_settings); + DB::flush(); + + throw new RedirectException(); + } + + return ['_template' => 'oomox/oomoxSettings.html.twig', 'oomox' => $form->createView()]; + } +} diff --git a/plugins/Oomox/Entity/Oomox.php b/plugins/Oomox/Entity/Oomox.php new file mode 100644 index 0000000000..483632c723 --- /dev/null +++ b/plugins/Oomox/Entity/Oomox.php @@ -0,0 +1,124 @@ +. + +// }}} + +namespace Plugin\Oomox\Entity; + +use App\Core\Entity; +use DateTimeInterface; + +/** + * For storing theme colour settings + * + * @package GNUsocial + * @category Oomox + * + * @author Eliseu Amaro + * @copyright 2020 Free Software Foundation, Inc http://www.fsf.org + * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later + */ +class Oomox extends Entity +{ + // {{{ Autocode + // @codeCoverageIgnoreStart + private int $actor_id; + private ?string $color; + private ?string $background; + private DateTimeInterface $created; + private DateTimeInterface $modified; + + public function setActorId(int $actor_id): self + { + $this->actor_id = $actor_id; + return $this; + } + + public function getActorId(): int + { + return $this->actor_id; + } + + public function setColor(string $color): self + { + $this->color = $color; + return $this; + } + + public function getColor(): ?string + { + return $this->color; + } + + public function setBackground(string $background): self + { + $this->background = $background; + return $this; + } + + public function getBackground(): ?string + { + return $this->background; + } + + public function setCreated(DateTimeInterface $created): self + { + $this->created = $created; + return $this; + } + + public function getCreated(): DateTimeInterface + { + return $this->created; + } + + public function setModified(DateTimeInterface $modified): self + { + $this->modified = $modified; + return $this; + } + + public function getModified(): DateTimeInterface + { + return $this->modified; + } + + // @codeCoverageIgnoreEnd + // }}} Autocode + public static function schemaDef(): array + { + return [ + 'name' => 'oomox', + 'fields' => [ + 'actor_id' => ['type' => 'int', 'foreign key' => true, 'target' => 'Actor.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to actor table'], + 'colour_foreground' => ['type' => 'text', 'description' => 'color hex code'], + 'colour_background_hard' => ['type' => 'text', 'description' => 'color hex code'], + 'colour_background_card' => ['type' => 'text', 'description' => 'color hex code'], + 'colour_border' => ['type' => 'text', 'description' => 'color hex code'], + 'colour_accent' => ['type' => 'text', 'description' => 'color hex code'], + 'colour_shadow' => ['type' => 'text', 'description' => 'color hex code'], + 'created' => ['type' => 'datetime', 'not null' => true, 'description' => 'date this record was created', 'default' => 'CURRENT_TIMESTAMP'], + 'modified' => ['type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified', 'default' => 'CURRENT_TIMESTAMP'], + ], + 'primary key' => ['actor_id'], + ]; + } +} diff --git a/plugins/Oomox/Oomox.php b/plugins/Oomox/Oomox.php new file mode 100644 index 0000000000..779dcae51a --- /dev/null +++ b/plugins/Oomox/Oomox.php @@ -0,0 +1,94 @@ +. + +// }}} + +namespace Plugin\Oomox; + +use App\Core\DB\DB; +use App\Core\Event; +use App\Core\Modules\Plugin; +use App\Core\Router\RouteLoader; +use App\Util\Common; +use App\Util\Exception\NotFoundException; +use App\Util\Exception\RedirectException; +use App\Util\Exception\ServerException; +use App\Util\Formatting; +use Plugin\Oomox\Controller as C; +use Symfony\Component\HttpFoundation\Request; + +/** + * Profile Color plugin main class + * + * @package GNUsocial + * @category Oomox + * + * @author Eliseu Amaro + * @copyright 2020 Free Software Foundation, Inc http://www.fsf.org + * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later + */ +class Oomox extends Plugin +{ + /** + * Map URLs to actions + * + * @return bool hook value; true means continue processing, false means stop + */ + public function onAddRoute(RouteLoader $r): bool + { + $r->connect('settings_oomox', 'settings/oomox', [Controller\Oomox::class, 'oomoxSettings']); + return Event::next; + } + + /** + * @throws RedirectException + * @throws ServerException + */ + public function onPopulateProfileSettingsTabs(Request $request, array &$tabs): bool + { + $tabs[] = [ + 'title' => 'Theme colours', + 'desc' => 'Change the theme colours.', + 'controller' => C\Oomox::oomoxSettings($request), + ]; + + return Event::next; + } + + public function onOverrideStylesheet(string $original_stylesheet, string &$response) + { + $check_user = !\is_null(Common::user()); + + if ($check_user && $original_stylesheet === 'assets/default_theme/css/root.css') { + $actor_id = Common::actor()->getId(); + + try { + $oomox_table = DB::findOneBy('oomox', ['actor_id' => $actor_id]); + } catch (NotFoundException $e) { + return Event::next; + } + + $res[] = Formatting::twigRenderFile('/oomox/root_override.css.twig', ['oomox' => $oomox_table]); + return Event::stop; + } + + return Event::next; + } +} diff --git a/plugins/Oomox/templates/oomox/oomoxSettings.html.twig b/plugins/Oomox/templates/oomox/oomoxSettings.html.twig new file mode 100644 index 0000000000..d3155154c3 --- /dev/null +++ b/plugins/Oomox/templates/oomox/oomoxSettings.html.twig @@ -0,0 +1,3 @@ +
+ {{ form(oomox) }} +
\ No newline at end of file diff --git a/plugins/Oomox/templates/oomox/root_override.css.twig b/plugins/Oomox/templates/oomox/root_override.css.twig new file mode 100644 index 0000000000..7081bb2acb --- /dev/null +++ b/plugins/Oomox/templates/oomox/root_override.css.twig @@ -0,0 +1,39 @@ +:root { + --smaller: .6rem; + --default: 1rem; + --small: 1.3rem; + --medium: 1.62rem; + --big: 3rem; +} + +@media(prefers-color-scheme:dark) { + :root { + --foreground: {{ oomox.getColourForeground() | default('#f0f6f6') }}; + --background-hard: {{ oomox.getColourBackgroundHard() | default('#141216') }}; + --background-card: {{ oomox.getColourBackgroundCard() | default('#131217') }}; + --border: {{ oomox.getColourBorder() | default('#201f25') }}; + --accent: {{ oomox.getColourAccent() | default('#5ddbcf') }}; + --shadow: 0 0 12px 0 {{ oomox.getColourShadow() | default('#01010166') }}; + + --shadow-inset-accent: inset 0 0 0 2px var(--accent); + --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round; + --gradient: linear-gradient(10deg,var(--border) 0,transparent 90%) !important; + --gradient-backwards: linear-gradient(290deg,var(--border) 0,var(--background-card) 100%) !important; + } +} + +@media(prefers-color-scheme:light) { + :root { + --foreground: {{ oomox.getColourForeground() | default('#09090d') }}; + --background-hard: {{ oomox.getColourBackgroundHard() | default('#ebebeb') }}; + --background-card: {{ oomox.getColourBackgroundCard() | default('#f0f0f0') }}; + --border: {{ oomox.getColourBorder() | default('#d5d5d5') }}; + --accent: {{ oomox.getColourAccent() | default('#a22430') }}; + --shadow: 0 0 12px 0 {{ oomox.getColourShadow() | default('#24243416') }}; + + --shadow-inset-accent: inset 0 0 0 2px var(--accent); + --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round; + --gradient: linear-gradient(10deg,var(--background-hard) 0,transparent 60%) !important; + --gradient-backwards: linear-gradient(290deg,var(--background-hard) 0,var(--background-card) 100%) !important; + } +} \ No newline at end of file diff --git a/public/assets/default_theme/css/base.css b/public/assets/default_theme/css/base.css index 49eaa79b79..cc318b175f 100644 --- a/public/assets/default_theme/css/base.css +++ b/public/assets/default_theme/css/base.css @@ -6,13 +6,13 @@ @import url("widgets/sections.css"); -:root { - --smaller: .6rem; - --default: 1rem; - --small: 1.3rem; - --medium: 1.62rem; - --big: 3rem; -} +/*:root {*/ +/* --smaller: .6rem;*/ +/* --default: 1rem;*/ +/* --small: 1.3rem;*/ +/* --medium: 1.62rem;*/ +/* --big: 3rem;*/ +/*}*/ * { -webkit-box-sizing: border-box !important; @@ -179,18 +179,18 @@ li { } @media(prefers-color-scheme:dark) { - :root { - --foreground: #f0f6f6; - --background-hard: #141216; - --background-card: #131217; - --border: #201f25; - --accent: #5ddbcf; - --shadow: 0 0 12px 0 #01010166; - --shadow-inset-accent: inset 0 0 0 2px var(--accent); - --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round; - --gradient: linear-gradient(10deg,var(--border) 0,transparent 90%) !important; - --gradient-backwards: linear-gradient(290deg,var(--border) 0,var(--background-card) 100%) !important; - } + /*:root {*/ + /* --foreground: #f0f6f6;*/ + /* --background-hard: #141216;*/ + /* --background-card: #131217;*/ + /* --border: #201f25;*/ + /* --accent: #5ddbcf;*/ + /* --shadow: 0 0 12px 0 #01010166;*/ + /* --shadow-inset-accent: inset 0 0 0 2px var(--accent);*/ + /* --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round;*/ + /* --gradient: linear-gradient(10deg,var(--border) 0,transparent 90%) !important;*/ + /* --gradient-backwards: linear-gradient(290deg,var(--border) 0,var(--background-card) 100%) !important;*/ + /*}*/ .background-image { background-color: var(--background-hard); @@ -203,18 +203,18 @@ li { } @media(prefers-color-scheme:light) { - :root { - --foreground: #09090d; - --background-hard: #ebebeb; - --background-card: #f0f0f0; - --border: #d5d5d5; - --accent: #a22430; - --shadow: 0 0 12px 0 #24243416; - --shadow-inset-accent: inset 0 0 0 2px var(--accent); - --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round; - --gradient: linear-gradient(10deg,var(--background-hard) 0,transparent 60%) !important; - --gradient-backwards: linear-gradient(290deg,var(--background-hard) 0,var(--background-card) 100%) !important; - } + /*:root {*/ + /* --foreground: #09090d;*/ + /* --background-hard: #ebebeb;*/ + /* --background-card: #f0f0f0;*/ + /* --border: #d5d5d5;*/ + /* --accent: #a22430;*/ + /* --shadow: 0 0 12px 0 #24243416;*/ + /* --shadow-inset-accent: inset 0 0 0 2px var(--accent);*/ + /* --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round;*/ + /* --gradient: linear-gradient(10deg,var(--background-hard) 0,transparent 60%) !important;*/ + /* --gradient-backwards: linear-gradient(290deg,var(--background-hard) 0,var(--background-card) 100%) !important;*/ + /*}*/ .background-image { background-color: var(--background-hard); diff --git a/public/assets/default_theme/css/root.css b/public/assets/default_theme/css/root.css new file mode 100644 index 0000000000..bb06b935f2 --- /dev/null +++ b/public/assets/default_theme/css/root.css @@ -0,0 +1,37 @@ +:root { + --smaller: .6rem; + --default: 1rem; + --small: 1.3rem; + --medium: 1.62rem; + --big: 3rem; +} + +@media(prefers-color-scheme:dark) { + :root { + --foreground: #f0f6f6; + --background-hard: #141216; + --background-card: #131217; + --border: #201f25; + --accent: #5ddbcf; + --shadow: 0 0 12px 0 #01010166; + --shadow-inset-accent: inset 0 0 0 2px var(--accent); + --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round; + --gradient: linear-gradient(10deg,var(--border) 0,transparent 90%) !important; + --gradient-backwards: linear-gradient(290deg,var(--border) 0,var(--background-card) 100%) !important; + } +} + +@media(prefers-color-scheme:light) { + :root { + --foreground: #09090d; + --background-hard: #ebebeb; + --background-card: #f0f0f0; + --border: #d5d5d5; + --accent: #a22430; + --shadow: 0 0 12px 0 #24243416; + --shadow-inset-accent: inset 0 0 0 2px var(--accent); + --background-checkerboard: repeating-conic-gradient(#ffffff66 0 90deg,#ffffff33 0 180deg) 0 0/40px 40px round; + --gradient: linear-gradient(10deg,var(--background-hard) 0,transparent 60%) !important; + --gradient-backwards: linear-gradient(290deg,var(--background-hard) 0,var(--background-card) 100%) !important; + } +} \ No newline at end of file diff --git a/src/Twig/Runtime.php b/src/Twig/Runtime.php index 2dd5c46d14..0253652127 100644 --- a/src/Twig/Runtime.php +++ b/src/Twig/Runtime.php @@ -134,6 +134,15 @@ class Runtime implements RuntimeExtensionInterface, EventSubscriberInterface return $result; } + public function handleOverrideStylesheet(string $original_asset_path): string + { + $result = ''; + if (Event::handle('OverrideStylesheet', [$original_asset_path, &$result]) !== Event::stop) { + $result = $original_asset_path; + } + return $result; + } + public function openDetails(?string $query, array $ids) { return in_array($query, $ids) ? 'open=""' : ''; diff --git a/templates/base.html.twig b/templates/base.html.twig index 28fc7c2e7c..8fbcd1f46c 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -14,8 +14,11 @@ {% block stylesheets %} + + {% set root_override = handle_override_stylesheet('assets/default_theme/css/root.css') %} + {% for stylesheet in show_stylesheets(app.request.get('_route')) %} @@ -30,9 +33,9 @@ {% endfor %} - + -