mirror of
https://github.com/nextcloud/server.git
synced 2026-06-06 07:13:23 -04:00
Merge pull request #46431 from nextcloud/backport/46258/stable28
[stable28] fix(theming): Conitionally disable blur filter for performance
This commit is contained in:
commit
e8b4d4e97d
13 changed files with 111 additions and 43 deletions
|
|
@ -33,6 +33,12 @@ use OCP\EventDispatcher\Event;
|
|||
use OCP\EventDispatcher\IEventListener;
|
||||
|
||||
class BeforePreferenceListener implements IEventListener {
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private const ALLOWED_KEYS = ['force_enable_blur_filter', 'shortcuts_disabled'];
|
||||
|
||||
public function __construct(
|
||||
private IAppManager $appManager,
|
||||
) {
|
||||
|
|
@ -54,13 +60,22 @@ class BeforePreferenceListener implements IEventListener {
|
|||
}
|
||||
|
||||
private function handleThemingValues(BeforePreferenceSetEvent|BeforePreferenceDeletedEvent $event): void {
|
||||
if ($event->getConfigKey() !== 'shortcuts_disabled') {
|
||||
if (!in_array($event->getConfigKey(), self::ALLOWED_KEYS)) {
|
||||
// Not allowed config key
|
||||
return;
|
||||
}
|
||||
|
||||
if ($event instanceof BeforePreferenceSetEvent) {
|
||||
$event->setValid($event->getConfigValue() === 'yes');
|
||||
switch ($event->getConfigKey()) {
|
||||
case 'force_enable_blur_filter':
|
||||
$event->setValid($event->getConfigValue() === 'yes' || $event->getConfigValue() === 'no');
|
||||
break;
|
||||
case 'shortcuts_disabled':
|
||||
$event->setValid($event->getConfigValue() === 'yes');
|
||||
break;
|
||||
default:
|
||||
$event->setValid(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class Personal implements ISettings {
|
|||
$this->initialStateService->provideInitialState('themes', array_values($themes));
|
||||
$this->initialStateService->provideInitialState('enforceTheme', $enforcedTheme);
|
||||
$this->initialStateService->provideInitialState('isUserThemingDisabled', $this->themingDefaults->isUserThemingDisabled());
|
||||
$this->initialStateService->provideInitialState('enableBlurFilter', $this->config->getUserValue($this->userId, 'theming', 'force_enable_blur_filter', ''));
|
||||
$this->initialStateService->provideInitialState('navigationBar', [
|
||||
'userAppOrder' => json_decode($this->config->getUserValue($this->userId, 'core', 'apporder', '[]'), true, flags:JSON_THROW_ON_ERROR),
|
||||
'enforcedDefaultApp' => $forcedDefaultApp
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||
*/
|
||||
namespace OCA\Theming\Themes;
|
||||
|
||||
use OC\AppFramework\Http\Request;
|
||||
use OCA\Theming\ImageManager;
|
||||
use OCA\Theming\ITheme;
|
||||
use OCA\Theming\Service\BackgroundService;
|
||||
|
|
@ -33,41 +34,27 @@ use OCA\Theming\Util;
|
|||
use OCP\App\IAppManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserSession;
|
||||
|
||||
class DefaultTheme implements ITheme {
|
||||
use CommonThemeTrait;
|
||||
|
||||
public Util $util;
|
||||
public ThemingDefaults $themingDefaults;
|
||||
public IUserSession $userSession;
|
||||
public IURLGenerator $urlGenerator;
|
||||
public ImageManager $imageManager;
|
||||
public IConfig $config;
|
||||
public IL10N $l;
|
||||
public IAppManager $appManager;
|
||||
|
||||
public string $defaultPrimaryColor;
|
||||
public string $primaryColor;
|
||||
|
||||
public function __construct(Util $util,
|
||||
ThemingDefaults $themingDefaults,
|
||||
IUserSession $userSession,
|
||||
IURLGenerator $urlGenerator,
|
||||
ImageManager $imageManager,
|
||||
IConfig $config,
|
||||
IL10N $l,
|
||||
IAppManager $appManager) {
|
||||
$this->util = $util;
|
||||
$this->themingDefaults = $themingDefaults;
|
||||
$this->userSession = $userSession;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->imageManager = $imageManager;
|
||||
$this->config = $config;
|
||||
$this->l = $l;
|
||||
$this->appManager = $appManager;
|
||||
|
||||
public function __construct(
|
||||
public Util $util,
|
||||
public ThemingDefaults $themingDefaults,
|
||||
public IUserSession $userSession,
|
||||
public IURLGenerator $urlGenerator,
|
||||
public ImageManager $imageManager,
|
||||
public IConfig $config,
|
||||
public IL10N $l,
|
||||
public IAppManager $appManager,
|
||||
private ?IRequest $request,
|
||||
) {
|
||||
$this->defaultPrimaryColor = $this->themingDefaults->getDefaultColorPrimary();
|
||||
$this->primaryColor = $this->themingDefaults->getColorPrimary();
|
||||
|
||||
|
|
@ -116,12 +103,29 @@ class DefaultTheme implements ITheme {
|
|||
$colorSuccess = '#2d7b41';
|
||||
$colorInfo = '#0071ad';
|
||||
|
||||
$user = $this->userSession->getUser();
|
||||
// Chromium based browsers currently (2024) have huge performance issues with blur filters
|
||||
$isChromium = $this->request !== null && $this->request->isUserAgent([Request::USER_AGENT_CHROME, Request::USER_AGENT_MS_EDGE]);
|
||||
// Ignore MacOS because they always have hardware accelartion
|
||||
$isChromium = $isChromium && !$this->request->isUserAgent(['/Macintosh/']);
|
||||
// Allow to force the blur filter
|
||||
$forceEnableBlur = $user === null ? false : $this->config->getUserValue(
|
||||
$user->getUID(),
|
||||
'theming',
|
||||
'force_enable_blur_filter',
|
||||
);
|
||||
$workingBlur = match($forceEnableBlur) {
|
||||
'yes' => true,
|
||||
'no' => false,
|
||||
default => !$isChromium
|
||||
};
|
||||
|
||||
$variables = [
|
||||
'--color-main-background' => $colorMainBackground,
|
||||
'--color-main-background-rgb' => $colorMainBackgroundRGB,
|
||||
'--color-main-background-translucent' => 'rgba(var(--color-main-background-rgb), .97)',
|
||||
'--color-main-background-blur' => 'rgba(var(--color-main-background-rgb), .8)',
|
||||
'--filter-background-blur' => 'blur(25px)',
|
||||
'--filter-background-blur' => $workingBlur ? 'blur(25px)' : 'none',
|
||||
|
||||
// to use like this: background-image: linear-gradient(0, var('--gradient-main-background));
|
||||
'--gradient-main-background' => 'var(--color-main-background) 0%, var(--color-main-background-translucent) 85%, transparent 100%',
|
||||
|
|
|
|||
|
|
@ -51,6 +51,14 @@
|
|||
type="font"
|
||||
@change="changeFont" />
|
||||
</div>
|
||||
|
||||
<h3>{{ t('theming', 'Misc accessibility options') }}</h3>
|
||||
<NcCheckboxRadioSwitch type="checkbox"
|
||||
:checked="enableBlurFilter === 'yes'"
|
||||
:indeterminate="enableBlurFilter === ''"
|
||||
@update:checked="changeEnableBlurFilter">
|
||||
{{ t('theming', 'Enable blur background filter (may increase GPU load)') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
</NcSettingsSection>
|
||||
|
||||
<NcSettingsSection :name="t('theming', 'Background')"
|
||||
|
|
@ -93,6 +101,7 @@ import UserAppMenuSection from './components/UserAppMenuSection.vue'
|
|||
const availableThemes = loadState('theming', 'themes', [])
|
||||
const enforceTheme = loadState('theming', 'enforceTheme', '')
|
||||
const shortcutsDisabled = loadState('theming', 'shortcutsDisabled', false)
|
||||
const enableBlurFilter = loadState('theming', 'enableBlurFilter', '')
|
||||
|
||||
const isUserThemingDisabled = loadState('theming', 'isUserThemingDisabled')
|
||||
|
||||
|
|
@ -115,6 +124,8 @@ export default {
|
|||
enforceTheme,
|
||||
shortcutsDisabled,
|
||||
isUserThemingDisabled,
|
||||
|
||||
enableBlurFilter,
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -240,6 +251,22 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
async changeEnableBlurFilter() {
|
||||
this.enableBlurFilter = this.enableBlurFilter === 'no' ? 'yes' : 'no'
|
||||
await axios({
|
||||
url: generateOcsUrl('apps/provisioning_api/api/v1/config/users/{appId}/{configKey}', {
|
||||
appId: 'theming',
|
||||
configKey: 'force_enable_blur_filter',
|
||||
}),
|
||||
data: {
|
||||
configValue: this.enableBlurFilter,
|
||||
},
|
||||
method: 'POST',
|
||||
})
|
||||
// Refresh the styles
|
||||
this.$emit('update:background')
|
||||
},
|
||||
|
||||
updateBodyAttributes() {
|
||||
const enabledThemesIDs = this.themes.filter(theme => theme.enabled === true).map(theme => theme.id)
|
||||
const enabledFontsIDs = this.fonts.filter(font => font.enabled === true).map(font => font.id)
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ class ThemesServiceTest extends TestCase {
|
|||
$this->config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'light' => new LightTheme(
|
||||
$util,
|
||||
|
|
@ -342,6 +343,7 @@ class ThemesServiceTest extends TestCase {
|
|||
$this->config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'dark' => new DarkTheme(
|
||||
$util,
|
||||
|
|
@ -352,6 +354,7 @@ class ThemesServiceTest extends TestCase {
|
|||
$this->config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'light-highcontrast' => new HighContrastTheme(
|
||||
$util,
|
||||
|
|
@ -362,6 +365,7 @@ class ThemesServiceTest extends TestCase {
|
|||
$this->config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'dark-highcontrast' => new DarkHighContrastTheme(
|
||||
$util,
|
||||
|
|
@ -372,6 +376,7 @@ class ThemesServiceTest extends TestCase {
|
|||
$this->config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'opendyslexic' => new DyslexiaFont(
|
||||
$util,
|
||||
|
|
@ -382,6 +387,7 @@ class ThemesServiceTest extends TestCase {
|
|||
$this->config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,14 +47,15 @@ use OCP\IConfig;
|
|||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserSession;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class PersonalTest extends TestCase {
|
||||
private IConfig $config;
|
||||
private ThemesService $themesService;
|
||||
private IInitialState $initialStateService;
|
||||
private ThemingDefaults $themingDefaults;
|
||||
private IAppManager $appManager;
|
||||
private IConfig|MockObject $config;
|
||||
private ThemesService|MockObject $themesService;
|
||||
private IInitialState|MockObject $initialStateService;
|
||||
private ThemingDefaults|MockObject $themingDefaults;
|
||||
private IAppManager|MockObject $appManager;
|
||||
private Personal $admin;
|
||||
|
||||
/** @var ITheme[] */
|
||||
|
|
@ -116,23 +117,26 @@ class PersonalTest extends TestCase {
|
|||
->with('enforce_theme', '')
|
||||
->willReturn($enforcedTheme);
|
||||
|
||||
$this->config->expects($this->once())
|
||||
$this->config->expects($this->exactly(2))
|
||||
->method('getUserValue')
|
||||
->with('admin', 'core', 'apporder')
|
||||
->willReturn('[]');
|
||||
->willReturnMap([
|
||||
['admin', 'core', 'apporder', '[]', '[]'],
|
||||
['admin', 'theming', 'force_enable_blur_filter', '', ''],
|
||||
]);
|
||||
|
||||
$this->appManager->expects($this->once())
|
||||
->method('getDefaultAppForUser')
|
||||
->willReturn('forcedapp');
|
||||
|
||||
$this->initialStateService->expects($this->exactly(4))
|
||||
$this->initialStateService->expects($this->exactly(5))
|
||||
->method('provideInitialState')
|
||||
->withConsecutive(
|
||||
->willReturnMap([
|
||||
['themes', $themesState],
|
||||
['enableBlurFilter', ''],
|
||||
['enforceTheme', $enforcedTheme],
|
||||
['isUserThemingDisabled', false],
|
||||
['navigationBar', ['userAppOrder' => [], 'enforcedDefaultApp' => 'forcedapp']],
|
||||
);
|
||||
]);
|
||||
|
||||
$expected = new TemplateResponse('theming', 'settings-personal');
|
||||
$this->assertEquals($expected, $this->admin->getForm());
|
||||
|
|
@ -174,6 +178,7 @@ class PersonalTest extends TestCase {
|
|||
$config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'light' => new LightTheme(
|
||||
$util,
|
||||
|
|
@ -184,6 +189,7 @@ class PersonalTest extends TestCase {
|
|||
$config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'dark' => new DarkTheme(
|
||||
$util,
|
||||
|
|
@ -194,6 +200,7 @@ class PersonalTest extends TestCase {
|
|||
$config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'light-highcontrast' => new HighContrastTheme(
|
||||
$util,
|
||||
|
|
@ -204,6 +211,7 @@ class PersonalTest extends TestCase {
|
|||
$config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'dark-highcontrast' => new DarkHighContrastTheme(
|
||||
$util,
|
||||
|
|
@ -214,6 +222,7 @@ class PersonalTest extends TestCase {
|
|||
$config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
'opendyslexic' => new DyslexiaFont(
|
||||
$util,
|
||||
|
|
@ -224,6 +233,7 @@ class PersonalTest extends TestCase {
|
|||
$config,
|
||||
$l10n,
|
||||
$appManager,
|
||||
null,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ class DarkHighContrastThemeTest extends AccessibleThemeTestCase {
|
|||
$this->config,
|
||||
$this->l10n,
|
||||
$this->appManager,
|
||||
null,
|
||||
);
|
||||
|
||||
parent::setUp();
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class DarkThemeTest extends AccessibleThemeTestCase {
|
|||
$this->config,
|
||||
$this->l10n,
|
||||
$this->appManager,
|
||||
null,
|
||||
);
|
||||
|
||||
parent::setUp();
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class DefaultThemeTest extends AccessibleThemeTestCase {
|
|||
$this->config,
|
||||
$this->l10n,
|
||||
$this->appManager,
|
||||
null,
|
||||
);
|
||||
|
||||
parent::setUp();
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ class DyslexiaFontTest extends TestCase {
|
|||
$this->config,
|
||||
$this->l10n,
|
||||
$this->appManager,
|
||||
null,
|
||||
);
|
||||
|
||||
parent::setUp();
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ class HighContrastThemeTest extends AccessibleThemeTestCase {
|
|||
$this->config,
|
||||
$this->l10n,
|
||||
$this->appManager,
|
||||
null,
|
||||
);
|
||||
|
||||
parent::setUp();
|
||||
|
|
|
|||
4
dist/theming-personal-theming.js
vendored
4
dist/theming-personal-theming.js
vendored
File diff suppressed because one or more lines are too long
2
dist/theming-personal-theming.js.map
vendored
2
dist/theming-personal-theming.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue