Share Dialog with QR Code (#729)
This commit is contained in:
parent
c715d2bab1
commit
3b3357c473
8 changed files with 401 additions and 7 deletions
150
js/control/ShareRoute.js
Normal file
150
js/control/ShareRoute.js
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
BR.ShareRoute = L.Class.extend({
|
||||
/**
|
||||
* Sharing via Mastodon is currently disabled by default, because
|
||||
* the share intent fails when the current route URL is longer
|
||||
* than the post character limit for that instance.
|
||||
*/
|
||||
options: {
|
||||
services: {
|
||||
mastodon: false,
|
||||
},
|
||||
shortcut: {
|
||||
share_action: 65, // char code for 'a' ("action")
|
||||
},
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
L.DomUtil.get('shareButton').onclick = L.bind(this.share, this);
|
||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||
},
|
||||
|
||||
share: function (event) {
|
||||
event.preventDefault();
|
||||
this.services();
|
||||
this.qrcode();
|
||||
},
|
||||
|
||||
services: function () {
|
||||
const self = this;
|
||||
|
||||
$('.share-copy-link').on('click', function () {
|
||||
navigator.clipboard.writeText(self.getShareUrl());
|
||||
});
|
||||
|
||||
$('a.share-service').each(function () {
|
||||
$(this).attr('href', $(this).attr('href').replace('{url}', encodeURIComponent(self.getShareUrl())));
|
||||
});
|
||||
|
||||
if (this.options.services.mastodon === true) {
|
||||
$('.share-service-mastodon')
|
||||
.removeAttr('hidden')
|
||||
.on('click', function () {
|
||||
let mastodonServer = window.prompt(
|
||||
i18next.t('share.mastodon-enter-server-name'),
|
||||
'mastodon.social'
|
||||
);
|
||||
if (mastodonServer.indexOf('http') !== 0) {
|
||||
mastodonServer = 'https://' + mastodonServer;
|
||||
}
|
||||
window.open(mastodonServer + '/share?text=' + encodeURIComponent(self.getShareUrl()), '_blank');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders QR Code for the current route:
|
||||
*
|
||||
* - add query parameter `?export=dialog` to the current URL
|
||||
* - displays QR Code for that URL in the dialog, size is automatically adjusted
|
||||
* to the length of the URL
|
||||
* - displays buttons to change the size of the QR Code (small, medium, large)
|
||||
*/
|
||||
qrcode: function () {
|
||||
const exportUrl = this.createQrCodeUrl();
|
||||
|
||||
this.renderQrCode('share-qrcode-img', exportUrl, this.getQrCodeSizeForUrl(exportUrl));
|
||||
|
||||
$('.qrcode-size-button').on('click', { shareRoute: this, url: exportUrl }, function (event) {
|
||||
event.data.shareRoute.renderQrCode('share-qrcode-img', event.data.url, $(this).data('qrcodeSize'));
|
||||
});
|
||||
},
|
||||
|
||||
getQrCodeSizeForUrl: function (url) {
|
||||
if (url.length < 500) {
|
||||
return 256;
|
||||
}
|
||||
|
||||
if (url.length < 1700) {
|
||||
return 384;
|
||||
}
|
||||
|
||||
return 512;
|
||||
},
|
||||
|
||||
renderQrCode: function (elementId, url, size) {
|
||||
$('#share-qrcode-img').empty();
|
||||
$('#qrcode-buttons').show();
|
||||
$('#qrcode-msg-unknown-error').hide();
|
||||
$('#qrcode-msg-too-long').hide();
|
||||
|
||||
try {
|
||||
new QRCode(document.getElementById(elementId), {
|
||||
text: url,
|
||||
width: size,
|
||||
height: size,
|
||||
colorDark: '#000000',
|
||||
colorLight: '#ffffff',
|
||||
correctLevel: QRCode.CorrectLevel.M,
|
||||
});
|
||||
} catch (exception) {
|
||||
$('#share-qrcode-img').empty();
|
||||
$('#qrcode-buttons').hide();
|
||||
if (exception.message === 'Too long data') {
|
||||
$('#qrcode-msg-too-long').show();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
console.error('Cannot create QR Code', exception);
|
||||
$('#qrcode-msg-unknown-error').show();
|
||||
}
|
||||
},
|
||||
|
||||
createQrCodeUrl: function () {
|
||||
// We work on a copy of the current location instance to avoid
|
||||
// reloading the page (which will happen when the `export` query
|
||||
// parameter is added to the actual location object):
|
||||
const exportLocation = new URL(document.location.href);
|
||||
const searchParams = new URLSearchParams(exportLocation.search);
|
||||
|
||||
// We've to provide a value to the query parameter here, because
|
||||
// URLSearchParams uses a list of tuples internally where the
|
||||
// value part of such a tuple isn't optional. For now the value
|
||||
// is 'dialog', but it's possible to add support for other values
|
||||
// later, e.g. for starting a download directly after opening the link:
|
||||
searchParams.set('export', 'dialog');
|
||||
exportLocation.search = searchParams.toString();
|
||||
|
||||
return exportLocation.toString();
|
||||
},
|
||||
|
||||
getShareUrl: function () {
|
||||
const exportLocation = new URL(document.location.href);
|
||||
const searchParams = new URLSearchParams(exportLocation.search);
|
||||
searchParams.delete('export');
|
||||
exportLocation.search = searchParams.toString();
|
||||
|
||||
return exportLocation.toString();
|
||||
},
|
||||
|
||||
_keydownListener: function (event) {
|
||||
if (
|
||||
BR.Util.keyboardShortcutsAllowed(event) &&
|
||||
event.keyCode === this.options.shortcut.share_action &&
|
||||
!$('#shareButton').hasClass('disabled')
|
||||
) {
|
||||
$('#share-dialog').modal('show');
|
||||
this.share(event);
|
||||
}
|
||||
},
|
||||
});
|
||||
15
js/index.js
15
js/index.js
|
|
@ -85,7 +85,7 @@
|
|||
// https://github.com/Templarian/MaterialDesign/blob/d0b28330af6648ca4c50c14d55043d71f813b3ae/svg/vector-line.svg
|
||||
// Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0), https://github.com/Templarian/MaterialDesign/blob/master/LICENSE
|
||||
const svg = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
|
||||
id="mdi-vector-line" width="24" height="24" viewBox="0 0 24 24" class="mdi active">
|
||||
<path d="M15,3V7.59L7.59,15H3V21H9V16.42L16.42,9H21V3M17,5H19V7H17M5,17H7V19H5" />
|
||||
</svg>`;
|
||||
|
|
@ -306,11 +306,13 @@
|
|||
pois = new BR.PoiMarkers(routing);
|
||||
|
||||
exportRoute = new BR.Export(router, pois, profile);
|
||||
new BR.ShareRoute();
|
||||
|
||||
routing.on('routing:routeWaypointEnd routing:setWaypointsEnd routing:rerouteSegmentEnd', function (evt) {
|
||||
search.clear();
|
||||
onUpdate(evt && evt.err);
|
||||
});
|
||||
|
||||
map.on('routing:draw-start', function () {
|
||||
drawButton.state('deactivate-draw');
|
||||
beelineButton.enable();
|
||||
|
|
@ -346,6 +348,17 @@
|
|||
trackAnalysis.update(track, segments);
|
||||
|
||||
exportRoute.update(latLngs, segments);
|
||||
|
||||
// Open export dialog immediately when the `export` query parameter is set;
|
||||
// this is used for the QR code export:
|
||||
var searchParams = new URLSearchParams(window.location.search);
|
||||
if (searchParams.has('export') && searchParams.get('export') === 'dialog') {
|
||||
routing.once('routing:setWaypointsEnd', () => {
|
||||
if (latLngs.length > 1) {
|
||||
$('#exportButton').trigger('click');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
routing.addTo(map);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue