Skip to content

Commit 05516e3

Browse files
committed
more tweaks to map
1 parent e23fddc commit 05516e3

12 files changed

Lines changed: 117 additions & 70 deletions

src/cli/steps/export.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ function parseMapStyle(style: string | undefined): MapStyle | undefined {
161161

162162
/**
163163
* Extract image attributions from ImageResult objects.
164-
* Converts ImageResult.meta.attribution to ImageAttribution format.
164+
* Converts ImageResult.meta to ImageAttribution format.
165165
*
166166
* Only sources with meaningful attribution are included:
167167
* - wikipedia, pixabay, unsplash
@@ -179,16 +179,13 @@ function extractImageAttributions(
179179
// Only include sources that have meaningful artist attribution
180180
const source = mapToAttributionSource(result.meta.source)
181181
if (source) {
182-
const attr: ImageAttribution = {
182+
attributions.set(activityId, {
183183
name: result.meta.attribution.name,
184-
url: result.meta.attribution.url,
184+
photoUrl: result.meta.url, // URL to the photo/place page
185+
authorUrl: result.meta.attribution.url || undefined, // Empty string → undefined
186+
license: source === 'wikipedia' ? result.meta.license : undefined, // Only show license for Wikipedia
185187
source
186-
}
187-
// Only add license if defined (exactOptionalPropertyTypes)
188-
if (result.meta.license !== undefined) {
189-
;(attr as { license: string }).license = result.meta.license
190-
}
191-
attributions.set(activityId, attr)
188+
})
192189
}
193190
}
194191
}
@@ -206,16 +203,15 @@ function mapToAttributionSource(
206203
switch (source) {
207204
case 'wikipedia':
208205
case 'pixabay':
209-
return source
210206
case 'unsplash':
211-
return 'unsplash'
212207
case 'google_places':
208+
return source
213209
case 'user_upload':
214210
case 'unsplash+':
215211
// These sources don't have artist attribution to display
216212
return null
217213
default:
218-
return 'other'
214+
return null
219215
}
220216
}
221217

src/export/map/activity-list.js.template

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,13 @@ function attachLightboxHandlers(sorted) {
9797
window.openLightbox(lightboxImage, a.activity, a.imageAttribution)
9898
})
9999

100-
if (a.imageAttribution) {
101-
thumb.addEventListener('mouseenter', function () {
102-
showAttributionTooltip(thumb, a.imageAttribution.text)
103-
})
104-
thumb.addEventListener('mouseleave', hideTooltip)
105-
}
100+
// Attribution shown in lightbox - tooltip too noisy
101+
// if (a.imageAttribution) {
102+
// thumb.addEventListener('mouseenter', function () {
103+
// showAttributionTooltip(thumb, a.imageAttribution)
104+
// })
105+
// thumb.addEventListener('mouseleave', hideTooltip)
106+
// }
106107
})
107108
}
108109

src/export/map/app.js.template

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
return
88
}
99

10-
// Initialize map
11-
var map = L.map('map').setView([mapData.center.lat, mapData.center.lng], mapData.zoom)
10+
// Initialize map (map and currentTileLayer are global for setMapStyle)
11+
map = L.map('map').setView([mapData.center.lat, mapData.center.lng], mapData.zoom)
1212

13-
var currentTileLayer = L.tileLayer(tileStyles[currentStyle].url, {
13+
currentTileLayer = L.tileLayer(tileStyles[currentStyle].url, {
1414
attribution: tileStyles[currentStyle].attribution
1515
}).addTo(map)
1616

@@ -36,7 +36,7 @@
3636
}
3737

3838
// Setup popup tooltip handlers
39-
setupPopupTooltips()
39+
setupPopupTooltips(map)
4040

4141
// Render info box
4242
document.getElementById('infoTitle').textContent = mapData.title

src/export/map/data.ts

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -106,33 +106,13 @@ function toMapActivities(
106106

107107
/**
108108
* Format attribution info for display.
109-
* Creates user-friendly text like "Photo by X on Unsplash" or "Photo by X via Wikipedia (CC-BY-SA)"
110109
*/
111110
function formatAttribution(attr: ImageAttribution): MapImageAttribution {
112-
let text: string
113-
114-
switch (attr.source) {
115-
case 'unsplash':
116-
text = `Photo by ${attr.name} on Unsplash`
117-
break
118-
case 'wikipedia':
119-
text = attr.license ? `Photo by ${attr.name} (${attr.license})` : `Photo by ${attr.name}`
120-
break
121-
case 'pixabay':
122-
text = `Photo by ${attr.name} on Pixabay`
123-
break
124-
case 'media_library':
125-
// Media library images may have various sources
126-
text = attr.name
127-
break
128-
default:
129-
text = `Photo by ${attr.name}`
130-
}
131-
132111
return {
133112
name: attr.name,
134-
url: attr.url,
113+
photoUrl: attr.photoUrl,
114+
authorUrl: attr.authorUrl,
135115
license: attr.license,
136-
text
116+
source: attr.source
137117
}
138118
}

src/export/map/lightbox.js.template

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ window.openLightbox = function (imagePath, title, attribution) {
1818
document.getElementById('lightboxTitle').textContent = title
1919
var attrEl = document.getElementById('lightboxAttribution')
2020
if (attribution) {
21-
attrEl.innerHTML = '<a href="' + escapeHtml(attribution.url) + '" target="_blank">' +
22-
escapeHtml(attribution.text) + '</a>'
21+
attrEl.innerHTML = formatAttributionHtml(attribution)
2322
attrEl.style.display = 'block'
2423
} else {
2524
attrEl.style.display = 'none'

src/export/map/markers.js.template

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@ function createMarkers(markersLayer) {
1313
var imageHtml = ''
1414
var popupImage = p.mediumImagePath || p.imagePath
1515
if (popupImage) {
16-
imageHtml = '<img src="' +
17-
escapeHtml(popupImage) +
18-
'" style="display:block;width:100%;max-width:200px;border-radius:4px;margin-bottom:4px;" />'
19-
if (p.imageAttribution) {
20-
imageHtml += '<a href="' + escapeHtml(p.imageAttribution.url) +
21-
'" target="_blank" class="img-attribution">' +
22-
escapeHtml(p.imageAttribution.text) + '</a>'
23-
}
16+
var attrOverlay = p.imageAttribution
17+
? '<div class="img-attr-overlay">' + formatAttributionHtml(p.imageAttribution) + '</div>'
18+
: ''
19+
imageHtml = '<div class="img-container">' +
20+
'<img src="' + escapeHtml(popupImage) + '" />' +
21+
attrOverlay + '</div>'
2422
}
2523

2624
var mapsUrl = p.placeId
@@ -99,7 +97,7 @@ function createMarkers(markersLayer) {
9997
return geocodedPoints
10098
}
10199

102-
function setupPopupTooltips() {
100+
function setupPopupTooltips(map) {
103101
map.on('popupopen', function () {
104102
var triggers = document.querySelectorAll('.leaflet-popup .sender-trigger[data-messages]')
105103
triggers.forEach(function (trigger) {

src/export/map/styles.css.template

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,38 @@ body { margin: 0; padding: 0; }
235235
}
236236
.img-attribution:hover { text-decoration: underline; color: #4b5563; }
237237

238+
/* Popup image with attribution overlay */
239+
.img-container {
240+
position: relative;
241+
display: block;
242+
width: 240px;
243+
margin-bottom: 8px;
244+
overflow: hidden;
245+
border-radius: 4px;
246+
}
247+
.img-container img {
248+
display: block;
249+
width: 100%;
250+
}
251+
.img-attr-overlay {
252+
position: absolute;
253+
bottom: 0;
254+
left: 0;
255+
right: 0;
256+
padding: 16px 8px 6px;
257+
background: linear-gradient(to top, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 100%);
258+
color: rgba(255,255,255,0.7);
259+
font-size: 8px;
260+
line-height: 1.3;
261+
}
262+
.img-attr-overlay a {
263+
color: rgba(255,255,255,0.7);
264+
text-decoration: underline;
265+
}
266+
.img-attr-overlay a:hover {
267+
color: rgba(255,255,255,0.7);
268+
}
269+
238270
/* Clickable thumbnail with cursor */
239271
.activity-thumb-wrapper.has-image {
240272
cursor: pointer;

src/export/map/tiles.js.template

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/* Tile layer styles */
2+
var map = null
3+
var currentTileLayer = null
4+
25
var tileStyles = {
36
osm: {
47
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',

src/export/map/tooltip.js.template

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,31 @@ function escapeHtml(str) {
77
return escapeDiv.innerHTML
88
}
99

10+
var SERVICE_INFO = {
11+
wikipedia: { name: 'Wikipedia', url: 'https://wikipedia.org' },
12+
unsplash: { name: 'Unsplash', url: 'https://unsplash.com' },
13+
pixabay: { name: 'Pixabay', url: 'https://pixabay.com' },
14+
google_places: { name: 'Google', url: 'https://maps.google.com' }
15+
}
16+
17+
function formatAttributionHtml(attr) {
18+
var service = SERVICE_INFO[attr.source] || { name: attr.source, url: '#' }
19+
20+
var authorHtml = attr.authorUrl
21+
? '<a href="' + escapeHtml(attr.authorUrl) + '" target="_blank">' + escapeHtml(attr.name) + '</a>'
22+
: escapeHtml(attr.name)
23+
24+
var html = '<a href="' + escapeHtml(attr.photoUrl) + '" target="_blank">Photo</a> by ' +
25+
authorHtml + ' on ' +
26+
'<a href="' + escapeHtml(service.url) + '" target="_blank">' + service.name + '</a>'
27+
28+
if (attr.license) {
29+
html += ' (' + escapeHtml(attr.license) + ')'
30+
}
31+
32+
return html
33+
}
34+
1035
function formatSenders(messages) {
1136
var uniqueSenders = []
1237
var seen = {}
@@ -50,12 +75,21 @@ function showTooltip(trigger, messages) {
5075
positionTooltip(trigger, false)
5176
}
5277

53-
function showAttributionTooltip(trigger, text) {
78+
function showAttributionTooltip(trigger, attr) {
5479
floatingTooltip.className = 'tooltip-simple'
55-
floatingTooltip.innerHTML = '<div style="color:#e5e7eb;">' + escapeHtml(text) + '</div>'
80+
floatingTooltip.innerHTML = '<div style="color:#e5e7eb;">' + formatAttributionText(attr) + '</div>'
5681
positionTooltip(trigger, true)
5782
}
5883

84+
function formatAttributionText(attr) {
85+
var service = SERVICE_INFO[attr.source] || { name: attr.source }
86+
var text = 'Photo by ' + escapeHtml(attr.name) + ' on ' + service.name
87+
if (attr.license) {
88+
text += ' (' + escapeHtml(attr.license) + ')'
89+
}
90+
return text
91+
}
92+
5993
function positionTooltip(trigger, center) {
6094
var rect = trigger.getBoundingClientRect()
6195
floatingTooltip.style.display = 'block'

src/export/map/types.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ interface MapMessage {
1414
export interface MapImageAttribution {
1515
/** Artist/photographer name */
1616
name: string
17-
/** Link to source page */
18-
url: string
19-
/** License (e.g., "CC-BY-SA 4.0") */
17+
/** Link to the photo page */
18+
photoUrl: string
19+
/** Link to the author's profile (may be undefined for Google Places) */
20+
authorUrl: string | undefined
21+
/** License (only for Wikipedia) */
2022
license: string | undefined
21-
/** Formatted attribution text (e.g., "Photo by X on Unsplash") */
22-
text: string
23+
/** Source platform */
24+
source: 'wikipedia' | 'unsplash' | 'pixabay' | 'google_places'
2325
}
2426

2527
export interface MapActivity {

0 commit comments

Comments
 (0)