diff --git a/index.html b/index.html index 002d008..185867d 100644 --- a/index.html +++ b/index.html @@ -117,7 +117,7 @@ ui: { // If true, player markers will always be displayed in front of other marker types - playersAboveMarkers: false + playersAboveMarkers: true } }; diff --git a/src/api.ts b/src/api.ts index 3ecba90..a3d2aea 100644 --- a/src/api.ts +++ b/src/api.ts @@ -33,7 +33,7 @@ import { } from "@/dynmap"; import {useStore} from "@/store"; import ChatError from "@/errors/ChatError"; -import {LiveAtlasMessageConfig, LiveAtlasWorld} from "@/index"; +import {LiveAtlasServerMessageConfig, LiveAtlasWorld} from "@/index"; const titleColours = /ยง[0-9a-f]/ig; @@ -56,48 +56,17 @@ function buildServerConfig(response: any): DynmapServerConfig { }; } -function buildMessagesConfig(response: any): LiveAtlasMessageConfig { - const liveAtlasMessages = window.liveAtlasConfig?.messages || {}; - +function buildMessagesConfig(response: any): LiveAtlasServerMessageConfig { return { chatPlayerJoin: response.joinmessage || '', chatPlayerQuit: response.quitmessage || '', chatAnonymousJoin: response['msg-hiddennamejoin'] || '', chatAnonymousQuit: response['msg-hiddennamequit'] || '', - chatTitle: liveAtlasMessages.chatTitle || '', - chatLogin: liveAtlasMessages.chatLogin || '', - chatLoginLink: liveAtlasMessages.chatLoginLink || '', - chatNoMessages: liveAtlasMessages.chatNoMessages || '', - chatSend: liveAtlasMessages.chatSend || '', - chatPlaceholder: liveAtlasMessages.chatPlaceholder || '', chatErrorNotAllowed: response['msg-chatnotallowed'] || '', chatErrorRequiresLogin: response['msg-chatrequireslogin'] || '', chatErrorCooldown: response.spammessage || '', - chatErrorDisabled: liveAtlasMessages.chatErrorDisabled || '', - chatErrorUnknown: liveAtlasMessages.chatErrorUnknown || '', - serversHeading: liveAtlasMessages.serversHeading || '', worldsHeading: response['msg-maptypes'] || '', - worldsSkeleton: liveAtlasMessages.worldsSkeleton || '', playersHeading: response['msg-players'] || '', - playersSkeleton: liveAtlasMessages.playersSkeleton || '', - playersTitle: liveAtlasMessages.playersTitle || '', - playersTitleHidden: liveAtlasMessages.playersTitleHidden || '', - playersTitleOtherWorld: liveAtlasMessages.playersTitleOtherWorld || '', - followingHeading: liveAtlasMessages.followingHeading || '', - followingHidden: liveAtlasMessages.followingHidden || '', - followingUnfollow: liveAtlasMessages.followingUnfollow || '', - followingTitleUnfollow: liveAtlasMessages.followingTitleUnfollow || '', - linkTitle: liveAtlasMessages.linkTitle || '', - loadingTitle: liveAtlasMessages.loadingTitle || '', - locationRegion: liveAtlasMessages.locationRegion || '', - locationChunk: liveAtlasMessages.locationChunk || '', - contextMenuCopyLink: liveAtlasMessages.contextMenuCopyLink || '', - contextMenuCenterHere: liveAtlasMessages.contextMenuCenterHere || '', - toggleTitle: liveAtlasMessages.toggleTitle || '', - mapTitle: liveAtlasMessages.mapTitle || '', - layersTitle: liveAtlasMessages.layersTitle || '', - copyToClipboardSuccess: liveAtlasMessages.copyToClipboardSuccess || '', - copyToClipboardError: liveAtlasMessages.copyToClipboardError || '', } } diff --git a/src/dynmap.d.ts b/src/dynmap.d.ts index 24cc351..4734b05 100644 --- a/src/dynmap.d.ts +++ b/src/dynmap.d.ts @@ -18,13 +18,18 @@ import {PathOptions, PointTuple, PolylineOptions} from "leaflet"; import {CoordinatesControlOptions} from "@/leaflet/control/CoordinatesControl"; import {LogoControlOptions} from "@/leaflet/control/LogoControl"; import {ClockControlOptions} from "@/leaflet/control/ClockControl"; -import {Coordinate, LiveAtlasLocation, LiveAtlasMessageConfig, LiveAtlasWorld, LiveAtlasWorldState} from "@/index"; +import { + Coordinate, + LiveAtlasLocation, + LiveAtlasServerMessageConfig, + LiveAtlasWorld, + LiveAtlasWorldState +} from "@/index"; declare global { // noinspection JSUnusedGlobalSymbols interface Window { config: { url: DynmapUrlConfig }; - liveAtlasConfig: any, } } @@ -96,7 +101,7 @@ interface DynmapChatSendingConfig { interface DynmapConfigurationResponse { config: DynmapServerConfig, - messages: LiveAtlasMessageConfig, + messages: LiveAtlasServerMessageConfig, worlds: Array, components: DynmapComponentConfig, loggedIn: boolean, diff --git a/src/index.d.ts b/src/index.d.ts index 1ac7258..b3aa086 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -12,6 +12,13 @@ declare module '*.vue' { export default component } +declare global { + // noinspection JSUnusedGlobalSymbols + interface Window { + liveAtlasConfig: LiveAtlasGlobalConfig, + } +} + interface Coordinate { x: number; y: number; @@ -25,6 +32,12 @@ interface LiveAtlasLocation { world?: string; } +interface LiveAtlasGlobalConfig { + servers: Map; + messages: LiveAtlasGlobalMessageConfig; + ui: LiveAtlasUIConfig; +} + interface LiveAtlasServerDefinition { id: string label?: string @@ -35,27 +48,19 @@ interface LiveAtlasDynmapServerDefinition extends LiveAtlasServerDefinition { dynmap: DynmapUrlConfig, } -interface LiveAtlasMessageConfig { - chatPlayerJoin: string; - chatPlayerQuit: string; - chatAnonymousJoin: string; - chatAnonymousQuit: string; +// Messages defined directly in LiveAtlas and used for all servers +interface LiveAtlasGlobalMessageConfig { chatNoMessages: string; chatTitle: string; chatLogin: string; chatLoginLink: string; chatSend: string; chatPlaceholder: string; - chatErrorNotAllowed: string; - chatErrorRequiresLogin: string; - chatErrorCooldown: string; chatErrorDisabled: string; chatErrorUnknown: string; serversHeading: string; - worldsHeading: string; worldsSkeleton: string; playersSkeleton: string; - playersHeading: string; playersTitle: string; playersTitleHidden: string; playersTitleOtherWorld: string; @@ -76,6 +81,25 @@ interface LiveAtlasMessageConfig { copyToClipboardError: string; } +// Messages defined by dynmap configuration responses and can vary per server +interface LiveAtlasServerMessageConfig { + chatPlayerJoin: string; + chatPlayerQuit: string; + chatAnonymousJoin: string; + chatAnonymousQuit: string; + chatErrorNotAllowed: string; + chatErrorRequiresLogin: string; + chatErrorCooldown: string; + worldsHeading: string; + playersHeading: string; +} + +type LiveAtlasMessageConfig = LiveAtlasGlobalMessageConfig & LiveAtlasServerMessageConfig; + +interface LiveAtlasUIConfig { + playersAboveMarkers: boolean; +} + export type LiveAtlasUIElement = 'layers' | 'chat' | 'players' | 'maps' | 'settings'; export type LiveAtlasSidebarSection = 'servers' | 'players' | 'maps'; diff --git a/src/main.ts b/src/main.ts index 2f88fef..67368c2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -24,10 +24,10 @@ import '@/scss/style.scss'; import 'focus-visible'; import {MutationTypes} from "@/store/mutation-types"; -import {validateConfiguration} from "@/util/config"; import {showSplashError} from "@/util/splash"; import { VueClipboard } from '@soerenmartius/vue3-clipboard'; import Notifications from '@kyvg/vue3-notification' +import {getServerDefinitions} from "@/util/config"; const splash = document.getElementById('splash'), svgs = import.meta.globEager('/assets/icons/*.svg'); @@ -49,14 +49,14 @@ store.subscribe((mutation, state) => { }); try { - const config = validateConfiguration(); + const config = window.liveAtlasConfig; + config.servers = getServerDefinitions(config); - store.commit(MutationTypes.INIT, undefined); - store.commit(MutationTypes.SET_SERVERS, config); + store.commit(MutationTypes.INIT, config); - if(config.size > 1) { + if(store.state.servers.size > 1) { const lastSegment = window.location.pathname.split('/').pop(), - serverName = lastSegment && config.has(lastSegment) ? lastSegment : config.keys().next().value; + serverName = lastSegment && store.state.servers.has(lastSegment) ? lastSegment : store.state.servers.keys().next().value; //Update url if server doesn't exist if(serverName !== lastSegment) { @@ -65,7 +65,7 @@ try { store.commit(MutationTypes.SET_CURRENT_SERVER, serverName); } else { - store.commit(MutationTypes.SET_CURRENT_SERVER, config.keys().next().value); + store.commit(MutationTypes.SET_CURRENT_SERVER, store.state.servers.keys().next().value); } const app = createApp(App) diff --git a/src/store/actions.ts b/src/store/actions.ts index 58ad40c..c0e1646 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -80,12 +80,12 @@ export interface Actions { export const actions: ActionTree & Actions = { async [ActionTypes.LOAD_CONFIGURATION]({commit, state}): Promise { //Clear any existing has to avoid triggering a second config load, after this load changes the hash - commit(MutationTypes.CLEAR_CONFIGURATION_HASH, undefined); + commit(MutationTypes.CLEAR_SERVER_CONFIGURATION_HASH, undefined); const config = await getAPI().getConfiguration(); - commit(MutationTypes.SET_CONFIGURATION, config.config); - commit(MutationTypes.SET_MESSAGES, config.messages); + commit(MutationTypes.SET_SERVER_CONFIGURATION, config.config); + commit(MutationTypes.SET_SERVER_MESSAGES, config.messages); commit(MutationTypes.SET_WORLDS, config.worlds); commit(MutationTypes.SET_COMPONENTS, config.components); commit(MutationTypes.SET_LOGGED_IN, config.loggedIn); @@ -159,7 +159,7 @@ export const actions: ActionTree & Actions = { commit(MutationTypes.ADD_MARKER_SET_UPDATES, update.updates.markerSets); commit(MutationTypes.ADD_TILE_UPDATES, update.updates.tiles); commit(MutationTypes.ADD_CHAT, update.updates.chat); - commit(MutationTypes.SET_CONFIGURATION_HASH, update.configHash); + commit(MutationTypes.SET_SERVER_CONFIGURATION_HASH, update.configHash); await dispatch(ActionTypes.SET_PLAYERS, update.players); return update; diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts index bf26145..d992dbb 100644 --- a/src/store/mutation-types.ts +++ b/src/store/mutation-types.ts @@ -17,11 +17,10 @@ export enum MutationTypes { INIT ='init', - SET_SERVERS ='setServers', - SET_CONFIGURATION = 'setConfiguration', - SET_CONFIGURATION_HASH = 'setConfigurationHash', - CLEAR_CONFIGURATION_HASH = 'clearConfigurationHash', - SET_MESSAGES = 'setMessages', + SET_SERVER_CONFIGURATION = 'setServerConfiguration', + SET_SERVER_CONFIGURATION_HASH = 'setServerConfigurationHash', + CLEAR_SERVER_CONFIGURATION_HASH = 'clearServerConfigurationHash', + SET_SERVER_MESSAGES = 'setServerMessages', SET_WORLDS = 'setWorlds', CLEAR_WORLDS = 'clearWorlds', SET_COMPONENTS = 'setComponents', @@ -66,4 +65,4 @@ export enum MutationTypes { SET_SIDEBAR_SECTION_COLLAPSED_STATE = 'setSidebarSectionCollapsedState', SET_LOGGED_IN = 'setLoggedIn', -} \ No newline at end of file +} diff --git a/src/store/mutations.ts b/src/store/mutations.ts index fb252cf..96dbcd5 100644 --- a/src/store/mutations.ts +++ b/src/store/mutations.ts @@ -30,12 +30,16 @@ import { } from "@/dynmap"; import {DynmapProjection} from "@/leaflet/projection/DynmapProjection"; import { - Coordinate, LiveAtlasWorldState, - LiveAtlasMessageConfig, - LiveAtlasServerDefinition, + Coordinate, + LiveAtlasWorldState, LiveAtlasSidebarSection, LiveAtlasSortedPlayers, - LiveAtlasUIElement, LiveAtlasWorld, LiveAtlasParsedUrl + LiveAtlasUIElement, + LiveAtlasWorld, + LiveAtlasParsedUrl, + LiveAtlasGlobalConfig, + LiveAtlasGlobalMessageConfig, + LiveAtlasServerMessageConfig } from "@/index"; export type CurrentMapPayload = { @@ -44,12 +48,11 @@ export type CurrentMapPayload = { } export type Mutations = { - [MutationTypes.INIT](state: S): void - [MutationTypes.SET_SERVERS](state: S, servers: Map): void - [MutationTypes.SET_CONFIGURATION](state: S, config: DynmapServerConfig): void - [MutationTypes.SET_CONFIGURATION_HASH](state: S, hash: number): void - [MutationTypes.CLEAR_CONFIGURATION_HASH](state: S): void - [MutationTypes.SET_MESSAGES](state: S, messages: LiveAtlasMessageConfig): void + [MutationTypes.INIT](state: S, config: LiveAtlasGlobalConfig): void + [MutationTypes.SET_SERVER_CONFIGURATION](state: S, config: DynmapServerConfig): void + [MutationTypes.SET_SERVER_CONFIGURATION_HASH](state: S, hash: number): void + [MutationTypes.CLEAR_SERVER_CONFIGURATION_HASH](state: S): void + [MutationTypes.SET_SERVER_MESSAGES](state: S, messages: LiveAtlasServerMessageConfig): void [MutationTypes.SET_WORLDS](state: S, worlds: Array): void [MutationTypes.CLEAR_WORLDS](state: S): void [MutationTypes.SET_COMPONENTS](state: S, worlds: DynmapComponentConfig): void @@ -96,17 +99,54 @@ export type Mutations = { } export const mutations: MutationTree & Mutations = { - [MutationTypes.INIT](state: State) { - const collapsedSections = localStorage.getItem('collapsedSections'); + [MutationTypes.INIT](state: State, config: LiveAtlasGlobalConfig) { + const collapsedSections = localStorage.getItem('collapsedSections'), + messageConfig = config?.messages || {}, + uiConfig = config?.ui || {}; if(collapsedSections) { state.ui.sidebar.collapsedSections = new Set(JSON.parse(collapsedSections)); } - }, - // Sets configuration options from the initial config fetch - [MutationTypes.SET_SERVERS](state: State, config: Map) { - state.servers = config; + const messages: LiveAtlasGlobalMessageConfig = { + chatTitle: messageConfig.chatTitle || '', + chatLogin: messageConfig.chatLogin || '', + chatLoginLink: messageConfig.chatLoginLink || '', + chatNoMessages: messageConfig.chatNoMessages || '', + chatSend: messageConfig.chatSend || '', + chatPlaceholder: messageConfig.chatPlaceholder || '', + chatErrorDisabled: messageConfig.chatErrorDisabled || '', + chatErrorUnknown: messageConfig.chatErrorUnknown || '', + serversHeading: messageConfig.serversHeading || '', + worldsSkeleton: messageConfig.worldsSkeleton || '', + playersSkeleton: messageConfig.playersSkeleton || '', + playersTitle: messageConfig.playersTitle || '', + playersTitleHidden: messageConfig.playersTitleHidden || '', + playersTitleOtherWorld: messageConfig.playersTitleOtherWorld || '', + followingHeading: messageConfig.followingHeading || '', + followingHidden: messageConfig.followingHidden || '', + followingUnfollow: messageConfig.followingUnfollow || '', + followingTitleUnfollow: messageConfig.followingTitleUnfollow || '', + linkTitle: messageConfig.linkTitle || '', + loadingTitle: messageConfig.loadingTitle || '', + locationRegion: messageConfig.locationRegion || '', + locationChunk: messageConfig.locationChunk || '', + contextMenuCopyLink: messageConfig.contextMenuCopyLink || '', + contextMenuCenterHere: messageConfig.contextMenuCenterHere || '', + toggleTitle: messageConfig.toggleTitle || '', + mapTitle: messageConfig.mapTitle || '', + layersTitle: messageConfig.layersTitle || '', + copyToClipboardSuccess: messageConfig.copyToClipboardSuccess || '', + copyToClipboardError: messageConfig.copyToClipboardError || '', + } + + state.messages = Object.assign(state.messages, messages); + + if(typeof uiConfig.playersAboveMarkers === 'boolean') { + state.ui.playersAboveMarkers = uiConfig.playersAboveMarkers; + } + + state.servers = config.servers; if(state.currentServer && !state.servers.has(state.currentServer.id)) { state.currentServer = undefined; @@ -114,23 +154,23 @@ export const mutations: MutationTree & Mutations = { }, // Sets configuration options from the initial config fetch - [MutationTypes.SET_CONFIGURATION](state: State, config: DynmapServerConfig) { + [MutationTypes.SET_SERVER_CONFIGURATION](state: State, config: DynmapServerConfig) { state.configuration = Object.assign(state.configuration, config); state.configurationHash = config.hash; }, // Sets configuration hash - [MutationTypes.SET_CONFIGURATION_HASH](state: State, hash: number) { + [MutationTypes.SET_SERVER_CONFIGURATION_HASH](state: State, hash: number) { state.configurationHash = hash; }, // Sets configuration hash - [MutationTypes.CLEAR_CONFIGURATION_HASH](state: State) { + [MutationTypes.CLEAR_SERVER_CONFIGURATION_HASH](state: State) { state.configurationHash = undefined; }, - //Set messages from the initial config fetch - [MutationTypes.SET_MESSAGES](state: State, messages: LiveAtlasMessageConfig) { + // Sets messages from the initial config fetch + [MutationTypes.SET_SERVER_MESSAGES](state: State, messages: LiveAtlasServerMessageConfig) { state.messages = Object.assign(state.messages, messages); }, diff --git a/src/store/state.ts b/src/store/state.ts index 2fc5824..e9f6f62 100644 --- a/src/store/state.ts +++ b/src/store/state.ts @@ -22,12 +22,16 @@ import { } from "@/dynmap"; import {DynmapProjection} from "@/leaflet/projection/DynmapProjection"; import { - Coordinate, LiveAtlasWorldState, - LiveAtlasMessageConfig, + Coordinate, + LiveAtlasWorldState, LiveAtlasServerDefinition, LiveAtlasSidebarSection, LiveAtlasSortedPlayers, - LiveAtlasUIElement, LiveAtlasWorld, LiveAtlasWorldMap, LiveAtlasParsedUrl + LiveAtlasUIElement, + LiveAtlasWorld, + LiveAtlasWorldMap, + LiveAtlasParsedUrl, + LiveAtlasMessageConfig } from "@/index"; export type State = { @@ -222,7 +226,7 @@ export const state: State = { updateTimestamp: new Date(), ui: { - playersAboveMarkers: window.liveAtlasConfig?.ui?.playersAboveMarkers || false, + playersAboveMarkers: true, smallScreen: false, visibleElements: new Set(), diff --git a/src/util/config.ts b/src/util/config.ts index 10e2a2c..b837c45 100644 --- a/src/util/config.ts +++ b/src/util/config.ts @@ -1,4 +1,4 @@ -import {LiveAtlasDynmapServerDefinition, LiveAtlasServerDefinition} from "@/index"; +import {LiveAtlasDynmapServerDefinition, LiveAtlasGlobalConfig, LiveAtlasServerDefinition} from "@/index"; import ConfigurationError from "@/errors/ConfigurationError"; import {DynmapUrlConfig} from "@/dynmap"; @@ -102,14 +102,15 @@ const validateDynmapConfiguration = (config: DynmapUrlConfig): Map => { - if (!window.liveAtlasConfig) { +export const getServerDefinitions = (config: LiveAtlasGlobalConfig): Map => { + if (!config) { throw new ConfigurationError(`Configuration object is missing`); } - if (typeof window.liveAtlasConfig.servers !== 'undefined') { - return validateLiveAtlasConfiguration(window.liveAtlasConfig.servers || {}); + if (typeof config !== 'undefined') { + return validateLiveAtlasConfiguration(config.servers || {}); } return validateDynmapConfiguration(window.config?.url || null); }; +