Browse Source

add font configuration

master
jeffvli 3 years ago
parent
commit
cda704150b
  1. 9
      src/App.tsx
  2. 12
      src/components/layout/GenericPageHeader.tsx
  3. 7
      src/components/layout/Layout.tsx
  4. 8
      src/components/layout/Sidebar.tsx
  5. 4
      src/components/layout/Titlebar.tsx
  6. 23
      src/components/layout/styled.tsx
  7. 4
      src/components/player/NowPlayingView.tsx
  8. 144
      src/components/settings/Config.tsx
  9. 261
      src/components/settings/Fonts.ts
  10. 4
      src/components/settings/styled.tsx
  11. 4
      src/components/shared/setDefaultSettings.ts
  12. 8
      src/components/shared/styled.ts
  13. 8
      src/redux/miscSlice.ts
  14. 1
      src/shared/utils.ts
  15. 7
      src/styles/App.global.css
  16. 4
      src/styles/custom-theme.less
  17. 10
      src/styles/styledTheme.ts

9
src/App.tsx

@ -28,6 +28,7 @@ const keyMap = {
const App = () => {
const [theme, setTheme] = useState<any>(defaultDark);
const [font, setFont] = useState('Poppins');
const misc = useAppSelector((state) => state.misc);
useEffect(() => {
switch (misc.theme) {
@ -43,6 +44,10 @@ const App = () => {
}
}, [misc.theme]);
useEffect(() => {
setFont(misc.font);
}, [misc.font]);
const focusSearchInput = useCallback(() => {
document.getElementById('local-search-input')?.focus();
}, []);
@ -53,7 +58,7 @@ const App = () => {
) {
return (
<ThemeProvider theme={theme}>
<Layout disableSidebar footer={<MockFooter />}>
<Layout disableSidebar footer={<MockFooter />} font={font}>
<Login />
</Layout>
</ThemeProvider>
@ -71,7 +76,7 @@ const App = () => {
<ThemeProvider theme={theme}>
<GlobalHotKeys keyMap={keyMap} handlers={handlers}>
<Router>
<Layout footer={<PlayerBar />}>
<Layout footer={<PlayerBar />} font={font}>
<Switch>
<Route exact path="/library/album" component={AlbumList} />
<Route exact path="/library/artist" component={ArtistList} />

12
src/components/layout/GenericPageHeader.tsx

@ -2,7 +2,7 @@ import React from 'react';
import { Icon, Input, InputGroup } from 'rsuite';
import ViewTypeButtons from '../viewtypes/ViewTypeButtons';
import { StyledInputGroup } from '../shared/styled';
import { CoverArtWrapper } from './styled';
import { CoverArtWrapper, PageHeaderTitle } from './styled';
const GenericPageHeader = ({
image,
@ -53,15 +53,7 @@ const GenericPageHeader = ({
overflow: 'hidden',
}}
>
<h1
style={{
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
}}
>
{title}
</h1>
<PageHeaderTitle>{title}</PageHeaderTitle>
</span>
<span
style={{

7
src/components/layout/Layout.tsx

@ -5,7 +5,7 @@ import Sidebar from './Sidebar';
import Titlebar from './Titlebar';
import { RootContainer, RootFooter, MainContainer } from './styled';
const Layout = ({ footer, children, disableSidebar }: any) => {
const Layout = ({ footer, children, disableSidebar, font }: any) => {
const [expandSidebar, setExpandSidebar] = useState(false);
const history = useHistory();
@ -54,14 +54,15 @@ const Layout = ({ footer, children, disableSidebar }: any) => {
return (
<>
<Titlebar />
<Titlebar font={font} />
<Sidebar
expand={expandSidebar}
handleToggle={handleToggle}
handleSidebarSelect={handleSidebarSelect}
disableSidebar={disableSidebar}
font={font}
/>
<RootContainer id="container-root">
<RootContainer id="container-root" font={font}>
<MainContainer id="container-main" expanded={expandSidebar}>
<Content id="container-content">{children}</Content>
</MainContainer>

8
src/components/layout/Sidebar.tsx

@ -7,9 +7,15 @@ const Sidebar = ({
handleToggle,
handleSidebarSelect,
disableSidebar,
font,
}: any) => {
return (
<FixedSidebar id="sidebar" width={expand ? 193 : 56} collapsible>
<FixedSidebar
id="sidebar"
width={expand ? 193 : 56}
collapsible
font={font}
>
<Sidenav
style={{
height: '100%',

4
src/components/layout/Titlebar.tsx

@ -6,7 +6,7 @@ import {
WindowControlButton,
} from './styled';
const Titlebar = () => {
const Titlebar = ({ font }: any) => {
const [title, setTitle] = useState(document.title);
useEffect(() => {
@ -18,7 +18,7 @@ const Titlebar = () => {
});
return (
<TitleHeader id="titlebar">
<TitleHeader id="titlebar" font={font}>
<DragRegion id="drag-region">
<div id="window-title-wrapper">
<span id="window-title">{title}</span>

23
src/components/layout/styled.tsx

@ -3,10 +3,14 @@ import styled from 'styled-components';
import { Container, Content, Footer, Header, Sidebar } from 'rsuite';
// Layout.tsx
export const RootContainer = styled(Container)`
export const RootContainer = styled(Container)<{ font: string }>`
background: ${(props) => props.theme.primary.background};
height: 100vh;
color: ${(props) => props.theme.primary.text};
font-size: ${(props) => props.theme.all.fonts.pageFontSize};
font-family: ${(props) => `${props.font?.split(/Light|Medium/)[0]}`};
font-weight: ${(props) =>
props.font?.match('Light') ? 300 : props.font?.match('Medium') ? 500 : 400};
`;
interface ContainerProps {
@ -35,7 +39,7 @@ export const RootFooter = styled(Footer)`
// Titlebar.tsx
// Subtract 2px from width if you add window border
export const TitleHeader = styled.header`
export const TitleHeader = styled.header<{ font: string }>`
display: block;
position: fixed;
height: 32px;
@ -44,6 +48,9 @@ export const TitleHeader = styled.header`
background: ${(props) => props.theme.primary.titleBar};
padding: 4px;
color: ${(props) => props.theme.primary.titleText};
font-family: ${(props) => `${props.font?.split(/Light|Medium/)[0]}`};
font-weight: ${(props) =>
props.font?.match('Light') ? 300 : props.font?.match('Medium') ? 500 : 400};
`;
export const DragRegion = styled.div`
@ -106,12 +113,15 @@ export const PageContent = styled(Content)`
// Sidebar.tsx
// Add 1 to top if you add window border
export const FixedSidebar = styled(Sidebar)`
export const FixedSidebar = styled(Sidebar)<{ font: string }>`
background: ${(props) => props.theme.primary.sideBar} !important;
position: fixed;
top: 32px;
z-index: 1;
height: calc(100% - 130px);
font-family: ${(props) => `${props.font?.split(/Light|Medium/)[0]}`};
font-weight: ${(props) =>
props.font?.match('Light') ? 300 : props.font?.match('Medium') ? 500 : 400};
`;
export const CoverArtWrapper = styled.div`
@ -119,3 +129,10 @@ export const CoverArtWrapper = styled.div`
filter: ${(props) =>
`drop-shadow(0px 5px 8px ${props.theme.primary.coverArtShadow})`};
`;
export const PageHeaderTitle = styled.h1`
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-size: ${(props) => props.theme.all.fonts.pageTitleFontSize};
`;

4
src/components/player/NowPlayingView.tsx

@ -124,7 +124,7 @@ const NowPlayingView = () => {
<>
<ButtonToolbar>
<ShuffleButton
size="md"
size="lg"
onClick={() => {
if (playQueue.shuffle) {
dispatch(shuffleInPlace());
@ -134,7 +134,7 @@ const NowPlayingView = () => {
}}
/>
<ClearQueueButton
size="md"
size="lg"
onClick={() => {
dispatch(clearPlayQueue());
dispatch(setStatus('PAUSED'));

144
src/components/settings/Config.tsx

@ -35,6 +35,7 @@ import {
StyledCheckbox,
StyledInput,
StyledInputNumber,
StyledInputPicker,
StyledNavItem,
StyledRadio,
} from '../shared/styled';
@ -43,7 +44,8 @@ import {
setPlaybackSetting,
setPlayerVolume,
} from '../../redux/playQueueSlice';
import { setTheme } from '../../redux/miscSlice';
import { Fonts } from './Fonts';
import { setFont, setTheme } from '../../redux/miscSlice';
const fsUtils = require('nodejs-fs-utils');
@ -304,71 +306,89 @@ const Config = () => {
</div>
</ConfigPanel>
<ConfigPanel header="Look & Feel" bordered>
<p>Select the main application theme.</p>
<RadioGroup
name="themeRadioList"
appearance="default"
defaultValue={String(settings.getSync('theme'))}
onChange={(e) => {
settings.setSync('theme', e);
dispatch(setTheme(e));
}}
>
<StyledRadio value="defaultDark">Default Dark</StyledRadio>
<StyledRadio value="defaultLight">Default Light</StyledRadio>
</RadioGroup>
<br />
<p>Select the columns you want displayed on pages with a list-view.</p>
<Nav
style={{ paddingTop: '10px' }}
activeKey={currentLAFTab}
onSelect={(e) => setCurrentLAFTab(e)}
>
<StyledNavItem eventKey="songList">Song List</StyledNavItem>
<StyledNavItem eventKey="albumList">Album List</StyledNavItem>
<StyledNavItem eventKey="playlistList">Playlist List</StyledNavItem>
</Nav>
{currentLAFTab === 'songList' && (
<ListViewConfig
title="Song List"
defaultColumns={currentSongColumns}
columnPicker={songColumnPicker}
columnList={songColumnList}
settingsConfig={{
columnList: 'songListColumns',
rowHeight: 'songListRowHeight',
fontSize: 'songListFontSize',
<div style={{ width: '300px' }}>
<p>Select the main application theme.</p>
<RadioGroup
name="themeRadioList"
appearance="default"
defaultValue={String(settings.getSync('theme'))}
onChange={(e) => {
settings.setSync('theme', e);
dispatch(setTheme(e));
}}
/>
)}
{currentLAFTab === 'albumList' && (
<ListViewConfig
title="Album List"
defaultColumns={currentAlbumColumns}
columnPicker={albumColumnPicker}
columnList={albumColumnList}
settingsConfig={{
columnList: 'albumListColumns',
rowHeight: 'albumListRowHeight',
fontSize: 'albumListFontSize',
>
<StyledRadio value="defaultDark">Default Dark</StyledRadio>
<StyledRadio value="defaultLight">Default Light</StyledRadio>
</RadioGroup>
<br />
<ControlLabel>Font</ControlLabel>
<br />
<StyledInputPicker
data={Fonts}
groupBy="role"
defaultValue={String(settings.getSync('font'))}
onChange={(e: string) => {
settings.setSync('font', e);
dispatch(setFont(e));
}}
/>
)}
</div>
<br />
<ConfigPanel bordered>
<p>
Select the columns you want displayed on pages with a list-view.
</p>
<Nav
style={{ paddingTop: '10px' }}
activeKey={currentLAFTab}
onSelect={(e) => setCurrentLAFTab(e)}
>
<StyledNavItem eventKey="songList">Song List</StyledNavItem>
<StyledNavItem eventKey="albumList">Album List</StyledNavItem>
<StyledNavItem eventKey="playlistList">Playlist List</StyledNavItem>
</Nav>
{currentLAFTab === 'songList' && (
<ListViewConfig
title="Song List"
defaultColumns={currentSongColumns}
columnPicker={songColumnPicker}
columnList={songColumnList}
settingsConfig={{
columnList: 'songListColumns',
rowHeight: 'songListRowHeight',
fontSize: 'songListFontSize',
}}
/>
)}
{currentLAFTab === 'playlistList' && (
<ListViewConfig
title="Playlist List"
defaultColumns={currentPlaylistColumns}
columnPicker={playlistColumnPicker}
columnList={playlistColumnList}
settingsConfig={{
columnList: 'playlistListColumns',
rowHeight: 'playlistListRowHeight',
fontSize: 'playlistListFontSize',
}}
/>
)}
{currentLAFTab === 'albumList' && (
<ListViewConfig
title="Album List"
defaultColumns={currentAlbumColumns}
columnPicker={albumColumnPicker}
columnList={albumColumnList}
settingsConfig={{
columnList: 'albumListColumns',
rowHeight: 'albumListRowHeight',
fontSize: 'albumListFontSize',
}}
/>
)}
{currentLAFTab === 'playlistList' && (
<ListViewConfig
title="Playlist List"
defaultColumns={currentPlaylistColumns}
columnPicker={playlistColumnPicker}
columnList={playlistColumnList}
settingsConfig={{
columnList: 'playlistListColumns',
rowHeight: 'playlistListRowHeight',
fontSize: 'playlistListFontSize',
}}
/>
)}
</ConfigPanel>
</ConfigPanel>
<ConfigPanel header="Player" bordered>
<p>

261
src/components/settings/Fonts.ts

@ -0,0 +1,261 @@
export const Fonts = [
{
label: 'Archivo',
value: 'Archivo',
role: 'Regular',
},
{
label: 'Cormorant',
value: 'Cormorant',
role: 'Regular',
},
{
label: 'Encode Sans',
value: 'Encode Sans',
role: 'Regular',
},
{
label: 'Epilogue',
value: 'Epilogue',
role: 'Regular',
},
{
label: 'Hahmlet',
value: 'Hahmlet',
role: 'Regular',
},
{
label: 'Inter',
value: 'Inter',
role: 'Regular',
},
{
label: 'JetBrains Mono',
value: 'JetBrains Mono',
role: 'Regular',
},
{
label: 'Manrope',
value: 'Manrope',
role: 'Regular',
},
{
label: 'Monsterrat',
value: 'Monsterrat',
role: 'Regular',
},
{
label: 'Oswald',
value: 'Oswald',
role: 'Regular',
},
{
label: 'Oxygen',
value: 'Oxygen',
role: 'Regular',
},
{
label: 'Poppins',
value: 'Poppins',
role: 'Regular',
},
{
label: 'Raleway',
value: 'Raleway',
role: 'Regular',
},
{
label: 'Roboto',
value: 'Roboto',
role: 'Regular',
},
{
label: 'Sora',
value: 'Sora',
role: 'Regular',
},
{
label: 'Spectral',
value: 'Spectral',
role: 'Regular',
},
{
label: 'Work Sans',
value: 'Work Sans',
role: 'Regular',
},
// LIGHT
{
label: 'Archivo (Light)',
value: 'ArchivoLight',
role: 'Light',
},
{
label: 'Cormorant (Light)',
value: 'CormorantLight',
role: 'Light',
},
{
label: 'Encode Sans (Light)',
value: 'Encode SansLight',
role: 'Light',
},
{
label: 'Epilogue (Light)',
value: 'EpilogueLight',
role: 'Light',
},
{
label: 'Hahmlet (Light)',
value: 'HahmletLight',
role: 'Light',
},
{
label: 'Inter (Light)',
value: 'InterLight',
role: 'Light',
},
{
label: 'JetBrains Mono (Light)',
value: 'JetBrains MonoLight',
role: 'Light',
},
{
label: 'Manrope (Light)',
value: 'ManropeLight',
role: 'Light',
},
{
label: 'Monsterrat (Light)',
value: 'MonsterratLight',
role: 'Light',
},
{
label: 'Oswald (Light)',
value: 'OswaldLight',
role: 'Light',
},
{
label: 'Oxygen (Light)',
value: 'OxygenLight',
role: 'Light',
},
{
label: 'Poppins (Light)',
value: 'PoppinsLight',
role: 'Light',
},
{
label: 'Raleway (Light)',
value: 'RalewayLight',
role: 'Light',
},
{
label: 'Roboto (Light)',
value: 'RobotoLight',
role: 'Light',
},
{
label: 'Sora (Light)',
value: 'SoraLight',
role: 'Light',
},
{
label: 'Spectral (Light)',
value: 'SpectralLight',
role: 'Light',
},
{
label: 'Work Sans (Light)',
value: 'Work SansLight',
role: 'Light',
},
// MEDIUM
{
label: 'Archivo (Medium)',
value: 'ArchivoMedium',
role: 'Medium',
},
{
label: 'Cormorant (Medium)',
value: 'CormorantMedium',
role: 'Medium',
},
{
label: 'Encode Sans (Medium)',
value: 'Encode SansMedium',
role: 'Medium',
},
{
label: 'Epilogue (Medium)',
value: 'EpilogueMedium',
role: 'Medium',
},
{
label: 'Hahmlet (Medium)',
value: 'HahmletMedium',
role: 'Medium',
},
{
label: 'Inter (Medium)',
value: 'InterMedium',
role: 'Medium',
},
{
label: 'JetBrains Mono (Medium)',
value: 'JetBrains MonoMedium',
role: 'Medium',
},
{
label: 'Manrope (Medium)',
value: 'ManropeMedium',
role: 'Medium',
},
{
label: 'Monsterrat (Medium)',
value: 'MonsterratMedium',
role: 'Medium',
},
{
label: 'Oswald (Medium)',
value: 'OswaldMedium',
role: 'Medium',
},
{
label: 'Oxygen (Medium)',
value: 'OxygenMedium',
role: 'Medium',
},
{
label: 'Poppins (Medium)',
value: 'PoppinsMedium',
role: 'Medium',
},
{
label: 'Raleway (Medium)',
value: 'RalewayMedium',
role: 'Medium',
},
{
label: 'Roboto (Medium)',
value: 'RobotoMedium',
role: 'Medium',
},
{
label: 'Sora (Medium)',
value: 'SoraMedium',
role: 'Medium',
},
{
label: 'Spectral (Medium)',
value: 'SpectralMedium',
role: 'Medium',
},
{
label: 'Work Sans (Medium)',
value: 'Work SansMedium',
role: 'Medium',
},
];

4
src/components/settings/styled.tsx

@ -7,6 +7,10 @@ export const ConfigPanel = styled(Panel)`
min-width: 500px;
max-width: 800px;
margin: 15px auto 15px auto;
.rs-panel-heading {
font-size: ${(props) => props.theme.all.fonts.panelHeaderFontSize};
}
`;
export const MockFooter = styled.div`

4
src/components/shared/setDefaultSettings.ts

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

8
src/components/shared/styled.ts

@ -10,6 +10,7 @@ import {
Icon,
Rate,
Slider,
InputPicker,
} from 'rsuite';
import styled from 'styled-components';
@ -95,6 +96,7 @@ export const StyledIconButton = styled(IconButton)`
background-color: ${(props) =>
props.appearance === 'primary' ? props.theme.primary.main : undefined};
}
width: ${(props) => `${props.width}px`};
`;
export const StyledNavItem = styled(Nav.Item)`
@ -127,3 +129,9 @@ export const StyledSlider = styled(Slider)`
}
}
`;
export const StyledInputPicker = styled(InputPicker)`
.rs-picker-toggle-value {
color: ${(props) => `${props.theme.primary.main} !important`};
}
`;

8
src/redux/miscSlice.ts

@ -4,10 +4,12 @@ import { getSettings } from '../shared/utils';
const parsedSettings = getSettings();
interface General {
theme: string;
font: string;
}
const initialState: General = {
theme: parsedSettings.theme,
font: parsedSettings.font,
};
const miscSlice = createSlice({
@ -17,8 +19,12 @@ const miscSlice = createSlice({
setTheme: (state, action: PayloadAction<string>) => {
state.theme = action.payload;
},
setFont: (state, action: PayloadAction<string>) => {
state.font = action.payload;
},
},
});
export const { setTheme } = miscSlice.actions;
export const { setTheme, setFont } = miscSlice.actions;
export default miscSlice.reducer;

1
src/shared/utils.ts

@ -26,6 +26,7 @@ export const getSettings = () => {
volumeFade: parsedSettings.volumeFade,
showDebugWindow: parsedSettings.showDebugWindow,
theme: parsedSettings.theme,
font: parsedSettings.font,
};
};

7
src/styles/App.global.css

@ -5,8 +5,7 @@
@import '~rsuite/lib/styles/themes/dark/index.less';
@import 'custom-theme.less';
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@300;400;500&family=Cormorant:wght@300;400;500&family=Encode+Sans:wght@300;400;500&family=Epilogue:wght@300;400;500&family=Hahmlet:wght@300;400;500&family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@300;400;500&family=Manrope:wght@300;400;500&family=Montserrat:wght@300;400;500&family=Oswald:wght@300;400;500&family=Poppins:wght@300;400;500&family=Raleway:wght@300;400;500&family=Roboto:wght@300;400;500&family=Sora:wght@300;400;500&family=Spectral&family=Work+Sans:wght@300;400;500&display=swap');
html,
body {
height: 100%;
@ -20,10 +19,6 @@ body {
min-height: 100%;
}
h1 {
font-size: 30px !important;
}
.rhap_container {
position: fixed;
bottom: 0;

4
src/styles/custom-theme.less

@ -33,10 +33,6 @@
@sidenav-collapse-transition-config: 0s;
// Panel
@panel-heading-font-size: 20px;
@panel-heading-color: undefined;
// @font-family-base: 'Poppins', sans-serif;
// @font-size-base: 14px;
@button-ripple: false;

10
src/styles/styledTheme.ts

@ -1,5 +1,11 @@
export const defaultDark = {
all: {},
all: {
fonts: {
pageTitleFontSize: '30px',
pageFontSize: '14px',
panelHeaderFontSize: '20px',
},
},
primary: {
main: '#2196F3',
background: '#181a1f',
@ -7,7 +13,7 @@ export const defaultDark = {
titleText: '#FFFFFF',
playerBar: '#101010',
sideBar: '#101010',
text: '#e9ebf0',
text: '#D8D8D8',
rowSelected: '#4D5156',
playerBarText: '#e9ebf0',
playerBarButtons: '#b3b3b3',

Loading…
Cancel
Save