<commit_before>/*
 * Copyright 2013 Laurent Bovet <laurent.bovet@windmaster.ch>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var docson = docson || {};

docson.templateBaseUrl="templates";

define(["lib/jquery", "lib/handlebars", "lib/highlight", "lib/jsonpointer", "lib/marked", "lib/traverse"], function(jquery, handlebars, highlight, jsonpointer, marked) {

    var ready = $.Deferred();
    var boxTemplate;
    var signatureTemplate;
    var source;
    var stack = [];
    var boxes=[];

    Handlebars.registerHelper('scope', function(schema, options) {
        var result;
        boxes.push([]);
        if(schema && (schema.id || schema.root)) {
            stack.push( schema );
            result = options.fn(this);
            stack.pop();
        } else {
            result = options.fn(this);
        }
        boxes.pop();
        return result;
    });

    Handlebars.registerHelper('source', function(schema) {
        delete schema.root;
        delete schema.__boxId;
        delete schema.__name;
        return JSON.stringify(schema, null, 2);
    });

    Handlebars.registerHelper('desc', function(schema) {
        var description = schema.description;

        if( !description ) return "";
        var text = description;
        if(marked) {
            marked.setOptions({gfm: true, breaks: true})
            return new Handlebars.SafeString(marked(text));
        } else {
            return text;
        }
    });

    Handlebars.registerHelper('equals', function(lvalue, rvalue, options) {
        if (arguments.length < 3)
            throw new Error("Handlebars Helper equals needs 2 parameters");
        if( lvalue!=rvalue ) {
            return options.inverse(this);
        } else {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('contains', function(arr, item, options) {;
        if(arr && arr.indexOf(item) != -1) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('primitive', function(schema, options) {
        if(schema.type && schema.type != "object" && schema.type != "array" || schema.enum) {
            return withType(this, options, true)
        }
    });

    Handlebars.registerHelper('exists', function(value, options) {
        if(value !== undefined) {
            value = value === null ? "null": value;
            value = value === true ? "true": value;
            value = value === false ? "false": value;
            value = typeof value === "object" ? JSON.stringify(value): value;
            this.__default = value;
            var result = options.fn(this);
            delete this.__default;
            return result;
        }
    });

    Handlebars.registerHelper('range', function(from, to, replFrom, replTo, exclFrom, exclTo, sep) {
        var result = "";
        if(from !== undefined || to !== undefined) {
            result += exclFrom ? "]" : "[";
            result += from !== undefined ? from : replFrom;
            if( (from || replFrom) !== (to || replTo)) {
                result += (from !== undefined || replFrom !== null) && (to !== undefined || replTo !== null) ? sep : "";
                result += to !== undefined ? to : replTo;
            }
            result += exclTo ? "[" : "]";
            return result;
        }
    });

    var sub = function(schema) {
        return schema.type == "array" || schema.allOf || schema.anyOf || schema.oneOf || schema.not || schema.additionalProperties;
    }

    Handlebars.registerHelper('sub', function(schema, options) {
        if(sub(schema) || (schema.type && schema.type != "object" && schema.type != "array") || schema.enum) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('main', function(schema, options) {
        if(!sub(schema)) {
            return options.fn(this);
        }
    });

    var simpleSchema = function(schema) {
        var result = schema.description===undefined && schema.title===undefined && schema.id===undefined;
        result &= schema.properties===undefined;
        return result;
    };

    Handlebars.registerHelper('simple', function(schema, options) {
        if(simpleSchema(schema) && !schema.$ref) {
            return withType(schema, options, true);
        }
    });

    var withType = function(schema, options, hideAny) {
        schema.__type = schema.type;
        if(!schema.type && !hideAny) {
            schema.__type="any";
        }
        if(schema.format) {
            schema.__type=schema.format;
        }
        if( (schema.__type == "any" || schema.__type == "object") && schema.title) {
            schema.__type = schema.title;
        }
        var result = options.fn(schema);
        delete schema.__type;
        return result;
    }

    Handlebars.registerHelper('complex', function(schema, options) {
        if(!simpleSchema(schema) && !schema.$ref || schema.properties) {
            return withType(schema, options);
        }
    });

    Handlebars.registerHelper('obj', function(schema, options) {
        if(schema.properties || schema.type == "object") {
            return withType(schema, options);
        }
    });

    var pushBox = function(schema) {
        boxes[boxes.length-1].push(schema);
    }

    Handlebars.registerHelper('box', function(schema, options) {
        if(schema) {
            pushBox(schema);
            return options.fn(schema);
        }
    });

    Handlebars.registerHelper('boxId', function() {
        return boxes[boxes.length-1].length
    });

    Handlebars.registerHelper('boxes', function(options) {
        var result="";
        $.each(boxes[boxes.length-1], function(k, box) {
            box.__boxId = k+1;
            result=result+options.fn(box);
        });
        boxes[boxes.length-1] = []
        return result;
    });

    var resolveIdRef = function(ref) {
        if(stack) {
            var i;
            for(i=stack.length-1; i>=0; i--) {
                if(stack[i][ref]) {
                    return stack[i][ref];
                }
            }
        }
        return null;
    }

    var resolvePointerRef = function(ref) {
        var root = stack[1];
        if(ref=="#") {
            return root;
        }
        try {
            return jsonpointer.get(stack[1], ref);
        } catch(e) {
            console.log(e);
            return null;
        }
    }

    var resolveRef = function(ref) {
        if(ref.indexOf("#") == 0) {
            return resolvePointerRef(ref);
        } else {
            return resolveIdRef(ref);
        }
    }

    var getName = function(schema) {
        if(!schema) {
            return "<error>";
        }
        var name = schema.title;
        name = !name && schema.id ? schema.id: name;
        name = !name ? schema.__name: name;
        return name;
    }

    Handlebars.registerHelper('name', function(schema, options) {
        schema.__name = getName(schema);
        if(schema.__name) {
            return options.fn(schema);
        }
    });

    var refName = function(ref) {
        var name = getName(resolveRef(ref));
        if(!name) {
            if(ref == "#") {
                name = "<root>";
            } else {
                name = ref.replace("#", "/")
            }
        }
        var segments = name.split("/");
        name = segments[segments.length-1];
        return name;
    }

    function renderSchema(schema) {
        if(stack.indexOf(schema) == -1) { // avoid recursion
            return new Handlebars.SafeString(boxTemplate(schema));
        } else {
            return new Handlebars.SafeString(boxTemplate({"description": "_circular reference_"}));
        }
    }

    Handlebars.registerHelper('ref', function(schema, options) {
        if(schema.$ref) {
            var target = resolveRef(schema.$ref);
            if(target) {
                target.__name = refName(schema.$ref);
            }
            if(target) {
                return options.fn(target);
            } else {
                return new Handlebars.SafeString("Error: Could not resolve schema "+schema.$ref+"");
            }
        }
    });

    Handlebars.registerHelper('schema', function(schema) {
        return renderSchema(schema);
    });

    Handlebars.registerHelper('signature', function(schema, keyword, schemas) {
        if(!schemas) {
            schemas = []
        }
        schemas = schemas instanceof Array ? schemas : [schemas];
        return new Handlebars.SafeString(signatureTemplate({ schema: schema, keyword: keyword, schemas: schemas}));
    });

    Handlebars.registerHelper('l', function(context) {
        console.log(context);
    });

    function init() {
        $.when( $.get(docson.templateBaseUrl+"/box.html").done(function(content) {
            source = content
            boxTemplate = Handlebars.compile(source);
        }), $.get(docson.templateBaseUrl+"/signature.html").done(function(content) {
            source = content
            signatureTemplate = Handlebars.compile(source);
        })).always(function() {
            ready.resolve();
        });
    };

    docson.doc = function(element, schema, ref) {
        var d = $.Deferred();
        init();
        ready.done(function() {
            if(typeof element == "string") {
                element = $("#"+element);
            }
            if(typeof schema == "string") {
                schema = JSON.parse(schema);
            }

            var refsPromise = $.Deferred().resolve().promise();
            var refs = {};

            traverse(schema).forEach(function(item) {
                if(this.key === "$ref") {
                    if((/^https?:\/\//).test(item)) {
                        var segments = item.split("#");
                        var p = $.get(segments[0]).then(function(content) {
                            if(typeof content != "object") {
                                try {
                                    content = JSON.parse(content);
                                } catch(e) {
                                    console.error("Unable to parse "+segments[0], e);
                                }
                            }
                            if(content) {
                                refs[item] = content;
                            }
                        });
                        refsPromise = p.then(refsPromise)
                    }
                }
            });

            refsPromise.done(function() {
                stack.push(refs);
                var target = schema;
                if(ref) {
                    ref = ref[0] !== '/' ? '/'+ref : ref;
                    target = jsonpointer.get(schema, ref);
                    stack.push( schema );
                }

                target.root = true;
                var html = boxTemplate(target);

                if(ref) {
                    stack.pop();
                }
                stack.pop();

                element.addClass("docson").html(html);

                var resizeHandler = element.get(0).onresize;
                function resized() {
                    if(resizeHandler) {
                        var box = element.find(".box").first();
                        element.get(0).onresize(box.outerWidth(), box.outerHeight());
                    }
                }
                element.get(0).resized = resized;
                resized();

                if(highlight) {
                    element.find(".json-schema").each(function(k, schemaElement) {
                        highlight.highlightSchema(schemaElement);
                    });
                }
                element.find(".box").mouseenter(function() {
                    $(this).children(".source-button").fadeIn(300);
                    $(this).children(".box-body").children(".expand-button").fadeIn(300);
                });
                element.find(".box").mouseleave(function() {
                    $(this).children(".source-button").fadeOut(300);
                    $(this).children(".box-body").children(".expand-button").fadeOut(300);
                });
                element.find(".signature-type-expandable").click(function() {
                    var boxId = $(this).attr("boxid");
                    $(this).toggleClass("signature-type-expanded");
                    $(this).parent().parent().parent().children(".signature-box-container").
                        children("[boxid='"+boxId+"']").toggle(resizeHandler ? 0 : 300);
                    resized();
                });
                element.find(".expand-button").click(function() {
                    if(this.expanded) {
                        $(this).html(" + ").attr("title", "Expand all");
                        $(this).parent().parent().find(".signature-type-expandable").removeClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").hide( resizeHandler ? 0 : 300);
                        this.expanded=false;
                        resized();
                    } else {
                        $(this).html(" - ").attr("title", "Collapse all");
                        $(this).parent().parent().find(".signature-type-expandable").addClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").show(resizeHandler ? 0 : 300);
                        this.expanded=true;
                        resized();
                    }
                });
                element.find(".source-button").click(function() {
                    $(this).parent().children(".box-body").toggle();
                    $(this).parent().children(".source").toggle();
                    resized();
                });
            });
            d.resolve();
        })
        return d.promise();
    }

    return docson;
});
<commit_msg>Workaround to bad array generation from Swagger. Fixes #5, #6.<commit_after>/*
 * Copyright 2013 Laurent Bovet <laurent.bovet@windmaster.ch>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var docson = docson || {};

docson.templateBaseUrl="templates";

define(["lib/jquery", "lib/handlebars", "lib/highlight", "lib/jsonpointer", "lib/marked", "lib/traverse"], function(jquery, handlebars, highlight, jsonpointer, marked) {

    var ready = $.Deferred();
    var boxTemplate;
    var signatureTemplate;
    var source;
    var stack = [];
    var boxes=[];

    Handlebars.registerHelper('scope', function(schema, options) {
        var result;
        boxes.push([]);
        if(schema && (schema.id || schema.root)) {
            stack.push( schema );
            result = options.fn(this);
            stack.pop();
        } else {
            result = options.fn(this);
        }
        boxes.pop();
        return result;
    });

    Handlebars.registerHelper('source', function(schema) {
        delete schema.root;
        delete schema.__boxId;
        delete schema.__name;
        return JSON.stringify(schema, null, 2);
    });

    Handlebars.registerHelper('desc', function(schema) {
        var description = schema.description;

        if( !description ) return "";
        var text = description;
        if(marked) {
            marked.setOptions({gfm: true, breaks: true})
            return new Handlebars.SafeString(marked(text));
        } else {
            return text;
        }
    });

    Handlebars.registerHelper('equals', function(lvalue, rvalue, options) {
        if (arguments.length < 3)
            throw new Error("Handlebars Helper equals needs 2 parameters");
        if( lvalue!=rvalue ) {
            return options.inverse(this);
        } else {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('contains', function(arr, item, options) {;
        if(arr && arr.indexOf(item) != -1) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('primitive', function(schema, options) {
        if(schema.type && schema.type != "object" && schema.type != "array" || schema.enum) {
            return withType(this, options, true)
        }
    });

    Handlebars.registerHelper('exists', function(value, options) {
        if(value !== undefined) {
            value = value === null ? "null": value;
            value = value === true ? "true": value;
            value = value === false ? "false": value;
            value = typeof value === "object" ? JSON.stringify(value): value;
            this.__default = value;
            var result = options.fn(this);
            delete this.__default;
            return result;
        }
    });

    Handlebars.registerHelper('range', function(from, to, replFrom, replTo, exclFrom, exclTo, sep) {
        var result = "";
        if(from !== undefined || to !== undefined) {
            result += exclFrom ? "]" : "[";
            result += from !== undefined ? from : replFrom;
            if( (from || replFrom) !== (to || replTo)) {
                result += (from !== undefined || replFrom !== null) && (to !== undefined || replTo !== null) ? sep : "";
                result += to !== undefined ? to : replTo;
            }
            result += exclTo ? "[" : "]";
            return result;
        }
    });

    var sub = function(schema) {
        return schema.type == "array" || schema.allOf || schema.anyOf || schema.oneOf || schema.not || schema.additionalProperties;
    }

    Handlebars.registerHelper('sub', function(schema, options) {
        if(sub(schema) || (schema.type && schema.type != "object" && schema.type != "array") || schema.enum) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('main', function(schema, options) {
        if(!sub(schema)) {
            return options.fn(this);
        }
    });

    var simpleSchema = function(schema) {
        var result = schema.description===undefined && schema.title===undefined && schema.id===undefined;
        result &= schema.properties===undefined;
        return result;
    };

    Handlebars.registerHelper('simple', function(schema, options) {
        if(simpleSchema(schema) && !schema.$ref) {
            return withType(schema, options, true);
        }
    });

    var withType = function(schema, options, hideAny) {
        schema.__type = schema.type;
        if(!schema.type && !hideAny) {
            schema.__type="any";
        }
        if(schema.format) {
            schema.__type=schema.format;
        }
        if( (schema.__type == "any" || schema.__type == "object") && schema.title) {
            schema.__type = schema.title;
        }
        var result = options.fn(schema);
        delete schema.__type;
        return result;
    }

    Handlebars.registerHelper('complex', function(schema, options) {
        if(!simpleSchema(schema) && !schema.$ref || schema.properties) {
            return withType(schema, options);
        }
    });

    Handlebars.registerHelper('obj', function(schema, options) {
        if(schema.properties || schema.type == "object") {
            return withType(schema, options);
        }
    });

    var pushBox = function(schema) {
        boxes[boxes.length-1].push(schema);
    }

    Handlebars.registerHelper('box', function(schema, options) {
        if(schema) {
            pushBox(schema);
            return options.fn(schema);
        }
    });

    Handlebars.registerHelper('boxId', function() {
        return boxes[boxes.length-1].length
    });

    Handlebars.registerHelper('boxes', function(options) {
        var result="";
        $.each(boxes[boxes.length-1], function(k, box) {
            box.__boxId = k+1;
            result=result+options.fn(box);
        });
        boxes[boxes.length-1] = []
        return result;
    });

    var resolveIdRef = function(ref) {
        if(stack) {
            var i;
            for(i=stack.length-1; i>=0; i--) {
                if(stack[i][ref]) {
                    return stack[i][ref];
                }
            }
        }
        return null;
    }

    var resolvePointerRef = function(ref) {
        var root = stack[1];
        if(ref=="#") {
            return root;
        }
        try {
            return jsonpointer.get(stack[1], ref);
        } catch(e) {
            console.log(e);
            return null;
        }
    }

    var resolveRef = function(ref) {
        if(ref.indexOf("#") == 0) {
            return resolvePointerRef(ref);
        } else {
            return resolveIdRef(ref);
        }
    }

    var getName = function(schema) {
        if(!schema) {
            return "<error>";
        }
        var name = schema.title;
        name = !name && schema.id ? schema.id: name;
        name = !name ? schema.__name: name;
        return name;
    }

    Handlebars.registerHelper('name', function(schema, options) {
        schema.__name = getName(schema);
        if(schema.__name) {
            return options.fn(schema);
        }
    });

    var refName = function(ref) {
        var name = getName(resolveRef(ref));
        if(!name) {
            if(ref == "#") {
                name = "<root>";
            } else {
                name = ref.replace("#", "/")
            }
        }
        var segments = name.split("/");
        name = segments[segments.length-1];
        return name;
    }

    function renderSchema(schema) {
        if(stack.indexOf(schema) == -1) { // avoid recursion
            return new Handlebars.SafeString(boxTemplate(schema));
        } else {
            return new Handlebars.SafeString(boxTemplate({"description": "_circular reference_"}));
        }
    }

    Handlebars.registerHelper('ref', function(schema, options) {
        if(schema.$ref) {
            var target = resolveRef(schema.$ref);
            if(target) {
                target.__name = refName(schema.$ref);
            }
            if(target) {
                return options.fn(target);
            } else {
                return new Handlebars.SafeString("Error: Could not resolve schema "+schema.$ref+"");
            }
        }
    });

    Handlebars.registerHelper('schema', function(schema) {
        return renderSchema(schema);
    });

    Handlebars.registerHelper('signature', function(schema, keyword, schemas) {
        if(!schemas) {
            schemas = []
        }
        schemas = schemas instanceof Array ? schemas : [schemas];
        return new Handlebars.SafeString(signatureTemplate({ schema: schema, keyword: keyword, schemas: schemas}));
    });

    Handlebars.registerHelper('l', function(context) {
        console.log(context);
    });

    function init() {
        $.when( $.get(docson.templateBaseUrl+"/box.html").done(function(content) {
            source = content
            boxTemplate = Handlebars.compile(source);
        }), $.get(docson.templateBaseUrl+"/signature.html").done(function(content) {
            source = content
            signatureTemplate = Handlebars.compile(source);
        })).always(function() {
            ready.resolve();
        });
    };

    docson.doc = function(element, schema, ref) {
        var d = $.Deferred();
        init();
        ready.done(function() {
            if(typeof element == "string") {
                element = $("#"+element);
            }
            if(typeof schema == "string") {
                schema = JSON.parse(schema);
            }

            var refsPromise = $.Deferred().resolve().promise();
            var refs = {};

            traverse(schema).forEach(function(item) {
                // Fix Swagger weird generation for array.
                if(item && item.$ref == "array") {
                    delete item.$ref;
                    item.type ="array";
                }

                // Fetch external schema
                if(this.key === "$ref") {
                    if((/^https?:\/\//).test(item)) {
                        var segments = item.split("#");
                        var p = $.get(segments[0]).then(function(content) {
                            if(typeof content != "object") {
                                try {
                                    content = JSON.parse(content);
                                } catch(e) {
                                    console.error("Unable to parse "+segments[0], e);
                                }
                            }
                            if(content) {
                                refs[item] = content;
                            }
                        });
                        refsPromise = p.then(refsPromise)
                    }
                }
            });

            refsPromise.done(function() {
                stack.push(refs);
                var target = schema;
                if(ref) {
                    ref = ref[0] !== '/' ? '/'+ref : ref;
                    target = jsonpointer.get(schema, ref);
                    stack.push( schema );
                }

                target.root = true;
                var html = boxTemplate(target);

                if(ref) {
                    stack.pop();
                }
                stack.pop();

                element.addClass("docson").html(html);

                var resizeHandler = element.get(0).onresize;
                function resized() {
                    if(resizeHandler) {
                        var box = element.find(".box").first();
                        element.get(0).onresize(box.outerWidth(), box.outerHeight());
                    }
                }
                element.get(0).resized = resized;
                resized();

                if(highlight) {
                    element.find(".json-schema").each(function(k, schemaElement) {
                        highlight.highlightSchema(schemaElement);
                    });
                }
                element.find(".box").mouseenter(function() {
                    $(this).children(".source-button").fadeIn(300);
                    $(this).children(".box-body").children(".expand-button").fadeIn(300);
                });
                element.find(".box").mouseleave(function() {
                    $(this).children(".source-button").fadeOut(300);
                    $(this).children(".box-body").children(".expand-button").fadeOut(300);
                });
                element.find(".signature-type-expandable").click(function() {
                    var boxId = $(this).attr("boxid");
                    $(this).toggleClass("signature-type-expanded");
                    $(this).parent().parent().parent().children(".signature-box-container").
                        children("[boxid='"+boxId+"']").toggle(resizeHandler ? 0 : 300);
                    resized();
                });
                element.find(".expand-button").click(function() {
                    if(this.expanded) {
                        $(this).html(" + ").attr("title", "Expand all");
                        $(this).parent().parent().find(".signature-type-expandable").removeClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").hide( resizeHandler ? 0 : 300);
                        this.expanded=false;
                        resized();
                    } else {
                        $(this).html(" - ").attr("title", "Collapse all");
                        $(this).parent().parent().find(".signature-type-expandable").addClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").show(resizeHandler ? 0 : 300);
                        this.expanded=true;
                        resized();
                    }
                });
                element.find(".source-button").click(function() {
                    $(this).parent().children(".box-body").toggle();
                    $(this).parent().children(".source").toggle();
                    resized();
                });
            });
            d.resolve();
        })
        return d.promise();
    }

    return docson;
});
<|endoftext|>


<commit_before>Polymer(
  {
    is: 'cordova-accelerometer',

    /**
     * Fired when an unkown error occured.
     *
     * @event error
     * @event cordova-accelerometerg-error
     */

    hostAttributes: {
      hidden: true
    },

    properties: {
      /**
       * If true, automatically performs watch when device is ready.
       */
      auto: Boolean,

      /**
       * If true, will watch over again, every period is finished.
       */
      loop: {
        observer: '_observeLoop',
        type: Boolean
      },

      /**
       * Time between updates of heading data in Milliseconds.
       */
      period: {
        type: Number,
        value: 3000
      },

      /**
       * Return if cordova deviceready event has been fired.
       */
      ready: {
        computed: '_computeReady(_ready_, _paused_)',
        notify: true,
        type: Boolean,
        value: false
      },

      /**
       * Creation timestamp for heading.
       */
      timestamp: {
        notify: true,
        readOnly: true,
        type: Number
      },

      /**
       * Amount of acceleration on the x-axis. (in m/s^2)
       */
      x: {
        notify: yes,
        readOnly: true,
        type: Number,
        value: 0
      }

      /**
       * Amount of acceleration on the y-axis. (in m/s^2)
       */
      y: {
        notify: yes,
        readOnly: true,
        type: Number,
        value: 0
      }

      /**
       * Amount of acceleration on the z-axis. (in m/s^2)
       */
      z: {
        notify: yes,
        readOnly: true,
        type: Number,
        value: 0
      }
    },

    observers: ['_observeReady(auto, ready)'],

    _computeReady(ready, paused) {
      return ready && !paused;
    },

    _observeLoop(loop) {
      (loop) ? this.watch() : this.clearWatch();
    },

    _observeReady(auto, ready) {
      if (auto && ready) {
        this.watch();
      }
    },

    _onError() {
      this.fire('error',...arguments
    )
      ;
      this.fire('cordova-accelerometer-error',...arguments
    )
      ;
    },

    _onWatch(acceleration) {
      this._setTimestamp(acceleration.timestamp);
      this._setX(acceleration.x);
      this._setY(acceleration.y);
      this._setZ(acceleration.z);
    },

    /**
     * Stop watching the Heading
     */
    clearWatch() {
      if (this.ready && this.watchId) {
        navigtor.compass.clearWatch(this.watchId);

        this.loop = false;
        this.watchId = null;
      }
    },

    /**
     * Get the current acceleration along the x, y, and z axes. If loop is
     * set, it gets acceleration at regular interval.
     */
    watch() {
      if (this.ready) {
        const errorCb = this._onError.bind(this);
        const fn = (this.loop) ? 'watchAcceleration' : 'getCurrentAcceleration';
        const optionsFn = {
          frequency: this.period
        };
        const successCb = this._onWatch.bind(this);

        this.watchId =
          navigator.accelerometer[fn](successCb, errorCb, optionsFn);
      }
    }
  }
)
<commit_msg>Update ES6 usage<commit_after>Polymer(
  {
    is: 'cordova-accelerometer',

    /**
     * Fired when an unkown error occured.
     *
     * @event error
     * @event cordova-accelerometerg-error
     */

    hostAttributes: {
      hidden: true
    },

    properties: {
      /**
       * If true, automatically performs watch when device is ready.
       */
      auto: Boolean,

      /**
       * If true, will watch over again, every period is finished.
       */
      loop: {
        observer: '_observeLoop',
        type: Boolean
      },

      /**
       * Time between updates of heading data in Milliseconds.
       */
      period: {
        type: Number,
        value: 3000
      },

      /**
       * Return if cordova deviceready event has been fired.
       */
      ready: {
        computed: '_computeReady(_ready_, _paused_)',
        notify: true,
        type: Boolean,
        value: false
      },

      /**
       * Creation timestamp for heading.
       */
      timestamp: {
        notify: true,
        readOnly: true,
        type: Number
      },

      /**
       * Amount of acceleration on the x-axis. (in m/s^2)
       */
      x: {
        notify: yes,
        readOnly: true,
        type: Number,
        value: 0
      }

      /**
       * Amount of acceleration on the y-axis. (in m/s^2)
       */
      y: {
        notify: yes,
        readOnly: true,
        type: Number,
        value: 0
      }

      /**
       * Amount of acceleration on the z-axis. (in m/s^2)
       */
      z: {
        notify: yes,
        readOnly: true,
        type: Number,
        value: 0
      }
    },

    observers: ['_observeReady(auto, ready)'],

    _computeReady(ready, paused) {
      return ready && !paused;
    },

    _observeLoop(loop) {
      (loop) ? this.watch() : this.clearWatch();
    },

    _observeReady(auto, ready) {
      if (auto && ready) {
        this.watch();
      }
    },

    _onError() {
      this.fire('error', ...arguments);
      this.fire('cordova-compass-error', ...argguments);
    },

    _onWatch(acceleration) {
      this._setTimestamp(acceleration.timestamp);
      this._setX(acceleration.x);
      this._setY(acceleration.y);
      this._setZ(acceleration.z);
    },

    /**
     * Stop watching the Heading
     */
    clearWatch() {
      if (this.ready && this.watchId) {
        navigtor.compass.clearWatch(this.watchId);

        this.loop = false;
        this.watchId = null;
      }
    },

    /**
     * Get the current acceleration along the x, y, and z axes. If loop is
     * set, it gets acceleration at regular interval.
     */
    watch() {
      if (this.ready) {
        const errorCb = this._onError.bind(this);
        const fn = (this.loop) ? 'watchAcceleration' : 'getCurrentAcceleration';
        const optionsFn = {
          frequency: this.period
        };
        const successCb = this._onWatch.bind(this);

        this.watchId =
          navigator.accelerometer[fn](successCb, errorCb, optionsFn);
      }
    }
  }
)
<|endoftext|>


