<commit_before>'use strict';

angular.module('Lunch.profile', [
  'openfb',
  'Lunch.factory.Geo',
  'Lunch.factory.requests',
  'Lunch.service.matchData'
])
.config(function($stateProvider) {
  $stateProvider
  .state('app.profile', {
    url: '/profile',
    views: {
      'menuContent' :{
        templateUrl: 'templates/profile.html',
        controller: 'ProfileCtrl'
      }
    }
  });
})

.controller('ProfileCtrl', function($q, $rootScope, $state, $scope,
                                    $ionicSlideBoxDelegate, $window,
                                    storedUserData, OpenFB, Geo, localStore,
                                    requests, matchData, match) {
  if (match.id === undefined) {
    $scope.action = 'Find a Lunch Buddy';
    $scope.takeAction = function() { $state.go('app.browse'); };
  } else {
    $scope.action = 'Plan your Lunch';
    $scope.takeAction = function() { $state.go('app.chats'); };
  }

  // Store data in scope
  $scope.userData = storedUserData;

  $scope.getLikes = function() {
    OpenFB.get('/me/likes')
      .success(function(fbLikeObj){
        // need to keep track of old ids
        var idTrack = {};
        angular.forEach(fbLikeObj.data, function(value){
          //if a new like / id
          if(value.name){
            //inform the database if a new id
            //add the new id and like data locally
            $scope.userData.likes[value.id] = value.name;

            postLikes(value);
          }
          //track id
          idTrack[value.id] = true;
        });
        //check ids fetched from fb to local ids.  if like stored locally no longer
        //avaiable from fb, inform the db and (then) delete locally
        for(var like in $scope.userData.likes) {
          if(!idTrack[like]){
            console.info('Deleteing like: ' + like + '; no longer in facebook');
            requests.deleteLike(like.id, {'userId': $scope.userData.id});
            delete $scope.userData.likes[like]; // since the like no longer exists
            //inform database using like.id and user.id and like.name ($scope.userData.likes[likeId])
          }
        }
      $rootScope.$emit('userDataChanged', $scope.userData);
      });
  };

  var postLikes = function(like) {
    requests.postLike({
      'userId' : $scope.userData.id,
      'id': like.id,
      'name': like.name
    });
  };

  var postTag = function(tagName) {
    requests.postTag({
      'userId' : $scope.userData.id,
      'id': tagName,
      'name': tagName
    });
  };

  var postTags = function() {
    angular.forEach(storedUserData.tags, function(value, key){
        // only post tags that are pressed currently
        if(value){
          postTag(key);
        }
    });
  };

  var deleteTag = function(tagName) {
    requests.deleteTag({
      'userId' : $scope.userData.id,
      'id': tagName
    });
  };

  var getPicture = function() {
    OpenFB.get('/me/picture?redirect=0&height=133&type=normal&width=100')//'/me/picture')
    .success(function(data){
      if(data !== $scope.userData.photo_url){
        var image = "

";
        angular.element(document.querySelector('#userimage')).html(image);
        $scope.userData.photo_url = data.data.url;
        //tell the database the image associated with the user has changed
        postUser();
        $rootScope.$emit('userDataChanged', $scope.userData);
      }
    });
  };

  var getDetails = function() {
    var deferredPost = $q.defer();

    if ($scope.userData.id) {
      deferredPost.resolve();
    } else {
      OpenFB.get('/me')
      .success(function(data){
        angular.extend($scope.userData, data);
        //store updates to data locally
        $rootScope.$emit('userDataChanged', $scope.userData);
        deferredPost.resolve();
      })
      .error(function(err){
        $window.alert('Unable to reach Facebook');
        deferredPost.reject();
      });
    }

    return deferredPost.promise;
  };

  $scope.tagClick = function(e){
    var clickedText = e.toElement.innerText;
    var wasPressed = $scope.userData.tags[clickedText];

    // toggle the state of the tag
    //if it was pressed, and is now not pressed, delete the tag
    if(wasPressed){
      deleteTag(clickedText);
      $scope.userData.tags[clickedText] = false;
    //if it was not pressed, and is now pressed, create the tag
    } else {
      postTag(clickedText);
      $scope.userData.tags[clickedText] = true;
    }
    $rootScope.$emit('userDataChanged', $scope.userData);
  };

  var postUser = function(){
    return getDetails().then(function() {
      return requests.postBasicDetails({
        'id' : $scope.userData.id,
        'firstname': $scope.userData.first_name,
        'lastname': $scope.userData.last_name,
        'profileImage': $scope.userData.photo_url
      });
    });
  };

  var postLocation = function(pos) {
    $scope.userData.geolocation = pos.coords;
      OpenFB.checkLogin().then(function(id) {
        requests.postLocation({
          'userId': id,
          'lat': pos.coords.latitude,
          'lng': pos.coords.longitude
        }).then(function(res) {
          console.info('You are in ' + angular.fromJson(res).data.city);
          $scope.userData.location = angular.fromJson(res).data.city;
          $rootScope.$emit('userDataChanged', $scope.userData);
        });
    });
  };

  $scope.$on('$stateChangeSuccess', function(e, state) { // this triggers every time we go to the profile page, may need something else
    postUser().then(function() {
      getPicture();
      $scope.getLikes();

      //post tags on initialisation
      postTags();

      Geo.getCurrentPosition()
        .then(function(pos) { postLocation(pos); })
        .catch(function(err) { console.error(err); });
      });
  });
});
<commit_msg>Rearranged profile.js to reduce long lines<commit_after>'use strict';

angular.module('Lunch.profile', [
  'openfb',
  'Lunch.factory.Geo',
  'Lunch.factory.requests',
  'Lunch.service.matchData'
])
.config(function($stateProvider) {
  $stateProvider
  .state('app.profile', {
    url: '/profile',
    views: {
      'menuContent' :{
        templateUrl: 'templates/profile.html',
        controller: 'ProfileCtrl'
      }
    }
  });
})

.controller('ProfileCtrl', function($q, $rootScope, $state, $scope,
                                    $ionicSlideBoxDelegate, $window,
                                    storedUserData, OpenFB, Geo, localStore,
                                    requests, matchData, match) {
  if (match.id === undefined) {
    $scope.action = 'Find a Lunch Buddy';
    $scope.takeAction = function() { $state.go('app.browse'); };
  } else {
    $scope.action = 'Plan your Lunch';
    $scope.takeAction = function() { $state.go('app.chats'); };
  }

  // Store data in scope
  $scope.userData = storedUserData;

  $scope.getLikes = function() {
    OpenFB.get('/me/likes')
      .success(function(fbLikeObj){
        // need to keep track of old ids
        var idTrack = {};
        angular.forEach(fbLikeObj.data, function(value){
          //if a new like / id
          if(value.name){
            //inform the database if a new id
            //add the new id and like data locally
            $scope.userData.likes[value.id] = value.name;

            postLikes(value);
          }
          //track id
          idTrack[value.id] = true;
        });
        // check ids fetched from fb to local ids.
        // if like stored locally no longer
        // avaiable from fb, inform the db and (then) delete locally
        for(var like in $scope.userData.likes) {
          if(!idTrack[like]){
            console.info('Deleting like: ' + like + '; no longer in facebook');
            requests.deleteLike(like.id, {'userId': $scope.userData.id});
            delete $scope.userData.likes[like];
            // since the like no longer exists
            // inform database using like.id and user.id and like.name
            // ($scope.userData.likes[likeId])
          }
        }
      $rootScope.$emit('userDataChanged', $scope.userData);
      });
  };

  var postLikes = function(like) {
    requests.postLike({
      'userId' : $scope.userData.id,
      'id': like.id,
      'name': like.name
    });
  };

  var postTag = function(tagName) {
    requests.postTag({
      'userId' : $scope.userData.id,
      'id': tagName,
      'name': tagName
    });
  };

  var postTags = function() {
    angular.forEach(storedUserData.tags, function(value, key){
        // only post tags that are pressed currently
        if(value){
          postTag(key);
        }
    });
  };

  var deleteTag = function(tagName) {
    requests.deleteTag({
      'userId' : $scope.userData.id,
      'id': tagName
    });
  };

  var getPicture = function() {
    OpenFB.get('/me/picture?redirect=0&height=133&type=normal&width=100')
    .success(function(data){
      if(data !== $scope.userData.photo_url){
        var image =
          "

";
        angular.element(document.querySelector('#userimage')).html(image);
        $scope.userData.photo_url = data.data.url;
        //tell the database the image associated with the user has changed
        postUser();
        $rootScope.$emit('userDataChanged', $scope.userData);
      }
    });
  };

  var getDetails = function() {
    var deferredPost = $q.defer();

    if ($scope.userData.id) {
      deferredPost.resolve();
    } else {
      OpenFB.get('/me')
      .success(function(data){
        angular.extend($scope.userData, data);
        //store updates to data locally
        $rootScope.$emit('userDataChanged', $scope.userData);
        deferredPost.resolve();
      })
      .error(function(err){
        $window.alert('Unable to reach Facebook');
        deferredPost.reject();
      });
    }

    return deferredPost.promise;
  };

  $scope.tagClick = function(e){
    var clickedText = e.toElement.innerText;
    var wasPressed = $scope.userData.tags[clickedText];

    // toggle the state of the tag
    //if it was pressed, and is now not pressed, delete the tag
    if(wasPressed){
      deleteTag(clickedText);
      $scope.userData.tags[clickedText] = false;
    //if it was not pressed, and is now pressed, create the tag
    } else {
      postTag(clickedText);
      $scope.userData.tags[clickedText] = true;
    }
    $rootScope.$emit('userDataChanged', $scope.userData);
  };

  var postUser = function(){
    return getDetails().then(function() {
      return requests.postBasicDetails({
        'id' : $scope.userData.id,
        'firstname': $scope.userData.first_name,
        'lastname': $scope.userData.last_name,
        'profileImage': $scope.userData.photo_url
      });
    });
  };

  var postLocation = function(pos) {
    $scope.userData.geolocation = pos.coords;
      OpenFB.checkLogin().then(function(id) {
        requests.postLocation({
          'userId': id,
          'lat': pos.coords.latitude,
          'lng': pos.coords.longitude
        }).then(function(res) {
          console.info('You are in ' + angular.fromJson(res).data.city);
          $scope.userData.location = angular.fromJson(res).data.city;
          $rootScope.$emit('userDataChanged', $scope.userData);
        });
    });
  };

  // this triggers every time we go to the profile page
  $scope.$on('$stateChangeSuccess', function(e, state) {
    postUser().then(function() {
      getPicture();
      $scope.getLikes();

      //post tags on initialisation
      postTags();

      Geo.getCurrentPosition()
        .then(function(pos) { postLocation(pos); })
        .catch(function(err) { console.error(err); });
      });
  });
});
<|endoftext|>


