<commit_before>/**
 * User controller.
 *
 * @desc This controller is the user controller.
 * @param {!angular.Scope} $scope
 * @constructor
 */
angular.module('app')
    .controller('User', ['$scope', '$interval', '$routeParams', '$location', 'Connection',
        function($scope, $interval, $routeParams, $location, Connection) {

            $scope.page_loading = true;
            $scope.path = $location.path();
            $scope.$emit('sidebar', true);
            $scope.guid = $routeParams.userId;

            /**
             * Establish message handlers
             * @msg - message from websocket to pass on to handler
             */
            Connection.$on('load_page', function(e, msg){ $scope.load_page(msg); });
            Connection.$on('store_contracts', function(e, msg){ $scope.parse_store_listings(msg); });
            Connection.$on('store_contract', function(e, msg){ $scope.parse_store_contract(msg); });
            Connection.$on('page', function(e, msg){ $scope.parse_page(msg); });
            Connection.$on('store_products', function(e, msg){ $scope.parse_store_products(msg); });
            Connection.$on('new_listing', function(e, msg){ $scope.parse_new_listing(msg); });
            Connection.$on('no_listings_found', function(e, msg){ $scope.handle_no_listings(); });
            Connection.$on('reputation_pledge_update', function(e, msg){ $scope.parse_reputation_pledge_update(msg); });

            $scope.load_page = function(msg) {
                console.log($scope.path);

                switch($scope.path) {

                    case "/user/"+$scope.guid+"/products":
                        $scope.queryShop($scope.guid);
                        $scope.storeProductsPanel = true;
                        $scope.showStorePanel('storeProducts');
                        break;
                    case "/user/"+$scope.guid+"/services":
                        $scope.queryShop($scope.guid);
                        $scope.storeServicesPanel = true;
                        $scope.showStorePanel('storeServices');
                        break;
                    default:
                        $scope.queryShop($scope.guid);
                        $scope.showStorePanel('storeInfo');
                }

            };

            $scope.parse_reputation_pledge_update = function(msg) {
                console.log('test', $scope.page);
                $scope.page.reputation_pledge = (msg.value) ? msg.value : 0;
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            /**
             * Query the network for a merchant and then
             * show the page
             * @guid - GUID of page to load
             */
            $scope.queryShop = function(guid) {

                $scope.awaitingShop = guid;
                console.log('Querying for shop: ', guid);

                var query = {
                    'type': 'query_page',
                    'findGUID': guid
                };

                $scope.page = null;
                Connection.send('query_page', query);

            };

            $scope.parse_page = function(msg) {

                $scope.page_loading = null;
                console.log('Received a page for: ', msg);

                msg.senderNick = msg.senderNick.substring(0, 120);
                msg.text = msg.text.substring(0, 2048);

                if (msg.senderGUID != $scope.awaitingShop)
                    return;
                if (!$scope.reviews.hasOwnProperty(msg.pubkey)) {
                    $scope.reviews[msg.pubkey] = [];
                }

                $.each($scope.settings.notaries, function(idx, val) {
                    if (val.guid == msg.senderGUID) {
                       msg.isTrustedNotary = true;
                    }
                });

                if (!$scope.dashboard) {
                    $scope.currentReviews = $scope.reviews[msg.pubkey];
                    $scope.page = msg;
                    $scope.page.reputation_pledge = 0;

                    // Write in store content into the HTML
                    var contentDiv = document.getElementById('page-content');
                    contentDiv.innerHTML = msg.text;

                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                }
            };

            // A listing has shown up from the network
            $scope.store_listings = [];
            $scope.parse_new_listing = function(msg) {
                console.log(msg.data);
                contract_data = msg.data;
                contract_data.key = msg.key;
                contract_data.rawContract = msg.rawContract;
                contract_data.nickname = msg.nickname;
                $scope.store_listings.push(contract_data);
                $scope.store_listings = jQuery.unique($scope.store_listings);
                $.each($scope.store_listings, function(index, contract) {
                    if (jQuery.isEmptyObject(contract.Contract.item_images)) {
                        console.log('empty object');
                        contract.Contract.item_images = "img/no-photo.png";
                    }
                });
                $('#listing-loader').hide();
                console.log('New Listing', $scope.store_listings);
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.no_listings = null;
            $scope.handle_no_listings = function() {
                $('#listing-loader').hide();
                $scope.no_listings = true;
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.compose_message = function(size, myself, address, subject) {
                $scope.$broadcast("compose_message", {
                    size: size,
                    myself: myself,
                    bm_address: address,
                    subject: subject
                });
            };

            $scope.parse_store_contract = function(msg) {

                contract = msg.contract;
                console.log(contract);

                $scope.store_listings.push(contract);

                $scope.store_listings = jQuery.unique($scope.store_listings);
                $.each($scope.store_listings, function(index, contract) {
                    if (jQuery.isEmptyObject(contract.contract_body.Contract.item_images)) {
                        contract.contract_body.Contract.item_images = "img/no-photo.png";
                    }
                });

                $('#listing-loader').hide();
                console.log('New Listing', $scope.store_listings);
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.parse_store_listings = function(msg) {

                contracts = msg.product;

                $scope.store_listings = [];
                $.each(contracts, function(key, value) {
                    console.log('value', value);
                    $scope.store_listings.push(value.contract_body);
                });

                //$scope.store_listings = jQuery.unique($scope.store_listings);
                $.each($scope.store_listings, function(index, contract) {
                    if (jQuery.isEmptyObject(contract.Contract.item_images)) {
                        contract.Contract.item_images = "img/no-photo.png";
                    }
                });

                $('#listing-loader').hide();
                console.log('New Listing', $scope.store_listings);
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.store_products = {};
            $scope.parse_store_products = function(msg) {

                console.log(msg);
                $scope.store_products = msg.products;

                if (!$scope.$$phase) {
                    $scope.$apply();
                }
                // $scope.store_products.forEach(function(product) {
                //   console.log(product);
                //
                // })

            };
            $scope.parse_listing_results = function(msg) {
                $scope.store_products = msg.contracts;
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            function resetStorePanels() {
                $scope.storeInfoPanel = false;
                $scope.storeProductsPanel = false;
                $scope.storeReviewsPanel = false;
                $scope.storeOrderHistoryPanel = false;
                $scope.storeServicesPanel = false;
            }

            $scope.showStorePanel = function(panelName) {

                resetStorePanels();
                $scope.dashboard = false;

                switch (panelName) {
                    case 'storeInfo':
                        $scope.storeInfoPanel = true;
                        break;
                    case 'storeProducts':
                        $('#listing-loader').show();
                        $scope.store_listings = [];
                        $scope.queryStoreProducts($scope.guid);
                        $scope.getNotaries();
                        break;
                    case 'storeOrders':
                        //$scope.storeOrdersPanel = true;
                        break;
                    case 'storeReviews':
                        $scope.storeReviewsPanel = true;
                        break;
                    case 'storeServices':
                        $scope.storeServicesPanel = true;
                        break;

                }
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            // Query for product listings from this store
            $scope.queryStoreProducts = function(storeID) {

                console.log('Querying for contracts in store: ' + storeID);
                $scope.storeProductsPanel = true;
                var query = {
                    'type': 'query_store_products',
                    'key': storeID
                };
                Connection.send('query_store_products', query);

            };

            $scope.addNotary = function(guid, nickname) {

                //if(notaryGUID.length != 40 || !notaryGUID.match(/^[0-9a-z]+$/)) {
                //    alert('Incorrect format for GUID');
                //    return;
                //}
                $scope.page.isTrustedNotary = true;

                Connection.send('add_trusted_notary', { 'type': 'add_trusted_notary',
                    'guid': guid,
                    'nickname': nickname
                    }
                );

                Notifier.success('Success', 'Notary added successfully.');

                if (!$scope.$$phase) {
                    $scope.$apply();
                }

            };

            $scope.BuyItemCtrl = function($scope, $modal, $log) {

                $scope.open = function(size, myself, merchantPubkey, listing,
                    notaries, arbiters, btc_pubkey) {

                    // Send socket a request for order info
                    //Connection.send('query_order', { orderId: orderId } )

                    notaries = $scope.settings.notaries;

                    modalInstance = $modal.open({
                        templateUrl: 'partials/modal/buyItem.html',
                        controller: $scope.BuyItemInstanceCtrl,
                        resolve: {
                            merchantPubkey: function() {
                                return merchantPubkey;
                            },
                            myself: function() {
                                return myself;
                            },
                            btc_pubkey: function() {
                                return btc_pubkey;
                            },
                            notaries: function() {
                                return notaries;
                            },
                            arbiters: function() {
                                return arbiter;
                            },
                            listing: function() {
                                return listing;
                            },
                            scope: function() {
                                return $scope;
                            }
                        },
                        size: size
                    });

                    modalInstance.result.then(function() {

                        $scope.showDashboardPanel('orders_purchases');

                        $('#pill-orders').addClass('active').siblings().removeClass('active').blur();
                        $("#orderSuccessAlert").alert();
                        window.setTimeout(function() {
                            $("#orderSuccessAlert").alert('close');
                        }, 5000);

                        if (!$scope.$$phase) {
                            $scope.$apply();
                        }

                    }, function() {
                        $log.info('Modal dismissed at: ' + new Date());

                    });
                };
            };

            $scope.BuyItemInstanceCtrl = function($scope, $modalInstance, myself, merchantPubkey, listing,
                notaries,
                arbiters,
                btc_pubkey,
                scope) {

                $scope.myself = myself;
                $scope.merchantPubkey = merchantPubkey;
                $scope.productTitle = listing.contract_body.Contract.item_title;
                $scope.productPrice = (listing.contract_body.Contract.item_price !== "") ? +listing.contract_body.Contract.item_price : 0;
                $scope.productDescription = listing.contract_body.Contract.item_desc;
                $scope.productImageData = listing.contract_body.Contract.item_images;
                $scope.shippingPrice = (listing.contract_body.Contract.item_delivery.hasOwnProperty('shipping_price')) ? listing.contract_body.Contract.item_delivery.shipping_price : 0;
                $scope.totalPrice = +(parseFloat($scope.productPrice) + parseFloat($scope.shippingPrice)).toPrecision(8);
                $scope.productQuantity = 1;
                $scope.rawContract = listing.signed_contract_body;
                $scope.guid = listing.contract_body.Seller.seller_GUID;
                $scope.arbiters = arbiters;

                $scope.notaries = notaries;

                $scope.key = listing.key;

                $scope.update = function(user) {
                    console.log('Updated');
                };

                $scope.ok = function() {
                    $modalInstance.close();
                };

                $scope.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };

                $scope.updateTotal = function() {
                    var newPrice = $('#itemQuantity').val() * $scope.productPrice;
                    newPrice = Math.round(newPrice * 100000) / 100000;
                    $('#totalPrice').html(+(parseFloat(newPrice) + parseFloat($scope.shippingPrice)).toPrecision(8));
                };

                $scope.gotoStep2 = function() {
                    $scope.order.step2 = 1;
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                };

                $scope.gotoStep1 = function() {
                    $scope.order.step2 = '';
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                };

                $scope.order = {
                    message: '',
                    tx: '',
                    listingKey: listing.key,
                    listingTotal: '',
                    productTotal: '',
                    productQuantity: 1,
                    rawContract: listing.signed_contract_body,
                    btc_pubkey: btc_pubkey
                };
                $scope.order.notary = ($scope.notaries.length > 0) ? $scope.notaries[0].guid : "";
                $scope.order.arbiter = $scope.arbiters[0];

                $scope.submitOrder = function() {

                    $scope.creatingOrder = false;
                    $scope.order.step2 = '';
                    $scope.order.step1 = '';
                    $scope.order.confirmation = true;

                    var newOrder = {
                        'message': $scope.order.message,
                        'state': 'new',
                        'buyer': $scope.myself.pubkey,
                        'seller': $scope.merchantPubkey,
                        'sellerGUID': $scope.guid,
                        'listingKey': $scope.key,
                        'orderTotal': $('#totalPrice').html(),
                        'rawContract': $scope.rawContract,
                        'notary': $scope.order.notary,
                        'btc_pubkey': $scope.order.btc_pubkey,
                        'arbiter': $scope.order.arbiter
                    };
                    console.log(newOrder);
                    Connection.send('order', newOrder);
                    $scope.sentOrder = true;

                };

                $scope.closeConfirmation = function() {
                    $modalInstance.close();
                    window.location = '#/orders/purchases';
                };

            };

            if (Connection.websocket.readyState == 1) {
                $scope.load_page({});
            }

        }
    ]);
<commit_msg>Another one.<commit_after>/**
 * User controller.
 *
 * @desc This controller is the user controller.
 * @param {!angular.Scope} $scope
 * @constructor
 */
angular.module('app')
    .controller('User', ['$scope', '$interval', '$routeParams', '$location', 'Connection',
        function($scope, $interval, $routeParams, $location, Connection) {

            $scope.page_loading = true;
            $scope.path = $location.path();
            $scope.$emit('sidebar', true);
            $scope.guid = $routeParams.userId;

            /**
             * Establish message handlers
             * @msg - message from websocket to pass on to handler
             */
            Connection.$on('load_page', function(e, msg){ $scope.load_page(msg); });
            Connection.$on('store_contracts', function(e, msg){ $scope.parse_store_listings(msg); });
            Connection.$on('store_contract', function(e, msg){ $scope.parse_store_contract(msg); });
            Connection.$on('page', function(e, msg){ $scope.parse_page(msg); });
            Connection.$on('store_products', function(e, msg){ $scope.parse_store_products(msg); });
            Connection.$on('new_listing', function(e, msg){ $scope.parse_new_listing(msg); });
            Connection.$on('no_listings_found', function(e, msg){ $scope.handle_no_listings(); });
            Connection.$on('reputation_pledge_update', function(e, msg){ $scope.parse_reputation_pledge_update(msg); });

            $scope.load_page = function(msg) {
                console.log($scope.path);

                switch($scope.path) {

                    case "/user/"+$scope.guid+"/products":
                        $scope.queryShop($scope.guid);
                        $scope.storeProductsPanel = true;
                        $scope.showStorePanel('storeProducts');
                        break;
                    case "/user/"+$scope.guid+"/services":
                        $scope.queryShop($scope.guid);
                        $scope.storeServicesPanel = true;
                        $scope.showStorePanel('storeServices');
                        break;
                    default:
                        $scope.queryShop($scope.guid);
                        $scope.showStorePanel('storeInfo');
                }

            };

            $scope.parse_reputation_pledge_update = function(msg) {
                console.log('test', $scope.page);
                $scope.page.reputation_pledge = (msg.value) ? msg.value : 0;
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            /**
             * Query the network for a merchant and then
             * show the page
             * @guid - GUID of page to load
             */
            $scope.queryShop = function(guid) {

                $scope.awaitingShop = guid;
                console.log('Querying for shop: ', guid);

                var query = {
                    'type': 'query_page',
                    'findGUID': guid
                };

                $scope.page = null;
                Connection.send('query_page', query);

            };

            $scope.parse_page = function(msg) {

                $scope.page_loading = null;
                console.log('Received a page for: ', msg);

                msg.senderNick = msg.senderNick.substring(0, 120);
                msg.text = msg.text.substring(0, 2048);

                if (msg.senderGUID != $scope.awaitingShop)
                    return;
                if (!$scope.reviews.hasOwnProperty(msg.pubkey)) {
                    $scope.reviews[msg.pubkey] = [];
                }

                $.each($scope.settings.notaries, function(idx, val) {
                    if (val.guid == msg.senderGUID) {
                       msg.isTrustedNotary = true;
                    }
                });

                if (!$scope.dashboard) {
                    $scope.currentReviews = $scope.reviews[msg.pubkey];
                    $scope.page = msg;
                    $scope.page.reputation_pledge = 0;

                    // Write in store content into the HTML
                    var contentDiv = document.getElementById('page-content');
                    contentDiv.innerHTML = msg.text;

                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                }
            };

            // A listing has shown up from the network
            $scope.store_listings = [];
            $scope.parse_new_listing = function(msg) {
                console.log(msg.data);
                contract_data = msg.data;
                contract_data.key = msg.key;
                contract_data.rawContract = msg.rawContract;
                contract_data.nickname = msg.nickname;
                $scope.store_listings.push(contract_data);
                $scope.store_listings = jQuery.unique($scope.store_listings);
                $.each($scope.store_listings, function(index, contract) {
                    if (jQuery.isEmptyObject(contract.Contract.item_images)) {
                        console.log('empty object');
                        contract.Contract.item_images = "img/no-photo.png";
                    }
                });
                $('#listing-loader').hide();
                console.log('New Listing', $scope.store_listings);
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.no_listings = null;
            $scope.handle_no_listings = function() {
                $('#listing-loader').hide();
                $scope.no_listings = true;
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.compose_message = function(size, myself, address, subject) {
                $scope.$broadcast("compose_message", {
                    size: size,
                    myself: myself,
                    bm_address: address,
                    subject: subject
                });
            };

            $scope.parse_store_contract = function(msg) {

                contract = msg.contract;
                console.log(contract);

                $scope.store_listings.push(contract);

                $scope.store_listings = jQuery.unique($scope.store_listings);
                $.each($scope.store_listings, function(index, contract) {
                    if (jQuery.isEmptyObject(contract.contract_body.Contract.item_images)) {
                        contract.contract_body.Contract.item_images = "img/no-photo.png";
                    }
                });

                $('#listing-loader').hide();
                console.log('New Listing', $scope.store_listings);
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.parse_store_listings = function(msg) {

                contracts = msg.product;

                $scope.store_listings = [];
                $.each(contracts, function(key, value) {
                    console.log('value', value);
                    $scope.store_listings.push(value.contract_body);
                });

                //$scope.store_listings = jQuery.unique($scope.store_listings);
                $.each($scope.store_listings, function(index, contract) {
                    if (jQuery.isEmptyObject(contract.Contract.item_images)) {
                        contract.Contract.item_images = "img/no-photo.png";
                    }
                });

                $('#listing-loader').hide();
                console.log('New Listing', $scope.store_listings);
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            $scope.store_products = {};
            $scope.parse_store_products = function(msg) {

                console.log(msg);
                $scope.store_products = msg.products;

                if (!$scope.$$phase) {
                    $scope.$apply();
                }
                // $scope.store_products.forEach(function(product) {
                //   console.log(product);
                //
                // })

            };
            $scope.parse_listing_results = function(msg) {
                $scope.store_products = msg.contracts;
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            function resetStorePanels() {
                $scope.storeInfoPanel = false;
                $scope.storeProductsPanel = false;
                $scope.storeReviewsPanel = false;
                $scope.storeOrderHistoryPanel = false;
                $scope.storeServicesPanel = false;
            }

            $scope.showStorePanel = function(panelName) {

                resetStorePanels();
                $scope.dashboard = false;

                switch (panelName) {
                    case 'storeInfo':
                        $scope.storeInfoPanel = true;
                        break;
                    case 'storeProducts':
                        $('#listing-loader').show();
                        $scope.store_listings = [];
                        $scope.queryStoreProducts($scope.guid);
                        $scope.getNotaries();
                        break;
                    case 'storeOrders':
                        //$scope.storeOrdersPanel = true;
                        break;
                    case 'storeReviews':
                        $scope.storeReviewsPanel = true;
                        break;
                    case 'storeServices':
                        $scope.storeServicesPanel = true;
                        break;

                }
                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            // Query for product listings from this store
            $scope.queryStoreProducts = function(storeID) {

                console.log('Querying for contracts in store: ' + storeID);
                $scope.storeProductsPanel = true;
                var query = {
                    'type': 'query_store_products',
                    'key': storeID
                };
                Connection.send('query_store_products', query);

            };

            $scope.addNotary = function(guid, nickname) {

                //if(notaryGUID.length != 40 || !notaryGUID.match(/^[0-9a-z]+$/)) {
                //    alert('Incorrect format for GUID');
                //    return;
                //}
                $scope.page.isTrustedNotary = true;

                Connection.send('add_trusted_notary', { 'type': 'add_trusted_notary',
                    'guid': guid,
                    'nickname': nickname
                    }
                );

                Notifier.success('Success', 'Notary added successfully.');

                if (!$scope.$$phase) {
                    $scope.$apply();
                }

            };

            $scope.BuyItemCtrl = function($scope, $modal, $log) {

                $scope.open = function(size, myself, merchantPubkey, listing,
                    notaries, arbiters, btc_pubkey) {

                    // Send socket a request for order info
                    //Connection.send('query_order', { orderId: orderId } )

                    notaries = $scope.settings.notaries;

                    modalInstance = $modal.open({
                        templateUrl: 'partials/modal/buyItem.html',
                        controller: $scope.BuyItemInstanceCtrl,
                        resolve: {
                            merchantPubkey: function() {
                                return merchantPubkey;
                            },
                            myself: function() {
                                return myself;
                            },
                            btc_pubkey: function() {
                                return btc_pubkey;
                            },
                            notaries: function() {
                                return notaries;
                            },
                            arbiters: function() {
                                return arbiters;
                            },
                            listing: function() {
                                return listing;
                            },
                            scope: function() {
                                return $scope;
                            }
                        },
                        size: size
                    });

                    modalInstance.result.then(function() {

                        $scope.showDashboardPanel('orders_purchases');

                        $('#pill-orders').addClass('active').siblings().removeClass('active').blur();
                        $("#orderSuccessAlert").alert();
                        window.setTimeout(function() {
                            $("#orderSuccessAlert").alert('close');
                        }, 5000);

                        if (!$scope.$$phase) {
                            $scope.$apply();
                        }

                    }, function() {
                        $log.info('Modal dismissed at: ' + new Date());

                    });
                };
            };

            $scope.BuyItemInstanceCtrl = function($scope, $modalInstance, myself, merchantPubkey, listing,
                notaries,
                arbiters,
                btc_pubkey,
                scope) {

                $scope.myself = myself;
                $scope.merchantPubkey = merchantPubkey;
                $scope.productTitle = listing.contract_body.Contract.item_title;
                $scope.productPrice = (listing.contract_body.Contract.item_price !== "") ? +listing.contract_body.Contract.item_price : 0;
                $scope.productDescription = listing.contract_body.Contract.item_desc;
                $scope.productImageData = listing.contract_body.Contract.item_images;
                $scope.shippingPrice = (listing.contract_body.Contract.item_delivery.hasOwnProperty('shipping_price')) ? listing.contract_body.Contract.item_delivery.shipping_price : 0;
                $scope.totalPrice = +(parseFloat($scope.productPrice) + parseFloat($scope.shippingPrice)).toPrecision(8);
                $scope.productQuantity = 1;
                $scope.rawContract = listing.signed_contract_body;
                $scope.guid = listing.contract_body.Seller.seller_GUID;
                $scope.arbiters = arbiters;

                $scope.notaries = notaries;

                $scope.key = listing.key;

                $scope.update = function(user) {
                    console.log('Updated');
                };

                $scope.ok = function() {
                    $modalInstance.close();
                };

                $scope.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };

                $scope.updateTotal = function() {
                    var newPrice = $('#itemQuantity').val() * $scope.productPrice;
                    newPrice = Math.round(newPrice * 100000) / 100000;
                    $('#totalPrice').html(+(parseFloat(newPrice) + parseFloat($scope.shippingPrice)).toPrecision(8));
                };

                $scope.gotoStep2 = function() {
                    $scope.order.step2 = 1;
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                };

                $scope.gotoStep1 = function() {
                    $scope.order.step2 = '';
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                };

                $scope.order = {
                    message: '',
                    tx: '',
                    listingKey: listing.key,
                    listingTotal: '',
                    productTotal: '',
                    productQuantity: 1,
                    rawContract: listing.signed_contract_body,
                    btc_pubkey: btc_pubkey
                };
                $scope.order.notary = ($scope.notaries.length > 0) ? $scope.notaries[0].guid : "";
                $scope.order.arbiter = $scope.arbiters[0];

                $scope.submitOrder = function() {

                    $scope.creatingOrder = false;
                    $scope.order.step2 = '';
                    $scope.order.step1 = '';
                    $scope.order.confirmation = true;

                    var newOrder = {
                        'message': $scope.order.message,
                        'state': 'new',
                        'buyer': $scope.myself.pubkey,
                        'seller': $scope.merchantPubkey,
                        'sellerGUID': $scope.guid,
                        'listingKey': $scope.key,
                        'orderTotal': $('#totalPrice').html(),
                        'rawContract': $scope.rawContract,
                        'notary': $scope.order.notary,
                        'btc_pubkey': $scope.order.btc_pubkey,
                        'arbiter': $scope.order.arbiter
                    };
                    console.log(newOrder);
                    Connection.send('order', newOrder);
                    $scope.sentOrder = true;

                };

                $scope.closeConfirmation = function() {
                    $modalInstance.close();
                    window.location = '#/orders/purchases';
                };

            };

            if (Connection.websocket.readyState == 1) {
                $scope.load_page({});
            }

        }
    ]);
<|endoftext|>


<commit_before>Package.describe({
  git: 'https://github.com/zimme/meteor-collection-softremovable',
  name: 'zimme:collection-softremovable',
  summary: 'Add soft remove to collections',
  version: '1.0.0'
});

Package.onUse(function(api) {
  api.versionsFrom('1.0');

  api.use([
    'coffeescript',
    'underscore'
  ]);

  api.use([
    'matb33:collection-hooks@0.7.6',
    'zimme:collection-behaviours@1.0.0'
  ]);

  api.use([
    'aldeed:autoform@4.0.0',
    'aldeed:collection2@2.0.0',
    'aldeed:simple-schema@1.0.3'
  ], ['client', 'server'], {weak: true});

  api.addFiles('softremovable.coffee');
});
<commit_msg>Version bump<commit_after>Package.describe({
  git: 'https://github.com/zimme/meteor-collection-softremovable',
  name: 'zimme:collection-softremovable',
  summary: 'Add soft remove to collections',
  version: '1.0.1'
});

Package.onUse(function(api) {
  api.versionsFrom('1.0');

  api.use([
    'coffeescript',
    'underscore'
  ]);

  api.use([
    'matb33:collection-hooks@0.7.6',
    'zimme:collection-behaviours@1.0.0'
  ]);

  api.use([
    'aldeed:autoform@4.0.0',
    'aldeed:collection2@2.0.0',
    'aldeed:simple-schema@1.0.3'
  ], ['client', 'server'], {weak: true});

  api.addFiles('softremovable.coffee');
});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import {
  Dimensions,
  ScrollView,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

import Day from './Day';

import moment from 'moment';
import styles from './styles';

const DEVICE_WIDTH = Dimensions.get('window').width;
const VIEW_INDEX = 2;

function prepareEventDates(eventDates) {
  const res = {};
  for (const _date of eventDates) {
    const date = moment(_date);
    const month = moment(date).startOf('month').format();
    if (!res[month]) {
      res[month] = {};
    }
    res[month][date.date() - 1] = true;
  }
  return res;
}

export default class Calendar extends Component {

  state = {
    selectedMoment: moment(this.props.selectedDate),
    currentMonthMoment: moment(this.props.startDate),
  };

  static defaultProps = {
    scrollEnabled: false,
    showControls: false,
    prevButtonText: 'Prev',
    nextButtonText: 'Next',
    titleFormat: 'MMMM YYYY',
    dayHeadings: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    monthNames: ['January', 'February', 'March', 'April', 'May', 'June',
      'July', 'August', 'September', 'October', 'November', 'December'],
    startDate: moment().format('YYYY-MM-DD'),
    eventDates: [],
    customStyle: {},
    weekStart: 1,
    today: moment(),
  };

  static propTypes = {
    onDateSelect: PropTypes.func,
    scrollEnabled: PropTypes.bool,
    showControls: PropTypes.bool,
    prevButtonText: PropTypes.string,
    nextButtonText: PropTypes.string,
    titleFormat: PropTypes.string,
    onSwipeNext: PropTypes.func,
    onSwipePrev: PropTypes.func,
    onTouchNext: PropTypes.func,
    onTouchPrev: PropTypes.func,
    // all Date types can be anything that moment.js can parse to a proper moment.
    // Most common cases are: Date object, date string, Moment object.
    startDate: PropTypes.any,
    selectedDate: PropTypes.any,
    // defaults to, well, today. The moment of rendering.
    today: PropTypes.any,
    eventDates: PropTypes.array, // array of anythng date-like, see comment above
    customStyle: PropTypes.object,
    // 0 - Sunday, 1 - Monday, 2 - Tuesday, etc (typically 0 or 1)
    weekStart: PropTypes.number,
    // array of weekday labels, starting with Sunday
    dayHeadings: PropTypes.array,
    // array of 12 month names, defaults to English
    monthNames: PropTypes.array,
  };

  componentDidMount() {
    this.scrollToItem(VIEW_INDEX);
  }

  componentDidUpdate() {
    this.scrollToItem(VIEW_INDEX);
  }

  getMonthStack(currentMonth) {
    if (this.props.scrollEnabled) {
      const res = [];
      for (let i = -VIEW_INDEX; i <= VIEW_INDEX; i++) {
        res.push(moment(currentMonth).add(i, 'month'));
      }
      return res;
    }
    return [moment(currentMonth)];
  }

  selectDate(date) {
    this.setState({
      selectedMoment: date,
    });
    this.props.onDateSelect && this.props.onDateSelect(date.format()); // eslint-disable-line no-unused-expressions, max-len
  }

  onPrev() {
    const newMoment = moment(this.state.currentMonthMoment).subtract(1, 'month');
    this.setState({ currentMonthMoment: newMoment });
    this.props.onTouchPrev && this.props.onTouchPrev(newMoment); // eslint-disable-line no-unused-expressions, max-len
  }

  onNext() {
    const newMoment = moment(this.state.currentMonthMoment).add(1, 'month');
    this.setState({ currentMonthMoment: newMoment });
    this.props.onTouchNext && this.props.onTouchNext(newMoment); // eslint-disable-line no-unused-expressions, max-len
  }

  scrollToItem(itemIndex) {
    const scrollToX = itemIndex * DEVICE_WIDTH;
    if (this.props.scrollEnabled) {
      this._calendar.scrollTo({ y: 0, x: scrollToX, animated: false });
    }
  }

  scrollEnded(event) {
    const position = event.nativeEvent.contentOffset.x;
    const currentPage = position / DEVICE_WIDTH;
    const newMoment = moment(this.state.currentMonthMoment).add(currentPage - VIEW_INDEX, 'month');
    this.setState({ currentMonthMoment: newMoment });

    if (currentPage < VIEW_INDEX) {
      this.props.onSwipePrev && this.props.onSwipePrev();
    } else if (currentPage > VIEW_INDEX) {
      this.props.onSwipeNext && this.props.onSwipeNext();
    }
  }

  renderMonthView(argMoment, eventDatesMap) {
    /*
      In the code bellow. several moments and datatypes are mentioned. To avoid confusion,
      here is the naming convention I used:

      Moments:
        arg - (any) date in a month we want to render
        today - day rendered as today. typically the moment of rendering
        selected moment

      Data types:
        moment - moment.js object
        index - 0, 1, 2, .. :) Typically index of day within a given month
    */

    let // eslint-disable-line one-var
      renderIndex = 0,
      weekRows = [],
      days = [],
      startOfArgMonthMoment = argMoment.startOf('month');

    const // eslint-disable-line one-var
      selectedMoment = moment(this.state.selectedMoment),
      weekStart = this.props.weekStart,
      todayMoment = moment(this.props.today),
      todayIndex = todayMoment.date() - 1,
      argMonthDaysCount = argMoment.daysInMonth(),
      offset = (startOfArgMonthMoment.isoWeekday() - weekStart + 7) % 7,
      argMonthIsToday = argMoment.isSame(todayMoment, 'month'),
      selectedIndex = moment(selectedMoment).date() - 1,
      selectedMonthIsArg = selectedMoment.isSame(argMoment, 'month');

    const events = (eventDatesMap !== null)
      ? eventDatesMap[argMoment.startOf('month').format()]
      : null;

    // let before = (new Date()).getTime()

    for (;;) {
      const dayIndex = renderIndex - offset;
      const isoWeekday = (renderIndex + weekStart) % 7;

      if (dayIndex >= 0 && dayIndex < argMonthDaysCount) {
        days.push((
          <Day
            startOfMonth={startOfArgMonthMoment}
            isWeekend={isoWeekday === 0 || isoWeekday === 6}
            key={`${renderIndex}`}
            onPress={() => {
              this.selectDate(moment(startOfArgMonthMoment).set('date', dayIndex + 1));
            }}
            caption={`${dayIndex + 1}`}
            isToday={argMonthIsToday && (dayIndex === todayIndex)}
            isSelected={selectedMonthIsArg && (dayIndex === selectedIndex)}
            hasEvent={events && events[dayIndex] === true}
            usingEvents={this.props.eventDates.length > 0}
            customStyle={this.props.customStyle}
          />
        ));
      } else {
        days.push(<Day key={`${renderIndex}`} filler />);
      }
      if (renderIndex % 7 === 6) {
        weekRows.push(
          <View
            key={weekRows.length}
            style={[styles.weekRow, this.props.customStyle.weekRow]}
          >
              {days}
          </View>);
        days = [];
        if (dayIndex + 1 >= argMonthDaysCount) {
          break;
        }
      }
      renderIndex += 1;
    }

    // let after = (new Date()).getTime()
    // console.log('--- render time ---', after - before)
    return <View key={argMoment.month()} style={styles.monthContainer}>{weekRows}</View>;
  }

  renderHeading() {
    const headings = [];
    for (let i = 0; i < 7; i++) {
      const j = (i + this.props.weekStart) % 7;
      headings.push(
        <Text
          key={i}
          style={j === 0 || j === 6 ?
            [styles.weekendHeading, this.props.customStyle.weekendHeading] :
            [styles.dayHeading, this.props.customStyle.dayHeading]}
        >
          {this.props.dayHeadings[j]}
        </Text>
      );
    }

    return (
      <View style={[styles.calendarHeading, this.props.customStyle.calendarHeading]}>
        {headings}
      </View>
    );
  }

  renderTopBar() {
    let localizedMonth = this.props.monthNames[this.state.currentMonthMoment.month()];
    return this.props.showControls
    ? (
        <View style={[styles.calendarControls, this.props.customStyle.calendarControls]}>
          <TouchableOpacity
            style={[styles.controlButton, this.props.customStyle.controlButton]}
            onPress={this.onPrev}
          >
            <Text style={[styles.controlButtonText, this.props.customStyle.controlButtonText]}>
              {this.props.prevButtonText}
            </Text>
          </TouchableOpacity>
          <Text style={[styles.title, this.props.customStyle.title]}>
            {localizedMonth} {this.state.currentMonthMoment.year()}
          </Text>
          <TouchableOpacity
            style={[styles.controlButton, this.props.customStyle.controlButton]}
            onPress={this.onNext}
          >
            <Text style={[styles.controlButtonText, this.props.customStyle.controlButtonText]}>
              {this.props.nextButtonText}
            </Text>
          </TouchableOpacity>
        </View>
      )
    : (
      <View style={[styles.calendarControls, this.props.customStyle.calendarControls]}>
        <Text style={[styles.title, this.props.customStyle.title]}>
          {this.state.currentMonthMoment.format(this.props.titleFormat)}
        </Text>
      </View>
    );
  }

  render() {
    console.log('Rendering')
    const calendarDates = this.getMonthStack(this.state.currentMonthMoment);
    const eventDatesMap = prepareEventDates(this.props.eventDates);
    return (
      <View style={[styles.calendarContainer, this.props.customStyle.calendarContainer]}>
        {this.renderTopBar()}
        {this.renderHeading(this.props.titleFormat)}
        {this.props.scrollEnabled ?
          <ScrollView
            ref={calendar => this._calendar = calendar}
            horizontal
            scrollEnabled
            pagingEnabled
            removeClippedSubviews
            scrollEventThrottle={1000}
            showsHorizontalScrollIndicator={false}
            automaticallyAdjustContentInsets
            onMomentumScrollEnd={(event) => this.scrollEnded(event)}
          >
            {calendarDates.map((date) => this.renderMonthView(moment(date), eventDatesMap))}
          </ScrollView>
          :
          <View ref={calendar => this._calendar = calendar}>
            {calendarDates.map((date) => this.renderMonthView(moment(date), eventDatesMap))}
          </View>
        }
      </View>
    );
  }
}
<commit_msg>[Calendar] Add class binding where necessary<commit_after>import React, { Component, PropTypes } from 'react';
import {
  Dimensions,
  ScrollView,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

import Day from './Day';

import moment from 'moment';
import styles from './styles';

const DEVICE_WIDTH = Dimensions.get('window').width;
const VIEW_INDEX = 2;

function prepareEventDates(eventDates) {
  const res = {};
  for (const _date of eventDates) {
    const date = moment(_date);
    const month = moment(date).startOf('month').format();
    if (!res[month]) {
      res[month] = {};
    }
    res[month][date.date() - 1] = true;
  }
  return res;
}

export default class Calendar extends Component {

  state = {
    selectedMoment: moment(this.props.selectedDate),
    currentMonthMoment: moment(this.props.startDate),
  };

  static defaultProps = {
    scrollEnabled: false,
    showControls: false,
    prevButtonText: 'Prev',
    nextButtonText: 'Next',
    titleFormat: 'MMMM YYYY',
    dayHeadings: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
    monthNames: ['January', 'February', 'March', 'April', 'May', 'June',
      'July', 'August', 'September', 'October', 'November', 'December'],
    startDate: moment().format('YYYY-MM-DD'),
    eventDates: [],
    customStyle: {},
    weekStart: 1,
    today: moment(),
  };

  static propTypes = {
    onDateSelect: PropTypes.func,
    scrollEnabled: PropTypes.bool,
    showControls: PropTypes.bool,
    prevButtonText: PropTypes.string,
    nextButtonText: PropTypes.string,
    titleFormat: PropTypes.string,
    onSwipeNext: PropTypes.func,
    onSwipePrev: PropTypes.func,
    onTouchNext: PropTypes.func,
    onTouchPrev: PropTypes.func,
    // all Date types can be anything that moment.js can parse to a proper moment.
    // Most common cases are: Date object, date string, Moment object.
    startDate: PropTypes.any,
    selectedDate: PropTypes.any,
    // defaults to, well, today. The moment of rendering.
    today: PropTypes.any,
    eventDates: PropTypes.array, // array of anythng date-like, see comment above
    customStyle: PropTypes.object,
    // 0 - Sunday, 1 - Monday, 2 - Tuesday, etc (typically 0 or 1)
    weekStart: PropTypes.number,
    // array of weekday labels, starting with Sunday
    dayHeadings: PropTypes.array,
    // array of 12 month names, defaults to English
    monthNames: PropTypes.array,
  };

  componentDidMount() {
    this.scrollToItem(VIEW_INDEX);
  }

  componentDidUpdate() {
    this.scrollToItem(VIEW_INDEX);
  }

  getMonthStack(currentMonth) {
    if (this.props.scrollEnabled) {
      const res = [];
      for (let i = -VIEW_INDEX; i <= VIEW_INDEX; i++) {
        res.push(moment(currentMonth).add(i, 'month'));
      }
      return res;
    }
    return [moment(currentMonth)];
  }

  selectDate(date) {
    this.setState({
      selectedMoment: date,
    });
    this.props.onDateSelect && this.props.onDateSelect(date.format()); // eslint-disable-line no-unused-expressions, max-len
  }

  onPrev = () => {
    const newMoment = moment(this.state.currentMonthMoment).subtract(1, 'month');
    this.setState({ currentMonthMoment: newMoment });
    this.props.onTouchPrev && this.props.onTouchPrev(newMoment); // eslint-disable-line no-unused-expressions, max-len
  }

  onNext = () => {
    const newMoment = moment(this.state.currentMonthMoment).add(1, 'month');
    this.setState({ currentMonthMoment: newMoment });
    this.props.onTouchNext && this.props.onTouchNext(newMoment); // eslint-disable-line no-unused-expressions, max-len
  }

  scrollToItem(itemIndex) {
    const scrollToX = itemIndex * DEVICE_WIDTH;
    if (this.props.scrollEnabled) {
      this._calendar.scrollTo({ y: 0, x: scrollToX, animated: false });
    }
  }

  scrollEnded(event) {
    const position = event.nativeEvent.contentOffset.x;
    const currentPage = position / DEVICE_WIDTH;
    const newMoment = moment(this.state.currentMonthMoment).add(currentPage - VIEW_INDEX, 'month');
    this.setState({ currentMonthMoment: newMoment });

    if (currentPage < VIEW_INDEX) {
      this.props.onSwipePrev && this.props.onSwipePrev();
    } else if (currentPage > VIEW_INDEX) {
      this.props.onSwipeNext && this.props.onSwipeNext();
    }
  }

  renderMonthView(argMoment, eventDatesMap) {
    /*
      In the code bellow. several moments and datatypes are mentioned. To avoid confusion,
      here is the naming convention I used:

      Moments:
        arg - (any) date in a month we want to render
        today - day rendered as today. typically the moment of rendering
        selected moment

      Data types:
        moment - moment.js object
        index - 0, 1, 2, .. :) Typically index of day within a given month
    */

    let // eslint-disable-line one-var
      renderIndex = 0,
      weekRows = [],
      days = [],
      startOfArgMonthMoment = argMoment.startOf('month');

    const // eslint-disable-line one-var
      selectedMoment = moment(this.state.selectedMoment),
      weekStart = this.props.weekStart,
      todayMoment = moment(this.props.today),
      todayIndex = todayMoment.date() - 1,
      argMonthDaysCount = argMoment.daysInMonth(),
      offset = (startOfArgMonthMoment.isoWeekday() - weekStart + 7) % 7,
      argMonthIsToday = argMoment.isSame(todayMoment, 'month'),
      selectedIndex = moment(selectedMoment).date() - 1,
      selectedMonthIsArg = selectedMoment.isSame(argMoment, 'month');

    const events = (eventDatesMap !== null)
      ? eventDatesMap[argMoment.startOf('month').format()]
      : null;

    // let before = (new Date()).getTime()

    for (;;) {
      const dayIndex = renderIndex - offset;
      const isoWeekday = (renderIndex + weekStart) % 7;

      if (dayIndex >= 0 && dayIndex < argMonthDaysCount) {
        days.push((
          <Day
            startOfMonth={startOfArgMonthMoment}
            isWeekend={isoWeekday === 0 || isoWeekday === 6}
            key={`${renderIndex}`}
            onPress={() => {
              this.selectDate(moment(startOfArgMonthMoment).set('date', dayIndex + 1));
            }}
            caption={`${dayIndex + 1}`}
            isToday={argMonthIsToday && (dayIndex === todayIndex)}
            isSelected={selectedMonthIsArg && (dayIndex === selectedIndex)}
            hasEvent={events && events[dayIndex] === true}
            usingEvents={this.props.eventDates.length > 0}
            customStyle={this.props.customStyle}
          />
        ));
      } else {
        days.push(<Day key={`${renderIndex}`} filler />);
      }
      if (renderIndex % 7 === 6) {
        weekRows.push(
          <View
            key={weekRows.length}
            style={[styles.weekRow, this.props.customStyle.weekRow]}
          >
              {days}
          </View>);
        days = [];
        if (dayIndex + 1 >= argMonthDaysCount) {
          break;
        }
      }
      renderIndex += 1;
    }

    // let after = (new Date()).getTime()
    // console.log('--- render time ---', after - before)
    return <View key={argMoment.month()} style={styles.monthContainer}>{weekRows}</View>;
  }

  renderHeading() {
    const headings = [];
    for (let i = 0; i < 7; i++) {
      const j = (i + this.props.weekStart) % 7;
      headings.push(
        <Text
          key={i}
          style={j === 0 || j === 6 ?
            [styles.weekendHeading, this.props.customStyle.weekendHeading] :
            [styles.dayHeading, this.props.customStyle.dayHeading]}
        >
          {this.props.dayHeadings[j]}
        </Text>
      );
    }

    return (
      <View style={[styles.calendarHeading, this.props.customStyle.calendarHeading]}>
        {headings}
      </View>
    );
  }

  renderTopBar() {
    let localizedMonth = this.props.monthNames[this.state.currentMonthMoment.month()];
    return this.props.showControls
    ? (
        <View style={[styles.calendarControls, this.props.customStyle.calendarControls]}>
          <TouchableOpacity
            style={[styles.controlButton, this.props.customStyle.controlButton]}
            onPress={this.onPrev}
          >
            <Text style={[styles.controlButtonText, this.props.customStyle.controlButtonText]}>
              {this.props.prevButtonText}
            </Text>
          </TouchableOpacity>
          <Text style={[styles.title, this.props.customStyle.title]}>
            {localizedMonth} {this.state.currentMonthMoment.year()}
          </Text>
          <TouchableOpacity
            style={[styles.controlButton, this.props.customStyle.controlButton]}
            onPress={this.onNext}
          >
            <Text style={[styles.controlButtonText, this.props.customStyle.controlButtonText]}>
              {this.props.nextButtonText}
            </Text>
          </TouchableOpacity>
        </View>
      )
    : (
      <View style={[styles.calendarControls, this.props.customStyle.calendarControls]}>
        <Text style={[styles.title, this.props.customStyle.title]}>
          {this.state.currentMonthMoment.format(this.props.titleFormat)}
        </Text>
      </View>
    );
  }

  render() {
    console.log('Rendering')
    const calendarDates = this.getMonthStack(this.state.currentMonthMoment);
    const eventDatesMap = prepareEventDates(this.props.eventDates);
    return (
      <View style={[styles.calendarContainer, this.props.customStyle.calendarContainer]}>
        {this.renderTopBar()}
        {this.renderHeading(this.props.titleFormat)}
        {this.props.scrollEnabled ?
          <ScrollView
            ref={calendar => this._calendar = calendar}
            horizontal
            scrollEnabled
            pagingEnabled
            removeClippedSubviews
            scrollEventThrottle={1000}
            showsHorizontalScrollIndicator={false}
            automaticallyAdjustContentInsets
            onMomentumScrollEnd={(event) => this.scrollEnded(event)}
          >
            {calendarDates.map((date) => this.renderMonthView(moment(date), eventDatesMap))}
          </ScrollView>
          :
          <View ref={calendar => this._calendar = calendar}>
            {calendarDates.map((date) => this.renderMonthView(moment(date), eventDatesMap))}
          </View>
        }
      </View>
    );
  }
}
<|endoftext|>


<commit_before>/* Copyright (c) 2012 The Tagspaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
console.debug("Loading SettingsAPI.js..");

var TSSETTINGS = (typeof TSSETTINGS == "object" && TSSETTINGS != null) ? TSSETTINGS : {};

TSSETTINGS.TagTemplate = {
                            "title": undefined,
                            "type": "plain",
                            /*          ,
                            "pattern":"yyyymmddhhmmss-yyyymmddhhmmss",
                            "example":"20120114123456-20120823231235",
                            "action":"showDatePicker",
                            "regex":"",
                            "maxlength":17,
                            "chainedTags":[
                                "isbn","autor"
                            ],
                            "url": "http://example.com",
                            "action":"showDatePicker",
                            "prefixes":[
                                "EUR", "USD", "BGN"
                            ]
                            */
                        }

TSSETTINGS.FavoriteTemplate = {
                            "name": undefined,
                            "path": undefined
                        }

TSSETTINGS.TagGroupTemplate = {
            "title": undefined,
            "isFolder": true,
            "key": undefined,
            "expand": true,
            "noLink": false,
            "children": []
        }

TSSETTINGS.DefaultSettings = {
	"appName": "@APPNAME@",
	"appVersion": "@VERSION@beta",
    "appBuild": "@VERSION@.@BUILD@",
	"settingsVersion": 1,
    "supportedFileTypeThumnailing": ['jpg','jpeg','png','gif'],
	"newTextFileContent": "Text file created with tagspaces(@VERSION@.@BUILD@)...",
    "newHTMLFileContent": "<meta http-equiv='content-type' content='text/html; charset=utf-8'><title>Tagspaces File</title>File created with tagspaces(@VERSION@.@BUILD@)...",
	"newMDFileContent": '#File created with tagspaces(@VERSION@.@BUILD@)...',
	"showUnixHiddenEntries": false,
	"lastOpenedTSID": 0,
    "lastOpenedDirectory": "",
	"tagspacesList": [
        {
            "name":'Windows Location Example',
            "path":'Z:\\'
        },
        {
            "name":'Unix Location Example',
            "path":'/media/'
        },
	],
    "extensions": [
        {
            "id": "editorText", // ID should be equal to the directory name where the ext. is located
            "enabled": true,
        },
        {
            "id": "tsTodo", // ID should be equal to the directory name where the ext. is located
            "enabled": false,
        },
    ],
    "supportedFileTypes": [
        { "type": "jpg", "viewer": "viewerImage", "editor": false  },
        { "type": "jpeg", "viewer": "viewerImage", "editor": false  },
        { "type": "gif", "viewer": "viewerImage", "editor": false  },
        { "type": "png", "viewer": "viewerImage", "editor": false  },
        { "type": "pdf", "viewer": "viewerBrowser", "editor": false  },
        { "type": "html", "viewer": "viewerBrowser", "editor": false  },
        { "type": "htm", "viewer": "viewerBrowser", "editor": false  },
        { "type": "mht", "viewer": "viewerBrowser", "editor": false  },
        { "type": "mhtml", "viewer": "viewerBrowser", "editor": false  },
        { "type": "maff", "viewer": "viewerBrowser", "editor": false  },
        { "type": "txt", "viewer": "viewerBrowser", "editor": false  },
        { "type": "js", "viewer": false, "editor": false  },
        { "type": "css", "viewer": false, "editor": false  },
        { "type": "mdown", "viewer": false, "editor": false  },
        { "type": "md", "viewer": false, "editor": false  }
    ],
	"tagGroups": [
		{
		    "title":"common",
		    "isFolder": true,
		    "key":"OTB",
		    "expand": true,
		    "children":[
		        {
		            "title":"book",
		            "type":"plain",
		        },
		        {
		            "title":"paper",
		            "type":"plain",
		        },
		        {
		            "title":"XEUR",
		            "type":"plain",
		        },
		        {
		            "title":"201XMMDD",
		            "type":"plain",
		        }
		    ]
		}
	]
}

TSSETTINGS.Settings = undefined;

//TSSETTINGS.DummyDirlistTree = [
//{"title":"2009","isFolder":true,"isLazy":true,"key":"z:\\Chronique\\2009"},
//{"title":"2010","isFolder":true,"isLazy":true,"key":"z:\\Chronique\\2010"},
//];

TSSETTINGS.getNewTextFileContent = function() {
    return TSSETTINGS.Settings["newTextFileContent"];
}

TSSETTINGS.getNewHTMLFileContent = function() {
    return TSSETTINGS.Settings["newHTMLFileContent"];
}

TSSETTINGS.getNewMDFileContent = function() {
    return TSSETTINGS.Settings["newMDFileContent"];
}

TSSETTINGS.getSupportedFileExt4Thumbnailing = function() {
    return TSSETTINGS.Settings["supportedFileTypeThumnailing"];
}

TSSETTINGS.getFileTypeEditor = function(fileTypeExt) {
    for(var i=0; i < TSSETTINGS.Settings["supportedFileTypes"].length; i++) {
        if(TSSETTINGS.Settings["supportedFileTypes"][i].type == fileTypeExt) {
             return TSSETTINGS.Settings["supportedFileTypes"][i].editor;
        }
    }
    return false;
}

TSSETTINGS.getFileTypeViewer = function(fileTypeExt) {
    for(var i=0; i < TSSETTINGS.Settings["supportedFileTypes"].length; i++) {
        if(TSSETTINGS.Settings["supportedFileTypes"][i].type == fileTypeExt) {
             return TSSETTINGS.Settings["supportedFileTypes"][i].viewer;
        }
    }
    return false;
}

TSSETTINGS.findTag = function(tagName, tagGroupKey) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagGroupKey) {
            // console.debug("Current taggroup "+TSSETTINGS.Settings["tagGroups"][i].key);
            for(var j=0; j < TSSETTINGS.Settings["tagGroups"][i]["children"].length; j++) {
                // console.debug("Current tagname "+TSSETTINGS.Settings["tagGroups"][i]["children"][j].title);
                if(TSSETTINGS.Settings["tagGroups"][i]["children"][j].title == tagName) {
                    return TSSETTINGS.Settings["tagGroups"][i]["children"][j];
                }
            }
        }
    }
    return false;
}

TSSETTINGS.setLastOpenedDir = function(directory) {
    TSSETTINGS.Settings["lastOpenedDirectory"] = directory;
    TSSETTINGS.saveSettings();
}

TSSETTINGS.getLastOpenedDir = function() {
    return TSSETTINGS.Settings["lastOpenedDirectory"];
}

TSSETTINGS.deleteTag = function(tagData) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.parentKey) {
            for(var j=0; j < TSSETTINGS.Settings["tagGroups"][i]["children"].length; j++) {
                if(TSSETTINGS.Settings["tagGroups"][i]["children"][j].title == tagData.title) {
                    TSSETTINGS.Settings["tagGroups"][i]["children"].splice(j, 1);
                    break;
                }
            }
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.deleteTagGroup = function(tagData) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
            console.debug("Deleting taggroup "+TSSETTINGS.Settings["tagGroups"][i].key);
            TSSETTINGS.Settings["tagGroups"].splice(i, 1);
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.editTag = function(tagData, newTagName) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.parentKey) {
            for(var j=0; j < TSSETTINGS.Settings["tagGroups"][i]["children"].length; j++) {
                if(TSSETTINGS.Settings["tagGroups"][i]["children"][j].title == tagData.title) {
                    TSSETTINGS.Settings["tagGroups"][i]["children"][j].title = newTagName;
                    break;
                }
            }
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.createTag = function(tagData, newTagName) {
    var newTagModel = JSON.parse( JSON.stringify(TSSETTINGS.TagTemplate));
    newTagModel.title = newTagName;
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
            console.debug("Creating tag: "+JSON.stringify(newTagModel)+" with parent: "+tagData.key);
            TSSETTINGS.Settings["tagGroups"][i]["children"].push(newTagModel);
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.editTagGroup = function(tagData, tagGroupName) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
//            console.debug("Deleting taggroup "+TSSETTINGS.Settings["tagGroups"][i].key);
            TSSETTINGS.Settings["tagGroups"][i].title = tagGroupName;
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.duplicateTagGroup = function(tagData, tagGroupName, tagGroupKey) {
    var newTagGroupModel = undefined;
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
            newTagGroupModel = JSON.parse( JSON.stringify(TSSETTINGS.Settings["tagGroups"][i]));
            break;
        }
    }
    newTagGroupModel.title = tagGroupName;
    newTagGroupModel.key = tagGroupKey;
    console.debug("Creating taggroup: "+JSON.stringify(newTagGroupModel)+" with key: "+tagGroupKey);
    TSSETTINGS.Settings["tagGroups"].push(newTagGroupModel);
    TSSETTINGS.saveSettings();
}

TSSETTINGS.createFavorite = function(name, location) {
    var newFavoriteModel = JSON.parse( JSON.stringify(TSSETTINGS.FavoriteTemplate));
    name = name.replace("\\", "\\\\");
    name = name.replace("\\\\\\", "\\\\");
    name = name.replace("\\\\\\\\", "\\\\");
    newFavoriteModel.name = name;
    newFavoriteModel.path = location;
    TSSETTINGS.Settings["tagspacesList"].push(newFavoriteModel);
    TSSETTINGS.saveSettings();
}

TSSETTINGS.deleteFavorite = function(name) {
    for(var i=0; i < TSSETTINGS.Settings["tagspacesList"].length; i++) {
            console.debug("Traversing favorite "+TSSETTINGS.Settings["tagspacesList"][i].name+" searching for "+name);
        if(TSSETTINGS.Settings["tagspacesList"][i].name == name) {
            console.debug("Deleting favorite "+TSSETTINGS.Settings["tagspacesList"][i].name);
            TSSETTINGS.Settings["tagspacesList"].splice(i, 1);
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.updateSettingMozillaPreferences = function(settings) {
    var tmpSettings = JSON.parse(settings);
    if(tmpSettings != null) {
        TSSETTINGS.Settings = tmpSettings;
        console.debug("Settings loaded from firefox preferences: "+tmpSettings);
    } else {
        TSSETTINGS.Settings = TSSETTINGS.DefaultSettings;
        console.debug('Default settings loaded(Firefox)!');
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.loadSettingsLocalStorage = function() {
    try {
        var tmpSettings = JSON.parse(localStorage.getItem('tsSettings'));
        console.debug("Settings: "+JSON.stringify(tmpSettings));
    	if(tmpSettings!=null) {
    		TSSETTINGS.Settings = tmpSettings;
    	}
    } catch(ex) {
        console.debug("Loading default settings due exception while loading settings: "+ex);
    }
}

// Save setting and Reloads the app
TSSETTINGS.saveSettings = function() {
    // Storing setting in the local storage for mozilla and chorme
	localStorage.setItem('tsSettings', JSON.stringify(TSSETTINGS.Settings));

    // Storing settings in mozilla native preferences
    if($.browser.mozilla) {
        IOAPI.saveSettings(JSON.stringify(TSSETTINGS.Settings));
	}

	console.debug('Tagspace Settings Saved!');
}
<commit_msg>Added getAllTags function for extracting all plain tags from the settings<commit_after>/* Copyright (c) 2012 The Tagspaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
console.debug("Loading SettingsAPI.js..");

var TSSETTINGS = (typeof TSSETTINGS == "object" && TSSETTINGS != null) ? TSSETTINGS : {};

TSSETTINGS.TagTemplate = {
                            "title": undefined,
                            "type": "plain",
                            /*          ,
                            "pattern":"yyyymmddhhmmss-yyyymmddhhmmss",
                            "example":"20120114123456-20120823231235",
                            "regex":"",
                            "maxlength":17,
                            "chainedTags":[
                                "isbn","autor"
                            ],
                            "url": "http://example.com",
                            "action":"showDatePicker",
                            "prefixes":[
                                "EUR", "USD", "BGN"
                            ]
                            */
                        }

TSSETTINGS.FavoriteTemplate = {
                            "name": undefined,
                            "path": undefined
                        }

TSSETTINGS.TagGroupTemplate = {
            "title": undefined,
            "isFolder": true,
            "key": undefined,
            "expand": true,
            "noLink": false,
            "children": []
        }

TSSETTINGS.DefaultSettings = {
	"appName": "@APPNAME@",
	"appVersion": "@VERSION@beta",
    "appBuild": "@VERSION@.@BUILD@",
	"settingsVersion": 1,
    "supportedFileTypeThumnailing": ['jpg','jpeg','png','gif'],
	"newTextFileContent": "Text file created with tagspaces(@VERSION@.@BUILD@)...",
    "newHTMLFileContent": "<meta http-equiv='content-type' content='text/html; charset=utf-8'><title>Tagspaces File</title>File created with tagspaces(@VERSION@.@BUILD@)...",
	"newMDFileContent": '#File created with tagspaces(@VERSION@.@BUILD@)...',
	"showUnixHiddenEntries": false,
	"lastOpenedTSID": 0,
    "lastOpenedDirectory": "",
	"tagspacesList": [
        {
            "name":'Windows Location Example',
            "path":'Z:\\'
        },
        {
            "name":'Unix Location Example',
            "path":'/media/'
        },
	],
    "extensions": [
        {
            "id": "editorText", // ID should be equal to the directory name where the ext. is located
            "enabled": true,
        },
        {
            "id": "tsTodo", // ID should be equal to the directory name where the ext. is located
            "enabled": false,
        },
    ],
    "supportedFileTypes": [
        { "type": "jpg", "viewer": "viewerImage", "editor": false  },
        { "type": "jpeg", "viewer": "viewerImage", "editor": false  },
        { "type": "gif", "viewer": "viewerImage", "editor": false  },
        { "type": "png", "viewer": "viewerImage", "editor": false  },
        { "type": "pdf", "viewer": "viewerBrowser", "editor": false  },
        { "type": "html", "viewer": "viewerBrowser", "editor": false  },
        { "type": "htm", "viewer": "viewerBrowser", "editor": false  },
        { "type": "mht", "viewer": "viewerBrowser", "editor": false  },
        { "type": "mhtml", "viewer": "viewerBrowser", "editor": false  },
        { "type": "maff", "viewer": "viewerBrowser", "editor": false  },
        { "type": "txt", "viewer": "viewerBrowser", "editor": false  },
        { "type": "js", "viewer": false, "editor": false  },
        { "type": "css", "viewer": false, "editor": false  },
        { "type": "mdown", "viewer": false, "editor": false  },
        { "type": "md", "viewer": false, "editor": false  }
    ],
	"tagGroups": [
		{
		    "title":"common",
		    "isFolder": true,
		    "key":"OTB",
		    "expand": true,
		    "children":[
		        {
		            "title":"book",
		            "type":"plain",
		        },
		        {
		            "title":"paper",
		            "type":"plain",
		        },
		        {
		            "title":"XEUR",
		            "type":"plain",
		        },
		        {
		            "title":"201XMMDD",
		            "type":"plain",
		        }
		    ]
		}
	]
}

TSSETTINGS.Settings = undefined;

//TSSETTINGS.DummyDirlistTree = [
//{"title":"2009","isFolder":true,"isLazy":true,"key":"z:\\Chronique\\2009"},
//{"title":"2010","isFolder":true,"isLazy":true,"key":"z:\\Chronique\\2010"},
//];

TSSETTINGS.getNewTextFileContent = function() {
    return TSSETTINGS.Settings["newTextFileContent"];
}

TSSETTINGS.getNewHTMLFileContent = function() {
    return TSSETTINGS.Settings["newHTMLFileContent"];
}

TSSETTINGS.getNewMDFileContent = function() {
    return TSSETTINGS.Settings["newMDFileContent"];
}

TSSETTINGS.getSupportedFileExt4Thumbnailing = function() {
    return TSSETTINGS.Settings["supportedFileTypeThumnailing"];
}

TSSETTINGS.getFileTypeEditor = function(fileTypeExt) {
    for(var i=0; i < TSSETTINGS.Settings["supportedFileTypes"].length; i++) {
        if(TSSETTINGS.Settings["supportedFileTypes"][i].type == fileTypeExt) {
             return TSSETTINGS.Settings["supportedFileTypes"][i].editor;
        }
    }
    return false;
}

TSSETTINGS.getFileTypeViewer = function(fileTypeExt) {
    for(var i=0; i < TSSETTINGS.Settings["supportedFileTypes"].length; i++) {
        if(TSSETTINGS.Settings["supportedFileTypes"][i].type == fileTypeExt) {
             return TSSETTINGS.Settings["supportedFileTypes"][i].viewer;
        }
    }
    return false;
}

TSSETTINGS.findTag = function(tagName, tagGroupKey) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagGroupKey) {
            // console.debug("Current taggroup "+TSSETTINGS.Settings["tagGroups"][i].key);
            for(var j=0; j < TSSETTINGS.Settings["tagGroups"][i]["children"].length; j++) {
                // console.debug("Current tagname "+TSSETTINGS.Settings["tagGroups"][i]["children"][j].title);
                if(TSSETTINGS.Settings["tagGroups"][i]["children"][j].title == tagName) {
                    return TSSETTINGS.Settings["tagGroups"][i]["children"][j];
                }
            }
        }
    }
    return false;
}

TSSETTINGS.getAllTags = function() {
    var allTags = [];
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        // console.debug("Current taggroup "+TSSETTINGS.Settings["tagGroups"][i].key);
        for(var j=0; j < TSSETTINGS.Settings["tagGroups"][i]["children"].length; j++) {
            // console.debug("Current tagname "+TSSETTINGS.Settings["tagGroups"][i]["children"][j].title);
            if(TSSETTINGS.Settings["tagGroups"][i]["children"][j].type == "plain") {
                allTags.push(TSSETTINGS.Settings["tagGroups"][i]["children"][j].title);
            }
        }
    }
    return allTags;
}

TSSETTINGS.setLastOpenedDir = function(directory) {
    TSSETTINGS.Settings["lastOpenedDirectory"] = directory;
    TSSETTINGS.saveSettings();
}

TSSETTINGS.getLastOpenedDir = function() {
    return TSSETTINGS.Settings["lastOpenedDirectory"];
}

TSSETTINGS.deleteTag = function(tagData) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.parentKey) {
            for(var j=0; j < TSSETTINGS.Settings["tagGroups"][i]["children"].length; j++) {
                if(TSSETTINGS.Settings["tagGroups"][i]["children"][j].title == tagData.title) {
                    TSSETTINGS.Settings["tagGroups"][i]["children"].splice(j, 1);
                    break;
                }
            }
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.deleteTagGroup = function(tagData) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
            console.debug("Deleting taggroup "+TSSETTINGS.Settings["tagGroups"][i].key);
            TSSETTINGS.Settings["tagGroups"].splice(i, 1);
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.editTag = function(tagData, newTagName) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.parentKey) {
            for(var j=0; j < TSSETTINGS.Settings["tagGroups"][i]["children"].length; j++) {
                if(TSSETTINGS.Settings["tagGroups"][i]["children"][j].title == tagData.title) {
                    TSSETTINGS.Settings["tagGroups"][i]["children"][j].title = newTagName;
                    break;
                }
            }
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.createTag = function(tagData, newTagName) {
    var newTagModel = JSON.parse( JSON.stringify(TSSETTINGS.TagTemplate));
    newTagModel.title = newTagName;
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
            console.debug("Creating tag: "+JSON.stringify(newTagModel)+" with parent: "+tagData.key);
            TSSETTINGS.Settings["tagGroups"][i]["children"].push(newTagModel);
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.editTagGroup = function(tagData, tagGroupName) {
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
//            console.debug("Deleting taggroup "+TSSETTINGS.Settings["tagGroups"][i].key);
            TSSETTINGS.Settings["tagGroups"][i].title = tagGroupName;
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.duplicateTagGroup = function(tagData, tagGroupName, tagGroupKey) {
    var newTagGroupModel = undefined;
    for(var i=0; i < TSSETTINGS.Settings["tagGroups"].length; i++) {
        if(TSSETTINGS.Settings["tagGroups"][i].key == tagData.key) {
            newTagGroupModel = JSON.parse( JSON.stringify(TSSETTINGS.Settings["tagGroups"][i]));
            break;
        }
    }
    newTagGroupModel.title = tagGroupName;
    newTagGroupModel.key = tagGroupKey;
    console.debug("Creating taggroup: "+JSON.stringify(newTagGroupModel)+" with key: "+tagGroupKey);
    TSSETTINGS.Settings["tagGroups"].push(newTagGroupModel);
    TSSETTINGS.saveSettings();
}

TSSETTINGS.createFavorite = function(name, location) {
    var newFavoriteModel = JSON.parse( JSON.stringify(TSSETTINGS.FavoriteTemplate));
    name = name.replace("\\", "\\\\");
    name = name.replace("\\\\\\", "\\\\");
    name = name.replace("\\\\\\\\", "\\\\");
    newFavoriteModel.name = name;
    newFavoriteModel.path = location;
    TSSETTINGS.Settings["tagspacesList"].push(newFavoriteModel);
    TSSETTINGS.saveSettings();
}

TSSETTINGS.deleteFavorite = function(name) {
    for(var i=0; i < TSSETTINGS.Settings["tagspacesList"].length; i++) {
            console.debug("Traversing favorite "+TSSETTINGS.Settings["tagspacesList"][i].name+" searching for "+name);
        if(TSSETTINGS.Settings["tagspacesList"][i].name == name) {
            console.debug("Deleting favorite "+TSSETTINGS.Settings["tagspacesList"][i].name);
            TSSETTINGS.Settings["tagspacesList"].splice(i, 1);
            break;
        }
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.updateSettingMozillaPreferences = function(settings) {
    var tmpSettings = JSON.parse(settings);
    if(tmpSettings != null) {
        TSSETTINGS.Settings = tmpSettings;
        console.debug("Settings loaded from firefox preferences: "+tmpSettings);
    } else {
        TSSETTINGS.Settings = TSSETTINGS.DefaultSettings;
        console.debug('Default settings loaded(Firefox)!');
    }
    TSSETTINGS.saveSettings();
}

TSSETTINGS.loadSettingsLocalStorage = function() {
    try {
        var tmpSettings = JSON.parse(localStorage.getItem('tsSettings'));
        console.debug("Settings: "+JSON.stringify(tmpSettings));
    	if(tmpSettings!=null) {
    		TSSETTINGS.Settings = tmpSettings;
    	}
    } catch(ex) {
        console.debug("Loading default settings due exception while loading settings: "+ex);
    }
}

// Save setting and Reloads the app
TSSETTINGS.saveSettings = function() {
    // Storing setting in the local storage for mozilla and chorme
	localStorage.setItem('tsSettings', JSON.stringify(TSSETTINGS.Settings));

    // Storing settings in mozilla native preferences
    if($.browser.mozilla) {
        IOAPI.saveSettings(JSON.stringify(TSSETTINGS.Settings));
	}

	console.debug('Tagspace Settings Saved!');
}
<|endoftext|>


<commit_before>'use strict';

var crypto = require('crypto');
var fs = require('fs');
var Q = require('q');
var through2 = require('through2');
var VinylFile = require('vinyl');
var bufferStream = require('./buffer-stream.js');

function File() {
    VinylFile.apply(this, arguments);

    // data piped to browser-pack
    this._hash = sha1(this.path);
    this._deps = {};

    // whether transforms were run
    this._transformed = false;
}

File.prototype = Object.create(VinylFile.prototype);

File.prototype._buffer = function (transforms) {
    var self = this;

    if (this._transformed || (!(transforms && transforms.length) && this.isBuffer())) {
        return Q.Promise(function (resolve) {resolve(self)});
    }

    var stream;
    if (this.isStream()) {
        stream = this.contents;
    } else if (this.isBuffer()) {
        // it'll be converted back to a buffer, but transforms require streams
        stream = bufferStream(this.contents);
    } else {
        stream = fs.createReadStream(this.path);
    }

    transforms && transforms.forEach(function (args) {
        var transform = args[0];

        if (typeof transform === 'string') {
            transform = require(transform);
        }

        stream = stream.pipe(transform.apply(null, [self.path].concat(args.slice(1))));
    });

    var chunks = [];
    var deferred = Q.defer();

    stream
        .on('error', deferred.reject)
        .on('end', function () {
            self.contents = Buffer.concat(chunks);
            self._transformed = true;
            deferred.resolve(self);
        })
        .pipe(through2(function (chunk, enc, cb) {
            chunks.push(chunk);
            cb();
        }));

    return deferred.promise;
};

function sha1(str) {
    return crypto.createHash('sha1').update(str).digest('hex').substring(0, 7);
}

module.exports = File;
<commit_msg>Some light refactoring<commit_after>'use strict';

var concat = require('concat-stream');
var crypto = require('crypto');
var fs = require('fs');
var Q = require('q');
var VinylFile = require('vinyl');
var bufferStream = require('./buffer-stream.js');

function File() {
    VinylFile.apply(this, arguments);

    // data piped to browser-pack
    this._hash = sha1(this.path);
    this._deps = {};

    // whether transforms were run
    this._transformed = false;
}

File.prototype = Object.create(VinylFile.prototype);

File.prototype._buffer = function (transforms) {
    var self = this;

    if (this._transformed || (!(transforms && transforms.length) && this.isBuffer())) {
        return Q.Promise(function (resolve) {resolve(self)});
    }

    var stream = contentsToStream(this);
    var deferred = Q.defer();

    if (transforms) {
        transforms.forEach(function (args) {
            var transform = args[0];

            if (typeof transform === 'string') {
                transform = require(transform);
            }

            stream = stream.pipe(transform.apply(null, [self.path].concat(args.slice(1))));
        });
    }

    stream.on('error', deferred.reject).pipe(concat(function (buf) {
        self.contents = buf;
        self._transformed = true;
        deferred.resolve(self);
    }));

    return deferred.promise;
};

function contentsToStream(file) {
    if (file.isStream()) {
        return file.contents;
    } else if (file.isBuffer()) {
        // it'll be converted back to a buffer, but transforms require streams
        return bufferStream(file.contents);
    } else {
        return fs.createReadStream(file.path);
    }
}

function sha1(str) {
    return crypto.createHash('sha1').update(str).digest('hex').substring(0, 7);
}

module.exports = File;
<|endoftext|>


<commit_before>/* globals __DEV__ */
import Phaser from 'phaser'
import config from '../config'
import {makeGreen,findObjectsByType,createFromTiledObject} from '../utils'
import _ from 'lodash'
import Player from '../sprites/Player'

export default class extends Phaser.State {
	init() {
		this.years = 11
		this.startYear = 2007
	}

	preload() {
	}

	create() {
		this.map = this.game.add.tilemap('liip')
		this.map.addTilesetImage('tiles_spritesheet', 'gameTiles')
		this.mapWidthInPixels = this.map.widthInPixels

		// create layers
		this.backgroundLayer = this.map.createLayer('backgroundLayer')
		this.blockedLayer = this.map.createLayer('blockedLayer')
		this.map.setCollisionBetween(1, 200000, true, 'blockedLayer', true)
		this.backgroundLayer.resizeWorld()

		this.logo = this.game.add.sprite(20, 35, 'liipLogoSmall')
		this.logo.scale.setTo(0.5)
		this.logo.fixedToCamera = true

		// setup player
		this.player = new Player({
			game: this.game,
			x: 0,
			y: 250,
			asset: 'player'
		})
		this.player.enable()

		// score
		this.scoreLabel = this.game.add.text(config.gameWidth - 70, 30, '0', makeGreen(config.text.xl))
		this.scoreLabel.fixedToCamera = true

		// current position
		this.positionLabel = this.game.add.text(0, 0, '2007', Object.assign(config.text.xl, ({boundsAlignH: "center"})))
		this.positionLabel.setTextBounds(0, 30, config.gameWidth, 30)
		this.positionLabel.fixedToCamera = true

		// init keys
		this.keys = this.game.input.keyboard.addKeys({
			space: Phaser.KeyCode.SPACEBAR,
			down: Phaser.KeyCode.DOWN
		})

		// load sounds
		this.soundCoin = this.game.add.audio('coin')
		this.soundOuch = this.game.add.audio('ouch')

		// add objects
		this.createBeers()
		this.createAwards()
		this.createCoffees()
	}

	update() {
		this.game.physics.arcade.collide(this.player, this.blockedLayer, this.playerHit, null, this)

		if (this.player.alive) {
			if (this.keys.space.isDown) {
				this.player.jump()
			} else if (this.keys.down.isDown) {
				this.player.duck()
			}

			this.updateScore(5)

			if (!this.keys.down.isDown && this.player.isDucked) {
				this.player.stopDucking()
			}

			// Update position label depending on the position of the player
			this.positionLabel.text = this.getCurrentYear(this.player.x)
		}

		// make obejects collectable
		this.game.physics.arcade.overlap(this.player, this.beers, this.collect, null, this);
		this.game.physics.arcade.overlap(this.player, this.awards, this.collect, null, this);
		this.game.physics.arcade.overlap(this.player, this.coffees, this.collect, null, this);

		// restart the game if reaching the edge
		if (this.player.x >= this.game.world.width) {
			this.game.time.events.add(1500, this.gameOver, this)
		}
	}

	getCurrentYear(playerPositionX) {
		const pixelsPerYear = this.mapWidthInPixels / this.years
		let relativeYear = Math.floor(playerPositionX / pixelsPerYear)
		if (relativeYear > this.years - 1) {
			relativeYear = this.years - 1
		}
		return this.startYear + relativeYear
	}

	gameOver() {
		this.game.state.start('HighScore')
	}

	restart() {
		this.game.state.start('Game')
	}

	playerHit(player, blockedLayer) {
		this.game.physics.arcade.collide(this.player, this.blockedLayer, this.playerHit, null, this)

		if (player.body.blocked.right) {
			this.soundOuch.play()
			// kill player
			this.player.die()
			// go to gameover after a few milliseconds
			this.game.time.events.add(1500, this.gameOver, this)
		}
	}

	updateScore(newScore) {
		// this.score = newScore
		let score = parseInt(this.scoreLabel.text, 10) + newScore
		this.scoreLabel.text = score
	}

	createBeers() {
		this.beers = this.game.add.group();
		this.beers.enableBody = true;
		let result = findObjectsByType('beer', this.map, 'objectsLayer');

		result.forEach((element) => {
			createFromTiledObject(element, this.beers)
		})
	}

	createAwards() {
		this.awards = this.game.add.group()
		this.awards.enableBody = true
		let result = findObjectsByType('award', this.map, 'objectsLayer')

		result.forEach((element) => {
			createFromTiledObject(element, this.awards)
		})
	}

	createCoffees() {
		this.coffees = this.game.add.group()
		this.coffees.enableBody = true
		let result = findObjectsByType('coffee', this.map, 'objectsLayer')

		result.forEach((element) => {
			createFromTiledObject(element, this.coffees)
		})
	}

	collect(player, collectable) {
		// show +500 notice
		if(collectable.type === 'beer') {
			this.player.speedUp()
		} else if(collectable.type === 'coffee') {
			this.player.slowDown()
		}

		let oneUp = this.game.add.text(
			collectable.x,
			collectable.y,
			'+' + config.coinValue,
			makeGreen(config.text.xl)
			)
		// oneUp.fixedToCamera = true
		// destroy it shortly thereafter
		setTimeout(() => {
			oneUp.destroy()
		}, 500)

		// play audio
		this.soundCoin.play()
		// update score
		// @todo different bonuses per collectable?
		this.updateScore(config.coinValue)
		// remove sprite
		collectable.destroy()
	}
}
<commit_msg>mute button... we missing button graphics :D<commit_after>/* globals __DEV__ */
import Phaser from 'phaser'
import config from '../config'
import {makeGreen,findObjectsByType,createFromTiledObject} from '../utils'
import _ from 'lodash'
import Player from '../sprites/Player'

export default class extends Phaser.State {
	init() {
		this.years = 11
		this.startYear = 2007
		this.game.sound.mute = false
	}

	preload() {
	}

	create() {
		this.map = this.game.add.tilemap('liip')
		this.map.addTilesetImage('tiles_spritesheet', 'gameTiles')
		this.mapWidthInPixels = this.map.widthInPixels

		// create layers
		this.backgroundLayer = this.map.createLayer('backgroundLayer')
		this.blockedLayer = this.map.createLayer('blockedLayer')
		this.map.setCollisionBetween(1, 200000, true, 'blockedLayer', true)
		this.backgroundLayer.resizeWorld()

		this.logo = this.game.add.sprite(20, 35, 'liipLogoSmall')
		this.logo.scale.setTo(0.5)
		this.logo.fixedToCamera = true

		// setup player
		this.player = new Player({
			game: this.game,
			x: 0,
			y: 250,
			asset: 'player'
		})
		this.player.enable()

		// score
		this.scoreLabel = this.game.add.text(config.gameWidth - 70, 30, '0', makeGreen(config.text.xl))
		this.scoreLabel.fixedToCamera = true

		// current position
		this.positionLabel = this.game.add.text(0, 0, '2007', Object.assign(config.text.xl, ({boundsAlignH: "center"})))
		this.positionLabel.setTextBounds(0, 30, config.gameWidth, 30)
		this.positionLabel.fixedToCamera = true

		// mute button
		this.muteBtn = this.game.add.text(config.gameWidth - 120, 35, 'mute', makeGreen(config.text.md))
		this.muteBtn.fixedToCamera = true
		this.muteBtn.inputEnabled = true
		this.muteBtn.events.onInputDown.add(() => {
			this.game.sound.mute = !this.game.sound.mute
		})

		// init keys
		this.keys = this.game.input.keyboard.addKeys({
			space: Phaser.KeyCode.SPACEBAR,
			down: Phaser.KeyCode.DOWN
		})

		// load sounds
		this.soundCoin = this.game.add.audio('coin')
		this.soundOuch = this.game.add.audio('ouch')

		// add objects
		this.createBeers()
		this.createAwards()
		this.createCoffees()
	}

	update() {
		this.game.physics.arcade.collide(this.player, this.blockedLayer, this.playerHit, null, this)

		if (this.player.alive) {
			if (this.keys.space.isDown) {
				this.player.jump()
			} else if (this.keys.down.isDown) {
				this.player.duck()
			}

			this.updateScore(5)

			if (!this.keys.down.isDown && this.player.isDucked) {
				this.player.stopDucking()
			}

			// Update position label depending on the position of the player
			this.positionLabel.text = this.getCurrentYear(this.player.x)
		}

		// make obejects collectable
		this.game.physics.arcade.overlap(this.player, this.beers, this.collect, null, this);
		this.game.physics.arcade.overlap(this.player, this.awards, this.collect, null, this);
		this.game.physics.arcade.overlap(this.player, this.coffees, this.collect, null, this);

		// restart the game if reaching the edge
		if (this.player.x >= this.game.world.width) {
			this.game.time.events.add(1500, this.gameOver, this)
		}
	}

	getCurrentYear(playerPositionX) {
		const pixelsPerYear = this.mapWidthInPixels / this.years
		let relativeYear = Math.floor(playerPositionX / pixelsPerYear)
		if (relativeYear > this.years - 1) {
			relativeYear = this.years - 1
		}
		return this.startYear + relativeYear
	}

	gameOver() {
		this.game.state.start('HighScore')
	}

	restart() {
		this.game.state.start('Game')
	}

	playerHit(player, blockedLayer) {
		this.game.physics.arcade.collide(this.player, this.blockedLayer, this.playerHit, null, this)

		if (player.body.blocked.right) {
			this.soundOuch.play()
			// kill player
			this.player.die()
			// go to gameover after a few milliseconds
			this.game.time.events.add(1500, this.gameOver, this)
		}
	}

	updateScore(newScore) {
		// this.score = newScore
		let score = parseInt(this.scoreLabel.text, 10) + newScore
		this.scoreLabel.text = score
	}

	createBeers() {
		this.beers = this.game.add.group();
		this.beers.enableBody = true;
		let result = findObjectsByType('beer', this.map, 'objectsLayer');

		result.forEach((element) => {
			createFromTiledObject(element, this.beers)
		})
	}

	createAwards() {
		this.awards = this.game.add.group()
		this.awards.enableBody = true
		let result = findObjectsByType('award', this.map, 'objectsLayer')

		result.forEach((element) => {
			createFromTiledObject(element, this.awards)
		})
	}

	createCoffees() {
		this.coffees = this.game.add.group()
		this.coffees.enableBody = true
		let result = findObjectsByType('coffee', this.map, 'objectsLayer')

		result.forEach((element) => {
			createFromTiledObject(element, this.coffees)
		})
	}

	collect(player, collectable) {
		// show +500 notice
		if(collectable.type === 'beer') {
			this.player.speedUp()
		} else if(collectable.type === 'coffee') {
			this.player.slowDown()
		}

		let oneUp = this.game.add.text(
			collectable.x,
			collectable.y,
			'+' + config.coinValue,
			makeGreen(config.text.xl)
			)
		// oneUp.fixedToCamera = true
		// destroy it shortly thereafter
		setTimeout(() => {
			oneUp.destroy()
		}, 500)

		// play audio
		this.soundCoin.play()
		// update score
		// @todo different bonuses per collectable?
		this.updateScore(config.coinValue)
		// remove sprite
		collectable.destroy()
	}
}
<|endoftext|>