Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
f82ea00
feat(preview): honor MIME priority, cache headers, and record failures
rayvincent2 Aug 23, 2026
b764d61
feat(settings): add Previews administration page
rayvincent2 Aug 23, 2026
714478a
feat(settings): expose remaining preview settings with detection
rayvincent2 Aug 23, 2026
d32b86b
feat(settings): show inactive preview settings with unlock states
rayvincent2 Aug 23, 2026
f601416
feat(settings): treat enable previews as a page-level master switch
rayvincent2 Aug 25, 2026
e127de1
feat(settings): warn on unsaved Previews changes and duplicate Save
rayvincent2 Aug 25, 2026
7167059
feat(settings): drop MIME priority and finish Previews admin UX
rayvincent2 Aug 26, 2026
dfd838f
feat(settings): refine Previews admin defaults, filters, and failures
rayvincent2 Aug 26, 2026
f6119cb
chore(settings): fix Previews admin lint and Playwright specs
rayvincent2 Aug 26, 2026
e6ad2da
feat(settings): lock preview providers that fail requirements
rayvincent2 Aug 26, 2026
70c705c
feat(preview): honor enabledPreviewProviders as generation order
rayvincent2 Aug 26, 2026
6f5478f
chore(settings): fix Previews admin watch eslint
rayvincent2 Aug 26, 2026
725f56b
fix(settings): show Previews icon in admin navigation
rayvincent2 Aug 29, 2026
fda7774
test(settings): fix Previews admin Playwright locators
rayvincent2 Aug 29, 2026
a109b4b
feat(settings): drop failures UI and align Previews admin with review…
rayvincent2 Aug 30, 2026
3933746
fix(settings): wire Previews admin hints to their inputs
rayvincent2 Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion REUSE.toml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions apps/settings/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<admin>OCA\Settings\Settings\Admin\ArtificialIntelligence</admin>
<admin>OCA\Settings\Settings\Admin\Server</admin>
<admin>OCA\Settings\Settings\Admin\Sharing</admin>
<admin>OCA\Settings\Settings\Admin\Previews</admin>
<admin>OCA\Settings\Settings\Admin\Security</admin>
<admin>OCA\Settings\Settings\Admin\Delegation</admin>
<admin-section>OCA\Settings\Sections\Admin\Additional</admin-section>
Expand All @@ -45,6 +46,7 @@
<admin-section>OCA\Settings\Sections\Admin\Security</admin-section>
<admin-section>OCA\Settings\Sections\Admin\Server</admin-section>
<admin-section>OCA\Settings\Sections\Admin\Sharing</admin-section>
<admin-section>OCA\Settings\Sections\Admin\Previews</admin-section>
<admin-delegation>OCA\Settings\Settings\Admin\Users</admin-delegation>
<admin-delegation-section>OCA\Settings\Sections\Admin\Users</admin-delegation-section>
<personal>OCA\Settings\Settings\Personal\Additional</personal>
Expand Down
3 changes: 3 additions & 0 deletions apps/settings/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
'OCA\\Settings\\Controller\\MailSettingsController' => $baseDir . '/../lib/Controller/MailSettingsController.php',
'OCA\\Settings\\Controller\\PersonalSettingsController' => $baseDir . '/../lib/Controller/PersonalSettingsController.php',
'OCA\\Settings\\Controller\\PresetController' => $baseDir . '/../lib/Controller/PresetController.php',
'OCA\\Settings\\Controller\\PreviewAdminController' => $baseDir . '/../lib/Controller/PreviewAdminController.php',
'OCA\\Settings\\Controller\\ReasonsController' => $baseDir . '/../lib/Controller/ReasonsController.php',
'OCA\\Settings\\Controller\\TwoFactorSettingsController' => $baseDir . '/../lib/Controller/TwoFactorSettingsController.php',
'OCA\\Settings\\Controller\\UsersController' => $baseDir . '/../lib/Controller/UsersController.php',
Expand All @@ -57,6 +58,7 @@
'OCA\\Settings\\Sections\\Admin\\Office' => $baseDir . '/../lib/Sections/Admin/Office.php',
'OCA\\Settings\\Sections\\Admin\\Overview' => $baseDir . '/../lib/Sections/Admin/Overview.php',
'OCA\\Settings\\Sections\\Admin\\Presets' => $baseDir . '/../lib/Sections/Admin/Presets.php',
'OCA\\Settings\\Sections\\Admin\\Previews' => $baseDir . '/../lib/Sections/Admin/Previews.php',
'OCA\\Settings\\Sections\\Admin\\Security' => $baseDir . '/../lib/Sections/Admin/Security.php',
'OCA\\Settings\\Sections\\Admin\\Server' => $baseDir . '/../lib/Sections/Admin/Server.php',
'OCA\\Settings\\Sections\\Admin\\Sharing' => $baseDir . '/../lib/Sections/Admin/Sharing.php',
Expand All @@ -77,6 +79,7 @@
'OCA\\Settings\\Settings\\Admin\\MailProvider' => $baseDir . '/../lib/Settings/Admin/MailProvider.php',
'OCA\\Settings\\Settings\\Admin\\Overview' => $baseDir . '/../lib/Settings/Admin/Overview.php',
'OCA\\Settings\\Settings\\Admin\\Presets' => $baseDir . '/../lib/Settings/Admin/Presets.php',
'OCA\\Settings\\Settings\\Admin\\Previews' => $baseDir . '/../lib/Settings/Admin/Previews.php',
'OCA\\Settings\\Settings\\Admin\\Security' => $baseDir . '/../lib/Settings/Admin/Security.php',
'OCA\\Settings\\Settings\\Admin\\Server' => $baseDir . '/../lib/Settings/Admin/Server.php',
'OCA\\Settings\\Settings\\Admin\\Sharing' => $baseDir . '/../lib/Settings/Admin/Sharing.php',
Expand Down
3 changes: 3 additions & 0 deletions apps/settings/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class ComposerStaticInitSettings
'OCA\\Settings\\Controller\\MailSettingsController' => __DIR__ . '/..' . '/../lib/Controller/MailSettingsController.php',
'OCA\\Settings\\Controller\\PersonalSettingsController' => __DIR__ . '/..' . '/../lib/Controller/PersonalSettingsController.php',
'OCA\\Settings\\Controller\\PresetController' => __DIR__ . '/..' . '/../lib/Controller/PresetController.php',
'OCA\\Settings\\Controller\\PreviewAdminController' => __DIR__ . '/..' . '/../lib/Controller/PreviewAdminController.php',
'OCA\\Settings\\Controller\\ReasonsController' => __DIR__ . '/..' . '/../lib/Controller/ReasonsController.php',
'OCA\\Settings\\Controller\\TwoFactorSettingsController' => __DIR__ . '/..' . '/../lib/Controller/TwoFactorSettingsController.php',
'OCA\\Settings\\Controller\\UsersController' => __DIR__ . '/..' . '/../lib/Controller/UsersController.php',
Expand All @@ -72,6 +73,7 @@ class ComposerStaticInitSettings
'OCA\\Settings\\Sections\\Admin\\Office' => __DIR__ . '/..' . '/../lib/Sections/Admin/Office.php',
'OCA\\Settings\\Sections\\Admin\\Overview' => __DIR__ . '/..' . '/../lib/Sections/Admin/Overview.php',
'OCA\\Settings\\Sections\\Admin\\Presets' => __DIR__ . '/..' . '/../lib/Sections/Admin/Presets.php',
'OCA\\Settings\\Sections\\Admin\\Previews' => __DIR__ . '/..' . '/../lib/Sections/Admin/Previews.php',
'OCA\\Settings\\Sections\\Admin\\Security' => __DIR__ . '/..' . '/../lib/Sections/Admin/Security.php',
'OCA\\Settings\\Sections\\Admin\\Server' => __DIR__ . '/..' . '/../lib/Sections/Admin/Server.php',
'OCA\\Settings\\Sections\\Admin\\Sharing' => __DIR__ . '/..' . '/../lib/Sections/Admin/Sharing.php',
Expand All @@ -92,6 +94,7 @@ class ComposerStaticInitSettings
'OCA\\Settings\\Settings\\Admin\\MailProvider' => __DIR__ . '/..' . '/../lib/Settings/Admin/MailProvider.php',
'OCA\\Settings\\Settings\\Admin\\Overview' => __DIR__ . '/..' . '/../lib/Settings/Admin/Overview.php',
'OCA\\Settings\\Settings\\Admin\\Presets' => __DIR__ . '/..' . '/../lib/Settings/Admin/Presets.php',
'OCA\\Settings\\Settings\\Admin\\Previews' => __DIR__ . '/..' . '/../lib/Settings/Admin/Previews.php',
'OCA\\Settings\\Settings\\Admin\\Security' => __DIR__ . '/..' . '/../lib/Settings/Admin/Security.php',
'OCA\\Settings\\Settings\\Admin\\Server' => __DIR__ . '/..' . '/../lib/Settings/Admin/Server.php',
'OCA\\Settings\\Settings\\Admin\\Sharing' => __DIR__ . '/..' . '/../lib/Settings/Admin/Sharing.php',
Expand Down
1 change: 1 addition & 0 deletions apps/settings/img/previews.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 112 additions & 0 deletions apps/settings/lib/Controller/PreviewAdminController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Settings\Controller;

use OC\Preview\PreviewAdminConfig;
use OCA\Settings\Settings\Admin\Previews;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\ApiRoute;
use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCSController;
use OCP\Http\Client\IClientService;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

#[OpenAPI(scope: OpenAPI::SCOPE_ADMINISTRATION)]
class PreviewAdminController extends OCSController {
public function __construct(
string $appName,
IRequest $request,
private PreviewAdminConfig $previewAdminConfig,
private IClientService $clientService,
private LoggerInterface $logger,
) {
parent::__construct($appName, $request);
}

/**
* Update preview administration settings
*
* @param array<string, mixed> $settings Preview settings to persist
* @return DataResponse<Http::STATUS_OK, array<string, mixed>, array{}>
* @throws OCSBadRequestException Invalid settings payload
*
* 200: Settings saved
*/
#[AuthorizedAdminSetting(settings: Previews::class)]
#[PasswordConfirmationRequired]
#[ApiRoute(verb: 'PUT', url: '/api/admin/previews')]
public function update(array $settings): DataResponse {
try {
$this->previewAdminConfig->setSettings($settings);
} catch (\InvalidArgumentException $e) {
throw new OCSBadRequestException($e->getMessage());
}

return new DataResponse($this->previewAdminConfig->getSettings());
}

/**
* Test connectivity to an Imaginary preview service
*
* @param string|null $url Imaginary base URL
* @param string|null $key Optional Imaginary API key
* @return DataResponse<Http::STATUS_OK, array{status: string, httpCode?: int, error?: string}, array{}>
* @throws OCSBadRequestException Invalid URL
*
* 200: Connection test completed
*/
#[AuthorizedAdminSetting(settings: Previews::class)]
#[ApiRoute(verb: 'POST', url: '/api/admin/previews/imaginary/test')]
public function testImaginary(?string $url = null, ?string $key = null): DataResponse {
try {
$target = $this->previewAdminConfig->validateImaginaryUrl($url ?? '');
} catch (\InvalidArgumentException $e) {
throw new OCSBadRequestException($e->getMessage());
}

if ($target === '') {
return new DataResponse([
'status' => 'unconfigured',
]);
}

try {
$client = $this->clientService->newClient();
$options = [
'timeout' => 3,
'connect_timeout' => 3,
'nextcloud' => ['allow_local_address' => true],
];
if (is_string($key) && $key !== '') {
$options['query'] = ['key' => $key];
}
$response = $client->get($target, $options);
$statusCode = $response->getStatusCode();
$reachable = $statusCode >= 200 && $statusCode < 500;
return new DataResponse([
'status' => $reachable ? 'reachable' : 'unreachable',
'httpCode' => $statusCode,
]);
} catch (\Throwable $e) {
$this->logger->info('Imaginary connection test failed', [
'exception' => $e,
]);
return new DataResponse([
'status' => 'unreachable',
'error' => $e->getMessage(),
]);
}
}
}
42 changes: 42 additions & 0 deletions apps/settings/lib/Sections/Admin/Previews.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Settings\Sections\Admin;

