kopia lustrzana https://github.com/FacilMap/facilmap
Porównaj commity
7 Commity
79a2c08273
...
e080834696
Autor | SHA1 | Data |
---|---|---|
Candid Dauth | e080834696 | |
Candid Dauth | c9d20cea88 | |
Candid Dauth | 78d36ff2fa | |
Roman Deev | 15f2d91d23 | |
Roman Deev | 19eda4b29f | |
Roman Deev | d9be2030b7 | |
Candid Dauth | 347edfc861 |
|
@ -1,6 +1,6 @@
|
|||
import { io, type ManagerOptions, type Socket as SocketIO, type SocketOptions } from "socket.io-client";
|
||||
import { type Bbox, type BboxWithZoom, type CRU, type EventHandler, type EventName, type FindOnMapQuery, type FindPadsQuery, type FindPadsResult, type FindQuery, type GetPadQuery, type HistoryEntry, type ID, type Line, type LineExportRequest, type LineTemplateRequest, type LineToRouteCreate, type SocketEvents, type Marker, type MultipleEvents, type ObjectWithId, type PadData, type PadId, type PagedResults, type SocketRequest, type SocketRequestName, type SocketResponse, type Route, type RouteClear, type RouteCreate, type RouteExportRequest, type RouteInfo, type RouteRequest, type SearchResult, type SocketVersion, type TrackPoint, type Type, type View, type Writable, type SocketClientToServerEvents, type SocketServerToClientEvents, type LineTemplate, type LinePointsEvent, PadNotFoundError, type SetLanguageRequest } from "facilmap-types";
|
||||
import { deserializeError, errorConstructors } from "serialize-error";
|
||||
import { deserializeError, errorConstructors, serializeError } from "serialize-error";
|
||||
|
||||
export interface ClientEvents extends SocketEvents<SocketVersion.V2> {
|
||||
connect: [];
|
||||
|
@ -194,10 +194,12 @@ class Client {
|
|||
|
||||
this._simulateEvent("emit", eventName as any, data as any);
|
||||
|
||||
const outerError = new Error();
|
||||
return await new Promise((resolve, reject) => {
|
||||
this.socket.emit(eventName as any, data, (err: any, data: SocketResponse<SocketVersion.V2, R>) => {
|
||||
if(err) {
|
||||
reject(deserializeError(err));
|
||||
const cause = deserializeError(err);
|
||||
reject(deserializeError({ ...serializeError(outerError), message: cause.message, cause }));
|
||||
this._simulateEvent("emitReject", eventName as any, err);
|
||||
} else {
|
||||
const fixedData = this._fixResponseObject(eventName, data);
|
||||
|
|
|
@ -32,5 +32,11 @@
|
|||
},
|
||||
"zoom-to-object-button": {
|
||||
"fallback-label": "Приблизить объект"
|
||||
},
|
||||
"toolbox-collab-maps-dropdown": {
|
||||
"label": "Совместные карты"
|
||||
},
|
||||
"open-map-dialog": {
|
||||
"search-alt": "Поиск"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ export interface MapComponents {
|
|||
bboxHandler: BboxHandler;
|
||||
container: HTMLElement;
|
||||
graphicScale: any;
|
||||
hashHandler: HashHandler;
|
||||
hashHandler: HashHandler & { _fmActivate: () => Promise<void> };
|
||||
linesLayer: LinesLayer;
|
||||
locateControl?: L.Control.Locate;
|
||||
map: Map;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface WritableSearchFormTabContext {
|
||||
setQuery(query: string, zoom?: boolean, smooth?: boolean, autofocus?: boolean): void;
|
||||
setQuery(query: string, zoom?: boolean, smooth?: boolean, autofocus?: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export type SearchFormTabContext = Readonly<WritableSearchFormTabContext>;
|
|
@ -1,4 +1,4 @@
|
|||
import { type Ref, ref, watch, markRaw, reactive, watchEffect, shallowRef, shallowReadonly, type Raw } from "vue";
|
||||
import { type Ref, ref, watch, markRaw, reactive, watchEffect, shallowRef, shallowReadonly, type Raw, nextTick } from "vue";
|
||||
import { type Control, latLng, latLngBounds, type Map, map as leafletMap, DomUtil, control } from "leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import { BboxHandler, getSymbolHtml, getVisibleLayers, HashHandler, LinesLayer, MarkersLayer, SearchResultsLayer, OverpassLayer, OverpassLoadStatus, displayView, getInitialView, coreSymbolList } from "facilmap-leaflet";
|
||||
|
@ -15,7 +15,7 @@ import type { MapComponents, MapContextData, MapContextEvents, WritableMapContex
|
|||
import type { ClientContext } from "../facil-map-context-provider/client-context";
|
||||
import type { FacilMapContext } from "../facil-map-context-provider/facil-map-context";
|
||||
import { requireClientContext } from "../facil-map-context-provider/facil-map-context-provider.vue";
|
||||
import { type Optional, sleep } from "facilmap-utils";
|
||||
import { type Optional } from "facilmap-utils";
|
||||
import { getI18n, i18nResourceChangeCounter } from "../../utils/i18n";
|
||||
import { AttributionControl } from "./attribution";
|
||||
import { fixOnCleanup } from "../../utils/vue";
|
||||
|
@ -310,31 +310,36 @@ function useSelectionHandler(map: Ref<Map>, context: FacilMapContext, mapContext
|
|||
);
|
||||
}
|
||||
|
||||
function useHashHandler(map: Ref<Map>, client: Ref<ClientContext>, context: FacilMapContext, mapContext: MapContextWithoutComponents, overpassLayer: Ref<OverpassLayer>): Ref<Raw<HashHandler>> {
|
||||
function useHashHandler(map: Ref<Map>, client: Ref<ClientContext>, context: FacilMapContext, mapContext: MapContextWithoutComponents, overpassLayer: Ref<OverpassLayer>): Ref<Raw<HashHandler & { _fmActivate: () => Promise<void> }>> {
|
||||
return useMapComponent(
|
||||
map,
|
||||
() => markRaw(new HashHandler(map.value, client.value, { overpassLayer: overpassLayer.value, simulate: !context.settings.updateHash }))
|
||||
.on("fmQueryChange", async (e: any) => {
|
||||
let smooth = true;
|
||||
let autofocus = false;
|
||||
if (!mapContext.components) {
|
||||
// This is called while the hash handler is being enabled, so it is the initial view
|
||||
smooth = false;
|
||||
autofocus = context.settings.autofocus;
|
||||
await sleep(0); // Wait for components to be initialized (needed by openSpecialQuery())
|
||||
}
|
||||
() => {
|
||||
let queryChangePromise: Promise<void> | undefined;
|
||||
const hashHandler = markRaw(new HashHandler(map.value, client.value, { overpassLayer: overpassLayer.value, simulate: !context.settings.updateHash }))
|
||||
.on("fmQueryChange", async (e: any) => {
|
||||
let smooth = true;
|
||||
let autofocus = false;
|
||||
|
||||
const searchFormTab = context.components.searchFormTab;
|
||||
if (!e.query)
|
||||
searchFormTab?.setQuery("", false, false);
|
||||
else if (!await openSpecialQuery(e.query, context, e.zoom, smooth))
|
||||
searchFormTab?.setQuery(e.query, e.zoom, smooth, autofocus);
|
||||
})
|
||||
.on("fmHash", (e: any) => {
|
||||
mapContext.hash = e.hash;
|
||||
}),
|
||||
const searchFormTab = context.components.searchFormTab;
|
||||
queryChangePromise = (async () => {
|
||||
if (!e.query)
|
||||
await searchFormTab?.setQuery("", false, false);
|
||||
else if (!await openSpecialQuery(e.query, context, e.zoom, smooth))
|
||||
await searchFormTab?.setQuery(e.query, e.zoom, smooth, autofocus);
|
||||
})();
|
||||
await queryChangePromise;
|
||||
})
|
||||
.on("fmHash", (e: any) => {
|
||||
mapContext.hash = e.hash;
|
||||
});
|
||||
return Object.assign(hashHandler, {
|
||||
_fmActivate: async () => {
|
||||
hashHandler.enable();
|
||||
await queryChangePromise;
|
||||
}
|
||||
});
|
||||
},
|
||||
(hashHandler, onCleanup) => {
|
||||
hashHandler.enable();
|
||||
onCleanup(() => {
|
||||
hashHandler.disable();
|
||||
});
|
||||
|
@ -420,20 +425,31 @@ export async function useMapContext(context: FacilMapContext, mapRef: Ref<HTMLEl
|
|||
|
||||
const client = requireClientContext(context);
|
||||
|
||||
if (!map._loaded) {
|
||||
try {
|
||||
// Initial view was not set by hash handler
|
||||
displayView(map, await getInitialView(client.value), { overpassLayer });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
displayView(map, undefined, { overpassLayer });
|
||||
}
|
||||
}
|
||||
(async () => {
|
||||
await nextTick(); // useMapContext() return promise is resolved, setting mapContext.value in <LeafletMap>
|
||||
await nextTick(); // <LeafletMap> rerenders with its slot, search box tabs are now available and can receive the query from the hash handler
|
||||
|
||||
watchEffect(() => {
|
||||
mapContext.activeQuery = getHashQuery(mapContext.components.map, client.value, mapContext.selection) || mapContext.fallbackQuery;
|
||||
mapContext.components.hashHandler.setQuery(mapContext.activeQuery);
|
||||
});
|
||||
await mapContext.components.hashHandler._fmActivate();
|
||||
|
||||
if (!map._loaded) {
|
||||
try {
|
||||
// Initial view was not set by hash handler
|
||||
displayView(map, await getInitialView(client.value), { overpassLayer });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
displayView(map, undefined, { overpassLayer });
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => mapContext.components.hashHandler, async (hashHandler) => {
|
||||
await hashHandler._fmActivate();
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
mapContext.activeQuery = getHashQuery(mapContext.components.map, client.value, mapContext.selection) || mapContext.fallbackQuery;
|
||||
mapContext.components.hashHandler.setQuery(mapContext.activeQuery);
|
||||
});
|
||||
})().catch(console.error);
|
||||
|
||||
return mapContext;
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
}
|
||||
|
||||
const searchFormTabContext: WritableSearchFormTabContext = {
|
||||
setQuery(query, zoom = false, smooth = true, autofocus = false): void {
|
||||
async setQuery(query, zoom = false, smooth = true, autofocus = false): Promise<void> {
|
||||
searchForm.value!.setSearchString(query);
|
||||
searchForm.value!.search(zoom, undefined, smooth);
|
||||
searchBoxContext.value.activateTab(`fm${context.id}-search-form-tab`, { expand: !!query, autofocus });
|
||||
await searchForm.value!.search(zoom, undefined, smooth);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -618,7 +618,7 @@ test("Export line", async () => {
|
|||
</extensions>
|
||||
</metadata>
|
||||
<extensions>
|
||||
<osmand:color>#0000ff</osmand:color>
|
||||
<osmand:color>#aa0000ff</osmand:color>
|
||||
<osmand:width>4</osmand:width>
|
||||
</extensions>
|
||||
<trk>
|
||||
|
@ -642,7 +642,7 @@ test("Export line", async () => {
|
|||
</extensions>
|
||||
</metadata>
|
||||
<extensions>
|
||||
<osmand:color>#0000ff</osmand:color>
|
||||
<osmand:color>#aa0000ff</osmand:color>
|
||||
<osmand:width>4</osmand:width>
|
||||
</extensions>
|
||||
<rte>
|
||||
|
@ -693,7 +693,7 @@ test("Export line (track)", async () => {
|
|||
</extensions>
|
||||
</metadata>
|
||||
<extensions>
|
||||
<osmand:color>#00ff00</osmand:color>
|
||||
<osmand:color>#aa00ff00</osmand:color>
|
||||
<osmand:width>10</osmand:width>
|
||||
</extensions>
|
||||
<trk>
|
||||
|
@ -718,7 +718,7 @@ test("Export line (track)", async () => {
|
|||
</extensions>
|
||||
</metadata>
|
||||
<extensions>
|
||||
<osmand:color>#00ff00</osmand:color>
|
||||
<osmand:color>#aa00ff00</osmand:color>
|
||||
<osmand:width>10</osmand:width>
|
||||
</extensions>
|
||||
<rte>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"leaflet-auto-graticule": "^2.0.0",
|
||||
"leaflet-draggable-lines": "^2.0.0",
|
||||
"leaflet-freie-tonne": "^2.0.1",
|
||||
"leaflet-highlightable-layers": "^3.0.0",
|
||||
"leaflet-highlightable-layers": "^3.0.1",
|
||||
"leaflet.markercluster": "^1.5.3",
|
||||
"lodash-es": "^4.17.21"
|
||||
},
|
||||
|
|
|
@ -1 +1,83 @@
|
|||
{}
|
||||
{
|
||||
"layers": {
|
||||
"topo-name": "OpenTopoMap",
|
||||
"ocyc-name": "OpenCycleMap",
|
||||
"mpnk-attribution": "© [Участники OSM](https://www.openstreetmap.org/copyright)",
|
||||
"topl-name": "TopPlus",
|
||||
"mpnk-name": "Mapnik",
|
||||
"map1-name": "Map1.eu",
|
||||
"cyco-name": "CyclOSM"
|
||||
},
|
||||
"overpass-presets": {
|
||||
"bank": "Банки",
|
||||
"bench": "Скамейки",
|
||||
"bicycleparking": "Велопарковки",
|
||||
"bicyclerental": "Велопрокаты",
|
||||
"cinema": "Кинотеатры",
|
||||
"clinic": "Клиники",
|
||||
"embassy": "Посольства",
|
||||
"fuel": "Заправки",
|
||||
"hospital": "Больницы",
|
||||
"pharmacy": "Аптеки",
|
||||
"postbox": "Почтовые ящики",
|
||||
"postoffice": "Почта",
|
||||
"theatre": "Театры",
|
||||
"church": "Церкви",
|
||||
"mosque": "Мечети",
|
||||
"buddhist": "Буддийские храмы",
|
||||
"hindu": "Индуистские храмы",
|
||||
"synagogue": "Синагоги",
|
||||
"category-restaurants": "Рестораны",
|
||||
"category-various": "Прочее",
|
||||
"firestation": "Пожарные части",
|
||||
"library": "Библиотеки",
|
||||
"police": "Полиция",
|
||||
"musicschool": "Музыкальные школы",
|
||||
"toilets": "Туалеты",
|
||||
"worship": "Религиозные объекты",
|
||||
"parking": "Парковки",
|
||||
"school": "Школы/колледжы",
|
||||
"shower": "Душ",
|
||||
"university": "Университеты",
|
||||
"taxi": "Такси",
|
||||
"cemetery": "Кладбища",
|
||||
"category-tourism": "Туризм",
|
||||
"category-sports": "Спорт",
|
||||
"category-shops": "Магазины",
|
||||
"shops": "Все магазины",
|
||||
"atm": "Банкоматы",
|
||||
"drinkingwater": "Питьевая вода",
|
||||
"statue": "Статуи",
|
||||
"abandoned": "Заброшенное",
|
||||
"artwork": "Произведения искусства",
|
||||
"attraction": "Достопримечательности",
|
||||
"castle": "Замки",
|
||||
"gallery": "Галереи",
|
||||
"heritage": "Культурное наследие",
|
||||
"historic": "Исторические объекты",
|
||||
"museum": "Музеи",
|
||||
"picnic": "Места для пикников",
|
||||
"sauna": "Сауны",
|
||||
"zoo": "Зоопарки",
|
||||
"spa": "Спа",
|
||||
"themepark": "Парки развлечений",
|
||||
"viewpoint": "Смотровые площадки",
|
||||
"vineyard": "Виноградники",
|
||||
"alpinehut": "Альпийские хижины",
|
||||
"apartment": "Апартаменты",
|
||||
"campsite": "Кемпинги",
|
||||
"guesthouse": "Гостевые дома",
|
||||
"hotel": "Отели",
|
||||
"golfcourse": "Гольф",
|
||||
"touristinformation": "Информация для туристов",
|
||||
"monument": "Монументы/мемориалы",
|
||||
"chalet": "Шале",
|
||||
"tourism": "Все туристические места",
|
||||
"hostel": "Хостелы",
|
||||
"motel": "Мотели",
|
||||
"artscentre": "Центры искусств",
|
||||
"casino": "Казино",
|
||||
"windmill": "Ветряные мельницы",
|
||||
"watermill": "Водяные мельницы"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,13 +142,13 @@ export default class LinesLayer extends FeatureGroup {
|
|||
|
||||
highlightLine(id: ID): void {
|
||||
this.highlightedLinesIds.add(id);
|
||||
if (this.client.lines[id])
|
||||
if (this._map && this.client.lines[id])
|
||||
this.handleLine(this.client.lines[id]);
|
||||
}
|
||||
|
||||
unhighlightLine(id: ID): void {
|
||||
this.highlightedLinesIds.delete(id);
|
||||
if (this.client.lines[id])
|
||||
if (this._map && this.client.lines[id])
|
||||
this.handleLine(this.client.lines[id]);
|
||||
}
|
||||
|
||||
|
|
|
@ -104,13 +104,13 @@ export default class MarkersLayer extends MarkerCluster {
|
|||
|
||||
highlightMarker(id: ID): void {
|
||||
this.highlightedMarkerIds.add(id);
|
||||
if (this.client.markers[id])
|
||||
if (this._map && this.client.markers[id])
|
||||
this.handleMarker(this.client.markers[id]);
|
||||
}
|
||||
|
||||
unhighlightMarker(id: ID): void {
|
||||
this.highlightedMarkerIds.delete(id);
|
||||
if (this.client.markers[id])
|
||||
if (this._map && this.client.markers[id])
|
||||
this.handleMarker(this.client.markers[id]);
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ function getMarkerGpx(marker: Marker, type: Type): ReadableStream<string> {
|
|||
`\t<desc>${quoteHtml(dataToText(type.fields, marker.data))}</desc>\n` +
|
||||
`\t<extensions>\n` +
|
||||
(osmandBackground ? `\t\t<osmand:background>${osmandBackground}</osmand:background>\n` : "") +
|
||||
`\t\t<osmand:color>#${marker.colour}</osmand:color>\n` +
|
||||
`\t\t<osmand:color>#aa${marker.colour}</osmand:color>\n` +
|
||||
`\t</extensions>\n` +
|
||||
`</wpt>`
|
||||
);
|
||||
|
@ -235,7 +235,7 @@ function getLineMetadataGpx(line: LineForExport, type: Type | undefined): string
|
|||
}
|
||||
}, {
|
||||
...(line.colour ? {
|
||||
"osmand:color": `#${line.colour}`
|
||||
"osmand:color": `#aa${line.colour}`
|
||||
} : {}),
|
||||
...(line.width ? {
|
||||
"osmand:width": `${line.width}`
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -4013,7 +4013,7 @@ __metadata:
|
|||
leaflet-auto-graticule: ^2.0.0
|
||||
leaflet-draggable-lines: ^2.0.0
|
||||
leaflet-freie-tonne: ^2.0.1
|
||||
leaflet-highlightable-layers: ^3.0.0
|
||||
leaflet-highlightable-layers: ^3.0.1
|
||||
leaflet.markercluster: ^1.5.3
|
||||
lodash-es: ^4.17.21
|
||||
node-fetch: ^3.3.2
|
||||
|
@ -5490,12 +5490,12 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"leaflet-highlightable-layers@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "leaflet-highlightable-layers@npm:3.0.0"
|
||||
"leaflet-highlightable-layers@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "leaflet-highlightable-layers@npm:3.0.1"
|
||||
peerDependencies:
|
||||
leaflet: x
|
||||
checksum: b0ffe1210f5f5cde618866980589f41b4083e6361624bece3bd8f1cce9e0498ad8554bea5791d73ab95fe36aeb23094f4aa372773c0c96036dcedc94ff865703
|
||||
checksum: 7f9478533eb86cf411f247b38a446c25d3530d077349896ba55527c9bb9300b4162ad6786a74b62ca103b8941c839336216412fd5fb03f120e247da3cb0946bf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue