forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			189 lines
		
	
	
		
			No EOL
		
	
	
		
			6.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			No EOL
		
	
	
		
			6.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import {UIEventSource} from "../UIEventSource";
 | |
| import UserDetails, {OsmConnection} from "./OsmConnection";
 | |
| import {Utils} from "../../Utils";
 | |
| 
 | |
| export class OsmPreferences {
 | |
| 
 | |
|     public preferences = new UIEventSource<any>({}, "all-osm-preferences");
 | |
|     public preferenceSources: any = {}
 | |
|     private auth: any;
 | |
|     private userDetails: UIEventSource<UserDetails>;
 | |
|     private longPreferences = {};
 | |
| 
 | |
|     constructor(auth, osmConnection: OsmConnection) {
 | |
|         this.auth = auth;
 | |
|         this.userDetails = osmConnection.userDetails;
 | |
|         const self = this;
 | |
|         osmConnection.OnLoggedIn(() => self.UpdatePreferences());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * OSM preferences can be at most 255 chars
 | |
|      * @param key
 | |
|      * @param prefix
 | |
|      * @constructor
 | |
|      */
 | |
|     public GetLongPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource<string> {
 | |
| 
 | |
|         if (this.longPreferences[prefix + key] !== undefined) {
 | |
|             return this.longPreferences[prefix + key];
 | |
|         }
 | |
| 
 | |
|         const source = new UIEventSource<string>(undefined, "long-osm-preference:"+prefix+key);
 | |
|         this.longPreferences[prefix + key] = source;
 | |
| 
 | |
|         const allStartWith = prefix + key + "-combined";
 | |
|         // Gives the number of combined preferences
 | |
|         const length = this.GetPreference(allStartWith + "-length", "");
 | |
| 
 | |
|         const self = this;
 | |
|         source.addCallback(str => {
 | |
|             if (str === undefined || str === "") {
 | |
|                 return;
 | |
|             }
 | |
|             if (str === null) {
 | |
|                 console.error("Deleting " + allStartWith);
 | |
|                 let count = parseInt(length.data);
 | |
|                 for (let i = 0; i < count; i++) {
 | |
|                     // Delete all the preferences
 | |
|                     self.GetPreference(allStartWith + "-" + i, "")
 | |
|                         .setData("");
 | |
|                 }
 | |
|                 self.GetPreference(allStartWith + "-length", "")
 | |
|                     .setData("");
 | |
|                 return
 | |
|             }
 | |
| 
 | |
|             let i = 0;
 | |
|             while (str !== "") {
 | |
|                 if (str === undefined || str === "undefined") {
 | |
|                     throw "Long pref became undefined?"
 | |
|                 }
 | |
|                 if (i > 100) {
 | |
|                     throw "This long preference is getting very long... "
 | |
|                 }
 | |
|                 self.GetPreference(allStartWith + "-" + i, "").setData(str.substr(0, 255));
 | |
|                 str = str.substr(255);
 | |
|                 i++;
 | |
|             }
 | |
|             length.setData("" + i); // We use I, the number of preference fields used
 | |
|         });
 | |
| 
 | |
| 
 | |
|         function updateData(l: number) {
 | |
|             if (l === undefined) {
 | |
|                 source.setData(undefined);
 | |
|                 return;
 | |
|             }
 | |
|             const prefsCount = Number(l);
 | |
|             if (prefsCount > 100) {
 | |
|                 throw "Length to long";
 | |
|             }
 | |
|             let str = "";
 | |
|             for (let i = 0; i < prefsCount; i++) {
 | |
|                 str += self.GetPreference(allStartWith + "-" + i, "").data;
 | |
|             }
 | |
| 
 | |
|             source.setData(str);
 | |
|         }
 | |
| 
 | |
|         length.addCallback(l => {
 | |
|             updateData(Number(l));
 | |
|         });
 | |
|         updateData(Number(length.data));
 | |
| 
 | |
|         return source;
 | |
|     }
 | |
| 
 | |
|     public GetPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource<string> {
 | |
|         key = prefix + key;
 | |
|         key = key.replace(/[:\\\/"' {}.%]/g, '')
 | |
|         if (key.length >= 255) {
 | |
|             throw "Preferences: key length to big";
 | |
|         }
 | |
|         if (this.preferenceSources[key] !== undefined) {
 | |
|             return this.preferenceSources[key];
 | |
|         }
 | |
|         if (this.userDetails.data.loggedIn && this.preferences.data[key] === undefined) {
 | |
|             this.UpdatePreferences();
 | |
|         }
 | |
|         const pref = new UIEventSource<string>(this.preferences.data[key],"osm-preference:"+key);
 | |
|         pref.addCallback((v) => {
 | |
|             this.SetPreference(key, v);
 | |
|         });
 | |
| 
 | |
|         this.preferences.addCallback((prefs) => {
 | |
|             if (prefs[key] !== undefined) {
 | |
|                 pref.setData(prefs[key]);
 | |
|             }
 | |
|         });
 | |
| 
 | |
|         this.preferenceSources[key] = pref;
 | |
|         return pref;
 | |
|     }
 | |
| 
 | |
|     private UpdatePreferences() {
 | |
|         const self = this;
 | |
|         this.auth.xhr({
 | |
|             method: 'GET',
 | |
|             path: '/api/0.6/user/preferences'
 | |
|         }, function (error, value: XMLDocument) {
 | |
|             if (error) {
 | |
|                 console.log("Could not load preferences", error);
 | |
|                 return;
 | |
|             }
 | |
|             const prefs = value.getElementsByTagName("preference");
 | |
|             for (let i = 0; i < prefs.length; i++) {
 | |
|                 const pref = prefs[i];
 | |
|                 const k = pref.getAttribute("k");
 | |
|                 const v = pref.getAttribute("v");
 | |
|                 self.preferences.data[k] = v;
 | |
|             }
 | |
|             self.preferences.ping();
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     private SetPreference(k: string, v: string) {
 | |
|         if (!this.userDetails.data.loggedIn) {
 | |
|             console.log(`Not saving preference ${k}: user not logged in`);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (this.preferences.data[k] === v) {
 | |
|             return;
 | |
|         }
 | |
|         console.log("Updating preference", k, " to ", Utils.EllipsesAfter(v, 15));
 | |
| 
 | |
|         if (v === undefined || v === "") {
 | |
|             this.auth.xhr({
 | |
|                 method: 'DELETE',
 | |
|                 path: '/api/0.6/user/preferences/' + encodeURIComponent(k),
 | |
|                 options: {header: {'Content-Type': 'text/plain'}},
 | |
|             }, function (error) {
 | |
|                 if (error) {
 | |
|                     console.log("Could not remove preference", error);
 | |
|                     return;
 | |
|                 }
 | |
|                 console.log("Preference ", k, "removed!");
 | |
| 
 | |
|             });
 | |
|             return;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         this.auth.xhr({
 | |
|             method: 'PUT',
 | |
|             path: '/api/0.6/user/preferences/' + encodeURIComponent(k),
 | |
|             options: {header: {'Content-Type': 'text/plain'}},
 | |
|             content: v
 | |
|         }, function (error) {
 | |
|             if (error) {
 | |
|                 console.log(`Could not set preference "${k}"'`, error);
 | |
|                 return;
 | |
|             }
 | |
|             console.log(`Preference ${k} written!`);
 | |
|         });
 | |
|     }
 | |
| 
 | |
| 
 | |
| } |