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.debug(`Not saving preference ${k}: user not logged in`);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (this.preferences.data[k] === v) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        console.debug("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.warn("Could not remove preference", error);
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                console.debug("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!`);
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
} |