feat: Add folder view to view folder media (#2077)
- Closes: #2068 Note: Renames existing `folder` view to `folders` [experimental functionality]
This commit is contained in:
+4
-3
@@ -1,9 +1,9 @@
|
||||
import { FolderActionConfig } from '../../../config/schema/actions/custom/folder';
|
||||
import { FoldersViewActionConfig } from '../../../config/schema/actions/custom/folders-view';
|
||||
import { FolderViewQuery } from '../../../view/query';
|
||||
import { CardActionsAPI } from '../../types';
|
||||
import { AdvancedCameraCardAction } from './base';
|
||||
|
||||
export class FolderAction extends AdvancedCameraCardAction<FolderActionConfig> {
|
||||
export class FoldersViewAction extends AdvancedCameraCardAction<FoldersViewActionConfig> {
|
||||
public async execute(api: CardActionsAPI): Promise<void> {
|
||||
await super.execute(api);
|
||||
|
||||
@@ -19,7 +19,8 @@ export class FolderAction extends AdvancedCameraCardAction<FolderActionConfig> {
|
||||
|
||||
await api.getViewManager().setViewByParametersWithExistingQuery({
|
||||
params: {
|
||||
view: 'folder',
|
||||
// Supports both 'folder' and 'folders' views.
|
||||
view: this._action.advanced_camera_card_action,
|
||||
query: new FolderViewQuery(query),
|
||||
},
|
||||
});
|
||||
@@ -10,7 +10,7 @@ import { DefaultAction } from './actions/default';
|
||||
import { DisplayModeSelectAction } from './actions/display-mode-select';
|
||||
import { DownloadAction } from './actions/download';
|
||||
import { ExpandAction } from './actions/expand';
|
||||
import { FolderAction } from './actions/folder';
|
||||
import { FoldersViewAction } from './actions/folders-view';
|
||||
import { FullscreenAction } from './actions/fullscreen';
|
||||
import { InternalCallbackAction } from './actions/internal-callback';
|
||||
import { LogAction } from './actions/log';
|
||||
@@ -152,7 +152,8 @@ export class ActionFactory {
|
||||
case INTERNAL_CALLBACK_ACTION:
|
||||
return new InternalCallbackAction(context, action, options?.config);
|
||||
case 'folder':
|
||||
return new FolderAction(context, action, options?.config);
|
||||
case 'folders':
|
||||
return new FoldersViewAction(context, action, options?.config);
|
||||
}
|
||||
|
||||
/* istanbul ignore next: this path cannot be reached -- @preserve */
|
||||
|
||||
@@ -120,6 +120,7 @@ export class ViewQueryExecutor {
|
||||
viewModifiers.push(...(await executeMediaQuery(mediaType)));
|
||||
break;
|
||||
case 'folder':
|
||||
case 'folders':
|
||||
viewModifiers.push(...(await executeFolderQuery()));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { MediaLoadedInfo } from '../types';
|
||||
import {
|
||||
createCameraAction,
|
||||
createDisplayModeAction,
|
||||
createFolderAction,
|
||||
createFoldersViewAction,
|
||||
createGeneralAction,
|
||||
createMediaPlayerAction,
|
||||
createPTZControlsAction,
|
||||
@@ -658,7 +658,8 @@ export class MenuButtonController {
|
||||
type: 'custom:advanced-camera-card-menu-icon',
|
||||
title: folder.title ?? localize('config.menu.buttons.folders'),
|
||||
style: isSelected ? this._getEmphasizedStyle() : {},
|
||||
tap_action: createFolderAction(),
|
||||
tap_action: createFoldersViewAction('folders'),
|
||||
hold_action: createFoldersViewAction('folder'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -667,14 +668,14 @@ export class MenuButtonController {
|
||||
QueryClassifier.isFolderQuery(view?.query) &&
|
||||
view.query.getQuery()?.folder.id === id;
|
||||
|
||||
const action = createFolderAction({ folderID: id });
|
||||
return {
|
||||
enabled: true,
|
||||
title: folder.title ?? folder.id,
|
||||
icon: folder.icon ?? 'mdi:folder',
|
||||
selected: isSelected,
|
||||
style: isSelected ? this._getEmphasizedStyle() : {},
|
||||
...(action && { tap_action: action }),
|
||||
tap_action: createFoldersViewAction('folders', { folderID: id }),
|
||||
hold_action: createFoldersViewAction('folder', { folderID: id }),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -684,7 +685,7 @@ export class MenuButtonController {
|
||||
type: 'custom:advanced-camera-card-menu-submenu',
|
||||
title: localize('config.menu.buttons.folders'),
|
||||
items: submenuItems,
|
||||
style: view?.is('folder') ? this._getEmphasizedStyle() : {},
|
||||
style: view?.isAnyFolderView() ? this._getEmphasizedStyle() : {},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export class AdvancedCameraCardViews extends LitElement {
|
||||
if (view?.is('live') || this._shouldLivePreload()) {
|
||||
import('./live/index.js');
|
||||
}
|
||||
if (view?.isMediaGalleryView() && !view.is('folder')) {
|
||||
if (view?.isMediaGalleryView() && !view.is('folders')) {
|
||||
import('./gallery/media-gallery.js');
|
||||
} else if (view?.isViewerView()) {
|
||||
import('./viewer/index.js');
|
||||
@@ -76,7 +76,7 @@ export class AdvancedCameraCardViews extends LitElement {
|
||||
import('./image.js');
|
||||
} else if (view?.is('timeline')) {
|
||||
import('./timeline.js');
|
||||
} else if (view?.is('folder')) {
|
||||
} else if (view?.is('folders')) {
|
||||
import('./gallery/folder-gallery.js');
|
||||
}
|
||||
}
|
||||
@@ -157,7 +157,7 @@ export class AdvancedCameraCardViews extends LitElement {
|
||||
>
|
||||
</advanced-camera-card-image>`
|
||||
: ``}
|
||||
${!this.hide && view?.isMediaGalleryView() && !view.is('folder')
|
||||
${!this.hide && view?.isMediaGalleryView() && !view.is('folders')
|
||||
? html` <advanced-camera-card-media-gallery
|
||||
.hass=${this.hass}
|
||||
.viewManagerEpoch=${this.viewManagerEpoch}
|
||||
@@ -200,7 +200,7 @@ export class AdvancedCameraCardViews extends LitElement {
|
||||
>
|
||||
</advanced-camera-card-diagnostics>`
|
||||
: ``}
|
||||
${!this.hide && view?.is('folder')
|
||||
${!this.hide && view?.is('folders')
|
||||
? html` <advanced-camera-card-folder-gallery
|
||||
.hass=${this.hass}
|
||||
.viewManagerEpoch=${this.viewManagerEpoch}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { z } from 'zod';
|
||||
import { advancedCameraCardCustomActionsBaseSchema } from './base';
|
||||
|
||||
export const folderActionConfigSchema = advancedCameraCardCustomActionsBaseSchema.extend(
|
||||
{
|
||||
advanced_camera_card_action: z.literal('folder'),
|
||||
folder: z.string().optional(),
|
||||
},
|
||||
);
|
||||
export type FolderActionConfig = z.infer<typeof folderActionConfigSchema>;
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
import { advancedCameraCardCustomActionsBaseSchema } from './base';
|
||||
|
||||
export const foldersViewActionConfigSchema =
|
||||
advancedCameraCardCustomActionsBaseSchema.extend({
|
||||
advanced_camera_card_action: z.literal('folders').or(z.literal('folder')),
|
||||
folder: z.string().optional(),
|
||||
});
|
||||
export type FoldersViewActionConfig = z.infer<typeof foldersViewActionConfigSchema>;
|
||||
@@ -7,14 +7,14 @@ import { advancedCameraCardCustomActionsBaseSchema } from './base';
|
||||
|
||||
type AdvancedCameraCardUserSpecifiedViewWithoutFolder = Exclude<
|
||||
AdvancedCameraCardUserSpecifiedView,
|
||||
'folder'
|
||||
'folder' | 'folders'
|
||||
>;
|
||||
|
||||
export const viewActionConfigSchema = advancedCameraCardCustomActionsBaseSchema.extend({
|
||||
advanced_camera_card_action: z.enum(
|
||||
// The folder view is handled by the `folder` action since it accepts an
|
||||
// The folder/folders views are handled separately as they accept an
|
||||
// optional folder ID.
|
||||
VIEWS_USER_SPECIFIED.filter((view) => view !== 'folder') as [
|
||||
VIEWS_USER_SPECIFIED.filter((view) => view !== 'folder' && view !== 'folders') as [
|
||||
AdvancedCameraCardUserSpecifiedViewWithoutFolder,
|
||||
...AdvancedCameraCardUserSpecifiedViewWithoutFolder[],
|
||||
],
|
||||
|
||||
@@ -3,7 +3,7 @@ import { statusBarItemBaseSchema } from '../common/status-bar';
|
||||
import { advancedCameraCardCustomActionsBaseSchema } from './custom/base';
|
||||
import { cameraSelectActionConfigSchema } from './custom/camera-select';
|
||||
import { viewDisplayModeActionConfigSchema } from './custom/display-mode';
|
||||
import { folderActionConfigSchema } from './custom/folder';
|
||||
import { foldersViewActionConfigSchema } from './custom/folders-view';
|
||||
import { generalActionConfigSchema } from './custom/general';
|
||||
import { internalCallbackActionConfigSchema } from './custom/internal';
|
||||
import { logActionConfigSchema } from './custom/log';
|
||||
@@ -42,7 +42,7 @@ export const statusBarActionConfigSchema: z.ZodSchema<
|
||||
|
||||
const advancedCameraCardCustomActionSchema = z.union([
|
||||
cameraSelectActionConfigSchema,
|
||||
folderActionConfigSchema,
|
||||
foldersViewActionConfigSchema,
|
||||
generalActionConfigSchema,
|
||||
internalCallbackActionConfigSchema,
|
||||
logActionConfigSchema,
|
||||
|
||||
@@ -17,6 +17,7 @@ export const VIEWS_USER_SPECIFIED = [
|
||||
'clip',
|
||||
'clips',
|
||||
'folder',
|
||||
'folders',
|
||||
'snapshot',
|
||||
'snapshots',
|
||||
'recording',
|
||||
|
||||
@@ -414,6 +414,7 @@ export class AdvancedCameraCardEditor extends LitElement implements LovelaceCard
|
||||
{ value: 'clip', label: localize('config.view.views.clip') },
|
||||
{ value: 'clips', label: localize('config.view.views.clips') },
|
||||
{ value: 'folder', label: localize('config.view.views.folder') },
|
||||
{ value: 'folders', label: localize('config.view.views.folders') },
|
||||
{ value: 'image', label: localize('config.view.views.image') },
|
||||
{ value: 'live', label: localize('config.view.views.live') },
|
||||
{ value: 'recording', label: localize('config.view.views.recording') },
|
||||
|
||||
@@ -589,6 +589,7 @@
|
||||
"clips": "Galeria de clips",
|
||||
"current": "Vista actual",
|
||||
"folder": "",
|
||||
"folders": "",
|
||||
"image": "Imatge estàtica",
|
||||
"live": "Visualització en directe",
|
||||
"recording": "Enregistrament més recent",
|
||||
|
||||
@@ -588,7 +588,8 @@
|
||||
"clip": "Most recent clip",
|
||||
"clips": "Clips gallery",
|
||||
"current": "Current view",
|
||||
"folder": "Folder view",
|
||||
"folder": "Folder media",
|
||||
"folders": "Folders gallery",
|
||||
"image": "Static image",
|
||||
"live": "Live view",
|
||||
"recording": "Most recent recording",
|
||||
|
||||
@@ -589,6 +589,7 @@
|
||||
"clips": "Galerie de clips",
|
||||
"current": "Vue actuelle",
|
||||
"folder": "",
|
||||
"folders": "",
|
||||
"image": "Image statique",
|
||||
"live": "Vue en direct",
|
||||
"recording": "Enregistrement le plus récent",
|
||||
|
||||
@@ -589,6 +589,7 @@
|
||||
"clips": "Galleria delle clip",
|
||||
"current": "Vista corrente",
|
||||
"folder": "",
|
||||
"folders": "",
|
||||
"image": "Immagine statica",
|
||||
"live": "Dal vivo",
|
||||
"recording": "",
|
||||
|
||||
@@ -589,6 +589,7 @@
|
||||
"clips": "Galeria de clipes",
|
||||
"current": "Visualização atual",
|
||||
"folder": "",
|
||||
"folders": "",
|
||||
"image": "Imagem estática",
|
||||
"live": "Visualização ao vivo",
|
||||
"recording": "Gravação mais recente",
|
||||
|
||||
@@ -589,6 +589,7 @@
|
||||
"clips": "Galeria de clipes",
|
||||
"current": "Visualização atual",
|
||||
"folder": "",
|
||||
"folders": "",
|
||||
"image": "Imagem estática",
|
||||
"live": "Visualização ao vivo",
|
||||
"recording": "",
|
||||
|
||||
+10
-7
@@ -2,7 +2,7 @@ import { CardActionsAPI } from '../card-controller/types.js';
|
||||
import { ZoomSettingsBase } from '../components-lib/zoom/types.js';
|
||||
import { CameraSelectActionConfig } from '../config/schema/actions/custom/camera-select.js';
|
||||
import { DisplayModeActionConfig } from '../config/schema/actions/custom/display-mode.js';
|
||||
import { FolderActionConfig } from '../config/schema/actions/custom/folder.js';
|
||||
import { FoldersViewActionConfig } from '../config/schema/actions/custom/folders-view.js';
|
||||
import {
|
||||
AdvancedCameraCardGeneralAction,
|
||||
GeneralActionConfig,
|
||||
@@ -47,7 +47,7 @@ export function createGeneralAction(
|
||||
}
|
||||
|
||||
export function createViewAction(
|
||||
action: Exclude<AdvancedCameraCardUserSpecifiedView, 'folder'>,
|
||||
action: Exclude<AdvancedCameraCardUserSpecifiedView, 'folder' | 'folders'>,
|
||||
options?: {
|
||||
cardID?: string;
|
||||
},
|
||||
@@ -74,13 +74,16 @@ export function createCameraAction(
|
||||
};
|
||||
}
|
||||
|
||||
export function createFolderAction(options?: {
|
||||
cardID?: string;
|
||||
folderID?: string;
|
||||
}): FolderActionConfig {
|
||||
export function createFoldersViewAction(
|
||||
view: 'folder' | 'folders',
|
||||
options?: {
|
||||
cardID?: string;
|
||||
folderID?: string;
|
||||
},
|
||||
): FoldersViewActionConfig {
|
||||
return {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
advanced_camera_card_action: view,
|
||||
...(options?.folderID && { folder: options.folderID }),
|
||||
...(options?.cardID && { card_id: options.cardID }),
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ export const getCameraIDsForViewName = (
|
||||
case 'diagnostics':
|
||||
case 'image':
|
||||
case 'folder':
|
||||
case 'folders':
|
||||
case 'media':
|
||||
return cameraManager.getStore().getCameraIDs();
|
||||
|
||||
|
||||
+6
-2
@@ -126,7 +126,7 @@ export class View {
|
||||
* Determine if a view is a media gallery.
|
||||
*/
|
||||
public isMediaGalleryView(): boolean {
|
||||
return ['clips', 'folder', 'snapshots', 'recordings'].includes(this.view);
|
||||
return ['clips', 'folders', 'snapshots', 'recordings'].includes(this.view);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,11 +137,15 @@ export class View {
|
||||
return this.isViewerView() || this.is('live') || this.is('image');
|
||||
}
|
||||
|
||||
public isAnyFolderView(): boolean {
|
||||
return ['folder', 'folders'].includes(this.view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a view is for the media viewer.
|
||||
*/
|
||||
public isViewerView(): boolean {
|
||||
return ['media', 'clip', 'snapshot', 'recording'].includes(this.view);
|
||||
return ['folder', 'media', 'clip', 'snapshot', 'recording'].includes(this.view);
|
||||
}
|
||||
|
||||
public supportsMultipleDisplayModes(): boolean {
|
||||
|
||||
Reference in New Issue
Block a user