Refactored scenery list logic
*Moved scenery list logic from SceneriesList to SceneryManager *Renamed SceneriesList to SceneryList *Updated InfoFooter texts -Removed sceneriesListService as it is not necessary anymore
This commit is contained in:
parent
e10b410f4f
commit
95ec3898ad
@ -1,4 +1,4 @@
|
|||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback, useEffect } from 'react';
|
||||||
import SceneryContext from '../contexts/SceneryContext';
|
import SceneryContext from '../contexts/SceneryContext';
|
||||||
import { useZoomPanEmitter } from '../hooks/useZoomPubSub';
|
import { useZoomPanEmitter } from '../hooks/useZoomPubSub';
|
||||||
import SceneryParser from '../model/scenery-parser';
|
import SceneryParser from '../model/scenery-parser';
|
||||||
@ -11,6 +11,7 @@ import Constants from '../helpers/constants';
|
|||||||
export default function SceneryManager(props) {
|
export default function SceneryManager(props) {
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [scenery, setScenery] = useState(null);
|
const [scenery, setScenery] = useState(null);
|
||||||
|
const [sceneryListData, setSceneryListData] = useState(null);
|
||||||
const { setCamera } = useZoomPanEmitter();
|
const { setCamera } = useZoomPanEmitter();
|
||||||
|
|
||||||
const myFetch = useCallback(async (url, toJson) => {
|
const myFetch = useCallback(async (url, toJson) => {
|
||||||
@ -23,13 +24,14 @@ export default function SceneryManager(props) {
|
|||||||
return toJson ? await response.json() : await response.blob();
|
return toJson ? await response.json() : await response.blob();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getSceneryList = useCallback(async () => {
|
const updateSceneryList = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const url = Constants.sceneryFiles.fetchListUrl;
|
const url = Constants.sceneryFiles.fetchListUrl;
|
||||||
return await myFetch(url, true);
|
const listData = await myFetch(url, true);
|
||||||
|
setSceneryListData(listData || null);
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
console.error(`Failed to fetch sceneries list`, error);
|
console.error(`Failed to fetch scenery list`, error);
|
||||||
return null;
|
setSceneryListData(null);
|
||||||
}
|
}
|
||||||
}, [myFetch]);
|
}, [myFetch]);
|
||||||
|
|
||||||
@ -84,8 +86,12 @@ export default function SceneryManager(props) {
|
|||||||
return await loadCustomScenery(file);
|
return await loadCustomScenery(file);
|
||||||
}, [myFetch, loadCustomScenery]);
|
}, [myFetch, loadCustomScenery]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(!Constants.sceneryFiles.fetchDisable) updateSceneryList();
|
||||||
|
}, [updateSceneryList]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SceneryContext.Provider value={{ isLoading, scenery, getSceneryList, loadScenery, loadCustomScenery }}>
|
<SceneryContext.Provider value={{ isLoading, scenery, sceneryListData, loadScenery, loadCustomScenery }}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</SceneryContext.Provider>
|
</SceneryContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,27 +1,20 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useContext } from 'react';
|
||||||
import { sceneriesListVersionDate$ } from "../../services/sceneriesListService";
|
|
||||||
import Constants from '../../helpers/constants';
|
import Constants from '../../helpers/constants';
|
||||||
|
import SceneryContext from '../../contexts/SceneryContext';
|
||||||
|
|
||||||
export default function InfoFooter() {
|
export default function InfoFooter() {
|
||||||
const [sceneriesVersionDate, setSceneriesVersionDate] = useState(null);
|
const { sceneryListData } = useContext(SceneryContext);
|
||||||
|
const sceneryListVersionDate = sceneryListData?.info?.versionDate || null;
|
||||||
|
|
||||||
useEffect(() => {
|
const sceneryListText = sceneryListVersionDate ?
|
||||||
const subscription = sceneriesListVersionDate$.subscribe(date => {
|
`included sceneries as of ${sceneryListVersionDate}` :
|
||||||
setSceneriesVersionDate(date);
|
'included sceneries not available';
|
||||||
});
|
|
||||||
|
|
||||||
return () => subscription.unsubscribe();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const sceneriesListText = sceneriesVersionDate ?
|
|
||||||
`included sceneries as of ${sceneriesVersionDate}` :
|
|
||||||
'included sceneries list not available';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="info-footer">
|
<div className="info-footer">
|
||||||
<span>TD2 Visualizer v{Constants.buildVersion}</span>
|
<span>TD2 Visualizer v{Constants.buildVersion}</span>
|
||||||
<span>masuo 2025.06</span>
|
<span>masuo 2025.06</span>
|
||||||
<span>{sceneriesListText}</span>
|
<span>{sceneryListText}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1,47 +0,0 @@
|
|||||||
import { useContext, useCallback, useState, useEffect } from 'react';
|
|
||||||
import SceneryContext from '../../contexts/SceneryContext';
|
|
||||||
import { setSceneriesListVersionDate } from '../../services/sceneriesListService';
|
|
||||||
import Constants from '../../helpers/constants';
|
|
||||||
|
|
||||||
export default function SceneriesList() {
|
|
||||||
const {getSceneryList, loadScenery} = useContext(SceneryContext);
|
|
||||||
const [ sceneriesListData, setSceneriesListData ] = useState(null);
|
|
||||||
|
|
||||||
const handleSelectChange = async (event) => {
|
|
||||||
const name = event.target.value;
|
|
||||||
if (!name) return;
|
|
||||||
await loadScenery(name);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateSceneryList = useCallback(async () => {
|
|
||||||
const sceneryListData = await getSceneryList();
|
|
||||||
setSceneriesListData(sceneryListData);
|
|
||||||
setSceneriesListVersionDate(sceneryListData?.info?.versionDate || null);
|
|
||||||
}, [getSceneryList]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if(Constants.sceneryFiles.fetchDisable) return;
|
|
||||||
updateSceneryList();
|
|
||||||
}, [updateSceneryList]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='sceneries-list'>
|
|
||||||
<select onChange={handleSelectChange} defaultValue="">
|
|
||||||
<option value="" disabled>Select a scenery</option>
|
|
||||||
{Array.isArray(sceneriesListData?.list) && sceneriesListData.list.map((name) => (
|
|
||||||
<SceneriesListOption key={name} name={name} />
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function SceneriesListOption({ name }) {
|
|
||||||
// remove .lite.sc or .sc
|
|
||||||
const regex = /\.(lite\.)?sc$/i;
|
|
||||||
const displayName = name.replace(regex, '');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<option value={name}>{displayName}</option>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
33
src/components/toolbar/SceneryList.js
Normal file
33
src/components/toolbar/SceneryList.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { useContext } from 'react';
|
||||||
|
import SceneryContext from '../../contexts/SceneryContext';
|
||||||
|
|
||||||
|
export default function SceneryList() {
|
||||||
|
const { sceneryListData, loadScenery} = useContext(SceneryContext);
|
||||||
|
|
||||||
|
const handleSelectChange = async (event) => {
|
||||||
|
const name = event.target.value;
|
||||||
|
if (!name) return;
|
||||||
|
await loadScenery(name);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='scenery-list'>
|
||||||
|
<select onChange={handleSelectChange} defaultValue="">
|
||||||
|
<option value="" disabled>Select a scenery</option>
|
||||||
|
{Array.isArray(sceneryListData?.list) && sceneryListData.list.map((name) => (
|
||||||
|
<SceneryListOption key={name} name={name} />
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SceneryListOption({ name }) {
|
||||||
|
// remove .lite.sc or .sc
|
||||||
|
const regex = /\.(lite\.)?sc$/i;
|
||||||
|
const displayName = name.replace(regex, '');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<option value={name}>{displayName}</option>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,15 +1,14 @@
|
|||||||
import React from 'react';
|
|
||||||
import './Toolbar.css';
|
import './Toolbar.css';
|
||||||
import LoadingIndicator from './LoadingIndicator';
|
import LoadingIndicator from './LoadingIndicator';
|
||||||
import CustomFileSelect from './CustomFileSelect';
|
import CustomFileSelect from './CustomFileSelect';
|
||||||
import SideMenuToggle from './SideMenuToggle';
|
import SideMenuToggle from './SideMenuToggle';
|
||||||
import SceneriesList from './SceneriesList';
|
import SceneryList from './SceneryList';
|
||||||
|
|
||||||
export default function Toolbar() {
|
export default function Toolbar() {
|
||||||
return (
|
return (
|
||||||
<div className='toolbar-cont'>
|
<div className='toolbar-cont'>
|
||||||
<div className='toolbar'>
|
<div className='toolbar'>
|
||||||
<SceneriesList />
|
<SceneryList />
|
||||||
or
|
or
|
||||||
<CustomFileSelect />
|
<CustomFileSelect />
|
||||||
<div className='toolbar-spacer'></div>
|
<div className='toolbar-spacer'></div>
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
import { BehaviorSubject } from 'rxjs';
|
|
||||||
|
|
||||||
export const sceneriesListVersionDate$ = new BehaviorSubject(null);
|
|
||||||
|
|
||||||
export function setSceneriesListVersionDate(versionDate) {
|
|
||||||
sceneriesListVersionDate$.next(versionDate);
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user