forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			198 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
 | |
| import { OsmConnection } from "../Osm/OsmConnection"
 | |
| import { MangroveIdentity } from "../Web/MangroveReviews"
 | |
| import { Store, UIEventSource } from "../UIEventSource"
 | |
| import { QueryParameters } from "../Web/QueryParameters"
 | |
| import { LocalStorageSource } from "../Web/LocalStorageSource"
 | |
| import { Utils } from "../../Utils"
 | |
| import Locale from "../../UI/i18n/Locale"
 | |
| import ElementsState from "./ElementsState"
 | |
| import SelectedElementTagsUpdater from "../Actors/SelectedElementTagsUpdater"
 | |
| import { Changes } from "../Osm/Changes"
 | |
| import ChangeToElementsActor from "../Actors/ChangeToElementsActor"
 | |
| import PendingChangesUploader from "../Actors/PendingChangesUploader"
 | |
| import * as translators from "../../assets/translators.json"
 | |
| import Maproulette from "../Maproulette"
 | |
| 
 | |
| /**
 | |
|  * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection,
 | |
|  * which layers they enabled, ...
 | |
|  */
 | |
| export default class UserRelatedState extends ElementsState {
 | |
|     /**
 | |
|      The user credentials
 | |
|      */
 | |
|     public osmConnection: OsmConnection
 | |
|     /**
 | |
|      THe change handler
 | |
|      */
 | |
|     public changes: Changes
 | |
|     /**
 | |
|      * The key for mangrove
 | |
|      */
 | |
|     public mangroveIdentity: MangroveIdentity
 | |
| 
 | |
|     /**
 | |
|      * Maproulette connection
 | |
|      */
 | |
|     public maprouletteConnection: Maproulette
 | |
| 
 | |
|     public readonly isTranslator: Store<boolean>
 | |
| 
 | |
|     public readonly installedUserThemes: Store<string[]>
 | |
| 
 | |
|     constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) {
 | |
|         super(layoutToUse)
 | |
| 
 | |
|         this.osmConnection = new OsmConnection({
 | |
|             dryRun: this.featureSwitchIsTesting,
 | |
|             fakeUser: this.featureSwitchFakeUser.data,
 | |
|             oauth_token: QueryParameters.GetQueryParameter(
 | |
|                 "oauth_token",
 | |
|                 undefined,
 | |
|                 "Used to complete the login"
 | |
|             ),
 | |
|             osmConfiguration: <"osm" | "osm-test">this.featureSwitchApiURL.data,
 | |
|             attemptLogin: options?.attemptLogin,
 | |
|         })
 | |
|         const translationMode = this.osmConnection.GetPreference("translation-mode").sync(
 | |
|             (str) => (str === undefined ? undefined : str === "true"),
 | |
|             [],
 | |
|             (b) => (b === undefined ? undefined : b + "")
 | |
|         )
 | |
| 
 | |
|         translationMode.syncWith(Locale.showLinkToWeblate)
 | |
| 
 | |
|         this.isTranslator = this.osmConnection.userDetails.map((ud) => {
 | |
|             if (!ud.loggedIn) {
 | |
|                 return false
 | |
|             }
 | |
|             const name = ud.name.toLowerCase().replace(/\s+/g, "")
 | |
|             return translators.contributors.some(
 | |
|                 (c) => c.contributor.toLowerCase().replace(/\s+/g, "") === name
 | |
|             )
 | |
|         })
 | |
| 
 | |
|         this.isTranslator.addCallbackAndRunD((ud) => {
 | |
|             if (ud) {
 | |
|                 Locale.showLinkToWeblate.setData(true)
 | |
|             }
 | |
|         })
 | |
| 
 | |
|         this.changes = new Changes(this, layoutToUse?.isLeftRightSensitive() ?? false)
 | |
| 
 | |
|         new ChangeToElementsActor(this.changes, this.allElements)
 | |
|         new PendingChangesUploader(this.changes, this.selectedElement)
 | |
| 
 | |
|         this.mangroveIdentity = new MangroveIdentity(
 | |
|             this.osmConnection.GetLongPreference("identity", "mangrove")
 | |
|         )
 | |
| 
 | |
|         this.maprouletteConnection = new Maproulette()
 | |
| 
 | |
|         if (layoutToUse?.hideFromOverview) {
 | |
|             this.osmConnection.isLoggedIn.addCallbackAndRunD((loggedIn) => {
 | |
|                 if (loggedIn) {
 | |
|                     this.osmConnection
 | |
|                         .GetPreference("hidden-theme-" + layoutToUse?.id + "-enabled")
 | |
|                         .setData("true")
 | |
|                     return true
 | |
|                 }
 | |
|             })
 | |
|         }
 | |
| 
 | |
|         if (this.layoutToUse !== undefined && !this.layoutToUse.official) {
 | |
|             console.log("Marking unofficial theme as visited")
 | |
|             this.osmConnection.GetLongPreference("unofficial-theme-" + this.layoutToUse.id).setData(
 | |
|                 JSON.stringify({
 | |
|                     id: this.layoutToUse.id,
 | |
|                     icon: this.layoutToUse.icon,
 | |
|                     title: this.layoutToUse.title.translations,
 | |
|                     shortDescription: this.layoutToUse.shortDescription.translations,
 | |
|                     definition: this.layoutToUse["definition"],
 | |
|                 })
 | |
|             )
 | |
|         }
 | |
| 
 | |
|         this.InitializeLanguage()
 | |
|         new SelectedElementTagsUpdater(this)
 | |
|         this.installedUserThemes = this.InitInstalledUserThemes()
 | |
|     }
 | |
