Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code improvements, fix rounding issue ... #46

Merged
merged 10 commits into from
Jan 31, 2025
Merged
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.*
!.gitignore
2 changes: 1 addition & 1 deletion Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function getDescription()
// Link to configuration page
public function getConfigUrl()
{
return Url::to(['/flex-theme/config']);
return Url::to(['/flex-theme/admin']);
}

// Module Activation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use humhub\modules\flexTheme\models\AdvancedSettings;
use Yii;

class ConfigController extends \humhub\modules\admin\components\Controller
class AdminController extends \humhub\modules\admin\components\Controller
{
public $subLayout = '@flex-theme/views/layouts/admin';

Expand All @@ -19,7 +19,7 @@ public function actionIndex()
if ($form->load(Yii::$app->request->post()) && $form->save()) {
$this->view->saved();
// Redirect instead of render to make browser reload CSS
return $this->redirect(['/flex-theme/config']);
return $this->redirect(['/flex-theme/admin']);
}

return $this->render('index', ['model' => $form]);
Expand All @@ -36,7 +36,7 @@ public function actionColors()
$this->view->saved();
}
// Redirect instead of render to make browser reload CSS
return $this->redirect(['/flex-theme/config/colors']);
return $this->redirect(['/flex-theme/admin/colors']);
}

return $this->render('colors', ['model' => $form]);
Expand All @@ -53,7 +53,7 @@ public function actionDarkColors()
$this->view->saved();
}
// Redirect instead of render to make browser reload CSS
return $this->redirect(['/flex-theme/config/dark-colors']);
return $this->redirect(['/flex-theme/admin/dark-colors']);
}

return $this->render('dark-colors', ['model' => $form]);
Expand Down Expand Up @@ -90,7 +90,7 @@ public function actionAdvanced()
if ($config->save() && $colorSettings->save() && $darkColorSettings->save()) {
$this->view->saved();
// Redirect instead of render to make browser reload CSS
return $this->redirect(['/flex-theme/config/advanced']);
return $this->redirect(['/flex-theme/admin/advanced']);
}
}

Expand Down
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## TBA
- Fix #39: rounding issue in ColorHelper - thanks to @marc-farre
- Fix #42: Division by zero (when trying to lighten white color)
- Fix #43: Invalid faded color calculated from 3 digits base color
- Enh #45: Add option to reset all colors of the current form
Expand Down
6 changes: 0 additions & 6 deletions docs/INSTALLATION.md

This file was deleted.

75 changes: 45 additions & 30 deletions helpers/ColorHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@

namespace humhub\modules\flexTheme\helpers;

