+
+
+`
+ );
+
+ els.push(link)
+
+
+ }
+
+
+ return new VerticalCombine([
+ tr.intro,
+ new VerticalCombine(els),
+ tr.streetcomplete
+ ]).Render();
+ }
+
+}
\ No newline at end of file
diff --git a/UI/ShareScreen.ts b/UI/ShareScreen.ts
new file mode 100644
index 000000000..591a3f3fe
--- /dev/null
+++ b/UI/ShareScreen.ts
@@ -0,0 +1,160 @@
+import {UIElement} from "./UIElement";
+import {Layout} from "../Customizations/Layout";
+import Translations from "./i18n/Translations";
+import {FixedUiElement} from "./Base/FixedUiElement";
+import Combine from "./Base/Combine";
+import {VariableUiElement} from "./Base/VariableUIElement";
+import {UIEventSource} from "./UIEventSource";
+import {CheckBox} from "./Input/CheckBox";
+import {VerticalCombine} from "./Base/VerticalCombine";
+import {QueryParameters} from "../Logic/QueryParameters";
+import {Img} from "./Img";
+
+export class ShareScreen extends UIElement {
+
+ private _shareButton: UIElement;
+
+ private _options: UIElement;
+ private _iframeCode: UIElement;
+ private _link: UIElement;
+ private _linkStatus: UIElement;
+
+ constructor(layout: Layout, currentLocation: UIEventSource<{ zoom: number, lat: number, lon: number }>) {
+ super(undefined)
+ const tr = Translations.t.general.sharescreen;
+
+ const optionCheckboxes: UIElement[] = []
+ const optionParts: (UIEventSource)[] = [];
+
+ const includeLocation = new CheckBox(
+ new Combine([Img.checkmark, "Include current location"]),
+ new Combine([Img.no_checkmark, "Include current location"]),
+ true
+ )
+ optionCheckboxes.push(includeLocation);
+ optionParts.push(includeLocation.isEnabled.map((includeL) => {
+ if (includeL) {
+ return `z=${currentLocation.data.zoom}&lat=${currentLocation.data.lat}&lon=${currentLocation.data.lon}`
+ } else {
+ return null;
+ }
+ }, [currentLocation]));
+
+
+ const switches = [{urlName: "fs-userbadge", human: "Enable the login-button"},
+ {urlName: "fs-search", human: "Enable search bar"},
+ {urlName: "fs-welcome-message", human: "Enable the welcome message"},
+ {urlName: "fs-layers", human: "Enable layer control"},
+ {urlName: "fs-add-new", human: "Enable the 'add new POI' button"}
+ ]
+
+
+ for (const swtch of switches) {
+
+ const checkbox = new CheckBox(
+ new Combine([Img.checkmark, swtch.human]),
+ new Combine([Img.no_checkmark, swtch.human]),
+ true
+ );
+ optionCheckboxes.push(checkbox);
+ optionParts.push(checkbox.isEnabled.map((isEn) => {
+ if (isEn) {
+ return null;
+ } else {
+ return `${swtch.urlName}=false`
+ }
+ }))
+
+
+ }
+
+
+ this._options = new VerticalCombine(optionCheckboxes)
+ const url = currentLocation.map(() => {
+
+ let literalText = "https://pietervdvn.github.io/MapComplete/" + layout.name + ".html"
+
+ const parts = [];
+ for (const part of optionParts) {
+ if (part.data === null) {
+ continue;
+ }
+ parts.push(part.data);
+ }
+
+ if (parts.length === 0) {
+ return literalText;
+ }
+
+ return literalText + "?" + parts.join("&");
+ }, optionParts);
+ this._iframeCode = new VariableUiElement(
+ url.map((url) => {
+ return `
+ <iframe src="${url}" title="${layout.name} with MapComplete"></iframe>
+ `
+ })
+ );
+
+
+ this._link = new VariableUiElement(
+ url.map((url) => {
+ return ``
+ })
+ );
+
+
+ const status = new UIEventSource(" ");
+ this._linkStatus = new VariableUiElement(status);
+ const self = this;
+ this._link.onClick(async () => {
+
+ const shareData = {
+ title: Translations.W(layout.name).InnerRender(),
+ text: Translations.W(layout.description).InnerRender(),
+ url: self._link.data,
+ }
+
+ function rejected() {
+ status.setData("Copying to clipboard...")
+ var copyText = document.getElementById("code-link--copyable");
+
+ // @ts-ignore
+ copyText.select();
+ // @ts-ignore
+ copyText.setSelectionRange(0, 99999); /*For mobile devices*/
+
+ document.execCommand("copy");
+ status.setData("Copied to clipboard")
+ }
+
+ try {
+ navigator.share(shareData)
+ .then(() => {
+ status.setData("Thanks for sharing!")
+ }, rejected)
+ .catch(rejected)
+ } catch (err) {
+ rejected();
+ }
+
+ });
+
+ }
+
+ InnerRender(): string {
+
+ const tr = Translations.t.general.sharescreen;
+
+ return new VerticalCombine([
+ tr.intro,
+ this._link,
+ this._linkStatus,
+ tr.addToHomeScreen,
+ tr.embedIntro,
+ this._options,
+ this._iframeCode
+ ]).Render()
+ }
+
+}
\ No newline at end of file
diff --git a/UI/UIElement.ts b/UI/UIElement.ts
index 48b42687e..6d6d7cfd0 100644
--- a/UI/UIElement.ts
+++ b/UI/UIElement.ts
@@ -136,6 +136,8 @@ export abstract class UIElement extends UIEventSource{
public IsEmpty(): boolean {
return this.InnerRender() === "";
}
+
}
+
diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts
index 0389b7631..2d34a7f15 100644
--- a/UI/i18n/Translations.ts
+++ b/UI/i18n/Translations.ts
@@ -160,7 +160,11 @@ export default class Translations {
// title: new T({en: 'Bike station', nl: 'Fietsstation', fr: 'Station vélo'}), Old, non-dynamic title
titlePump: new T({en: 'Bike pump', nl: 'Fietspomp', fr: 'TODO: fr'}),
titleRepair: new T({en: 'Bike repair station', nl: 'Herstelpunt', fr: 'TODO: fr'}),
- titlePumpAndRepair: new T({en: 'Bike station (pump & repair)', nl: 'Herstelpunt met pomp', fr: 'TODO: fr'}),
+ titlePumpAndRepair: new T({
+ en: 'Bike station (pump & repair)',
+ nl: 'Herstelpunt met pomp',
+ fr: 'TODO: fr'
+ }),
manometer: {
question: new T({
en: 'Does the pump have a pressure indicator or manometer?',
@@ -168,7 +172,11 @@ export default class Translations {
fr: 'Est-ce que la pompe à un manomètre integré?'
}),
yes: new T({en: 'There is a manometer', nl: 'Er is een luchtdrukmeter', fr: 'Il y a un manomètre'}),
- no: new T({en: 'There is no manometer', nl: 'Er is geen luchtdrukmeter', fr: 'Il n\'y a pas de manomètre'}),
+ no: new T({
+ en: 'There is no manometer',
+ nl: 'Er is geen luchtdrukmeter',
+ fr: 'Il n\'y a pas de manomètre'
+ }),
broken: new T({
en: 'There is manometer but it is broken',
nl: 'Er is een luchtdrukmeter maar die is momenteel defect',
@@ -300,11 +308,22 @@ export default class Translations {
title: new T({en: "Bike repair/shop", nl: "Fietszaak", fr: "Magasin et réparateur de vélo"}),
titleRepair: new T({en: "Bike repair", nl: "Fietsenmaker", fr: "Réparateur de vélo"}),
titleShop: new T({en: "Bike shop", nl: "Fietswinkel", fr: "Magasin de vélo"}),
-
- titleNamed: new T({en: "Bike repair/shop {name}", nl: "Fietszaak {name}", fr: "Magasin et réparateur de vélo {name}"}),
- titleRepairNamed: new T({en: "Bike repair {name}", nl: "Fietsenmaker {name}", fr: "Réparateur de vélo {name}"}),
- titleShopNamed: new T({en: "Bike shop {name}", nl: "Fietswinkel {name}", fr: "Magasin de vélo {name}"}),
+ titleNamed: new T({
+ en: "Bike repair/shop {name}",
+ nl: "Fietszaak {name}",
+ fr: "Magasin et réparateur de vélo {name}"
+ }),
+ titleRepairNamed: new T({
+ en: "Bike repair {name}",
+ nl: "Fietsenmaker {name}",
+ fr: "Réparateur de vélo {name}"
+ }),
+ titleShopNamed: new T({
+ en: "Bike shop {name}",
+ nl: "Fietswinkel {name}",
+ fr: "Magasin de vélo {name}"
+ }),
retail: {
@@ -313,7 +332,11 @@ export default class Translations {
nl: "Verkoopt deze winkel fietsen?",
fr: "Est-ce que ce magasin vend des vélos?"
}),
- yes: new T({en: "This shop sells bikes", nl: "Deze winkel verkoopt fietsen", fr: "Ce magasin vend des vélos"}),
+ yes: new T({
+ en: "This shop sells bikes",
+ nl: "Deze winkel verkoopt fietsen",
+ fr: "Ce magasin vend des vélos"
+ }),
no: new T({
en: "This shop doesn't sell bikes",
nl: "Deze winkel verkoopt geen fietsen",
@@ -451,15 +474,43 @@ export default class Translations {
}
},
nonBikeShop: {
- name: new T({en: "shop that sells/repairs bikes", nl: "winkel die fietsen verkoopt/herstelt", fr: "TODO: fr"}),
+ name: new T({
+ en: "shop that sells/repairs bikes",
+ nl: "winkel die fietsen verkoopt/herstelt",
+ fr: "TODO: fr"
+ }),
- title: new T({en: "Shop that sells/repairs bikes", nl: "Winkel die fietsen verkoopt/herstelt", fr: "TODO: fr"}),
- titleRepair: new T({en: "Shop that repairs bikes", nl: "Winkel die fietsen herstelt", fr: "TODO: fr"}),
- titleShop: new T({en: "Shop that sells bikes", nl: "Winkel die fietsen verkoopt", fr: "TODO: fr"}),
+ title: new T({
+ en: "Shop that sells/repairs bikes",
+ nl: "Winkel die fietsen verkoopt/herstelt",
+ fr: "TODO: fr"
+ }),
+ titleRepair: new T({
+ en: "Shop that repairs bikes",
+ nl: "Winkel die fietsen herstelt",
+ fr: "TODO: fr"
+ }),
+ titleShop: new T({
+ en: "Shop that sells bikes",
+ nl: "Winkel die fietsen verkoopt",
+ fr: "TODO: fr"
+ }),
- titleNamed: new T({en: "{name} (sells/repairs bikes)", nl: "{name} (verkoopt/herstelt fietsen)", fr: "TODO: fr"}),
- titleRepairNamed: new T({en: "{name} (repairs bikes)", nl: "{name} (herstelt fietsen)", fr: "TODO: fr"}),
- titleShopNamed: new T({en: "{name} (sells bikes)", nl: "{name} (verkoopt fietsen)", fr: "TODO: fr"}),
+ titleNamed: new T({
+ en: "{name} (sells/repairs bikes)",
+ nl: "{name} (verkoopt/herstelt fietsen)",
+ fr: "TODO: fr"
+ }),
+ titleRepairNamed: new T({
+ en: "{name} (repairs bikes)",
+ nl: "{name} (herstelt fietsen)",
+ fr: "TODO: fr"
+ }),
+ titleShopNamed: new T({
+ en: "{name} (sells bikes)",
+ nl: "{name} (verkoopt fietsen)",
+ fr: "TODO: fr"
+ }),
},
drinking_water: {
title: new T({
@@ -686,6 +737,43 @@ export default class Translations {
en: "Website: {website}",
nl: "Website: {website}"
})
+
+ },
+ openStreetMapIntro: new T({
+ en: "
An Open Map
" +
+ "Wouldn't it be cool if there was a single map, which everyone could freely use and edit?" +
+ "A single place to store all geo-information? Then, all those websites with different, small and incompatible maps (which are always outdated) wouldn't be needed anymore.
" +
+ "
OpenStreetMap is this map. The map data can be used for free (with attribution and publication of changes to that data)." +
+ " On top of that, everyone can freely add new data and fix errors. This website uses OpenStreetMap as well. All the data is from there, and your answers and corrections are added there as well.
" +
+ "
A ton of people and application already use OpenStreetMap: Maps.me, OsmAnd, but also the maps at Facebook, Intsagram, Apple-maps and Bing-maps are (partly) powered by OpenStreetMap." +
+ "If you change something here, it'll be reflected in those applications too - after their next update!
",
+ nl: "
Een open kaart
" +
+ "
Zou het niet fantastisch zijn als er een open kaart zou zijn, die door iedereen aangepast én gebruikt kon worden? Waar iedereen zijn interesses aan zou kunnen toevoegen?" +
+ "Dan zouden er geen duizend-en-één verschillende kleine kaartjes, websites, ... meer nodig zijn
" +
+ "
OpenStreetMap is deze open kaart. Je mag de kaartdata gratis gebruiken (mits bronvermelding en herpublicatie van aanpassingen). Daarenboven mag je de kaart ook gratis aanpassen als je een account maakt." +
+ "Ook deze website is gebaseerd op OpenStreetMap. Als je hier een vraag beantwoord, gaat het antwoord daar ook naartoe
" +
+ "
Tenslotte zijn er reeds vele gebruikers van OpenStreetMap. Denk maar Maps.me, OsmAnd, verschillende gespecialiseerde routeplanners, de achtergrondkaarten op Facebook, Instagram,... Zelfs Apple Maps en Bing-Maps gebruiken OpenStreetMap in hun kaarten!
" +
+ "Kortom, als je hier een antwoord geeft of een fout aanpast, zal dat na een tijdje ook in al dié applicaties te zien zijn."
+ }),
+
+ sharescreen: {
+ intro: new T({
+ en: "
Share this map
Share this map by copying the link below and sending it to friends and family:"
+ }),
+ addToHomeScreen: new T({
+ en: "
Add to your home screen
You can easily add this website to your home screen for a native feel. Click the 'add to home screen button' in the URL bar to do this."
+ }),
+ embedIntro: new T({
+ en: "
Embed on your website
Please, embed this map into your website. We encourage you to do it - you don't even have to ask permission. It is free, and always will be. The more people using this, the more valuable it becomes."
+ })
+ },
+ morescreen: {
+ intro:new T({
+ en:"