aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/lib
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@protonmail.com>2023-04-14 12:40:08 +0200
committerJohn Molakvoæ <skjnldsv@protonmail.com>2023-04-18 09:02:01 +0200
commitd7ab8da1ef7decb512d68b038fc7e92758fbb518 (patch)
tree302b14a5a8a5c3b07cabc3595caba53500eca238 /apps/files/lib
parentff58cd52279cccfbda0cc4683f1194d6c7ee283b (diff)
downloadnextcloud-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.php2
-rw-r--r--apps/files/lib/Controller/ApiController.php74
-rw-r--r--apps/files/lib/Controller/ViewController.php7
-rw-r--r--apps/files/lib/Service/ViewConfig.php184
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;
+ }, []);
+ }
+}