mapwize-ui-react-native
Version:
Fully featured and ready to use UI to add Mapwize Indoor Maps and Navigation in your React Native app.
1,484 lines (1,393 loc) • 61.7 kB
text/typescript
import produce from 'immer'
import type { WritableDraft } from 'immer/dist/internal'
import type { Floor, SearchResult } from './types'
import type { MapwizeUIState } from './uiController'
import type MapActionsDispatcher from './mapActionsDispatcher'
import {
buildDirectionError,
buildDirectionInfo,
buildFloorDisplays,
buildLanguageDisplay,
buildLanguageDisplays,
buildNavigationInfo,
buildPlaceDetails,
buildPlacelistDetails,
buildSearchResult,
titleForLanguage,
} from './formatter'
import type { DevCallbackInterceptor } from './devCallbackInterceptor'
import type { ApiService } from './apiService'
import {
lang_available_locale,
lang_back,
lang_change_language,
lang_change_universe,
lang_choose_destination,
lang_choose_starting_point,
lang_coordinates,
lang_current_location,
lang_destination,
lang_direction,
lang_entering_venue,
lang_floor_controller,
lang_search_global,
lang_search_no_results,
lang_search_venue,
lang_start,
Locale,
} from './localizor'
import {
Camera,
DirectionMode,
DirectionOptions,
DirectionPointWrapper,
DirectionProp,
NavigationInfo,
NavigationProp,
Place,
Placelist,
PlacePreview,
Universe,
} from 'mapwize-sdk-react-native'
export class UIControllerStore {
private render: (oldState: MapwizeUIState, newState: MapwizeUIState) => void
public state: MapwizeUIState
private mapActionsDispatcher: MapActionsDispatcher
private devCallbackInterceptor: DevCallbackInterceptor
private apiService: ApiService
constructor(
defaultState: MapwizeUIState,
render: (oldState: MapwizeUIState, newState: MapwizeUIState) => void,
mapActionsDispatcher: MapActionsDispatcher,
apiService: ApiService,
devCallbackInterceptor: DevCallbackInterceptor
) {
this.render = render
this.state = defaultState
this.mapActionsDispatcher = mapActionsDispatcher
this.apiService = apiService
this.devCallbackInterceptor = devCallbackInterceptor
}
public getLocale(): Locale | undefined {
return lang_available_locale().find(
(l) => l.code === this.state.uiControllerState.preferredLanguage
)
}
public getAvailableLocales(): Locale[] {
return lang_available_locale()
}
public async setLocale(locale: string) {
if (
!lang_available_locale()
.map((l) => l.code)
.includes(locale)
) {
return
}
const nextState = await produce(
this.state,
async (draftState: WritableDraft<MapwizeUIState>) => {
draftState.uiControllerState.preferredLanguage = locale
draftState.universeSelectorState.tooltipMessage = lang_change_universe(
locale
)
draftState.languageSelectorState.tooltipMessage = lang_change_language(
locale
)
draftState.floorControllerState.tooltipMessage = lang_floor_controller(
locale
)
draftState.searchBarState.backTooltipMessage = lang_back(locale)
draftState.searchBarState.directionTooltipMessage = lang_direction(
locale
)
draftState.searchResultListState.noResultLabel = lang_search_no_results(
locale
)
if (this.state.uiControllerState.venue) {
draftState.searchBarState.searchPlaceholder = lang_search_venue(
locale,
titleForLanguage(this.state.uiControllerState.venue, locale)
)
} else {
draftState.searchBarState.searchPlaceholder = lang_search_global(
locale
)
}
draftState.searchDirectionBarState.fromPlaceholder = lang_choose_starting_point(
locale
)
draftState.searchDirectionBarState.toPlaceholder = lang_choose_destination(
locale
)
if (this.state.uiControllerState.directionFromPoint) {
if (
this.state.uiControllerState.directionFromPoint.objectClass ===
'Place'
) {
draftState.searchDirectionBarState.fromQuery = titleForLanguage(
this.state.uiControllerState.directionFromPoint,
locale
)
} else {
draftState.searchDirectionBarState.fromQuery = lang_coordinates(
locale
)
}
}
if (this.state.uiControllerState.directionToPoint) {
if (
this.state.uiControllerState.directionToPoint.objectClass ===
'Place' ||
this.state.uiControllerState.directionToPoint.objectClass ===
'Placelist'
) {
draftState.searchDirectionBarState.toQuery = titleForLanguage(
this.state.uiControllerState.directionToPoint,
locale
)
} else {
draftState.searchDirectionBarState.toQuery = lang_coordinates(
locale
)
}
}
draftState.bottomViewState.language = locale
if (this.state.uiControllerState.selectedContent) {
if (
this.state.uiControllerState.selectedContent.objectClass ===
'Place' ||
this.state.uiControllerState.selectedContent.objectClass ===
'PlaceDetails'
) {
const details = await this.apiService.getPlaceDetailsWithId(
this.state.uiControllerState.selectedContent._id
)
draftState.bottomViewState.content = buildPlaceDetails(
details,
locale
)
}
if (
this.state.uiControllerState.selectedContent.objectClass ===
'Placelist'
) {
const places = await this.apiService.getPlacesForPlacelist(
this.state.uiControllerState.selectedContent as any
)
draftState.bottomViewState.content = buildPlacelistDetails(
this.state.uiControllerState.selectedContent,
places,
locale
)
}
}
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.mapActionsDispatcher.setLanguage(locale)
}
public setUnit(unit: string) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.uiControllerState.unit = unit
if (this.state.uiControllerState.direction) {
draftState.bottomViewState.directionContent = buildDirectionInfo(
this.state.uiControllerState.direction,
unit
)
}
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public getUnit(): string {
return this.state.uiControllerState.unit
}
public getUnits(): string[] {
return ['m', 'ft']
}
public setLanguage(language: string) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.uiControllerState.language = language
draftState.universeSelectorState.tooltipMessage = lang_change_universe(
language
)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public toggleUniverseSelector() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.universeSelectorState.isExpanded = !this.state
.universeSelectorState.isExpanded
draftState.languageSelectorState.isExpanded = false
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeSelectedUniverse(universe: Universe) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.universeSelectorState.isExpanded = false
draftState.universeSelectorState.selectedUniverse = universe
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public toggleLanguageSelector() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.languageSelectorState.isExpanded = !this.state
.languageSelectorState.isExpanded
draftState.universeSelectorState.isExpanded = false
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public async directionButtonClick() {
if (!this.state.uiControllerState.venue) {
this.mapActionsDispatcher.fireError(
'Must be inside venue to enter in direction'
)
return
}
const nextState = await produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.defaultToDirection(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
if (!this.state.uiControllerState.directionFromPoint) {
this.directionSearchFromQueryChange('')
} else if (!this.state.uiControllerState.directionToPoint) {
this.directionSearchToQueryChange('')
}
}
public directionFromBlur() {
setTimeout(() => {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchDirectionBarState.isFromFocus = false
if (
!this.state.searchDirectionBarState.isFromFocus &&
!this.state.searchDirectionBarState.isToFocus
) {
draftState.searchResultListState.isHidden = true
draftState.searchResultListState.results = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
draftState.searchResultListState.showCurrentLocation = undefined
draftState.searchContainerState.isInSearch = false
}
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}, 250)
}
public directionToBlur() {
setTimeout(() => {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchDirectionBarState.isToFocus = false
if (
!this.state.searchDirectionBarState.isFromFocus &&
!this.state.searchDirectionBarState.isToFocus
) {
draftState.searchResultListState.isHidden = true
draftState.searchResultListState.results = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
draftState.searchResultListState.showCurrentLocation = undefined
draftState.searchContainerState.isInSearch = false
}
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}, 250)
}
public async directionFromFocus() {
const nextState = await produce(
this.state,
async (draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchContainerState.isInSearch = true
draftState.searchDirectionBarState.isFromFocus = true
draftState.searchDirectionBarState.isToFocus = false
draftState.uiControllerState.status = 'inFromSearch'
draftState.bottomViewState.hidden = true
if (
this.state.searchDirectionBarState.fromQuery ===
lang_current_location(this.state.uiControllerState.preferredLanguage)
) {
draftState.searchDirectionBarState.fromQuery = ''
}
await this.setMainFroms(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public async directionToFocus() {
const nextState = await produce(
this.state,
async (draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchContainerState.isInSearch = true
draftState.searchDirectionBarState.isToFocus = true
draftState.searchDirectionBarState.isFromFocus = false
draftState.uiControllerState.status = 'inToSearch'
draftState.bottomViewState.hidden = true
await this.setMainFroms(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public directionBackButtonClick() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.directionToDefault(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeDirectionModes(modes: DirectionMode[]) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchDirectionBarState.modes = modes
if (
!draftState.uiControllerState.directionMode ||
(draftState.uiControllerState.directionMode &&
!modes
.map((mode) => mode._id)
.includes(draftState.uiControllerState.directionMode?._id))
) {
draftState.searchDirectionBarState.selectedMode = modes[0]
draftState.uiControllerState.directionMode = modes[0]
} else {
draftState.searchDirectionBarState.selectedMode = this.state.uiControllerState.directionMode
}
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeDirectionMode(mode: DirectionMode) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchDirectionBarState.selectedMode = mode
draftState.uiControllerState.directionMode = mode
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
}
public searchBackButtonClick() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.searchToDefault(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public searchResultsChange(results: SearchResult[]) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchResultListState.results = results
draftState.searchResultListState.showCurrentLocation = undefined
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public searchFocus() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.defaultToSearch(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public async setMainFroms(draftState: WritableDraft<MapwizeUIState>) {
const searchResults = await this.apiService.getMainFroms(
this.state.uiControllerState?.venue
)
draftState.searchResultListState.results = buildSearchResult(
searchResults,
this.state.uiControllerState.language
)
draftState.searchResultListState.showCurrentLocation = this.mapActionsDispatcher.hasIndoorLocation()
? lang_current_location(this.state.uiControllerState.preferredLanguage)
: undefined
}
public async setMainSearches(draftState: WritableDraft<MapwizeUIState>) {
const searchResults = await this.apiService.getMainSearches(
this.state.uiControllerState.venue
)
draftState.searchResultListState.results = buildSearchResult(
searchResults,
this.state.uiControllerState.language
)
draftState.searchResultListState.showCurrentLocation = undefined
}
public searchBlur() {
setTimeout(() => {
if (
!this.state.searchDirectionBarState.isFromFocus &&
!this.state.searchDirectionBarState.isToFocus
) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.searchToDefault(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
}, 500)
}
public async searchQueryChange(query: string) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchBarState.searchQuery = query
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
let searchResults: any
if (this.state.uiControllerState.venue) {
const searchParams = {
query,
objectClasses: ['place', 'placeList'],
venueId: this.state.uiControllerState.venue._id,
}
if (query.length === 0) {
searchResults = await this.apiService.getMainSearches(
this.state.uiControllerState.venue
)
} else {
searchResults = await this.apiService.search(searchParams)
}
} else {
const searchParams = { query, objectClasses: ['venue'] }
searchResults = await this.apiService.search(searchParams)
}
const nextStateAsync = await produce(
this.state,
async (draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchResultListState.results = buildSearchResult(
searchResults,
this.state.uiControllerState.language
)
draftState.searchResultListState.universes = this.state.universeSelectorState.universes
draftState.searchResultListState.currentUniverse = this.state.universeSelectorState.selectedUniverse
draftState.searchResultListState.showCurrentLocation = undefined
}
)
const oldStateAsync = this.state
this.state = nextStateAsync
this.render(oldStateAsync, nextStateAsync)
}
public async directionSearchFromQueryChange(query: string) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchContainerState.isInSearch = true
draftState.searchDirectionBarState.isInSearch = true
draftState.searchDirectionBarState.fromQuery = query
draftState.searchResultListState.isHidden = false
draftState.searchResultListState.isInDirectionSearch = true
draftState.bottomViewState.hidden = true
draftState.uiControllerState.status = 'inFromSearch'
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
const searchParams = {
query,
objectClasses: ['place'],
universeId: this.state.universeSelectorState.selectedUniverse?._id,
venueId: this.state.uiControllerState.venue?._id,
}
let searchResults: any
if (query.length === 0) {
searchResults = await this.apiService.getMainFroms(
this.state.uiControllerState.venue
)
} else {
searchResults = await this.apiService.search(searchParams)
}
const nextStateAsync = await produce(
this.state,
async (draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchResultListState.results = buildSearchResult(
searchResults,
this.state.uiControllerState.language
)
draftState.searchResultListState.showCurrentLocation = this.mapActionsDispatcher.hasIndoorLocation()
? lang_current_location(
this.state.uiControllerState.preferredLanguage
)
: undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
}
)
const oldStateAsync = this.state
this.state = nextStateAsync
this.render(oldStateAsync, nextStateAsync)
}
public async directionSearchToQueryChange(query: string) {
this.generic((draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchContainerState.isInSearch = true
draftState.searchDirectionBarState.isInSearch = true
draftState.searchDirectionBarState.toQuery = query
draftState.searchResultListState.isHidden = false
draftState.searchResultListState.isInDirectionSearch = true
draftState.bottomViewState.hidden = true
draftState.uiControllerState.status = 'inToSearch'
})
const searchParams = {
query,
objectClasses: ['place', 'placeList'],
universeId: this.state.universeSelectorState.selectedUniverse?._id,
venueId: this.state.uiControllerState.venue?._id,
}
let searchResults: any
if (query.length === 0) {
searchResults = await this.apiService.getMainSearches(
this.state.uiControllerState.venue
)
} else {
searchResults = await this.apiService.search(searchParams)
}
const nextStateAsync = await produce(
this.state,
async (draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchResultListState.results = buildSearchResult(
searchResults,
this.state.uiControllerState.language
)
draftState.searchResultListState.showCurrentLocation = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
}
)
const oldStateAsync = this.state
this.state = nextStateAsync
this.render(oldStateAsync, nextStateAsync)
}
// TODO use it everywhere
private generic(
producer: (draftState: WritableDraft<MapwizeUIState>) => void
) {
const nextState = produce(this.state, producer)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public selectSearchResult(
result: SearchResult,
universe?: Universe | undefined
) {
if (this.state.uiControllerState.status === 'inFromSearch') {
this.selectFrom(result)
if (
this.state.searchDirectionBarState.toQuery === undefined ||
this.state.searchDirectionBarState.toQuery === ''
) {
this.directionSearchToQueryChange('')
}
} else if (this.state.uiControllerState.status === 'inToSearch') {
this.selectTo(result)
} else if (this.state.uiControllerState.status === 'inSearch') {
this.selectDefaultSearchResult(result, universe)
}
}
private async selectDefaultSearchResult(
result: SearchResult,
universe?: Universe | undefined
) {
if (result.objectClass === 'Place') {
await this.selectPlace(result)
this.mapActionsDispatcher.centerOnPlace(result)
if (universe) {
this.mapActionsDispatcher.setUniverse(universe)
}
}
if (result.objectClass === 'Placelist') {
this.selectPlacelist(result)
// TODO Verify this.mapActionsDispatcher.selectPlacelist(result, { channel: 'search', searchQuery: this.state.searchBarState.searchQuery })
}
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchResultListState.isHidden = true
draftState.searchBarState.isInSearch = false
draftState.searchBarState.searchQuery = ''
draftState.searchContainerState.isInSearch = false
draftState.uiControllerState.status = 'default'
draftState.searchResultListState.results = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
draftState.searchResultListState.showCurrentLocation = undefined
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
if (result.objectClass === 'Venue') {
this.mapActionsDispatcher.centerOnVenue(result as any)
}
}
public selectCurrentLocation() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.uiControllerState.directionFromPoint = this.mapActionsDispatcher.getUserLocation()
draftState.searchDirectionBarState.fromQuery = lang_current_location(
this.state.uiControllerState.preferredLanguage
)
this.setNextDirectionStep(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
}
private async selectFrom(result: any) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.setFromSelected(draftState, result)
this.setNextDirectionStep(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
}
private async selectTo(result: any) {
if (result.objectClass === 'Place') {
// this.selectPlace(result);
}
if (result.objectClass === 'Placelist') {
this.selectPlacelist(result)
}
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.setToSelected(draftState, result)
this.setNextDirectionStep(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
}
public willEnterInVenue(venue: any) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchBarState.searchPlaceholder = lang_entering_venue(
this.state.uiControllerState.language,
venue.name
)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public enterInVenue(venue: any) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
if (this.state.uiControllerState.direction) {
if (
!this.state.uiControllerState.lastExitedVenue ||
venue._id === this.state.uiControllerState.lastExitedVenue._id
) {
this.enterVenueInDirection(draftState)
} else {
this.directionToDefault(draftState)
}
}
if (this.state.uiControllerState.selectedContent) {
if (
!this.state.uiControllerState.lastExitedVenue ||
venue._id === this.state.uiControllerState.lastExitedVenue._id
) {
this.enterVenueInSelectedContent(draftState)
if (
this.state.uiControllerState.selectedContent.objectClass ===
'Place' ||
this.state.uiControllerState.selectedContent.objectClass ===
'PlaceDetails'
) {
setTimeout(
() =>
this.mapActionsDispatcher.selectPlace(
this.state.uiControllerState.selectedContent as any,
true
),
500
)
} else if (
this.state.uiControllerState.selectedContent.objectClass ===
'Placelist'
) {
setTimeout(
() =>
this.mapActionsDispatcher.selectPlacelist(
this.state.uiControllerState.selectedContent as any
),
500
)
}
} else {
draftState.mapwizeMapState.selectedPlace = undefined
draftState.uiControllerState.selectedContent = undefined
draftState.bottomViewState.content = undefined
draftState.bottomViewState.expanded = false
draftState.bottomViewState.hidden = true
draftState.languageSelectorState.isHidden =
draftState.languageSelectorState.languages.length <= 1
draftState.universeSelectorState.isHidden =
draftState.universeSelectorState.universes.length <= 1
this.mapActionsDispatcher.unselectContent()
}
}
draftState.searchBarState.searchPlaceholder = lang_search_venue(
this.state.uiControllerState.language,
titleForLanguage(venue, this.state.uiControllerState.language)
)
draftState.uiControllerState.venue = venue
draftState.searchBarState.directionButtonHidden = false
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public exitVenue(venue: any) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchBarState.searchPlaceholder = lang_search_global(
this.state.uiControllerState.language
)
draftState.uiControllerState.lastExitedVenue = venue
draftState.uiControllerState.venue = undefined
draftState.searchBarState.directionButtonHidden = true
if (this.state.uiControllerState.direction) {
this.directionToExitVenue(draftState)
} else if (this.state.uiControllerState.selectedContent) {
this.selectedContentToExitVenue(draftState)
}
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeFloors(floors: Floor[]) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.uiControllerState.floors = floors
draftState.floorControllerState.floors = buildFloorDisplays(
floors,
this.state.uiControllerState.language
)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public loadFloor(floor: number) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.floorControllerState.loadingFloor = floor
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeFloor(floor: number | null) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.floorControllerState.loadingFloor = undefined
draftState.floorControllerState.selectedFloor = floor
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeUniverses(universes: Universe[]) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.universeSelectorState.universes = universes
draftState.universeSelectorState.isHidden = universes.length <= 1
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public loadUniverse() {}
public changeUniverse(universe: Universe) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.universeSelectorState.selectedUniverse = universe
draftState.universeSelectorState.isExpanded = false
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeLanguages(languages: string[]) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.languageSelectorState.languages = buildLanguageDisplays(
languages
)
draftState.languageSelectorState.isHidden = languages.length <= 1
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public changeLanguage(language: string) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.languageSelectorState.selectedLanguage = buildLanguageDisplay(
language
)
draftState.languageSelectorState.isExpanded = false
draftState.uiControllerState.language = language
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public selectContent(content: any) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.uiControllerState.selectedContent = content
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public async externalSelectPlace(place: any): Promise<void> {
this.selectPlace(place)
return this.mapActionsDispatcher.centerOnPlace(place)
}
public async externalSelectPlacelist(placelist: any): Promise<void> {
this.selectPlacelist(placelist)
return this.mapActionsDispatcher.centerOnPlacelist(placelist)
}
public onPlaceClick(place: any) {
if (this.state.uiControllerState.status === 'default') {
this.selectPlace(place)
}
if (this.state.uiControllerState.status === 'inFromSearch') {
this.selectFrom(place)
return
} else if (this.state.uiControllerState.status === 'inToSearch') {
this.selectTo(place)
return
} else if (this.state.uiControllerState.status === 'inDirection') {
return
}
}
public onVenueClick(venue: any) {
this.mapActionsDispatcher.centerOnVenue(venue)
}
public onMapClick(coordinate: any) {
if (this.state.uiControllerState.status === 'default') {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.mapwizeMapState.selectedPlace = undefined
draftState.uiControllerState.selectedContent = undefined
draftState.bottomViewState.content = undefined
draftState.bottomViewState.expanded = false
draftState.bottomViewState.hidden = true
draftState.languageSelectorState.isExpanded = false
draftState.languageSelectorState.isHidden =
draftState.languageSelectorState.languages.length <= 1
draftState.universeSelectorState.isExpanded = false
draftState.universeSelectorState.isHidden =
draftState.universeSelectorState.universes.length <= 1
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.mapActionsDispatcher.unselectContent()
} else if (
this.state.uiControllerState.status === 'inFromSearch' &&
this.state.searchDirectionBarState.isFromFocus
) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.setFromCoordinateSelected(draftState, coordinate)
this.setNextDirectionStep(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
} else if (
this.state.uiControllerState.status === 'inToSearch' &&
this.state.searchDirectionBarState.isToFocus
) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.setToCoordinateSelected(draftState, coordinate)
this.setNextDirectionStep(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
}
}
public toggleBottomViewExpand() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.bottomViewState.expanded = !draftState.bottomViewState
.expanded
draftState.searchBarState.isHidden = draftState.bottomViewState.expanded
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public async selectPlace(placePreview: any) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
if (this.state.uiControllerState.venue) {
draftState.bottomViewState.hidden = false
draftState.languageSelectorState.isHidden = true
draftState.universeSelectorState.isHidden = true
}
draftState.bottomViewState.content = {
...placePreview,
titleLabel: placePreview?.title,
subtitleLabel: placePreview?.subtitle,
}
draftState.uiControllerState.selectedContent = placePreview
draftState.mapwizeMapState.selectedPlace = placePreview
draftState.mapwizeMapState.markers = []
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
await this.getDetailsForPlacePreview({ ...placePreview })
}
private async getDetailsForPlacePreview(
placePreview: PlacePreview | Placelist | Place
) {
let place = placePreview
let details: any = placePreview
if (placePreview.objectClass === 'PlacePreview') {
place = await this.apiService.getPlace(placePreview as PlacePreview)
details = await this.apiService.getPlaceDetails(
placePreview as PlacePreview
)
} else if (placePreview.objectClass === 'Place') {
details = await this.apiService.getPlaceDetails(
placePreview as PlacePreview
)
}
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
if (this.state.uiControllerState.venue) {
draftState.bottomViewState.hidden = false
draftState.languageSelectorState.isHidden = true
draftState.universeSelectorState.isHidden = true
}
draftState.bottomViewState.content = buildPlaceDetails(
details,
this.state.uiControllerState.language
)
draftState.uiControllerState.selectedContent = place
draftState.mapwizeMapState.selectedPlace = place
draftState.mapwizeMapState.markers = []
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public async selectPlaceAndGoDirection(place: any) {
if (this.state.mapwizeMapState.selectedPlace?._id !== place?._id) {
await this.selectPlace(place)
}
this.directionButtonClick()
this.tryToStartDirection()
}
private async selectPlacelist(placelist: any) {
const places = await this.apiService.getPlacesForPlacelist(placelist)
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
if (this.state.uiControllerState.venue) {
draftState.bottomViewState.hidden = false
draftState.languageSelectorState.isHidden = true
draftState.universeSelectorState.isHidden = true
}
draftState.bottomViewState.content = buildPlacelistDetails(
placelist,
places,
this.state.uiControllerState.language
)
draftState.uiControllerState.selectedContent = placelist
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
if (this.state.uiControllerState.status !== 'inDirection') {
this.mapActionsDispatcher.selectPlacelist(placelist)
}
}
public getFrom(): any {
return this.state.uiControllerState.directionFromPoint
}
public getTo(): any {
return this.state.uiControllerState.directionToPoint
}
public setMode(modeId: string) {
const mode = this.state.searchDirectionBarState.modes.find(
(m) => m._id === modeId
)
if (!mode) {
console.error('Mode does not exist in this venue')
return
}
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchDirectionBarState.selectedMode = mode
draftState.uiControllerState.directionMode = mode
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
}
private setFromSelected(
draftState: WritableDraft<MapwizeUIState>,
from: any
) {
draftState.uiControllerState.directionFromPoint = from
draftState.searchDirectionBarState.fromQuery =
titleForLanguage(from, draftState.uiControllerState.language) || ''
}
private setFromCoordinateSelected(
draftState: WritableDraft<MapwizeUIState>,
from: any
) {
draftState.uiControllerState.directionFromPoint = from
draftState.searchDirectionBarState.fromQuery = lang_coordinates(
this.state.uiControllerState.language
)
}
private setToSelected(draftState: WritableDraft<MapwizeUIState>, to: any) {
draftState.uiControllerState.directionToPoint = to
draftState.searchDirectionBarState.toQuery =
titleForLanguage(to, draftState.uiControllerState.language) || ''
}
private setToCoordinateSelected(
draftState: WritableDraft<MapwizeUIState>,
to: any
) {
draftState.uiControllerState.directionToPoint = to
draftState.searchDirectionBarState.toQuery = lang_coordinates(
this.state.uiControllerState.language
)
}
private setNextDirectionStep(draftState: WritableDraft<MapwizeUIState>) {
if (!draftState.uiControllerState.directionFromPoint) {
draftState.searchDirectionBarState.isFromFocus = true
draftState.searchResultListState.results = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
draftState.searchResultListState.showCurrentLocation = undefined
} else if (!draftState.uiControllerState.directionToPoint) {
draftState.searchDirectionBarState.isToFocus = true
draftState.searchResultListState.results = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
draftState.searchResultListState.showCurrentLocation = undefined
} else {
draftState.searchResultListState.isInDirectionSearch = false
draftState.searchResultListState.isHidden = true
draftState.searchResultListState.results = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
draftState.searchResultListState.showCurrentLocation = undefined
draftState.searchContainerState.isInSearch = false
draftState.uiControllerState.status = 'inDirection'
}
}
public onCameraChange(camera: Camera) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
draftState.uiControllerState.heading = camera.bearing
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
}
public swapFromAndTo() {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
const oldFrom = this.state.uiControllerState.directionFromPoint
const oldTo = this.state.uiControllerState.directionToPoint
const oldFromQuery = this.state.searchDirectionBarState.fromQuery
const oldToQuery = this.state.searchDirectionBarState.toQuery
if (oldTo?.objectClass === 'Placelist') {
draftState.uiControllerState.directionFromPoint = undefined
draftState.searchDirectionBarState.fromQuery = ''
} else {
draftState.uiControllerState.directionFromPoint = oldTo
draftState.searchDirectionBarState.fromQuery = oldToQuery
}
draftState.uiControllerState.directionToPoint = oldFrom
draftState.searchDirectionBarState.toQuery = oldFromQuery
if (
oldFrom?.objectClass === 'Place' ||
oldFrom?.objectClass === 'PlaceDetails'
) {
this.selectPlace(oldFrom as any)
}
this.setNextDirectionStep(draftState)
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.tryToStartDirection()
}
public async tryToStartDirection() {
if (
this.state.uiControllerState.status !== 'default' &&
this.state.uiControllerState.directionFromPoint &&
this.state.uiControllerState.directionToPoint
) {
try {
if (
this.state.uiControllerState.directionFromPoint.objectClass ===
'LatLngFloor' &&
this.mapActionsDispatcher.hasIndoorLocation()
) {
this.startNavigation()
} else {
let direction =
this.state.uiControllerState.venue &&
this.state.universeSelectorState.selectedUniverse &&
this.state.uiControllerState.directionMode &&
(await this.devCallbackInterceptor.onDirectionWillStart?.(
this.state.uiControllerState.venue,
this.state.universeSelectorState.selectedUniverse,
this.state.uiControllerState.directionFromPoint,
this.state.uiControllerState.directionToPoint,
this.state.uiControllerState.directionMode,
false
))
if (direction === undefined) {
direction = await this.apiService.getDirection({
from: this.buildDirectionPoint(
this.state.uiControllerState.directionFromPoint
),
to: this.buildDirectionPoint(
this.state.uiControllerState.directionToPoint
),
mode: this.state.uiControllerState.directionMode,
})
}
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.setNextDirectionStep(draftState)
draftState.uiControllerState.direction = direction
draftState.bottomViewState.directionContent = buildDirectionInfo(
direction,
this.state.uiControllerState.unit
)
draftState.bottomViewState.hidden = false
draftState.bottomViewState.expanded = false
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.mapActionsDispatcher.unselectContent()
this.startDirection(direction, new DirectionOptions())
}
} catch (e) {
const nextState = produce(
this.state,
(draftState: WritableDraft<MapwizeUIState>) => {
this.setNextDirectionStep(draftState)
draftState.uiControllerState.direction = undefined
draftState.bottomViewState.directionContent = buildDirectionError(
this.state.uiControllerState.preferredLanguage
)
draftState.bottomViewState.hidden = false
draftState.bottomViewState.expanded = false
}
)
const oldState = this.state
this.state = nextState
this.render(oldState, nextState)
this.mapActionsDispatcher.stopDirection()
}
}
}
private async directionObjectToMapwizeObject(
directionPointWrapper: DirectionPointWrapper
): Promise<any> {
if (directionPointWrapper.placeId) {
const place = await this.apiService.getPlaceWithId(
directionPointWrapper.placeId
)
return place
} else {
return Promise.resolve(directionPointWrapper)
}
}
public async startDirectionFromProps(
directionProp: DirectionProp | undefined
) {
if (directionProp === undefined || directionProp.direction == undefined) {
this.directionBackButtonClick()
return
}
const direction = directionProp.direction
const [from, to] = await Promise.all([
this.directionObjectToMapwizeObject(direction.from),
this.directionObjectToMapwizeObject(direction.to),
])
const nextState = await produce(
this.state,
async (draftState: WritableDraft<MapwizeUIState>) => {
draftState.searchBarState.searchQuery = ''
draftState.searchBarState.isHidden = true
draftState.searchBarState.isInSearch = false
draftState.searchResultListState.isHidden = true
draftState.searchResultListState.results = undefined
draftState.searchResultListState.universes = []
draftState.searchResultListState.currentUniverse = undefined
draftState.searchResultListState.showCurrentLocation = undefined
draftState.searchDirectionBarState.isHidden = false
draftState.universeSelectorState.isHidden = true
draftState.languageSelectorState.isHidden = true
draftState.searchResultListState.isInDirectionSearch = false
draftState.searchContainerState.isInSearch = false
draftState.uiControllerState.status = 'inDirection'
if (to.objectClass === 'Place') {
const details = await this.apiService.getPlaceDetailsWithId(to._id)
draftState.bottomViewState.content = buildPlaceDetails(
details,
draftState.uiControllerState.preferredLanguage
)
}
draftState.uiControllerState.status = 'inDirection'
draftState.uiControllerState.direction = direction
draftState.uiControllerState.directionFromPoint = from
draftState.uiControllerState.directionToPoint = to
draftState.uiControllerState.directionMode = direction.mode
draftState.bottomViewState.directionContent = buildDirectionInfo(
direction,
draftState.uiControllerState.unit
)
draftState.searchDirectionBarState.fromQuery =
from.objectClass === 'Place'
? titleForLanguage