import { Map } from '$modules/Map'; import { Poly } from '$modules/Poly'; import { MODES } from '$constants/modes'; import { Stickers } from '$modules/Stickers'; import { Router } from '$modules/Router'; import { Shotter } from '$modules/Shotter'; import { DEFAULT_LOGO } from '$constants/logos'; import { parseStickerAngle, parseStickerStyle } from '$utils/import'; import { getUrlData, pushPath } from '$utils/history'; import { store } from '$redux/store'; import { setActiveSticker, setAddress, setChanged, setDistance, setEditing, setLogo, setRouterPoints, setTitle } from '$redux/user/actions'; export class Editor { constructor({ // container, // mode, // setMode, // setRouterPoints, // setTotalDist, // setEditing, // triggerOnChange, // getTitle, // clearChanged, // setActiveSticker, // setLogo, // setTitle, // setAddress, }) { this.logo = DEFAULT_LOGO; this.owner = null; this.map = new Map({ container: 'map' }); this.initialData = {}; const { triggerOnChange, lockMapClicks, routerMoveStart, changeMode, pushPolyPoints, map: { map } } = this; this.poly = new Poly({ map, routerMoveStart, lockMapClicks, setTotalDist: this.setDistance, triggerOnChange }); this.stickers = new Stickers({ map, lockMapClicks, triggerOnChange }); this.router = new Router({ map, lockMapClicks, setRouterPoints: this.setRouterPoints, changeMode, pushPolyPoints }); this.shotter = new Shotter({ map }); this.switches = { [MODES.POLY]: { start: this.poly.continue, stop: this.poly.stop, }, [MODES.ROUTER]: { start: this.routerSetStart, }, [MODES.SHOTTER]: { start: this.shotter.makeShot, }, [MODES.STICKERS]: { toggle: this.clearSticker, }, [MODES.TRASH]: { toggle: this.clearAll, }, [MODES.CONFIRM_CANCEL]: { toggle: this.cancelEditing, } }; this.clickHandlers = { [MODES.STICKERS]: this.createStickerOnClick, [MODES.ROUTER]: this.router.pushWaypointOnClick, }; this.activeSticker = null; this.mode = MODES.NONE; // this.clearChanged = clearChanged; // this.setActiveSticker = setActiveSticker; // this.setLogo = setLogo; // this.setMode = setMode; // this.setEditing = setEditing; // this.setTitle = setTitle; // this.setAddress = setAddress; // this.getUser = getUser; // this.getTitle = getTitle; map.addEventListener('mouseup', this.onClick); map.addEventListener('dragstart', () => lockMapClicks(true)); map.addEventListener('dragstop', () => lockMapClicks(false)); } getUser = () => store.getState().user.user; getTitle = () => store.getState().user.title; getEditing = () => store.getState().user.editing; getChanged = () => store.getState().user.changed; setEditing = value => store.dispatch(setEditing(value)); setDistance = value => store.dispatch(setDistance(value)); setChanged = value => store.dispatch(setChanged(value)); setRouterPoints = value => store.dispatch(setRouterPoints(value)); setActiveSticker = value => store.dispatch(setActiveSticker(value)); setLogo = value => store.dispatch(setLogo(value)); setTitle = value => store.dispatch(setTitle(value)); setAddress = value => store.dispatch(setAddress(value)); clearChanged = () => store.dispatch(setChanged(false)); triggerOnChange = () => { if (!this.getEditing() && this.getChanged()) return; this.setChanged(true); }; createStickerOnClick = (e) => { if (!e || !e.latlng || !this.activeSticker) return; const { latlng } = e; this.stickers.createSticker({ latlng, sticker: this.activeSticker }); this.setSticker(null); }; changeMode = mode => { if (this.mode === mode) { if (this.switches[mode] && this.switches[mode].toggle) { this.switches[mode].toggle(); // if we have special function on mode when it toggles } else { this.disableMode(mode); // this.setMode(MODES.NONE); this.mode = MODES.NONE; } } else { this.disableMode(this.mode); // this.setMode(mode); this.mode = mode; this.enableMode(mode); } }; enableMode = mode => { if (this.switches[mode] && this.switches[mode].start) this.switches[mode].start(); }; disableMode = mode => { if (this.switches[mode] && this.switches[mode].stop) this.switches[mode].stop(); }; onClick = e => { if (e.originalEvent.which === 3) return; // skip right click if (this.clickHandlers[this.mode]) this.clickHandlers[this.mode](e); }; lockMapClicks = lock => { if (lock) { this.map.map.removeEventListener('mouseup', this.onClick); this.map.map.addEventListener('mouseup', this.unlockMapClicks); } else { this.map.map.removeEventListener('mouseup', this.unlockMapClicks); this.map.map.addEventListener('mouseup', this.onClick); } }; unlockMapClicks = () => { this.lockMapClicks(false); }; routerSetStart = () => { const { latlngs } = this.poly; if (!latlngs || !latlngs.length) return; this.router.startFrom(latlngs[latlngs.length - 1]); }; routerMoveStart = () => { const { _latlngs } = this.poly.poly; if (_latlngs) this.router.moveStart(_latlngs[_latlngs.length - 1]); }; pushPolyPoints = latlngs => { this.poly.pushPoints(latlngs); }; setSticker = sticker => { this.activeSticker = sticker; this.setActiveSticker(sticker); }; clearSticker = () => { if (this.activeSticker) { this.setSticker(null); } else { this.changeMode(MODES.NONE); } }; clearAll = () => { this.poly.clearAll(); this.router.clearAll(); this.stickers.clearAll(); this.setSticker(null); this.changeMode(MODES.NONE); this.clearChanged(); }; changeLogo = logo => { this.logo = logo; this.setLogo(logo); this.changeMode(MODES.NONE); }; setData = ({ route, stickers, version = 1, owner, title, address }) => { this.setTitle(title || ''); const { id } = this.getUser(); if (address && id && owner && id === owner) this.setAddress(address); if (route) { this.poly.setPoints(route); } if (stickers) { stickers.map(sticker => this.stickers.createSticker({ latlng: sticker.latlng, angle: parseStickerAngle({ sticker, version }), sticker: parseStickerStyle({ sticker, version }), })); } if (owner) { this.owner = owner; } if (!route || route.length <= 1) return; const bounds = this.poly.poly.getBounds(); if (Object.values(bounds)) this.map.map.fitBounds(bounds); }; setInitialData = () => { const { path } = getUrlData(); const { id } = this.getUser(); const { route, stickers } = this.dumpData(); this.initialData = { version: 2, title: this.getTitle(), owner: this.owner, address: this.owner === id ? path : null, path, route, stickers, }; }; startEditing = () => { const { path } = getUrlData(); const { random_url, id } = this.getUser(); this.setInitialData(); const url = (this.owner && this.owner === id) ? path : random_url; pushPath(`/${url}/edit`); if (this.poly.latlngs && this.poly.latlngs.length > 1) this.poly.poly.enableEdit(); this.stickers.startEditing(); // this.setEditing(true); console.log(this.initialData); }; stopEditing = () => { const { path } = getUrlData(); pushPath(`/${(this.initialData && this.initialData.path) || path}`); this.changeMode(MODES.NONE); this.poly.poly.disableEdit(); this.stickers.stopEditing(); this.setEditing(false); }; cancelEditing = () => { this.stopEditing(); console.log('trying to set initial data'); if (this.hasEmptyHistory()) { this.clearAll(); this.startEditing(); } else { this.setData(this.initialData); } this.clearChanged(); }; dumpData = () => ({ route: this.poly.dumpData(), stickers: this.stickers.dumpData(), }); isEmpty = () => { const { route, stickers } = this.dumpData(); return (route.length > 1 && stickers.length > 0); }; hasEmptyHistory = () => { const { route, stickers } = this.initialData; return (!route || route.length < 1) && (!stickers || stickers.length <= 0); } } export const editor = new Editor({ // setMode: this.setMode, // setTotalDist: this.setTotalDist, // setEditing: this.setEditing, // getUser: this.getUser, // triggerOnChange: this.triggerOnChange, // getTitle: this.getTitle, // setRouterPoints: this.setRouterPoints, // setActiveSticker: this.setActiveSticker, // setLogo: this.setLogo, // setTitle: this.setTitle, // setAddress: this.setAddress, // clearChanged: this.clearChanged, });