<commit_before>(function() {

	"use strict";

	angular
		.module('app')
		.controller('SignInController', ['$rootScope', '$http', '$state', function SignInController($rootScope, $http, $state) {
			var signIn = this;

			signIn.user = {
				username: "",
				password: ""
			}

			signIn.submit = function signInSubmit($event) {
				$event.preventDefault();
				console.log("form submitted");
				$http({
					method: "POST",
					data: signIn.user,
					url: "/sessions"
				}).then(function onSuccessfulSignIn(response) {
					signIn.errorTitle = undefined;
					$rootScope.currentUser = response.data;
					$state.go('index.signed_in.contacts');
				}, function onFailedSignIn(response) {
					console.log('in failure callback');
					console.log(response);
					console.log(response.data);
					console.log(response.data.errors);
				});
			};

		}]);

})();<commit_msg>signIn.user is now reset on a successful sign in<commit_after>(function() {

	"use strict";

	angular
		.module('app')
		.controller('SignInController', ['$rootScope', '$http', '$state', function SignInController($rootScope, $http, $state) {
			var signIn = this;

			signIn.newUser = {
				username: "",
				password: ""
			};

			signIn.user = Object.assign({}, signIn.newUser)

			signIn.submit = function signInSubmit($event) {
				$event.preventDefault();
				console.log("form submitted");
				$http({
					method: "POST",
					data: signIn.user,
					url: "/sessions"
				}).then(function onSuccessfulSignIn(response) {
					signIn.errorTitle = undefined;
					signIn.user = Object.assign({}, signIn.newUser)
					$rootScope.currentUser = response.data;
					$state.go('index.signed_in.contacts');
				}, function onFailedSignIn(response) {
					console.log('in failure callback');
					console.log(response);
					console.log(response.data);
					console.log(response.data.errors);
				});
			};

		}]);

})();<|endoftext|>


