Add "Crop image previews" setting to files

Added a new user setting that toggles cropping on image previews
in grid view.

True (default value): crops each image to a square. False: keep original
aspect ratio.

Signed-off-by: Nina Pypchenko <22447785+nina-py@users.noreply.github.com>

Closes #18439.

Signed-off-by: npmbuildbot-nextcloud[bot] <npmbuildbot-nextcloud[bot]@users.noreply.github.com>
This commit is contained in:
Nina Pypchenko 2021-01-10 19:14:49 +11:00 committed by npmbuildbot-nextcloud[bot]
parent 97743df3fc
commit c14638877c
9 changed files with 85 additions and 2 deletions

View File

@ -76,6 +76,11 @@ $application->registerRoutes(
'url' => '/api/v1/showhidden', 'url' => '/api/v1/showhidden',
'verb' => 'POST' 'verb' => 'POST'
], ],
[
'name' => 'API#cropImagePreviews',
'url' => '/api/v1/cropimagepreviews',
'verb' => 'POST'
],
[ [
'name' => 'API#showGridView', 'name' => 'API#showGridView',
'url' => '/api/v1/showgridview', 'url' => '/api/v1/showgridview',

View File

@ -56,13 +56,18 @@
var showHidden = $('#showHiddenFiles').val() === "1"; var showHidden = $('#showHiddenFiles').val() === "1";
this.$showHiddenFiles.prop('checked', showHidden); this.$showHiddenFiles.prop('checked', showHidden);
// crop image previews
this.$cropImagePreviews = $('input#cropimagepreviewsToggle');
var cropImagePreviews = $('#cropImagePreviews').val() === "1";
this.$cropImagePreviews.prop('checked', cropImagePreviews);
if ($('#fileNotFound').val() === "1") { if ($('#fileNotFound').val() === "1") {
OC.Notification.show(t('files', 'File could not be found'), {type: 'error'}); OC.Notification.show(t('files', 'File could not be found'), {type: 'error'});
} }
this._filesConfig = new OC.Backbone.Model({ this._filesConfig = new OC.Backbone.Model({
showhidden: showHidden showhidden: showHidden,
cropimagepreviews: cropImagePreviews,
}); });
var urlParams = OC.Util.History.parseUrlQuery(); var urlParams = OC.Util.History.parseUrlQuery();
@ -132,6 +137,7 @@
}); });
this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200); this._debouncedPersistShowHiddenFilesState = _.debounce(this._persistShowHiddenFilesState, 1200);
this._debouncedPersistCropImagePreviewsState = _.debounce(this._persistCropImagePreviewsState, 1200);
if (sessionStorage.getItem('WhatsNewServerCheck') < (Date.now() - 3600*1000)) { if (sessionStorage.getItem('WhatsNewServerCheck') < (Date.now() - 3600*1000)) {
OCP.WhatsNew.query(); // for Nextcloud server OCP.WhatsNew.query(); // for Nextcloud server
@ -231,6 +237,7 @@
$('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this)); $('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this));
this.$showHiddenFiles.on('change', _.bind(this._onShowHiddenFilesChange, this)); this.$showHiddenFiles.on('change', _.bind(this._onShowHiddenFilesChange, this));
this.$cropImagePreviews.on('change', _.bind(this._onCropImagePreviewsChange, this));
}, },
/** /**
@ -256,6 +263,29 @@
}); });
}, },
/**
* Toggle cropping image previews according to the settings checkbox
*
* @returns void
*/
_onCropImagePreviewsChange: function() {
var crop = this.$cropImagePreviews.is(':checked');
this._filesConfig.set('cropimagepreviews', crop);
this._debouncedPersistCropImagePreviewsState();
},
/**
* Persist crop image previews preference on the server
*
* @returns void
*/
_persistCropImagePreviewsState: function() {
var crop = this._filesConfig.get('cropimagepreviews');
$.post(OC.generateUrl('/apps/files/api/v1/cropimagepreviews'), {
crop: crop
});
},
/** /**
* Event handler for when the current navigation item has changed * Event handler for when the current navigation item has changed
*/ */

View File

@ -252,7 +252,8 @@
this._filesConfig = OCA.Files.App.getFilesConfig(); this._filesConfig = OCA.Files.App.getFilesConfig();
} else { } else {
this._filesConfig = new OC.Backbone.Model({ this._filesConfig = new OC.Backbone.Model({
'showhidden': false 'showhidden': false,
'cropimagepreviews': true
}); });
} }
@ -291,6 +292,10 @@
} }
}); });
this._filesConfig.on('change:cropimagepreviews', function() {
self.reload();
});
this.$el.toggleClass('hide-hidden-files', !this._filesConfig.get('showhidden')); this.$el.toggleClass('hide-hidden-files', !this._filesConfig.get('showhidden'));
} }
@ -2215,6 +2220,12 @@
urlSpec.y = Math.ceil(urlSpec.y); urlSpec.y = Math.ceil(urlSpec.y);
urlSpec.forceIcon = 0; urlSpec.forceIcon = 0;
/**
* Images are cropped to a square by default. Append a=1 to the URL
* if the user wants to see images with original aspect ratio.
*/
urlSpec.a = this._filesConfig.get('cropimagepreviews') ? 0 : 1;
if (typeof urlSpec.fileId !== 'undefined') { if (typeof urlSpec.fileId !== 'undefined') {
delete urlSpec.file; delete urlSpec.file;
return OC.generateUrl('/core/preview?') + $.param(urlSpec); return OC.generateUrl('/core/preview?') + $.param(urlSpec);

View File

@ -280,6 +280,20 @@ class ApiController extends Controller {
return new Response(); return new Response();
} }
/**
* Toggle default for cropping preview images
*
* @NoAdminRequired
*
* @param bool $crop
* @return Response
* @throws \OCP\PreConditionNotMetException
*/
public function cropImagePreviews($crop) {
$this->config->setUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', (int)$crop);
return new Response();
}
/** /**
* Toggle default for files grid view * Toggle default for files grid view
* *

View File

@ -296,6 +296,8 @@ class ViewController extends Controller {
$params['isIE'] = \OCP\Util::isIE(); $params['isIE'] = \OCP\Util::isIE();
$showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false); $showHidden = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'show_hidden', false);
$params['showHiddenFiles'] = $showHidden ? 1 : 0; $params['showHiddenFiles'] = $showHidden ? 1 : 0;
$cropImagePreviews = (bool) $this->config->getUserValue($this->userSession->getUser()->getUID(), 'files', 'crop_image_previews', true);
$params['cropImagePreviews'] = $cropImagePreviews ? 1 : 0;
$params['fileNotFound'] = $fileNotFound ? 1 : 0; $params['fileNotFound'] = $fileNotFound ? 1 : 0;
$params['appNavigation'] = $nav; $params['appNavigation'] = $nav;
$params['appContents'] = $contentItems; $params['appContents'] = $contentItems;

View File

@ -44,6 +44,11 @@ script(\OCA\Files\AppInfo\Application::APP_ID, 'dist/files-app-settings');
checked="checked" type="checkbox"> checked="checked" type="checkbox">
<label for="showhiddenfilesToggle"><?php p($l->t('Show hidden files')); ?></label> <label for="showhiddenfilesToggle"><?php p($l->t('Show hidden files')); ?></label>
</div> </div>
<div id="files-setting-cropimagepreviews">
<input class="checkbox" id="cropimagepreviewsToggle"
checked="checked" type="checkbox">
<label for="cropimagepreviewsToggle"><?php p($l->t('Crop image previews')); ?></label>
</div>
<label for="webdavurl"><?php p($l->t('WebDAV')); ?></label> <label for="webdavurl"><?php p($l->t('WebDAV')); ?></label>
<input id="webdavurl" type="text" readonly="readonly" <input id="webdavurl" type="text" readonly="readonly"
value="<?php p($_['webdav_url']); ?>"/> value="<?php p($_['webdav_url']); ?>"/>

View File

@ -28,6 +28,7 @@
<input type="hidden" name="defaultFileSorting" id="defaultFileSorting" value="<?php p($_['defaultFileSorting']) ?>" /> <input type="hidden" name="defaultFileSorting" id="defaultFileSorting" value="<?php p($_['defaultFileSorting']) ?>" />
<input type="hidden" name="defaultFileSortingDirection" id="defaultFileSortingDirection" value="<?php p($_['defaultFileSortingDirection']) ?>" /> <input type="hidden" name="defaultFileSortingDirection" id="defaultFileSortingDirection" value="<?php p($_['defaultFileSortingDirection']) ?>" />
<input type="hidden" name="showHiddenFiles" id="showHiddenFiles" value="<?php p($_['showHiddenFiles']); ?>" /> <input type="hidden" name="showHiddenFiles" id="showHiddenFiles" value="<?php p($_['showHiddenFiles']); ?>" />
<input type="hidden" name="cropImagePreviews" id="cropImagePreviews" value="<?php p($_['cropImagePreviews']); ?>" />
<?php endif; <?php endif;
foreach ($_['hiddenFields'] as $name => $value) {?> foreach ($_['hiddenFields'] as $name => $value) {?>

View File

@ -246,4 +246,17 @@ class ApiControllerTest extends TestCase {
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
} }
public function testCropImagePreviews() {
$crop = true;
$this->config->expects($this->once())
->method('setUserValue')
->with($this->user->getUID(), 'files', 'crop_image_previews', $crop);
$expected = new Http\Response();
$actual = $this->apiController->cropImagePreviews($crop);
$this->assertEquals($expected, $actual);
}
} }

View File

@ -135,6 +135,7 @@ class ViewControllerTest extends TestCase {
[$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'], [$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'],
[$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc'], [$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc'],
[$this->user->getUID(), 'files', 'show_hidden', false, false], [$this->user->getUID(), 'files', 'show_hidden', false, false],
[$this->user->getUID(), 'files', 'crop_image_previews', true, true],
[$this->user->getUID(), 'files', 'show_grid', true], [$this->user->getUID(), 'files', 'show_grid', true],
]); ]);
@ -316,6 +317,7 @@ class ViewControllerTest extends TestCase {
'defaultFileSorting' => 'name', 'defaultFileSorting' => 'name',
'defaultFileSortingDirection' => 'asc', 'defaultFileSortingDirection' => 'asc',
'showHiddenFiles' => 0, 'showHiddenFiles' => 0,
'cropImagePreviews' => 1,
'fileNotFound' => 0, 'fileNotFound' => 0,
'allowShareWithLink' => 'yes', 'allowShareWithLink' => 'yes',
'appNavigation' => $nav, 'appNavigation' => $nav,