Browse Source

add experimental dynamic background

master
jeffvli 3 years ago
parent
commit
b0c101604f
  1. 1
      src/__tests__/App.test.tsx
  2. 40
      src/components/layout/GenericPage.tsx
  3. 25
      src/components/layout/styled.tsx
  4. 26
      src/components/settings/ConfigPanels/LookAndFeelConfig.tsx
  5. 4
      src/components/shared/setDefaultSettings.ts
  6. 7
      src/redux/miscSlice.ts
  7. 84
      src/shared/settings.json
  8. 9
      src/shared/utils.ts

1
src/__tests__/App.test.tsx

@ -76,6 +76,7 @@ const miscState: General = {
}, },
modalPages: [], modalPages: [],
isProcessingPlaylist: [], isProcessingPlaylist: [],
dynamicBackground: false,
}; };
const mockInitialState = { const mockInitialState = {

40
src/components/layout/GenericPage.tsx

@ -1,10 +1,46 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import path from 'path';
import { Divider } from 'rsuite'; import { Divider } from 'rsuite';
import { useAppSelector } from '../../redux/hooks';
import { PageContainer, PageHeader, PageContent } from './styled'; import { PageContainer, PageHeader, PageContent } from './styled';
import { isCached, getImageCachePath } from '../../shared/utils';
const GenericPage = ({ header, children, hideDivider, ...rest }: any) => { const GenericPage = ({ header, children, hideDivider, ...rest }: any) => {
const playQueue = useAppSelector((state) => state.playQueue);
const misc = useAppSelector((state) => state.misc);
const [cachePath] = useState(path.join(getImageCachePath(), '/'));
const [backgroundImage, setBackgroundImage] = useState('');
useEffect(() => {
if (misc.dynamicBackground) {
const cachedImagePath = `${cachePath}album_${playQueue.current?.albumId}.jpg`;
const serverImagePath = playQueue.current?.image.replace(
/size=\d+/,
'size=500'
);
const cssBackgroundImagePath = `${cachePath}album_${playQueue.current?.albumId}.jpg`.replaceAll(
'\\',
'/'
);
if (!isCached(cachedImagePath)) {
const preloadImage = new Image();
preloadImage.src = serverImagePath;
}
const imagePath = isCached(cachedImagePath)
? cssBackgroundImagePath
: serverImagePath;
setBackgroundImage(imagePath);
}
}, [cachePath, misc.dynamicBackground, playQueue]);
return ( return (
<PageContainer id="page-container"> <PageContainer
id="page-container"
$backgroundSrc={misc.dynamicBackground ? backgroundImage : undefined}
>
<PageHeader <PageHeader
id="page-header" id="page-header"
padding={rest.padding} padding={rest.padding}

25
src/components/layout/styled.tsx

@ -40,6 +40,7 @@ export const RootFooter = styled(Footer)`
// Titlebar.tsx // Titlebar.tsx
// Subtract 2px from width if you add window border // Subtract 2px from width if you add window border
export const TitleHeader = styled.header<{ font: string }>` export const TitleHeader = styled.header<{ font: string }>`
z-index: 1;
display: block; display: block;
position: fixed; position: fixed;
height: 32px; height: 32px;
@ -98,13 +99,35 @@ export const WindowControlButton = styled.div<{
`; `;
// GenericPage.tsx // GenericPage.tsx
export const PageContainer = styled(Container)` export const PageContainer = styled(Container)<{ $backgroundSrc?: string }>`
height: 100%; height: 100%;
overflow-x: hidden; overflow-x: hidden;
&:before {
content: '';
position: fixed;
left: 0;
right: 0;
display: block;
background-image: ${(props) =>
props.$backgroundSrc ? `url(${props.$backgroundSrc})` : undefined};
transition: background-image 1s ease-in-out;
width: 100%;
height: 92%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
opacity: 0.3;
filter: blur(50px) brightness(0.8);
}
`; `;
export const PageHeader = styled(Header)<{ padding?: string }>` export const PageHeader = styled(Header)<{ padding?: string }>`
padding: ${(props) => (props.padding ? props.padding : '10px 20px 0px 20px')}; padding: ${(props) => (props.padding ? props.padding : '10px 20px 0px 20px')};
z-index: 1;
`; `;
export const PageContent = styled(Content)<{ padding?: string }>` export const PageContent = styled(Content)<{ padding?: string }>`

26
src/components/settings/ConfigPanels/LookAndFeelConfig.tsx

@ -7,11 +7,16 @@ import {
StyledInputPicker, StyledInputPicker,
StyledNavItem, StyledNavItem,
StyledInputNumber, StyledInputNumber,
StyledCheckbox,
} from '../../shared/styled'; } from '../../shared/styled';
import ListViewConfig from './ListViewConfig'; import ListViewConfig from './ListViewConfig';
import { Fonts } from '../Fonts'; import { Fonts } from '../Fonts';
import { useAppDispatch } from '../../../redux/hooks'; import { useAppDispatch } from '../../../redux/hooks';
import { setTheme, setFont } from '../../../redux/miscSlice'; import {
setTheme,
setFont,
setDynamicBackground,
} from '../../../redux/miscSlice';
import { import {
songColumnPicker, songColumnPicker,
songColumnList, songColumnList,
@ -53,7 +58,26 @@ const LookAndFeelConfig = () => {
<StyledRadio value="defaultLight">Default Light</StyledRadio> <StyledRadio value="defaultLight">Default Light</StyledRadio>
</RadioGroup> </RadioGroup>
<br /> <br />
<StyledCheckbox
defaultChecked={settings.getSync('dynamicBackground')}
onChange={() => {
settings.setSync(
'dynamicBackground',
!settings.getSync('dynamicBackground')
);
dispatch(
setDynamicBackground(
Boolean(settings.getSync('dynamicBackground'))
)
);
}}
>
Enable dynamic background
</StyledCheckbox>
<br />
<ControlLabel>Font</ControlLabel> <ControlLabel>Font</ControlLabel>
<br /> <br />
<StyledInputPicker <StyledInputPicker
data={Fonts} data={Fonts}

4
src/components/shared/setDefaultSettings.ts

@ -12,6 +12,10 @@ const setDefaultSettings = (force: boolean) => {
settings.setSync('font', 'Poppins'); settings.setSync('font', 'Poppins');
} }
if (force || !settings.hasSync('dynamicBackground')) {
settings.setSync('dynamicBackground', false);
}
if (force || !settings.hasSync('showDebugWindow')) { if (force || !settings.hasSync('showDebugWindow')) {
settings.setSync('showDebugWindow', false); settings.setSync('showDebugWindow', false);
} }

7
src/redux/miscSlice.ts

@ -28,6 +28,7 @@ export interface General {
expandSidebar: boolean; expandSidebar: boolean;
isProcessingPlaylist: string[]; isProcessingPlaylist: string[];
contextMenu: ContextMenu; contextMenu: ContextMenu;
dynamicBackground: boolean;
} }
const initialState: General = { const initialState: General = {
@ -43,12 +44,17 @@ const initialState: General = {
contextMenu: { contextMenu: {
show: false, show: false,
}, },
dynamicBackground: parsedSettings.dynamicBackground,
}; };
const miscSlice = createSlice({ const miscSlice = createSlice({
name: 'misc', name: 'misc',
initialState, initialState,
reducers: { reducers: {
setDynamicBackground: (state, action: PayloadAction<boolean>) => {
state.dynamicBackground = action.payload;
},
setExpandSidebar: (state, action: PayloadAction<boolean>) => { setExpandSidebar: (state, action: PayloadAction<boolean>) => {
state.expandSidebar = action.payload; state.expandSidebar = action.payload;
}, },
@ -139,5 +145,6 @@ export const {
removeProcessingPlaylist, removeProcessingPlaylist,
setContextMenu, setContextMenu,
setExpandSidebar, setExpandSidebar,
setDynamicBackground,
} = miscSlice.actions; } = miscSlice.actions;
export default miscSlice.reducer; export default miscSlice.reducer;

84
src/shared/settings.json

@ -1,30 +1,40 @@
{ {
"theme": "defaultDark",
"showDebugWindow": false,
"globalMediaHotkeys": true,
"cachePath": "C:\\Users\\jli\\AppData\\Roaming\\Electron", "cachePath": "C:\\Users\\jli\\AppData\\Roaming\\Electron",
"volume": 0.93,
"seekForwardInterval": 5,
"seekBackwardInterval": 5,
"volumeFade": true,
"repeat": "all", "repeat": "all",
"shuffle": false, "shuffle": false,
"scrollWithCurrentSong": true, "scrollWithCurrentSong": true,
"cacheImages": true, "cacheImages": true,
"cacheSongs": false, "cacheSongs": false,
"fadeDuration": "9.0", "pollingInterval": 20,
"playlistViewType": "list", "fadeDuration": 9,
"albumViewType": "list", "fadeType": "equalPower",
"songListFontSize": "14", "gridCardSize": 200,
"songListRowHeight": "60.0", "playlistViewType": "grid",
"songListColumns": [ "albumViewType": "grid",
"musicListFontSize": "13",
"musicListRowHeight": "50",
"musicListColumns": [
{ {
"id": "#", "id": "#",
"dataKey": "index", "dataKey": "index",
"alignment": "center", "alignment": "center",
"resizable": true, "resizable": true,
"width": 50, "width": 50,
"label": "#" "label": "# (Drag/Drop)"
}, },
{ {
"id": "Title", "id": "Title",
"dataKey": "combinedtitle", "dataKey": "combinedtitle",
"alignment": "left", "alignment": "left",
"resizable": true, "resizable": true,
"width": 450, "width": 273,
"label": "Title (Combined)" "label": "Title (Combined)"
}, },
{ {
@ -32,7 +42,7 @@
"dataKey": "album", "dataKey": "album",
"alignment": "left", "alignment": "left",
"resizable": true, "resizable": true,
"width": 450, "width": 263,
"label": "Album" "label": "Album"
}, },
{ {
@ -40,20 +50,28 @@
"dataKey": "duration", "dataKey": "duration",
"alignment": "center", "alignment": "center",
"resizable": true, "resizable": true,
"width": 100, "width": 110,
"label": "Duration" "label": "Duration"
}, },
{
"id": "Bitrate",
"dataKey": "bitRate",
"alignment": "left",
"resizable": true,
"width": 72,
"label": "Bitrate"
},
{ {
"id": "Fav", "id": "Fav",
"dataKey": "starred", "dataKey": "starred",
"alignment": "center", "alignment": "center",
"resizable": true, "resizable": true,
"width": 60, "width": 100,
"label": "Favorite" "label": "Favorite"
} }
], ],
"albumListFontSize": "14", "albumListFontSize": "14",
"albumListRowHeight": "60.0", "albumListRowHeight": "60",
"albumListColumns": [ "albumListColumns": [
{ {
"id": "#", "id": "#",
@ -68,7 +86,7 @@
"dataKey": "combinedtitle", "dataKey": "combinedtitle",
"alignment": "left", "alignment": "left",
"resizable": true, "resizable": true,
"width": 450, "width": 457,
"label": "Title (Combined)" "label": "Title (Combined)"
}, },
{ {
@ -84,7 +102,7 @@
"dataKey": "duration", "dataKey": "duration",
"alignment": "center", "alignment": "center",
"resizable": true, "resizable": true,
"width": 100, "width": 80,
"label": "Duration" "label": "Duration"
}, },
{ {
@ -92,12 +110,12 @@
"dataKey": "starred", "dataKey": "starred",
"alignment": "center", "alignment": "center",
"resizable": true, "resizable": true,
"width": 60, "width": 100,
"label": "Favorite" "label": "Favorite"
} }
], ],
"playlistListFontSize": "14", "playlistListFontSize": "14",
"playlistListRowHeight": "55.0", "playlistListRowHeight": "80",
"playlistListColumns": [ "playlistListColumns": [
{ {
"id": "#", "id": "#",
@ -156,6 +174,36 @@
"label": "Modified" "label": "Modified"
} }
], ],
"defaultRepeat": "all", "miniListFontSize": "14",
"defaultShuffle": true "miniListColumns": [
{
"id": "#",
"dataKey": "index",
"alignment": "center",
"resizable": true,
"width": 50,
"label": "# (Drag/Drop)"
},
{
"id": "Title",
"dataKey": "title",
"alignment": "left",
"resizable": true,
"width": 250,
"label": "Title"
},
{
"id": "Duration",
"dataKey": "duration",
"alignment": "center",
"resizable": true,
"width": 80,
"label": "Duration"
}
],
"font": "Poppins",
"server": "http://192.168.14.11:4040",
"serverBase64": "aHR0cDovLzE5Mi4xNjguMTQuMTE6NDA0MA==",
"miniListRowHeight": "30",
"dynamicBackground": false
} }

9
src/shared/utils.ts

@ -1,6 +1,5 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import settings from 'electron-settings';
import moment from 'moment'; import moment from 'moment';
let settingsPath = path.join( let settingsPath = path.join(
@ -28,6 +27,9 @@ export const getSettings = () => {
theme: parsedSettings.theme, theme: parsedSettings.theme,
font: parsedSettings.font, font: parsedSettings.font,
scrollWithCurrentSong: parsedSettings.scrollWithCurrentSong, scrollWithCurrentSong: parsedSettings.scrollWithCurrentSong,
dynamicBackground: parsedSettings.dynamicBackground,
cachePath: parsedSettings.cachePath,
serverBase64: parsedSettings.serverBase64,
}; };
}; };
@ -36,10 +38,11 @@ export const isCached = (filePath: string) => {
}; };
export const getRootCachePath = () => { export const getRootCachePath = () => {
const parsedSettings = getSettings();
return path.join( return path.join(
String(settings.getSync('cachePath')), parsedSettings.cachePath,
'sonixdCache', 'sonixdCache',
`${settings.getSync('serverBase64')}` parsedSettings.serverBase64
); );
}; };

Loading…
Cancel
Save