diff options
author | John Molakvoæ <skjnldsv@protonmail.com> | 2023-04-14 12:40:08 +0200 |
---|---|---|
committer | John Molakvoæ <skjnldsv@protonmail.com> | 2023-04-18 09:02:01 +0200 |
commit | d7ab8da1ef7decb512d68b038fc7e92758fbb518 (patch) | |
tree | 302b14a5a8a5c3b07cabc3595caba53500eca238 /apps/files/lib | |
parent | ff58cd52279cccfbda0cc4683f1194d6c7ee283b (diff) | |
download | nextcloud-server-d7ab8da1ef7decb512d68b038fc7e92758fbb518.tar.gz nextcloud-server-d7ab8da1ef7decb512d68b038fc7e92758fbb518.zip |
feat(files): add view config service to store user-config per view
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Diffstat (limited to 'apps/files/lib')
-rw-r--r-- | apps/files/lib/AppInfo/Application.php | 2 | ||||
-rw-r--r-- | apps/files/lib/Controller/ApiController.php | 74 | ||||
-rw-r--r-- | apps/files/lib/Controller/ViewController.php | 7 | ||||
-rw-r--r-- | apps/files/lib/Service/ViewConfig.php | 184 |
4 files changed, 218 insertions, 49 deletions
diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php index e3152c77abc..0d366e66fe8 100644 --- a/apps/files/lib/AppInfo/Application.php +++ b/apps/files/lib/AppInfo/Application.php @@ -49,6 +49,7 @@ use OCA\Files\Notification\Notifier; use OCA\Files\Search\FilesSearchProvider; use OCA\Files\Service\TagService; use OCA\Files\Service\UserConfig; +use OCA\Files\Service\ViewConfig; use OCP\Activity\IManager as IActivityManager; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; @@ -93,6 +94,7 @@ class Application extends App implements IBootstrap { $c->get(IConfig::class), $server->getUserFolder(), $c->get(UserConfig::class), + $c->get(ViewConfig::class), ); }); diff --git a/apps/files/lib/Controller/ApiController.php b/apps/files/lib/Controller/ApiController.php index 808f0d555d0..9b5d12baa96 100644 --- a/apps/files/lib/Controller/ApiController.php +++ b/apps/files/lib/Controller/ApiController.php @@ -40,6 +40,7 @@ namespace OCA\Files\Controller; use OC\Files\Node\Node; use OCA\Files\Service\TagService; use OCA\Files\Service\UserConfig; +use OCA\Files\Service\ViewConfig; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\ContentSecurityPolicy; @@ -71,6 +72,7 @@ class ApiController extends Controller { private IConfig $config; private Folder $userFolder; private UserConfig $userConfig; + private ViewConfig $viewConfig; /** * @param string $appName @@ -90,7 +92,8 @@ class ApiController extends Controller { IManager $shareManager, IConfig $config, Folder $userFolder, - UserConfig $userConfig) { + UserConfig $userConfig, + ViewConfig $viewConfig) { parent::__construct($appName, $request); $this->userSession = $userSession; $this->tagService = $tagService; @@ -99,6 +102,7 @@ class ApiController extends Controller { $this->config = $config; $this->userFolder = $userFolder; $this->userConfig = $userConfig; + $this->viewConfig = $viewConfig; } /** @@ -275,39 +279,39 @@ class ApiController extends Controller { } /** - * Change the default sort mode + * Set a user view config * * @NoAdminRequired * - * @param string $mode - * @param string $direction + * @param string $view + * @param string $key + * @param string|bool $value * @return JSONResponse - * @throws \OCP\PreConditionNotMetException */ - public function updateFileSorting($mode, string $direction = 'asc', string $view = 'files'): JSONResponse { - $allowedDirection = ['asc', 'desc']; - if (!in_array($direction, $allowedDirection)) { - return new JSONResponse(['message' => 'Invalid direction parameter'], Http::STATUS_UNPROCESSABLE_ENTITY); + public function setViewConfig(string $view, string $key, $value): JSONResponse { + try { + $this->viewConfig->setConfig($view, $key, (string)$value); + } catch (\InvalidArgumentException $e) { + return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST); } - $userId = $this->userSession->getUser()->getUID(); + return new JSONResponse(['message' => 'ok', 'data' => $this->viewConfig->getConfig($view)]); + } - $sortingJson = $this->config->getUserValue($userId, 'files', 'files_sorting_configs', '{}'); - $sortingConfig = json_decode($sortingJson, true) ?: []; - $sortingConfig[$view] = [ - 'mode' => $mode, - 'direction' => $direction, - ]; - $this->config->setUserValue($userId, 'files', 'files_sorting_configs', json_encode($sortingConfig)); - return new JSONResponse([ - 'message' => 'ok', - 'data' => $sortingConfig, - ]); + /** + * Get the user view config + * + * @NoAdminRequired + * + * @return JSONResponse + */ + public function getViewConfigs(): JSONResponse { + return new JSONResponse(['message' => 'ok', 'data' => $this->viewConfig->getConfigs()]); } /** - * Toggle default files user config + * Set a user config * * @NoAdminRequired * @@ -390,32 +394,6 @@ class ApiController extends Controller { } /** - * Toggle default for showing/hiding xxx folder - * - * @NoAdminRequired - * - * @param int $show - * @param string $key the key of the folder - * - * @return Response - * @throws \OCP\PreConditionNotMetException - */ - public function toggleShowFolder(int $show, string $key): Response { - if ($show !== 0 && $show !== 1) { - return new DataResponse([ - 'message' => 'Invalid show value. Only 0 and 1 are allowed.' - ], Http::STATUS_BAD_REQUEST); - } - - $userId = $this->userSession->getUser()->getUID(); - - // Set the new value and return it - // Using a prefix prevents the user from setting arbitrary keys - $this->config->setUserValue($userId, 'files', 'show_' . $key, (string)$show); - return new JSONResponse([$key => $show]); - } - - /** * Get sorting-order for custom sorting * * @NoAdminRequired diff --git a/apps/files/lib/Controller/ViewController.php b/apps/files/lib/Controller/ViewController.php index cb41dfb300b..70e0fd48456 100644 --- a/apps/files/lib/Controller/ViewController.php +++ b/apps/files/lib/Controller/ViewController.php @@ -40,6 +40,7 @@ use OCA\Files\AppInfo\Application; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Files\Event\LoadSidebar; use OCA\Files\Service\UserConfig; +use OCA\Files\Service\ViewConfig; use OCA\Viewer\Event\LoadViewer; use OCP\App\IAppManager; use OCP\AppFramework\Controller; @@ -79,6 +80,7 @@ class ViewController extends Controller { private ITemplateManager $templateManager; private IManager $shareManager; private UserConfig $userConfig; + private ViewConfig $viewConfig; public function __construct(string $appName, IRequest $request, @@ -93,7 +95,8 @@ class ViewController extends Controller { IInitialState $initialState, ITemplateManager $templateManager, IManager $shareManager, - UserConfig $userConfig + UserConfig $userConfig, + ViewConfig $viewConfig ) { parent::__construct($appName, $request); $this->urlGenerator = $urlGenerator; @@ -108,6 +111,7 @@ class ViewController extends Controller { $this->templateManager = $templateManager; $this->shareManager = $shareManager; $this->userConfig = $userConfig; + $this->viewConfig = $viewConfig; } /** @@ -248,6 +252,7 @@ class ViewController extends Controller { $this->initialState->provideInitialState('storageStats', $storageInfo); $this->initialState->provideInitialState('navigation', $navItems); $this->initialState->provideInitialState('config', $this->userConfig->getConfigs()); + $this->initialState->provideInitialState('viewConfigs', $this->viewConfig->getConfigs()); // File sorting user config $filesSortingConfig = json_decode($this->config->getUserValue($userId, 'files', 'files_sorting_configs', '{}'), true); diff --git a/apps/files/lib/Service/ViewConfig.php b/apps/files/lib/Service/ViewConfig.php new file mode 100644 index 00000000000..51d90ffdb4e --- /dev/null +++ b/apps/files/lib/Service/ViewConfig.php @@ -0,0 +1,184 @@ +<?php +/** + * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +namespace OCA\Files\Service; + +use OCA\Files\AppInfo\Application; +use OCP\IConfig; +use OCP\IUser; +use OCP\IUserSession; + +class ViewConfig { + const CONFIG_KEY = 'files_views_configs'; + const ALLOWED_CONFIGS = [ + [ + // The default sorting key for the files list view + 'key' => 'sorting_mode', + // null by default as views can provide default sorting key + // and will fallback to it if user hasn't change it + 'default' => null, + ], + [ + // The default sorting direction for the files list view + 'key' => 'sorting_direction', + 'default' => 'asc', + 'allowed' => ['asc', 'desc'], + ], + [ + // If the navigation entry for this view is expanded or not + 'key' => 'expanded', + 'default' => true, + 'allowed' => [true, false], + ], + ]; + + protected IConfig $config; + protected ?IUser $user = null; + + public function __construct(IConfig $config, IUserSession $userSession) { + $this->config = $config; + $this->user = $userSession->getUser(); + } + + /** + * Get the list of all allowed user config keys + * @return string[] + */ + public function getAllowedConfigKeys(): array { + return array_map(function($config) { + return $config['key']; + }, self::ALLOWED_CONFIGS); + } + + /** + * Get the list of allowed config values for a given key + * + * @param string $key a valid config key + * @return array + */ + private function getAllowedConfigValues(string $key): array { + foreach (self::ALLOWED_CONFIGS as $config) { + if ($config['key'] === $key) { + return $config['allowed'] ?? []; + } + } + return []; + } + + /** + * Get the default config value for a given key + * + * @param string $key a valid config key + * @return string|bool|null + */ + private function getDefaultConfigValue(string $key) { + foreach (self::ALLOWED_CONFIGS as $config) { + if ($config['key'] === $key) { + return $config['default']; + } + } + return ''; + } + + /** + * Set a user config + * + * @param string $view + * @param string $key + * @param string|bool $value + * @throws \Exception + * @throws \InvalidArgumentException + */ + public function setConfig(string $view, string $key, $value): void { + if ($this->user === null) { + throw new \Exception('No user logged in'); + } + + if (!$view) { + throw new \Exception('Unknown view'); + } + + if (!in_array($key, $this->getAllowedConfigKeys())) { + throw new \InvalidArgumentException('Unknown config key'); + } + + if (!in_array($value, $this->getAllowedConfigValues($key)) + && !empty($this->getAllowedConfigValues($key))) { + throw new \InvalidArgumentException('Invalid config value'); + } + + // Cast boolean values + if (is_bool($this->getDefaultConfigValue($key))) { + $value = $value === '1'; + } + + $config = $this->getConfigs(); + $config[$view][$key] = $value; + + $this->config->setUserValue($this->user->getUID(), Application::APP_ID, self::CONFIG_KEY, json_encode($config)); + } + + /** + * Get the current user configs array for a given view + * + * @return array + */ + public function getConfig(string $view): array { + if ($this->user === null) { + throw new \Exception('No user logged in'); + } + + $userId = $this->user->getUID(); + $configs = json_decode($this->config->getUserValue($userId, Application::APP_ID, self::CONFIG_KEY, '[]'), true); + + if (!isset($configs[$view])) { + $configs[$view] = []; + } + + // Extend undefined values with defaults + return array_reduce(self::ALLOWED_CONFIGS, function($carry, $config) use ($view, $configs) { + $key = $config['key']; + $carry[$key] = $configs[$view][$key] ?? $this->getDefaultConfigValue($key); + return $carry; + }, []); + } + + /** + * Get the current user configs array + * + * @return array + */ + public function getConfigs(): array { + if ($this->user === null) { + throw new \Exception('No user logged in'); + } + + $userId = $this->user->getUID(); + $configs = json_decode($this->config->getUserValue($userId, Application::APP_ID, self::CONFIG_KEY, '[]'), true); + $views = array_keys($configs); + + return array_reduce($views, function($carry, $view) use ($configs) { + $carry[$view] = $this->getConfig($view); + return $carry; + }, []); + } +} |