keep photo viewer state on reset, properly clean up active marker

when switching between photos from different providers

fixes #10987
This commit is contained in:
Martin Raifer
2025-04-29 09:33:30 +02:00
parent 4dc4e7dbdc
commit 19957d0e39
11 changed files with 64 additions and 65 deletions

View File

@@ -7,6 +7,7 @@ import RBush from 'rbush';
import { localizer } from '../core/localizer'; import { localizer } from '../core/localizer';
import { geoExtent, geoScaleToZoom } from '../geo'; import { geoExtent, geoScaleToZoom } from '../geo';
import { utilQsString, utilRebind, utilSetTransform, utilStringQs, utilTiler } from '../util'; import { utilQsString, utilRebind, utilSetTransform, utilStringQs, utilTiler } from '../util';
import { services } from './';
var apibase = 'https://kartaview.org'; var apibase = 'https://kartaview.org';
@@ -191,8 +192,6 @@ export default {
images: { inflight: {}, loaded: {}, nextPage: {}, rtree: new RBush(), forImageKey: {} }, images: { inflight: {}, loaded: {}, nextPage: {}, rtree: new RBush(), forImageKey: {} },
sequences: {} sequences: {}
}; };
_oscSelectedImage = null;
}, },
@@ -368,21 +367,22 @@ export default {
showViewer: function(context) { showViewer: function(context) {
var viewer = context.container().select('.photoviewer') var viewer = context.container().select('.photoviewer');
.classed('hide', false);
var isHidden = viewer.selectAll('.photo-wrapper.kartaview-wrapper.hide').size(); var isHidden = viewer.selectAll('.photo-wrapper.kartaview-wrapper.hide').size();
if (isHidden) { if (isHidden) {
viewer for (const service of Object.values(services)) {
.selectAll('.photo-wrapper:not(.kartaview-wrapper)') if (service === this) continue;
.classed('hide', true); if (typeof service.hideViewer === 'function') {
service.hideViewer(context);
}
}
viewer viewer
.selectAll('.photo-wrapper.kartaview-wrapper') .selectAll('.photo-wrapper.kartaview-wrapper')
.classed('hide', false); .classed('hide', false);
} }
viewer.classed('hide', false);
return this; return this;
}, },

View File

@@ -10,6 +10,7 @@ import { isEqual } from 'lodash';
import { utilRebind, utilTiler, utilQsString, utilStringQs, utilSetTransform } from '../util'; import { utilRebind, utilTiler, utilQsString, utilStringQs, utilSetTransform } from '../util';
import {geoExtent, geoScaleToZoom} from '../geo'; import {geoExtent, geoScaleToZoom} from '../geo';
import {localizer} from '../core/localizer'; import {localizer} from '../core/localizer';
import { services } from './';
const apiUrl = 'https://end.mapilio.com'; const apiUrl = 'https://end.mapilio.com';
const imageBaseUrl = 'https://cdn.mapilio.com/im'; const imageBaseUrl = 'https://cdn.mapilio.com/im';
@@ -222,8 +223,6 @@ export default {
sequences: { rtree: new RBush(), lineString: {} }, sequences: { rtree: new RBush(), lineString: {} },
requests: { loaded: {}, inflight: {} } requests: { loaded: {}, inflight: {} }
}; };
_activeImage = null;
}, },
// Get visible images // Get visible images
@@ -575,21 +574,22 @@ export default {
}, },
showViewer:function (context) { showViewer:function (context) {
let wrap = context.container().select('.photoviewer') let wrap = context.container().select('.photoviewer');
.classed('hide', false);
let isHidden = wrap.selectAll('.photo-wrapper.mapilio-wrapper.hide').size(); let isHidden = wrap.selectAll('.photo-wrapper.mapilio-wrapper.hide').size();
if (isHidden) { if (isHidden) {
wrap for (const service of Object.values(services)) {
.selectAll('.photo-wrapper:not(.mapilio-wrapper)') if (service === this) continue;
.classed('hide', true); if (typeof service.hideViewer === 'function') {
service.hideViewer(context);
}
}
wrap wrap
.selectAll('.photo-wrapper.mapilio-wrapper') .selectAll('.photo-wrapper.mapilio-wrapper')
.classed('hide', false); .classed('hide', false);
} }
wrap.classed('hide', false);
return this; return this;
}, },

