Skip to content

Commit 3bbbc6f

Browse files
committed
Expose MapviewAPI for programatic consumption of Search Providers
1 parent 76f956b commit 3bbbc6f

4 files changed

Lines changed: 122 additions & 89 deletions

File tree

src/geosearch.ts

Lines changed: 44 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { request, App } from 'obsidian';
1+
import { App } from 'obsidian';
22
import * as geosearch from 'leaflet-geosearch';
33
import * as leaflet from 'leaflet';
4-
import * as querystring from 'query-string';
54

65
import { PluginSettings } from 'src/settings';
76
import { UrlConvertor } from 'src/urlConvertor';
87
import { FileMarker } from 'src/markers';
98
import * as consts from 'src/consts';
9+
import { GooglePlacesAPI } from './google';
1010

1111
/**
1212
* A generic result of a geosearch
@@ -19,10 +19,18 @@ export class GeoSearchResult {
1919
existingMarker?: FileMarker;
2020
}
2121

22+
type searchProviderParms = {
23+
query: string;
24+
location?: string;
25+
};
26+
27+
export type GeoSearcherProvider =
28+
| geosearch.OpenStreetMapProvider
29+
| geosearch.GoogleProvider
30+
| GooglePlacesAPI;
31+
2232
export class GeoSearcher {
23-
private searchProvider:
24-
| geosearch.OpenStreetMapProvider
25-
| geosearch.GoogleProvider = null;
33+
public searchProvider: GeoSearcherProvider;
2634
private settings: PluginSettings;
2735
private urlConvertor: UrlConvertor;
2836

@@ -31,7 +39,9 @@ export class GeoSearcher {
3139
this.urlConvertor = new UrlConvertor(app, settings);
3240
if (settings.searchProvider == 'osm')
3341
this.searchProvider = new geosearch.OpenStreetMapProvider();
34-
else if (settings.searchProvider == 'google') {
42+
else if (this.usingGooglePlacesSearch) {
43+
this.searchProvider = new GooglePlacesAPI(settings);
44+
} else if (settings.searchProvider == 'google') {
3545
this.searchProvider = new geosearch.GoogleProvider({
3646
params: { key: settings.geocodingApiKey },
3747
});
@@ -59,97 +69,42 @@ export class GeoSearcher {
5969
});
6070
}
6171

62-
// Google Place results
63-
if (
64-
this.settings.searchProvider == 'google' &&
65-
this.settings.useGooglePlaces &&
66-
this.settings.geocodingApiKey
67-
) {
68-
try {
69-
const placesResults = await googlePlacesSearch(
70-
query,
71-
this.settings,
72-
searchArea?.getCenter()
73-
);
74-
for (const result of placesResults)
75-
results.push({
76-
name: result.name,
77-
location: result.location,
78-
resultType: 'searchResult',
79-
});
80-
} catch (e) {
81-
console.log(
82-
'Map View: Google Places search failed: ',
83-
e.message
84-
);
85-
}
86-
} else {
87-
const areaSW = searchArea?.getSouthWest() || null;
88-
const areaNE = searchArea?.getNorthEast() || null;
89-
let searchResults = await this.searchProvider.search({
90-
query: query,
91-
});
72+
let params: searchProviderParms = {
73+
query: query,
74+
};
75+
76+
if (this.usingGooglePlacesSearch() && searchArea) {
77+
const centerOfSearch = searchArea?.getCenter();
78+
params.location = `${centerOfSearch.lat},${centerOfSearch.lng}`;
79+
}
80+
let searchResults = await this.searchProvider.search(params);
81+
82+
if (!this.usingGooglePlacesSearch()) {
9283
searchResults = searchResults.slice(
9384
0,
9485
consts.MAX_EXTERNAL_SEARCH_SUGGESTIONS
9586
);
96-
results = results.concat(
97-
searchResults.map(
98-
(result) =>
99-
({
100-
name: result.label,
101-
location: new leaflet.LatLng(result.y, result.x),
102-
resultType: 'searchResult',
103-
} as GeoSearchResult)
104-
)
105-
);
10687
}
10788

89+
results = results.concat(
90+
searchResults.map(
91+
(result) =>
92+
({
93+
name: result.label,
94+
location: new leaflet.LatLng(result.y, result.x),
95+
resultType: 'searchResult',
96+
} as GeoSearchResult)
97+
)
98+
);
99+
108100
return results;
109101
}
110-
}
111102

112-
export async function googlePlacesSearch(
113-
query: string,
114-
settings: PluginSettings,
115-
centerOfSearch: leaflet.LatLng | null
116-
): Promise<GeoSearchResult[]> {
117-
if (settings.searchProvider != 'google' || !settings.useGooglePlaces)
118-
return [];
119-
const googleApiKey = settings.geocodingApiKey;
120-
const params = {
121-
query: query,
122-
key: googleApiKey,
123-
};
124-
if (centerOfSearch)
125-
(params as any)[
126-
'location'
127-
] = `${centerOfSearch.lat},${centerOfSearch.lng}`;
128-
const googleUrl =
129-
'https://maps.googleapis.com/maps/api/place/textsearch/json?' +
130-
querystring.stringify(params);
131-
const googleContent = await request({ url: googleUrl });
132-
const jsonContent = JSON.parse(googleContent) as any;
133-
let results: GeoSearchResult[] = [];
134-
if (
135-
jsonContent &&
136-
'results' in jsonContent &&
137-
jsonContent?.results.length > 0
138-
) {
139-
for (const result of jsonContent.results) {
140-
const location = result.geometry?.location;
141-
if (location && location.lat && location.lng) {
142-
const geolocation = new leaflet.LatLng(
143-
location.lat,
144-
location.lng
145-
);
146-
results.push({
147-
name: `${result?.name} (${result?.formatted_address})`,
148-
location: geolocation,
149-
resultType: 'searchResult',
150-
} as GeoSearchResult);
151-
}
152-
}
103+
usingGooglePlacesSearch(): Boolean {
104+
return (
105+
this.settings.searchProvider == 'google' &&
106+
this.settings.useGooglePlaces &&
107+
this.settings.geocodingApiKey !== null
108+
);
153109
}
154-
return results;
155110
}

src/google.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { PluginSettings } from './settings';
2+
import * as leaflet from 'leaflet';
3+
import { request } from 'obsidian';
4+
import * as querystring from 'query-string';
5+
import { GeoSearchResult } from './geosearch';
6+
import { SearchResult } from 'leaflet-geosearch/dist/providers/provider';
7+
8+
export type GooglePlacesAPIQuery = { [key: string]: string };
9+
10+
export class GooglePlacesAPI {
11+
private googleApiKey: string;
12+
13+
constructor(settings: PluginSettings) {
14+
this.googleApiKey = settings.geocodingApiKey;
15+
}
16+
17+
async googlePlacesRequest(
18+
query: GooglePlacesAPIQuery,
19+
scope: string
20+
): Promise<{}> {
21+
query.key = this.googleApiKey;
22+
const googleUrl = `https://maps.googleapis.com/maps/api/place/${scope}/json?${querystring.stringify(
23+
query
24+
)}`;
25+
const googleContent = await request({ url: googleUrl });
26+
return JSON.parse(googleContent) as any;
27+
}
28+
29+
async search(query: GooglePlacesAPIQuery): Promise<SearchResult[]> {
30+
let jsonContent: any = await this.googlePlacesSearch(query);
31+
32+
let results: SearchResult[] = [];
33+
if (
34+
jsonContent &&
35+
'results' in jsonContent &&
36+
jsonContent?.results.length > 0
37+
) {
38+
for (const result of jsonContent.results) {
39+
const location = result.geometry?.location;
40+
if (location && location.lat && location.lng) {
41+
results.push({
42+
label: `${result?.name} (${result?.formatted_address})`,
43+
y: location.lat,
44+
x: location.lng,
45+
} as any);
46+
}
47+
}
48+
}
49+
return results;
50+
}
51+
52+
async googlePlacesSearch(query: GooglePlacesAPIQuery): Promise<{}> {
53+
return await this.googlePlacesRequest(query, 'textsearch');
54+
}
55+
56+
async googlePlacesDetailsSearch(placeId: string): Promise<{}> {
57+
const params = {
58+
place_id: placeId,
59+
};
60+
return this.googlePlacesRequest(params, 'details');
61+
}
62+
}

src/main.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ import { SettingsTab } from 'src/settingsTab';
4040
import { LocationSearchDialog } from 'src/locationSearchDialog';
4141
import { TagSuggest } from 'src/tagSuggest';
4242
import * as utils from 'src/utils';
43+
import { MapviewAPI } from './mapviewAPI';
4344

4445
export default class MapViewPlugin extends Plugin {
4546
settings: PluginSettings;
4647
public highestVersionSeen: number = 0;
4748
public iconCache: IconCache;
49+
public mapviewAPI: MapviewAPI;
4850
private suggestor: LocationSuggest;
4951
private tagSuggestor: TagSuggest;
5052
private urlConvertor: UrlConvertor;
@@ -138,6 +140,7 @@ export default class MapViewPlugin extends Plugin {
138140
);
139141

140142
this.suggestor = new LocationSuggest(this.app, this.settings);
143+
this.mapviewAPI = new MapviewAPI(this.app, this.settings);
141144
this.tagSuggestor = new TagSuggest(this.app, this.settings);
142145
this.urlConvertor = new UrlConvertor(this.app, this.settings);
143146

src/mapviewAPI.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { App } from 'obsidian';
2+
import { GeoSearcher, GeoSearcherProvider } from './geosearch';
3+
import { PluginSettings } from 'src/settings';
4+
5+
export class MapviewAPI {
6+
public searchProvider: GeoSearcherProvider;
7+
public searcher: GeoSearcher;
8+
9+
constructor(app: App, settings: PluginSettings) {
10+
this.searcher = new GeoSearcher(app, settings);
11+
this.searchProvider = this.searcher.searchProvider;
12+
}
13+
}

0 commit comments

Comments
 (0)