The sidebar's eleven entries are more than most libraries need, and Autotag rewrites tags on disk, which is not what a fresh install should be one click from. Stored as a map keyed by view id, where an absent key means that view's own default. A `HiddenViews []string` cannot express "Autotag off by default" -- its zero value is *hide nothing* -- and a boolean per view turns a view that later stops existing into stored garbage. With a map, an unknown key is dropped on load, a view added later gets its own default, and no install needs migrating in either direction. Same polarity as AllowMeteredCatalogDownload: the zero value is the intended answer. `Views` is also what DefaultPage now validates against, so which views exist and which may be the launch page are one list rather than two. Two states the user could not get out of are refused rather than allowed: Settings is never hideable, and the launch page is not hideable while it is the launch page. Both refuse in the *config*, not in the UI, because `config.toml` is hand-editable. On load the launch page is instead un-hidden -- there is nobody to tell, and the honest reading of "my launch page is Autotag" is that this user wants Autotag, not that their launch page should be silently reset.
90 lines
3.4 KiB
Go
90 lines
3.4 KiB
Go
package config
|
|
|
|
import "errors"
|
|
|
|
var (
|
|
errUnknownView = errors.New("unknown view")
|
|
errViewNotHideable = errors.New("view cannot be hidden")
|
|
errViewIsLaunchPage = errors.New("view is the launch page")
|
|
)
|
|
|
|
// View identifies one of the shell's primary destinations -- the
|
|
// things the sidebar lists and `index.ts` knows as `VIEW_TAGS`.
|
|
type View string
|
|
|
|
// The primary views, in no particular order: the sidebar owns the order
|
|
// it draws them in, because that is presentation.
|
|
const (
|
|
ViewHome View = "home"
|
|
ViewPlaylists View = "playlists"
|
|
ViewArtists View = "artists"
|
|
ViewGenres View = "genres"
|
|
ViewAlbums View = "albums"
|
|
ViewTracks View = "tracks"
|
|
ViewExplore View = "explore"
|
|
ViewDownloads View = "downloads"
|
|
ViewAutotag View = "autotag"
|
|
ViewJobs View = "jobs"
|
|
ViewSettings View = "settings"
|
|
)
|
|
|
|
// ViewSpec is what the backend knows about a destination. The label and
|
|
// the icon are deliberately absent: those are presentation, they live
|
|
// beside the rest of the app's icon vocabulary in
|
|
// `frontend/src/utils/icon-language.ts`, and a Go copy of them would be
|
|
// a second thing to keep in step for nothing.
|
|
type ViewSpec struct {
|
|
// ID is the view name the frontend navigates by.
|
|
ID View
|
|
// VisibleByDefault is what an install gets when the config says
|
|
// nothing about this view -- which is every install until somebody
|
|
// changes it, and every view added after this one shipped.
|
|
VisibleByDefault bool
|
|
// Hideable is false for Settings alone. It is a property of the
|
|
// view rather than a check in the setter because `config.toml` is
|
|
// hand-editable, and an app that can be locked out of its own
|
|
// Settings by a typo is a support problem nobody can debug
|
|
// remotely.
|
|
Hideable bool
|
|
// CanLaunch reports whether the view may be the launch page.
|
|
// Settings is the only one that may not, which is the shape the
|
|
// DefaultPage enum already had.
|
|
CanLaunch bool
|
|
}
|
|
|
|
// Views is the one list of primary destinations, in the order Settings
|
|
// offers them.
|
|
//
|
|
// It is the single source for three things that used to be written down
|
|
// separately: which views exist, which of them may be the launch page
|
|
// (`DefaultPage`'s validation reads it), and what an unconfigured
|
|
// install shows.
|
|
//
|
|
// Autotag is the one view hidden by default: it rewrites tags on disk,
|
|
// which is not what most libraries want on day one, and #25 asks for it
|
|
// to be turned on deliberately.
|
|
var Views = []ViewSpec{
|
|
{ID: ViewHome, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewPlaylists, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewArtists, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewGenres, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewAlbums, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewTracks, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewExplore, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewDownloads, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewAutotag, VisibleByDefault: false, Hideable: true, CanLaunch: true},
|
|
{ID: ViewJobs, VisibleByDefault: true, Hideable: true, CanLaunch: true},
|
|
{ID: ViewSettings, VisibleByDefault: true, Hideable: false, CanLaunch: false},
|
|
}
|
|
|
|
// LookupView returns the spec for a view id.
|
|
func LookupView(id string) (ViewSpec, bool) {
|
|
for _, v := range Views {
|
|
if string(v.ID) == id {
|
|
return v, true
|
|
}
|
|
}
|
|
|
|
return ViewSpec{}, false
|
|
}
|