mirror of
https://github.com/navidrome/navidrome.git
synced 2026-04-03 06:41:01 +00:00
Compare commits
7 Commits
af648bc2cf
...
fc9c23268f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc9c23268f | ||
|
|
c40f12e65b | ||
|
|
12d0898585 | ||
|
|
c21aee7360 | ||
|
|
ee51bd9281 | ||
|
|
2451e9e7ae | ||
|
|
f6b2ab5726 |
@ -137,7 +137,6 @@ ENV ND_MUSICFOLDER=/music
|
||||
ENV ND_DATAFOLDER=/data
|
||||
ENV ND_CONFIGFILE=/data/navidrome.toml
|
||||
ENV ND_PORT=4533
|
||||
ENV GODEBUG="asyncpreemptoff=1"
|
||||
RUN touch /.nddockerenv
|
||||
|
||||
EXPOSE ${ND_PORT}
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/gob"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/navidrome/navidrome/core"
|
||||
"github.com/navidrome/navidrome/db"
|
||||
@ -19,13 +18,13 @@ import (
|
||||
var (
|
||||
fullScan bool
|
||||
subprocess bool
|
||||
targets string
|
||||
targets []string
|
||||
)
|
||||
|
||||
func init() {
|
||||
scanCmd.Flags().BoolVarP(&fullScan, "full", "f", false, "check all subfolders, ignoring timestamps")
|
||||
scanCmd.Flags().BoolVarP(&subprocess, "subprocess", "", false, "run as subprocess (internal use)")
|
||||
scanCmd.Flags().StringVarP(&targets, "targets", "t", "", "comma-separated list of libraryID:folderPath pairs (e.g., \"1:Music/Rock,1:Music/Jazz,2:Classical\")")
|
||||
scanCmd.Flags().StringArrayVarP(&targets, "target", "t", []string{}, "list of libraryID:folderPath pairs, can be repeated (e.g., \"-t 1:Music/Rock -t 1:Music/Jazz -t 2:Classical\")")
|
||||
rootCmd.AddCommand(scanCmd)
|
||||
}
|
||||
|
||||
@ -74,9 +73,9 @@ func runScanner(ctx context.Context) {
|
||||
|
||||
// Parse targets if provided
|
||||
var scanTargets []model.ScanTarget
|
||||
if targets != "" {
|
||||
if len(targets) > 0 {
|
||||
var err error
|
||||
scanTargets, err = model.ParseTargets(strings.Split(targets, ","))
|
||||
scanTargets, err = model.ParseTargets(targets)
|
||||
if err != nil {
|
||||
log.Fatal(ctx, "Failed to parse targets", err)
|
||||
}
|
||||
|
||||
@ -617,7 +617,12 @@ func init() {
|
||||
|
||||
func InitConfig(cfgFile string) {
|
||||
codecRegistry := viper.NewCodecRegistry()
|
||||
_ = codecRegistry.RegisterCodec("ini", ini.Codec{})
|
||||
_ = codecRegistry.RegisterCodec("ini", ini.Codec{
|
||||
LoadOptions: ini.LoadOptions{
|
||||
UnescapeValueDoubleQuotes: true,
|
||||
UnescapeValueCommentSymbols: true,
|
||||
},
|
||||
})
|
||||
viper.SetOptions(viper.WithCodecRegistry(codecRegistry))
|
||||
|
||||
cfgFile = getConfigFile(cfgFile)
|
||||
|
||||
@ -39,6 +39,7 @@ var _ = Describe("Configuration", func() {
|
||||
Expect(conf.Server.MusicFolder).To(Equal(fmt.Sprintf("/%s/music", format)))
|
||||
Expect(conf.Server.UIWelcomeMessage).To(Equal("Welcome " + format))
|
||||
Expect(conf.Server.Tags["custom"].Aliases).To(Equal([]string{format, "test"}))
|
||||
Expect(conf.Server.Tags["artist"].Split).To(Equal([]string{";"}))
|
||||
|
||||
// The config file used should be the one we created
|
||||
Expect(conf.Server.ConfigFile).To(Equal(filename))
|
||||
|
||||
5
conf/testdata/cfg.ini
vendored
5
conf/testdata/cfg.ini
vendored
@ -1,6 +1,7 @@
|
||||
[default]
|
||||
MusicFolder = /ini/music
|
||||
UIWelcomeMessage = Welcome ini
|
||||
UIWelcomeMessage = 'Welcome ini' ; Just a comment to test the LoadOptions
|
||||
|
||||
[Tags]
|
||||
Custom.Aliases = ini,test
|
||||
Custom.Aliases = ini,test
|
||||
artist.Split = ";" # Should be able to read ; as a separator
|
||||
3
conf/testdata/cfg.json
vendored
3
conf/testdata/cfg.json
vendored
@ -2,6 +2,9 @@
|
||||
"musicFolder": "/json/music",
|
||||
"uiWelcomeMessage": "Welcome json",
|
||||
"Tags": {
|
||||
"artist": {
|
||||
"split": ";"
|
||||
},
|
||||
"custom": {
|
||||
"aliases": [
|
||||
"json",
|
||||
|
||||
2
conf/testdata/cfg.toml
vendored
2
conf/testdata/cfg.toml
vendored
@ -1,5 +1,7 @@
|
||||
musicFolder = "/toml/music"
|
||||
uiWelcomeMessage = "Welcome toml"
|
||||
|
||||
Tags.artist.Split = ';'
|
||||
|
||||
[Tags.custom]
|
||||
aliases = ["toml", "test"]
|
||||
|
||||
2
conf/testdata/cfg.yaml
vendored
2
conf/testdata/cfg.yaml
vendored
@ -1,6 +1,8 @@
|
||||
musicFolder: "/yaml/music"
|
||||
uiWelcomeMessage: "Welcome yaml"
|
||||
Tags:
|
||||
artist:
|
||||
split: [";"]
|
||||
custom:
|
||||
aliases:
|
||||
- yaml
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
"actions": {
|
||||
"playAll": "Afspil",
|
||||
"playNext": "Afspil næste",
|
||||
"addToQueue": "Afspil senere",
|
||||
"addToQueue": "Føj til kø",
|
||||
"shuffle": "Bland",
|
||||
"addToPlaylist": "Føj til afspilningsliste",
|
||||
"download": "Download",
|
||||
@ -301,14 +301,19 @@
|
||||
"actions": {
|
||||
"scan": "Scanningsbibliotek",
|
||||
"manageUsers": "Administrer brugeradgang",
|
||||
"viewDetails": "Se detaljer"
|
||||
"viewDetails": "Se detaljer",
|
||||
"quickScan": "hurtig skanning",
|
||||
"fullScan": "Fuld skanning"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Bibliotek oprettet",
|
||||
"updated": "Biblioteket er blevet opdateret",
|
||||
"deleted": "Biblioteket er blevet slettet",
|
||||
"scanStarted": "Biblioteksscanning startet",
|
||||
"scanCompleted": "Biblioteksscanning fuldført"
|
||||
"scanCompleted": "Biblioteksscanning fuldført",
|
||||
"quickScanStarted": "hurtig skanning startet",
|
||||
"fullScanStarted": "Fuld skanning startet",
|
||||
"scanError": "Kan ikke starte skanning. Tjek loggen"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Biblioteksnavn er påkrævet",
|
||||
@ -549,7 +554,7 @@
|
||||
"closeText": "Luk",
|
||||
"notContentText": "Ingen musik",
|
||||
"clickToPlayText": "Tryk for at afspille",
|
||||
"clickToPauseText": "Tryk for at pause",
|
||||
"clickToPauseText": "Tryk for at sætte på pause",
|
||||
"nextTrackText": "Næste nummer",
|
||||
"previousTrackText": "Forrige nummer",
|
||||
"reloadText": "Genindlæs",
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "OFFLINE",
|
||||
"scanType": "Type",
|
||||
"status": "Scanningsfejl",
|
||||
"elapsedTime": "Medgået tid"
|
||||
"elapsedTime": "Medgået tid",
|
||||
"selectiveScan": "Selektiv"
|
||||
},
|
||||
"help": {
|
||||
"title": "Navidrome genvejstaster",
|
||||
|
||||
@ -301,14 +301,19 @@
|
||||
"actions": {
|
||||
"scan": "Bibliothek scannen",
|
||||
"manageUsers": "Zugriff verwalten",
|
||||
"viewDetails": "Details ansehen"
|
||||
"viewDetails": "Details ansehen",
|
||||
"quickScan": "Schneller Scan",
|
||||
"fullScan": "Kompletter Scan"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Bibliothek erfolgreich erstellt",
|
||||
"updated": "Bibliothek erfolgreich geändert",
|
||||
"deleted": "Bibliothek erfolgreich gelöscht",
|
||||
"scanStarted": "Bibliothek Scan gestartet",
|
||||
"scanCompleted": "Bibliothek Scan vollständig"
|
||||
"scanCompleted": "Bibliothek Scan vollständig",
|
||||
"quickScanStarted": "Schneller Scan gestartet",
|
||||
"fullScanStarted": "Kompletter Scan gestartet",
|
||||
"scanError": "Fehler beim Starten des Scans. Logs prüfen"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Bibliotheksname ist Pflichtfeld",
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "OFFLINE",
|
||||
"scanType": "Typ",
|
||||
"status": "Scan Fehler",
|
||||
"elapsedTime": "Laufzeit"
|
||||
"elapsedTime": "Laufzeit",
|
||||
"selectiveScan": "Selektiver Scan"
|
||||
},
|
||||
"help": {
|
||||
"title": "Navidrome Hotkeys",
|
||||
|
||||
@ -301,14 +301,19 @@
|
||||
"actions": {
|
||||
"scan": "Σάρωση βιβλιοθήκης",
|
||||
"manageUsers": "Διαχείριση πρόσβασης χρήστη",
|
||||
"viewDetails": "Προβολή λεπτομερειών"
|
||||
"viewDetails": "Προβολή λεπτομερειών",
|
||||
"quickScan": "Γρήγορη σάρωση",
|
||||
"fullScan": "Πλήρης σάρωση"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Η βιβλιοθήκη δημιουργήθηκε με επιτυχία",
|
||||
"updated": "Η βιβλιοθήκη ενημερώθηκε με επιτυχία",
|
||||
"deleted": "Η βιβλιοθήκη διαγράφηκε με επιτυχία",
|
||||
"scanStarted": "Ξεκίνησε η σάρωση της βιβλιοθήκης",
|
||||
"scanCompleted": "Η σάρωση της βιβλιοθήκης ολοκληρώθηκε"
|
||||
"scanCompleted": "Η σάρωση της βιβλιοθήκης ολοκληρώθηκε",
|
||||
"quickScanStarted": "Η Γρήγορη Σάρωση ξεκίνησε",
|
||||
"fullScanStarted": "Η πλήρης σάρωση ξεκίνησε",
|
||||
"scanError": "Σφάλμα κατά την έναρξη της σάρωσης. Ελέγξτε τα αρχεία καταγραφής."
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Απαιτείται όνομα βιβλιοθήκης",
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "ΕΚΤΟΣ ΣΥΝΔΕΣΗΣ",
|
||||
"scanType": "Τύπος",
|
||||
"status": "Σφάλμα σάρωσης",
|
||||
"elapsedTime": "Χρόνος που πέρασε"
|
||||
"elapsedTime": "Χρόνος που πέρασε",
|
||||
"selectiveScan": "Εκλεκτικός"
|
||||
},
|
||||
"help": {
|
||||
"title": "Συντομεύσεις του Navidrome",
|
||||
|
||||
@ -27,12 +27,16 @@
|
||||
"playDate": "最後の再生",
|
||||
"channels": "チャンネル",
|
||||
"createdAt": "追加日",
|
||||
"grouping": "",
|
||||
"mood": "",
|
||||
"participants": "",
|
||||
"tags": "",
|
||||
"mappedTags": "",
|
||||
"rawTags": ""
|
||||
"grouping": "グループ分け",
|
||||
"mood": "ムード",
|
||||
"participants": "追加参加者",
|
||||
"tags": "追加タグ",
|
||||
"mappedTags": "マッピング済みタグ",
|
||||
"rawTags": "未処理タグ",
|
||||
"bitDepth": "ビット深度",
|
||||
"sampleRate": "サンプリングレート",
|
||||
"missing": "不明",
|
||||
"libraryName": "ライブラリ"
|
||||
},
|
||||
"actions": {
|
||||
"addToQueue": "最後に再生",
|
||||
@ -41,7 +45,8 @@
|
||||
"shuffleAll": "全曲シャッフル",
|
||||
"download": "ダウンロード",
|
||||
"playNext": "次に再生",
|
||||
"info": "詳細"
|
||||
"info": "詳細",
|
||||
"showInPlaylist": "含まれるプレイリスト"
|
||||
}
|
||||
},
|
||||
"album": {
|
||||
@ -65,12 +70,15 @@
|
||||
"releaseDate": "リリース日",
|
||||
"releases": "リリース",
|
||||
"released": "リリース",
|
||||
"recordLabel": "",
|
||||
"catalogNum": "",
|
||||
"releaseType": "",
|
||||
"grouping": "",
|
||||
"media": "",
|
||||
"mood": ""
|
||||
"recordLabel": "ラベル",
|
||||
"catalogNum": "カタログ番号",
|
||||
"releaseType": "タイプ",
|
||||
"grouping": "グループ分け",
|
||||
"media": "メディア",
|
||||
"mood": "ムード",
|
||||
"date": "録音日",
|
||||
"missing": "不明",
|
||||
"libraryName": "ライブラリ"
|
||||
},
|
||||
"actions": {
|
||||
"playAll": "再生",
|
||||
@ -102,22 +110,29 @@
|
||||
"rating": "レート",
|
||||
"genre": "ジャンル",
|
||||
"size": "サイズ",
|
||||
"role": ""
|
||||
"role": "役割",
|
||||
"missing": "不明"
|
||||
},
|
||||
"roles": {
|
||||
"albumartist": "",
|
||||
"artist": "",
|
||||
"composer": "",
|
||||
"conductor": "",
|
||||
"lyricist": "",
|
||||
"arranger": "",
|
||||
"producer": "",
|
||||
"director": "",
|
||||
"engineer": "",
|
||||
"mixer": "",
|
||||
"remixer": "",
|
||||
"djmixer": "",
|
||||
"performer": ""
|
||||
"albumartist": "アルバムアーティスト",
|
||||
"artist": "アーティスト",
|
||||
"composer": "作曲家",
|
||||
"conductor": "指揮者",
|
||||
"lyricist": "作詞家",
|
||||
"arranger": "編曲者",
|
||||
"producer": "プロデューサー",
|
||||
"director": "ディレクター",
|
||||
"engineer": "エンジニア",
|
||||
"mixer": "ミキサー",
|
||||
"remixer": "リミキサー",
|
||||
"djmixer": "DJ ミキサー",
|
||||
"performer": "演奏者",
|
||||
"maincredit": "アルバムアーティストもしくはアーティスト"
|
||||
},
|
||||
"actions": {
|
||||
"shuffle": "シャッフル",
|
||||
"radio": "ラジオ",
|
||||
"topSongs": "トップソング"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
@ -134,10 +149,12 @@
|
||||
"currentPassword": "現在のパスワード",
|
||||
"newPassword": "新しいパスワード",
|
||||
"token": "トークン",
|
||||
"lastAccessAt": "最終アクセス"
|
||||
"lastAccessAt": "最終アクセス",
|
||||
"libraries": "ライブラリ"
|
||||
},
|
||||
"helperTexts": {
|
||||
"name": "名前の変更は次回ログイン以降反映されます"
|
||||
"name": "名前の変更は次回ログイン以降反映されます",
|
||||
"libraries": "このユーザーに対して特定ライブラリを選択するか、デフォルトのライブラリを使用する場合は空欄のままにします"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "ユーザーが作成されました",
|
||||
@ -146,7 +163,12 @@
|
||||
},
|
||||
"message": {
|
||||
"listenBrainzToken": "ListenBrainzユーザートークンを入力",
|
||||
"clickHereForToken": "ここをクリックしトークンを入手"
|
||||
"clickHereForToken": "ここをクリックしトークンを入手",
|
||||
"selectAllLibraries": "全てのライブラリを選択",
|
||||
"adminAutoLibraries": "管理者ユーザーは自動的にすべてのライブラリにアクセスできます"
|
||||
},
|
||||
"validation": {
|
||||
"librariesRequired": "管理者以外のユーザーには少なくとも1つのライブラリを選択する必要があります"
|
||||
}
|
||||
},
|
||||
"player": {
|
||||
@ -190,11 +212,17 @@
|
||||
"addNewPlaylist": "'%{name}' を作成",
|
||||
"export": "エクスポート",
|
||||
"makePublic": "公開する",
|
||||
"makePrivate": "非公開にする"
|
||||
"makePrivate": "非公開にする",
|
||||
"saveQueue": "キューをプレイリストに保存",
|
||||
"searchOrCreate": "プレイリストを検索または入力して新規作成...",
|
||||
"pressEnterToCreate": "Enterキーを押して新しいプレイリストを作成",
|
||||
"removeFromSelection": "選択から削除"
|
||||
},
|
||||
"message": {
|
||||
"duplicate_song": "重複する曲を追加",
|
||||
"song_exist": "既にプレイリストに存在する曲です。追加しますか?"
|
||||
"song_exist": "既にプレイリストに存在する曲です。追加しますか?",
|
||||
"noPlaylistsFound": "プレイリストが見つかりません",
|
||||
"noPlaylists": "利用可能なプレイリストはありません"
|
||||
}
|
||||
},
|
||||
"radio": {
|
||||
@ -228,17 +256,77 @@
|
||||
}
|
||||
},
|
||||
"missing": {
|
||||
"name": "",
|
||||
"name": "欠落したファイル",
|
||||
"fields": {
|
||||
"path": "",
|
||||
"size": "",
|
||||
"updatedAt": ""
|
||||
"path": "パス",
|
||||
"size": "サイズ",
|
||||
"updatedAt": "欠落日",
|
||||
"libraryName": "ライブラリ"
|
||||
},
|
||||
"actions": {
|
||||
"remove": ""
|
||||
"remove": "削除",
|
||||
"remove_all": "全て削除"
|
||||
},
|
||||
"notifications": {
|
||||
"removed": ""
|
||||
"removed": "欠落ファイルが削除されました"
|
||||
},
|
||||
"empty": "ファイルの欠落はありません"
|
||||
},
|
||||
"library": {
|
||||
"name": "ライブラリ",
|
||||
"fields": {
|
||||
"name": "名前",
|
||||
"path": "パス",
|
||||
"remotePath": "リモートパス",
|
||||
"lastScanAt": "最終スキャン",
|
||||
"songCount": "曲数",
|
||||
"albumCount": "アルバム数",
|
||||
"artistCount": "アーティスト数",
|
||||
"totalSongs": "曲数",
|
||||
"totalAlbums": "アルバム数",
|
||||
"totalArtists": "アーティスト数",
|
||||
"totalFolders": "フォルダー数",
|
||||
"totalFiles": "ファイル数",
|
||||
"totalMissingFiles": "欠落したファイル",
|
||||
"totalSize": "合計サイズ",
|
||||
"totalDuration": "合計時間",
|
||||
"defaultNewUsers": "新規ユーザーに対するデフォルト",
|
||||
"createdAt": "作成日",
|
||||
"updatedAt": "更新日"
|
||||
},
|
||||
"sections": {
|
||||
"basic": "基本情報",
|
||||
"statistics": "統計"
|
||||
},
|
||||
"actions": {
|
||||
"scan": "ライブラリをスキャン",
|
||||
"manageUsers": "ユーザーアクセス管理",
|
||||
"viewDetails": "詳細を表示",
|
||||
"quickScan": "クイックスキャン",
|
||||
"fullScan": "フルスキャン"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "ライブラリが正常に作成されました",
|
||||
"updated": "ライブラリが正常に更新されました",
|
||||
"deleted": "ライブラリが正常に削除されました",
|
||||
"scanStarted": "スキャンを開始しました",
|
||||
"scanCompleted": "スキャンが完了しました",
|
||||
"quickScanStarted": "クイックスキャンを開始しました",
|
||||
"fullScanStarted": "フルスキャンを開始しました",
|
||||
"scanError": "スキャン開始中にエラーが発生。ログを確認してください"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "ライブラリの名前が必要です",
|
||||
"pathRequired": "ライブラリのパスが必要です",
|
||||
"pathNotDirectory": "ライブラリパスはディレクトリである必要があります",
|
||||
"pathNotFound": "ライブラリのパスが見つかりません",
|
||||
"pathNotAccessible": "ライブラリパスへアクセスできません",
|
||||
"pathInvalid": "無効なライブラリパス"
|
||||
},
|
||||
"messages": {
|
||||
"deleteConfirm": "このライブラリを削除しますか?関連する全てのデータとユーザーアクセスが削除されます。",
|
||||
"scanInProgress": "スキャン中...",
|
||||
"noLibrariesAssigned": "このユーザーに割り当てられているライブラリはありません"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -418,8 +506,12 @@
|
||||
"shareFailure": "コピーに失敗しました %{url}",
|
||||
"downloadDialogTitle": "ダウンロード %{resource} '%{name}' (%{size})",
|
||||
"shareCopyToClipboard": "クリップボードへコピー: Ctrl+C, Enter",
|
||||
"remove_missing_title": "",
|
||||
"remove_missing_content": ""
|
||||
"remove_missing_title": "欠落ファイルを削除",
|
||||
"remove_missing_content": "選択した欠落ファイルをデータベースから削除してもよろしいですか?これにより、再生数や評価を含むそれらのファイルへの参照が完全に削除されます。",
|
||||
"remove_all_missing_title": "全ての欠落ファイルを削除",
|
||||
"remove_all_missing_content": "データベースから欠落ファイルをすべて削除してもよろしいですか?これにより、再生数や評価を含むそれらのファイルへの参照が永久に削除されます。",
|
||||
"noSimilarSongsFound": "類似の曲が見つかりませんでした",
|
||||
"noTopSongsFound": "トップソングが見つかりません"
|
||||
},
|
||||
"menu": {
|
||||
"library": "ライブラリ",
|
||||
@ -448,7 +540,13 @@
|
||||
"albumList": "アルバム",
|
||||
"about": "詳細",
|
||||
"playlists": "プレイリスト",
|
||||
"sharedPlaylists": "共有プレイリスト"
|
||||
"sharedPlaylists": "共有プレイリスト",
|
||||
"librarySelector": {
|
||||
"allLibraries": "全てのライブラリ( %{count} )",
|
||||
"multipleLibraries": "%{selected} 個 / %{total} 個のライブラリ",
|
||||
"selectLibraries": "ライブラリを選択",
|
||||
"none": "無し"
|
||||
}
|
||||
},
|
||||
"player": {
|
||||
"playListsText": "再生リスト",
|
||||
@ -485,15 +583,34 @@
|
||||
"disabled": "無効",
|
||||
"waiting": "待機中"
|
||||
}
|
||||
},
|
||||
"tabs": {
|
||||
"about": "詳細",
|
||||
"config": "設定"
|
||||
},
|
||||
"config": {
|
||||
"configName": "設定名",
|
||||
"environmentVariable": "環境変数",
|
||||
"currentValue": "現在値",
|
||||
"configurationFile": "設定ファイル",
|
||||
"exportToml": "設定をエクスポート(TOML)",
|
||||
"exportSuccess": "設定をTOML形式でクリップボードへエクスポートしました",
|
||||
"exportFailed": "設定のコピーに失敗しました",
|
||||
"devFlagsHeader": "開発フラグ(変更・削除の可能性あり)",
|
||||
"devFlagsComment": "これらは実験的な設定であり、将来のバージョンで削除される可能性があります"
|
||||
}
|
||||
},
|
||||
"activity": {
|
||||
"title": "活動",
|
||||
"totalScanned": "スキャン済みフォルダー",
|
||||
"quickScan": "クイックスキャン",
|
||||
"fullScan": "フルスキャン",
|
||||
"quickScan": "クイック",
|
||||
"fullScan": "フル",
|
||||
"serverUptime": "サーバー稼働時間",
|
||||
"serverDown": "サーバーオフライン"
|
||||
"serverDown": "サーバーオフライン",
|
||||
"scanType": "最終スキャン",
|
||||
"status": "スキャンエラー",
|
||||
"elapsedTime": "経過時間",
|
||||
"selectiveScan": "選択的スキャン"
|
||||
},
|
||||
"help": {
|
||||
"title": "ホットキー",
|
||||
@ -508,5 +625,10 @@
|
||||
"toggle_love": "星の付け外し",
|
||||
"current_song": "現在の曲へ移動"
|
||||
}
|
||||
},
|
||||
"nowPlaying": {
|
||||
"title": "再生中",
|
||||
"empty": "何も再生されていません",
|
||||
"minutesAgo": "%{smart_count} 分前 |||| %{smart_count} 分前"
|
||||
}
|
||||
}
|
||||
@ -301,14 +301,19 @@
|
||||
"actions": {
|
||||
"scan": "Skanuj Bibliotekę",
|
||||
"manageUsers": "Zarządzaj Dostępami Użytkownika",
|
||||
"viewDetails": "Zobacz Szczegóły"
|
||||
"viewDetails": "Zobacz Szczegóły",
|
||||
"quickScan": "Szybkie Skanowanie",
|
||||
"fullScan": "Pełne Skanowanie"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Biblioteka utworzona prawidłowo",
|
||||
"updated": "Biblioteka zaktualizowana prawidłowo",
|
||||
"deleted": "Biblioteka usunięta prawidłowo",
|
||||
"scanStarted": "Rozpoczęto skan biblioteki",
|
||||
"scanCompleted": "Zakończono skan biblioteki"
|
||||
"scanCompleted": "Zakończono skan biblioteki",
|
||||
"quickScanStarted": "Szybkie skanowanie rozpoczęte",
|
||||
"fullScanStarted": "Pełne skanowanie rozpoczęte",
|
||||
"scanError": "Błąd podczas startu skanowania. Sprawdź logi"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Nazwa biblioteki jest wymagana",
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "NIEDOSTĘPNY",
|
||||
"scanType": "Typ",
|
||||
"status": "Błąd Skanowania",
|
||||
"elapsedTime": "Upłynięty Czas"
|
||||
"elapsedTime": "Upłynięty Czas",
|
||||
"selectiveScan": "Selektywne"
|
||||
},
|
||||
"help": {
|
||||
"title": "Skróty Klawiszowe Navidrome",
|
||||
|
||||
@ -301,20 +301,25 @@
|
||||
"actions": {
|
||||
"scan": "Сканировать библиотеку",
|
||||
"manageUsers": "Управление доступом пользователей",
|
||||
"viewDetails": "Просмотреть подробности"
|
||||
"viewDetails": "Просмотреть подробности",
|
||||
"quickScan": "Быстрое сканирование",
|
||||
"fullScan": "Полное сканирование"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Библиотека успешно создана",
|
||||
"updated": "Библиотека успешно обновлена",
|
||||
"deleted": "Библиотека успешно удалена",
|
||||
"scanStarted": "Сканирование библиотеки начато",
|
||||
"scanCompleted": "Сканирование библиотеки закончено"
|
||||
"scanCompleted": "Сканирование библиотеки закончено",
|
||||
"quickScanStarted": "Быстрое сканирование началось",
|
||||
"fullScanStarted": "Началось полное сканирование",
|
||||
"scanError": "Ошибка при запуске сканирования. Проверьте логи"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Имя библиотеки обязательно",
|
||||
"pathRequired": "Путь к библиотеке обязателен",
|
||||
"pathNotDirectory": "Путь к библиотеке должен быть директорией",
|
||||
"pathNotFound": "Путь к библиотеке не найдено",
|
||||
"pathNotFound": "Путь к библиотеке не найден",
|
||||
"pathNotAccessible": "Путь к библиотеке недоступен",
|
||||
"pathInvalid": "Неверный путь к библиотеке"
|
||||
},
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "Оффлайн",
|
||||
"scanType": "Тип",
|
||||
"status": "Ошибка сканирования",
|
||||
"elapsedTime": "Прошедшее время"
|
||||
"elapsedTime": "Прошедшее время",
|
||||
"selectiveScan": "Избирательный"
|
||||
},
|
||||
"help": {
|
||||
"title": "Горячие клавиши Navidrome",
|
||||
|
||||
@ -301,14 +301,19 @@
|
||||
"actions": {
|
||||
"scan": "Scanna bibliotek",
|
||||
"manageUsers": "Hantera användaråtkomst",
|
||||
"viewDetails": "Se detaljer"
|
||||
"viewDetails": "Se detaljer",
|
||||
"quickScan": "Snabbscan",
|
||||
"fullScan": "Komplett scan"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Biblioteket har skapats",
|
||||
"updated": "Biblioteket har uppdaterats",
|
||||
"deleted": "Biblioteket har raderats",
|
||||
"scanStarted": "Biblioteksscan startad",
|
||||
"scanCompleted": "Biblioteksscan avslutad"
|
||||
"scanCompleted": "Biblioteksscan avslutad",
|
||||
"quickScanStarted": "Snabbscan startad",
|
||||
"fullScanStarted": "Komplett scan startad",
|
||||
"scanError": "Fel vid start av scan. Se loggarna"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Biblioteksnamn krävs",
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "OFFLINE",
|
||||
"scanType": "Typ",
|
||||
"status": "Fel vid scanning",
|
||||
"elapsedTime": "Spelad tid"
|
||||
"elapsedTime": "Spelad tid",
|
||||
"selectiveScan": "Urval"
|
||||
},
|
||||
"help": {
|
||||
"title": "Navidrome kortkommandon",
|
||||
|
||||
@ -301,14 +301,19 @@
|
||||
"actions": {
|
||||
"scan": "สแกนห้องสมุด",
|
||||
"manageUsers": "ตั้งค่าการเข้าถึง",
|
||||
"viewDetails": "ดูรายละเอียด"
|
||||
"viewDetails": "ดูรายละเอียด",
|
||||
"quickScan": "สแกนแบบเร็ว",
|
||||
"fullScan": "สแกนแบบเต็ม"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "สร้างห้องสมุดเรียบร้อย",
|
||||
"updated": "อัพเดทห้องสมุดเรียบร้อย",
|
||||
"deleted": "ลบห้องสมุดเพลงเรียบร้อยแล้ว",
|
||||
"scanStarted": "เริ่มสแกนห้องสมุด",
|
||||
"scanCompleted": "สแกนห้องสมุดเสร็จแล้ว"
|
||||
"scanCompleted": "สแกนห้องสมุดเสร็จแล้ว",
|
||||
"quickScanStarted": "เริ่มสแกนแบบเร็ว",
|
||||
"fullScanStarted": "เริ่มสแกนแบบเต็ม",
|
||||
"scanError": "การเริ่มสแกนผิดพลาด ดูในบันทึก"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "ต้องใส่ชื่อห้องสมุดเพลง",
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "ออฟไลน์",
|
||||
"scanType": "ประเภท",
|
||||
"status": "สแกนผิดพลาด",
|
||||
"elapsedTime": "เวลาที่ใช้"
|
||||
"elapsedTime": "เวลาที่ใช้",
|
||||
"selectiveScan": "เลือก"
|
||||
},
|
||||
"help": {
|
||||
"title": "คีย์ลัด Navidrome",
|
||||
|
||||
@ -301,14 +301,19 @@
|
||||
"actions": {
|
||||
"scan": "Сканувати бібліотеку",
|
||||
"manageUsers": "Керування доступом користувачів",
|
||||
"viewDetails": "Переглянути подробиці"
|
||||
"viewDetails": "Переглянути подробиці",
|
||||
"quickScan": "Швидке сканування",
|
||||
"fullScan": "Повне сканування"
|
||||
},
|
||||
"notifications": {
|
||||
"created": "Бібліотеку успішно створено",
|
||||
"updated": "Бібліотеку успішно оновлено",
|
||||
"deleted": "Бібліотеку успішно видалено",
|
||||
"scanStarted": "Сканування бібліотеки розпочато",
|
||||
"scanCompleted": "Сканування бібліотеки закінчено"
|
||||
"scanCompleted": "Сканування бібліотеки закінчено",
|
||||
"quickScanStarted": "Швидке сканування виконується",
|
||||
"fullScanStarted": "Повне сканування виконується",
|
||||
"scanError": "Помилка при виконанні сканування. Перевірте лоґи"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Ім'я бібліотеки обов'язкове",
|
||||
@ -604,7 +609,8 @@
|
||||
"serverDown": "Оффлайн",
|
||||
"scanType": "Тип",
|
||||
"status": "Помилка сканування",
|
||||
"elapsedTime": "Пройдений час"
|
||||
"elapsedTime": "Пройдений час",
|
||||
"selectiveScan": "Вибірковий"
|
||||
},
|
||||
"help": {
|
||||
"title": "Гарячі клавіші Navidrome",
|
||||
|
||||
@ -8,12 +8,10 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/navidrome/navidrome/conf"
|
||||
"github.com/navidrome/navidrome/log"
|
||||
"github.com/navidrome/navidrome/model"
|
||||
"github.com/navidrome/navidrome/utils/slice"
|
||||
)
|
||||
|
||||
// scannerExternal is a scanner that runs an external process to do the scanning. It is used to avoid
|
||||
@ -47,9 +45,10 @@ func (s *scannerExternal) scan(ctx context.Context, fullScan bool, targets []mod
|
||||
|
||||
// Add targets if provided
|
||||
if len(targets) > 0 {
|
||||
targetsStr := strings.Join(slice.Map(targets, func(t model.ScanTarget) string { return t.String() }), ",")
|
||||
args = append(args, "--targets", targetsStr)
|
||||
log.Debug(ctx, "Spawning external scanner process with targets", "fullScan", fullScan, "path", exe, "targets", targetsStr)
|
||||
for _, target := range targets {
|
||||
args = append(args, "-t", target.String())
|
||||
}
|
||||
log.Debug(ctx, "Spawning external scanner process with targets", "fullScan", fullScan, "path", exe, "targets", targets)
|
||||
} else {
|
||||
log.Debug(ctx, "Spawning external scanner process", "fullScan", fullScan, "path", exe)
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { useMediaQuery } from '@material-ui/core'
|
||||
import { useMediaQuery, CircularProgress } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
Button,
|
||||
@ -45,6 +45,12 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
}))
|
||||
|
||||
const LoadingButton = ({ loading, icon, ...rest }) => (
|
||||
<Button {...rest}>
|
||||
{loading ? <CircularProgress size={20} color="inherit" /> : icon}
|
||||
</Button>
|
||||
)
|
||||
|
||||
const ArtistActions = ({ className, record, ...rest }) => {
|
||||
const dispatch = useDispatch()
|
||||
const translate = useTranslate()
|
||||
@ -52,34 +58,45 @@ const ArtistActions = ({ className, record, ...rest }) => {
|
||||
const notify = useNotify()
|
||||
const classes = useStyles()
|
||||
const isMobile = useMediaQuery((theme) => theme.breakpoints.down('xs'))
|
||||
const [loadingAction, setLoadingAction] = React.useState(null)
|
||||
const isLoading = !!loadingAction
|
||||
|
||||
const handlePlay = React.useCallback(async () => {
|
||||
setLoadingAction('play')
|
||||
try {
|
||||
await playTopSongs(dispatch, notify, record.name)
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error fetching top songs for artist:', e)
|
||||
notify('ra.page.error', 'warning')
|
||||
} finally {
|
||||
setLoadingAction(null)
|
||||
}
|
||||
}, [dispatch, notify, record])
|
||||
|
||||
const handleShuffle = React.useCallback(async () => {
|
||||
setLoadingAction('shuffle')
|
||||
try {
|
||||
await playShuffle(dataProvider, dispatch, record.id)
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error fetching songs for shuffle:', e)
|
||||
notify('ra.page.error', 'warning')
|
||||
} finally {
|
||||
setLoadingAction(null)
|
||||
}
|
||||
}, [dataProvider, dispatch, record, notify])
|
||||
|
||||
const handleRadio = React.useCallback(async () => {
|
||||
setLoadingAction('radio')
|
||||
try {
|
||||
await playSimilar(dispatch, notify, record.id)
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error starting radio for artist:', e)
|
||||
notify('ra.page.error', 'warning')
|
||||
} finally {
|
||||
setLoadingAction(null)
|
||||
}
|
||||
}, [dispatch, notify, record])
|
||||
|
||||
@ -88,30 +105,33 @@ const ArtistActions = ({ className, record, ...rest }) => {
|
||||
className={`${className} ${classes.toolbar}`}
|
||||
{...sanitizeListRestProps(rest)}
|
||||
>
|
||||
<Button
|
||||
<LoadingButton
|
||||
onClick={handlePlay}
|
||||
label={translate('resources.artist.actions.topSongs')}
|
||||
className={classes.button}
|
||||
size={isMobile ? 'small' : 'medium'}
|
||||
>
|
||||
<PlayArrowIcon />
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isLoading}
|
||||
loading={loadingAction === 'play'}
|
||||
icon={<PlayArrowIcon />}
|
||||
/>
|
||||
<LoadingButton
|
||||
onClick={handleShuffle}
|
||||
label={translate('resources.artist.actions.shuffle')}
|
||||
className={classes.button}
|
||||
size={isMobile ? 'small' : 'medium'}
|
||||
>
|
||||
<ShuffleIcon />
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isLoading}
|
||||
loading={loadingAction === 'shuffle'}
|
||||
icon={<ShuffleIcon />}
|
||||
/>
|
||||
<LoadingButton
|
||||
onClick={handleRadio}
|
||||
label={translate('resources.artist.actions.radio')}
|
||||
className={classes.button}
|
||||
size={isMobile ? 'small' : 'medium'}
|
||||
>
|
||||
<IoIosRadio className={classes.radioIcon} />
|
||||
</Button>
|
||||
disabled={isLoading}
|
||||
loading={loadingAction === 'radio'}
|
||||
icon={<IoIosRadio className={classes.radioIcon} />}
|
||||
/>
|
||||
</TopToolbar>
|
||||
)
|
||||
}
|
||||
|
||||
175
ui/src/themes/SquiddiesGlass.css.js
Normal file
175
ui/src/themes/SquiddiesGlass.css.js
Normal file
@ -0,0 +1,175 @@
|
||||
const stylesheet = `
|
||||
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-handle {
|
||||
background: #c231ab
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-track,
|
||||
.react-jinke-music-player-mobile-progress .rc-slider-track {
|
||||
background: linear-gradient(to left, #c231ab, #380eff)
|
||||
}
|
||||
|
||||
.react-jinke-music-player-mobile {
|
||||
background-color: #171717 !important;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-mobile-progress .rc-slider-handle {
|
||||
background: #c231ab;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-top: -9px;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main ::-webkit-scrollbar-thumb {
|
||||
background-color: #c231ab;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-pause-icon {
|
||||
background-color: #c231ab;
|
||||
border-radius: 50%;
|
||||
outline: auto;
|
||||
color: white;
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .player-content {
|
||||
z-index: 99999;
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .player-content .play-btn svg {
|
||||
border-radius: 50%;
|
||||
outline: auto;
|
||||
color: white;
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .player-content .play-btn svg:hover {
|
||||
background-color: #c231ab;
|
||||
border-radius: 50%;
|
||||
outline: auto;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.react-jinke-music-player-main svg:hover {
|
||||
color: #c231ab;
|
||||
}
|
||||
|
||||
.react-jinke-music-player .music-player-controller {
|
||||
color: #c231ab;
|
||||
border: 1px solid #e14ac2;
|
||||
}
|
||||
|
||||
.react-jinke-music-player .music-player-controller.music-player-playing:before {
|
||||
border: 1px solid rgba(194, 49, 171, 0.3);
|
||||
}
|
||||
|
||||
.react-jinke-music-player .music-player .destroy-btn {
|
||||
background-color: #c2c1c2;
|
||||
top: -7px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.react-jinke-music-player .music-player .destroy-btn svg {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.react-jinke-music-player .music-player .destroy-btn {
|
||||
right: -12px;
|
||||
}
|
||||
}
|
||||
|
||||
.react-jinke-music-player-mobile-header-right {
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.react-jinke-music-player-main svg {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gradientFlow {
|
||||
0% { background-position: 0% 50%; }
|
||||
50% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
|
||||
.RaBulkActionsToolbar .MuiButton-label {
|
||||
color: white;
|
||||
}
|
||||
|
||||
a[aria-current="page"] {
|
||||
color: #c231ab !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a[aria-current="page"] .MuiListItemIcon-root {
|
||||
color: #c231ab !important;
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(90deg, #311f2f, #0a0912, #2f0c28);
|
||||
background-size: 300% 300%;
|
||||
animation: gradientFlow 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Equalizer bars */
|
||||
.panel-content::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: repeating-linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0.05) 0px,
|
||||
rgba(255, 255, 255, 0.05) 2px,
|
||||
transparent 1px,
|
||||
transparent 3px
|
||||
);
|
||||
animation: equalizer 1.8s infinite ease-in-out;
|
||||
filter: blur(1px);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@keyframes backgroundFlow {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Vertical movement, equalizer type */
|
||||
@keyframes equalizer {
|
||||
0%, 100% {
|
||||
transform: scaleY(1);
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
transform: scaleY(1.4);
|
||||
opacity: 0.9;
|
||||
}
|
||||
50% {
|
||||
transform: scaleY(0.7);
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
transform: scaleY(1.2);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { opacity: 0.5; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
`
|
||||
|
||||
export default stylesheet
|
||||
608
ui/src/themes/SquiddiesGlass.js
Normal file
608
ui/src/themes/SquiddiesGlass.js
Normal file
@ -0,0 +1,608 @@
|
||||
import stylesheet from './SquiddiesGlass.css.js'
|
||||
|
||||
/**
|
||||
* Color constants used throughout the Squiddies Glass theme.
|
||||
* Provides a consistent color palette with pink, gray, purple, and basic colors.
|
||||
* @type {Object}
|
||||
*/
|
||||
const colors = {
|
||||
pink: {
|
||||
100: '#fbe3f4',
|
||||
200: '#f5b9e3',
|
||||
300: '#ec7cd6',
|
||||
400: '#e14ac2',
|
||||
500: '#c231ab', // base
|
||||
600: '#a31a92',
|
||||
700: '#8b0f7e',
|
||||
800: '#7a006d',
|
||||
900: '#670066',
|
||||
},
|
||||
gray: {
|
||||
50: '#c2c1c2',
|
||||
100: '#b3b3b3', // light gray
|
||||
200: '#282828', // medium dark
|
||||
300: '#1d1d1d', // darker
|
||||
400: '#181818', // even darker
|
||||
500: '#171717', // darkest
|
||||
},
|
||||
purple: {
|
||||
400: '#524590',
|
||||
500: '#4d3249',
|
||||
600: '#6d1c5e',
|
||||
},
|
||||
black: '#000',
|
||||
white: '#fff',
|
||||
dark: '#121212',
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared style object for music list action buttons.
|
||||
* Defines common styling for buttons in music lists, including hover effects and responsive scaling.
|
||||
* @type {Object}
|
||||
*/
|
||||
const musicListActions = {
|
||||
padding: '1rem 0',
|
||||
alignItems: 'center',
|
||||
'@global': {
|
||||
button: {
|
||||
border: '1px solid transparent',
|
||||
backgroundColor: 'inherit',
|
||||
color: colors.gray[100],
|
||||
'&:hover': {
|
||||
border: `1px solid ${colors.gray[100]}`,
|
||||
backgroundColor: 'inherit !important',
|
||||
},
|
||||
},
|
||||
'button:first-child:not(:only-child)': {
|
||||
'@media screen and (max-width: 720px)': {
|
||||
transform: 'scale(1.3)',
|
||||
margin: '1em',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.2) !important',
|
||||
},
|
||||
},
|
||||
transform: 'scale(1.3)',
|
||||
margin: '1em',
|
||||
minWidth: 0,
|
||||
padding: 5,
|
||||
transition: 'transform .3s ease',
|
||||
background: colors.pink[500],
|
||||
color: `${colors.black} !important`,
|
||||
borderRadius: 500,
|
||||
border: 0,
|
||||
'&:hover': {
|
||||
transform: 'scale(1.2)',
|
||||
backgroundColor: `${colors.pink[500]} !important`,
|
||||
border: 0,
|
||||
},
|
||||
},
|
||||
'button:only-child': {
|
||||
marginTop: '0.3em',
|
||||
},
|
||||
'button:first-child>span:first-child': {
|
||||
padding: 0,
|
||||
color: `${colors.black} !important`,
|
||||
},
|
||||
'button:first-child>span:first-child>span': {
|
||||
display: 'none',
|
||||
},
|
||||
'button>span:first-child>span, button:not(:first-child)>span:first-child>svg':
|
||||
{
|
||||
color: colors.gray[100],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Squiddies Glass theme configuration object.
|
||||
* Defines the complete theme structure including typography, palette, component overrides, and player settings.
|
||||
* @type {Object}
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* The name of the theme.
|
||||
* @type {string}
|
||||
*/
|
||||
themeName: 'Squiddies Glass',
|
||||
|
||||
/**
|
||||
* Typography settings for the theme.
|
||||
* Specifies font family and heading sizes.
|
||||
* @type {Object}
|
||||
*/
|
||||
typography: {
|
||||
fontFamily: "system-ui, 'Helvetica Neue', Helvetica, Arial, sans-serif",
|
||||
h6: {
|
||||
fontSize: '1rem', // AppBar title
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Color palette configuration.
|
||||
* Defines primary, secondary, and background colors for the theme.
|
||||
* @type {Object}
|
||||
*/
|
||||
palette: {
|
||||
primary: {
|
||||
light: colors.pink[300],
|
||||
main: colors.pink[500],
|
||||
},
|
||||
secondary: {
|
||||
main: colors.white,
|
||||
contrastText: colors.white,
|
||||
},
|
||||
background: {
|
||||
default: colors.dark,
|
||||
paper: colors.dark,
|
||||
},
|
||||
type: 'dark',
|
||||
},
|
||||
|
||||
/**
|
||||
* Component overrides for Material-UI and custom Navidrome components.
|
||||
* Customizes the appearance and behavior of various UI components.
|
||||
* @type {Object}
|
||||
*/
|
||||
overrides: {
|
||||
// Material-UI Components
|
||||
MuiAppBar: {
|
||||
positionFixed: {
|
||||
backgroundColor: `${colors.black} !important`,
|
||||
boxShadow: 'none',
|
||||
},
|
||||
},
|
||||
MuiButton: {
|
||||
root: {
|
||||
background: colors.pink[500],
|
||||
color: colors.white,
|
||||
border: '1px solid transparent',
|
||||
borderRadius: 500,
|
||||
'&:hover': {
|
||||
background: `${colors.pink[900]} !important`,
|
||||
},
|
||||
},
|
||||
textSecondary: {
|
||||
border: `1px solid ${colors.gray[100]}`,
|
||||
background: colors.black,
|
||||
'&:hover': {
|
||||
border: `1px solid ${colors.white} !important`,
|
||||
background: `${colors.black} !important`,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
color: colors.white,
|
||||
paddingRight: '1rem',
|
||||
paddingLeft: '0.7rem',
|
||||
},
|
||||
},
|
||||
MuiCardMedia: {
|
||||
root: {
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
boxShadow: `0 2px 32px rgba(0,0,0,0.5), 0px 1px 5px rgba(0,0,0,0.1)`,
|
||||
},
|
||||
},
|
||||
MuiDivider: {
|
||||
root: {
|
||||
margin: '.75rem 0',
|
||||
},
|
||||
},
|
||||
MuiDrawer: {
|
||||
root: {
|
||||
background: colors.gray[500],
|
||||
paddingTop: '10px',
|
||||
},
|
||||
},
|
||||
MuiFormGroup: {
|
||||
root: {
|
||||
color: colors.pink[500],
|
||||
},
|
||||
},
|
||||
MuiMenuItem: {
|
||||
root: {
|
||||
fontSize: '0.875rem',
|
||||
},
|
||||
},
|
||||
MuiTableCell: {
|
||||
root: {
|
||||
borderBottom: `1px solid ${colors.gray[300]}`,
|
||||
padding: '10px !important',
|
||||
color: `${colors.gray[100]} !important`,
|
||||
'& img': {
|
||||
filter:
|
||||
'brightness(0) saturate(100%) invert(36%) sepia(93%) saturate(7463%) hue-rotate(289deg) brightness(95%) contrast(102%);',
|
||||
},
|
||||
'& img + span': {
|
||||
color: colors.pink[500],
|
||||
},
|
||||
},
|
||||
head: {
|
||||
borderBottom: `1px solid ${colors.gray[200]}`,
|
||||
fontSize: '0.75rem',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: 1.2,
|
||||
},
|
||||
},
|
||||
MuiTableRow: {
|
||||
root: {
|
||||
padding: '10px 0',
|
||||
transition: 'background-color .3s ease',
|
||||
'&:hover': {
|
||||
backgroundColor: `${colors.gray[300]} !important`,
|
||||
},
|
||||
'@global': {
|
||||
'td:nth-child(4)': {
|
||||
color: `${colors.white} !important`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// React Admin Components
|
||||
RaBulkActionsToolbar: {
|
||||
topToolbar: {
|
||||
gap: '8px',
|
||||
},
|
||||
},
|
||||
RaFilter: {
|
||||
form: {
|
||||
'& .MuiOutlinedInput-input:-webkit-autofill': {
|
||||
'-webkit-box-shadow': `0 0 0 100px ${colors.gray[50]} inset`,
|
||||
'-webkit-text-fill-color': colors.white,
|
||||
},
|
||||
},
|
||||
},
|
||||
RaFilterButton: {
|
||||
root: {
|
||||
marginRight: '1rem',
|
||||
},
|
||||
},
|
||||
RaLayout: {
|
||||
content: {
|
||||
padding: '0 !important',
|
||||
background: `linear-gradient(${colors.dark}, ${colors.gray[500]})`,
|
||||
borderTopRightRadius: '8px',
|
||||
borderTopLeftRadius: '8px',
|
||||
},
|
||||
contentWithSidebar: {
|
||||
gap: '2px',
|
||||
},
|
||||
},
|
||||
RaList: {
|
||||
content: {
|
||||
backgroundColor: 'inherit',
|
||||
},
|
||||
bulkActionsDisplayed: {
|
||||
marginTop: '-20px',
|
||||
},
|
||||
},
|
||||
RaListToolbar: {
|
||||
toolbar: {
|
||||
padding: '0 .55rem !important',
|
||||
},
|
||||
},
|
||||
RaPaginationActions: {
|
||||
currentPageButton: {
|
||||
border: `1px solid ${colors.gray[100]}`,
|
||||
},
|
||||
button: {
|
||||
backgroundColor: 'inherit',
|
||||
minWidth: 48,
|
||||
margin: '0 4px',
|
||||
border: `1px solid ${colors.gray[200]}`,
|
||||
'@global': {
|
||||
'> .MuiButton-label': {
|
||||
padding: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
'@global': {
|
||||
'.next-page': {
|
||||
marginLeft: 8,
|
||||
marginRight: 8,
|
||||
},
|
||||
'.previous-page': {
|
||||
marginRight: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RaSearchInput: {
|
||||
input: {
|
||||
paddingLeft: '.9rem',
|
||||
border: 0,
|
||||
'& .MuiInputBase-root': {
|
||||
backgroundColor: `${colors.white} !important`,
|
||||
borderRadius: '20px !important',
|
||||
color: colors.black,
|
||||
border: '0px',
|
||||
'& fieldset': {
|
||||
borderColor: colors.white,
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: colors.white,
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: colors.white,
|
||||
},
|
||||
'& svg': {
|
||||
color: `${colors.black} !important`,
|
||||
},
|
||||
'& .MuiOutlinedInput-input:-webkit-autofill': {
|
||||
borderRadius: '20px 0px 0px 20px',
|
||||
'-webkit-box-shadow': `0 0 0 100px ${colors.gray[50]} inset`,
|
||||
'-webkit-text-fill-color': colors.black,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RaSidebar: {
|
||||
root: {
|
||||
height: 'initial',
|
||||
borderTopRightRadius: '8px',
|
||||
borderTopLeftRadius: '8px',
|
||||
},
|
||||
},
|
||||
|
||||
// Navidrome Custom Components
|
||||
NDAlbumDetails: {
|
||||
root: {
|
||||
boxShadow: 'none',
|
||||
background: `linear-gradient(45deg, ${colors.purple[500]}, ${colors.purple[400]}, ${colors.purple[600]})`,
|
||||
backgroundSize: '200% 200%',
|
||||
animation: 'gradientFlow 8s ease-in-out infinite',
|
||||
position: 'relative',
|
||||
'&:before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
background: `linear-gradient(to bottom, transparent, ${colors.dark})`,
|
||||
},
|
||||
},
|
||||
cardContents: {
|
||||
alignItems: 'flex-start',
|
||||
},
|
||||
coverParent: {
|
||||
zIndex: '99999',
|
||||
position: 'relative',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
inset: '0',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: '50%',
|
||||
animation: 'pulse 1.5s ease-in-out infinite alternate',
|
||||
zIndex: -1,
|
||||
},
|
||||
'&::after': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
inset: '0',
|
||||
zIndex: '-1',
|
||||
borderRadius: '50%',
|
||||
background:
|
||||
'repeating-conic-gradient(from 0deg, rgba(255,255,255,0.08) 0deg, rgba(255,255,255,0.08) 0.5deg, rgba(0,0,0,1) 1deg)',
|
||||
filter: 'contrast(999) sepia(1)',
|
||||
boxShadow:
|
||||
'inset 0 0 25px rgba(255,255,255,0.05), inset 0 0 95px rgba(0,0,0,0.9)',
|
||||
animation: 'spin 6s linear infinite',
|
||||
},
|
||||
},
|
||||
details: {
|
||||
zIndex: '99999',
|
||||
},
|
||||
recordName: {
|
||||
fontSize: 'calc(1rem + 1.5vw)',
|
||||
fontWeight: 900,
|
||||
},
|
||||
recordArtist: {
|
||||
fontSize: '1.5rem',
|
||||
fontWeight: 700,
|
||||
textShadow: '0 2px 16px rgba(0, 0, 0, 0.3)',
|
||||
},
|
||||
recordMeta: {
|
||||
fontSize: '.875rem',
|
||||
color: `rgba(${colors.white}, 0.8)`,
|
||||
},
|
||||
content: {
|
||||
paddingBottom: '0px !important',
|
||||
paddingTop: '0px',
|
||||
},
|
||||
},
|
||||
RaSingleFieldList: {
|
||||
root: {
|
||||
'& a:first-of-type > .MuiChip-root': {
|
||||
marginLeft: '0px',
|
||||
},
|
||||
'& a > .MuiChip-root': {
|
||||
backgroundColor: colors.pink[500],
|
||||
fontSize: '0.6rem',
|
||||
height: '20px',
|
||||
'& .MuiChip-label': {
|
||||
color: colors.white,
|
||||
paddingLeft: '5px',
|
||||
paddingRight: '5px',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiGridListTile: {
|
||||
tile: {
|
||||
'&:hover': {
|
||||
boxShadow: '0 2px 32px rgba(0,0,0,0.5), 0px 1px 5px rgba(0,0,0,0.1)',
|
||||
},
|
||||
},
|
||||
},
|
||||
NDAlbumGridView: {
|
||||
tileBar: {
|
||||
background:
|
||||
'linear-gradient(to top, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.4) 50%, rgba(0, 0, 0, 0) 100%)',
|
||||
marginBottom: '2px',
|
||||
},
|
||||
albumName: {
|
||||
marginTop: '0.5rem',
|
||||
fontWeight: 700,
|
||||
textTransform: 'none',
|
||||
color: colors.white,
|
||||
},
|
||||
albumSubtitle: {
|
||||
color: colors.gray[100],
|
||||
},
|
||||
albumContainer: {
|
||||
backgroundColor: colors.gray[400],
|
||||
borderRadius: '.5rem',
|
||||
padding: '.75rem',
|
||||
transition: 'background-color .3s ease',
|
||||
'&:hover': {
|
||||
backgroundColor: colors.gray[200],
|
||||
},
|
||||
},
|
||||
albumPlayButton: {
|
||||
color: colors.black,
|
||||
backgroundColor: colors.pink[500],
|
||||
borderRadius: '50%',
|
||||
boxShadow: '0 8px 8px rgb(0 0 0 / 30%)',
|
||||
padding: '0.35rem',
|
||||
transition: 'padding .3s ease',
|
||||
'&:hover': {
|
||||
background: `${colors.pink[500]} !important`,
|
||||
padding: '0.45rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
NDAlbumShow: {
|
||||
albumActions: musicListActions,
|
||||
},
|
||||
NDArtistShow: {
|
||||
actions: {
|
||||
padding: '2rem 0',
|
||||
alignItems: 'center',
|
||||
overflow: 'visible',
|
||||
minHeight: '120px',
|
||||
'@global': {
|
||||
button: {
|
||||
border: '1px solid transparent',
|
||||
backgroundColor: 'inherit',
|
||||
color: colors.gray[100],
|
||||
margin: '0 0.5rem',
|
||||
'&:hover': {
|
||||
border: `1px solid ${colors.gray[100]}`,
|
||||
backgroundColor: 'inherit !important',
|
||||
},
|
||||
},
|
||||
// Hide shuffle button label (first button)
|
||||
'button:first-child>span:first-child>span': {
|
||||
display: 'none',
|
||||
},
|
||||
// Style shuffle button (first button)
|
||||
'button:first-child': {
|
||||
'@media screen and (max-width: 720px)': {
|
||||
transform: 'scale(1.5)',
|
||||
margin: '1rem',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.6) !important',
|
||||
},
|
||||
},
|
||||
transform: 'scale(2)',
|
||||
margin: '1.5rem',
|
||||
minWidth: 0,
|
||||
padding: 5,
|
||||
transition: 'transform .3s ease',
|
||||
background: colors.pink[500],
|
||||
color: colors.white,
|
||||
borderRadius: 500,
|
||||
border: 0,
|
||||
'&:hover': {
|
||||
transform: 'scale(2.1)',
|
||||
backgroundColor: `${colors.pink[500]} !important`,
|
||||
border: 0,
|
||||
},
|
||||
},
|
||||
'button:first-child>span:first-child': {
|
||||
padding: 0,
|
||||
color: `${colors.black} !important`,
|
||||
},
|
||||
'button>span:first-child>span, button:not(:first-child)>span:first-child>svg':
|
||||
{
|
||||
color: colors.gray[100],
|
||||
},
|
||||
},
|
||||
},
|
||||
actionsContainer: {
|
||||
overflow: 'visible',
|
||||
},
|
||||
},
|
||||
NDAudioPlayer: {
|
||||
audioTitle: {
|
||||
color: colors.white,
|
||||
fontSize: '1.5rem',
|
||||
'& span:nth-child(3)': {
|
||||
fontSize: '0.8rem',
|
||||
},
|
||||
},
|
||||
songTitle: {
|
||||
fontWeight: 900,
|
||||
},
|
||||
songInfo: {
|
||||
fontSize: '0.9rem',
|
||||
color: colors.gray[100],
|
||||
},
|
||||
},
|
||||
NDCollapsibleComment: {
|
||||
commentBlock: {
|
||||
fontSize: '.875rem',
|
||||
color: `rgba(${colors.white}, 0.8)`,
|
||||
},
|
||||
},
|
||||
NDLogin: {
|
||||
main: {
|
||||
boxShadow: `inset 0 0 0 2000px rgba(${colors.black}, .75)`,
|
||||
},
|
||||
systemNameLink: {
|
||||
color: colors.white,
|
||||
},
|
||||
card: {
|
||||
border: `1px solid ${colors.gray[200]}`,
|
||||
},
|
||||
avatar: {
|
||||
marginBottom: 0,
|
||||
},
|
||||
},
|
||||
NDPlaylistDetails: {
|
||||
container: {
|
||||
background: `linear-gradient(${colors.gray[300]}, transparent)`,
|
||||
borderRadius: 0,
|
||||
paddingTop: '2.5rem !important',
|
||||
boxShadow: 'none',
|
||||
},
|
||||
title: {
|
||||
fontSize: 'calc(1.5rem + 1.5vw)',
|
||||
fontWeight: 700,
|
||||
color: colors.white,
|
||||
},
|
||||
details: {
|
||||
fontSize: '.875rem',
|
||||
color: `rgba(${colors.white}, 0.8)`,
|
||||
},
|
||||
},
|
||||
NDPlaylistShow: {
|
||||
playlistActions: musicListActions,
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Player configuration settings.
|
||||
* Specifies the player theme and associated stylesheet.
|
||||
* @type {Object}
|
||||
*/
|
||||
player: {
|
||||
theme: 'dark',
|
||||
stylesheet,
|
||||
},
|
||||
}
|
||||
89
ui/src/themes/amusic.css.js
Normal file
89
ui/src/themes/amusic.css.js
Normal file
@ -0,0 +1,89 @@
|
||||
const stylesheet = `
|
||||
.react-jinke-music-player-main svg:active, .react-jinke-music-player-main svg:hover {
|
||||
color: #D60017
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-handle,
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-track {
|
||||
background-color: #ff4e6b
|
||||
}
|
||||
.react-jinke-music-player-main ::-webkit-scrollbar-thumb,
|
||||
.react-jinke-music-player-mobile-progress .rc-slider-handle,
|
||||
.react-jinke-music-player-mobile-progress .rc-slider-track {
|
||||
background-color: #ff4e6b
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .rc-slider-handle:active {
|
||||
box-shadow: 0 0 2px #ff4e6b
|
||||
}
|
||||
.audio-lists-panel-content .audio-item.playing,
|
||||
.react-jinke-music-player-main .audio-item.playing svg,
|
||||
.react-jinke-music-player-main .group player-delete {
|
||||
color: #ff4e6b
|
||||
}
|
||||
.audio-lists-panel-content .audio-item:hover,
|
||||
.audio-lists-panel-content .audio-item:hover svg
|
||||
.audio-lists-panel-content .audio-item:active .group:not([class=".player-delete"]) svg, .audio-lists-panel-content .audio-item:hover .group:not([class=".player-delete"]) svg{
|
||||
color: #D60017
|
||||
}
|
||||
.react-jinke-music-player-main .audio-item.playing .player-singer {
|
||||
color: #ff4e6b !important
|
||||
}
|
||||
.react-jinke-music-player-main .lyric-btn,
|
||||
.react-jinke-music-player-main .lyric-btn-active svg{
|
||||
color: #ff4e6b !important
|
||||
}
|
||||
.react-jinke-music-player-main .lyric-btn-active {
|
||||
color: #D60017 !important
|
||||
}
|
||||
.react-jinke-music-player-main .loading svg {
|
||||
color: #ff4e6b !important
|
||||
}
|
||||
.react-jinke-music-player .music-player-controller .music-player-controller-setting{
|
||||
background: #ff4e6b4d
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-lyric{
|
||||
color: #ff4e6b !important;
|
||||
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel,
|
||||
.react-jinke-music-player-mobile,
|
||||
.ril__outer{
|
||||
background-color: #1f1f1f;
|
||||
border: 1px solid #fff1;
|
||||
}
|
||||
.ril__toolbar{
|
||||
background-color: #1d1d1d
|
||||
}
|
||||
.ril__toolbarItem{
|
||||
font-size: 100%;
|
||||
color: #eee
|
||||
}
|
||||
.audio-lists-panel{
|
||||
background-color: #1f1f1f;
|
||||
border: 1px solid #fff1;
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .img-rotate,
|
||||
.react-jinke-music-player-mobile .react-jinke-music-player-mobile-cover img.cover,
|
||||
.react-jinke-music-player-mobile-cover {
|
||||
border-radius: 6px !important;
|
||||
animation-duration: 0s !important
|
||||
}
|
||||
.react-jinke-music-player-main .music-player-panel .panel-content .img-content{
|
||||
width: 60px;
|
||||
height: 60px
|
||||
}
|
||||
.react-jinke-music-player-main .songTitle{
|
||||
color: #eee
|
||||
}
|
||||
.react-jinke-music-player .music-player-controller{
|
||||
color: #ff4e6b
|
||||
}
|
||||
.audio-lists-panel-mobile .audio-item:not(.audio-lists-panel-sortable-highlight-bg){
|
||||
background: unset
|
||||
}
|
||||
.lastfm-icon,
|
||||
.musicbrainz-icon{
|
||||
color: #eee
|
||||
}
|
||||
`
|
||||
export default stylesheet
|
||||
197
ui/src/themes/amusic.js
Normal file
197
ui/src/themes/amusic.js
Normal file
@ -0,0 +1,197 @@
|
||||
import stylesheet from './amusic.css.js'
|
||||
|
||||
export default {
|
||||
themeName: 'AMusic',
|
||||
typography: {
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, Apple Color Emoji, SF Pro, SF Pro Icons, Helvetica Neue, Helvetica, Arial, sans-serif',
|
||||
h6: {
|
||||
fontSize: '1rem', // AppBar title
|
||||
},
|
||||
h5: {
|
||||
fontSize: '2em',
|
||||
fontWeight: '600',
|
||||
},
|
||||
},
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#ff4e6b',
|
||||
},
|
||||
secondary: {
|
||||
main: '#D60017',
|
||||
contrastText: '#eee',
|
||||
},
|
||||
background: {
|
||||
default: '#1a1a1a',
|
||||
paper: '#1a1a1a',
|
||||
},
|
||||
type: 'dark',
|
||||
},
|
||||
overrides: {
|
||||
MuiFormGroup: {
|
||||
root: {
|
||||
color: 'white',
|
||||
},
|
||||
},
|
||||
MuiAppBar: {
|
||||
positionFixed: {
|
||||
backgroundColor: '#1d1d1d !important',
|
||||
boxShadow: 'none',
|
||||
borderBottom: '1px solid #fff1',
|
||||
},
|
||||
colorSecondary: {
|
||||
color: '#eee',
|
||||
},
|
||||
},
|
||||
MuiDrawer: {
|
||||
root: {
|
||||
background: '#1d1d1d',
|
||||
borderRight: '1px solid #fff1',
|
||||
},
|
||||
},
|
||||
MuiToolbar: {
|
||||
root: {
|
||||
background: 'transparent !important',
|
||||
},
|
||||
},
|
||||
MuiCardMedia: {
|
||||
img: {
|
||||
borderRadius: '10px',
|
||||
boxShadow: '5px 5px 20px #111',
|
||||
},
|
||||
},
|
||||
MuiButton: {
|
||||
root: {
|
||||
background: '#D60017',
|
||||
color: '#fff',
|
||||
borderRadius: '6px',
|
||||
paddingRight: '0.5rem',
|
||||
paddingLeft: '0.5rem',
|
||||
marginLeft: '0.5rem',
|
||||
marginBottom: '0.5rem',
|
||||
textTransform: 'capitalize',
|
||||
fontWeight: 600,
|
||||
},
|
||||
textPrimary: {
|
||||
color: '#eee',
|
||||
},
|
||||
textSecondary: {
|
||||
color: '#eee',
|
||||
backgroundColor: '#ff4e6b',
|
||||
},
|
||||
textSizeSmall: {
|
||||
fontSize: '0.8rem',
|
||||
paddingRight: '0.5rem',
|
||||
paddingLeft: '0.5rem',
|
||||
},
|
||||
label: {
|
||||
paddingRight: '1rem',
|
||||
paddingLeft: '0.7rem',
|
||||
},
|
||||
},
|
||||
MuiListItemIcon: {
|
||||
root: {
|
||||
color: '#ff4e6b',
|
||||
},
|
||||
},
|
||||
MuiChip: {
|
||||
root: {
|
||||
borderRadius: '6px',
|
||||
},
|
||||
},
|
||||
MuiIconButton: {
|
||||
root: {
|
||||
color: '#ff4e6b',
|
||||
},
|
||||
},
|
||||
MuiTableBody: {
|
||||
root: {
|
||||
'&>tr:nth-child(odd)': {
|
||||
background: 'rgba(255, 255, 255, 0.025)',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTableRow: {
|
||||
root: {
|
||||
background: 'transparent',
|
||||
},
|
||||
},
|
||||
MuiTableCell: {
|
||||
root: {
|
||||
borderBottom: '0 none !important',
|
||||
padding: '10px !important',
|
||||
color: '#b3b3b3 !important',
|
||||
},
|
||||
head: {
|
||||
color: '#b3b3b3 !important',
|
||||
},
|
||||
},
|
||||
MuiMenuItem: {
|
||||
root: {
|
||||
fontSize: '0.875rem',
|
||||
borderRadius: '10px',
|
||||
color: '#eee',
|
||||
},
|
||||
},
|
||||
NDAlbumGridView: {
|
||||
albumName: {
|
||||
color: '#eee',
|
||||
},
|
||||
albumSubtitle: {
|
||||
color: '#ccc',
|
||||
},
|
||||
albumPlayButton: {
|
||||
color: '#ff4e6b !important',
|
||||
},
|
||||
albumArtistName: {
|
||||
color: '#ff4e6b !important',
|
||||
},
|
||||
cover: {
|
||||
borderRadius: '10px !important',
|
||||
},
|
||||
},
|
||||
NDLogin: {
|
||||
systemNameLink: {
|
||||
color: '#D60017',
|
||||
},
|
||||
welcome: {
|
||||
color: '#eee',
|
||||
},
|
||||
card: {
|
||||
minWidth: 300,
|
||||
backgroundColor: '#1d1d1d',
|
||||
},
|
||||
},
|
||||
MuiPaper: {
|
||||
elevation1: {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
root: {
|
||||
color: '#eee',
|
||||
},
|
||||
},
|
||||
NDMobileArtistDetails: {
|
||||
bgContainer: {
|
||||
background: '#1a1a1a',
|
||||
},
|
||||
artistName: {
|
||||
fontWeight: '600',
|
||||
fontSize: '2em',
|
||||
},
|
||||
},
|
||||
NDDesktopArtistDetails: {
|
||||
artistName: {
|
||||
fontWeight: '600',
|
||||
fontSize: '2em',
|
||||
},
|
||||
artistDetail: {
|
||||
padding: 'unset',
|
||||
paddingBottom: '1rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
player: {
|
||||
theme: 'dark',
|
||||
stylesheet,
|
||||
},
|
||||
}
|
||||
@ -10,6 +10,8 @@ import NordTheme from './nord'
|
||||
import GruvboxDarkTheme from './gruvboxDark'
|
||||
import CatppuccinMacchiatoTheme from './catppuccinMacchiato'
|
||||
import NuclearTheme from './nuclear'
|
||||
import AmusicTheme from './amusic'
|
||||
import SquiddiesGlassTheme from './SquiddiesGlass'
|
||||
|
||||
export default {
|
||||
// Classic default themes
|
||||
@ -17,6 +19,7 @@ export default {
|
||||
DarkTheme,
|
||||
|
||||
// New themes should be added here, in alphabetic order
|
||||
AmusicTheme,
|
||||
CatppuccinMacchiatoTheme,
|
||||
ElectricPurpleTheme,
|
||||
ExtraDarkTheme,
|
||||
@ -27,4 +30,5 @@ export default {
|
||||
NordTheme,
|
||||
NuclearTheme,
|
||||
SpotifyTheme,
|
||||
SquiddiesGlassTheme,
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user