forked from MapComplete/MapComplete
		
	More refactoring, stabilizing rotation and direction_gradient
This commit is contained in:
		
							parent
							
								
									5fec108ba2
								
							
						
					
					
						commit
						778044d0fb
					
				
					 45 changed files with 656 additions and 640 deletions
				
			
		
							
								
								
									
										268
									
								
								UI/BigComponents/ShareScreen.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								UI/BigComponents/ShareScreen.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,268 @@ | |||
| import {VerticalCombine} from "../Base/VerticalCombine"; | ||||
| import {UIElement} from "../UIElement"; | ||||
| import {VariableUiElement} from "../Base/VariableUIElement"; | ||||
| import {Translation} from "../i18n/Translation"; | ||||
| import LayoutConfig from "../../Customizations/JSON/LayoutConfig"; | ||||
| import Svg from "../../Svg"; | ||||
| import Combine from "../Base/Combine"; | ||||
| import {SubtleButton} from "../Base/SubtleButton"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import {Utils} from "../../Utils"; | ||||
| import State from "../../State"; | ||||
| import CheckBox from "../Input/CheckBox"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| import Translations from "../i18n/Translations"; | ||||
| import Constants from "../../Models/Constants"; | ||||
| import LayerConfig from "../../Customizations/JSON/LayerConfig"; | ||||
| 
 | ||||
