Non-cropped layout

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Signed-off-by: npmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2020-09-01 06:51:29 +02:00 committed by npmbuildbot[bot]
parent 14addf3994
commit f612c264bb
36 changed files with 244 additions and 33 deletions

View File

@ -1,5 +1,8 @@
module.exports = {
extends: [
'@nextcloud'
]
],
globals: {
appName: true
}
};

View File

@ -23,6 +23,8 @@
return [
'routes' => [
['name' => 'api#setUserConfig', 'url' => '/api/v1/config/{key}', 'verb' => 'PUT'],
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
['name' => 'page#index', 'url' => '/videos', 'verb' => 'GET', 'postfix' => 'videos'],
['name' => 'page#index', 'url' => '/favorites', 'verb' => 'GET', 'postfix' => 'favorites'],

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 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\Photos\Controller;
use OCA\Photos\AppInfo\Application;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IConfig;
use OCP\IRequest;
use OCP\IUserSession;
class ApiController extends Controller {
/** @var IConfig */
private $config;
/** @var IUserSession */
private $userSession;
public function __construct(IRequest $request,
IConfig $config,
IUserSession $userSession) {
parent::__construct(Application::APP_ID, $request);
$this->config = $config;
$this->userSession = $userSession;
}
/**
* @NoAdminRequired
*
* update preferences (user setting)
*
* @param string key the identifier to change
* @param string value the value to set
*
* @return JSONResponse an empty JSONResponse with respective http status code
*/
public function setUserConfig(string $key, string $value): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
$userId = $user->getUid();
$this->config->setUserValue($userId, Application::APP_ID, $key, $value);
return new JSONResponse([], Http::STATUS_OK);
}
}

View File

@ -28,40 +28,45 @@ namespace OCA\Photos\Controller;
use OCA\Files\Event\LoadSidebar;
use OCA\Photos\AppInfo\Application;
use OCA\Viewer\Event\LoadViewer;
use OCP\App\IAppManager;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IInitialStateService;
use OCP\IRequest;
use OCP\IUserSession;
use OCP\Util;
use OCP\IConfig;
use OCP\App\IAppManager;
class PageController extends Controller {
protected $appName;
/** @var IAppManager */
private $appManager;
/** @var IEventDispatcher */
private $eventDispatcher;
/** @var IConfig */
private $config;
/** @var IInitialStateService */
private $initialStateService;
/** @var IAppManager */
private $appManager;
/** @var IUserSession */
private $userSession;
public function __construct($appName,
public function __construct(IRequest $request,
IAppManager $appManager,
IRequest $request,
IEventDispatcher $eventDispatcher,
IConfig $config,
IInitialStateService $initialStateService) {
parent::__construct($appName, $request);
IInitialStateService $initialStateService,
IUserSession $userSession) {
parent::__construct(Application::APP_ID, $request);
$this->appName = $appName;
$this->appManager = $appManager;
$this->eventDispatcher = $eventDispatcher;
$this->initialStateService = $initialStateService;
$this->config = $config;
$this->initialStateService = $initialStateService;
$this->userSession = $userSession;
}
/**
@ -72,17 +77,20 @@ class PageController extends Controller {
* @return TemplateResponse
*/
public function index(): TemplateResponse {
$user = $this->userSession->getUser();
$this->eventDispatcher->dispatch(LoadSidebar::class, new LoadSidebar());
$this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());
$this->initialStateService->provideInitialState($this->appName, 'image-mimes', Application::IMAGE_MIMES);
$this->initialStateService->provideInitialState($this->appName, 'video-mimes', Application::VIDEO_MIMES);
$this->initialStateService->provideInitialState($this->appName, 'maps', $this->appManager->isEnabledForUser('maps') === true);
$this->initialStateService->provideInitialState($this->appName, 'croppedLayout', $this->config->getUserValue($user->getUid(), Application::APP_ID, 'croppedLayout', 'false'));
Util::addScript($this->appName, 'photos-main');
Util::addStyle($this->appName, 'icons');
Util::addScript(Application::APP_ID, 'photos-main');
Util::addStyle(Application::APP_ID, 'icons');
$response = new TemplateResponse($this->appName, 'main');
$response = new TemplateResponse(Application::APP_ID, 'main');
return $response;
}
}

14
package-lock.json generated
View File

@ -2562,11 +2562,6 @@
"integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=",
"dev": true
},
"@types/node": {
"version": "14.0.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.11.tgz",
"integrity": "sha512-lCvvI24L21ZVeIiyIUHZ5Oflv1hhHQ5E1S25IRlKIXaRkVgmXpJMI3wUJkmym2bTbCe+WoIibQnMVAU3FguaOg=="
},
"@types/normalize-package-data": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
@ -2580,12 +2575,9 @@
"dev": true
},
"@types/semver": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.2.0.tgz",
"integrity": "sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ==",
"requires": {
"@types/node": "*"
}
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ=="
},
"@types/unist": {
"version": "2.0.3",

View File

@ -34,6 +34,7 @@
"@essentials/request-timeout": "^1.3.0",
"@nextcloud/auth": "^1.3.0",
"@nextcloud/axios": "^1.4.0",
"@nextcloud/event-bus": "^1.2.0",
"@nextcloud/initial-state": "^1.2.0",
"@nextcloud/l10n": "^1.4.1",
"@nextcloud/router": "^1.2.0",

View File

@ -39,6 +39,11 @@
:title="t('photos', 'Locations')"
icon="icon-address" />
</template>
<template #footer>
<AppNavigationSettings :title="t('photos', 'Settings')">
<CroppedLayoutSettings />
</AppNavigationSettings>
</template>
</AppNavigation>
<AppContent :class="{ 'icon-loading': loading }">
<router-view v-show="!loading" :loading.sync="loading" />
@ -55,23 +60,29 @@
</template>
<script>
import { getCurrentUser } from '@nextcloud/auth'
import Content from '@nextcloud/vue/dist/Components/Content'
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
import AppNavigation from '@nextcloud/vue/dist/Components/AppNavigation'
import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
import AppNavigationSettings from '@nextcloud/vue/dist/Components/AppNavigationSettings'
import CroppedLayoutSettings from './components/Settings/CroppedLayoutSettings'
import svgplaceholder from './assets/file-placeholder.svg'
import imgplaceholder from './assets/image.svg'
import videoplaceholder from './assets/video.svg'
import isMapsInstalled from './services/IsMapsInstalled'
import { getCurrentUser } from '@nextcloud/auth'
export default {
name: 'Photos',
components: {
Content,
CroppedLayoutSettings,
AppContent,
AppNavigation,
AppNavigationItem,
AppNavigationSettings,
},
data() {
return {

View File

@ -21,7 +21,10 @@
-->
<template>
<a :class="{'file--clear': !loaded}"
<a :class="{
'file--clear': !loaded,
'file--cropped': croppedLayout,
}"
class="file"
:href="davPath"
:aria-label="ariaLabel"
@ -54,10 +57,12 @@
import { generateRemoteUrl, generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import UserConfig from '../mixins/UserConfig'
export default {
name: 'File',
mixins: [UserConfig],
inheritAttrs: false,
props: {
item: {
type: Object,
@ -85,7 +90,7 @@ export default {
return this.item.injected.mime.startsWith('image')
},
src() {
return generateUrl(`/core/preview?fileId=${this.item.injected.fileid}&x=${256}&y=${256}&a=false&v=${this.item.injected.etag}`)
return generateUrl(`/core/preview?fileId=${this.item.injected.fileid}&x=${256}&y=${256}&a=${!this.croppedLayout}&v=${this.item.injected.etag}`)
},
},
@ -127,7 +132,11 @@ img {
width: 100%;
height: 100%;
object-fit: cover;
object-fit: contain;
.file--cropped & {
object-fit: cover;
}
}
svg {

View File

@ -0,0 +1,48 @@
<!--
- @copyright Copyright (c) 2019 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/>.
-
-->
<template>
<div class="section">
<h2>{{ t('photos', 'Layout') }}</h2>
<p>
<input
id="enable-cropped-layout"
v-model="croppedLayout"
type="checkbox"
class="checkbox"
@change="updateSetting('croppedLayout')">
<label for="enable-cropped-layout">{{ t('photos', 'Enable cropped layout') }}</label>
</p>
</div>
</template>
<script>
import UserConfig from '../../mixins/UserConfig'
export default {
name: 'CroppedLayoutSettings',
mixins: [
UserConfig,
],
}
</script>

View File

@ -36,7 +36,7 @@ export default {
getGridConfig.$on('changed', val => {
this.gridConfig = val
})
console.debug('Current grid config', getGridConfig.gridConfig)
console.debug(`[${appName}]`, 'Grid config', Object.assign({}, getGridConfig.gridConfig))
this.gridConfig = getGridConfig.gridConfig
},

64
src/mixins/UserConfig.js Normal file
View File

@ -0,0 +1,64 @@
/**
* @copyright Copyright (c) 2020 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/>.
*
*/
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { generateUrl } from '@nextcloud/router'
import { loadState } from '@nextcloud/initial-state'
import axios from '@nextcloud/axios'
const eventName = 'photos:user-config-changed'
export default {
data() {
const croppedLayoutLocalStorage = localStorage.getItem('photos:croppedLayout')
return {
croppedLayout: croppedLayoutLocalStorage !== null
? croppedLayoutLocalStorage === 'true'
: loadState('photos', 'croppedLayout') === 'true',
}
},
created() {
subscribe(eventName, this.updateLocalSetting)
},
beforeDestroy() {
unsubscribe(eventName, this.updateLocalSetting)
},
methods: {
updateLocalSetting({ setting, value }) {
this[setting] = value
},
updateSetting(setting) {
const value = this[setting]
// Long time save setting
axios.put(generateUrl('apps/photos/api/v1/config/' + setting), {
value: value.toString(),
})
// Current session save setting
localStorage.setItem('photos:' + setting, value)
// Visible elements update setting
emit(eventName, { setting, value })
},
},
}

View File

@ -2,7 +2,7 @@ const { merge } = require('webpack-merge')
const webpackConfig = require('@nextcloud/webpack-vue-config')
const SassGetGridConfig = require('./src/utils/SassGetGridConfig')
const ModuleReplaceWebpackPlugin = require('module-replace-webpack-plugin');
const ModuleReplaceWebpackPlugin = require('module-replace-webpack-plugin')
const BabelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
const config = {