/**
* helper class for color manipulations, imitating the LESS functions lighten, darken, fade
*/
class ColorHelper
{
/*
* This function imitates the LESS function lighten()
* But it does not convert the color into HSL and back because this is not necessary to achieve the same result.
* lighten() imitates the LESS function lighten()
* It does not convert the color into HSL and back because this is not necessary to achieve the same result.
* @param string $color RGB hexadecimal color code including '#'
* @param int $amount between 0 and 100
* @param bool $relative wether to lighten relatively to ligthness, default: false
* @return string RGB hexadecimal color code including '#'
*/
public static function lighten(string $color, int $amount, bool $relative = false): string
{
Expand All @@ -16,16 +23,11 @@ public static function lighten(string $color, int $amount, bool $relative = fals
*/
$color_parts = ColorHelper::getColorComponents($color);

// $amount is expected to be a number between 0 an 100
$percentage = $amount / 100;

// By default the LESS lighten() function adds the $amount absolutely to L, not relatively
if (!$relative) {

/*
* Converting a RGB color to HSL, the Lightness would be calculated by L = [max(R,G,B) + min(R,G,B)] / (2 * 255)
* So we need $max and $min
*/
//Converting a RGB color to HSL, the Lightness would be calculated by L = [max(R,G,B) + min(R,G,B)] / (2 * 255)
$max = hexdec(max($color_parts));
$min = hexdec(min($color_parts));

Expand All @@ -39,65 +41,78 @@ public static function lighten(string $color, int $amount, bool $relative = fals
$percentage = $percentage / (1 - ($max + $min) / (2 * 255));
}

$return = '#';
$result = '#';

foreach ($color_parts as $color) {
$color = hexdec($color); // Convert to decimal
$color = round($color + (255 - $color) * $percentage); // Adjust color
$color = max(min($color, 255), 0); // keep between 0 and 255
$return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
$result .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
}

return $return;

return $result;
}

/*
* Documentation, see lighten()
* see lighten()
* @param string $color RGB hexadecimal color code including '#'
* @param int $amount between 0 and 100
* @param bool $relative wether to darken relatively to ligthness, default: false
* @return string RGB hexadecimal color code including '#'
*/
public static function darken(string $color, int $amount, bool $relative = false): string
{

$percentage = $amount / 100;
// split color into its components
$color_parts = ColorHelper::getColorComponents($color);
$max = hexdec(max($color_parts));
$min = hexdec(min($color_parts));

if ($max == 0) {
return '#000000';
}


$percentage = $amount / 100;

// By default the LESS darken() function substracts the $amount absolutely to L, not relatively
if (!$relative) {
$percentage = 2 * 255 * $percentage / ($max + $min);
//Converting a RGB color to HSL, the Lightness would be calculated by L = [max(R,G,B) + min(R,G,B)] / (2 * 255)
$max = hexdec(max($color_parts));
$min = hexdec(min($color_parts));
if ($max !== 0) {
$percentage = 2 * 255 * $percentage / ($max + $min);
}
}

$return = '#';
$result = '#';

foreach ($color_parts as $color) {
$color = hexdec($color); // Convert to decimal
$color = round($color * (1 - $percentage)); // Adjust color
$color = max(min($color, 255), 0); // keep between 0 and 255
$return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
$result .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); // Make two char hex code
}

return $return;

return $result;
}

/*
* fade() imitates the LESS function fade() which sets the opacity defined by $amount
* @param string $color RGB hexadecimal color code including '#'
* @param int $amount between 0 and 100
* @return string RGBA hexadecimal color code including '#'
*/
public static function fade(string $color, int $amount): string
{
// make sure we have 6 letters code not 3
$color = '#' . self::getSixDigitsColor($color);

// $amount is expected to be between 0 and 100
$opacity = ($amount / 100) * 255;
$opacity = round(($amount / 100) * 255);
$opacity = max(min($opacity, 255), 0); // keep between 0 and 255
$opacity = str_pad(dechex($opacity), 2, '0', STR_PAD_LEFT); // make 2 char hex code

// return RGBA as hex code
return $color . $opacity;
}


/*
* Split color into its components (R, G, B)
* @param string $color RGB hexadecimal color code
* @return array color components as 2 character hexadecimal code
*/
protected static function getColorComponents(string $color): array
{
$hexstr = self::getSixDigitsColor($color);
Expand Down
60 changes: 34 additions & 26 deletions helpers/FileHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,18 @@
use Yii;
use yii\base\ErrorException;

/*
* helper class for safely accessing and modifying files
*/
class FileHelper
{
public const THEME_PATH = '@flex-theme/themes/FlexTheme';

private static function getVarsFile(string $prefix)
{
return Yii::getAlias(self::THEME_PATH . '/css/' . $prefix . 'variables.css');
}

private static function getThemeFile(string $prefix)
{
if ($prefix === 'dark_') {
$fileName = 'dark';
} else {
$fileName = 'theme';
}
return Yii::getAlias(self::THEME_PATH . '/css/' . $fileName . '.css');
}

private static function getThemeBaseFile(string $prefix)
{
return Yii::getAlias(self::THEME_PATH . '/css/' . $prefix . 'theme_base.css');
}

/*
* Update the color variables CSS file with given content
* @param string $content
* @param string $prefix, empty for default file or 'dark_'
*/
public static function updateVarsFile(string $content, string $prefix): bool
{
try {
Expand All @@ -40,16 +28,16 @@ public static function updateVarsFile(string $content, string $prefix): bool
return true;
}

/*
* Reload the CSS and update the main theme CSS file
* @param string $prefix, empty for default file or 'dark_'
*/
public static function updateThemeFile(string $prefix): bool
{
// Base Theme
$theme_base = file_get_contents(self::getThemeBaseFile($prefix));

$content = file_get_contents(self::getThemeBaseFile($prefix));
// CSS Variables
$vars = file_get_contents(self::getVarsFile($prefix));

// Create/Update theme.css
$content = $theme_base . $vars;
$content .= file_get_contents(self::getVarsFile($prefix));

try {
file_put_contents(self::getThemeFile($prefix), $content);
Expand All @@ -67,4 +55,24 @@ public static function updateThemeFile(string $prefix): bool
}
return true;
}

private static function getVarsFile(string $prefix): string
{
return Yii::getAlias(self::THEME_PATH . '/css/' . $prefix . 'variables.css');
}

private static function getThemeFile(string $prefix): string
{
if ($prefix === 'dark_') {
$fileName = 'dark';
} else {
$fileName = 'theme';
}
return Yii::getAlias(self::THEME_PATH . '/css/' . $fileName . '.css');
}

private static function getThemeBaseFile(string $prefix): string
{
return Yii::getAlias(self::THEME_PATH . '/css/' . $prefix . 'theme_base.css');
}
}
2 changes: 1 addition & 1 deletion models/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Config extends \yii\base\Model
public $showTopicMenu;
public $showUploadAsButtons;

public static function getSetting(string $setting_name): string
public static function getSetting(string $setting_name): ?string
{
// Note: return can be empty
return Yii::$app->getModule('flex-theme')->settings->get($setting_name);
Expand Down
4 changes: 2 additions & 2 deletions tests/codeception/acceptance/SettingsCest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SettingsCest
public function testSettings(AcceptanceTester $I)
{
$I->amAdmin();
$I->amOnRoute(['/flex-theme/config']);
$I->amOnRoute(['/flex-theme/admin']);
$I->waitForText('Flex Theme');
$I->selectOption('#config-commentlink', 'icon');
$I->selectOption('#config-likelink', 'icon');
Expand All @@ -22,7 +22,7 @@ public function testSettings(AcceptanceTester $I)
public function testSettingsColor(AcceptanceTester $I)
{
$I->amAdmin();
$I->amOnRoute(['/flex-theme/config/colors']);
$I->amOnRoute(['/flex-theme/admin/colors']);
$I->waitForText('Flex Theme');
$I->jsClick('.form-collapsible-fields:nth-of-type(3) > div');
$I->see('Background Color Page');
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
18 changes: 8 additions & 10 deletions widgets/AdminMenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

/**
* User Administration Menu
*
* @author Basti
*/
class AdminMenu extends TabMenu
{
Expand All @@ -27,39 +25,39 @@ public function init()
{
$this->addEntry(new MenuLink([
'label' => Yii::t('FlexThemeModule.admin', 'General Settings'),
'url' => ['/flex-theme/config/index'],
'url' => ['/flex-theme/admin/index'],
'sortOrder' => 100,
'isActive' => MenuLink::isActiveState('flex-theme', 'config', 'index'),
'isActive' => MenuLink::isActiveState('flex-theme', 'admin', 'index'),
'isVisible' => Yii::$app->user->can([
ManageSettings::class
])
]));

$this->addEntry(new MenuLink([
'label' => Yii::t('FlexThemeModule.admin', 'Colors'),
'url' => ['/flex-theme/config/colors'],
'url' => ['/flex-theme/admin/colors'],
'sortOrder' => 200,
'isActive' => MenuLink::isActiveState('flex-theme', 'config', 'colors'),
'isActive' => MenuLink::isActiveState('flex-theme', 'admin', 'colors'),
'isVisible' => Yii::$app->user->can([
ManageSettings::class
])
]));

$this->addEntry(new MenuLink([
'label' => Yii::t('FlexThemeModule.admin', 'Dark Mode'),
'url' => ['/flex-theme/config/dark-colors'],
'url' => ['/flex-theme/admin/dark-colors'],
'sortOrder' => 300,
'isActive' => MenuLink::isActiveState('flex-theme', 'config', 'dark-colors'),
'isActive' => MenuLink::isActiveState('flex-theme', 'admin', 'dark-colors'),
'isVisible' => Yii::$app->user->can([
ManageSettings::class
])
]));

$this->addEntry(new MenuLink([
'label' => Yii::t('FlexThemeModule.admin', 'Advanced'),
'url' => ['/flex-theme/config/advanced'],
'url' => ['/flex-theme/admin/advanced'],
'sortOrder' => 400,
'isActive' => MenuLink::isActiveState('flex-theme', 'config', 'advanced'),
'isActive' => MenuLink::isActiveState('flex-theme', 'admin', 'advanced'),
'isVisible' => Yii::$app->user->can([
ManageSettings::class
])
Expand Down