diff --git a/apps/files/lib/Service/UserConfig.php b/apps/files/lib/Service/UserConfig.php index dcf30b7796db6..f2ad1db02d7d4 100644 --- a/apps/files/lib/Service/UserConfig.php +++ b/apps/files/lib/Service/UserConfig.php @@ -79,6 +79,13 @@ class UserConfig { 'default' => true, 'allowed' => [true, false], ], + [ + // Maximum number of files to display in the recent section + 'key' => 'recent_files_limit', + 'default' => 100, + 'min' => 1, + 'max' => 100, + ], ]; protected ?IUser $user = null; @@ -118,7 +125,7 @@ private function getAllowedConfigValues(string $key): array { * Get the default config value for a given key * * @param string $key a valid config key - * @return string|bool + * @return string|bool|int */ private function getDefaultConfigValue(string $key) { foreach (self::ALLOWED_CONFIGS as $config) { @@ -146,7 +153,13 @@ public function setConfig(string $key, $value): void { throw new \InvalidArgumentException('Unknown config key'); } - if (!in_array($value, $this->getAllowedConfigValues($key))) { + $config = $this->getConfigDefinition($key); + + if (isset($config['min'], $config['max'])) { + if ((int)$value < $config['min'] || (int)$value > $config['max']) { + throw new \InvalidArgumentException('Invalid config value'); + } + } elseif (!in_array($value, $this->getAllowedConfigValues($key))) { throw new \InvalidArgumentException('Invalid config value'); } @@ -179,4 +192,19 @@ public function getConfigs(): array { return array_combine($this->getAllowedConfigKeys(), $userConfigs); } + + /** + * Get the config definition for a given key + * + * @param string $key + * @return array + */ + private function getConfigDefinition(string $key): array { + foreach (self::ALLOWED_CONFIGS as $config) { + if ($config['key'] === $key) { + return $config; + } + } + return []; + } } diff --git a/apps/files/src/components/FilesAppSettings/FilesAppSettingsRecent.vue b/apps/files/src/components/FilesAppSettings/FilesAppSettingsRecent.vue new file mode 100644 index 0000000000000..71a127443bbc8 --- /dev/null +++ b/apps/files/src/components/FilesAppSettings/FilesAppSettingsRecent.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/apps/files/src/services/Recent.ts b/apps/files/src/services/Recent.ts index 314426101b66d..484bf7cf230a7 100644 --- a/apps/files/src/services/Recent.ts +++ b/apps/files/src/services/Recent.ts @@ -41,7 +41,7 @@ export async function getContents(path = '/', options: { signal: AbortSignal }): const contentsResponse = await client.search('/', { signal: options.signal, details: true, - data: getRecentSearch(lastTwoWeeksTimestamp), + data: getRecentSearch(lastTwoWeeksTimestamp, store.userConfig.recent_files_limit), }) as ResponseDataDetailed const contents = contentsResponse.data.results diff --git a/apps/files/src/store/userconfig.ts b/apps/files/src/store/userconfig.ts index 00fd45e67ac7b..e3675a510544a 100644 --- a/apps/files/src/store/userconfig.ts +++ b/apps/files/src/store/userconfig.ts @@ -23,6 +23,7 @@ const initialUserConfig = loadState('files', 'config', { show_mime_column: true, sort_favorites_first: true, sort_folders_first: true, + recent_files_limit: 100, show_dialog_deletion: false, show_dialog_file_extension: true, diff --git a/apps/files/src/types.ts b/apps/files/src/types.ts index f87c0c4b8e7c9..a1d830dbf9e7b 100644 --- a/apps/files/src/types.ts +++ b/apps/files/src/types.ts @@ -51,7 +51,7 @@ export interface PathOptions { // User config store export interface UserConfig { - [key: string]: boolean | string | undefined + [key: string]: boolean | string | number | undefined crop_image_previews: boolean default_view: 'files' | 'personal' @@ -59,6 +59,7 @@ export interface UserConfig { grid_view: boolean sort_favorites_first: boolean sort_folders_first: boolean + recent_files_limit: number show_files_extensions: boolean show_hidden: boolean diff --git a/apps/files/src/views/FilesAppSettings.vue b/apps/files/src/views/FilesAppSettings.vue index 7772b3d89c220..0e1967bf58a69 100644 --- a/apps/files/src/views/FilesAppSettings.vue +++ b/apps/files/src/views/FilesAppSettings.vue @@ -11,6 +11,7 @@ import NcAppSettingsDialog from '@nextcloud/vue/components/NcAppSettingsDialog' import FilesAppSettingsAppearance from '../components/FilesAppSettings/FilesAppSettingsAppearance.vue' import FilesAppSettingsGeneral from '../components/FilesAppSettings/FilesAppSettingsGeneral.vue' import FilesAppSettingsLegacyApi from '../components/FilesAppSettings/FilesAppSettingsLegacyApi.vue' +import FilesAppSettingsRecent from '../components/FilesAppSettings/FilesAppSettingsRecent.vue' import FilesAppSettingsShortcuts from '../components/FilesAppSettings/FilesAppSettingsShortcuts.vue' import FilesAppSettingsWarnings from '../components/FilesAppSettings/FilesAppSettingsWarnings.vue' import FilesAppSettingsWebDav from '../components/FilesAppSettings/FilesAppSettingsWebDav.vue' @@ -57,6 +58,7 @@ async function showKeyboardShortcuts() { + diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php index 284ba7f6ef039..7bec32d0d2331 100644 --- a/lib/private/Files/Cache/QuerySearchHelper.php +++ b/lib/private/Files/Cache/QuerySearchHelper.php @@ -153,9 +153,7 @@ public function searchInCaches(ISearchQuery $searchQuery, array $caches): array $requestedFields = $this->searchBuilder->extractRequestedFields($searchQuery->getSearchOperation()); - $joinExtendedCache = in_array('creation_time', $requestedFields) || in_array('upload_time', $requestedFields); - - $query = $builder->selectFileCache('file', $joinExtendedCache); + $query = $builder->selectFileCache('file', true); if (in_array('systemtag', $requestedFields)) { $this->equipQueryForSystemTags($query, $this->requireUser($searchQuery));