big: remove initial state except for shares
Signed-off-by: Varun Patil <radialapps@gmail.com>pull/653/head
parent
80836d4e05
commit
37abc991b1
|
@ -84,6 +84,7 @@ return [
|
|||
|
||||
// Config
|
||||
['name' => 'Other#setUserConfig', 'url' => '/api/config/{key}', 'verb' => 'PUT'],
|
||||
['name' => 'Other#getUserConfig', 'url' => '/api/config', 'verb' => 'GET'],
|
||||
|
||||
// Admin
|
||||
['name' => 'Admin#getSystemStatus', 'url' => '/api/system-status', 'verb' => 'GET'],
|
||||
|
|
|
@ -56,6 +56,50 @@ class OtherController extends GenericApiController
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @PublicPage
|
||||
*/
|
||||
public function getUserConfig(): Http\Response
|
||||
{
|
||||
return Util::guardEx(function () {
|
||||
$appManager = \OC::$server->get(\OCP\App\IAppManager::class);
|
||||
|
||||
try {
|
||||
$uid = Util::getUID();
|
||||
} catch (\Exception $e) {
|
||||
$uid = null;
|
||||
}
|
||||
|
||||
$getAppConfig = function ($key, $default) use ($uid) {
|
||||
return $this->config->getUserValue($uid, Application::APPNAME, $key, $default);
|
||||
};
|
||||
|
||||
return new JSONResponse([
|
||||
"version" => $appManager->getAppInfo('memories')['version'],
|
||||
"vod_disable" => Util::getSystemConfig('memories.vod.disable'),
|
||||
"video_default_quality" => Util::getSystemConfig('memories.video_default_quality'),
|
||||
"places_gis" => Util::getSystemConfig('memories.gis_type'),
|
||||
|
||||
"systemtags_enabled" => Util::tagsIsEnabled(),
|
||||
"recognize_enabled" => Util::recognizeIsEnabled(),
|
||||
"albums_enabled" => Util::albumsIsEnabled(),
|
||||
"facerecognition_installed" => Util::facerecognitionIsInstalled(),
|
||||
"facerecognition_enabled" => Util::facerecognitionIsEnabled(),
|
||||
|
||||
"timeline_path" => $getAppConfig('timelinePath', 'EMPTY'),
|
||||
"folders_path" => $getAppConfig('foldersPath', '/'),
|
||||
"show_hidden_folders" => $getAppConfig('showHidden', false) === "true",
|
||||
"sort_folder_month" => $getAppConfig('sortFolderMonth', false) === "true",
|
||||
"sort_album_month" => $getAppConfig('sortAlbumMonth', "true") === "true",
|
||||
"enable_top_memories" => $getAppConfig('enableTopMemories', 'true') === "true",
|
||||
], Http::STATUS_OK);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
|
|
|
@ -58,35 +58,6 @@ class PageController extends Controller
|
|||
OCPUtil::addScript($this->appName, 'memories-main');
|
||||
$this->eventDispatcher->dispatchTyped(new LoadSidebar());
|
||||
|
||||
// Configuration
|
||||
$uid = $user->getUID();
|
||||
$pi = function ($key, $default) use ($uid) {
|
||||
$this->initialState->provideInitialState($key, $this->config->getUserValue(
|
||||
$uid,
|
||||
Application::APPNAME,
|
||||
$key,
|
||||
$default
|
||||
));
|
||||
};
|
||||
|
||||
// User configuration
|
||||
$pi('timelinePath', 'EMPTY');
|
||||
$pi('foldersPath', '/');
|
||||
$pi('showHidden', false);
|
||||
$pi('sortFolderMonth', false);
|
||||
$pi('sortAlbumMonth', 'true');
|
||||
$pi('enableTopMemories', 'true');
|
||||
|
||||
// Apps enabled
|
||||
$this->initialState->provideInitialState('systemtags', Util::tagsIsEnabled());
|
||||
$this->initialState->provideInitialState('recognize', Util::recognizeIsEnabled());
|
||||
$this->initialState->provideInitialState('facerecognitionInstalled', Util::facerecognitionIsInstalled());
|
||||
$this->initialState->provideInitialState('facerecognitionEnabled', Util::facerecognitionIsEnabled());
|
||||
$this->initialState->provideInitialState('albums', Util::albumsIsEnabled());
|
||||
|
||||
// Common state
|
||||
self::provideCommonInitialState($this->initialState);
|
||||
|
||||
// Extra translations
|
||||
if (Util::recognizeIsEnabled()) {
|
||||
// Auto translation for tags
|
||||
|
@ -138,22 +109,6 @@ class PageController extends Controller
|
|||
return $policy;
|
||||
}
|
||||
|
||||
/** Provide initial state for all pages */
|
||||
public static function provideCommonInitialState(IInitialState &$initialState)
|
||||
{
|
||||
$appManager = \OC::$server->get(\OCP\App\IAppManager::class);
|
||||
|
||||
// App version
|
||||
$initialState->provideInitialState('version', $appManager->getAppInfo('memories')['version']);
|
||||
|
||||
// Video configuration
|
||||
$initialState->provideInitialState('vod_disable', Util::getSystemConfig('memories.vod.disable'));
|
||||
$initialState->provideInitialState('video_default_quality', Util::getSystemConfig('memories.video_default_quality'));
|
||||
|
||||
// Geo configuration
|
||||
$initialState->provideInitialState('places_gis', Util::getSystemConfig('memories.gis_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
|
|
|
@ -85,7 +85,6 @@ class PublicAlbumController extends Controller
|
|||
|
||||
// Scripts
|
||||
Util::addScript($this->appName, 'memories-main');
|
||||
PageController::provideCommonInitialState($this->initialState);
|
||||
|
||||
$response = new PublicTemplateResponse($this->appName, 'main');
|
||||
$response->setHeaderTitle($album['name']);
|
||||
|
|
|
@ -111,7 +111,6 @@ class PublicController extends AuthPublicShareController
|
|||
|
||||
// Scripts
|
||||
\OCP\Util::addScript($this->appName, 'memories-main');
|
||||
PageController::provideCommonInitialState($this->initialState);
|
||||
|
||||
// Share info
|
||||
$this->initialState->provideInitialState('no_download', $share->getHideDownload());
|
||||
|
|
35
src/App.vue
35
src/App.vue
|
@ -59,7 +59,7 @@ const NcAppNavigationItem = () => import('@nextcloud/vue/dist/Components/NcAppNa
|
|||
|
||||
import { generateUrl } from '@nextcloud/router';
|
||||
import { translate as t } from '@nextcloud/l10n';
|
||||
import { emit } from '@nextcloud/event-bus';
|
||||
import { emit, subscribe } from '@nextcloud/event-bus';
|
||||
|
||||
import * as utils from './services/Utils';
|
||||
import UserConfig from './mixins/UserConfig';
|
||||
|
@ -137,11 +137,11 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
recognize(): string | false {
|
||||
if (!this.config_recognizeEnabled) {
|
||||
if (!this.config.recognize_enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.config_facerecognitionInstalled) {
|
||||
if (this.config.facerecognition_enabled) {
|
||||
return t('memories', 'People (Recognize)');
|
||||
}
|
||||
|
||||
|
@ -149,11 +149,11 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
facerecognition(): string | false {
|
||||
if (!this.config_facerecognitionInstalled) {
|
||||
if (!this.config.facerecognition_installed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.config_recognizeEnabled) {
|
||||
if (this.config.recognize_enabled) {
|
||||
return t('memories', 'People (Face Recognition)');
|
||||
}
|
||||
|
||||
|
@ -161,11 +161,15 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
isFirstStart(): boolean {
|
||||
return this.config_timelinePath === 'EMPTY';
|
||||
return (
|
||||
this.config.timeline_path === 'EMPTY' &&
|
||||
this.$route.name !== 'folder-share' &&
|
||||
this.$route.name !== 'album-share'
|
||||
);
|
||||
},
|
||||
|
||||
showAlbums(): boolean {
|
||||
return this.config_albumsEnabled;
|
||||
return this.config.albums_enabled;
|
||||
},
|
||||
|
||||
removeOuterGap(): boolean {
|
||||
|
@ -197,13 +201,14 @@ export default defineComponent({
|
|||
window.addEventListener('resize', () => {
|
||||
utils.setRenewingTimeout(this, 'resizeTimer', onResize, 100);
|
||||
});
|
||||
|
||||
// Register navigation items on config change
|
||||
subscribe(this.configEventName, this.refreshNav);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.doRouteChecks();
|
||||
|
||||
// Populate navigation
|
||||
this.navItems = this.navItemsAll().filter((item) => typeof item.if === 'undefined' || Boolean(item.if));
|
||||
this.refreshNav();
|
||||
|
||||
// Store CSS variables modified
|
||||
const root = document.documentElement;
|
||||
|
@ -255,8 +260,8 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
methods: {
|
||||
navItemsAll(): NavItem[] {
|
||||
return [
|
||||
refreshNav() {
|
||||
const navItems = [
|
||||
{
|
||||
name: 'timeline',
|
||||
icon: ImageMultiple,
|
||||
|
@ -309,7 +314,7 @@ export default defineComponent({
|
|||
name: 'places',
|
||||
icon: MarkerIcon,
|
||||
title: t('memories', 'Places'),
|
||||
if: this.config_placesGis > 0,
|
||||
if: this.config.places_gis > 0,
|
||||
},
|
||||
{
|
||||
name: 'map',
|
||||
|
@ -320,9 +325,11 @@ export default defineComponent({
|
|||
name: 'tags',
|
||||
icon: TagsIcon,
|
||||
title: t('memories', 'Tags'),
|
||||
if: this.config_tagsEnabled,
|
||||
if: this.config.systemtags_enabled,
|
||||
},
|
||||
];
|
||||
|
||||
this.navItems = navItems.filter((item) => typeof item.if === 'undefined' || Boolean(item.if));
|
||||
},
|
||||
|
||||
linkClick() {
|
||||
|
|
|
@ -53,11 +53,11 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
created() {
|
||||
subscribe(this.config_eventName, this.routeChange);
|
||||
subscribe(this.configEventName, this.routeChange);
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
unsubscribe(this.config_eventName, this.routeChange);
|
||||
unsubscribe(this.configEventName, this.routeChange);
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
@ -74,7 +74,7 @@ export default defineComponent({
|
|||
this.loading++;
|
||||
|
||||
if (route === 'albums') {
|
||||
this.items = await dav.getAlbums(3, this.config_albumListSort);
|
||||
this.items = await dav.getAlbums(3, this.config.album_list_sort);
|
||||
} else if (route === 'tags') {
|
||||
this.items = await dav.getTags();
|
||||
} else if (route === 'recognize' || route === 'facerecognition') {
|
||||
|
|
|
@ -118,8 +118,8 @@ export default defineComponent({
|
|||
async finish() {
|
||||
this.show = false;
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
this.config_timelinePath = this.chosenPath;
|
||||
await this.updateSetting('timelinePath');
|
||||
this.config.timeline_path = this.chosenPath;
|
||||
await this.updateSetting('timeline_path', 'timelinePath');
|
||||
},
|
||||
|
||||
async chooseFolder(title: string, initial: string) {
|
||||
|
|
|
@ -254,7 +254,7 @@ export default defineComponent({
|
|||
|
||||
/** Is album route */
|
||||
routeIsAlbum() {
|
||||
return this.config_albumsEnabled && this.$route.name === 'albums';
|
||||
return this.config.albums_enabled && this.$route.name === 'albums';
|
||||
},
|
||||
|
||||
/** Public route that can't modify anything */
|
||||
|
@ -786,7 +786,7 @@ export default defineComponent({
|
|||
* Move selected photos to another person
|
||||
*/
|
||||
async moveSelectionToPerson(selection: Selection) {
|
||||
if (!this.config_showFaceRect) {
|
||||
if (!this.config.show_face_rect) {
|
||||
showError(this.t('memories', 'You must enable "Mark person in preview" to use this feature'));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -30,39 +30,51 @@
|
|||
>
|
||||
<NcAppSettingsSection id="general-settings" :title="t('memories', 'General')">
|
||||
<label for="timeline-path">{{ t('memories', 'Timeline Path') }}</label>
|
||||
<input id="timeline-path" @click="chooseTimelinePath" v-model="config_timelinePath" type="text" />
|
||||
<input id="timeline-path" @click="chooseTimelinePath" v-model="config.timeline_path" type="text" />
|
||||
|
||||
<NcCheckboxRadioSwitch :checked.sync="config_squareThumbs" @update:checked="updateSquareThumbs" type="switch">
|
||||
<NcCheckboxRadioSwitch :checked.sync="config.square_thumbs" @update:checked="updateSquareThumbs" type="switch">
|
||||
{{ t('memories', 'Square grid mode') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
|
||||
<NcCheckboxRadioSwitch
|
||||
:checked.sync="config_enableTopMemories"
|
||||
:checked.sync="config.enable_top_memories"
|
||||
@update:checked="updateEnableTopMemories"
|
||||
type="switch"
|
||||
>
|
||||
{{ t('memories', 'Show past photos on top of timeline') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
|
||||
<NcCheckboxRadioSwitch :checked.sync="config_fullResOnZoom" @update:checked="updateFullResOnZoom" type="switch">
|
||||
<NcCheckboxRadioSwitch
|
||||
:checked.sync="config.full_res_on_zoom"
|
||||
@update:checked="updateFullResOnZoom"
|
||||
type="switch"
|
||||
>
|
||||
{{ t('memories', 'Load full size image on zoom') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
|
||||
<NcCheckboxRadioSwitch :checked.sync="config_fullResAlways" @update:checked="updateFullResAlways" type="switch">
|
||||
<NcCheckboxRadioSwitch
|
||||
:checked.sync="config.full_res_always"
|
||||
@update:checked="updateFullResAlways"
|
||||
type="switch"
|
||||
>
|
||||
{{ t('memories', 'Always load full size image (not recommended)') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
</NcAppSettingsSection>
|
||||
|
||||
<NcAppSettingsSection id="folders-settings" :title="t('memories', 'Folders')">
|
||||
<label for="folders-path">{{ t('memories', 'Folders Path') }}</label>
|
||||
<input id="folders-path" @click="chooseFoldersPath" v-model="config_foldersPath" type="text" />
|
||||
<input id="folders-path" @click="chooseFoldersPath" v-model="config.folders_path" type="text" />
|
||||
|
||||
<NcCheckboxRadioSwitch :checked.sync="config_showHidden" @update:checked="updateShowHidden" type="switch">
|
||||
<NcCheckboxRadioSwitch
|
||||
:checked.sync="config.show_hidden_folders"
|
||||
@update:checked="updateShowHidden"
|
||||
type="switch"
|
||||
>
|
||||
{{ t('memories', 'Show hidden folders') }}
|
||||
</NcCheckboxRadioSwitch>
|
||||
|
||||
<NcCheckboxRadioSwitch
|
||||
:checked.sync="config_sortFolderMonth"
|
||||
:checked.sync="config.sort_folder_month"
|
||||
@update:checked="updateSortFolderMonth"
|
||||
type="switch"
|
||||
>
|
||||
|
@ -72,7 +84,7 @@
|
|||
|
||||
<NcAppSettingsSection id="albums-settings" :title="t('memories', 'Albums')">
|
||||
<NcCheckboxRadioSwitch
|
||||
:checked.sync="config_sortAlbumMonth"
|
||||
:checked.sync="config.sort_album_month"
|
||||
@update:checked="updateSortAlbumMonth"
|
||||
type="switch"
|
||||
>
|
||||
|
@ -147,57 +159,57 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
async chooseTimelinePath() {
|
||||
(<any>this.$refs.multiPathModal).open(this.config_timelinePath.split(';'));
|
||||
(<any>this.$refs.multiPathModal).open(this.config.timeline_path.split(';'));
|
||||
},
|
||||
|
||||
async saveTimelinePath(paths: string[]) {
|
||||
if (!paths || !paths.length) return;
|
||||
|
||||
const newPath = paths.join(';');
|
||||
if (newPath !== this.config_timelinePath) {
|
||||
this.config_timelinePath = newPath;
|
||||
await this.updateSetting('timelinePath');
|
||||
if (newPath !== this.config.timeline_path) {
|
||||
this.config.timeline_path = newPath;
|
||||
await this.updateSetting('timeline_path', 'timelinePath');
|
||||
}
|
||||
},
|
||||
|
||||
async chooseFoldersPath() {
|
||||
let newPath = await this.chooseFolder(
|
||||
this.t('memories', 'Choose the root for the folders view'),
|
||||
this.config_foldersPath
|
||||
this.config.folders_path
|
||||
);
|
||||
if (newPath === '') newPath = '/';
|
||||
if (newPath !== this.config_foldersPath) {
|
||||
this.config_foldersPath = newPath;
|
||||
await this.updateSetting('foldersPath');
|
||||
if (newPath !== this.config.folders_path) {
|
||||
this.config.folders_path = newPath;
|
||||
await this.updateSetting('folders_path', 'foldersPath');
|
||||
}
|
||||
},
|
||||
|
||||
async updateSquareThumbs() {
|
||||
await this.updateSetting('squareThumbs');
|
||||
await this.updateSetting('square_thumbs');
|
||||
},
|
||||
|
||||
async updateFullResOnZoom() {
|
||||
await this.updateSetting('fullResOnZoom');
|
||||
await this.updateSetting('full_res_on_zoom');
|
||||
},
|
||||
|
||||
async updateFullResAlways() {
|
||||
await this.updateSetting('fullResAlways');
|
||||
await this.updateSetting('full_res_always');
|
||||
},
|
||||
|
||||
async updateEnableTopMemories() {
|
||||
await this.updateSetting('enableTopMemories');
|
||||
await this.updateSetting('enable_top_memories', 'enableTopMemories');
|
||||
},
|
||||
|
||||
async updateShowHidden() {
|
||||
await this.updateSetting('showHidden');
|
||||
await this.updateSetting('show_hidden_folders', 'showHidden');
|
||||
},
|
||||
|
||||
async updateSortFolderMonth() {
|
||||
await this.updateSetting('sortFolderMonth');
|
||||
await this.updateSetting('sort_folder_month', 'sortFolderMonth');
|
||||
},
|
||||
|
||||
async updateSortAlbumMonth() {
|
||||
await this.updateSetting('sortAlbumMonth');
|
||||
await this.updateSetting('sort_album_month', 'sortAlbumMonth');
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
</div>
|
||||
|
||||
<OnThisDay
|
||||
v-if="routeIsBase && config_enableTopMemories"
|
||||
:key="config_timelinePath"
|
||||
v-if="routeIsBase && config.enable_top_memories"
|
||||
:key="config.timeline_path"
|
||||
:viewer="$refs.viewer"
|
||||
@load="scrollerManager.adjust()"
|
||||
>
|
||||
|
@ -204,16 +204,17 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
created() {
|
||||
subscribe(this.config_eventName, this.softRefresh);
|
||||
subscribe(this.configEventName, this.softRefresh);
|
||||
subscribe('files:file:created', this.softRefresh);
|
||||
subscribe('memories:window:resize', this.handleResizeWithDelay);
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
unsubscribe(this.config_eventName, this.softRefresh);
|
||||
unsubscribe(this.configEventName, this.softRefresh);
|
||||
unsubscribe('files:file:created', this.softRefresh);
|
||||
unsubscribe('memories:window:resize', this.handleResizeWithDelay);
|
||||
this.resetState();
|
||||
this.state = 0;
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
@ -234,8 +235,8 @@ export default defineComponent({
|
|||
|
||||
return (
|
||||
this.$route.query.sort === 'album' ||
|
||||
(this.config_sortAlbumMonth && (this.$route.name === 'albums' || this.$route.name === 'album-share')) ||
|
||||
(this.config_sortFolderMonth && this.$route.name === 'folders')
|
||||
(this.config.sort_album_month && (this.$route.name === 'albums' || this.$route.name === 'album-share')) ||
|
||||
(this.config.sort_folder_month && this.$route.name === 'folders')
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -316,7 +317,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
allowBreakout() {
|
||||
return globalThis.windowInnerWidth <= 600 && !this.config_squareThumbs;
|
||||
return globalThis.windowInnerWidth <= 600 && !this.config.square_thumbs;
|
||||
},
|
||||
|
||||
/** Create new state */
|
||||
|
@ -412,7 +413,7 @@ export default defineComponent({
|
|||
this.rowHeight = Math.floor(this.rowWidth / this.numCols);
|
||||
} else {
|
||||
// Desktop
|
||||
if (this.config_squareThumbs) {
|
||||
if (this.config.square_thumbs) {
|
||||
this.numCols = Math.max(3, Math.floor(this.rowWidth / DESKTOP_ROW_HEIGHT));
|
||||
this.rowHeight = Math.floor(this.rowWidth / this.numCols);
|
||||
} else {
|
||||
|
@ -557,7 +558,7 @@ export default defineComponent({
|
|||
|
||||
// Folder
|
||||
if (this.$route.name === 'folders') {
|
||||
const path = utils.getFolderRoutePath(this.config_foldersPath);
|
||||
const path = utils.getFolderRoutePath(this.config.folders_path);
|
||||
API.DAYS_FILTER(query, DaysFilterType.FOLDER, path);
|
||||
if (this.$route.query.recursive) {
|
||||
API.DAYS_FILTER(query, DaysFilterType.RECURSIVE);
|
||||
|
@ -589,7 +590,7 @@ export default defineComponent({
|
|||
API.DAYS_FILTER(query, filter, `${user}/${name}`);
|
||||
|
||||
// Face rect
|
||||
if (this.config_showFaceRect) {
|
||||
if (this.config.show_face_rect) {
|
||||
API.DAYS_FILTER(query, DaysFilterType.FACE_RECT);
|
||||
}
|
||||
}
|
||||
|
@ -639,7 +640,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
// Get subfolders URL
|
||||
const folder = utils.getFolderRoutePath(this.config_foldersPath);
|
||||
const folder = utils.getFolderRoutePath(this.config.folders_path);
|
||||
const url = API.Q(API.FOLDERS_SUB(), { folder });
|
||||
|
||||
// Make API call to get subfolders
|
||||
|
@ -654,7 +655,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
// Filter out hidden folders
|
||||
if (!this.config_showHidden) {
|
||||
if (!this.config.show_hidden_folders) {
|
||||
this.folders = this.folders.filter((f) => !f.name.startsWith('.') && f.previews?.length);
|
||||
}
|
||||
},
|
||||
|
@ -730,6 +731,8 @@ export default defineComponent({
|
|||
|
||||
/** Process the data for days call including folders */
|
||||
async processDays(data: IDay[]) {
|
||||
if (!data || !this.state) return;
|
||||
|
||||
const list: typeof this.list = [];
|
||||
const heads: typeof this.heads = {};
|
||||
|
||||
|
@ -941,7 +944,7 @@ export default defineComponent({
|
|||
* @param data photos
|
||||
*/
|
||||
processDay(dayId: number, data: IPhoto[]) {
|
||||
if (!data) return;
|
||||
if (!data || !this.state) return;
|
||||
|
||||
const head = this.heads[dayId];
|
||||
if (!head) return;
|
||||
|
@ -964,7 +967,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
// Force all to square
|
||||
const squareMode = this.isMobileLayout() || this.config_squareThumbs;
|
||||
const squareMode = this.isMobileLayout() || this.config.square_thumbs;
|
||||
|
||||
// Create justified layout with correct params
|
||||
const justify = getLayout(
|
||||
|
|
|
@ -70,7 +70,7 @@ export default defineComponent({
|
|||
.slice(2) as string[];
|
||||
|
||||
// Remove base path if present
|
||||
const basePath = this.config_foldersPath.split('/').filter((x) => x);
|
||||
const basePath = this.config.folders_path.split('/').filter((x) => x);
|
||||
if (path.length >= basePath.length && path.slice(0, basePath.length).every((x, i) => x === basePath[i])) {
|
||||
path.splice(0, basePath.length);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
async chooseFolderPath() {
|
||||
let destination = await this.chooseFolderModal(this.t('memories', 'Choose a folder'), this.config_foldersPath);
|
||||
let destination = await this.chooseFolderModal(this.t('memories', 'Choose a folder'), this.config.folders_path);
|
||||
// Fails if the target exists, same behavior with Nextcloud files implementation.
|
||||
const gen = dav.movePhotos(this.photos, destination, false);
|
||||
this.processing = true;
|
||||
|
|
|
@ -71,12 +71,12 @@
|
|||
import { defineComponent } from 'vue';
|
||||
|
||||
import { showError } from '@nextcloud/dialogs';
|
||||
import { loadState } from '@nextcloud/initial-state';
|
||||
import axios from '@nextcloud/axios';
|
||||
|
||||
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem';
|
||||
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon';
|
||||
import Modal from './Modal.vue';
|
||||
import UserConfig from '../../mixins/UserConfig';
|
||||
|
||||
import { IPhoto } from '../../types';
|
||||
import { API } from '../../services/API';
|
||||
|
@ -88,9 +88,6 @@ import LargePhotoIcon from 'vue-material-design-icons/ImageArea.vue';
|
|||
import LinkIcon from 'vue-material-design-icons/LinkVariant.vue';
|
||||
import FileIcon from 'vue-material-design-icons/File.vue';
|
||||
|
||||
// Is video transcoding enabled?
|
||||
const config_vodDisable = loadState('memories', 'vod_disable', true);
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ShareModal',
|
||||
|
||||
|
@ -105,6 +102,8 @@ export default defineComponent({
|
|||
FileIcon,
|
||||
},
|
||||
|
||||
mixins: [UserConfig],
|
||||
|
||||
data: () => {
|
||||
return {
|
||||
photo: null as IPhoto | null,
|
||||
|
@ -128,7 +127,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
canShareHighRes() {
|
||||
return !this.isVideo || !config_vodDisable;
|
||||
return !this.isVideo || !this.config.vod_disable;
|
||||
},
|
||||
|
||||
canShareLink() {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<NcActionRadio
|
||||
name="sort"
|
||||
:aria-label="t('memories', 'Sort by date')"
|
||||
:checked="config_albumListSort === 1"
|
||||
:checked="config.album_list_sort === 1"
|
||||
@change="changeSort(1)"
|
||||
close-after-click
|
||||
>
|
||||
|
@ -29,7 +29,7 @@
|
|||
<NcActionRadio
|
||||
name="sort"
|
||||
:aria-label="t('memories', 'Sort by name')"
|
||||
:checked="config_albumListSort === 2"
|
||||
:checked="config.album_list_sort === 2"
|
||||
@change="changeSort(2)"
|
||||
close-after-click
|
||||
>
|
||||
|
@ -194,8 +194,8 @@ export default defineComponent({
|
|||
* 1 = date, 2 = name
|
||||
*/
|
||||
changeSort(order: 1 | 2) {
|
||||
this.config_albumListSort = order;
|
||||
this.updateSetting('albumListSort');
|
||||
this.config.album_list_sort = order;
|
||||
this.updateSetting('album_list_sort');
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</NcActionButton>
|
||||
<NcActionCheckbox
|
||||
:aria-label="t('memories', 'Mark person in preview')"
|
||||
:checked.sync="config_showFaceRect"
|
||||
:checked.sync="config.show_face_rect"
|
||||
@change="changeShowFaceRect"
|
||||
>
|
||||
{{ t('memories', 'Mark person in preview') }}
|
||||
|
@ -104,10 +104,8 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
changeShowFaceRect() {
|
||||
localStorage.setItem('memories_showFaceRect', this.config_showFaceRect ? '1' : '0');
|
||||
setTimeout(() => {
|
||||
this.$router.go(0); // refresh page
|
||||
}, 500);
|
||||
this.updateSetting('show_face_rect');
|
||||
setTimeout(() => this.$router.go(0), 100); // refresh page
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -108,7 +108,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
share() {
|
||||
globalThis.shareNodeLink(utils.getFolderRoutePath(this.config_foldersPath));
|
||||
globalThis.shareNodeLink(utils.getFolderRoutePath(this.config.folders_path));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import PhotoSwipe from 'photoswipe';
|
||||
import { loadState } from '@nextcloud/initial-state';
|
||||
import staticConfig from '../../services/static-config';
|
||||
import { showError } from '@nextcloud/dialogs';
|
||||
import { translate as t } from '@nextcloud/l10n';
|
||||
import { getCurrentUser } from '@nextcloud/auth';
|
||||
|
@ -25,10 +25,6 @@ type PsVideoEvent = PsEvent & {
|
|||
content: VideoContent;
|
||||
};
|
||||
|
||||
const config_vodDisable = loadState('memories', 'vod_disable', true);
|
||||
|
||||
const config_video_default_quality = Number(loadState('memories', 'video_default_quality', <string>'0') as string);
|
||||
|
||||
/**
|
||||
* Check if slide has video content
|
||||
*/
|
||||
|
@ -155,7 +151,7 @@ class VideoContentSetup {
|
|||
type: string;
|
||||
}[] = [];
|
||||
|
||||
if (!config_vodDisable) {
|
||||
if (!staticConfig.getSync('vod_disable')) {
|
||||
sources.push(this.getHLSsrc(content));
|
||||
}
|
||||
|
||||
|
@ -205,7 +201,7 @@ class VideoContentSetup {
|
|||
directFailed = true;
|
||||
console.warn('PsVideo: Direct video stream could not be opened.');
|
||||
|
||||
if (!hlsFailed && !config_vodDisable) {
|
||||
if (!hlsFailed && !staticConfig.getSync('vod_disable')) {
|
||||
console.warn('PsVideo: Trying HLS stream');
|
||||
vjs.src(this.getHLSsrc(content));
|
||||
}
|
||||
|
@ -336,7 +332,7 @@ class VideoContentSetup {
|
|||
// Add quality options
|
||||
if (qualityNums) {
|
||||
opts.quality = {
|
||||
default: config_video_default_quality,
|
||||
default: Number(staticConfig.getSync('video_default_quality')),
|
||||
options: qualityNums,
|
||||
forced: true,
|
||||
onChange: (quality: number) => {
|
||||
|
|
|
@ -770,7 +770,7 @@ export default defineComponent({
|
|||
|
||||
// Get full image URL
|
||||
const fullUrl = isvideo ? null : API.IMAGE_DECODABLE(photo.fileid, photo.etag);
|
||||
const fullLoadCond = this.config_fullResAlways ? 'always' : this.config_fullResOnZoom ? 'zoom' : 'never';
|
||||
const fullLoadCond = this.config.full_res_always ? 'always' : this.config.full_res_on_zoom ? 'zoom' : 'never';
|
||||
|
||||
return {
|
||||
src: previewUrl,
|
||||
|
|
|
@ -1,43 +1,30 @@
|
|||
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus';
|
||||
import { loadState } from '@nextcloud/initial-state';
|
||||
import axios from '@nextcloud/axios';
|
||||
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus';
|
||||
import { API } from '../services/API';
|
||||
import { defineComponent } from 'vue';
|
||||
import { IConfig } from '../types';
|
||||
import staticConfig from '../services/static-config';
|
||||
|
||||
const eventName = 'memories:user-config-changed';
|
||||
const localSettings = ['squareThumbs', 'fullResOnZoom', 'fullResAlways', 'showFaceRect', 'albumListSort'];
|
||||
const localSettings: (keyof IConfig)[] = [
|
||||
'square_thumbs',
|
||||
'full_res_on_zoom',
|
||||
'full_res_always',
|
||||
'show_face_rect',
|
||||
'album_list_sort',
|
||||
];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'UserConfig',
|
||||
|
||||
data: () => ({
|
||||
config_timelinePath: loadState('memories', 'timelinePath', <string>'') as string,
|
||||
config_foldersPath: loadState('memories', 'foldersPath', <string>'/') as string,
|
||||
|
||||
config_showHidden: loadState('memories', 'showHidden', <string>'false') === 'true',
|
||||
config_sortFolderMonth: loadState('memories', 'sortFolderMonth', <string>'false') === 'true',
|
||||
config_sortAlbumMonth: loadState('memories', 'sortAlbumMonth', <string>'true') === 'true',
|
||||
config_enableTopMemories: loadState('memories', 'enableTopMemories', <string>'false') === 'true',
|
||||
|
||||
config_tagsEnabled: Boolean(loadState('memories', 'systemtags', <string>'')),
|
||||
config_recognizeEnabled: Boolean(loadState('memories', 'recognize', <string>'')),
|
||||
config_facerecognitionInstalled: Boolean(loadState('memories', 'facerecognitionInstalled', <string>'')),
|
||||
config_facerecognitionEnabled: Boolean(loadState('memories', 'facerecognitionEnabled', <string>'')),
|
||||
config_albumsEnabled: Boolean(loadState('memories', 'albums', <string>'')),
|
||||
|
||||
config_placesGis: Number(loadState('memories', 'places_gis', <string>'-1')),
|
||||
|
||||
config_squareThumbs: localStorage.getItem('memories_squareThumbs') === '1',
|
||||
config_fullResOnZoom: localStorage.getItem('memories_fullResOnZoom') !== '0',
|
||||
config_fullResAlways: localStorage.getItem('memories_fullResAlways') === '1',
|
||||
config_showFaceRect: localStorage.getItem('memories_showFaceRect') === '1',
|
||||
config_albumListSort: Number(localStorage.getItem('memories_albumListSort') || 1),
|
||||
|
||||
config_eventName: eventName,
|
||||
config: { ...staticConfig.getDefault() },
|
||||
configEventName: eventName,
|
||||
}),
|
||||
|
||||
created() {
|
||||
subscribe(eventName, this.updateLocalSetting);
|
||||
this.refreshFromConfig();
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
|
@ -45,27 +32,32 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
methods: {
|
||||
updateLocalSetting({ setting, value }) {
|
||||
this['config_' + setting] = value;
|
||||
async refreshFromConfig() {
|
||||
const config = await staticConfig.getAll();
|
||||
const changed = Object.keys(config).filter((key) => config[key] !== this.config[key]);
|
||||
if (changed.length === 0) return;
|
||||
|
||||
changed.forEach((key) => (this.config[key] = config[key]));
|
||||
emit(eventName, { setting: null, value: null });
|
||||
},
|
||||
|
||||
async updateSetting(setting: string) {
|
||||
const value = this['config_' + setting];
|
||||
updateLocalSetting({ setting, value }) {
|
||||
if (setting) {
|
||||
this.config[setting] = value;
|
||||
}
|
||||
},
|
||||
|
||||
if (localSettings.includes(setting)) {
|
||||
if (typeof value === 'boolean') {
|
||||
localStorage.setItem('memories_' + setting, value ? '1' : '0');
|
||||
} else {
|
||||
localStorage.setItem('memories_' + setting, value);
|
||||
}
|
||||
} else {
|
||||
// Long time save setting
|
||||
await axios.put(API.CONFIG(setting), {
|
||||
async updateSetting<K extends keyof IConfig>(setting: K, remote?: string) {
|
||||
const value = this.config[setting];
|
||||
|
||||
if (!localSettings.includes(setting)) {
|
||||
await axios.put(API.CONFIG(remote ?? setting), {
|
||||
value: value.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
// Visible elements update setting
|
||||
staticConfig.setLs(setting, value);
|
||||
|
||||
emit(eventName, { setting, value });
|
||||
},
|
||||
},
|
||||
|
|
|
@ -185,6 +185,10 @@ export class API {
|
|||
return gen(`${BASE}/config/{setting}`, { setting });
|
||||
}
|
||||
|
||||
static CONFIG_GET() {
|
||||
return gen(`${BASE}/config`);
|
||||
}
|
||||
|
||||
static SYSTEM_CONFIG(setting: string | null) {
|
||||
return setting ? gen(`${BASE}/system-config/{setting}`, { setting }) : gen(`${BASE}/system-config`);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
import axios from '@nextcloud/axios';
|
||||
import { API } from './API';
|
||||
import { IConfig } from '../types';
|
||||
|
||||
class StaticConfig {
|
||||
private config: IConfig | null = null;
|
||||
private initPromises: Array<() => void> = [];
|
||||
private default: IConfig | null = null;
|
||||
|
||||
public constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
private async init() {
|
||||
const res = await axios.get<IConfig>(API.CONFIG_GET());
|
||||
this.config = res.data;
|
||||
|
||||
this.getDefault();
|
||||
for (const key in this.config) {
|
||||
this.default![key] = this.config[key];
|
||||
this.setLs(key as keyof IConfig, this.config[key]);
|
||||
}
|
||||
|
||||
this.initPromises.forEach((resolve) => resolve());
|
||||
}
|
||||
|
||||
private async waitForInit() {
|
||||
if (!this.config) {
|
||||
await new Promise<void>((resolve) => {
|
||||
this.initPromises.push(resolve);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async getAll() {
|
||||
await this.waitForInit();
|
||||
return this.config!;
|
||||
}
|
||||
|
||||
public async get<K extends keyof IConfig>(key: K) {
|
||||
await this.waitForInit();
|
||||
return this.config![key];
|
||||
}
|
||||
|
||||
public getSync<K extends keyof IConfig>(key: K) {
|
||||
return this.getDefault()[key];
|
||||
}
|
||||
|
||||
public setLs<K extends keyof IConfig>(key: K, value: IConfig[K]) {
|
||||
if (this.default) {
|
||||
this.default[key] = value;
|
||||
}
|
||||
|
||||
if (this.config) {
|
||||
this.config[key] = value;
|
||||
}
|
||||
|
||||
localStorage.setItem(`memories_${key}`, value.toString());
|
||||
}
|
||||
|
||||
public getDefault(): IConfig {
|
||||
if (this.default) {
|
||||
return this.default;
|
||||
}
|
||||
|
||||
const config: IConfig = {
|
||||
version: '',
|
||||
vod_disable: false,
|
||||
video_default_quality: '0',
|
||||
places_gis: -1,
|
||||
|
||||
systemtags_enabled: false,
|
||||
recognize_enabled: false,
|
||||
albums_enabled: false,
|
||||
facerecognition_installed: false,
|
||||
facerecognition_enabled: false,
|
||||
|
||||
timeline_path: '',
|
||||
folders_path: '',
|
||||
show_hidden_folders: false,
|
||||
sort_folder_month: false,
|
||||
sort_album_month: true,
|
||||
enable_top_memories: true,
|
||||
|
||||
square_thumbs: false,
|
||||
full_res_on_zoom: true,
|
||||
full_res_always: false,
|
||||
show_face_rect: false,
|
||||
album_list_sort: 1,
|
||||
};
|
||||
|
||||
for (const key in config) {
|
||||
const val = localStorage.getItem(`memories_${key}`);
|
||||
if (val !== null) {
|
||||
if (typeof config[key] === 'boolean') {
|
||||
config[key] = val === 'true';
|
||||
} else if (typeof config[key] === 'number') {
|
||||
config[key] = Number(val);
|
||||
} else {
|
||||
config[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.default = config;
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
export default new StaticConfig();
|
|
@ -1,8 +1,6 @@
|
|||
import { loadState } from '@nextcloud/initial-state';
|
||||
import staticConfig from './static-config';
|
||||
import { translate as t } from '@nextcloud/l10n';
|
||||
|
||||
const config_facerecognitionEnabled = Boolean(loadState('memories', 'facerecognitionEnabled', <string>''));
|
||||
|
||||
type RouteNameType = string | null | undefined;
|
||||
|
||||
export function emptyDescription(routeName: RouteNameType): string {
|
||||
|
@ -14,7 +12,7 @@ export function emptyDescription(routeName: RouteNameType): string {
|
|||
case 'thisday':
|
||||
return t('memories', 'Memories from past years will appear here');
|
||||
case 'facerecognition':
|
||||
return config_facerecognitionEnabled
|
||||
return staticConfig.getSync('facerecognition_enabled')
|
||||
? t('memories', 'You will find your friends soon. Please be patient')
|
||||
: t('memories', 'Face Recognition is disabled. Enable in settings to find your friends');
|
||||
case 'videos':
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import { getCurrentUser } from '@nextcloud/auth';
|
||||
import { loadState } from '@nextcloud/initial-state';
|
||||
import staticConfig from '../static-config';
|
||||
|
||||
/** Cache keys */
|
||||
const memoriesVersion: string = loadState('memories', 'version', '');
|
||||
const uid = getCurrentUser()?.uid || 'guest';
|
||||
const cacheName = `memories-${memoriesVersion}-${uid}`;
|
||||
|
||||
async function getCacheName() {
|
||||
const memoriesVersion = await staticConfig.get('version');
|
||||
return `memories-${memoriesVersion}-${uid}`;
|
||||
}
|
||||
|
||||
// Clear all caches except the current one
|
||||
(async function clearCaches() {
|
||||
if (!memoriesVersion || uid === 'guest') return;
|
||||
if (uid === 'guest') return;
|
||||
|
||||
const keys = await window.caches?.keys();
|
||||
if (!keys?.length) return;
|
||||
|
||||
const cacheName = await getCacheName();
|
||||
|
||||
for (const key of keys) {
|
||||
if (key.startsWith('memories-') && key !== cacheName) {
|
||||
window.caches.delete(key);
|
||||
|
@ -23,10 +28,8 @@ const cacheName = `memories-${memoriesVersion}-${uid}`;
|
|||
/** Singleton cache instance */
|
||||
let staticCache: Cache | null = null;
|
||||
export async function openCache() {
|
||||
if (!memoriesVersion) return null;
|
||||
|
||||
try {
|
||||
return (staticCache ??= (await window.caches?.open(cacheName)) ?? null);
|
||||
return (staticCache ??= (await window.caches?.open(await getCacheName())) ?? null);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
|
26
src/types.ts
26
src/types.ts
|
@ -236,3 +236,29 @@ export type ISelectionAction = {
|
|||
/** Allow for public routes (default false) */
|
||||
allowPublic?: boolean;
|
||||
};
|
||||
|
||||
export type IConfig = {
|
||||
version: string;
|
||||
vod_disable: boolean;
|
||||
video_default_quality: string;
|
||||
places_gis: number;
|
||||
|
||||
systemtags_enabled: boolean;
|
||||
recognize_enabled: boolean;
|
||||
albums_enabled: boolean;
|
||||
facerecognition_installed: boolean;
|
||||
facerecognition_enabled: boolean;
|
||||
|
||||
timeline_path: string;
|
||||
folders_path: string;
|
||||
show_hidden_folders: boolean;
|
||||
sort_folder_month: boolean;
|
||||
sort_album_month: boolean;
|
||||
enable_top_memories: boolean;
|
||||
|
||||
square_thumbs: boolean;
|
||||
full_res_on_zoom: boolean;
|
||||
full_res_always: boolean;
|
||||
show_face_rect: boolean;
|
||||
album_list_sort: 1 | 2;
|
||||
};
|
||||
|
|
|
@ -10,29 +10,6 @@ declare module 'vue' {
|
|||
c: typeof constants.c;
|
||||
|
||||
state_noDownload: boolean;
|
||||
|
||||
// UserConfig.ts
|
||||
config_timelinePath: string;
|
||||
config_foldersPath: string;
|
||||
config_showHidden: boolean;
|
||||
config_sortFolderMonth: boolean;
|
||||
config_sortAlbumMonth: boolean;
|
||||
config_tagsEnabled: boolean;
|
||||
config_recognizeEnabled: boolean;
|
||||
config_facerecognitionInstalled: boolean;
|
||||
config_facerecognitionEnabled: boolean;
|
||||
config_albumsEnabled: boolean;
|
||||
config_placesGis: number;
|
||||
config_squareThumbs: boolean;
|
||||
config_enableTopMemories: boolean;
|
||||
config_fullResOnZoom: boolean;
|
||||
config_fullResAlways: boolean;
|
||||
config_showFaceRect: boolean;
|
||||
config_albumListSort: 1 | 2;
|
||||
config_eventName: string;
|
||||
|
||||
updateSetting: (setting: string) => Promise<void>;
|
||||
updateLocalSetting: (opts: { setting: string; value: any }) => void;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue