|
|
@ -2,14 +2,15 @@ import React, { useReducer, Reducer } from 'react'; |
|
|
|
import { ThemeProvider, CssBaseline, createMuiTheme } from '@material-ui/core'; |
|
|
|
import { ThemeProvider, CssBaseline, createMuiTheme } from '@material-ui/core'; |
|
|
|
import { grey } from '@material-ui/core/colors'; |
|
|
|
import { grey } from '@material-ui/core/colors'; |
|
|
|
import AppBar from './appbar/AppBar'; |
|
|
|
import AppBar from './appbar/AppBar'; |
|
|
|
import QueryWindow from './windows/query/QueryWindow'; |
|
|
|
import QueryWindow, { QueryWindowReducer } from './windows/query/QueryWindow'; |
|
|
|
import { NewTabProps } from './appbar/AddTabMenu'; |
|
|
|
import { NewTabProps } from './appbar/AddTabMenu'; |
|
|
|
import { newWindowState, newWindowReducer, WindowType } from './windows/Windows'; |
|
|
|
import { newWindowState, newWindowReducer, WindowType, Window } from './windows/Windows'; |
|
|
|
import ArtistWindow from './windows/artist/ArtistWindow'; |
|
|
|
import ArtistWindow from './windows/artist/ArtistWindow'; |
|
|
|
import AlbumWindow from './windows/album/AlbumWindow'; |
|
|
|
import AlbumWindow from './windows/album/AlbumWindow'; |
|
|
|
import TagWindow from './windows/tag/TagWindow'; |
|
|
|
import TagWindow from './windows/tag/TagWindow'; |
|
|
|
import SongWindow from './windows/song/SongWindow'; |
|
|
|
import SongWindow from './windows/song/SongWindow'; |
|
|
|
import ManageTagsWindow from './windows/manage_tags/ManageTagsWindow'; |
|
|
|
import ManageTagsWindow from './windows/manage_tags/ManageTagsWindow'; |
|
|
|
|
|
|
|
import { BrowserRouter, Switch, Route, useParams, Redirect } from 'react-router-dom'; |
|
|
|
var _ = require('lodash'); |
|
|
|
var _ = require('lodash'); |
|
|
|
|
|
|
|
|
|
|
|
const darkTheme = createMuiTheme({ |
|
|
|
const darkTheme = createMuiTheme({ |
|
|
@ -21,150 +22,56 @@ const darkTheme = createMuiTheme({ |
|
|
|
}, |
|
|
|
}, |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
export interface MainWindowState { |
|
|
|
function WindowContent(props: { |
|
|
|
tabStates: any[], |
|
|
|
type: WindowType, |
|
|
|
tabReducers: Reducer<any, any>[], |
|
|
|
}) { |
|
|
|
tabTypes: WindowType[], |
|
|
|
const { id } = useParams(); |
|
|
|
activeTab: number, |
|
|
|
return <Window type={props.type} stateOverride={id ? { "id": id } : {}} /> |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export enum MainWindowStateActions { |
|
|
|
|
|
|
|
SetActiveTab = "setActiveTab", |
|
|
|
|
|
|
|
DispatchToTab = "dispatchToTab", |
|
|
|
|
|
|
|
CloseTab = "closeTab", |
|
|
|
|
|
|
|
AddTab = "addTab", |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function MainWindowReducer(state: MainWindowState, action: any) { |
|
|
|
|
|
|
|
switch (action.type) { |
|
|
|
|
|
|
|
case MainWindowStateActions.SetActiveTab: |
|
|
|
|
|
|
|
return { ...state, activeTab: action.value } |
|
|
|
|
|
|
|
case MainWindowStateActions.CloseTab: |
|
|
|
|
|
|
|
const newSize = state.tabStates.length - 1; |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...state, |
|
|
|
|
|
|
|
tabStates: state.tabStates.filter((i: any, idx: number) => idx != action.idx), |
|
|
|
|
|
|
|
tabReducers: state.tabReducers.filter((i: any, idx: number) => idx != action.idx), |
|
|
|
|
|
|
|
tabTypes: state.tabTypes.filter((i: any, idx: number) => idx != action.idx), |
|
|
|
|
|
|
|
activeTab: state.activeTab >= (newSize - 1) ? (newSize - 1) : state.activeTab, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case MainWindowStateActions.AddTab: |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...state, |
|
|
|
|
|
|
|
tabStates: [...state.tabStates, action.tabState], |
|
|
|
|
|
|
|
tabReducers: [...state.tabReducers, action.tabReducer], |
|
|
|
|
|
|
|
tabTypes: [...state.tabTypes, action.tabType], |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case MainWindowStateActions.DispatchToTab: |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
...state, |
|
|
|
|
|
|
|
tabStates: state.tabStates.map((item: any, i: number) => { |
|
|
|
|
|
|
|
return i === action.idx ? |
|
|
|
|
|
|
|
state.tabReducers[i](item, action.tabAction) : |
|
|
|
|
|
|
|
item; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new Error("Unimplemented MainWindow state update.") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export default function MainWindow(props: any) { |
|
|
|
export default function MainWindow(props: any) { |
|
|
|
const [state, dispatch] = useReducer(MainWindowReducer, { |
|
|
|
const [windowState, windowDispatch] = useReducer( |
|
|
|
tabStates: [ |
|
|
|
QueryWindowReducer, |
|
|
|
newWindowState[WindowType.Query](), |
|
|
|
{ |
|
|
|
newWindowState[WindowType.Song](), |
|
|
|
editingQuery: false, |
|
|
|
newWindowState[WindowType.Album](), |
|
|
|
query: null, |
|
|
|
newWindowState[WindowType.Artist](), |
|
|
|
resultsForQuery: null, |
|
|
|
newWindowState[WindowType.Tag](), |
|
|
|
}, |
|
|
|
newWindowState[WindowType.ManageTags](), |
|
|
|
); |
|
|
|
], |
|
|
|
|
|
|
|
tabReducers: [ |
|
|
|
|
|
|
|
newWindowReducer[WindowType.Query], |
|
|
|
|
|
|
|
newWindowReducer[WindowType.Song], |
|
|
|
|
|
|
|
newWindowReducer[WindowType.Album], |
|
|
|
|
|
|
|
newWindowReducer[WindowType.Artist], |
|
|
|
|
|
|
|
newWindowReducer[WindowType.Tag], |
|
|
|
|
|
|
|
newWindowReducer[WindowType.ManageTags], |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
tabTypes: [ |
|
|
|
|
|
|
|
WindowType.Query, |
|
|
|
|
|
|
|
WindowType.Song, |
|
|
|
|
|
|
|
WindowType.Album, |
|
|
|
|
|
|
|
WindowType.Artist, |
|
|
|
|
|
|
|
WindowType.Tag, |
|
|
|
|
|
|
|
WindowType.ManageTags, |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
activeTab: 0 |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const windows = state.tabStates.map((tabState: any, i: number) => { |
|
|
|
|
|
|
|
const tabDispatch = (action: any) => { |
|
|
|
|
|
|
|
dispatch({ |
|
|
|
|
|
|
|
type: MainWindowStateActions.DispatchToTab, |
|
|
|
|
|
|
|
tabAction: action, |
|
|
|
|
|
|
|
idx: i |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (state.tabTypes[i]) { |
|
|
|
|
|
|
|
case WindowType.Query: |
|
|
|
|
|
|
|
return <QueryWindow |
|
|
|
|
|
|
|
state={tabState} |
|
|
|
|
|
|
|
dispatch={tabDispatch} |
|
|
|
|
|
|
|
mainDispatch={dispatch} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
case WindowType.Artist: |
|
|
|
|
|
|
|
return <ArtistWindow |
|
|
|
|
|
|
|
state={tabState} |
|
|
|
|
|
|
|
dispatch={tabDispatch} |
|
|
|
|
|
|
|
mainDispatch={dispatch} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
case WindowType.Album: |
|
|
|
|
|
|
|
return <AlbumWindow |
|
|
|
|
|
|
|
state={tabState} |
|
|
|
|
|
|
|
dispatch={tabDispatch} |
|
|
|
|
|
|
|
mainDispatch={dispatch} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
case WindowType.Tag: |
|
|
|
|
|
|
|
return <TagWindow |
|
|
|
|
|
|
|
state={tabState} |
|
|
|
|
|
|
|
dispatch={tabDispatch} |
|
|
|
|
|
|
|
mainDispatch={dispatch} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
case WindowType.Song: |
|
|
|
|
|
|
|
return <SongWindow |
|
|
|
|
|
|
|
state={tabState} |
|
|
|
|
|
|
|
dispatch={tabDispatch} |
|
|
|
|
|
|
|
mainDispatch={dispatch} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
case WindowType.ManageTags: |
|
|
|
|
|
|
|
return <ManageTagsWindow |
|
|
|
|
|
|
|
state={tabState} |
|
|
|
|
|
|
|
dispatch={tabDispatch} |
|
|
|
|
|
|
|
mainDispatch={dispatch} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new Error("Unimplemented window type"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return <ThemeProvider theme={darkTheme}> |
|
|
|
return <ThemeProvider theme={darkTheme}> |
|
|
|
<CssBaseline /> |
|
|
|
<CssBaseline /> |
|
|
|
|
|
|
|
<BrowserRouter> |
|
|
|
<AppBar |
|
|
|
<AppBar |
|
|
|
tabLabels={state.tabStates.map((s: any) => s.tabLabel)} |
|
|
|
tabLabels={[]} |
|
|
|
selectedTab={state.activeTab} |
|
|
|
selectedTab={0} |
|
|
|
setSelectedTab={(t: number) => dispatch({ type: MainWindowStateActions.SetActiveTab, value: t })} |
|
|
|
setSelectedTab={(t: number) => { }} |
|
|
|
onCloseTab={(t: number) => dispatch({ type: MainWindowStateActions.CloseTab, idx: t })} |
|
|
|
onCloseTab={(t: number) => { }} |
|
|
|
onAddTab={(w: NewTabProps) => { |
|
|
|
onAddTab={(w: NewTabProps) => { }} |
|
|
|
dispatch({ |
|
|
|
|
|
|
|
type: MainWindowStateActions.AddTab, |
|
|
|
|
|
|
|
tabState: newWindowState[w.windowType](), |
|
|
|
|
|
|
|
tabReducer: newWindowReducer[w.windowType], |
|
|
|
|
|
|
|
tabType: w.windowType, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
}} |
|
|
|
|
|
|
|
/> |
|
|
|
/> |
|
|
|
{windows[state.activeTab]} |
|
|
|
<Switch> |
|
|
|
|
|
|
|
<Route exact path="/"> |
|
|
|
|
|
|
|
<Redirect to={"/query"} /> |
|
|
|
|
|
|
|
</Route> |
|
|
|
|
|
|
|
<Route path="/query"> |
|
|
|
|
|
|
|
<WindowContent type={WindowType.Query} /> |
|
|
|
|
|
|
|
</Route> |
|
|
|
|
|
|
|
<Route path="/artist/:id"> |
|
|
|
|
|
|
|
<WindowContent type={WindowType.Artist} /> |
|
|
|
|
|
|
|
</Route> |
|
|
|
|
|
|
|
<Route path="/tag/:id"> |
|
|
|
|
|
|
|
<WindowContent type={WindowType.Tag} /> |
|
|
|
|
|
|
|
</Route> |
|
|
|
|
|
|
|
<Route path="/album/:id"> |
|
|
|
|
|
|
|
<WindowContent type={WindowType.Album} /> |
|
|
|
|
|
|
|
</Route> |
|
|
|
|
|
|
|
<Route path="/song/:id"> |
|
|
|
|
|
|
|
<WindowContent type={WindowType.Song} /> |
|
|
|
|
|
|
|
</Route> |
|
|
|
|
|
|
|
<Route path="/tags"> |
|
|
|
|
|
|
|
<WindowContent type={WindowType.ManageTags} /> |
|
|
|
|
|
|
|
</Route> |
|
|
|
|
|
|
|
</Switch> |
|
|
|
|
|
|
|
</BrowserRouter> |
|
|
|
</ThemeProvider> |
|
|
|
</ThemeProvider> |
|
|
|
} |
|
|
|
} |