mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
Compare commits
10 Commits
d40e19ca13
...
b8f12b070a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8f12b070a | ||
|
|
f939ad84f3 | ||
|
|
c3e8c67116 | ||
|
|
d57a8e6d84 | ||
|
|
73ec89e1af | ||
|
|
5cb851f2a8 | ||
|
|
5c18951e31 | ||
|
|
2b744c878e | ||
|
|
4548e75d49 | ||
|
|
841af03393 |
@ -23,7 +23,7 @@ func legacyTrackID(mf model.MediaFile, prependLibId bool) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func legacyAlbumID(mf model.MediaFile, md Metadata, prependLibId bool) string {
|
func legacyAlbumID(mf model.MediaFile, md Metadata, prependLibId bool) string {
|
||||||
releaseDate := legacyReleaseDate(md)
|
_, _, releaseDate := md.mapDates()
|
||||||
albumPath := strings.ToLower(fmt.Sprintf("%s\\%s", legacyMapAlbumArtistName(md), legacyMapAlbumName(md)))
|
albumPath := strings.ToLower(fmt.Sprintf("%s\\%s", legacyMapAlbumArtistName(md), legacyMapAlbumName(md)))
|
||||||
if !conf.Server.Scanner.GroupAlbumReleases {
|
if !conf.Server.Scanner.GroupAlbumReleases {
|
||||||
if len(releaseDate) != 0 {
|
if len(releaseDate) != 0 {
|
||||||
@ -55,9 +55,3 @@ func legacyMapAlbumName(md Metadata) string {
|
|||||||
consts.UnknownAlbum,
|
consts.UnknownAlbum,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the TaggedLikePicard logic for backwards compatibility
|
|
||||||
func legacyReleaseDate(md Metadata) string {
|
|
||||||
_, _, releaseDate := md.mapDates()
|
|
||||||
return string(releaseDate)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
package metadata
|
|
||||||
|
|
||||||
import (
|
|
||||||
. "github.com/onsi/ginkgo/v2"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("legacyReleaseDate", func() {
|
|
||||||
|
|
||||||
DescribeTable("legacyReleaseDate",
|
|
||||||
func(recordingDate, originalDate, releaseDate, expected string) {
|
|
||||||
md := New("", Info{
|
|
||||||
Tags: map[string][]string{
|
|
||||||
"DATE": {recordingDate},
|
|
||||||
"ORIGINALDATE": {originalDate},
|
|
||||||
"RELEASEDATE": {releaseDate},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
result := legacyReleaseDate(md)
|
|
||||||
Expect(result).To(Equal(expected))
|
|
||||||
},
|
|
||||||
Entry("regular mapping", "2020-05-15", "2019-02-10", "2021-01-01", "2021-01-01"),
|
|
||||||
Entry("legacy mapping", "2020-05-15", "2019-02-10", "", "2020-05-15"),
|
|
||||||
Entry("legacy mapping, originalYear < year", "2018-05-15", "2019-02-10", "2021-01-01", "2021-01-01"),
|
|
||||||
Entry("legacy mapping, originalYear empty", "2020-05-15", "", "2021-01-01", "2021-01-01"),
|
|
||||||
Entry("legacy mapping, releaseYear", "2020-05-15", "2019-02-10", "2021-01-01", "2021-01-01"),
|
|
||||||
Entry("legacy mapping, same dates", "2020-05-15", "2020-05-15", "", "2020-05-15"),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
@ -75,6 +75,23 @@ var _ = Describe("ToMediaFile", func() {
|
|||||||
Expect(mf.OriginalYear).To(Equal(1966))
|
Expect(mf.OriginalYear).To(Equal(1966))
|
||||||
Expect(mf.ReleaseYear).To(Equal(2014))
|
Expect(mf.ReleaseYear).To(Equal(2014))
|
||||||
})
|
})
|
||||||
|
DescribeTable("legacyReleaseDate (TaggedLikePicard old behavior)",
|
||||||
|
func(recordingDate, originalDate, releaseDate, expected string) {
|
||||||
|
mf := toMediaFile(model.RawTags{
|
||||||
|
"DATE": {recordingDate},
|
||||||
|
"ORIGINALDATE": {originalDate},
|
||||||
|
"RELEASEDATE": {releaseDate},
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(mf.ReleaseDate).To(Equal(expected))
|
||||||
|
},
|
||||||
|
Entry("regular mapping", "2020-05-15", "2019-02-10", "2021-01-01", "2021-01-01"),
|
||||||
|
Entry("legacy mapping", "2020-05-15", "2019-02-10", "", "2020-05-15"),
|
||||||
|
Entry("legacy mapping, originalYear < year", "2018-05-15", "2019-02-10", "2021-01-01", "2021-01-01"),
|
||||||
|
Entry("legacy mapping, originalYear empty", "2020-05-15", "", "2021-01-01", "2021-01-01"),
|
||||||
|
Entry("legacy mapping, releaseYear", "2020-05-15", "2019-02-10", "2021-01-01", "2021-01-01"),
|
||||||
|
Entry("legacy mapping, same dates", "2020-05-15", "2020-05-15", "", "2020-05-15"),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Lyrics", func() {
|
Describe("Lyrics", func() {
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { createHashHistory } from 'history'
|
import { createHashHistory } from 'history'
|
||||||
import { Admin as RAAdmin, Resource } from 'react-admin'
|
import {
|
||||||
|
Admin as RAAdmin,
|
||||||
|
Resource,
|
||||||
|
useSetLocale,
|
||||||
|
useRefresh,
|
||||||
|
} from 'react-admin'
|
||||||
import { HotKeys } from 'react-hotkeys'
|
import { HotKeys } from 'react-hotkeys'
|
||||||
import dataProvider from './dataProvider'
|
import dataProvider from './dataProvider'
|
||||||
import authProvider from './authProvider'
|
import authProvider from './authProvider'
|
||||||
@ -34,7 +39,7 @@ import {
|
|||||||
shareDialogReducer,
|
shareDialogReducer,
|
||||||
} from './reducers'
|
} from './reducers'
|
||||||
import createAdminStore from './store/createAdminStore'
|
import createAdminStore from './store/createAdminStore'
|
||||||
import { i18nProvider } from './i18n'
|
import { i18nProvider, retrieveTranslation } from './i18n'
|
||||||
import config, { shareInfo } from './config'
|
import config, { shareInfo } from './config'
|
||||||
import { keyMap } from './hotkeys'
|
import { keyMap } from './hotkeys'
|
||||||
import useChangeThemeColor from './useChangeThemeColor'
|
import useChangeThemeColor from './useChangeThemeColor'
|
||||||
@ -42,6 +47,7 @@ import SharePlayer from './share/SharePlayer'
|
|||||||
import { HTML5Backend } from 'react-dnd-html5-backend'
|
import { HTML5Backend } from 'react-dnd-html5-backend'
|
||||||
import { DndProvider } from 'react-dnd'
|
import { DndProvider } from 'react-dnd'
|
||||||
import missing from './missing/index.js'
|
import missing from './missing/index.js'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
const history = createHashHistory()
|
const history = createHashHistory()
|
||||||
|
|
||||||
@ -81,6 +87,24 @@ const App = () => (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const Admin = (props) => {
|
const Admin = (props) => {
|
||||||
|
const setLocale = useSetLocale()
|
||||||
|
const refresh = useRefresh()
|
||||||
|
useEffect(() => {
|
||||||
|
if (config.defaultLanguage !== '' && !localStorage.getItem('locale')) {
|
||||||
|
retrieveTranslation(config.defaultLanguage)
|
||||||
|
.then(() => setLocale(config.defaultLanguage))
|
||||||
|
.then(() => {
|
||||||
|
localStorage.setItem('locale', config.defaultLanguage)
|
||||||
|
refresh(true)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(
|
||||||
|
'Cannot load language "' + config.defaultLanguage + '": ' + e,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [setLocale, refresh])
|
||||||
useChangeThemeColor()
|
useChangeThemeColor()
|
||||||
/* eslint-disable react/jsx-key */
|
/* eslint-disable react/jsx-key */
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useCallback, useEffect } from 'react'
|
import React, { useState, useCallback } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Field, Form } from 'react-final-form'
|
import { Field, Form } from 'react-final-form'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
@ -13,8 +13,6 @@ import {
|
|||||||
createMuiTheme,
|
createMuiTheme,
|
||||||
useLogin,
|
useLogin,
|
||||||
useNotify,
|
useNotify,
|
||||||
useRefresh,
|
|
||||||
useSetLocale,
|
|
||||||
useTranslate,
|
useTranslate,
|
||||||
useVersion,
|
useVersion,
|
||||||
} from 'react-admin'
|
} from 'react-admin'
|
||||||
@ -24,7 +22,6 @@ import Notification from './Notification'
|
|||||||
import useCurrentTheme from '../themes/useCurrentTheme'
|
import useCurrentTheme from '../themes/useCurrentTheme'
|
||||||
import config from '../config'
|
import config from '../config'
|
||||||
import { clearQueue } from '../actions'
|
import { clearQueue } from '../actions'
|
||||||
import { retrieveTranslation } from '../i18n'
|
|
||||||
import { INSIGHTS_DOC_URL } from '../consts.js'
|
import { INSIGHTS_DOC_URL } from '../consts.js'
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
@ -400,27 +397,8 @@ Login.propTypes = {
|
|||||||
// the right theme
|
// the right theme
|
||||||
const LoginWithTheme = (props) => {
|
const LoginWithTheme = (props) => {
|
||||||
const theme = useCurrentTheme()
|
const theme = useCurrentTheme()
|
||||||
const setLocale = useSetLocale()
|
|
||||||
const refresh = useRefresh()
|
|
||||||
const version = useVersion()
|
const version = useVersion()
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (config.defaultLanguage !== '' && !localStorage.getItem('locale')) {
|
|
||||||
retrieveTranslation(config.defaultLanguage)
|
|
||||||
.then(() => {
|
|
||||||
setLocale(config.defaultLanguage).then(() => {
|
|
||||||
localStorage.setItem('locale', config.defaultLanguage)
|
|
||||||
})
|
|
||||||
refresh(true)
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
throw new Error(
|
|
||||||
'Cannot load language "' + config.defaultLanguage + '": ' + e,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [refresh, setLocale])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={createMuiTheme(theme)}>
|
<ThemeProvider theme={createMuiTheme(theme)}>
|
||||||
<Login key={version} {...props} />
|
<Login key={version} {...props} />
|
||||||
|
|||||||
@ -169,7 +169,7 @@ const LibraryEdit = (props) => {
|
|||||||
resource={'library'}
|
resource={'library'}
|
||||||
source={'totalSize'}
|
source={'totalSize'}
|
||||||
label={translate('resources.library.fields.totalSize')}
|
label={translate('resources.library.fields.totalSize')}
|
||||||
format={formatBytes}
|
format={(v) => formatBytes(v, 2)}
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
BooleanField,
|
BooleanField,
|
||||||
} from 'react-admin'
|
} from 'react-admin'
|
||||||
import { useMediaQuery } from '@material-ui/core'
|
import { useMediaQuery } from '@material-ui/core'
|
||||||
import { List, DateField, useResourceRefresh } from '../common'
|
import { List, DateField, useResourceRefresh, SizeField } from '../common'
|
||||||
|
|
||||||
const LibraryFilter = (props) => (
|
const LibraryFilter = (props) => (
|
||||||
<Filter {...props} variant={'outlined'}>
|
<Filter {...props} variant={'outlined'}>
|
||||||
@ -42,6 +42,7 @@ const LibraryList = (props) => {
|
|||||||
<NumberField source="totalSongs" label="Songs" />
|
<NumberField source="totalSongs" label="Songs" />
|
||||||
<NumberField source="totalAlbums" label="Albums" />
|
<NumberField source="totalAlbums" label="Albums" />
|
||||||
<NumberField source="totalMissingFiles" label="Missing Files" />
|
<NumberField source="totalMissingFiles" label="Missing Files" />
|
||||||
|
<SizeField source="totalSize" />
|
||||||
<DateField
|
<DateField
|
||||||
source="lastScanAt"
|
source="lastScanAt"
|
||||||
label="Last Scan"
|
label="Last Scan"
|
||||||
|
|||||||
@ -16,6 +16,11 @@ export default {
|
|||||||
color: 'white',
|
color: 'white',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
MuiButton: {
|
||||||
|
textPrimary: {
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
},
|
||||||
NDLogin: {
|
NDLogin: {
|
||||||
systemNameLink: {
|
systemNameLink: {
|
||||||
color: '#0085ff',
|
color: '#0085ff',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user