<commit_before>/* global app, VSError, Youtube, Cloud */

const _ = require('underscore');
const path = require('path');
const moment = require('moment');
const Promise = require('bluebird');
const rename = Promise.promisify(require('fs').rename);
const sharp = require('sharp');
const uuid = require('uuid');

module.exports = {

    file: function (f, opts) {

        const { title, description } = opts || {};
        let file = this.isUploaded(f, opts.name || null);
        let type = 'file';
        let name = opts.name || '';
        const ext = this.getExtension(file);
        const enableCloud = app.config.aws.isEnabled || false;

        return Promise.try( () => {

            // Check if file is uploaded
            if (!file) {
                throw new VSError('The file could not be uploaded', 400);
            }

            // Check if the folder is writable
            if (!this.isWritable()) {
                throw new VSError('The folder don\'t have permission to save the file', 500);
            }

            // Check mimetype
            if (!this.isValidMimeType(file.mimetype, 'file')) {
                throw new VSError('The MIME type of the selected file is not allowed: ' + file.mimetype, 400);
            }

            if(_.contains(['gif', 'jpg', 'jpeg', 'png', 'jpe'], ext)) {
                type = 'image';
                name = uuid.v4();
            } else if(_.contains(['quicktime', 'ogg', 'webm', 'mp4', '3gp', 'mov', 'm4v', 'avi', 'mpg'], ext)) {
                type = 'video';
                name = uuid.v4();
            }

            // name file
            file.originalname = name + '.' + ext;

            let filePath = path.normalize(process.cwd() + '/' + file.path);
            let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);

            return rename(filePath, filePublic).then( () => {

                if (enableCloud) {
                    if (type === 'image') {
                        return this.uploadImageS3(file, ext);
                    } else if (type === 'video') {
                        return this.uploadYoutube(file, title, description);
                    } else {
                        return this.uploadFileS3(file, ext);
                    }
                } else if(type === 'image') {
                    return this.processImage(file, ext);
                } else {
                    return this.processFile(file, ext);
                }

            }).then( (r) => {

                let result = {
                    name: file.originalname,
                    url: r.url
                };

                if (type === 'image') {
                    result = Object.assign(result, {
                        thumbnail: r.thumbnail,
                        medium: r.medium,
                        large: r.large
                    });

                }

                return result;
            });

        });

    },

    /**
     * Check if has a file uploaded
     *
     * @param {type} file
     * @param {type} fieldname
     * @returns {nm$_Upload.module.exports.isUploaded.tmp|Boolean}
     */

    isUploaded: function (file, fieldname) {

        let tmp = (file && file[0]) || null;
        if (!tmp) {
            return false;
        }
        return (tmp.fieldname === 'file' || tmp.fieldname === '' + fieldname || tmp.originalname === '' + fieldname) ? tmp : false;

    },

    /**
     * Check if a path is writable
     *
     * @param {type} path
     * @returns {Boolean}
     */
    isWritable: function (path) {

        return true;

    },

    /**
     * Method to get the file extension
     *
     * @param {type} file
     * @param {type} name
     * @returns {String}
     */
    getExtension: function (file, name) {

        let ext = (file.originalname || '').split('.').pop();
        let extTemporal = (name || '').split('.').pop();
        if (!ext || ext === 'blob') {
            let extMimeType = (this.isValidMimeType(file.mimetype) || '').split('/').pop();
            if (!extMimeType) {
                ext = extTemporal || extMimeType;
            }
        }
        return ext.toLowerCase();

    },

    /**
     * Check mimetype image
     *
     * @param {string} mimetype
     * @returns {string}
     */
    isValidMimeType: function (mimetype) {

        // jpe?g, png, gif
        const images = ['image/jpeg', 'image/jpg', 'image/pjpeg', 'image/gif', 'image/png'];

        // quicktime, ogg, webm, mp4, 3gp, mov, m4v, avi, mpg
        const videos = ['video/quicktime', 'video/ogg', 'video/webm', 'video/mp4', 'video/x-mp4', 'video/3gp', 'video/x-3gp', 'video/mov', 'video/x-mov', 'video/m4v', 'video/x-m4v', 'video/avi', 'video/x-avi', 'video/mpg', 'video/x-mpg'];

        // pdf, doc, docx, xls, xlsx, ppt, pptx
        const files = ['application/pdf', 'application/x-pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'];

        // zip, rar
        const zip = ['application/zip', 'application/x-rar', 'application/gzip'];

        const validType = [...images, ...videos, ...files, ...zip];
        return _.find( validType, (item) => {
            return item === mimetype;
        });

    },

    /**
     * Process Images
     *
     * @param {object} file
     * @param {string} ext
     * @returns {object}
     */
    processImage: function (file, ext) {

        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        let thumbnailPublic = filePublic.replace('.' + ext, '-thumbnail.' + ext);
        let largePublic = filePublic.replace('.' + ext, '-large.' + ext);
        let mediumPublic = filePublic.replace('.' + ext, '-medium.' + ext);
        return Promise.props({
            thumbnail: sharp(filePublic).resize(200, 200).toFile(thumbnailPublic),
            medium: sharp(filePublic).resize(640, 640).max().toFile(mediumPublic),
            large: sharp(filePublic).resize(1200, 1200).max().toFile(largePublic)
        }).then( () => {
            return {
                name: file.orinalname,
                url: `//${app.config.settings.host}/files/${file.originalname}`,
                thumbnail: `//${app.config.settings.host}/files/${  (file.originalname).replace('.' + ext, '-thumbnail.' + ext)}`,
                medium: `//${app.config.settings.host}/files/${ (file.originalname).replace('.' + ext, '-medium.' + ext) }`,
                large: `//${app.config.settings.host}/files/${ (file.originalname).replace('.' + ext, '-large.' + ext) }`
            };
        });

    },

    /**
     * Process Files
     *
     * @param {object} file
     * @returns {object}
     */
    processFile: function (file) {

        return Promise.resolve({
            name: file.orinalname,
            url: `//${app.config.settings.host}/files/${file.originalname}`
        });

    },

    /**
     * Upload image to s3
     *
     * @param {type} file
     * @param {string} ext
     * @returns {Object}
     */
    uploadImageS3: function (file, ext) {

        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        return Cloud.image(filePublic, ext).then( (r) => {
            return {
                name: file.originalname,
                url: r.original || '',
                thumbnail: r.thumbnail || '',
                medium: r.medium || '',
                large: r.large || ''
            };
        });

    },

    /**
     * Upload file to s3
     *
     * @param {type} file
     * @param {string} ext
     * @returns {Object}
     */
    uploadFileS3: function (file, ext) {

        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        return Cloud.file(filePublic).then( (r) => {
            return {
                name: file.originalname,
                url: r
            };
        });

    },

    /**
     * Upload to Youtube
     *
     * @param {type} file
     * @param {string} title
     * @param {string} description
     * @returns {Object}
     */
    uploadYoutube: function (file, title, description) {

        let result = {
            name: file.originalname,
            url: '',
            youtubeId: ''
        };
        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        return Youtube.upload({video: filePublic, title, description}).then( (upload) => {
            result.url = 'https://www.youtube.com/watch?v=' + upload.id;
            result.youtubeId = upload.id;
            return result;
        });

    }

};
<commit_msg>[Updated] Eslint<commit_after>/* global app, VSError, Youtube, Cloud */

const _ = require('underscore');
const path = require('path');
const Promise = require('bluebird');
const rename = Promise.promisify(require('fs').rename);
const sharp = require('sharp');
const uuid = require('uuid');