| export default class ShareScreen extends UIElement { | ||||
|     private readonly _options: UIElement; | ||||
|     private readonly _iframeCode: UIElement; | ||||
|     public iframe: UIEventSource<string>; | ||||
|     private readonly _link: UIElement; | ||||
|     private readonly _linkStatus: UIEventSource<string | UIElement>; | ||||
|     private readonly _editLayout: UIElement; | ||||
| 
 | ||||
|     constructor(layout: LayoutConfig = undefined, layoutDefinition: string = undefined) { | ||||
|         super(undefined) | ||||
|         layout = layout ?? State.state?.layoutToUse?.data; | ||||
|         layoutDefinition = layoutDefinition ?? State.state?.layoutDefinition; | ||||
|         const tr = Translations.t.general.sharescreen; | ||||
| 
 | ||||
|         const optionCheckboxes: UIElement[] = [] | ||||
|         const optionParts: (UIEventSource<string>)[] = []; | ||||
| 
 | ||||
|         function check() { | ||||
|             return Svg.checkmark_svg().SetStyle("width: 1.5em; display:inline-block;"); | ||||
|         } | ||||
| 
 | ||||
|         function nocheck() { | ||||
|             return Svg.no_checkmark_svg().SetStyle("width: 1.5em; display: inline-block;"); | ||||
|         } | ||||
| 
 | ||||
|         const includeLocation = new CheckBox( | ||||
|             new Combine([check(), tr.fsIncludeCurrentLocation]), | ||||
|             new Combine([nocheck(), tr.fsIncludeCurrentLocation]), | ||||
|             true | ||||
|         ) | ||||
|         optionCheckboxes.push(includeLocation); | ||||
| 
 | ||||
|         const currentLocation = State.state?.locationControl; | ||||
| 
 | ||||
|         optionParts.push(includeLocation.isEnabled.map((includeL) => { | ||||
|             if (currentLocation === undefined) { | ||||
|                 return null; | ||||
|             } | ||||
|             if (includeL) { | ||||
|                 return `z=${currentLocation.data.zoom}&lat=${currentLocation.data.lat}&lon=${currentLocation.data.lon}` | ||||
|             } else { | ||||
|                 return null; | ||||
|             } | ||||
|         }, [currentLocation])); | ||||
| 
 | ||||
| 
 | ||||
|         function fLayerToParam(flayer: {isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig}) { | ||||
|             if (flayer.isDisplayed.data) { | ||||
|                 return null; // Being displayed is the default
 | ||||
|             } | ||||
|             return "layer-" + flayer.layerDef.id + "=" + flayer.isDisplayed.data | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         if (State.state !== undefined) { | ||||
| 
 | ||||
|             const currentLayer: UIEventSource<{ id: string, name: string, layer: any }> = State.state.backgroundLayer; | ||||
|             const currentBackground = new VariableUiElement(currentLayer.map(layer => { | ||||
|                 return tr.fsIncludeCurrentBackgroundMap.Subs({name: layer?.name ?? ""}).Render(); | ||||
|             })); | ||||
|             const includeCurrentBackground = new CheckBox( | ||||
|                 new Combine([check(), currentBackground]), | ||||
|                 new Combine([nocheck(), currentBackground]), | ||||
|                 true | ||||
|             ) | ||||
|             optionCheckboxes.push(includeCurrentBackground); | ||||
|             optionParts.push(includeCurrentBackground.isEnabled.map((includeBG) => { | ||||
|                 if (includeBG) { | ||||
|                     return "background=" + currentLayer.data.id | ||||
|                 } else { | ||||
|                     return null | ||||
|                 } | ||||
|             }, [currentLayer])); | ||||
| 
 | ||||
| 
 | ||||
|             const includeLayerChoices = new CheckBox( | ||||
|                 new Combine([check(), tr.fsIncludeCurrentLayers]), | ||||
|                 new Combine([nocheck(), tr.fsIncludeCurrentLayers]), | ||||
|                 true | ||||
|             ) | ||||
|             optionCheckboxes.push(includeLayerChoices); | ||||
| 
 | ||||
|             optionParts.push(includeLayerChoices.isEnabled.map((includeLayerSelection) => { | ||||
|                 if (includeLayerSelection) { | ||||
|                     return Utils.NoNull(State.state.filteredLayers.data.map(fLayerToParam)).join("&") | ||||
|                 } else { | ||||
|                     return null | ||||
|                 } | ||||
|             }, State.state.filteredLayers.data.map((flayer) => flayer.isDisplayed))); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         const switches = [ | ||||
|             {urlName: "fs-userbadge", human: tr.fsUserbadge}, | ||||
|             {urlName: "fs-search", human: tr.fsSearch}, | ||||
|             {urlName: "fs-welcome-message", human: tr.fsWelcomeMessage}, | ||||
|             {urlName: "fs-layers", human: tr.fsLayers}, | ||||
|             {urlName: "layer-control-toggle", human: tr.fsLayerControlToggle, reverse: true}, | ||||
|             {urlName: "fs-add-new", human: tr.fsAddNew}, | ||||
|             {urlName: "fs-geolocation", human: tr.fsGeolocation}, | ||||
|         ] | ||||
| 
 | ||||
| 
 | ||||
|         for (const swtch of switches) { | ||||
| 
 | ||||
|             const checkbox = new CheckBox( | ||||
|                 new Combine([check(), Translations.W(swtch.human)]), | ||||
|                 new Combine([nocheck(), Translations.W(swtch.human)]), !swtch.reverse | ||||
|             ); | ||||
|             optionCheckboxes.push(checkbox); | ||||
|             optionParts.push(checkbox.isEnabled.map((isEn) => { | ||||
|                 if (isEn) { | ||||
|                     if(swtch.reverse){ | ||||
|                        return `${swtch.urlName}=true` | ||||
|                     } | ||||
|                     return null; | ||||
|                 } else { | ||||
|                     if(swtch.reverse){ | ||||
|                         return null; | ||||
|                     } | ||||
|                     return `${swtch.urlName}=false` | ||||
|                 } | ||||
|             })) | ||||
| 
 | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         this._options = new VerticalCombine(optionCheckboxes) | ||||
|         const url = (currentLocation ?? new UIEventSource(undefined)).map(() => { | ||||
| 
 | ||||
|             const host = window.location.host; | ||||
|             let literalText = `https://${host}/${layout.id.toLowerCase()}.html` | ||||
| 
 | ||||
|             const parts = Utils.NoEmpty(Utils.NoNull(optionParts.map((eventSource) => eventSource.data))); | ||||
| 
 | ||||
|             let hash = ""; | ||||
|             if (layoutDefinition !== undefined) { | ||||
|                 literalText = `https://${host}/index.html` | ||||
|                 if (layout.id.startsWith("wiki:")) { | ||||
|                     parts.push("userlayout=" + encodeURIComponent(layout.id)) | ||||
|                 } else { | ||||
|                     hash = ("#" + layoutDefinition) | ||||
|                     parts.push("userlayout=true"); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             if (parts.length === 0) { | ||||
|                 return literalText + hash; | ||||
|             } | ||||
| 
 | ||||
|             return literalText + "?" + parts.join("&") + hash; | ||||
|         }, optionParts); | ||||
| 
 | ||||
| 
 | ||||
|         this.iframe = url.map(url => `<iframe src="${url}" width="100%" height="100%" title="${layout?.title?.txt ?? "MapComplete"} with MapComplete"></iframe>`); | ||||
|          | ||||
|         this._iframeCode = new VariableUiElement( | ||||
|             url.map((url) => { | ||||
|                 return `<span class='literal-code iframe-code-block'>
 | ||||
|                          <iframe src="${url}" width="100%" height="100%" title="${layout.title?.txt ?? "MapComplete"} with MapComplete"></iframe>  | ||||
|                     </span>` | ||||
|             }) | ||||
|         ); | ||||
| 
 | ||||
| 
 | ||||
|       | ||||
| 
 | ||||
|         this._editLayout = new FixedUiElement(""); | ||||
|         if ((layoutDefinition !== undefined && State.state?.osmConnection !== undefined)) { | ||||
|             this._editLayout = | ||||
|                 new VariableUiElement( | ||||
|                     State.state.osmConnection.userDetails.map( | ||||
|                         userDetails => { | ||||
|                             if (userDetails.csCount <= Constants.userJourney.themeGeneratorReadOnlyUnlock) { | ||||
|                                 return ""; | ||||
|                             } | ||||
| 
 | ||||
|                             return new SubtleButton(Svg.pencil_ui(), | ||||
|                                 new Combine([tr.editThisTheme.SetClass("bold"), "<br/>", | ||||
|                                     tr.editThemeDescription]), | ||||
|                                 {url: `./customGenerator.html#${State.state.layoutDefinition}`, newTab: true}).Render(); | ||||
| 
 | ||||
|                         } | ||||
|                     )); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         this._linkStatus = new UIEventSource<string | Translation>(""); | ||||
|         this.ListenTo(this._linkStatus); | ||||
|         const self = this; | ||||
|         this._link = new VariableUiElement( | ||||
|             url.map((url) => { | ||||
|                 return `<input type="text" value=" ${url}" id="code-link--copyable" style="width:90%">` | ||||
|             }) | ||||
|         ).onClick(async () => { | ||||
| 
 | ||||
|             const shareData = { | ||||
|                 title: Translations.W(layout.id)?.InnerRender() ?? "", | ||||
|                 text: Translations.W(layout.description)?.InnerRender() ?? "", | ||||
|                 url: self._link.data, | ||||
|             } | ||||
| 
 | ||||
|             function rejected() { | ||||
|                 const copyText = document.getElementById("code-link--copyable"); | ||||
| 
 | ||||
|                 // @ts-ignore
 | ||||
|                 copyText.select(); | ||||
|                 // @ts-ignore
 | ||||
|                 copyText.setSelectionRange(0, 99999); /*For mobile devices*/ | ||||
| 
 | ||||
|                 document.execCommand("copy"); | ||||
|                 const copied = tr.copiedToClipboard; | ||||
|                 copied.SetClass("thanks") | ||||
|                 self._linkStatus.setData(copied); | ||||
|             } | ||||
| 
 | ||||
|             try { | ||||
|                 navigator.share(shareData) | ||||
|                     .then(() => { | ||||
|                         const thx = tr.thanksForSharing; | ||||
|                         thx.SetClass("thanks"); | ||||
|                         this._linkStatus.setData(thx); | ||||
|                     }, rejected) | ||||
|                     .catch(rejected) | ||||
|             } catch (err) { | ||||
|                 rejected(); | ||||
|             } | ||||
| 
 | ||||
|         }); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
| 
 | ||||
|         const tr = Translations.t.general.sharescreen; | ||||
| 
 | ||||
|         return new VerticalCombine([ | ||||
|             this._editLayout, | ||||
|             tr.intro, | ||||
|             this._link, | ||||
|             Translations.W(this._linkStatus.data), | ||||
|             tr.addToHomeScreen, | ||||
|             tr.embedIntro, | ||||
|             this._options, | ||||
|             this._iframeCode, | ||||
|         ]).Render() | ||||
|     } | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue