@ -1482,6 +1482,93 @@ function _invalidateListenBrainzCache() {
}
}
const PROFILE _PAGE _LABELS = {
dashboard : 'Dashboard' ,
sync : 'Sync' ,
search : 'Search' ,
discover : 'Discover' ,
watchlist : 'Watchlist' ,
wishlist : 'Wishlist' ,
automations : 'Automations' ,
'active-downloads' : 'Downloads' ,
library : 'Library' ,
stats : 'Listening Stats' ,
'playlist-explorer' : 'Playlist Explorer' ,
import : 'Import' ,
tools : 'Tools' ,
hydrabase : 'Hydrabase' ,
issues : 'Issues' ,
help : 'Help & Docs' ,
settings : 'Settings' ,
'artist-detail' : 'Artist Detail' ,
} ;
function getProfilePageLabel ( pageId ) {
return PROFILE _PAGE _LABELS [ pageId ] || pageId . split ( '-' ) . map ( part => part ? part [ 0 ] . toUpperCase ( ) + part . slice ( 1 ) : part ) . join ( ' ' ) ;
}
function getProfilePageSelectOptions ( profileSettings = { } ) {
const options = [ ] ;
const seen = new Set ( ) ;
const homeSelect = document . getElementById ( 'new-profile-home-page' ) ;
if ( homeSelect ) {
homeSelect . querySelectorAll ( 'option' ) . forEach ( option => {
if ( ! option . value || seen . has ( option . value ) ) return ;
options . push ( {
value : option . value ,
label : option . textContent ? . trim ( ) || getProfilePageLabel ( option . value ) ,
} ) ;
seen . add ( option . value ) ;
} ) ;
}
if ( profileSettings . home _page && ! seen . has ( profileSettings . home _page ) ) {
options . push ( {
value : profileSettings . home _page ,
label : getProfilePageLabel ( profileSettings . home _page ) ,
} ) ;
seen . add ( profileSettings . home _page ) ;
}
return options ;
}
function getProfilePageAccessOptions ( profileSettings = { } ) {
const options = [ ] ;
const seen = new Set ( ) ;
const allowedSet = Array . isArray ( profileSettings . allowed _pages ) ? new Set ( profileSettings . allowed _pages ) : null ;
const accessContainer = document . getElementById ( 'new-profile-allowed-pages' ) ;
if ( accessContainer ) {
accessContainer . querySelectorAll ( 'input[type="checkbox"]' ) . forEach ( cb => {
if ( seen . has ( cb . value ) ) return ;
options . push ( {
value : cb . value ,
label : cb . parentElement ? . textContent ? . trim ( ) || getProfilePageLabel ( cb . value ) ,
checked : cb . disabled ? true : ( allowedSet ? allowedSet . has ( cb . value ) : true ) ,
disabled : cb . disabled ,
} ) ;
seen . add ( cb . value ) ;
} ) ;
}
if ( allowedSet ) {
allowedSet . forEach ( pageId => {
if ( seen . has ( pageId ) ) return ;
options . push ( {
value : pageId ,
label : getProfilePageLabel ( pageId ) ,
checked : true ,
disabled : false ,
} ) ;
seen . add ( pageId ) ;
} ) ;
}
return options ;
}
function initProfileManagement ( ) {
const manageBtn = document . getElementById ( 'manage-profiles-btn' ) ;
const closeBtn = document . getElementById ( 'profile-manage-close' ) ;
@ -1698,11 +1785,8 @@ function showProfileEditForm(profileId, currentName, currentColor, currentAvatar
const isAdmin = currentProfile && currentProfile . is _admin ;
const isEditingAdmin = profileSettings . is _admin ;
const editColors = [ '#6366f1' , '#ec4899' , '#10b981' , '#f59e0b' , '#3b82f6' , '#ef4444' , '#8b5cf6' , '#14b8a6' ] ;
const pageLabels = {
dashboard : 'Dashboard' , sync : 'Sync' , search : 'Search' , discover : 'Discover' ,
automations : 'Automations' , library : 'Library' , stats : 'Listening Stats' ,
'playlist-explorer' : 'Playlist Explorer' , import : 'Import' , help : 'Help & Docs'
} ;
const pageSelectOptions = getProfilePageSelectOptions ( profileSettings ) ;
const pageAccessOptions = getProfilePageAccessOptions ( profileSettings ) ;
const form = document . createElement ( 'div' ) ;
form . id = 'profile-edit-form' ;
@ -1752,14 +1836,12 @@ function showProfileEditForm(profileId, currentName, currentColor, currentAvatar
defaultOpt . value = '' ;
defaultOpt . textContent = isEditingAdmin ? 'Default (Dashboard)' : 'Default (Discover)' ;
homeSelect . appendChild ( defaultOpt ) ;
const allowedSet = profileSettings . allowed _pages ;
const normalizedHome = profileSettings . home _page ;
Object . entries ( pageLabels ) . forEach ( ( [ id , label ] ) => {
if ( allowedSet && ! allowedSet . includes ( id ) ) return ; // Skip non-permitted
pageSelectOptions . forEach ( ( { value , label } ) => {
const opt = document . createElement ( 'option' ) ;
opt . value = id ;
opt . value = value ;
opt . textContent = label ;
if ( id === normalizedHome ) opt . selected = true ;
if ( value === normalizedHome ) opt . selected = true ;
homeSelect . appendChild ( opt ) ;
} ) ;
form . appendChild ( homeSelect ) ;
@ -1775,26 +1857,18 @@ function showProfileEditForm(profileId, currentName, currentColor, currentAvatar
const apContainer = document . createElement ( 'div' ) ;
apContainer . className = 'profile-page-checkboxes' ;
Object . entries ( pageLabels ) . forEach ( ( [ id , label ] ) => {
pageAccessOptions . forEach ( ( { value , label , checked , disabled } ) => {
const lbl = document . createElement ( 'label' ) ;
const cb = document . createElement ( 'input' ) ;
cb . type = 'checkbox' ;
cb . value = id ;
cb . checked = ! allowedSet || allowedSet . includes ( id ) ;
cb . value = value ;
cb . checked = checked ;
cb . disabled = disabled ;
lbl . appendChild ( cb ) ;
lbl . appendChild ( document . createTextNode ( ' ' + label ) ) ;
apContainer . appendChild ( lbl ) ;
pageCheckboxes . push ( cb ) ;
} ) ;
// Always-on help
const helpLbl = document . createElement ( 'label' ) ;
const helpCb = document . createElement ( 'input' ) ;
helpCb . type = 'checkbox' ;
helpCb . checked = true ;
helpCb . disabled = true ;
helpLbl . appendChild ( helpCb ) ;
helpLbl . appendChild ( document . createTextNode ( ' Help & Docs' ) ) ;
apContainer . appendChild ( helpLbl ) ;
form . appendChild ( apContainer ) ;
const dlLabel = document . createElement ( 'label' ) ;
@ -1824,8 +1898,9 @@ function showProfileEditForm(profileId, currentName, currentColor, currentAvatar
// Admin-only fields
if ( isAdmin && ! isEditingAdmin && pageCheckboxes . length ) {
const allChecked = pageCheckboxes . every ( cb => cb . checked ) ;
payload . allowed _pages = allChecked ? null : pageCheckboxes . filter ( cb => cb . checked ) . map ( cb => cb . value ) ;
const editablePageCheckboxes = pageCheckboxes . filter ( cb => ! cb . disabled ) ;
const allChecked = editablePageCheckboxes . every ( cb => cb . checked ) ;
payload . allowed _pages = allChecked ? null : editablePageCheckboxes . filter ( cb => cb . checked ) . map ( cb => cb . value ) ;
payload . can _download = canDlCheckbox ? canDlCheckbox . checked : true ;
}
@ -1921,14 +1996,12 @@ function showSelfEditForm() {
defaultOpt . value = '' ;
defaultOpt . textContent = 'Default (Discover)' ;
homeSelect . appendChild ( defaultOpt ) ;
const ap = currentProfile . allowed _pages ;
const normalizedHome = currentProfile . home _page ;
Object . entries ( pageLabels ) . forEach ( ( [ id , label ] ) => {
if ( ap && ! ap . includes ( id ) ) return ;
getProfilePageSelectOptions ( { home _page : normalizedHome } ) . forEach ( ( { value , label } ) => {
const opt = document . createElement ( 'option' ) ;
opt . value = id ;
opt . value = value ;
opt . textContent = label ;
if ( id === normalizedHome ) opt . selected = true ;
if ( value === normalizedHome ) opt . selected = true ;
homeSelect . appendChild ( opt ) ;
} ) ;
form . appendChild ( homeSelect ) ;