use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Settings\IIconSection;

class Previews implements IIconSection {
public function __construct(
private IL10N $l,
private IURLGenerator $urlGenerator,
) {
}

#[\Override]
public function getIcon(): string {
return $this->urlGenerator->imagePath('settings', 'previews.svg');
}

#[\Override]
public function getID(): string {
return 'previews';
}

#[\Override]
public function getName(): string {
return $this->l->t('Previews');
}

#[\Override]
public function getPriority(): int {
return 6;
}
}
56 changes: 56 additions & 0 deletions apps/settings/lib/Settings/Admin/Previews.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Settings\Settings\Admin;

use OC\Preview\PreviewAdminConfig;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\Settings\IDelegatedSettings;
use OCP\Util;

class Previews implements IDelegatedSettings {
public function __construct(
private PreviewAdminConfig $previewAdminConfig,
private IInitialState $initialState,
private string $appName,
) {
}

#[\Override]
public function getForm(): TemplateResponse {
$this->initialState->provideInitialState('previewsSettings', $this->previewAdminConfig->getSettings());
$this->initialState->provideInitialState('previewsDocumentation', 'https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/previews_configuration.html');

Util::addScript($this->appName, 'vue-settings-admin-previews');
return new TemplateResponse($this->appName, 'settings/admin/previews', [], '');
}

#[\Override]
public function getSection(): string {
return 'previews';
}

#[\Override]
public function getPriority(): int {
return 0;
}

#[\Override]
public function getAuthorizedAppConfig(): array {
return [
'preview' => ['/jpeg_quality/', '/webp_quality/'],
];
}

#[\Override]
public function getName(): ?string {
return null;
}
}
13 changes: 13 additions & 0 deletions apps/settings/src/admin-settings-previews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*!
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import Vue from 'vue'
import AdminSettingsPreviews from './views/AdminSettingsPreviews.vue'

export default new Vue({
name: 'AdminSettingsPreviewsSection',
el: '#vue-admin-settings-previews',
render: (h) => h(AdminSettingsPreviews),
})
Loading