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:
@@ -105,7 +105,17 @@ describe('ActionsManager', () => {
|
||||
{
|
||||
tap_action: {
|
||||
action: 'navigate',
|
||||
// Folder also uses the media gallery.
|
||||
// Folders also uses the media viewer.
|
||||
navigation_path: '4',
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
'folders' as const,
|
||||
{
|
||||
tap_action: {
|
||||
action: 'navigate',
|
||||
// Folders also uses the media gallery.
|
||||
navigation_path: '3',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { FolderAction } from '../../../../src/card-controller/actions/actions/folder';
|
||||
import { FoldersViewAction } from '../../../../src/card-controller/actions/actions/folders-view';
|
||||
import { FolderQuery } from '../../../../src/card-controller/folders/types';
|
||||
import { FolderViewQuery } from '../../../../src/view/query';
|
||||
import { createCardAPI, createFolder } from '../../../test-utils';
|
||||
@@ -7,7 +7,7 @@ import { createCardAPI, createFolder } from '../../../test-utils';
|
||||
describe('should handle folder action', async () => {
|
||||
it('should handle folder action successfully', async () => {
|
||||
const api = createCardAPI();
|
||||
const action = new FolderAction(
|
||||
const action = new FoldersViewAction(
|
||||
{},
|
||||
{
|
||||
action: 'fire-dom-event',
|
||||
@@ -20,7 +20,7 @@ describe('should handle folder action', async () => {
|
||||
|
||||
const query: FolderQuery = {
|
||||
folder,
|
||||
path: ['path'],
|
||||
path: [{ ha: { id: 'path' } }],
|
||||
};
|
||||
vi.mocked(api.getFoldersManager().generateDefaultFolderQuery).mockReturnValue(query);
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('should handle folder action', async () => {
|
||||
|
||||
it('should do nothing with non-existent folder', async () => {
|
||||
const api = createCardAPI();
|
||||
const action = new FolderAction(
|
||||
const action = new FoldersViewAction(
|
||||
{},
|
||||
{
|
||||
action: 'fire-dom-event',
|
||||
@@ -64,7 +64,7 @@ describe('should handle folder action', async () => {
|
||||
|
||||
it('should do nothing with non-existent default query', async () => {
|
||||
const api = createCardAPI();
|
||||
const action = new FolderAction(
|
||||
const action = new FoldersViewAction(
|
||||
{},
|
||||
{
|
||||
action: 'fire-dom-event',
|
||||
|
||||
@@ -7,7 +7,7 @@ import { DefaultAction } from '../../../src/card-controller/actions/actions/defa
|
||||
import { DisplayModeSelectAction } from '../../../src/card-controller/actions/actions/display-mode-select';
|
||||
import { DownloadAction } from '../../../src/card-controller/actions/actions/download';
|
||||
import { ExpandAction } from '../../../src/card-controller/actions/actions/expand';
|
||||
import { FolderAction } from '../../../src/card-controller/actions/actions/folder';
|
||||
import { FoldersViewAction } from '../../../src/card-controller/actions/actions/folders-view';
|
||||
import { FullscreenAction } from '../../../src/card-controller/actions/actions/fullscreen';
|
||||
import { InternalCallbackAction } from '../../../src/card-controller/actions/actions/internal-callback';
|
||||
import { LogAction } from '../../../src/card-controller/actions/actions/log';
|
||||
@@ -185,7 +185,8 @@ describe('ActionFactory', () => {
|
||||
},
|
||||
InternalCallbackAction,
|
||||
],
|
||||
[{ advanced_camera_card_action: 'folder' as const }, FolderAction],
|
||||
[{ advanced_camera_card_action: 'folder' as const }, FoldersViewAction],
|
||||
[{ advanced_camera_card_action: 'folders' as const }, FoldersViewAction],
|
||||
])(
|
||||
'advanced_camera_card_action: $advanced_camera_card_action',
|
||||
(action: Partial<ActionConfig>, classObject: object) => {
|
||||
|
||||
@@ -1792,7 +1792,8 @@ describe('MenuButtonController', () => {
|
||||
style: {},
|
||||
type: 'custom:advanced-camera-card-menu-icon',
|
||||
title: 'Folders',
|
||||
tap_action: { action: 'fire-dom-event', advanced_camera_card_action: 'folder' },
|
||||
tap_action: { action: 'fire-dom-event', advanced_camera_card_action: 'folders' },
|
||||
hold_action: { action: 'fire-dom-event', advanced_camera_card_action: 'folder' },
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1807,7 +1808,7 @@ describe('MenuButtonController', () => {
|
||||
foldersManager,
|
||||
view: createView({
|
||||
view: 'folder',
|
||||
query: new FolderViewQuery({ folder, path: [{ id: 'one' }] }),
|
||||
query: new FolderViewQuery({ folder, path: [{ ha: { id: 'one' } }] }),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1820,7 +1821,8 @@ describe('MenuButtonController', () => {
|
||||
},
|
||||
type: 'custom:advanced-camera-card-menu-icon',
|
||||
title: 'Folders',
|
||||
tap_action: { action: 'fire-dom-event', advanced_camera_card_action: 'folder' },
|
||||
tap_action: { action: 'fire-dom-event', advanced_camera_card_action: 'folders' },
|
||||
hold_action: { action: 'fire-dom-event', advanced_camera_card_action: 'folder' },
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1837,7 +1839,7 @@ describe('MenuButtonController', () => {
|
||||
view: 'folder',
|
||||
query: new FolderViewQuery({
|
||||
folder: selectedFolder,
|
||||
path: [{ id: 'id' }],
|
||||
path: [{ ha: { id: 'id' } }],
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1858,18 +1860,28 @@ describe('MenuButtonController', () => {
|
||||
items: [
|
||||
{
|
||||
enabled: true,
|
||||
hold_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
folder: 'folder-0',
|
||||
},
|
||||
icon: 'mdi:folder',
|
||||
selected: false,
|
||||
style: {},
|
||||
tap_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
advanced_camera_card_action: 'folders',
|
||||
folder: 'folder-0',
|
||||
},
|
||||
title: 'folder-0',
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
hold_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
folder: 'folder-selected',
|
||||
},
|
||||
icon: 'mdi:folder',
|
||||
selected: true,
|
||||
style: {
|
||||
@@ -1877,7 +1889,7 @@ describe('MenuButtonController', () => {
|
||||
},
|
||||
tap_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
advanced_camera_card_action: 'folders',
|
||||
folder: 'folder-selected',
|
||||
},
|
||||
title: 'folder-selected',
|
||||
@@ -1909,23 +1921,33 @@ describe('MenuButtonController', () => {
|
||||
{
|
||||
enabled: true,
|
||||
icon: 'mdi:folder',
|
||||
hold_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
folder: 'folder-0',
|
||||
},
|
||||
selected: false,
|
||||
style: {},
|
||||
tap_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
advanced_camera_card_action: 'folders',
|
||||
folder: 'folder-0',
|
||||
},
|
||||
title: 'folder-0',
|
||||
},
|
||||
{
|
||||
enabled: true,
|
||||
hold_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
folder: 'folder-1',
|
||||
},
|
||||
icon: 'mdi:folder',
|
||||
selected: false,
|
||||
style: {},
|
||||
tap_action: {
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
advanced_camera_card_action: 'folders',
|
||||
folder: 'folder-1',
|
||||
},
|
||||
title: 'folder-1',
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ActionConfig } from '../../src/config/schema/actions/types.js';
|
||||
import {
|
||||
createCameraAction,
|
||||
createDisplayModeAction,
|
||||
createFolderAction,
|
||||
createFoldersViewAction,
|
||||
createGeneralAction,
|
||||
createInternalCallbackAction,
|
||||
createLogAction,
|
||||
@@ -64,14 +64,19 @@ describe('createCameraAction', () => {
|
||||
});
|
||||
|
||||
describe('createFolderAction', () => {
|
||||
it('should create folder action', () => {
|
||||
expect(createFolderAction({ folderID: 'folderID', cardID: 'card_id' })).toEqual({
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: 'folder',
|
||||
card_id: 'card_id',
|
||||
folder: 'folderID',
|
||||
});
|
||||
});
|
||||
it.each([['folder' as const], ['folders' as const]])(
|
||||
'%s',
|
||||
(viewName: 'folder' | 'folders') => {
|
||||
expect(
|
||||
createFoldersViewAction(viewName, { folderID: 'folderID', cardID: 'card_id' }),
|
||||
).toEqual({
|
||||
action: 'fire-dom-event',
|
||||
advanced_camera_card_action: viewName,
|
||||
card_id: 'card_id',
|
||||
folder: 'folderID',
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('createMediaPlayerAction', () => {
|
||||
|
||||
@@ -11,31 +11,34 @@ import {
|
||||
|
||||
describe('getCameraIDsForViewName', () => {
|
||||
describe('views that are always supported', () => {
|
||||
it.each([['diagnostics' as const], ['image' as const], ['media' as const]])(
|
||||
'%s',
|
||||
(viewName: AdvancedCameraCardView) => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera-1',
|
||||
config: createCameraConfig({ dependencies: { cameras: ['camera-2'] } }),
|
||||
},
|
||||
{ cameraID: 'camera-2' },
|
||||
]),
|
||||
);
|
||||
it.each([
|
||||
['diagnostics' as const],
|
||||
['folder' as const],
|
||||
['folders' as const],
|
||||
['image' as const],
|
||||
['media' as const],
|
||||
])('%s', (viewName: AdvancedCameraCardView) => {
|
||||
const cameraManager = createCameraManager();
|
||||
vi.mocked(cameraManager.getStore).mockReturnValue(
|
||||
createStore([
|
||||
{
|
||||
cameraID: 'camera-1',
|
||||
config: createCameraConfig({ dependencies: { cameras: ['camera-2'] } }),
|
||||
},
|
||||
{ cameraID: 'camera-2' },
|
||||
]),
|
||||
);
|
||||
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName)).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-1')).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-2')).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
},
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName)).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-1')).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
expect(getCameraIDsForViewName(cameraManager, viewName, 'camera-2')).toEqual(
|
||||
new Set(['camera-1', 'camera-2']),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('views that respect dependencies and need a capability', () => {
|
||||
|
||||
+66
-41
@@ -153,56 +153,81 @@ describe('View Basics', () => {
|
||||
expect(view.context).toEqual({});
|
||||
});
|
||||
|
||||
it('should detect gallery views', () => {
|
||||
expect(createView({ view: 'clips' }).isMediaGalleryView()).toBeTruthy();
|
||||
expect(createView({ view: 'folder' }).isMediaGalleryView()).toBeTruthy();
|
||||
expect(createView({ view: 'snapshots' }).isMediaGalleryView()).toBeTruthy();
|
||||
expect(createView({ view: 'recordings' }).isMediaGalleryView()).toBeTruthy();
|
||||
describe('should detect folder views', () => {
|
||||
it('should detect folder views', () => {
|
||||
expect(createView({ view: 'folder' }).isAnyFolderView()).toBeTruthy();
|
||||
expect(createView({ view: 'folders' }).isAnyFolderView()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not detect folder views', () => {
|
||||
expect(createView({ view: 'live' }).isAnyFolderView()).toBeFalsy();
|
||||
expect(createView({ view: 'clip' }).isAnyFolderView()).toBeFalsy();
|
||||
expect(createView({ view: 'clips' }).isAnyFolderView()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not detect gallery view', () => {
|
||||
expect(createView({ view: 'live' }).isMediaGalleryView()).toBeFalsy();
|
||||
expect(createView({ view: 'timeline' }).isMediaGalleryView()).toBeFalsy();
|
||||
describe('should detect media views', () => {
|
||||
it('should detect any media views', () => {
|
||||
expect(createView({ view: 'clip' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'snapshot' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'media' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'recording' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'live' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'image' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'folder' }).isAnyMediaView()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not detect any media view', () => {
|
||||
expect(createView({ view: 'timeline' }).isAnyMediaView()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should detect any media views', () => {
|
||||
expect(createView({ view: 'clip' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'snapshot' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'media' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'recording' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'live' }).isAnyMediaView()).toBeTruthy();
|
||||
expect(createView({ view: 'image' }).isAnyMediaView()).toBeTruthy();
|
||||
describe('should detect gallery views', () => {
|
||||
it('should detect gallery views', () => {
|
||||
expect(createView({ view: 'clips' }).isMediaGalleryView()).toBeTruthy();
|
||||
expect(createView({ view: 'folders' }).isMediaGalleryView()).toBeTruthy();
|
||||
expect(createView({ view: 'snapshots' }).isMediaGalleryView()).toBeTruthy();
|
||||
expect(createView({ view: 'recordings' }).isMediaGalleryView()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not detect gallery view', () => {
|
||||
expect(createView({ view: 'live' }).isMediaGalleryView()).toBeFalsy();
|
||||
expect(createView({ view: 'timeline' }).isMediaGalleryView()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not detect any media view', () => {
|
||||
expect(createView({ view: 'timeline' }).isAnyMediaView()).toBeFalsy();
|
||||
describe('should detect viewer views', () => {
|
||||
it('should detect viewer views', () => {
|
||||
expect(createView({ view: 'clip' }).isViewerView()).toBeTruthy();
|
||||
expect(createView({ view: 'snapshot' }).isViewerView()).toBeTruthy();
|
||||
expect(createView({ view: 'media' }).isViewerView()).toBeTruthy();
|
||||
expect(createView({ view: 'recording' }).isViewerView()).toBeTruthy();
|
||||
expect(createView({ view: 'folder' }).isAnyMediaView()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not detect viewer views', () => {
|
||||
expect(createView({ view: 'live' }).isViewerView()).toBeFalsy();
|
||||
expect(createView({ view: 'live' }).isViewerView()).toBeFalsy();
|
||||
expect(createView({ view: 'timeline' }).isViewerView()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should detect viewer views', () => {
|
||||
expect(createView({ view: 'clip' }).isViewerView()).toBeTruthy();
|
||||
expect(createView({ view: 'snapshot' }).isViewerView()).toBeTruthy();
|
||||
expect(createView({ view: 'media' }).isViewerView()).toBeTruthy();
|
||||
expect(createView({ view: 'recording' }).isViewerView()).toBeTruthy();
|
||||
});
|
||||
describe('should get default media type', () => {
|
||||
it('should get default media type', () => {
|
||||
expect(createView({ view: 'clip' }).getDefaultMediaType()).toBe('clips');
|
||||
expect(createView({ view: 'clips' }).getDefaultMediaType()).toBe('clips');
|
||||
expect(createView({ view: 'snapshot' }).getDefaultMediaType()).toBe('snapshots');
|
||||
expect(createView({ view: 'snapshots' }).getDefaultMediaType()).toBe('snapshots');
|
||||
expect(createView({ view: 'recording' }).getDefaultMediaType()).toBe('recordings');
|
||||
expect(createView({ view: 'recordings' }).getDefaultMediaType()).toBe(
|
||||
'recordings',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not detect viewer views', () => {
|
||||
expect(createView({ view: 'live' }).isViewerView()).toBeFalsy();
|
||||
expect(createView({ view: 'live' }).isViewerView()).toBeFalsy();
|
||||
expect(createView({ view: 'timeline' }).isViewerView()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should get default media type', () => {
|
||||
expect(createView({ view: 'clip' }).getDefaultMediaType()).toBe('clips');
|
||||
expect(createView({ view: 'clips' }).getDefaultMediaType()).toBe('clips');
|
||||
expect(createView({ view: 'snapshot' }).getDefaultMediaType()).toBe('snapshots');
|
||||
expect(createView({ view: 'snapshots' }).getDefaultMediaType()).toBe('snapshots');
|
||||
expect(createView({ view: 'recording' }).getDefaultMediaType()).toBe('recordings');
|
||||
expect(createView({ view: 'recordings' }).getDefaultMediaType()).toBe('recordings');
|
||||
});
|
||||
|
||||
it('should not get default media type', () => {
|
||||
expect(createView({ view: 'live' }).getDefaultMediaType()).toBeNull();
|
||||
expect(createView({ view: 'timeline' }).getDefaultMediaType()).toBeNull();
|
||||
it('should not get default media type', () => {
|
||||
expect(createView({ view: 'live' }).getDefaultMediaType()).toBeNull();
|
||||
expect(createView({ view: 'timeline' }).getDefaultMediaType()).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('should determine if display mode is grid', () => {
|
||||
|
||||
Reference in New Issue
Block a user