View File

@@ -8,6 +8,7 @@ import { VectorTile } from '@mapbox/vector-tile';
import { geoExtent, geoScaleToZoom } from '../geo'; import { geoExtent, geoScaleToZoom } from '../geo';
import { utilQsString, utilRebind, utilTiler, utilStringQs } from '../util'; import { utilQsString, utilRebind, utilTiler, utilStringQs } from '../util';
import { services } from './';
const accessToken = 'MLY|4100327730013843|5bb78b81720791946a9a7b956c57b7cf'; const accessToken = 'MLY|4100327730013843|5bb78b81720791946a9a7b956c57b7cf';
const apiUrl = 'https://graph.mapillary.com/'; const apiUrl = 'https://graph.mapillary.com/';
@@ -260,8 +261,6 @@ export default {
sequences: { rtree: new RBush(), lineString: {} }, sequences: { rtree: new RBush(), lineString: {} },
requests: { loaded: {}, inflight: {} } requests: { loaded: {}, inflight: {} }
}; };
_mlyActiveImage = null;
}, },
// Get visible images // Get visible images
@@ -465,15 +464,16 @@ export default {
// Make the image viewer visible // Make the image viewer visible
showViewer: function(context) { showViewer: function(context) {
const wrap = context.container().select('.photoviewer') const wrap = context.container().select('.photoviewer');
.classed('hide', false);
const isHidden = wrap.selectAll('.photo-wrapper.mly-wrapper.hide').size(); const isHidden = wrap.selectAll('.photo-wrapper.mly-wrapper.hide').size();
if (isHidden && _mlyViewer) { if (isHidden && _mlyViewer) {
wrap for (const service of Object.values(services)) {
.selectAll('.photo-wrapper:not(.mly-wrapper)') if (service === this) continue;
.classed('hide', true); if (typeof service.hideViewer === 'function') {
service.hideViewer(context);
}
}
wrap wrap
.selectAll('.photo-wrapper.mly-wrapper') .selectAll('.photo-wrapper.mly-wrapper')
@@ -483,6 +483,7 @@ export default {
} }
_isViewerOpen = true; _isViewerOpen = true;
wrap.classed('hide', false);
return this; return this;
}, },

View File

@@ -9,6 +9,8 @@ import { geoExtent, geoScaleToZoom } from '../geo';
import { t, localizer } from '../core/localizer'; import { t, localizer } from '../core/localizer';
import pannellumPhotoFrame from './pannellum_photo'; import pannellumPhotoFrame from './pannellum_photo';
import planePhotoFrame from './plane_photo'; import planePhotoFrame from './plane_photo';
import { services } from './';
const apiUrl = 'https://api.panoramax.xyz/'; const apiUrl = 'https://api.panoramax.xyz/';
const tileUrl = apiUrl + 'api/map/{z}/{x}/{y}.mvt'; const tileUrl = apiUrl + 'api/map/{z}/{x}/{y}.mvt';
@@ -255,9 +257,6 @@ export default {
mockSequences: { rtree: new RBush(), lineString: {} }, mockSequences: { rtree: new RBush(), lineString: {} },
requests: { loaded: {}, inflight: {} } requests: { loaded: {}, inflight: {} }
}; };
_currentScene.currentImage = null;
_activeImage = null;
}, },
/** /**
@@ -685,19 +684,22 @@ export default {
* @param {*} context * @param {*} context
*/ */
showViewer: function (context) { showViewer: function (context) {
let wrap = context.container().select('.photoviewer') let wrap = context.container().select('.photoviewer');
.classed('hide', false);
let isHidden = wrap.selectAll('.photo-wrapper.panoramax-wrapper.hide').size(); let isHidden = wrap.selectAll('.photo-wrapper.panoramax-wrapper.hide').size();
if (isHidden) { if (isHidden) {
wrap for (const service of Object.values(services)) {
.selectAll('.photo-wrapper:not(.panoramax-wrapper)') if (service === this) continue;
.classed('hide', true); if (typeof service.hideViewer === 'function') {
service.hideViewer(context);
}
}
wrap wrap
.selectAll('.photo-wrapper.panoramax-wrapper') .selectAll('.photo-wrapper.panoramax-wrapper')
.classed('hide', false); .classed('hide', false);
} }
_isViewerOpen = true; _isViewerOpen = true;
wrap.classed('hide', false);
return this; return this;
}, },