<commit_before>$(document).ready(

function () {
    "use strict";

    //
    // Get the current widget id
    //
    var widget_id = $('#widgetid').val();

    //
    // set up the rating module
    //
    $('#rating-module').raty({
        click   : function(score,evt){
            console.log('id='+$(this).attr('id'));
            console.log('score='+score);
            console.log('event=');
            console.log(evt);

            var rate  = {};
            rate.rating = score;
            rate.userId = $('#logged-in-user-id').text();

            $.ajax({
                type: 'POST',
                dataType: 'json',
                url:"/api/widget/"+widget_id+"/rating",
                data: JSON.stringify(rate),
                cache: false,
                beforeSend: function(x) {
                    if (x && x.overrideMimeType) {
                        x.overrideMimeType("application/json;charset=UTF-8");
                    }
                },
                success: function (resp) {
                    if (resp['message'] === "OK") {
                       console.log("successssssssssss");
                    } else {
                        console.log('error');
                        //$('#widget-description').append("1there was an error in your update");
                    }
                },

                error: function () {
                    console.log('error');
                }
            });

        },
        starOff : 'star-off.png',
        starOn  : 'star-on.png',
        path    : '/images',
           //cancel  : true
        });

    //
    // Add edit event handler
    //
    $('#edit-widget-information').click(function () {
        var current_desc = $('#widget-description').text();
        console.log(current_desc);
        $('#widget-description').replaceWith('

<textarea class="input-xlarge" id="textarea" rows="3">' + current_desc + '</textarea>
<button type="submit" class="btn btn-primary">Save changes</button><button id="edit-description-cancel" class="btn">Cancel</button>
');
        $('#widget-description button[type="submit"]').click(function () {
            var newText = $('#widget-description textarea').val();
            $.ajax({
                type: 'PUT',
                dataType: 'json',
                url: "/api/widget/" + widget_id + "/description",
                data: newText,
                cache: false,
                success: function (resp) {
                    //console.log(resp);
                    if (resp['message'] === "OK update description done") {
                        $('#widget-description').replaceWith('
' + newText + '
');
                    } else {
                        $('#widget-description').append("1there was an error in your update");
                    }
                },
                error: function () {
                    $('#widget-description').append("2there was an error in your update");
                }
            });
        });
        $('#widget-description #edit-description-cancel').click(function () {
            $('#widget-description').replaceWith('
' + current_desc + '
');
        });
    });

    //
    // Add tag edit event handler
    //
    $('#add-tag').click(function () {
        $('#widget-tags').append('<form id="add-tag-form" action="javascript:function(){return false;}" class="well form-inline"><input type="text" class="input-small">' + '<button type="submit" class="btn">add</button>' + '</form>');
        // console.log('form added');
        // var new_position = $('#add-tag-form').offset();
        // console.log(new_position);
       //window.scrollTo(new_position.left,new_position.top);
        $('#add-tag-form input').focus();
        $('#add-tag-form').submit(function () {
            var newTag = $('#add-tag-form input[type="text"]').val();
            $.ajax({
                type: 'POST',
                dataType: 'json',
                url: "/api/widget/" + widget_id +"/tag",
                data: newTag,
                cache: false,
                success: function (resp) {
                    //console.log(resp);
                    if (resp['message']=="OK") {
                        var tag_db_id = resp['id'];
                        $('#add-tag-form').remove();
                        $('#widget-tags').append('' + newTag + '');
                    } else {
                        $('#widget-tags').append("1 - there was an error in your addition");
                    }
                },
                error: function () {
                    $('#widget-tags').append("2 - there was an error in your addition");
                }
            });
        });
        //console.log("done");
    });

    //
    // Add affordance event handler
    //
    $('#add-affordance').click(function () {

        //store in an array all current affordances of this widget profile
        //get this from dom elements
        var widget_affordances = [];
        $('#widget-useful-for a').each(function(){
            widget_affordances.push($(this).text());
        });
        console.log(widget_affordances);
        //show all available affordances
        $.ajax({
                type: 'GET',
                dataType: 'json',
                url: "/api/activity?operation=all",
                cache: false,
                beforeSend: function(){
                    //implement a loading icon here
                },
                success: function (resp) {
                    console.log(resp);
                    $('#widget-useful-for').append('<form id="select-affordances-form" action="javascript:function(){return false;}" class="well form-inline"></form>');

                    for (var index in resp){
                        var affordance = resp[index];
                        if ($.inArray(affordance.activitytext,widget_affordances)<0){
                            //if not in the array show it
                            var affordance_element = document.createElement("a");
                            var affordance_icon = document.createElement("i");
                            var affordance_id = affordance.id;
                            $(affordance_icon).attr("class", "icon-ok-circle icon-white available-affordance");
                            $(affordance_element).attr("class", "btn btn-warning disabled");
                            $(affordance_element).text(affordance.activitytext);
                            $(affordance_element).attr("href", "/activity/" + affordance_id);
                            $(affordance_element).attr("id", "add-activity-" + affordance_id);
                            $(affordance_element).prepend(affordance_icon);

                            var insert_element = document.createElement("a");
                            $(insert_element).attr("class","btn-mini btn-warning insert-activity-element");
                            $(insert_element).attr("href","#add-activity-"+affordance_id);
                            $(insert_element).attr("id","add-activity-insert-icon-"+affordance_id);
                            var insert_element_icon = document.createElement("i");
                            $(insert_element_icon).attr("class", "icon-plus icon-white");
                            $(insert_element).prepend(insert_element_icon);

                            $('#select-affordances-form').append(affordance_element);
                            $('#select-affordances-form').append(insert_element).append(" ");

                        }
                    }

                    //add click handlers in the affordance list elements
                    $('a.insert-activity-element').click(function(e){
                        //e.preventDefault();
                        console.log("aff clicked");
                        var insert_element = $(this);
                        var affordance_id = $(this).attr("id").split('add-activity-insert-icon-')[1];

                        $.ajax({
                            type: 'POST',
                            dataType: 'json',
                            url: "/api/widget/" + widget_id +"/activity",
                            data: affordance_id,
                            cache: false,
                            success: function (resp) {
                                //console.log(resp);
                                if (resp['message']=="OK") {
                                    var affordance_element = $('#add-activity-'+affordance_id);
                                    $(insert_element).remove();
                                    $(affordance_element).remove();

                                    var affordance = document.createElement("a");
                                    var affordance_icon = document.createElement("i");
                                    $(affordance_icon).attr("class", "icon-ok-circle icon-white");
                                    $(affordance).attr("class", "btn btn-warning");
                                    $(affordance).text($(affordance_element).text());
                                    $(affordance).attr("href", "/activity/" + affordance_id);
                                    $(affordance).prepend(affordance_icon);
                                    $("#widget-useful-for").prepend(affordance).prepend(" ");
                                } else {
                                    $('#widget-tags').append("1 - there was an error in your addition");
                                    console.log('activity addition error:');
                                    console.log(resp);
                                }
                            },
                            error: function () {
                                $('#widget-tags').append("2 - there was an error in your addition");
                                console.log('activity addition - ajax error');
                            }
                        });
                    });
                },
                error: function () {
                    $('#widget-useful-for').append("There was an error while retrieving available affordances");
                }
            });

    });

    //
    // add write a review handler
    //
    $('#write-a-review-anchor').click(function () {
        $(this).replaceWith('
' +
        		'Your review:' +
        		'
' +
        		'<textarea class="input-xlarge" id="review-textarea" rows="3"></textarea>' +
        		'
<button type="submit" class="btn btn-primary">Submit</button>' +
        		'<button id="edit-description-cancel" class="btn">Cancel</button>' +
        		'
');

        $('#write-a-review button[type="submit"]').click(function () {
            //get info from hidden fields and profile area
            var reviewText = $('#review-textarea').val();
            var userid = $('#logged-in-user-id').text();
            var gravatarImg = $('#logged-in-user-gravatar-img').val();
            var username = $('#logged-in-user-name').text();

            var review  = {};
            review.comment = $('#review-textarea').val();
            review.userId = $('#logged-in-user-id').text();

            $.ajax({
                type: 'POST',
                dataType: 'json',
                url:"/api/widget/"+widget_id+"/comment",
                data: JSON.stringify(review),
                cache: false,
                beforeSend: function(x) {
                    if (x && x.overrideMimeType) {
                        x.overrideMimeType("application/json;charset=UTF-8");
                    }
                },
                success: function (resp) {
                    if (resp['message'] === "OK") {
                        $('#user-reviews').append("

"+reviewText+"
"+username+", just now");
                        $('#write-a-review').remove();
                    } else {
                        console.log('error');
                        //$('#widget-description').append("1there was an error in your update");
                    }
                },

                error: function () {
                    console.log('error');
                }
            });
        });
        $('#widget-description #edit-description-cancel').click(function () {
            $('#widget-description').replaceWith('
' + current_desc + '
');
        });
    });
    var widgetUri;

    //
    // Load the widget profile
    //
    $.getJSON('/api/widget/' + widget_id, function (data) {
        widgetUri = data.widgetProfile.uri;

        //
        // Show metadata
        //
        $("#widget_name").text(
        data.widgetProfile.name);
        if (data.uploadedBy) {
            $("#upload-info").text("Uploaded by " + data.uploadedBy.username);
        }
        $("#widget_icon").attr("src",data.widgetProfile.icon);

        //
        // Show w3c or opensocial logo
        //
        if (data.widgetProfile.type === "W3C Widget") {
            $('#widget-type').html("This widget complies with the W3C widget standard");
        } else {
            $('#widget-type').html("This widget complies with the OpenSocial standard");

        }

        //
        // Show average rating
        //
        var average_rating;
        if (data.averageRating) {
            average_rating = data.averageRating;
        }else {
            average_rating = 0;
        }
        $('#widget-rating').raty({
                readOnly    : true,
                start       : average_rating,
                starOff : 'star-off.png',
                starOn  : 'star-on.png',
                path    : '/images',
            });

        //
        // Show description
        //
        if (data.widgetProfile.description) {
            $('#widget-description').text(data.widgetProfile.description);
        }

        //
        // Show preview instance if available
        // and create actions
        //
        if (data.renderInfo) {
            $('#widget-preview').html(data.renderInfo);
            $('#widget-open-fully-link').attr("href", data.renderUrl);
            $('#embedModal .modal-body pre').text((data.renderInfo));
            $('#modal-body-lti').html("
For Basic LTI, copy the following information to your Basic LTI consumer:

URL: http://widgets.open.ac.uk:8080/lti/" + data.widgetProfile.id + "

Consumer Key: TEST

Consumer Secret: TEST
");
            //show embed code as a modal
            $('#embedModal').modal({
                show: false
            });
            $('#embedModal-link').click(function () {
                $('#embedModal').modal('toggle');
            });
            if (data.downloadUrl){
                $('#widget-actions').append(" Download
");
            }
        }

        //
        // Show tags
        //
        if (data.widgetProfile.tags) {
            var tags = data.widgetProfile.tags;
            for (var i = 0; i < tags.length; i++) {
                var tag = document.createElement("a");
                var tag_icon = document.createElement("i");
                $(tag_icon).attr("class", "icon-tag icon-white");
                $(tag).attr("class", "btn btn-info");
                $(tag).text(tags[i].tagtext);
                $(tag).attr("href", "/tag/" + tags[i].id);
                $(tag).prepend(tag_icon);
                $("#widget-tags").append(tag).append(" ");
            }
        }

        //
        // Show activities
        //
        if (data.widgetProfile.activities) {
            var affordances = data.widgetProfile.activities;
            for (var i = 0; i < affordances.length; i++) {
                var affordance = document.createElement("a");
                var affordance_icon = document.createElement("i");
                var affordance_id = affordances[i].id;
                $(affordance_icon).attr("class", "icon-ok-circle icon-white");
                $(affordance).attr("class", "btn btn-warning");
                $(affordance).text(affordances[i].activitytext);
                $(affordance).attr("href", "/activity/" + affordance_id);
                $(affordance).prepend(affordance_icon);
                $("#widget-useful-for").append(affordance).append(" ");
            }
        }

        //
        // Load similar widget profiles
        //
        $.getJSON('/api/widget/' + widget_id + "/similar", function (data) {
            for (var i = 0; i < data.length; i++) {
                $('#related-widgets').append(''+renderWidget(data[i].id, data[i].icon, data[i].name, data[i].description));
            }
        });

        //
        // Load reviews
        //
        $.getJSON('/api/widget/' + widget_id +'/comments', function (reviews) {
            for (var i = 0; i < reviews.length; i++) {
                var wrapper = document.createElement("div");
                $(wrapper).hide();
                $(wrapper).append("

"+reviews[i].text+"
"+reviews[i].user+", "+reviews[i].time+"");
                $(wrapper).appendTo("#user-reviews").fadeIn("slow");
            }
        });

        $("#widget_info").fadeIn();
    });
});<commit_msg>Render user reviews, including user profile link where supplied by the API<commit_after>$(document).ready(

function () {
    "use strict";

    //
    // Get the current widget id
    //
    var widget_id = $('#widgetid').val();

    //
    // set up the rating module
    //
    $('#rating-module').raty({
        click   : function(score,evt){
            console.log('id='+$(this).attr('id'));
            console.log('score='+score);
            console.log('event=');
            console.log(evt);

            var rate  = {};
            rate.rating = score;
            rate.userId = $('#logged-in-user-id').text();

            $.ajax({
                type: 'POST',
                dataType: 'json',
                url:"/api/widget/"+widget_id+"/rating",
                data: JSON.stringify(rate),
                cache: false,
                beforeSend: function(x) {
                    if (x && x.overrideMimeType) {
                        x.overrideMimeType("application/json;charset=UTF-8");
                    }
                },
                success: function (resp) {
                    if (resp['message'] === "OK") {
                       console.log("successssssssssss");
                    } else {
                        console.log('error');
                        //$('#widget-description').append("1there was an error in your update");
                    }
                },

                error: function () {
                    console.log('error');
                }
            });

        },
        starOff : 'star-off.png',
        starOn  : 'star-on.png',
        path    : '/images',
           //cancel  : true
        });

    //
    // Add edit event handler
    //
    $('#edit-widget-information').click(function () {
        var current_desc = $('#widget-description').text();
        console.log(current_desc);
        $('#widget-description').replaceWith('

<textarea class="input-xlarge" id="textarea" rows="3">' + current_desc + '</textarea>
<button type="submit" class="btn btn-primary">Save changes</button><button id="edit-description-cancel" class="btn">Cancel</button>
');
        $('#widget-description button[type="submit"]').click(function () {
            var newText = $('#widget-description textarea').val();
            $.ajax({
                type: 'PUT',
                dataType: 'json',
                url: "/api/widget/" + widget_id + "/description",
                data: newText,
                cache: false,
                success: function (resp) {
                    //console.log(resp);
                    if (resp['message'] === "OK update description done") {
                        $('#widget-description').replaceWith('
' + newText + '
');
                    } else {
                        $('#widget-description').append("1there was an error in your update");
                    }
                },
                error: function () {
                    $('#widget-description').append("2there was an error in your update");
                }
            });
        });
        $('#widget-description #edit-description-cancel').click(function () {
            $('#widget-description').replaceWith('
' + current_desc + '
');
        });
    });

    //
    // Add tag edit event handler
    //
    $('#add-tag').click(function () {
        $('#widget-tags').append('<form id="add-tag-form" action="javascript:function(){return false;}" class="well form-inline"><input type="text" class="input-small">' + '<button type="submit" class="btn">add</button>' + '</form>');
        // console.log('form added');
        // var new_position = $('#add-tag-form').offset();
        // console.log(new_position);
       //window.scrollTo(new_position.left,new_position.top);
        $('#add-tag-form input').focus();
        $('#add-tag-form').submit(function () {
            var newTag = $('#add-tag-form input[type="text"]').val();
            $.ajax({
                type: 'POST',
                dataType: 'json',
                url: "/api/widget/" + widget_id +"/tag",
                data: newTag,
                cache: false,
                success: function (resp) {
                    //console.log(resp);
                    if (resp['message']=="OK") {
                        var tag_db_id = resp['id'];
                        $('#add-tag-form').remove();
                        $('#widget-tags').append('' + newTag + '');
                    } else {
                        $('#widget-tags').append("1 - there was an error in your addition");
                    }
                },
                error: function () {
                    $('#widget-tags').append("2 - there was an error in your addition");
                }
            });
        });
        //console.log("done");
    });

    //
    // Add affordance event handler
    //
    $('#add-affordance').click(function () {

        //store in an array all current affordances of this widget profile
        //get this from dom elements
        var widget_affordances = [];
        $('#widget-useful-for a').each(function(){
            widget_affordances.push($(this).text());
        });
        console.log(widget_affordances);
        //show all available affordances
        $.ajax({
                type: 'GET',
                dataType: 'json',
                url: "/api/activity?operation=all",
                cache: false,
                beforeSend: function(){
                    //implement a loading icon here
                },
                success: function (resp) {
                    console.log(resp);
                    $('#widget-useful-for').append('<form id="select-affordances-form" action="javascript:function(){return false;}" class="well form-inline"></form>');

                    for (var index in resp){
                        var affordance = resp[index];
                        if ($.inArray(affordance.activitytext,widget_affordances)<0){
                            //if not in the array show it
                            var affordance_element = document.createElement("a");
                            var affordance_icon = document.createElement("i");
                            var affordance_id = affordance.id;
                            $(affordance_icon).attr("class", "icon-ok-circle icon-white available-affordance");
                            $(affordance_element).attr("class", "btn btn-warning disabled");
                            $(affordance_element).text(affordance.activitytext);
                            $(affordance_element).attr("href", "/activity/" + affordance_id);
                            $(affordance_element).attr("id", "add-activity-" + affordance_id);
                            $(affordance_element).prepend(affordance_icon);

                            var insert_element = document.createElement("a");
                            $(insert_element).attr("class","btn-mini btn-warning insert-activity-element");
                            $(insert_element).attr("href","#add-activity-"+affordance_id);
                            $(insert_element).attr("id","add-activity-insert-icon-"+affordance_id);
                            var insert_element_icon = document.createElement("i");
                            $(insert_element_icon).attr("class", "icon-plus icon-white");
                            $(insert_element).prepend(insert_element_icon);

                            $('#select-affordances-form').append(affordance_element);
                            $('#select-affordances-form').append(insert_element).append(" ");

                        }
                    }

                    //add click handlers in the affordance list elements
                    $('a.insert-activity-element').click(function(e){
                        //e.preventDefault();
                        console.log("aff clicked");
                        var insert_element = $(this);
                        var affordance_id = $(this).attr("id").split('add-activity-insert-icon-')[1];

                        $.ajax({
                            type: 'POST',
                            dataType: 'json',
                            url: "/api/widget/" + widget_id +"/activity",
                            data: affordance_id,
                            cache: false,
                            success: function (resp) {
                                //console.log(resp);
                                if (resp['message']=="OK") {
                                    var affordance_element = $('#add-activity-'+affordance_id);
                                    $(insert_element).remove();
                                    $(affordance_element).remove();

                                    var affordance = document.createElement("a");
                                    var affordance_icon = document.createElement("i");
                                    $(affordance_icon).attr("class", "icon-ok-circle icon-white");
                                    $(affordance).attr("class", "btn btn-warning");
                                    $(affordance).text($(affordance_element).text());
                                    $(affordance).attr("href", "/activity/" + affordance_id);
                                    $(affordance).prepend(affordance_icon);
                                    $("#widget-useful-for").prepend(affordance).prepend(" ");
                                } else {
                                    $('#widget-tags').append("1 - there was an error in your addition");
                                    console.log('activity addition error:');
                                    console.log(resp);
                                }
                            },
                            error: function () {
                                $('#widget-tags').append("2 - there was an error in your addition");
                                console.log('activity addition - ajax error');
                            }
                        });
                    });
                },
                error: function () {
                    $('#widget-useful-for').append("There was an error while retrieving available affordances");
                }
            });

    });

    //
    // add write a review handler
    //
    $('#write-a-review-anchor').click(function () {
        $(this).replaceWith('
' +
        		'Your review:' +
        		'
' +
        		'<textarea class="input-xlarge" id="review-textarea" rows="3"></textarea>' +
        		'
<button type="submit" class="btn btn-primary">Submit</button>' +
        		'<button id="edit-description-cancel" class="btn">Cancel</button>' +
        		'
');

        $('#write-a-review button[type="submit"]').click(function () {
            //get info from hidden fields and profile area
            var reviewText = $('#review-textarea').val();
            var userid = $('#logged-in-user-id').text();
            var gravatarImg = $('#logged-in-user-gravatar-img').val();
            var username = $('#logged-in-user-name').text();

            var review  = {};
            review.comment = $('#review-textarea').val();
            review.userId = $('#logged-in-user-id').text();

            $.ajax({
                type: 'POST',
                dataType: 'json',
                url:"/api/widget/"+widget_id+"/comment",
                data: JSON.stringify(review),
                cache: false,
                beforeSend: function(x) {
                    if (x && x.overrideMimeType) {
                        x.overrideMimeType("application/json;charset=UTF-8");
                    }
                },
                success: function (resp) {
                    if (resp['message'] === "OK") {
                        $('#user-reviews').append("

"+reviewText+"
"+username+", just now");
                        $('#write-a-review').remove();
                    } else {
                        console.log('error');
                        //$('#widget-description').append("1there was an error in your update");
                    }
                },

                error: function () {
                    console.log('error');
                }
            });
        });
        $('#widget-description #edit-description-cancel').click(function () {
            $('#widget-description').replaceWith('
' + current_desc + '
');
        });
    });
    var widgetUri;

    //
    // Load the widget profile
    //
    $.getJSON('/api/widget/' + widget_id, function (data) {
        widgetUri = data.widgetProfile.uri;

        //
        // Show metadata
        //
        $("#widget_name").text(
        data.widgetProfile.name);
        if (data.uploadedBy) {
            $("#upload-info").text("Uploaded by " + data.uploadedBy.username);
        }
        $("#widget_icon").attr("src",data.widgetProfile.icon);

        //
        // Show w3c or opensocial logo
        //
        if (data.widgetProfile.type === "W3C Widget") {
            $('#widget-type').html("This widget complies with the W3C widget standard");
        } else {
            $('#widget-type').html("This widget complies with the OpenSocial standard");

        }

        //
        // Show average rating
        //
        var average_rating;
        if (data.averageRating) {
            average_rating = data.averageRating;
        }else {
            average_rating = 0;
        }
        $('#widget-rating').raty({
                readOnly    : true,
                start       : average_rating,
                starOff : 'star-off.png',
                starOn  : 'star-on.png',
                path    : '/images',
            });

        //
        // Show description
        //
        if (data.widgetProfile.description) {
            $('#widget-description').text(data.widgetProfile.description);
        }

        //
        // Show preview instance if available
        // and create actions
        //
        if (data.renderInfo) {
            $('#widget-preview').html(data.renderInfo);
            $('#widget-open-fully-link').attr("href", data.renderUrl);
            $('#embedModal .modal-body pre').text((data.renderInfo));
            $('#modal-body-lti').html("
For Basic LTI, copy the following information to your Basic LTI consumer:

URL: http://widgets.open.ac.uk:8080/lti/" + data.widgetProfile.id + "

Consumer Key: TEST

Consumer Secret: TEST
");
            //show embed code as a modal
            $('#embedModal').modal({
                show: false
            });
            $('#embedModal-link').click(function () {
                $('#embedModal').modal('toggle');
            });
            if (data.downloadUrl){
                $('#widget-actions').append(" Download
");
            }
        }

        //
        // Show tags
        //
        if (data.widgetProfile.tags) {
            var tags = data.widgetProfile.tags;
            for (var i = 0; i < tags.length; i++) {
                var tag = document.createElement("a");
                var tag_icon = document.createElement("i");
                $(tag_icon).attr("class", "icon-tag icon-white");
                $(tag).attr("class", "btn btn-info");
                $(tag).text(tags[i].tagtext);
                $(tag).attr("href", "/tag/" + tags[i].id);
                $(tag).prepend(tag_icon);
                $("#widget-tags").append(tag).append(" ");
            }
        }

        //
        // Show activities
        //
        if (data.widgetProfile.activities) {
            var affordances = data.widgetProfile.activities;
            for (var i = 0; i < affordances.length; i++) {
                var affordance = document.createElement("a");
                var affordance_icon = document.createElement("i");
                var affordance_id = affordances[i].id;
                $(affordance_icon).attr("class", "icon-ok-circle icon-white");
                $(affordance).attr("class", "btn btn-warning");
                $(affordance).text(affordances[i].activitytext);
                $(affordance).attr("href", "/activity/" + affordance_id);
                $(affordance).prepend(affordance_icon);
                $("#widget-useful-for").append(affordance).append(" ");
            }
        }

        //
        // Load similar widget profiles
        //
        $.getJSON('/api/widget/' + widget_id + "/similar", function (data) {
            for (var i = 0; i < data.length; i++) {
                $('#related-widgets').append(''+renderWidget(data[i].id, data[i].icon, data[i].name, data[i].description));
            }
        });

        //
        // Load reviews
        //
        $.getJSON('/api/widget/' + widget_id +'/comments', function (reviews) {
            for (var i = 0; i < reviews.length; i++) {
                var wrapper = document.createElement("div");
                $(wrapper).hide();
                var profileLink;
                var userProfile = reviews[i].userProfile;
                if (!userProfile){
                    profileLink = reviews[i].user;
                } else {
                    profileLink = ""+reviews[i].user+"";
                }
                $(wrapper).append("

"+reviews[i].text+"
"+profileLink+", "+reviews[i].time+"");
                $(wrapper).appendTo("#user-reviews").fadeIn("slow");
            }
        });

        $("#widget_info").fadeIn();
    });
});<|endoftext|>


<commit_before>// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import path from 'path';
import {app, BrowserWindow, nativeImage, systemPreferences, ipcMain} from 'electron';
import log from 'electron-log';

import {MAXIMIZE_CHANGE, HISTORY, GET_LOADING_SCREEN_DATA, REACT_APP_INITIALIZED, LOADING_SCREEN_ANIMATION_FINISHED, FOCUS_THREE_DOT_MENU} from 'common/communication';
import urlUtils from 'common/utils/url';

import {getAdjustedWindowBoundaries} from '../utils';

import {ViewManager} from '../views/viewManager';
import {CriticalErrorHandler} from '../CriticalErrorHandler';

import {createSettingsWindow} from './settingsWindow';
import createMainWindow from './mainWindow';

// singleton module to manage application's windows

const status = {
    mainWindow: null,
    settingsWindow: null,
    config: null,
    viewManager: null,
};
const assetsDir = path.resolve(app.getAppPath(), 'assets');

ipcMain.on(HISTORY, handleHistory);
ipcMain.handle(GET_LOADING_SCREEN_DATA, handleLoadingScreenDataRequest);
ipcMain.on(REACT_APP_INITIALIZED, handleReactAppInitialized);
ipcMain.on(LOADING_SCREEN_ANIMATION_FINISHED, handleLoadingScreenAnimationFinished);

export function setConfig(data) {
    if (data) {
        status.config = data;
    }
    if (status.viewManager) {
        status.viewManager.reloadConfiguration(status.config.teams);
    }
}

export function showSettingsWindow() {
    if (status.settingsWindow) {
        status.settingsWindow.show();
    } else {
        if (!status.mainWindow) {
            showMainWindow();
        }
        const withDevTools = process.env.MM_DEBUG_SETTINGS || false;

        status.settingsWindow = createSettingsWindow(status.mainWindow, status.config, withDevTools);
        status.settingsWindow.on('closed', () => {
            status.settingsWindow = null;
            focusBrowserView();
        });
    }
}

export function showMainWindow(deeplinkingURL) {
    if (status.mainWindow) {
        if (status.mainWindow.isVisible()) {
            status.mainWindow.focus();
        } else {
            status.mainWindow.show();
        }
    } else {
        status.mainWindow = createMainWindow(status.config, {
            linuxAppIcon: path.join(assetsDir, 'linux', 'app_icon.png'),
        });

        if (!status.mainWindow) {
            log.error('unable to create main window');
            app.quit();
        }

        // window handlers
        status.mainWindow.on('closed', () => {
            log.warn('main window closed');
            status.mainWindow = null;
        });
        status.mainWindow.on('unresponsive', () => {
            const criticalErrorHandler = new CriticalErrorHandler();
            criticalErrorHandler.setMainWindow(status.mainWindow);
            criticalErrorHandler.windowUnresponsiveHandler();
        });
        status.mainWindow.on('crashed', handleMainWindowWebContentsCrashed);
        status.mainWindow.on('maximize', handleMaximizeMainWindow);
        status.mainWindow.on('unmaximize', handleUnmaximizeMainWindow);
        status.mainWindow.on('resize', handleResizeMainWindow);
        status.mainWindow.on('focus', focusBrowserView);
        status.mainWindow.on('enter-full-screen', () => sendToRenderer('enter-full-screen'));
        status.mainWindow.on('leave-full-screen', () => sendToRenderer('leave-full-screen'));

        if (process.env.MM_DEBUG_SETTINGS) {
            status.mainWindow.webContents.openDevTools({mode: 'detach'});
        }

        if (status.viewManager) {
            status.viewManager.updateMainWindow(status.mainWindow);
        }
    }
    initializeViewManager();

    if (deeplinkingURL) {
        status.viewManager.handleDeepLink(deeplinkingURL);
    }
}

export function getMainWindow(ensureCreated) {
    if (ensureCreated && status.mainWindow === null) {
        showMainWindow();
    }
    return status.mainWindow;
}

export function on(event, listener) {
    return status.mainWindow.on(event, listener);
}

function handleMainWindowWebContentsCrashed() {
    throw new Error('webContents \'crashed\' event has been emitted');
}

function handleMaximizeMainWindow() {
    sendToRenderer(MAXIMIZE_CHANGE, true);

    // Workaround as part of https://mattermost.atlassian.net/browse/MM-33577
    // Linux (or GNOME at least) seems to have issues with Electron and getting the size correctly when minimizing/maximizing
    // So we need to manually force the browser view to resize after a small interval to get the size correct
    // Please remove this once this issue has been resolved by Electron
    if (process.platform === 'linux') {
        setTimeout(setBoundsForCurrentView, 10);
    }
}

function handleUnmaximizeMainWindow() {
    sendToRenderer(MAXIMIZE_CHANGE, false);

    // Workaround as part of https://mattermost.atlassian.net/browse/MM-33577
    // Linux (or GNOME at least) seems to have issues with Electron and getting the size correctly when minimizing/maximizing
    // So we need to manually force the browser view to resize after a small interval to get the size correct
    // Please remove this once this issue has been resolved by Electron
    if (process.platform === 'linux') {
        setTimeout(setBoundsForCurrentView, 10);
    }
}

function handleResizeMainWindow(event, newBounds) {
    setBoundsForCurrentView(event, newBounds);
}

function setBoundsForCurrentView(event, newBounds) {
    const currentView = status.viewManager.getCurrentView();
    const bounds = newBounds || status.mainWindow.getContentBounds();
    if (currentView) {
        currentView.setBounds(getAdjustedWindowBoundaries(bounds.width, bounds.height, !urlUtils.isTeamUrl(currentView.server.url, currentView.view.webContents.getURL())));
    }
    status.viewManager.setLoadingScreenBounds();
}

export function sendToRenderer(channel, ...args) {
    if (!status.mainWindow) {
        showMainWindow();
    }
    status.mainWindow.webContents.send(channel, ...args);
    if (status.settingsWindow && status.settingsWindow.isVisible()) {
        status.settingsWindow.webContents.send(channel, ...args);
    }
}

export function sendToAll(channel, ...args) {
    sendToRenderer(channel, ...args);
    if (status.settingsWindow) {
        status.settingsWindow.webContents.send(channel, ...args);
    }

    // TODO: should we include popups?
}

export function sendToMattermostViews(channel, ...args) {
    if (status.viewManager) {
        status.viewManager.sendToAllViews(channel, ...args);
    }
}

export function restoreMain() {
    log.info('restoreMain');
    if (!status.mainWindow) {
        showMainWindow();
    }
    if (!status.mainWindow.isVisible() || status.mainWindow.isMinimized()) {
        if (status.mainWindow.isMinimized()) {
            status.mainWindow.restore();
        } else {
            status.mainWindow.show();
        }
        if (status.settingsWindow) {
            status.settingsWindow.focus();
        } else {
            status.mainWindow.focus();
        }
        if (process.platform === 'darwin') {
            app.dock.show();
        }
    } else if (status.settingsWindow) {
        status.settingsWindow.focus();
    } else {
        status.mainWindow.focus();
    }
}

export function flashFrame(flash) {
    if (process.platform === 'linux' || process.platform === 'win32') {
        status.mainWindow.flashFrame(flash);
        if (status.settingsWindow) {
            // main might be hidden behind the settings
            status.settingsWindow.flashFrame(flash);
        }
    }
    if (process.platform === 'darwin' && status.config.notifications.bounceIcon) {
        app.dock.bounce(status.config.notifications.bounceIconType);
    }
}

function drawBadge(text, small) {
    const scale = 2; // should rely display dpi
    const size = (small ? 20 : 16) * scale;
    const canvas = document.createElement('canvas');
    canvas.setAttribute('width', size);
    canvas.setAttribute('height', size);
    const ctx = canvas.getContext('2d');

    // circle
    ctx.fillStyle = '#FF1744'; // Material Red A400
    ctx.beginPath();
    ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
    ctx.fill();

    // text
    ctx.fillStyle = '#ffffff';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.font = (11 * scale) + 'px sans-serif';
    ctx.fillText(text, size / 2, size / 2, size);

    return canvas.toDataURL();
}

function createDataURL(text, small) {
    const win = status.mainWindow;
    if (!win) {
        return null;
    }

    // since we don't have a document/canvas object in the main process, we use the webcontents from the window to draw.
    const safeSmall = Boolean(small);
    const code = `
    window.drawBadge = ${drawBadge};
    window.drawBadge('${text || ''}', ${safeSmall});
  `;
    return win.webContents.executeJavaScript(code);
}

export async function setOverlayIcon(badgeText, description, small) {
    if (process.platform === 'win32') {
        let overlay = null;
        if (status.mainWindow && badgeText) {
            try {
                const dataUrl = await createDataURL(badgeText, small);
                overlay = nativeImage.createFromDataURL(dataUrl);
            } catch (err) {
                log.error(`Couldn't generate a badge: ${err}`);
            }
        }
        status.mainWindow.setOverlayIcon(overlay, description);
    }
}

export function isMainWindow(window) {
    return status.mainWindow && status.mainWindow === window;
}

export function handleDoubleClick(e, windowType) {
    let action = 'Maximize';
    if (process.platform === 'darwin') {
        action = systemPreferences.getUserDefault('AppleActionOnDoubleClick', 'string');
    }
    const win = (windowType === 'settings') ? status.settingsWindow : status.mainWindow;
    switch (action) {
    case 'Minimize':
        if (win.isMinimized()) {
            win.restore();
        } else {
            win.minimize();
        }
        break;
    case 'Maximize':
    default:
        if (win.isMaximized()) {
            win.unmaximize();
        } else {
            win.maximize();
        }
        break;
    }
}

function initializeViewManager() {
    if (!status.viewManager) {
        status.viewManager = new ViewManager(status.config, status.mainWindow);
        status.viewManager.load();
        status.viewManager.showInitial();
    }
}

export function switchServer(serverName) {
    showMainWindow();
    status.viewManager.showByName(serverName);
}

export function focusBrowserView() {
    if (status.viewManager) {
        status.viewManager.focus();
    } else {
        log.error('Trying to call focus when the viewmanager has not yet been initialized');
    }
}

export function openBrowserViewDevTools() {
    if (status.viewManager) {
        status.viewManager.openViewDevTools();
    }
}

export function focusThreeDotMenu() {
    if (status.mainWindow) {
        status.mainWindow.webContents.focus();
        status.mainWindow.webContents.send(FOCUS_THREE_DOT_MENU);
    }
}

function handleLoadingScreenDataRequest() {
    return {
        darkMode: status.config.darkMode,
    };
}

function handleReactAppInitialized(_, server) {
    if (status.viewManager) {
        status.viewManager.setServerInitialized(server);
    }
}

function handleLoadingScreenAnimationFinished() {
    if (status.viewManager) {
        status.viewManager.hideLoadingScreen();
    }
}

export function updateLoadingScreenDarkMode(darkMode) {
    if (status.viewManager) {
        status.viewManager.updateLoadingScreenDarkMode(darkMode);
    }
}

export function getServerNameByWebContentsId(webContentsId) {
    if (status.viewManager) {
        return status.viewManager.findByWebContent(webContentsId);
    }
    return null;
}

export function close() {
    const focused = BrowserWindow.getFocusedWindow();
    if (focused.id === status.mainWindow.id) {
    // TODO: figure out logic for closing
        focused.close();
    } else {
        focused.close();
    }
}
export function maximize() {
    const focused = BrowserWindow.getFocusedWindow();
    focused.maximize();
}
export function minimize() {
    const focused = BrowserWindow.getFocusedWindow();
    focused.minimize();
}
export function restore() {
    const focused = BrowserWindow.getFocusedWindow();
    focused.restore();
}

export function reload() {
    const currentView = status.viewManager.getCurrentView();
    if (currentView) {
        status.viewManager.showLoadingScreen();
        currentView.reload();
    }
}

export function sendToFind() {
    const currentView = status.viewManager.getCurrentView();
    if (currentView) {
        currentView.view.webContents.sendInputEvent({type: 'keyDown', keyCode: 'F', modifiers: ['CmdOrCtrl', 'Shift']});
    }
}

export function handleHistory(event, offset) {
    if (status.viewManager) {
        const activeView = status.viewManager.getCurrentView();
        if (activeView && activeView.view.webContents.canGoToOffset(offset)) {
            try {
                activeView.view.webContents.goToOffset(offset);
            } catch (error) {
                log.error(error);
                activeView.load(activeView.server.url);
            }
        }
    }
}
<commit_msg>[MM-35588] Ensure that the window exists before calling minimize/maximize/reload (#1598)<commit_after>// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import path from 'path';
import {app, BrowserWindow, nativeImage, systemPreferences, ipcMain} from 'electron';
import log from 'electron-log';

import {MAXIMIZE_CHANGE, HISTORY, GET_LOADING_SCREEN_DATA, REACT_APP_INITIALIZED, LOADING_SCREEN_ANIMATION_FINISHED, FOCUS_THREE_DOT_MENU} from 'common/communication';
import urlUtils from 'common/utils/url';

import {getAdjustedWindowBoundaries} from '../utils';

import {ViewManager} from '../views/viewManager';
import {CriticalErrorHandler} from '../CriticalErrorHandler';

import {createSettingsWindow} from './settingsWindow';
import createMainWindow from './mainWindow';

// singleton module to manage application's windows

const status = {
    mainWindow: null,
    settingsWindow: null,
    config: null,
    viewManager: null,
};
const assetsDir = path.resolve(app.getAppPath(), 'assets');

ipcMain.on(HISTORY, handleHistory);
ipcMain.handle(GET_LOADING_SCREEN_DATA, handleLoadingScreenDataRequest);
ipcMain.on(REACT_APP_INITIALIZED, handleReactAppInitialized);
ipcMain.on(LOADING_SCREEN_ANIMATION_FINISHED, handleLoadingScreenAnimationFinished);

export function setConfig(data) {
    if (data) {
        status.config = data;
    }
    if (status.viewManager) {
        status.viewManager.reloadConfiguration(status.config.teams);
    }
}

export function showSettingsWindow() {
    if (status.settingsWindow) {
        status.settingsWindow.show();
    } else {
        if (!status.mainWindow) {
            showMainWindow();
        }
        const withDevTools = process.env.MM_DEBUG_SETTINGS || false;

        status.settingsWindow = createSettingsWindow(status.mainWindow, status.config, withDevTools);
        status.settingsWindow.on('closed', () => {
            status.settingsWindow = null;
            focusBrowserView();
        });
    }
}

export function showMainWindow(deeplinkingURL) {
    if (status.mainWindow) {
        if (status.mainWindow.isVisible()) {
            status.mainWindow.focus();
        } else {
            status.mainWindow.show();
        }
    } else {
        status.mainWindow = createMainWindow(status.config, {
            linuxAppIcon: path.join(assetsDir, 'linux', 'app_icon.png'),
        });

        if (!status.mainWindow) {
            log.error('unable to create main window');
            app.quit();
        }

        // window handlers
        status.mainWindow.on('closed', () => {
            log.warn('main window closed');
            status.mainWindow = null;
        });
        status.mainWindow.on('unresponsive', () => {
            const criticalErrorHandler = new CriticalErrorHandler();
            criticalErrorHandler.setMainWindow(status.mainWindow);
            criticalErrorHandler.windowUnresponsiveHandler();
        });
        status.mainWindow.on('crashed', handleMainWindowWebContentsCrashed);
        status.mainWindow.on('maximize', handleMaximizeMainWindow);
        status.mainWindow.on('unmaximize', handleUnmaximizeMainWindow);
        status.mainWindow.on('resize', handleResizeMainWindow);
        status.mainWindow.on('focus', focusBrowserView);
        status.mainWindow.on('enter-full-screen', () => sendToRenderer('enter-full-screen'));
        status.mainWindow.on('leave-full-screen', () => sendToRenderer('leave-full-screen'));

        if (process.env.MM_DEBUG_SETTINGS) {
            status.mainWindow.webContents.openDevTools({mode: 'detach'});
        }

        if (status.viewManager) {
            status.viewManager.updateMainWindow(status.mainWindow);
        }
    }
    initializeViewManager();

    if (deeplinkingURL) {
        status.viewManager.handleDeepLink(deeplinkingURL);
    }
}

export function getMainWindow(ensureCreated) {
    if (ensureCreated && status.mainWindow === null) {
        showMainWindow();
    }
    return status.mainWindow;
}

export function on(event, listener) {
    return status.mainWindow.on(event, listener);
}

function handleMainWindowWebContentsCrashed() {
    throw new Error('webContents \'crashed\' event has been emitted');
}

function handleMaximizeMainWindow() {
    sendToRenderer(MAXIMIZE_CHANGE, true);

    // Workaround as part of https://mattermost.atlassian.net/browse/MM-33577
    // Linux (or GNOME at least) seems to have issues with Electron and getting the size correctly when minimizing/maximizing
    // So we need to manually force the browser view to resize after a small interval to get the size correct
    // Please remove this once this issue has been resolved by Electron
    if (process.platform === 'linux') {
        setTimeout(setBoundsForCurrentView, 10);
    }
}

function handleUnmaximizeMainWindow() {
    sendToRenderer(MAXIMIZE_CHANGE, false);

    // Workaround as part of https://mattermost.atlassian.net/browse/MM-33577
    // Linux (or GNOME at least) seems to have issues with Electron and getting the size correctly when minimizing/maximizing
    // So we need to manually force the browser view to resize after a small interval to get the size correct
    // Please remove this once this issue has been resolved by Electron
    if (process.platform === 'linux') {
        setTimeout(setBoundsForCurrentView, 10);
    }
}

function handleResizeMainWindow(event, newBounds) {
    setBoundsForCurrentView(event, newBounds);
}

function setBoundsForCurrentView(event, newBounds) {
    const currentView = status.viewManager.getCurrentView();
    const bounds = newBounds || status.mainWindow.getContentBounds();
    if (currentView) {
        currentView.setBounds(getAdjustedWindowBoundaries(bounds.width, bounds.height, !urlUtils.isTeamUrl(currentView.server.url, currentView.view.webContents.getURL())));
    }
    status.viewManager.setLoadingScreenBounds();
}

export function sendToRenderer(channel, ...args) {
    if (!status.mainWindow) {
        showMainWindow();
    }
    status.mainWindow.webContents.send(channel, ...args);
    if (status.settingsWindow && status.settingsWindow.isVisible()) {
        status.settingsWindow.webContents.send(channel, ...args);
    }
}

export function sendToAll(channel, ...args) {
    sendToRenderer(channel, ...args);
    if (status.settingsWindow) {
        status.settingsWindow.webContents.send(channel, ...args);
    }

    // TODO: should we include popups?
}

export function sendToMattermostViews(channel, ...args) {
    if (status.viewManager) {
        status.viewManager.sendToAllViews(channel, ...args);
    }
}

export function restoreMain() {
    log.info('restoreMain');
    if (!status.mainWindow) {
        showMainWindow();
    }
    if (!status.mainWindow.isVisible() || status.mainWindow.isMinimized()) {
        if (status.mainWindow.isMinimized()) {
            status.mainWindow.restore();
        } else {
            status.mainWindow.show();
        }
        if (status.settingsWindow) {
            status.settingsWindow.focus();
        } else {
            status.mainWindow.focus();
        }
        if (process.platform === 'darwin') {
            app.dock.show();
        }
    } else if (status.settingsWindow) {
        status.settingsWindow.focus();
    } else {
        status.mainWindow.focus();
    }
}

export function flashFrame(flash) {
    if (process.platform === 'linux' || process.platform === 'win32') {
        status.mainWindow.flashFrame(flash);
        if (status.settingsWindow) {
            // main might be hidden behind the settings
            status.settingsWindow.flashFrame(flash);
        }
    }
    if (process.platform === 'darwin' && status.config.notifications.bounceIcon) {
        app.dock.bounce(status.config.notifications.bounceIconType);
    }
}

function drawBadge(text, small) {
    const scale = 2; // should rely display dpi
    const size = (small ? 20 : 16) * scale;
    const canvas = document.createElement('canvas');
    canvas.setAttribute('width', size);
    canvas.setAttribute('height', size);
    const ctx = canvas.getContext('2d');

    // circle
    ctx.fillStyle = '#FF1744'; // Material Red A400
    ctx.beginPath();
    ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
    ctx.fill();

    // text
    ctx.fillStyle = '#ffffff';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.font = (11 * scale) + 'px sans-serif';
    ctx.fillText(text, size / 2, size / 2, size);

    return canvas.toDataURL();
}

function createDataURL(text, small) {
    const win = status.mainWindow;
    if (!win) {
        return null;
    }

    // since we don't have a document/canvas object in the main process, we use the webcontents from the window to draw.
    const safeSmall = Boolean(small);
    const code = `
    window.drawBadge = ${drawBadge};
    window.drawBadge('${text || ''}', ${safeSmall});
  `;
    return win.webContents.executeJavaScript(code);
}

export async function setOverlayIcon(badgeText, description, small) {
    if (process.platform === 'win32') {
        let overlay = null;
        if (status.mainWindow && badgeText) {
            try {
                const dataUrl = await createDataURL(badgeText, small);
                overlay = nativeImage.createFromDataURL(dataUrl);
            } catch (err) {
                log.error(`Couldn't generate a badge: ${err}`);
            }
        }
        status.mainWindow.setOverlayIcon(overlay, description);
    }
}

export function isMainWindow(window) {
    return status.mainWindow && status.mainWindow === window;
}

export function handleDoubleClick(e, windowType) {
    let action = 'Maximize';
    if (process.platform === 'darwin') {
        action = systemPreferences.getUserDefault('AppleActionOnDoubleClick', 'string');
    }
    const win = (windowType === 'settings') ? status.settingsWindow : status.mainWindow;
    if (!win) {
        return;
    }
    switch (action) {
    case 'Minimize':
        if (win.isMinimized()) {
            win.restore();
        } else {
            win.minimize();
        }
        break;
    case 'Maximize':
    default:
        if (win.isMaximized()) {
            win.unmaximize();
        } else {
            win.maximize();
        }
        break;
    }
}

function initializeViewManager() {
    if (!status.viewManager) {
        status.viewManager = new ViewManager(status.config, status.mainWindow);
        status.viewManager.load();
        status.viewManager.showInitial();
    }
}

export function switchServer(serverName) {
    showMainWindow();
    status.viewManager.showByName(serverName);
}

export function focusBrowserView() {
    if (status.viewManager) {
        status.viewManager.focus();
    } else {
        log.error('Trying to call focus when the viewmanager has not yet been initialized');
    }
}

export function openBrowserViewDevTools() {
    if (status.viewManager) {
        status.viewManager.openViewDevTools();
    }
}

export function focusThreeDotMenu() {
    if (status.mainWindow) {
        status.mainWindow.webContents.focus();
        status.mainWindow.webContents.send(FOCUS_THREE_DOT_MENU);
    }
}

function handleLoadingScreenDataRequest() {
    return {
        darkMode: status.config.darkMode,
    };
}

function handleReactAppInitialized(_, server) {
    if (status.viewManager) {
        status.viewManager.setServerInitialized(server);
    }
}

function handleLoadingScreenAnimationFinished() {
    if (status.viewManager) {
        status.viewManager.hideLoadingScreen();
    }
}

export function updateLoadingScreenDarkMode(darkMode) {
    if (status.viewManager) {
        status.viewManager.updateLoadingScreenDarkMode(darkMode);
    }
}

export function getServerNameByWebContentsId(webContentsId) {
    if (status.viewManager) {
        return status.viewManager.findByWebContent(webContentsId);
    }
    return null;
}

export function close() {
    const focused = BrowserWindow.getFocusedWindow();
    if (focused.id === status.mainWindow.id) {
    // TODO: figure out logic for closing
        focused.close();
    } else {
        focused.close();
    }
}
export function maximize() {
    const focused = BrowserWindow.getFocusedWindow();
    if (focused) {
        focused.maximize();
    }
}
export function minimize() {
    const focused = BrowserWindow.getFocusedWindow();
    if (focused) {
        focused.minimize();
    }
}
export function restore() {
    const focused = BrowserWindow.getFocusedWindow();
    if (focused) {
        focused.restore();
    }
}

export function reload() {
    const currentView = status.viewManager.getCurrentView();
    if (currentView) {
        status.viewManager.showLoadingScreen();
        currentView.reload();
    }
}

export function sendToFind() {
    const currentView = status.viewManager.getCurrentView();
    if (currentView) {
        currentView.view.webContents.sendInputEvent({type: 'keyDown', keyCode: 'F', modifiers: ['CmdOrCtrl', 'Shift']});
    }
}

export function handleHistory(event, offset) {
    if (status.viewManager) {
        const activeView = status.viewManager.getCurrentView();
        if (activeView && activeView.view.webContents.canGoToOffset(offset)) {
            try {
                activeView.view.webContents.goToOffset(offset);
            } catch (error) {
                log.error(error);
                activeView.load(activeView.server.url);
            }
        }
    }
}
<|endoftext|>