module.exports = {

    file: function (f, opts) {

        const { title, description, localPath, uploadToCloud, allowed } = opts || {};
        let fileName = opts && opts.name ? opts.name : null;
        let file = this.isUploaded(f, fileName);
        let type = 'file';
        const ext = this.getExtension(file);
        let name = (fileName || file.originalname || '').replace('.' + ext, '');
        let enableCloud = (app.config.aws && app.config.aws.isEnabled) ? true : false;
        if (uploadToCloud === false) {
          enableCloud = false;
        }

        return Promise.try( () => {

            // Check if file is uploaded
            if (!file) {
                throw new VSError('The file could not be uploaded', 400);
            }

            // Check if the folder is writable
            if (!this.isWritable()) {
                throw new VSError('The folder don\'t have permission to save the file', 500);
            }

            // Check mimetype
            if (!this.isValidMimeType(file.mimetype, 'file')) {
                throw new VSError('The MIME type of the selected file is not allowed: ' + file.mimetype, 400);
            }

            if (allowed && Array.isArray(allowed)) {
              if (!_.contains(allowed, ext)) {
                throw new VSError('The extension file is not allowed: ' + ext, 400);
              }
            }

            if (_.contains(['gif', 'jpg', 'jpeg', 'png', 'jpe'], ext)) {
                type = 'image';
                name = uuid.v4();
            } else if (_.contains(['quicktime', 'ogg', 'webm', 'mp4', '3gp', 'mov', 'm4v', 'avi', 'mpg'], ext)) {
                type = 'video';
                name = uuid.v4();
            }

            // name file
            file.originalname = name.replace(/\s/g, '_') + '.' + ext;

            let filePath = path.normalize(process.cwd() + '/' + file.path);
            let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);

            return rename(filePath, filePublic).then( () => {

                if (enableCloud) {
                    if (type === 'image') {
                        return this.uploadImageS3(file, ext);
                    } else if (type === 'video') {
                        return this.uploadYoutube(file, title, description);
                    } else {
                        return this.uploadFileS3(file, ext);
                    }
                } else if (type === 'image') {
                    return this.processImage(file, ext);
                } else {
                    return this.processFile(file, ext);
                }

            }).then( (r) => {

                let result = {
                    name: file.originalname,
                    url: r.url
                };

                if (localPath === true) {
                  result.path = path.normalize(process.cwd() + '/public/files/' + file.originalname);
                }

                if (type === 'image') {
                    result = Object.assign(result, {
                        thumbnail: r.thumbnail,
                        medium: r.medium,
                        large: r.large
                    });

                }

                return result;
            });

        });

    },

    /**
     * Check if has a file uploaded
     *
     * @param {type} file
     * @param {type} fieldname
     * @returns {nm$_Upload.module.exports.isUploaded.tmp|Boolean}
     */

    isUploaded: function (file, fieldname) {

        let tmp = (file && file[0]) || null;
        if (!tmp) {
            return false;
        }
        return (tmp.fieldname === 'file' || tmp.fieldname === '' + fieldname || tmp.originalname === '' + fieldname) ? tmp : false;

    },

    /**
     * Check if a path is writable
     *
     * @param {type} path
     * @returns {Boolean}
     */
    isWritable: function (_path) {

        // TODO: Check if the folder has permissions
        return true;

    },

    /**
     * Method to get the file extension
     *
     * @param {type} file
     * @param {type} name
     * @returns {String}
     */
    getExtension: function (file, name) {

        let ext = (file.originalname || '').split('.').pop();
        let extTemporal = (name || '').split('.').pop();
        if (!ext || ext === 'blob') {
            let extMimeType = (this.isValidMimeType(file.mimetype) || '').split('/').pop();
            if (!extMimeType) {
                ext = extTemporal || extMimeType;
            }
        }
        return ext.toLowerCase();

    },

    /**
     * Check mimetype image
     *
     * @param {string} mimetype
     * @returns {string}
     */
    isValidMimeType: function (mimetype) {

        // jpe?g, png, gif
        const images = ['image/jpeg', 'image/jpg', 'image/pjpeg', 'image/gif', 'image/png'];

        // quicktime, ogg, webm, mp4, 3gp, mov, m4v, avi, mpg
        const videos = ['video/quicktime', 'video/ogg', 'video/webm', 'video/mp4', 'video/x-mp4', 'video/3gp', 'video/x-3gp', 'video/mov', 'video/x-mov', 'video/m4v', 'video/x-m4v', 'video/avi', 'video/x-avi', 'video/mpg', 'video/x-mpg'];

        // pdf, doc, docx, xls, xlsx, xlsb, ppt, pptx, csv
        const files = ['application/pdf', 'application/x-pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'text/csv', 'application/vnd.ms-excel.sheet.binary.macroenabled.12'];

        // zip, rar, txt
        const zip = ['application/zip', 'application/x-rar', 'application/gzip', 'text/plain'];

        const validType = [...images, ...videos, ...files, ...zip];
        return _.find( validType, (item) => {
            return item === mimetype;
        });

    },

    /**
     * Process Images
     *
     * @param {object} file
     * @param {string} ext
     * @returns {object}
     */
    processImage: function (file, ext) {

        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        let thumbnailPublic = filePublic.replace('.' + ext, '-thumbnail.' + ext);
        let largePublic = filePublic.replace('.' + ext, '-large.' + ext);
        let mediumPublic = filePublic.replace('.' + ext, '-medium.' + ext);
        return Promise.props({
            thumbnail: sharp(filePublic).resize(200, 200).toFile(thumbnailPublic),
            medium: sharp(filePublic).resize(640, 640).max().toFile(mediumPublic),
            large: sharp(filePublic).resize(1200, 1200).max().toFile(largePublic)
        }).then( () => {
            return {
                name: file.orinalname,
                url: `//${app.config.settings.host}/files/${file.originalname}`,
                thumbnail: `//${app.config.settings.host}/files/${ (file.originalname).replace('.' + ext, '-thumbnail.' + ext)}`,
                medium: `//${app.config.settings.host}/files/${ (file.originalname).replace('.' + ext, '-medium.' + ext) }`,
                large: `//${app.config.settings.host}/files/${ (file.originalname).replace('.' + ext, '-large.' + ext) }`
            };
        });

    },

    /**
     * Process Files
     *
     * @param {object} file
     * @returns {object}
     */
    processFile: function (file) {

        return Promise.resolve({
            name: file.orinalname,
            url: `//${app.config.settings.host}/files/${file.originalname}`
        });

    },

    /**
     * Upload image to s3
     *
     * @param {type} file
     * @param {string} ext
     * @returns {Object}
     */
    uploadImageS3: function (file, ext) {

        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        return Cloud.image(filePublic, ext).then( (r) => {
            return {
                name: file.originalname,
                url: r.original || '',
                thumbnail: r.thumbnail || '',
                medium: r.medium || '',
                large: r.large || ''
            };
        });

    },

    /**
     * Upload file to s3
     *
     * @param {type} file
     * @param {string} ext
     * @returns {Object}
     */
    uploadFileS3: function (file, ext) {

        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        return Cloud.file(filePublic).then( (r) => {
            return {
                name: file.originalname,
                url: r
            };
        });

    },

    /**
     * Upload to Youtube
     *
     * @param {type} file
     * @param {string} title
     * @param {string} description
     * @returns {Object}
     */
    uploadYoutube: function (file, title, description) {

        let result = {
            name: file.originalname,
            url: '',
            youtubeId: ''
        };
        let filePublic = path.normalize(process.cwd() + '/public/files/' + file.originalname);
        return Youtube.upload({video: filePublic, title, description}).then( (upload) => {
            result.url = 'https://www.youtube.com/watch?v=' + upload.id;
            result.youtubeId = upload.id;
            return result;
        });

    }

};

<|endoftext|>


<commit_before>import EPMModalsService from '@tryghost/ember-promise-modals/services/modals';
import {bind} from '@ember/runloop';
import {inject as service} from '@ember/service';

export default class ModalsService extends EPMModalsService {
    @service dropdown;

    DEFAULT_OPTIONS = {
        className: 'fullscreen-modal-action fullscreen-modal-wide'
    };

    // we manually close modals on backdrop clicks and escape rather than letting focus-trap
    // handle it so we can intercept/abort closing for things like unsaved change confirmations
    focusTrapOptions = {
        allowOutsideClick: true,
        clickOutsideDeactivates: false,
        escapeDeactivates: false
    };

    open(modal, data, options) {
        const mergedOptions = Object.assign({}, this.DEFAULT_OPTIONS, modal.modalOptions, options);
        return super.open(modal, data, mergedOptions);
    }

    _onFirstModalAdded() {
        super._onFirstModalAdded(...arguments);
        this.addEventHandlers();
        this.dropdown.closeDropdowns();
    }

    _onLastModalRemoved() {
        super._onLastModalRemoved(...arguments);
        this.removeEventHandlers();
    }

    addEventHandlers() {
        if (!this.backdropClickHandler) {
            this.backdropClickHandler = bind(this, this.handleBackdropClick);
            document.body.addEventListener('click', this.backdropClickHandler, {capture: true, passive: false});
        }

        if (!this.escapeKeyHandler) {
            this.escapeKeyHandler = bind(this, this.handleEscapeKey);
            document.addEventListener('keydown', this.escapeKeyHandler, {capture: true, passive: false});
        }
    }

    removeEventHandlers() {
        document.body.removeEventListener('click', this.backdropClickHandler, {capture: true, passive: false});
        this.backdropClickHandler = null;

        document.removeEventListener('keydown', this.escapeKeyHandler, {capture: true, passive: false});
        this.escapeKeyHandler = null;
    }

    handleBackdropClick(event) {
        let shouldClose = true;

        for (const elem of (event.path || event.composedPath())) {
            if (elem.matches?.('.modal-content, .fullscreen-modal-total-overlay, .ember-basic-dropdown-content, a[download]')) {
                shouldClose = false;
                break;
            }
        }

        if (this.top.options.ignoreBackdropClick) {
            shouldClose = false;
        }

        if (shouldClose) {
            this.top.close();
        }
    }

    handleEscapeKey(event) {
        if (event.key === 'Escape') {
            this.top.close();
        }
    }
}
<commit_msg>Fixed error from backdrop click handler for modals without options<commit_after>import EPMModalsService from '@tryghost/ember-promise-modals/services/modals';
import {bind} from '@ember/runloop';
import {inject as service} from '@ember/service';

export default class ModalsService extends EPMModalsService {
    @service dropdown;

    DEFAULT_OPTIONS = {
        className: 'fullscreen-modal-action fullscreen-modal-wide'
    };

    // we manually close modals on backdrop clicks and escape rather than letting focus-trap
    // handle it so we can intercept/abort closing for things like unsaved change confirmations
    focusTrapOptions = {
        allowOutsideClick: true,
        clickOutsideDeactivates: false,
        escapeDeactivates: false
    };

    open(modal, data, options) {
        const mergedOptions = Object.assign({}, this.DEFAULT_OPTIONS, modal.modalOptions, options);
        return super.open(modal, data, mergedOptions);
    }

    _onFirstModalAdded() {
        super._onFirstModalAdded(...arguments);
        this.addEventHandlers();
        this.dropdown.closeDropdowns();
    }

    _onLastModalRemoved() {
        super._onLastModalRemoved(...arguments);
        this.removeEventHandlers();
    }

    addEventHandlers() {
        if (!this.backdropClickHandler) {
            this.backdropClickHandler = bind(this, this.handleBackdropClick);
            document.body.addEventListener('click', this.backdropClickHandler, {capture: true, passive: false});
        }

        if (!this.escapeKeyHandler) {
            this.escapeKeyHandler = bind(this, this.handleEscapeKey);
            document.addEventListener('keydown', this.escapeKeyHandler, {capture: true, passive: false});
        }
    }

    removeEventHandlers() {
        document.body.removeEventListener('click', this.backdropClickHandler, {capture: true, passive: false});
        this.backdropClickHandler = null;

        document.removeEventListener('keydown', this.escapeKeyHandler, {capture: true, passive: false});
        this.escapeKeyHandler = null;
    }

    handleBackdropClick(event) {
        let shouldClose = true;

        for (const elem of (event.path || event.composedPath())) {
            if (elem.matches?.('.modal-content, .fullscreen-modal-total-overlay, .ember-basic-dropdown-content, a[download]')) {
                shouldClose = false;
                break;
            }
        }

        if (this.top.options?.ignoreBackdropClick) {
            shouldClose = false;
        }

        if (shouldClose) {
            this.top.close();
        }
    }

    handleEscapeKey(event) {
        if (event.key === 'Escape') {
            this.top.close();
        }
    }
}
<|endoftext|>


<commit_before>import assign from 'lodash.assign'
import createDebug from 'debug'
import WebSocket from 'ws'

const debug = createDebug('xo:wsProxy')