View File

@@ -15,6 +15,8 @@ import {
import { utilAesDecrypt, utilArrayUnion, utilQsString, utilRebind, utilStringQs, utilTiler, utilUniqueDomId } from '../util'; import { utilAesDecrypt, utilArrayUnion, utilQsString, utilRebind, utilStringQs, utilTiler, utilUniqueDomId } from '../util';
import { services } from './';
const streetsideApi = 'https://dev.virtualearth.net/REST/v1/Imagery/MetaData/Streetside?mapArea={bbox}&key={key}&count={count}&uriScheme=https'; const streetsideApi = 'https://dev.virtualearth.net/REST/v1/Imagery/MetaData/Streetside?mapArea={bbox}&key={key}&count={count}&uriScheme=https';
const maxResults = 500; const maxResults = 500;
@@ -644,22 +646,22 @@ export default {
* showViewer() * showViewer()
*/ */
showViewer: function(context) { showViewer: function(context) {
let wrap = context.container().select('.photoviewer');
let wrap = context.container().select('.photoviewer')
.classed('hide', false);
let isHidden = wrap.selectAll('.photo-wrapper.ms-wrapper.hide').size(); let isHidden = wrap.selectAll('.photo-wrapper.ms-wrapper.hide').size();
if (isHidden) { if (isHidden) {
wrap for (const service of Object.values(services)) {
.selectAll('.photo-wrapper:not(.ms-wrapper)') if (service === this) continue;
.classed('hide', true); if (typeof service.hideViewer === 'function') {
service.hideViewer(context);
}
}
wrap wrap
.selectAll('.photo-wrapper.ms-wrapper') .selectAll('.photo-wrapper.ms-wrapper')
.classed('hide', false); .classed('hide', false);
} }
wrap.classed('hide', false);
return this; return this;
}, },

View File

@@ -8,6 +8,7 @@ import { utilQsString, utilTiler, utilRebind, utilArrayUnion, utilStringQs} from
import {geoExtent, geoScaleToZoom, geoVecAngle, geoVecEqual} from '../geo'; import {geoExtent, geoScaleToZoom, geoVecAngle, geoVecEqual} from '../geo';
import pannellumPhotoFrame from './pannellum_photo'; import pannellumPhotoFrame from './pannellum_photo';
import planePhotoFrame from './plane_photo'; import planePhotoFrame from './plane_photo';
import { services } from './';
const owsEndpoint = 'https://www.vegvesen.no/kart/ogc/vegbilder_1_0/ows?'; const owsEndpoint = 'https://www.vegvesen.no/kart/ogc/vegbilder_1_0/ows?';
@@ -493,20 +494,21 @@ export default {
}, },
showViewer: function (context) { showViewer: function (context) {
const viewer = context.container().select('.photoviewer') const viewer = context.container().select('.photoviewer');
.classed('hide', false);
const isHidden = viewer.selectAll('.photo-wrapper.vegbilder-wrapper.hide').size(); const isHidden = viewer.selectAll('.photo-wrapper.vegbilder-wrapper.hide').size();
if (isHidden) { if (isHidden) {
viewer for (const service of Object.values(services)) {
.selectAll('.photo-wrapper:not(.vegbilder-wrapper)') if (service === this) continue;
.classed('hide', true); if (typeof service.hideViewer === 'function') {
service.hideViewer(context);
}
}
viewer viewer
.selectAll('.photo-wrapper.vegbilder-wrapper') .selectAll('.photo-wrapper.vegbilder-wrapper')
.classed('hide', false); .classed('hide', false);
} }
viewer.classed('hide', false);
return this; return this;
}, },

View File

@@ -233,10 +233,6 @@ export function svgPanoramaxImages(projection, context, dispatch) {
let images = (service && zoom >= imageMinZoom ? service.images(projection) : []); let images = (service && zoom >= imageMinZoom ? service.images(projection) : []);
dispatch.call('photoDatesChanged', this, 'panoramax', [...images.map(p => p.capture_time), ...sequences.map(s => s.properties.date)]); dispatch.call('photoDatesChanged', this, 'panoramax', [...images.map(p => p.capture_time), ...sequences.map(s => s.properties.date)]);
let isHidden = d3_select('.photo-wrapper.panoramax-wrapper.hide').size();
if (isHidden) service.setActiveImage(null);
images = await filterImages(images); images = await filterImages(images);
sequences = await filterSequences(sequences, service); sequences = await filterSequences(sequences, service);

View File

@@ -26,12 +26,11 @@ export function uiPhotoviewer(context) {
.attr('class', 'thumb-hide') .attr('class', 'thumb-hide')
.attr('title', t('icons.close')) .attr('title', t('icons.close'))
.on('click', function () { .on('click', function () {
if (services.streetside) { services.streetside.hideViewer(context); } for (const service of Object.values(services)) {
if (services.mapillary) { services.mapillary.hideViewer(context); } if (typeof service.hideViewer === 'function') {
if (services.kartaview) { services.kartaview.hideViewer(context); } service.hideViewer(context);
if (services.mapilio) { services.mapilio.hideViewer(context); } }
if (services.panoramax) { services.panoramax.hideViewer(context); } }
if (services.vegbilder) { services.vegbilder.hideViewer(context); }
}) })
.append('div') .append('div')
.call(svgIcon('#iD-icon-close')); .call(svgIcon('#iD-icon-close'));

View File

@@ -43,13 +43,12 @@ describe('iD.serviceKartaview', function() {
}); });
describe('#reset', function() { describe('#reset', function() {
it('resets cache and image', function() { it('resets cache', function() {
kartaview.cache().foo = 'bar'; kartaview.cache().foo = 'bar';
kartaview.selectImage(context, {key: 'baz'}); kartaview.selectImage(context, {key: 'baz'});
kartaview.reset(); kartaview.reset();
expect(kartaview.cache()).to.not.have.property('foo'); expect(kartaview.cache()).to.not.have.property('foo');
expect(kartaview.getSelectedImage()).to.be.null;
}); });
}); });

View File

@@ -42,13 +42,12 @@ describe('iD.serviceMapillary', function() {
describe('#reset', function() { describe('#reset', function() {
it('resets cache and image', function() { it('resets cache', function() {
mapillary.cache().foo = 'bar'; mapillary.cache().foo = 'bar';
mapillary.selectImage(context, { key: 'baz', loc: [10,0] }); mapillary.selectImage(context, { key: 'baz', loc: [10,0] });
mapillary.reset(); mapillary.reset();
expect(mapillary.cache()).to.not.have.property('foo'); expect(mapillary.cache()).to.not.have.property('foo');
expect(mapillary.getActiveImage()).to.be.null;
}); });
}); });

View File

@@ -79,13 +79,12 @@ describe('iD.servicePanoramax', function() {
}); });
describe('#reset', function() { describe('#reset', function() {
it('resets cache and image', function() { it('resets cache', function() {
panoramax.cache().foo = 'bar'; panoramax.cache().foo = 'bar';
panoramax.setActiveImage(context, {key: 'baz'}); panoramax.setActiveImage(context, {key: 'baz'});
panoramax.reset(); panoramax.reset();
expect(panoramax.cache()).to.not.have.property('foo'); expect(panoramax.cache()).to.not.have.property('foo');
expect(panoramax.getActiveImage()).to.be.null;
}); });
}); });