| 
 | |
|     private InitializeLanguage() {
 | |
|         const layoutToUse = this.layoutToUse
 | |
|         Locale.language.syncWith(this.osmConnection.GetPreference("language"))
 | |
|         Locale.language.addCallback((currentLanguage) => {
 | |
|             if (layoutToUse === undefined) {
 | |
|                 return
 | |
|             }
 | |
|             if (Locale.showLinkToWeblate.data) {
 | |
|                 return true // Disable auto switching as we are in translators mode
 | |
|             }
 | |
|             if (this.layoutToUse.language.indexOf(currentLanguage) < 0) {
 | |
|                 console.log(
 | |
|                     "Resetting language to",
 | |
|                     layoutToUse.language[0],
 | |
|                     "as",
 | |
|                     currentLanguage,
 | |
|                     " is unsupported"
 | |
|                 )
 | |
|                 // The current language is not supported -> switch to a supported one
 | |
|                 Locale.language.setData(layoutToUse.language[0])
 | |
|             }
 | |
|         })
 | |
|         Locale.language.ping()
 | |
|     }
 | |
| 
 | |
|     private InitInstalledUserThemes(): Store<string[]> {
 | |
|         const prefix = "mapcomplete-unofficial-theme-"
 | |
|         const postfix = "-combined-length"
 | |
|         return this.osmConnection.preferencesHandler.preferences.map((prefs) =>
 | |
|             Object.keys(prefs)
 | |
|                 .filter((k) => k.startsWith(prefix) && k.endsWith(postfix))
 | |
|                 .map((k) => k.substring(prefix.length, k.length - postfix.length))
 | |
|         )
 | |
|     }
 | |
| 
 | |
|     public GetUnofficialTheme(id: string):
 | |
|         | {
 | |
|               id: string
 | |
|               icon: string
 | |
|               title: any
 | |
|               shortDescription: any
 | |
|               definition?: any
 | |
|               isOfficial: boolean
 | |
|           }
 | |
|         | undefined {
 | |
|         console.log("GETTING UNOFFICIAL THEME")
 | |
|         const pref = this.osmConnection.GetLongPreference("unofficial-theme-" + id)
 | |
|         const str = pref.data
 | |
| 
 | |
|         if (str === undefined || str === "undefined" || str === "") {
 | |
|             pref.setData(null)
 | |
|             return undefined
 | |
|         }
 | |
| 
 | |
|         try {
 | |
|             const value: {
 | |
|                 id: string
 | |
|                 icon: string
 | |
|                 title: any
 | |
|                 shortDescription: any
 | |
|                 definition?: any
 | |
|                 isOfficial: boolean
 | |
|             } = JSON.parse(str)
 | |
|             value.isOfficial = false
 | |
|             return value
 | |
|         } catch (e) {
 | |
|             console.warn(
 | |
|                 "Removing theme " +
 | |
|                     id +
 | |
|                     " as it could not be parsed from the preferences; the content is:",
 | |
|                 str
 | |
|             )
 | |
|             pref.setData(null)
 | |
|             return undefined
 | |
|         }
 | |
|     }
 | |
| }
 |