const defaults = {
  // Automatically close the client connection when the remote close.
  autoClose: true
}

// Proxy a WebSocket `client` to a remote server which has `url` as
// address.
export default function wsProxy (client, url, opts) {
  opts = assign({}, defaults, opts)
  const autoClose = !!opts.autoClose
  delete opts.autoClose

  function onClientSend (error) {
    if (error) {
      debug('client send error', error)
    }
  }
  function onRemoteSend (error) {
    if (error) {
      debug('remote send error', error)
    }
  }

  const remote = new WebSocket(url, opts).once('open', function () {
    debug('connected to %s', url)
  }).once('close', function () {
    debug('remote closed')

    if (autoClose) {
      client.close()
    }
  }).once('error', function (error) {
    debug('remote error: %s', error)
  }).on('message', function (message) {
    client.send(message, onClientSend)
  })

  client.once('close', function () {
    debug('client closed')
    remote.close()
  }).on('message', function (message) {
    remote.send(message, onRemoteSend)
  })
}
<commit_msg>WS proxy forwards the subprotocol.<commit_after>import assign from 'lodash.assign'
import createDebug from 'debug'
import WebSocket from 'ws'

const debug = createDebug('xo:wsProxy')

const defaults = {
  // Automatically close the client connection when the remote close.
  autoClose: true
}

// Proxy a WebSocket `client` to a remote server which has `url` as
// address.
export default function wsProxy (client, url, opts) {
  opts = assign({}, defaults, {
    protocol: client.protocol
  }, opts)
  const autoClose = !!opts.autoClose
  delete opts.autoClose

  function onClientSend (error) {
    if (error) {
      debug('client send error', error)
    }
  }
  function onRemoteSend (error) {
    if (error) {
      debug('remote send error', error)
    }
  }

  const remote = new WebSocket(url, opts).once('open', function () {
    debug('connected to %s', url)
  }).once('close', function () {
    debug('remote closed')

    if (autoClose) {
      client.close()
    }
  }).once('error', function (error) {
    debug('remote error: %s', error)
  }).on('message', function (message) {
    client.send(message, onClientSend)
  })

  client.once('close', function () {
    debug('client closed')
    remote.close()
  }).on('message', function (message) {
    remote.send(message, onRemoteSend)
  })
}
<|endoftext|>


<commit_before>var ref = require('ref');
var wchar_t = require('ref-wchar');
var ffi = require('ffi');

var PWChar = ref.refType(wchar_t.string);

// function binding
var lib = ffi.Library('XEditLib', {
	// META FUNCTIONS
	'Initialize': [ 'void', [] ],
	'Finalize': [ 'void', [] ],
	'GetBuffer': [ 'void', [ PWChar, 'int'] ],
	'FlushBuffer': [ 'void', [] ],
	'GetExceptionMessage': ['bool', [ PWChar, 'int'] ],
	'GetGlobal': [ 'bool', [PWChar, PWChar, 'int'] ],
	'Release': [ 'bool', [ref.types.uint32] ],
	'ResetStore': [ 'bool', [] ],
	// SETUP FUNCTIONS
	'SetGameMode': [ 'void', ['int'] ],
	'GetLoadOrder': [ 'bool', [PWChar, 'int'] ],
	'LoadPlugins': [ 'bool', [PWChar] ],
	'GetLoaderDone': [ 'bool', [] ],
	'GetGamePath': [ 'bool', ['int', PWChar, 'int'] ]
});

var xelib = {
	'Initialize': function() {
		lib.Initialize();
	},
	'Finalize': function() {
		lib.Finalize();
	},
	'GetBuffer': function() {
		var str = new Buffer(4096);
		str.type = PWChar;
		lib.GetBuffer(str, 4096);
		return wchar_t.toString(str);
	},
	'GetGlobal': function(keyValue) {
		var str = new Buffer(512);
		str.type = PWChar;
		var key = new Buffer(keyValue.length + 1);
		key.writeCString(keyValue);
		key.type = PWChar;
		console.log("key: " + wchar_t.toString(key));
		var success = lib.GetGlobal(key, str, 512);
		if (!success) throw "xedit-lib: GetGlobal failed.";
		return wchar_t.toString(str);
	},
	'GetLoaderDone': function() {
		return lib.GetLoaderDone();
	},
	'GetGamePath': function(mode) {
		var str = new Buffer(512);
		str.type = PWChar;
		var success = lib.GetGamePath(mode, str, 512);
		if (!success) throw "xedit-lib: GetGamePath failed.";
		return wchar_t.toString(str);
	}
}

export default xelib;
<commit_msg>added trimming of null terminators from strings retrieved from xedit-lib<commit_after>var ref = require('ref');
var wchar_t = require('ref-wchar');
var ffi = require('ffi');

var PWChar = ref.refType(wchar_t.string);

// function binding
var lib = ffi.Library('XEditLib', {
	// META FUNCTIONS
	'Initialize': [ 'void', [] ],
	'Finalize': [ 'void', [] ],
	'GetBuffer': [ 'void', [ PWChar, 'int'] ],
	'FlushBuffer': [ 'void', [] ],
	'GetExceptionMessage': ['bool', [ PWChar, 'int'] ],
	'GetGlobal': [ 'bool', [PWChar, PWChar, 'int'] ],
	'Release': [ 'bool', [ref.types.uint32] ],
	'ResetStore': [ 'bool', [] ],
	// SETUP FUNCTIONS
	'SetGameMode': [ 'void', ['int'] ],
	'GetLoadOrder': [ 'bool', [PWChar, 'int'] ],
	'LoadPlugins': [ 'bool', [PWChar] ],
	'GetLoaderDone': [ 'bool', [] ],
	'GetGamePath': [ 'bool', ['int', PWChar, 'int'] ]
});

var trimNull = function(str) {
	return str.substring(0, str.indexOf('\0'));
}

var xelib = {
	'Initialize': function() {
		lib.Initialize();
	},
	'Finalize': function() {
		lib.Finalize();
	},
	'GetBuffer': function() {
		var str = new Buffer(4096);
		str.type = PWChar;
		lib.GetBuffer(str, 4096);
		return trimNull(wchar_t.toString(str));
	},
	'GetExceptionMessage': function() {
		var str = new Buffer(4096);
		str.type = PWChar;
		lib.GetExceptionMessage(str, 4096);
		return trimNull(wchar_t.toString(str));
	},
	'GetGlobal': function(keyValue) {
		var str = new Buffer(512);
		str.type = PWChar;
		var key = new Buffer(keyValue.length + 1);
		key.writeCString(keyValue);
		key.type = PWChar;
		console.log("key: " + wchar_t.toString(key));
		var success = lib.GetGlobal(key, str, 512);
		if (!success) throw "xedit-lib: GetGlobal failed.";
		return trimNull(wchar_t.toString(str));
	},
	'GetLoaderDone': function() {
		return lib.GetLoaderDone();
	},
	'GetGamePath': function(mode) {
		var str = new Buffer(512);
		str.type = PWChar;
		var success = lib.GetGamePath(mode, str, 512);
		if (!success) return null;
		return trimNull(wchar_t.toString(str));
	}
}

export default xelib;
<|endoftext|>


<commit_before>import Alt from 'altFlux';
import { createStore } from 'alt-utils/lib/decorators';
import IdentityActions from 'actions/identity';

@createStore(Alt)
export default class IdentityStore {
  static displayName = 'IdentityStore';

  constructor() {
    this.bindListeners({
      setIdentities: IdentityActions.SET_IDENTITIES,
      delete: IdentityActions.DELETE
    });
  }

  setIdentities(identities) {
    this.identities = identities;
  }

  delete(params) {
    let identity = params.identity;
    let identities = params.identities;
    identities.splice(identities.findIndex(item => item === identity.id), 1);
    this.setIdentities(identities);
  }
}
<commit_msg>fix identity delete<commit_after>import Alt from 'altFlux';
import { createStore } from 'alt-utils/lib/decorators';
import IdentityActions from 'actions/identity';

@createStore(Alt)
export default class IdentityStore {
  static displayName = 'IdentityStore';

  constructor() {
    this.bindListeners({
      setIdentities: IdentityActions.SET_IDENTITIES,
      delete: IdentityActions.DELETE
    });
  }

  setIdentities(identities) {
    this.identities = identities;
  }

  delete(params) {
    let identity = params.identity;
    let identities = params.identities;
    let without_deleted = identities.filter(item => item.id != identity.id);
    this.setIdentities(without_deleted);
  }
}
<|endoftext|>


<commit_before><commit_msg>Mirrors public templates when running build script<commit_after><|endoftext|>


<commit_before>(function () {
  const electron = require('electron')
  const path = require('path')
  const getWindowLoadSettings = require('../src/get-window-load-settings')
  const entryPointDirPath = __dirname
  let blobStore = null
  let devMode = false
  let useSnapshot = false
  let requireFunction = null

  window.onload = function () {
    try {
      var startTime = Date.now()

      process.on('unhandledRejection', function (error, promise) {
        console.error('Unhandled promise rejection %o with error: %o', promise, error)
      })

      // Normalize to make sure drive letter case is consistent on Windows
      process.resourcesPath = path.normalize(process.resourcesPath)

      setupAtomHome()
      devMode = getWindowLoadSettings().devMode || !getWindowLoadSettings().resourcePath.startsWith(process.resourcesPath + path.sep)
      useSnapshot = !devMode && typeof snapshotResult !== 'undefined'
      requireFunction = useSnapshot ? snapshotResult.customRequire : require

      if (devMode) {
        var metadata = require('../package.json')
        if (!metadata._deprecatedPackages) {
          try {
            metadata._deprecatedPackages = require('../script/deprecated-packages.json')
          } catch (requireError) {
            console.error('Failed to setup deprecated packages list', requireError.stack)
          }
        }
      } else if (useSnapshot) {
        Module.prototype.require = function (modulePath) {
          const absoluteFilePath = Module._resolveFilename(modulePath, this, false)
          const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath)
          return snapshotResult.customRequire(relativeFilePath)
        }

        snapshotResult.setGlobals(global, process, window, document, Module._load)
      }

      const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js')
      blobStore = FileSystemBlobStore.load(
        path.join(process.env.ATOM_HOME, 'blob-store/')
      )

      const NativeCompileCache = requireFunction('../src/native-compile-cache.js')
      NativeCompileCache.setCacheStore(blobStore)
      NativeCompileCache.setV8Version(process.versions.v8)
      NativeCompileCache.install()

      if (getWindowLoadSettings().profileStartup) {
        profileStartup(Date.now() - startTime)
      } else {
        setupWindow()
        setLoadTime(Date.now() - startTime)
      }
    } catch (error) {
      handleSetupError(error)
    }
  }

  function setLoadTime (loadTime) {
    if (global.atom) {
      global.atom.loadTime = loadTime
    }
  }

  function handleSetupError (error) {
    const currentWindow = electron.remote.getCurrentWindow()
    currentWindow.setSize(800, 600)
    currentWindow.center()
    currentWindow.show()
    currentWindow.openDevTools()
    console.error(error.stack || error)
  }

  function setupWindow () {
    const CompileCache = requireFunction('../src/compile-cache.js')
    CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME)

    const ModuleCache = requireFunction('../src/module-cache.js')
    ModuleCache.register(getWindowLoadSettings())

    const startCrashReporter = requireFunction('../src/crash-reporter-start.js')
    startCrashReporter({_version: getWindowLoadSettings().appVersion})

    const CSON = requireFunction(useSnapshot ? '../node_modules/season/lib/cson.js' : 'season')
    CSON.setCacheDir(path.join(CompileCache.getCacheDirectory(), 'cson'))

    const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript)
    const initialize = requireFunction(initScriptPath)
    return initialize({blobStore: blobStore}).then(function () {
      electron.ipcRenderer.send('window-command', 'window:loaded')
    })
  }

  function profileStartup (initialTime) {
    function profile () {
      console.profile('startup')
      var startTime = Date.now()
      setupWindow().then(function () {
        setLoadTime(Date.now() - startTime + initialTime)
        console.profileEnd('startup')
        console.log('Switch to the Profiles tab to view the created startup profile')
      })
    }

    const webContents = electron.remote.getCurrentWindow().webContents
    if (webContents.devToolsWebContents) {
      profile()
    } else {
      webContents.once('devtools-opened', () => { setTimeout(profile, 1000) })
      webContents.openDevTools()
    }
  }

  function setupAtomHome () {
    if (process.env.ATOM_HOME) {
      return
    }

    // Ensure ATOM_HOME is always set before anything else is required
    // This is because of a difference in Linux not inherited between browser and render processes
    // https://github.com/atom/atom/issues/5412
    if (getWindowLoadSettings() && getWindowLoadSettings().atomHome) {
      process.env.ATOM_HOME = getWindowLoadSettings().atomHome
    }
  }
})()
<commit_msg>:art:<commit_after>(function () {
  const electron = require('electron')
  const path = require('path')
  const getWindowLoadSettings = require('../src/get-window-load-settings')
  const entryPointDirPath = __dirname
  let blobStore = null
  let devMode = false
  let useSnapshot = false
  let requireFunction = null

  window.onload = function () {
    try {
      const startTime = Date.now()

      process.on('unhandledRejection', function (error, promise) {
        console.error('Unhandled promise rejection %o with error: %o', promise, error)
      })

      // Normalize to make sure drive letter case is consistent on Windows
      process.resourcesPath = path.normalize(process.resourcesPath)

      setupAtomHome()
      devMode = getWindowLoadSettings().devMode || !getWindowLoadSettings().resourcePath.startsWith(process.resourcesPath + path.sep)
      useSnapshot = !devMode && typeof snapshotResult !== 'undefined'
      requireFunction = useSnapshot ? snapshotResult.customRequire : require

      if (devMode) {
        const metadata = require('../package.json')
        if (!metadata._deprecatedPackages) {
          try {
            metadata._deprecatedPackages = require('../script/deprecated-packages.json')
          } catch (requireError) {
            console.error('Failed to setup deprecated packages list', requireError.stack)
          }
        }
      } else if (useSnapshot) {
        Module.prototype.require = function (modulePath) {
          const absoluteFilePath = Module._resolveFilename(modulePath, this, false)
          const relativeFilePath = path.relative(entryPointDirPath, absoluteFilePath)
          return snapshotResult.customRequire(relativeFilePath)
        }

        snapshotResult.setGlobals(global, process, window, document, Module._load)
      }

      const FileSystemBlobStore = requireFunction('../src/file-system-blob-store.js')
      blobStore = FileSystemBlobStore.load(
        path.join(process.env.ATOM_HOME, 'blob-store/')
      )

      const NativeCompileCache = requireFunction('../src/native-compile-cache.js')
      NativeCompileCache.setCacheStore(blobStore)
      NativeCompileCache.setV8Version(process.versions.v8)
      NativeCompileCache.install()

      if (getWindowLoadSettings().profileStartup) {
        profileStartup(Date.now() - startTime)
      } else {
        setupWindow()
        setLoadTime(Date.now() - startTime)
      }
    } catch (error) {
      handleSetupError(error)
    }
  }

  function setLoadTime (loadTime) {
    if (global.atom) {
      global.atom.loadTime = loadTime
    }
  }

  function handleSetupError (error) {
    const currentWindow = electron.remote.getCurrentWindow()
    currentWindow.setSize(800, 600)
    currentWindow.center()
    currentWindow.show()
    currentWindow.openDevTools()
    console.error(error.stack || error)
  }

  function setupWindow () {
    const CompileCache = requireFunction('../src/compile-cache.js')
    CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME)

    const ModuleCache = requireFunction('../src/module-cache.js')
    ModuleCache.register(getWindowLoadSettings())

    const startCrashReporter = requireFunction('../src/crash-reporter-start.js')
    startCrashReporter({_version: getWindowLoadSettings().appVersion})

    const CSON = requireFunction(useSnapshot ? '../node_modules/season/lib/cson.js' : 'season')
    CSON.setCacheDir(path.join(CompileCache.getCacheDirectory(), 'cson'))

    const initScriptPath = path.relative(entryPointDirPath, getWindowLoadSettings().windowInitializationScript)
    const initialize = requireFunction(initScriptPath)
    return initialize({blobStore: blobStore}).then(function () {
      electron.ipcRenderer.send('window-command', 'window:loaded')
    })
  }

  function profileStartup (initialTime) {
    function profile () {
      console.profile('startup')
      const startTime = Date.now()
      setupWindow().then(function () {
        setLoadTime(Date.now() - startTime + initialTime)
        console.profileEnd('startup')
        console.log('Switch to the Profiles tab to view the created startup profile')
      })
    }

    const webContents = electron.remote.getCurrentWindow().webContents
    if (webContents.devToolsWebContents) {
      profile()
    } else {
      webContents.once('devtools-opened', () => { setTimeout(profile, 1000) })
      webContents.openDevTools()
    }
  }

  function setupAtomHome () {
    if (process.env.ATOM_HOME) {
      return
    }

    // Ensure ATOM_HOME is always set before anything else is required
    // This is because of a difference in Linux not inherited between browser and render processes
    // https://github.com/atom/atom/issues/5412
    if (getWindowLoadSettings() && getWindowLoadSettings().atomHome) {
      process.env.ATOM_HOME = getWindowLoadSettings().atomHome
    }
  }
})()
<|endoftext|>


<commit_before>var machineId;
var machineName;

// all static DOM elements
var domShowTokenInput = document.getElementById('showTokenInput');
var domTokenInput = document.getElementById('tokenInput');
var domTokenLabel = document.getElementById('tokenLabel');
var domTokenInteractive = document.getElementById('interactive');
var domMachineName = document.getElementById('machineName');
var domToken = document.getElementById('token');
var domTokenBarcode = document.getElementById('tokenBarcode');
var domRegister = document.getElementById('register');
var domUnregister = document.getElementById('unregister');
var domMachines = document.getElementById('machines');
var domShowMachineName = document.getElementById('showMachineName');

domShowTokenInput.onclick = function() {
  domTokenInput.style.display = 'block';
  domTokenLabel.style.display = 'block';
  this.style.display = 'none';

  Quagga.init({}, function(err) {
    if (err) {
      console.error(err);
      return;
    }

    Quagga.start();
  });

  Quagga.onDetected(function(result) {
    domTokenInput.value = result.codeResult.code;
    Quagga.stop();
    domTokenInteractive.style.display = 'none';
    window.alert('Token detected!');
  });
};

domMachineName.placeholder = window.navigator.userAgent;

function drawBarcode(text) {
  var bw = new BWIPJS;

  bw.bitmap(new Bitmap);

  bw.scale(1, 1);

  bw.push(text);
  bw.push({
    includetext: true,
  });

  bw.call('code128', function(e) {
    if (e) {
      if (typeof e === 'string') {
        console.error(e);
      } else if (e.stack) {
        console.error(e.message + '\r\n' + e.stack);
      } else {
        var s = '';
        if (e.fileName) {
          s += e.fileName + ' ';
        }
        if (e.lineNumber) {
          s += '[line ' + e.lineNumber + '] ';
        }
        console.error(s + (s ? ': ' : '') + e.message);
      }
    } else {
      bw.bitmap().show('tokenBarcode', 'N');
      domTokenBarcode.style.display = 'block';
    }
  });
}

function register() {
  localforage.getItem('token')
  .then(function(token) {
    if (token) {
      return;
    }

    navigator.serviceWorker.ready
    .then(function(registration) {
      return registration.pushManager.getSubscription()
      .then(function(subscription) {
        if (subscription) {
          return subscription;
        }

        return registration.pushManager.subscribe({ userVisibleOnly: true })
        .then(function(newSubscription) {
          return newSubscription;
        });
      });
    })
    .then(function(subscription) {
      var key = subscription.getKey ? subscription.getKey('p256dh') : '';

      machineName = domMachineName.value;

      fetch('./register', {
        method: 'post',
        headers: {
          'Content-type': 'application/json'
        },
        body: JSON.stringify({
          endpoint: subscription.endpoint,
          key: key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key))) : '',
          machineId: machineId,
          token: domTokenInput.value,
          name: machineName
        }),
      })
      .then(function(response) {
        response.json()
        .then(function(body) {
          var token = body.token;
          if (response.ok) {
            localforage.setItem('token', token);
            localforage.setItem('machineName', machineName);
            domShowMachineName.textContent = machineName || machineId;
            domToken.textContent = token;
            drawBarcode(token);
            showSection('unregistrationForm');
            showMachines(body.machines);
          } else {
            alert('Error: ' + token);
          }
        });
      });
    });
  });
}

domRegister.onclick = register;

var sections = ['registrationForm', 'unregistrationForm', 'unsupported'];
function showSection(section) {
  for (var index = 0; index < sections.length; index++) {
    if (sections[index] === section) {
      document.getElementById(section).style.display = 'block';
    } else {
      document.getElementById(sections[index]).style.display = 'none';
    }
  }
}

domUnregister.onclick = function() {
  unregisterMachine(machineId)
  .then(function(response) {
    domToken.textContent = '';
    domTokenBarcode.style.display = 'none';
    showSection('registrationForm');
    localforage.removeItem('token');
  });
};

function unregisterMachine(mId) {
  return localforage.getItem('token')
  .then(function(token) {
    return fetch('./unregisterMachine', {
      method: 'post',
      headers: {
        'Content-type': 'application/json'
      },
      body: JSON.stringify({
        token: token,
        machineId: mId
      }),
    });
  });
}

// generate a random string (default: 40)
function makeId(length) {
  var arr = new Uint8Array((length || 40) / 2);
  window.crypto.getRandomValues(arr);
  return [].map.call(arr, function(n) { return n.toString(16); }).join("");
}

// create DOM Element for a device
function showMachine(mId, device) {
  var li = document.createElement('li');
  var a = document.createElement('a');
  li.textContent = (device.name || mId) + ' ';
  a.textContent = '[x]';
  a.onclick = function() {
    unregisterMachine(mId)
    .then(function(response) {
      response.json()
      .then(function(body) {
        showMachines(body.machines);
      });
    });
  };
  li.appendChild(a);
  domMachines.appendChild(li);
}

// clean machine list and call showMachine on each machine from the list
function showMachines(deviceList) {
  // delete everything in the list
  domMachines.innerHTML = "";
  // create the list
  for (var machineId in deviceList) {
    showMachine(machineId, deviceList[machineId]);
  }
}

// load machines from the server
function getMachines(token) {
  fetch('/devices/' + token)
  .then(function(response) {
    response.json()
    .then(function(body) {
      showMachines(body.machines);
    });
  });
}

if (navigator.serviceWorker) {
  navigator.serviceWorker.register('service-worker.js');
} else {
  showSection('unsupported');
}

window.onload = function() {
  if (!navigator.serviceWorker) {
    return;
  }

  localforage.getItem('machineId')
  .then(function(id) {
    if (id) {
      machineId = id;
    } else {
      machineId = makeId(20);
      localforage.setItem('machineId', machineId);
    }
  })
  .then(function() {
    localforage.getItem('token')
    .then(function(token) {
      if (token) {
        showSection('unregistrationForm');
        domToken.textContent = token;
        drawBarcode(token);
        localforage.getItem('machineName')
        .then(function(mName) {
          machineName = mName;
          domShowMachineName.textContent = machineName || machineId;
        });
        getMachines(token);
      } else {
        showSection('registrationForm');
      }
    });
  });
};
<commit_msg>Increase barcode size<commit_after>var machineId;
var machineName;

// all static DOM elements
var domShowTokenInput = document.getElementById('showTokenInput');
var domTokenInput = document.getElementById('tokenInput');
var domTokenLabel = document.getElementById('tokenLabel');
var domTokenInteractive = document.getElementById('interactive');
var domMachineName = document.getElementById('machineName');
var domToken = document.getElementById('token');
var domTokenBarcode = document.getElementById('tokenBarcode');
var domRegister = document.getElementById('register');
var domUnregister = document.getElementById('unregister');
var domMachines = document.getElementById('machines');
var domShowMachineName = document.getElementById('showMachineName');

domShowTokenInput.onclick = function() {
  domTokenInput.style.display = 'block';
  domTokenLabel.style.display = 'block';
  this.style.display = 'none';

  Quagga.init({}, function(err) {
    if (err) {
      console.error(err);
      return;
    }

    Quagga.start();
  });

  Quagga.onDetected(function(result) {
    domTokenInput.value = result.codeResult.code;
    Quagga.stop();
    domTokenInteractive.style.display = 'none';
    window.alert('Token detected!');
  });
};

domMachineName.placeholder = window.navigator.userAgent;

function drawBarcode(text) {
  var bw = new BWIPJS;

  bw.bitmap(new Bitmap);

  bw.scale(2, 2);

  bw.push(text);
  bw.push({
    includetext: true,
  });

  bw.call('code128', function(e) {
    if (e) {
      if (typeof e === 'string') {
        console.error(e);
      } else if (e.stack) {
        console.error(e.message + '\r\n' + e.stack);
      } else {
        var s = '';
        if (e.fileName) {
          s += e.fileName + ' ';
        }
        if (e.lineNumber) {
          s += '[line ' + e.lineNumber + '] ';
        }
        console.error(s + (s ? ': ' : '') + e.message);
      }
    } else {
      bw.bitmap().show('tokenBarcode', 'N');
      domTokenBarcode.style.display = 'block';
    }
  });
}

function register() {
  localforage.getItem('token')
  .then(function(token) {
    if (token) {
      return;
    }

    navigator.serviceWorker.ready
    .then(function(registration) {
      return registration.pushManager.getSubscription()
      .then(function(subscription) {
        if (subscription) {
          return subscription;
        }

        return registration.pushManager.subscribe({ userVisibleOnly: true })
        .then(function(newSubscription) {
          return newSubscription;
        });
      });
    })
    .then(function(subscription) {
      var key = subscription.getKey ? subscription.getKey('p256dh') : '';

      machineName = domMachineName.value;

      fetch('./register', {
        method: 'post',
        headers: {
          'Content-type': 'application/json'
        },
        body: JSON.stringify({
          endpoint: subscription.endpoint,
          key: key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key))) : '',
          machineId: machineId,
          token: domTokenInput.value,
          name: machineName
        }),
      })
      .then(function(response) {
        response.json()
        .then(function(body) {
          var token = body.token;
          if (response.ok) {
            localforage.setItem('token', token);
            localforage.setItem('machineName', machineName);
            domShowMachineName.textContent = machineName || machineId;
            domToken.textContent = token;
            drawBarcode(token);
            showSection('unregistrationForm');
            showMachines(body.machines);
          } else {
            alert('Error: ' + token);
          }
        });
      });
    });
  });
}

domRegister.onclick = register;

var sections = ['registrationForm', 'unregistrationForm', 'unsupported'];
function showSection(section) {
  for (var index = 0; index < sections.length; index++) {
    if (sections[index] === section) {
      document.getElementById(section).style.display = 'block';
    } else {
      document.getElementById(sections[index]).style.display = 'none';
    }
  }
}

domUnregister.onclick = function() {
  unregisterMachine(machineId)
  .then(function(response) {
    domToken.textContent = '';
    domTokenBarcode.style.display = 'none';
    showSection('registrationForm');
    localforage.removeItem('token');
  });
};

function unregisterMachine(mId) {
  return localforage.getItem('token')
  .then(function(token) {
    return fetch('./unregisterMachine', {
      method: 'post',
      headers: {
        'Content-type': 'application/json'
      },
      body: JSON.stringify({
        token: token,
        machineId: mId
      }),
    });
  });
}

// generate a random string (default: 40)
function makeId(length) {
  var arr = new Uint8Array((length || 40) / 2);
  window.crypto.getRandomValues(arr);
  return [].map.call(arr, function(n) { return n.toString(16); }).join("");
}

// create DOM Element for a device
function showMachine(mId, device) {
  var li = document.createElement('li');
  var a = document.createElement('a');
  li.textContent = (device.name || mId) + ' ';
  a.textContent = '[x]';
  a.onclick = function() {
    unregisterMachine(mId)
    .then(function(response) {
      response.json()
      .then(function(body) {
        showMachines(body.machines);
      });
    });
  };
  li.appendChild(a);
  domMachines.appendChild(li);
}

// clean machine list and call showMachine on each machine from the list
function showMachines(deviceList) {
  // delete everything in the list
  domMachines.innerHTML = "";
  // create the list
  for (var machineId in deviceList) {
    showMachine(machineId, deviceList[machineId]);
  }
}

// load machines from the server
function getMachines(token) {
  fetch('/devices/' + token)
  .then(function(response) {
    response.json()
    .then(function(body) {
      showMachines(body.machines);
    });
  });
}

if (navigator.serviceWorker) {
  navigator.serviceWorker.register('service-worker.js');
} else {
  showSection('unsupported');
}

window.onload = function() {
  if (!navigator.serviceWorker) {
    return;
  }

  localforage.getItem('machineId')
  .then(function(id) {
    if (id) {
      machineId = id;
    } else {
      machineId = makeId(20);
      localforage.setItem('machineId', machineId);
    }
  })
  .then(function() {
    localforage.getItem('token')
    .then(function(token) {
      if (token) {
        showSection('unregistrationForm');
        domToken.textContent = token;
        drawBarcode(token);
        localforage.getItem('machineName')
        .then(function(mName) {
          machineName = mName;
          domShowMachineName.textContent = machineName || machineId;
        });
        getMachines(token);
      } else {
        showSection('registrationForm');
      }
    });
  });
};
<|endoftext|>


<commit_before>function show_Modal(title, content, type_class){
    $('#modContent').html('
\
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>\

'+title+'
\

'+content);
	$('#modFrm').modal();
}

function errShow(errContent) {
    show_Modal('Ошибка', '
'+errContent+'

<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>
', 'warning');
}

$(document).ajaxError(function (ev, jqXHR, ajaxSettings, thrownError) {
	//loaderShow(false);
	errShow(jqXHR.status + ': ' + jqXHR.statusText);
});

// SelectAjax
(function ($) {
	$.fn.selectajax = function (opt) {

		var settings = $.extend( {
			url		 : '/api'
		}, opt);

		var selectbtn = this.children('button.selectajax-btn');
		var selectinp = this.children('input[type=text].selectajax-inp');
		var selecthid = this.children('input[type=hidden].selectajax-hid');
		var selectul  = this.children('ul.selectajax-ul');

		var selectajax_click = function(){
			var a = $(this).children('a');
			var hr = a.attr('href');
			var tx = a.text();
			selecthid.val(hr.substr(1));
			console.debug(tx);
			selectbtn.text(tx).removeClass('hidden');
			selectinp.addClass('hidden').val(tx);
		};

		var refresh = function(){
			$.getJSON(settings.url, {'s': this.value}, function (r) {
				selectul.empty();
				r.forEach(function (o) {
					var li = $('
' + o.name + ": " + o.fio + '
');
					selectul.append(li);
					li.on('click', selectajax_click)
				});
			});
		};

		selectinp.on('keyup', refresh).on('focusin',refresh);

		selectbtn.on('click',function(){
			selectinp.removeClass('hidden');
			$(this).addClass('hidden');
			selectinp.focus().trigger('click.bs.dropdown');
			return false;
		});

		selectul.children().on('click', selectajax_click);
	};
})(jQuery);

$(document).ready(function () {

	// ajax tabs
	$('.nav-tabs a').on('show.bs.tab', function (e) {
		var ct = $(e.target).attr('href');
		var remoteUrl = $(this).attr('data-tab-remote');
		if (remoteUrl !== '') {
			$(ct).load(remoteUrl);
		}
	});

	// Live html5 image preview
	if (window.File && window.FileReader && window.FileList && window.Blob) {
		$('input[type=file].live_review').on('change', function () {
			var reader = new FileReader();
			var img = $('img[alt=ava]')[0];
			reader.readAsDataURL(this.files[0]);
			reader.onload = function (e) {
				img.src = e.target.result;
			}
		});
	} else {
		var t = "Ваш браузер не поддерживает FileAPI";
		console.warn(t);
		alert(t);
	}

	// Validate inputs of form
	$('input.form-control[pattern]').keyup(function () {
		var pr = $(this).closest('.form-group-sm,.form-group');
		pr.removeClass('has-success');
		pr.removeClass('has-error');
		pr.find('.form-control-feedback').remove();
		if ($(this)[0].checkValidity()) {
			pr.addClass('has-success');
			$(this).after('');
		} else {
			pr.addClass('has-error');
			$(this).after('');
		}
	});

	$('div.selectajax').selectajax({
		url: '/abons/api/abon_filter'
	});

	$('[data-toggle=offcanvas]').click(function () {
		$('.row-offcanvas').toggleClass('active');
	});
});
<commit_msg>Подправил функции подального окна<commit_after>function show_ModalMyContent(content){
    $('#modContent').html(content);
	$('#modFrm').modal();
}
function show_Modal(title, content, type_class){
var cnt='
' +
            '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' +
            '
'+title+'
' +
        '
' +
        '
'+content+'
' +
        '
<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>
';
	show_ModalMyContent(cnt);
}

function showErr(errContent) {show_Modal('Ошибка', errContent, 'warning');}
function showSuccess(errContent) {show_Modal('Успешно', errContent, 'success');}
function showPrimary(errContent) {show_Modal('Внимание!', errContent, 'primary');}

$(document).ajaxError(function (ev, jqXHR, ajaxSettings, thrownError) {
	//loaderShow(false);
	showErr(jqXHR.status + ': ' + jqXHR.statusText);
});

// SelectAjax
(function ($) {
	$.fn.selectajax = function (opt) {

		var settings = $.extend( {
			url		 : '/api'
		}, opt);

		var selectbtn = this.children('button.selectajax-btn');
		var selectinp = this.children('input[type=text].selectajax-inp');
		var selecthid = this.children('input[type=hidden].selectajax-hid');
		var selectul  = this.children('ul.selectajax-ul');

		var selectajax_click = function(){
			var a = $(this).children('a');
			var hr = a.attr('href');
			var tx = a.text();
			selecthid.val(hr.substr(1));
			console.debug(tx);
			selectbtn.text(tx).removeClass('hidden');
			selectinp.addClass('hidden').val(tx);
		};

		var refresh = function(){
			$.getJSON(settings.url, {'s': this.value}, function (r) {
				selectul.empty();
				r.forEach(function (o) {
					var li = $('
' + o.name + ": " + o.fio + '
');
					selectul.append(li);
					li.on('click', selectajax_click)
				});
			});
		};

		selectinp.on('keyup', refresh).on('focusin',refresh);

		selectbtn.on('click',function(){
			selectinp.removeClass('hidden');
			$(this).addClass('hidden');
			selectinp.focus().trigger('click.bs.dropdown');
			return false;
		});

		selectul.children().on('click', selectajax_click);
	};
})(jQuery);

$(document).ready(function () {

	// ajax tabs
	$('.nav-tabs a').on('show.bs.tab', function (e) {
		var ct = $(e.target).attr('href');
		var remoteUrl = $(this).attr('data-tab-remote');
		if (remoteUrl !== '') {
			$(ct).load(remoteUrl);
		}
	});

	// Live html5 image preview
	if (window.File && window.FileReader && window.FileList && window.Blob) {
		$('input[type=file].live_review').on('change', function () {
			var reader = new FileReader();
			var img = $('img[alt=ava]')[0];
			reader.readAsDataURL(this.files[0]);
			reader.onload = function (e) {
				img.src = e.target.result;
			}
		});
	} else {
		var t = "Ваш браузер не поддерживает FileAPI";
		console.warn(t);
		alert(t);
	}

	// Validate inputs of form
	$('input.form-control[pattern]').keyup(function () {
		var pr = $(this).closest('.form-group-sm,.form-group');
		pr.removeClass('has-success');
		pr.removeClass('has-error');
		pr.find('.form-control-feedback').remove();
		if ($(this)[0].checkValidity()) {
			pr.addClass('has-success');
			$(this).after('');
		} else {
			pr.addClass('has-error');
			$(this).after('');
		}
	});

	$('div.selectajax').selectajax({
		url: '/abons/api/abon_filter'
	});

	$('[data-toggle=offcanvas]').click(function () {
		$('.row-offcanvas').toggleClass('active');
	});
});
<|endoftext|>


<commit_before>"use strict";

const SimpleBar = require("simplebar/dist/simplebar");

// What, if anything, obscures the home tab?

exports.replace_emoji_with_text = function (element) {
    element.find(".emoji").replaceWith(function () {
        if ($(this).is("img")) {
            return $(this).attr("alt");
        }
        return $(this).text();
    });
};

exports.get_content_element = function (element_selector) {
    const element = element_selector.expectOne()[0];
    const sb = SimpleBar.instances.get(element);
    if (sb) {
        return $(sb.getContentElement());
    }
    return element_selector;
};

exports.get_scroll_element = function (element_selector) {
    const element = element_selector.expectOne()[0];
    const sb = SimpleBar.instances.get(element);
    if (sb) {
        return $(sb.getScrollElement());
    } else if ("simplebar" in element.dataset) {
        // The SimpleBar mutation observer hasn’t processed this element yet.
        // Create the SimpleBar early in case we need to add event listeners.
        return $(new SimpleBar(element).getScrollElement());
    }
    return element_selector;
};

exports.reset_scrollbar = function (element_selector) {
    const element = element_selector.expectOne()[0];
    const sb = SimpleBar.instances.get(element);
    if (sb) {
        sb.getScrollElement().scrollTop = 0;
    } else {
        element.scrollTop = 0;
    }
};

function update_message_in_all_views(message_id, callback) {
    for (const list of [message_list.all, home_msg_list, message_list.narrowed]) {
        if (list === undefined) {
            continue;
        }
        const row = list.get_row(message_id);
        if (row === undefined) {
            // The row may not exist, e.g. if you do an action on a message in
            // a narrowed view
            continue;
        }
        callback(row);
    }
}

exports.show_error_for_unsupported_platform = function () {
    // Check if the user is using old desktop app
    if (typeof bridge !== "undefined") {
        // We don't internationalize this string because it is long,
        // and few users will have both the old desktop app and an
        // internationalized version of Zulip anyway.
        const error =
            "Hello! You're using the unsupported old Zulip desktop app," +
            " which is no longer developed. We recommend switching to the new, " +
            "modern desktop app, which you can download at " +
            "zulip.com/apps.";

        ui_report.generic_embed_error(error);
    }
};

exports.update_starred_view = function (message_id, new_value) {
    const starred = new_value;

    // Avoid a full re-render, but update the star in each message
    // table in which it is visible.
    update_message_in_all_views(message_id, (row) => {
        const elt = row.find(".star");
        const star_container = row.find(".star_container");
        if (starred) {
            elt.addClass("fa-star").removeClass("fa-star-o");
            star_container.removeClass("empty-star");
        } else {
            elt.removeClass("fa-star").addClass("fa-star-o");
            star_container.addClass("empty-star");
        }
        const title_state = starred ? i18n.t("Unstar") : i18n.t("Star");
        elt.attr("title", i18n.t("__starred_status__ this message", {starred_status: title_state}));
    });
};

exports.show_message_failed = function (message_id, failed_msg) {
    // Failed to send message, so display inline retry/cancel
    update_message_in_all_views(message_id, (row) => {
        const failed_div = row.find(".message_failed");
        failed_div.toggleClass("notvisible", false);
        failed_div.find(".failed_text").attr("title", failed_msg);
    });
};

exports.show_failed_message_success = function (message_id) {
    // Previously failed message succeeded
    update_message_in_all_views(message_id, (row) => {
        row.find(".message_failed").toggleClass("notvisible", true);
    });
};

exports.get_hotkey_deprecation_notice = function (originalHotkey, replacementHotkey) {
    return i18n.t(
        'We\'ve replaced the "__originalHotkey__" hotkey with "__replacementHotkey__" ' +
            "to make this common shortcut easier to trigger.",
        {originalHotkey, replacementHotkey},
    );
};

let shown_deprecation_notices = [];
exports.maybe_show_deprecation_notice = function (key) {
    let message;
    const isCmdOrCtrl = common.has_mac_keyboard() ? "Cmd" : "Ctrl";
    if (key === "C") {
        message = exports.get_hotkey_deprecation_notice("C", "x");
    } else if (key === "*") {
        message = exports.get_hotkey_deprecation_notice("*", isCmdOrCtrl + " + s");
    } else {
        blueslip.error("Unexpected deprecation notice for hotkey:", key);
        return;
    }

    // Here we handle the tracking for showing deprecation notices,
    // whether or not local storage is available.
    if (localstorage.supported()) {
        const notices_from_storage = JSON.parse(localStorage.getItem("shown_deprecation_notices"));
        if (notices_from_storage !== null) {
            shown_deprecation_notices = notices_from_storage;
        } else {
            shown_deprecation_notices = [];
        }
    }

    if (!shown_deprecation_notices.includes(key)) {
        $("#deprecation-notice-modal").modal("show");
        $("#deprecation-notice-message").text(message);
        $("#close-deprecation-notice").trigger("focus");
        shown_deprecation_notices.push(key);
        if (localstorage.supported()) {
            localStorage.setItem(
                "shown_deprecation_notices",
                JSON.stringify(shown_deprecation_notices),
            );
        }
    }
};

// Save the compose content cursor position and restore when we
// shift-tab back in (see hotkey.js).
let saved_compose_cursor = 0;

exports.set_compose_textarea_handlers = function () {
    $("#compose-textarea").on("blur", function () {
        saved_compose_cursor = $(this).caret();
    });

    // on the end of the modified-message fade in, remove the fade-in-message class.
    const animationEnd = "webkitAnimationEnd oanimationend msAnimationEnd animationend";
    $("body").on(animationEnd, ".fade-in-message", function () {
        $(this).removeClass("fade-in-message");
    });
};

exports.restore_compose_cursor = function () {
    $("#compose-textarea").trigger("focus").caret(saved_compose_cursor);
};

exports.initialize = function () {
    exports.set_compose_textarea_handlers();
    exports.show_error_for_unsupported_platform();
};

window.ui = exports;
<commit_msg>Tooltip: edited tooltip string to add consistency in static/js/ui.js.<commit_after>"use strict";

const SimpleBar = require("simplebar/dist/simplebar");

// What, if anything, obscures the home tab?

exports.replace_emoji_with_text = function (element) {
    element.find(".emoji").replaceWith(function () {
        if ($(this).is("img")) {
            return $(this).attr("alt");
        }
        return $(this).text();
    });
};

exports.get_content_element = function (element_selector) {
    const element = element_selector.expectOne()[0];
    const sb = SimpleBar.instances.get(element);
    if (sb) {
        return $(sb.getContentElement());
    }
    return element_selector;
};

exports.get_scroll_element = function (element_selector) {
    const element = element_selector.expectOne()[0];
    const sb = SimpleBar.instances.get(element);
    if (sb) {
        return $(sb.getScrollElement());
    } else if ("simplebar" in element.dataset) {
        // The SimpleBar mutation observer hasn’t processed this element yet.
        // Create the SimpleBar early in case we need to add event listeners.
        return $(new SimpleBar(element).getScrollElement());
    }
    return element_selector;
};

exports.reset_scrollbar = function (element_selector) {
    const element = element_selector.expectOne()[0];
    const sb = SimpleBar.instances.get(element);
    if (sb) {
        sb.getScrollElement().scrollTop = 0;
    } else {
        element.scrollTop = 0;
    }
};

function update_message_in_all_views(message_id, callback) {
    for (const list of [message_list.all, home_msg_list, message_list.narrowed]) {
        if (list === undefined) {
            continue;
        }
        const row = list.get_row(message_id);
        if (row === undefined) {
            // The row may not exist, e.g. if you do an action on a message in
            // a narrowed view
            continue;
        }
        callback(row);
    }
}

exports.show_error_for_unsupported_platform = function () {
    // Check if the user is using old desktop app
    if (typeof bridge !== "undefined") {
        // We don't internationalize this string because it is long,
        // and few users will have both the old desktop app and an
        // internationalized version of Zulip anyway.
        const error =
            "Hello! You're using the unsupported old Zulip desktop app," +
            " which is no longer developed. We recommend switching to the new, " +
            "modern desktop app, which you can download at " +
            "zulip.com/apps.";

        ui_report.generic_embed_error(error);
    }
};

exports.update_starred_view = function (message_id, new_value) {
    const starred = new_value;

    // Avoid a full re-render, but update the star in each message
    // table in which it is visible.
    update_message_in_all_views(message_id, (row) => {
        const elt = row.find(".star");
        const star_container = row.find(".star_container");
        if (starred) {
            elt.addClass("fa-star").removeClass("fa-star-o");
            star_container.removeClass("empty-star");
        } else {
            elt.removeClass("fa-star").addClass("fa-star-o");
            star_container.addClass("empty-star");
        }
        const title_state = starred ? i18n.t("Unstar") : i18n.t("Star");
        elt.attr(
            "title",
            i18n.t("__starred_status__ this message (Ctrl + s)", {starred_status: title_state}),
        );
    });
};

exports.show_message_failed = function (message_id, failed_msg) {
    // Failed to send message, so display inline retry/cancel
    update_message_in_all_views(message_id, (row) => {
        const failed_div = row.find(".message_failed");
        failed_div.toggleClass("notvisible", false);
        failed_div.find(".failed_text").attr("title", failed_msg);
    });
};

exports.show_failed_message_success = function (message_id) {
    // Previously failed message succeeded
    update_message_in_all_views(message_id, (row) => {
        row.find(".message_failed").toggleClass("notvisible", true);
    });
};

exports.get_hotkey_deprecation_notice = function (originalHotkey, replacementHotkey) {
    return i18n.t(
        'We\'ve replaced the "__originalHotkey__" hotkey with "__replacementHotkey__" ' +
            "to make this common shortcut easier to trigger.",
        {originalHotkey, replacementHotkey},
    );
};

let shown_deprecation_notices = [];
exports.maybe_show_deprecation_notice = function (key) {
    let message;
    const isCmdOrCtrl = common.has_mac_keyboard() ? "Cmd" : "Ctrl";
    if (key === "C") {
        message = exports.get_hotkey_deprecation_notice("C", "x");
    } else if (key === "*") {
        message = exports.get_hotkey_deprecation_notice("*", isCmdOrCtrl + " + s");
    } else {
        blueslip.error("Unexpected deprecation notice for hotkey:", key);
        return;
    }

    // Here we handle the tracking for showing deprecation notices,
    // whether or not local storage is available.
    if (localstorage.supported()) {
        const notices_from_storage = JSON.parse(localStorage.getItem("shown_deprecation_notices"));
        if (notices_from_storage !== null) {
            shown_deprecation_notices = notices_from_storage;
        } else {
            shown_deprecation_notices = [];
        }
    }

    if (!shown_deprecation_notices.includes(key)) {
        $("#deprecation-notice-modal").modal("show");
        $("#deprecation-notice-message").text(message);
        $("#close-deprecation-notice").trigger("focus");
        shown_deprecation_notices.push(key);
        if (localstorage.supported()) {
            localStorage.setItem(
                "shown_deprecation_notices",
                JSON.stringify(shown_deprecation_notices),
            );
        }
    }
};

// Save the compose content cursor position and restore when we
// shift-tab back in (see hotkey.js).
let saved_compose_cursor = 0;

exports.set_compose_textarea_handlers = function () {
    $("#compose-textarea").on("blur", function () {
        saved_compose_cursor = $(this).caret();
    });

    // on the end of the modified-message fade in, remove the fade-in-message class.
    const animationEnd = "webkitAnimationEnd oanimationend msAnimationEnd animationend";
    $("body").on(animationEnd, ".fade-in-message", function () {
        $(this).removeClass("fade-in-message");
    });
};

exports.restore_compose_cursor = function () {
    $("#compose-textarea").trigger("focus").caret(saved_compose_cursor);
};

exports.initialize = function () {
    exports.set_compose_textarea_handlers();
    exports.show_error_for_unsupported_platform();
};

window.ui = exports;
<|endoftext|>


<commit_before>$(document).ready(function () {

	$(" .container ").hover(function(){
		$(this).addClass("hover_emp");
		//$(this).append("
Just a paragraph.
");
	}, function() {
		$(this).removeClass("hover_emp");
		//$('p').remove(".prompt");
	});

	$('p').click(function() {
		//$(this).append( $("#comment") ).css('visibility: visible');
		$(this).append("
<input type='text' name='comment' />");
		$(this).unbind('click');

		//<input type='button' value='Insert' />
		//$('#tooltip').css({'position': 'absolute', 'top': $('p').position().top + 'px', 'left': $('p').position().left + 'px'});
	});

	$(document).keypress(function(e) {
    	if(e.which == 13) {
        	var toAdd = $('input[name=comment]').val();
			$('p').append('
' + toAdd + '
');
    	}
	});

	$(document).on('click','.item', function() {
        $(this).remove();
    });

	$(".calculator").hide().fadeIn(1000);

	$(".calculator").resizable({ animate: true });;

	$(".calculator").dblclick(function(){
        $(this).html("
42
").fadeOut( 1000 );
    });

    $(document).keydown(function(key) {
        switch(parseInt(key.which,10)) {
			case 65:
				$(".calculator").animate({left: "-=10px"}, 'fast');
				break;
			case 83:
				$(".calculator").animate({up: "-=10px"}, 'fast');
				break;
			case 87:
				$(".calculator").animate({up: "+=10px"}, 'fast');
				break;
			case 68:
				$(".calculator").animate({left: "+=10px"}, 'fast');
				break;
			default:
				break;
		}
	});
});<commit_msg>test commenting more<commit_after>$(document).ready(function () {

	$(" .container ").hover(function(){
		$(this).addClass("hover_emp");
		//$(this).append("
Just a paragraph.
");
	}, function() {
		$(this).removeClass("hover_emp");
		//$('p').remove(".prompt");
	});

	$('p').click(function() {
		//$(this).append( $("#comment") ).css('visibility: visible');
		$(this).append("
<input type='text' name='comment' />");
		$(this).append("<form method='post'>Comments:
<textarea name='comments' id='comments'>Hey... say something!</textarea>
<input type='submit' value='Submit' /></form>")
		$(this).unbind('click');

		//<input type='button' value='Insert' />
		//$('#tooltip').css({'position': 'absolute', 'top': $('p').position().top + 'px', 'left': $('p').position().left + 'px'});
	});

	$(document).keypress(function(e) {
    	if(e.which == 13) {
        	var toAdd = $('input[name=comment]').val();
			$('p').append('
' + toAdd + '
');
    	}
	});

	$(document).on('click','.item', function() {
        $(this).remove();
    });

	$(".calculator").hide().fadeIn(1000);

	$(".calculator").resizable({ animate: true });;

	$(".calculator").dblclick(function(){
        $(this).html("
42
").fadeOut( 1000 );
    });

    $(document).keydown(function(key) {
        switch(parseInt(key.which,10)) {
			case 65:
				$(".calculator").animate({left: "-=10px"}, 'fast');
				break;
			case 83:
				$(".calculator").animate({up: "-=10px"}, 'fast');
				break;
			case 87:
				$(".calculator").animate({up: "+=10px"}, 'fast');
				break;
			case 68:
				$(".calculator").animate({left: "+=10px"}, 'fast');
				break;
			default:
				break;
		}
	});
});<|endoftext|>