<commit_before>/*
 * Module's settings and public API.
 */
var storage = {
  storageType: 'localStorage',
  async: true,
};
storage.works = storageSupported(storage.storageType);
var storageTypes = {
  'localStorage': localStorage,
  'sessionStorage': sessionStorage
};
var defaultStorage = storageTypes[storage.storageType];
var setItem = defaultStorage.setItem.bind(defaultStorage);
var getItem = defaultStorage.getItem.bind(defaultStorage);
var removeItem = defaultStorage.removeItem.bind(defaultStorage);

/*
 * Check browser support for storage
 *
 * @param {String} storageType
 * @return {Boolean} support for storage
 * @api private
 */
function storageSupported(storageType) {
  try {
    return storageType in window && window[storageType] !== null;
  } catch(e) {
    return false;
  }
}

/*
 * Functions for accessing storage:
 * get, getSync, getMulti
 * set, setSync, setMulti
 * remove, removeSync, removeMulti
 */

/*
 * Runs function asynchronously.
 *
 * Usage:
 * > async(localStorage.setItem)
       .run('hello', 'world', function() {})
 * > var result = async(localStorage.getItem)
 *     .run('hello', function(value){console.log(result)});
 *
 * @param {Function} synchronous function
 * @return {Object} asyncFunc
 * @api private
 */
function async(func) {
  var NOTSTARTED = 0, PENDING = 1, SUCCESS = 2, FAIL = -1;
  var asyncFunc = {};
  asyncFunc.status = NOTSTARTED;
  asyncFunc.run = function doAsyncFunc() {
    var args = Array.prototype.slice.call(arguments);
    var callback = args.pop();
    asyncFunc.status = PENDING;
    // Pushes it to background with 0ms delay
    var funcToBackground = setTimeout(function() {
      try {
        var result = func.apply(this, args);
        asyncFunc.status = SUCCESS;
        asyncFunc.result = result;
      } catch(e) {
        asyncFunc.status = FAIL;
        asyncFunc.result = e;
      }
    }, 0);
    // Runs continuously checking for status of asyncFunc
    // Runs after-task attached at asyncFunc.done
    var asyncFuncChecker = setInterval(function() {
      var status = asyncFunc.status;
      if (status === SUCCESS || status === FAIL) {
        clearInterval(asyncFuncChecker);
        callback(asyncFunc.result);
      }
    }, 0);
    // Attached to returned asyncFunc.done
    return asyncFunc;
  };
  return asyncFunc;
}

/*
 * Goes through settings and make changes to module.
 *
 * @api private
 */
(function parseSettings() {
  // Bail if it doesn't work, no fallback
  if (!storage.works) { storage = undefined; }
})();

/*
 * Attempt to parse string for JSON.
 *
 * @return {String} if not JSON
 * @return {Object} if able to JSON.parse
 * @api private
 */
function parseIfPossible(obj) {
  try {
    return JSON.parse(obj);
  } catch(e) {
    return obj;
  }
}

/*
 * Attempt to stringify JSON.
 *
 * @return {String} if serializable
 * @return {Object} if JSON.stringify fails
 * @api private
 */
function stringifyIfPossible(obj) {
  try {
    return JSON.stringify(obj);
  } catch(e) {
    return obj;
  }
}

/*
 * Wrapper function for localStorage.setItem
 * which is asynchronous and deserializes to string.
 * Callback accepts no parameters.
 *
 * @param {String} key
 * @param {Object} value
 * @param {Function} callback
 * @api public
 */
storage.set = function setStorage(key, value, callback) {
  value = stringifyIfPossible(value);
  async(setItem).run(key, value, function(){
    callback();
  });
};

/*
 * Wrapper function for localStorage.setItem
 * which just deserializes to string.
 *
 * @param {String} key
 * @param {Object} value
 * @api public
 */
storage.setSync = function(key, value) {
  defaultStorage.setItem(key, stringifyIfPossible(value));
};

/*
 * Iterates through keyValue Object and does storage.set.
 * Callback accepts no parameters.
 *
 * @param {Object} keyValue
 * @param {Function} callback
 * @api public
 */
storage.setMulti = function(keyValue, callback) {
  var keys = Object.keys(keyValue);
  var counter = 0;
  function incrementCounter() { counter++; }
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var value = keyValue[key];
    storage.set(key, value, incrementCounter);
  }
  var counterChecker = setInterval(function() {
    if (counter === keys.length) {
      clearInterval(counterChecker);
      callback();
    }
  }, 0);
};

/*
 * Wrapper function for localStorage.getItem
 * which is asynchronous and serializes to JSON.
 * Callback accepts value as parameter.
 *
 * @param {String} key
 * @param {Function} callback with value passed
 *   @param {Object} value
 * @api public
 */
storage.get = function getStorage(key, callback) {
  async(getItem).run(key, function(value) {
    callback(parseIfPossible(value));
  });
};

/*
 * Wrapper function for localStorage.setItem
 * which just deserializes to string.
 *
 * @param {String} key
 * @param {Object} value
 * @api public
 */
storage.getSync = function(key) {
  return parseIfPossible(defaultStorage.getItem(key));
};

/*
 * Iterates through keys and does storage.get.
 * Callback accepts array of values as parameter.
 *
 * @param {Array} keys
 * @param {Function} callback
 *   @param {Array} values
 * @api public
 */
storage.getMulti = function getMultiStorage(keys, callback) {
  var values = [];
  function rememberValue(value) {
    values.push(parseIfPossible(value));
  }
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    storage.get(key, rememberValue);
  }
  // Continuously check for function completion
  var counterChecker = setInterval(function() {
    if (values.length === keys.length) {
      clearInterval(counterChecker);
      callback(values);
    }
  }, 0);
};

/*
 * Wrapper function for localStorage.removeItem
 * which is asynchronous.
 * Callback takes no parameters.
 *
 * @param {String} key
 * @param {Function} callback
 * @api public
 */
storage.remove = function removeStorage(key, callback) {
  async(removeItem).run(key, function() {
    callback();
  });
};

/*
 * Wrapper function for localStorage.removeItem
 * which is behaves exactly the same.
 *
 * @param {String} key
 * @api public
 */
storage.removeSync = function removeSyncStorage(key) {
  defaultStorage.removeItem(key);
};

/*
 * Iterates through keys and does storage.remove.
 * Callback accepts array of values as parameter.
 *
 * @param {Array} keys
 * @param {Function} callback
 * @api public
 */
storage.removeMulti = function removeMultiStorage(keys, callback) {
  var counter = 0;
  function incrementCounter() { counter++; }
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    storage.remove(key, incrementCounter);
  }
  var counterChecker = setInterval(function() {
    if (counter === keys.length) {
      clearInterval(counterChecker);
      callback();
    }
  });
};

/*
 * Functions for space management:
 * size, left
 */

var MAX_SIZE = 1024 * 1024 * 5;  // 5 MB is default size of storage

/*
 * Iterates through keys and values, records their lengths.
 *
 * @api public
 */
storage.size = (function getStorageSize(callback) {
  var keys = Object.keys(defaultStorage);
  var keysLength = keys.join('').length;
  var value, values = [];
  for (var i = 0; i < keys.length; i++) {
    value = defaultStorage.getItem(keys[i]);
    values.push(value);
  }
  var valuesLength = values.join('').length;
  return keysLength + valuesLength;
})();

/*
 * Performs subtraction between MAX_SIZE and storage.size
 * Callback accepts storage left as param
 *
 * @api public
 */
storage.left = MAX_SIZE - storage.size;
<commit_msg>Edited storage.size and storage.left to be functions<commit_after>/*
 * Module's settings and public API.
 */
var storage = {
  storageType: 'localStorage',
  async: true,
};
storage.works = storageSupported(storage.storageType);
var storageTypes = {
  'localStorage': localStorage,
  'sessionStorage': sessionStorage
};
var defaultStorage = storageTypes[storage.storageType];
var setItem = defaultStorage.setItem.bind(defaultStorage);
var getItem = defaultStorage.getItem.bind(defaultStorage);
var removeItem = defaultStorage.removeItem.bind(defaultStorage);

/*
 * Check browser support for storage
 *
 * @param {String} storageType
 * @return {Boolean} support for storage
 * @api private
 */
function storageSupported(storageType) {
  try {
    return storageType in window && window[storageType] !== null;
  } catch(e) {
    return false;
  }
}

/*
 * Functions for accessing storage:
 * get, getSync, getMulti
 * set, setSync, setMulti
 * remove, removeSync, removeMulti
 */

/*
 * Runs function asynchronously.
 *
 * Usage:
 * > async(localStorage.setItem)
       .run('hello', 'world', function() {})
 * > var result = async(localStorage.getItem)
 *     .run('hello', function(value){console.log(result)});
 *
 * @param {Function} synchronous function
 * @return {Object} asyncFunc
 * @api private
 */
function async(func) {
  var NOTSTARTED = 0, PENDING = 1, SUCCESS = 2, FAIL = -1;
  var asyncFunc = {};
  asyncFunc.status = NOTSTARTED;
  asyncFunc.run = function doAsyncFunc() {
    var args = Array.prototype.slice.call(arguments);
    var callback = args.pop();
    asyncFunc.status = PENDING;
    // Pushes it to background with 0ms delay
    var funcToBackground = setTimeout(function() {
      try {
        var result = func.apply(this, args);
        asyncFunc.status = SUCCESS;
        asyncFunc.result = result;
      } catch(e) {
        asyncFunc.status = FAIL;
        asyncFunc.result = e;
      }
    }, 0);
    // Runs continuously checking for status of asyncFunc
    // Runs after-task attached at asyncFunc.done
    var asyncFuncChecker = setInterval(function() {
      var status = asyncFunc.status;
      if (status === SUCCESS || status === FAIL) {
        clearInterval(asyncFuncChecker);
        callback(asyncFunc.result);
      }
    }, 0);
    // Attached to returned asyncFunc.done
    return asyncFunc;
  };
  return asyncFunc;
}

/*
 * Goes through settings and make changes to module.
 *
 * @api private
 */
(function parseSettings() {
  // Bail if it doesn't work, no fallback
  if (!storage.works) { storage = undefined; }
})();

/*
 * Attempt to parse string for JSON.
 *
 * @return {String} if not JSON
 * @return {Object} if able to JSON.parse
 * @api private
 */
function parseIfPossible(obj) {
  try {
    return JSON.parse(obj);
  } catch(e) {
    return obj;
  }
}

/*
 * Attempt to stringify JSON.
 *
 * @return {String} if serializable
 * @return {Object} if JSON.stringify fails
 * @api private
 */
function stringifyIfPossible(obj) {
  try {
    return JSON.stringify(obj);
  } catch(e) {
    return obj;
  }
}

/*
 * Wrapper function for localStorage.setItem
 * which is asynchronous and deserializes to string.
 * Callback accepts no parameters.
 *
 * @param {String} key
 * @param {Object} value
 * @param {Function} callback
 * @api public
 */
storage.set = function setStorage(key, value, callback) {
  value = stringifyIfPossible(value);
  async(setItem).run(key, value, function(){
    if (callback) callback();
  });
};

/*
 * Wrapper function for localStorage.setItem
 * which just deserializes to string.
 *
 * @param {String} key
 * @param {Object} value
 * @api public
 */
storage.setSync = function(key, value) {
  defaultStorage.setItem(key, stringifyIfPossible(value));
};

/*
 * Iterates through keyValue Object and does storage.set.
 * Callback accepts no parameters.
 *
 * @param {Object} keyValue
 * @param {Function} callback
 * @api public
 */
storage.setMulti = function(keyValue, callback) {
  var keys = Object.keys(keyValue);
  var counter = 0;
  function incrementCounter() { counter++; }
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var value = keyValue[key];
    storage.set(key, value, incrementCounter);
  }
  var counterChecker = setInterval(function() {
    if (counter === keys.length) {
      clearInterval(counterChecker);
      if (callback) callback();
    }
  }, 0);
};

/*
 * Wrapper function for localStorage.getItem
 * which is asynchronous and serializes to JSON.
 * Callback accepts value as parameter.
 *
 * @param {String} key
 * @param {Function} callback with value passed
 *   @param {Object} value
 * @api public
 */
storage.get = function getStorage(key, callback) {
  async(getItem).run(key, function(value) {
    callback(parseIfPossible(value));
  });
};

/*
 * Wrapper function for localStorage.setItem
 * which just deserializes to string.
 *
 * @param {String} key
 * @param {Object} value
 * @api public
 */
storage.getSync = function(key) {
  return parseIfPossible(defaultStorage.getItem(key));
};

/*
 * Iterates through keys and does storage.get.
 * Callback accepts array of values as parameter.
 *
 * @param {Array} keys
 * @param {Function} callback
 *   @param {Array} values
 * @api public
 */
storage.getMulti = function getMultiStorage(keys, callback) {
  var values = [];
  function rememberValue(value) {
    values.push(parseIfPossible(value));
  }
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    storage.get(key, rememberValue);
  }
  // Continuously check for function completion
  var counterChecker = setInterval(function() {
    if (values.length === keys.length) {
      clearInterval(counterChecker);
      callback(values);
    }
  }, 0);
};

/*
 * Wrapper function for localStorage.removeItem
 * which is asynchronous.
 * Callback takes no parameters.
 *
 * @param {String} key
 * @param {Function} callback
 * @api public
 */
storage.remove = function removeStorage(key, callback) {
  async(removeItem).run(key, function() {
    callback();
  });
};

/*
 * Wrapper function for localStorage.removeItem
 * which is behaves exactly the same.
 *
 * @param {String} key
 * @api public
 */
storage.removeSync = function removeSyncStorage(key) {
  defaultStorage.removeItem(key);
};

/*
 * Iterates through keys and does storage.remove.
 * Callback accepts array of values as parameter.
 *
 * @param {Array} keys
 * @param {Function} callback
 * @api public
 */
storage.removeMulti = function removeMultiStorage(keys, callback) {
  var counter = 0;
  function incrementCounter() { counter++; }
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    storage.remove(key, incrementCounter);
  }
  var counterChecker = setInterval(function() {
    if (counter === keys.length) {
      clearInterval(counterChecker);
      callback();
    }
  });
};

/*
 * Functions for space management:
 * size, left
 */

var MAX_SIZE = 1024 * 1024 * 5;  // 5 MB is default size of storage

/*
 * Iterates through keys and values, records their lengths.
 *
 * @api public
 */
storage.size = function getStorageSize() {
  var keys = Object.keys(defaultStorage);
  var keysLength = keys.join('').length;
  var value, values = [];
  for (var i = 0; i < keys.length; i++) {
    value = defaultStorage.getItem(keys[i]);
    values.push(value);
  }
  var valuesLength = values.join('').length;
  return keysLength + valuesLength;
};

/*
 * Performs subtraction between MAX_SIZE and storage.size
 * Callback accepts storage left as param
 *
 * @api public
 */
storage.left = function getStorageLeft() {
  return MAX_SIZE - this.size();
};
<|endoftext|>


<commit_before>$(function() {
	var listSelector = '#article_list',
		messageType = $(listSelector).data('message_type'),
		relatedId = $(listSelector).data('id');
		messageGetUri = 'message/api/talks/' + messageType + '/' + relatedId + '.html';

	//$('body').tooltip({
	//	selector: 'a[data-toggle=tooltip]'
	//});

	$('textarea.input_message').css('height', '50px');
	loadMessageDefault(listSelector, messageGetUri);

	var listType = $(listSelector).data('type');
	if (!listType || listType != 'ajax') {
		postLoadMessage();
	}

	//$(document).on('click','.js-ajax-Load_message', function(){
	//	var getData = $(this).data('get_data') ? $(this).data('get_data') : {};
	//	loadMessage(getData, this, true);
	//	return false;
	//});

	$('#btn_message').click(function(){
		if (GL.execute_flg) return false;

		var body = $.trim($('#textarea_comment').val());// for legacy IE.
		var postData = $(this).data('post_data') ? $(this).data('post_data') : {};
		$('input[name^="image_tmp"]').each(function(){
			postData[this.name] = this.value;
		});
		if (body.length == 0 && Object.keys(postData).length == 0) return;
		postData[this.name] = this.value;

		var position = 'append';
		var getData = {
			latest: 1,
			desc: 0
		};

		// 「最新をみる」リンクがあれば削除する
		linkElement = $(listSelector + ' > a.listMoreBox:first');
		if (!empty(linkElement.data('type')) && linkElement.data('type') == 'see_latest') {
			linkElement.remove();
		}

		var sinceId = getSinceId(listSelector, position);
		if (sinceId) getData['since_id'] = sinceId;

		postComment(
			'message/api/create/' + messageType + '/' +relatedId + '.json',
			'#textarea_comment',
			messageGetUri,
			listSelector,
			position,
			getData,
			this,
			'',
			'',
			[resetInputs],
			[postLoadMessage],
			postData,
			false,
			get_term('message'),
			'50px'
		);
		return false;
	});
})

function resetInputs() {
	$('.upload').addClass('hidden');
	$('.display_upload_form').removeClass('hidden');
	$('#files_img').html('');
	$('#progress_img .progress-bar').css('width', 0);
	//scroll(is_sp() ? '#main_post_box' : 0, 'swing');
}

function loadMessageDefault(listSelector, getUri) {
	//var getData = {'mytimeline': 1};
	var getData = {};
	var max_id = url('?max_id');
	if (max_id) {
		getData['max_id'] = max_id;
		getData['before_link'] = 1;
	}
	loadMessage(listSelector, getUri, getData);
}

function loadMessage(parentListSelector, getUri) {
	var getData        = (arguments.length > 2) ? arguments[2] : {};
	var trigerSelector = (arguments.length > 3) ? arguments[3] : '';
	var isAddHisttory  = (arguments.length > 4) ? Boolean(arguments[4]) : false;

	//var getUri = 'message/api/talks/member/.html';
	//var parentListSelector = '#article_list';

	var pushStateInfo = {};
	if (isAddHisttory) {
		var trigerObj = trigerSelector ? $(trigerSelector) : null;
		if (trigerObj && trigerObj.attr('href') && trigerObj.attr('href') != '#') {
			pushStateInfo['url'] = trigerObj.attr('href');
		} else {
			pushStateInfo['keys'] = ['max_id'];
		}
	}

	loadList(
		getUri,
		parentListSelector,
		trigerSelector,
		'append',
		getData,
		pushStateInfo,
		null,
		null,
		[postLoadMessage]
	);
}

function postLoadMessage() {
}
<commit_msg>Implemented auto scroll after posted message<commit_after>$(function() {
	var listSelector = '#article_list',
		messageType = $(listSelector).data('message_type'),
		relatedId = $(listSelector).data('id');
		messageGetUri = 'message/api/talks/' + messageType + '/' + relatedId + '.html';

	//$('body').tooltip({
	//	selector: 'a[data-toggle=tooltip]'
	//});

	$('textarea.input_message').css('height', '50px');
	loadMessageDefault(listSelector, messageGetUri);

	var listType = $(listSelector).data('type');
	if (!listType || listType != 'ajax') {
		postLoadMessage();
	}

	//$(document).on('click','.js-ajax-Load_message', function(){
	//	var getData = $(this).data('get_data') ? $(this).data('get_data') : {};
	//	loadMessage(getData, this, true);
	//	return false;
	//});

	$('#btn_message').click(function(){
		if (GL.execute_flg) return false;

		var body = $.trim($('#textarea_comment').val());// for legacy IE.
		var postData = $(this).data('post_data') ? $(this).data('post_data') : {};
		$('input[name^="image_tmp"]').each(function(){
			postData[this.name] = this.value;
		});
		if (body.length == 0 && Object.keys(postData).length == 0) return;
		postData[this.name] = this.value;

		var position = 'append';
		var getData = {
			latest: 1,
			desc: 0
		};

		// 「最新をみる」リンクがあれば削除する
		linkElement = $(listSelector + ' > a.listMoreBox:first');
		if (!empty(linkElement.data('type')) && linkElement.data('type') == 'see_latest') {
			linkElement.remove();
		}

		var sinceId = getSinceId(listSelector, position);
		if (sinceId) getData['since_id'] = sinceId;

		postComment(
			'message/api/create/' + messageType + '/' +relatedId + '.json',
			'#textarea_comment',
			messageGetUri,
			listSelector,
			position,
			getData,
			this,
			'',
			'',
			[resetInputs],
			[postLoadMessage],
			postData,
			false,
			get_term('message'),
			'50px'
		);
		return false;
	});
})

function resetInputs() {
	$('.upload').addClass('hidden');
	$('.display_upload_form').removeClass('hidden');
	$('#files_img').html('');
	$('#progress_img .progress-bar').css('width', 0);
	//scroll(is_sp() ? '#main_post_box' : 0, 'swing');
}

function loadMessageDefault(listSelector, getUri) {
	//var getData = {'mytimeline': 1};
	var getData = {};
	var max_id = url('?max_id');
	if (max_id) {
		getData['max_id'] = max_id;
		getData['before_link'] = 1;
	}
	loadMessage(listSelector, getUri, getData, '', false, false);
}

function loadMessage(parentListSelector, getUri) {
	var getData        = (arguments.length > 2) ? arguments[2] : {};
	var trigerSelector = (arguments.length > 3) ? arguments[3] : '';
	var isAddHisttory  = (arguments.length > 4) ? Boolean(arguments[4]) : false;
	var isExecPostLoadFunc = (arguments.length > 5) ? Boolean(arguments[5]) : true;

	//var getUri = 'message/api/talks/member/.html';
	//var parentListSelector = '#article_list';

	var pushStateInfo = {};
	if (isAddHisttory) {
		var trigerObj = trigerSelector ? $(trigerSelector) : null;
		if (trigerObj && trigerObj.attr('href') && trigerObj.attr('href') != '#') {
			pushStateInfo['url'] = trigerObj.attr('href');
		} else {
			pushStateInfo['keys'] = ['max_id'];
		}
	}

	loadList(
		getUri,
		parentListSelector,
		trigerSelector,
		'append',
		getData,
		pushStateInfo,
		null,
		null,
		isExecPostLoadFunc ? [postLoadMessage] : []
	);
}

function postLoadMessage() {
	var $listBox = $('#article_list');
	var listBoxPositionY = $listBox.offset().top;
	var listBoxheight = $listBox.height();
	var postBoxheight = $('#main_post_box').height();
	var windowHeight = window.innerHeight ? window.innerHeight: $(window).height();
	var scrollPositionY = listBoxPositionY + listBoxheight + postBoxheight - windowHeight;
	if (scrollPositionY < 0) scrollPositionY = 0;
	$('html,body').animate({scrollTop:scrollPositionY});
}
<|endoftext|>


<commit_before>/**
 * A helper class to building valid permission structures
 */
class PermissionLevels {

	/**
	 * Permission levels indexed from 0-11, based on the level number
	 * @typedef {Array<permLevel>} validPermStructure
	 */

	/**
	 * @typedef {object} permLevel
	 * @property {boolean} break Whether the level should break (stop processing higher levels, and inhibit a no permission error)
	 * @property {Function} check The permission checking function
	 */

	constructor() {
		/**
		 * A cache of levels submitted with addLevel
		 * @type {Map}
		 */
		this.levels = new Map();
	}

	/**
	 * Adds levels to the levels cache to be converted to valid permission structure
	 * @param {number} level The permission number for the level you are defining
	 * @param {boolean} brk Whether the level should break (stop processing higher levels, and inhibit a no permission error)
	 * @param {Function} check The permission checking function
	 * @returns {PermissionLevels} This permission levels
	 */
	addLevel(level, brk, check) {
		if (this.levels.has(level)) throw new Error(`Level ${level} is already defined`);
		this.levels.set(level, { break: brk, check: check });
		return this;
	}

	/**
	 * The current valid permissions structure
	 * @readonly
	 * @type {validPermStructure}
	 */
	get structure() {
		const structure = [];
		for (let i = 0; i < 11; i++) {
			const myLevel = this.levels.get(i);
			if (myLevel) structure.push(myLevel);
			else structure.push({ break: false, check: () => false });
		}
		return structure;
	}

}

module.exports = PermissionLevels;
<commit_msg>fix PermLevels docs<commit_after>/**
 * A helper class to building valid permission structures
 */
class PermissionLevels {

	/**
	 * Permission levels indexed from 0-11, based on the level number
	 * @typedef {Array<permLevel>} validPermStructure
	 */

	/**
	 * @typedef {object} permLevel
	 * @property {boolean} break Whether the level should break (stop processing higher levels, and inhibit a no permission error)
	 * @property {Function} check The permission checking function
	 */

	/**
	 * Creates a new PermissionLevels
	 */
	constructor() {
		/**
		 * A cache of levels submitted with addLevel
		 * @type {Map}
		 */
		this.levels = new Map();
	}

	/**
	 * Adds levels to the levels cache to be converted to valid permission structure
	 * @param {number} level The permission number for the level you are defining
	 * @param {boolean} brk Whether the level should break (stop processing higher levels, and inhibit a no permission error)
	 * @param {Function} check The permission checking function
	 * @returns {PermissionLevels} This permission levels
	 */
	addLevel(level, brk, check) {
		if (this.levels.has(level)) throw new Error(`Level ${level} is already defined`);
		this.levels.set(level, { break: brk, check: check });
		return this;
	}

	/**
	 * The current valid permissions structure
	 * @readonly
	 * @type {validPermStructure}
	 */
	get structure() {
		const structure = [];
		for (let i = 0; i < 11; i++) {
			const myLevel = this.levels.get(i);
			if (myLevel) structure.push(myLevel);
			else structure.push({ break: false, check: () => false });
		}
		return structure;
	}

}

module.exports = PermissionLevels;
<|endoftext|>


<commit_before>import React from 'react';
import { shallow, configure } from 'enzyme';
import { expect } from 'meteor/practicalmeteor:chai';

import commentMockProps from '../../components/comments/CommentsItem/_comments-unit-tests.js'

import CommentsItem from '../../components/comments/CommentsItem/CommentsItem.jsx'
import CommentsListSection from '../../components/comments/CommentsListSection.jsx'

import Adapter from 'enzyme-adapter-react-16';
import ApolloClient from 'apollo-client';

import { createDummyUser, createDummyPost } from '../utils.js'

configure({ adapter: new Adapter() })

const mockClient = new ApolloClient()

const commentListMockProps = {
  store: {},
  router: { location: {query:()=>{}}, push: ()=>{}},
  classes: {}
}

describe('Commenting while banned from post --', async () => {
  it('CommentsItem does NOT render reply-button when user is in a Post bannedUserIds list', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser({groups:['trustLevel1']})
    const post = await createDummyPost(author, {bannedUserIds:[user._id]})
    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(0);
  });
  it('CommentsItem does not render reply-button when user is in a Post bannedUserIds list but PostAuthor NOT in trustLevel1', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser()
    const post = await createDummyPost(author, {bannedUserIds:[user._id]})

    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(0);
  });
  it('CommentsItem does NOT render reply-button when user is in a User bannedUserIds list', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser({groups:['trustLevel1'], bannedUserIds:[user._id]})
    const post = await createDummyPost(author)
    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(0);
  });
  it('CommentsItem renders reply-button when user is in Post bannedUserIds list but User is NOT in trustLevel1', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser({bannedUserIds:[user._id]})
    const post = await createDummyPost(author)

    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(1);
  });
  it('commentsListSection renders new-comment-form when user is NOT in a Post bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"1234"}}
        post={{id:"",slug:"", bannedUserIds:[], user:{groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(1);
    const commentsListSection2 = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"12345"}}
        post={{id:"",slug:""}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection2.find("#posts-thread-new-comment")).to.have.length(1);
  });
  it('commentsListSection does NOT render new-comment-form when user is in a Post bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"12345"}}
        post={{bannedUserIds:["12345"], user:{groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(0);
  });
  it('commentsListSection renders new-comment-form when user is NOT in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"12346"}}
        post={{user:{bannedUserIds:[]}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(1);
  });
  it('commentsListSection does NOT render new-comment-form when user is in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"4321"}}
        post={{user:{bannedUserIds:["4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(0);
  });

  // These tests are disabled because they were built on a brittle assumption
  // which no longer holds: that the relevant part of the resulting React tree
  // is present when only a shallow render is done (as opposed to a full
  // render). We can't do a full render in this context because we don't have
  // Apollo, and we also can't provide a user correctly without a full render
  // because shallow rendering can't do context variables.
  /*it('commentsListSection does NOT render banned_message when user is NOT in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"4321"}}
        post={{user:{bannedUserIds:["not4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find(".author_has_banned_you")).to.have.length(0);
  });
  it('commentsListSection does NOT render banned_message when user is not logged in', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{}}
        post={{user:{bannedUserIds:["not4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find(".author_has_banned_you")).to.have.length(0);
  });
  it('commentsListSection renders banned_message when user is in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"4321"}}
        post={{user:{bannedUserIds:["4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find(".author_has_banned_you")).to.have.length(1);
  });*/
});

// describe('BanUserSubmenu --', () => {
//   it('renders if Users.canModeratePost returns true', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<CommentsItem {...commentMockProps.commentMockProps} currentUser={testUser} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(1);
//   });
//   it('does not render if Users.canModeratePost returns false', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<Components.BanUserFromPostMenuItem currentUser={testUser} comment={{}} post={testPost} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(0);
//   });
// });

// describe('DeleteCommentMenuItem --', () => {
//   it('renders if Users.canModeratePost returns true', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<CommentsItem {...commentMockProps.commentMockProps} currentUser={testUser} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(1);
//   });
//   it('does not render if Users.canModeratePost returns false', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<Components.BanUserFromPostMenuItem currentUser={testUser} comment={{}} post={testPost} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(0);
//   });
// });
<commit_msg>Comment out brittle unit tests that tried to mock Apollo<commit_after>import React from 'react';

// Commented out because these unit tests were based on a very brittle hack:
// mocking Apollo with no backend. Under Apollo 2, you can't create an
// ApolloClient without a link, so that doesn't work at all.
/*
import { shallow, configure } from 'enzyme';
import { expect } from 'meteor/practicalmeteor:chai';

import commentMockProps from '../../components/comments/CommentsItem/_comments-unit-tests.js'

import CommentsItem from '../../components/comments/CommentsItem/CommentsItem.jsx'
import CommentsListSection from '../../components/comments/CommentsListSection.jsx'

import Adapter from 'enzyme-adapter-react-16';
import ApolloClient from 'apollo-client';

import { createDummyUser, createDummyPost } from '../utils.js'

configure({ adapter: new Adapter() })

const mockClient = new ApolloClient()

const commentListMockProps = {
  store: {},
  router: { location: {query:()=>{}}, push: ()=>{}},
  classes: {}
}
*/

describe('Commenting while banned from post --', async () => {
  /*
  it('CommentsItem does NOT render reply-button when user is in a Post bannedUserIds list', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser({groups:['trustLevel1']})
    const post = await createDummyPost(author, {bannedUserIds:[user._id]})
    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(0);
  });
  it('CommentsItem does not render reply-button when user is in a Post bannedUserIds list but PostAuthor NOT in trustLevel1', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser()
    const post = await createDummyPost(author, {bannedUserIds:[user._id]})

    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(0);
  });
  it('CommentsItem does NOT render reply-button when user is in a User bannedUserIds list', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser({groups:['trustLevel1'], bannedUserIds:[user._id]})
    const post = await createDummyPost(author)
    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(0);
  });
  it('CommentsItem renders reply-button when user is in Post bannedUserIds list but User is NOT in trustLevel1', async () => {
    const user = await createDummyUser()
    const author = await createDummyUser({bannedUserIds:[user._id]})
    const post = await createDummyPost(author)

    const commentsItem = shallow(
      <CommentsItem
        {...commentMockProps.commentMockProps}
        currentUser={user}
        post={post}
      />)
    expect(commentsItem.find(".comments-item-reply-link")).to.have.length(1);
  });
  it('commentsListSection renders new-comment-form when user is NOT in a Post bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"1234"}}
        post={{id:"",slug:"", bannedUserIds:[], user:{groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(1);
    const commentsListSection2 = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"12345"}}
        post={{id:"",slug:""}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection2.find("#posts-thread-new-comment")).to.have.length(1);
  });
  it('commentsListSection does NOT render new-comment-form when user is in a Post bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"12345"}}
        post={{bannedUserIds:["12345"], user:{groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(0);
  });
  it('commentsListSection renders new-comment-form when user is NOT in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"12346"}}
        post={{user:{bannedUserIds:[]}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(1);
  });
  it('commentsListSection does NOT render new-comment-form when user is in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"4321"}}
        post={{user:{bannedUserIds:["4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find("#posts-thread-new-comment")).to.have.length(0);
  });
  */

  // These tests are disabled because they were built on a brittle assumption
  // which no longer holds: that the relevant part of the resulting React tree
  // is present when only a shallow render is done (as opposed to a full
  // render). We can't do a full render in this context because we don't have
  // Apollo, and we also can't provide a user correctly without a full render
  // because shallow rendering can't do context variables.
  /*it('commentsListSection does NOT render banned_message when user is NOT in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"4321"}}
        post={{user:{bannedUserIds:["not4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find(".author_has_banned_you")).to.have.length(0);
  });
  it('commentsListSection does NOT render banned_message when user is not logged in', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{}}
        post={{user:{bannedUserIds:["not4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find(".author_has_banned_you")).to.have.length(0);
  });
  it('commentsListSection renders banned_message when user is in a User bannedUserIds list', () => {
    const commentsListSection = shallow(
      <CommentsListSection
        { ...commentListMockProps}
        currentUser={{_id:"4321"}}
        post={{user:{bannedUserIds:["4321"], groups:['trustLevel1']}}}
      />,
      {context:{client:mockClient}}
    )
    expect(commentsListSection.find(".author_has_banned_you")).to.have.length(1);
  });*/
});

// describe('BanUserSubmenu --', () => {
//   it('renders if Users.canModeratePost returns true', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<CommentsItem {...commentMockProps.commentMockProps} currentUser={testUser} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(1);
//   });
//   it('does not render if Users.canModeratePost returns false', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<Components.BanUserFromPostMenuItem currentUser={testUser} comment={{}} post={testPost} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(0);
//   });
// });

// describe('DeleteCommentMenuItem --', () => {
//   it('renders if Users.canModeratePost returns true', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<CommentsItem {...commentMockProps.commentMockProps} currentUser={testUser} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(1);
//   });
//   it('does not render if Users.canModeratePost returns false', () => {
//     TODO - stub Users.canModeratePost
//     const banUserMenuItem = shallow(<Components.BanUserFromPostMenuItem currentUser={testUser} comment={{}} post={testPost} />)
//     expect(banUserMenuItem.find(".comment-menu-item-ban-user-submenu")).to.have.length(0);
//   });
// });
<|endoftext|>


<commit_before>(function() {

function initialize_context_globals(gl)
{
    gl._lux_globals = {};

    // batches can currently be rendered in "draw" or "pick" mode.
    // draw: 0
    // pick: 1
    // these are indices into an array defined inside Lux.bake
    // For legibility, they should be strings, but for speed, they'll be integers.
    gl._lux_globals.batch_render_mode = 0;

    // epoch is the initial time being tracked by the context.
    gl._lux_globals.epoch = new Date().getTime() / 1000;

    gl._lux_globals.devicePixelRatio = undefined;

    // Optional, enabled WebGL extensions go here.
    gl._lux_globals.webgl_extensions = {};

    // from https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/DataView
    gl._lux_globals.little_endian = (function() {
        var buffer = new ArrayBuffer(2);
        new DataView(buffer).setInt16(0, 256, true);
        return new Int16Array(buffer)[0] === 256;
    })();

    // the transform stack is honored by Lux.bake and can be used to implement
    // a matrix stack, etc.
    gl._lux_globals.transform_stack = [];
}

////////////////////////////////////////////////////////////////////////////////

function polyfill_event(event, gl)
{
    // polyfill event.offsetX and offsetY in Firefox,
    // according to http://bugs.jquery.com/ticket/8523
    if(typeof event.offsetX === "undefined" || typeof event.offsetY === "undefined") {
        var targetOffset = $(event.target).offset();
        event.offsetX = event.pageX - targetOffset.left;
        event.offsetY = event.pageY - targetOffset.top;
    }

    event.luxX = event.offsetX * gl._lux_globals.devicePixelRatio;
    event.luxY = gl.viewportHeight - event.offsetY * gl._lux_globals.devicePixelRatio;
}

Lux.init = function(opts)
{
    opts = _.defaults(opts || {}, {
        clearColor: [1,1,1,0],
        clearDepth: 1.0,
        attributes: {
            alpha: true,
            depth: true,
            preserveDrawingBuffer: true
        },
        highDPS: true
    });

    var canvas = opts.canvas;
    if (_.isUndefined(canvas)) {
        var q = $("canvas");
        if (q.length === 0) {
            throw new Error("no canvas elements found in document");
        }
        if (q.length > 1) {
            throw new Error("More than one canvas element found in document; please specify a canvas option in Lux.init");
        }
        canvas = q[0];
    }

    canvas.unselectable = true;
    canvas.onselectstart = function() { return false; };
    var gl;

    var devicePixelRatio = 1;

    if (opts.highDPS) {
        devicePixelRatio = window.devicePixelRatio || 1;
        canvas.style.width = canvas.width;
        canvas.style.height = canvas.height;
        canvas.width = (canvas.clientWidth || canvas.width) * devicePixelRatio;
        canvas.height = (canvas.clientHeight || canvas.height) * devicePixelRatio;
    }

    try {
        if ("attributes" in opts) {
            gl = WebGLUtils.setupWebGL(canvas, opts.attributes);
            var x = gl.getContextAttributes();
            for (var key in opts.attributes) {
                if (opts.attributes[key] !== x[key]) {
                    throw new Error("requested attribute " +
                           key + ": " + opts.attributes[key] +
                           " could not be satisfied");
                }
            }
        } else
            gl = WebGLUtils.setupWebGL(canvas);
        if (!gl)
            throw new Error("failed context creation");
        initialize_context_globals(gl);
        if ("interactor" in opts) {
            for (var key in opts.interactor.events) {
                if (opts[key]) {
                    opts[key] = (function(handler, interactor_handler) {
                        return function(event) {
                            var v = handler(event);
                            return v && interactor_handler(event);
                        };
                    })(opts[key], opts.interactor.events[key]);
                } else {
                    opts[key] = opts.interactor.events[key];
                }
            }
        }

        if (opts.debugging) {
            var throwOnGLError = function(err, funcName, args) {
                throw new Error(WebGLDebugUtils.glEnumToString(err) +
                    " was caused by call to " + funcName);
            };
            gl = WebGLDebugUtils.makeDebugContext(gl, throwOnGLError, opts.tracing);
        }

        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;

        //////////////////////////////////////////////////////////////////////
        // event handling

        var canvas_events = ["mouseover", "mousemove", "mousedown", "mouseout", "mouseup"];
        _.each(canvas_events, function(ename) {
            var listener = opts[ename];
            function internal_listener(event) {
                polyfill_event(event, gl);
                if (!Lux.Scene.on(ename, event, gl))
                    return false;
                if (listener)
                    return listener(event);
                return true;
            }
            canvas.addEventListener(ename, Lux.on_context(gl, internal_listener), false);
        });

        if (!_.isUndefined(opts.mousewheel)) {
            $(canvas).bind('mousewheel', function(event, delta, deltaX, deltaY) {
                polyfill_event(event, gl);
                return opts.mousewheel(event, delta, deltaX, deltaY);
            });
        };

        //////////////////////////////////////////////////////////////////////

        var ext;
        var exts = gl.getSupportedExtensions();
        _.each(["OES_texture_float", "OES_standard_derivatives"], function(ext) {
            if (exts.indexOf(ext) === -1 ||
                (gl.getExtension(ext)) === null) { // must call this to enable extension
                alert(ext + " is not available on your browser/computer! " +
                      "Lux will not work, sorry.");
                throw new Error("insufficient GPU support");
            }
        });
        _.each(["WEBKIT_EXT_texture_filter_anisotropic",
                "EXT_texture_filter_anisotropic"],
               function(ext) {
                   if (exts.indexOf(ext) !== -1 && (gl.getExtension(ext) !== null)) {
                       gl._lux_globals.webgl_extensions.EXT_texture_filter_anisotropic = true;
                       gl.TEXTURE_MAX_ANISOTROPY_EXT     = 0x84FE;
                       gl.MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
                   }
               });
        if (exts.indexOf("OES_element_index_uint") !== -1 &&
            gl.getExtension("OES_element_index_uint") !== null) {
            gl._lux_globals.webgl_extensions.OES_element_index_uint = true;
        }
    } catch(e) {
        alert(e);
        throw e;
    }
    if (!gl) {
        alert("Could not initialize WebGL, sorry :-(");
        throw new Error("failed initalization");
    }

    gl._lux_globals.devicePixelRatio = devicePixelRatio;

    Lux.set_context(gl);

    gl.resize = function(width, height) {
        this.parameters.width.set(width);
        this.parameters.height.set(height);
        if (opts.highDPS) {
            this.viewportWidth = width * devicePixelRatio;
            this.viewportHeight = height * devicePixelRatio;
            this.canvas.style.width = width;
            this.canvas.style.height = height;
            this.canvas.width = this.canvas.clientWidth * devicePixelRatio;
            this.canvas.height = this.canvas.clientHeight * devicePixelRatio;
            if (opts.resize)
                opts.resize(width, height);
        } else {
            this.viewportWidth = width;
            this.viewportHeight = height;
            this.canvas.width = width;
            this.canvas.height = height;
            if (opts.resize)
                opts.resize(width, height);
        }
    };
    gl.parameters = {};
    if (opts.highDPS) {
        gl.parameters.width = Shade.parameter("float", gl.viewportWidth / devicePixelRatio);
        gl.parameters.height = Shade.parameter("float", gl.viewportHeight / devicePixelRatio);
    } else {
        gl.parameters.width = Shade.parameter("float", gl.viewportWidth);
        gl.parameters.height = Shade.parameter("float", gl.viewportHeight);
    }
    gl.parameters.now = Shade.parameter("float", gl._lux_globals.epoch);
    gl.parameters.frame_duration = Shade.parameter("float", 0);

    gl._lux_globals.scene = Lux.default_scene({
        context: gl,
        clearColor: opts.clearColor,
        clearDepth: opts.clearDepth,
        pre_draw: function() {
            var raw_t = new Date().getTime() / 1000;
            var new_t = raw_t - gl._lux_globals.epoch;
            var old_t = gl.parameters.now.get();
            gl.parameters.frame_duration.set(new_t - old_t);
            gl.parameters.now.set(new_t);
            gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        }
    });

    if ("interactor" in opts) {
        gl._lux_globals.scene.add(opts.interactor.scene);
        gl._lux_globals.scene = opts.interactor.scene;
    }

    return gl;
};

})();
<commit_msg>more old transform cleanup<commit_after>(function() {

function initialize_context_globals(gl)
{
    gl._lux_globals = {};

    // batches can currently be rendered in "draw" or "pick" mode.
    // draw: 0
    // pick: 1
    // these are indices into an array defined inside Lux.bake
    // For legibility, they should be strings, but for speed, they'll be integers.
    gl._lux_globals.batch_render_mode = 0;

    // epoch is the initial time being tracked by the context.
    gl._lux_globals.epoch = new Date().getTime() / 1000;

    gl._lux_globals.devicePixelRatio = undefined;

    // Optional, enabled WebGL extensions go here.
    gl._lux_globals.webgl_extensions = {};

    // from https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/DataView
    gl._lux_globals.little_endian = (function() {
        var buffer = new ArrayBuffer(2);
        new DataView(buffer).setInt16(0, 256, true);
        return new Int16Array(buffer)[0] === 256;
    })();
}

////////////////////////////////////////////////////////////////////////////////

function polyfill_event(event, gl)
{
    // polyfill event.offsetX and offsetY in Firefox,
    // according to http://bugs.jquery.com/ticket/8523
    if(typeof event.offsetX === "undefined" || typeof event.offsetY === "undefined") {
        var targetOffset = $(event.target).offset();
        event.offsetX = event.pageX - targetOffset.left;
        event.offsetY = event.pageY - targetOffset.top;
    }

    event.luxX = event.offsetX * gl._lux_globals.devicePixelRatio;
    event.luxY = gl.viewportHeight - event.offsetY * gl._lux_globals.devicePixelRatio;
}

Lux.init = function(opts)
{
    opts = _.defaults(opts || {}, {
        clearColor: [1,1,1,0],
        clearDepth: 1.0,
        attributes: {
            alpha: true,
            depth: true,
            preserveDrawingBuffer: true
        },
        highDPS: true
    });

    var canvas = opts.canvas;
    if (_.isUndefined(canvas)) {
        var q = $("canvas");
        if (q.length === 0) {
            throw new Error("no canvas elements found in document");
        }
        if (q.length > 1) {
            throw new Error("More than one canvas element found in document; please specify a canvas option in Lux.init");
        }
        canvas = q[0];
    }

    canvas.unselectable = true;
    canvas.onselectstart = function() { return false; };
    var gl;

    var devicePixelRatio = 1;

    if (opts.highDPS) {
        devicePixelRatio = window.devicePixelRatio || 1;
        canvas.style.width = canvas.width;
        canvas.style.height = canvas.height;
        canvas.width = (canvas.clientWidth || canvas.width) * devicePixelRatio;
        canvas.height = (canvas.clientHeight || canvas.height) * devicePixelRatio;
    }

    try {
        if ("attributes" in opts) {
            gl = WebGLUtils.setupWebGL(canvas, opts.attributes);
            var x = gl.getContextAttributes();
            for (var key in opts.attributes) {
                if (opts.attributes[key] !== x[key]) {
                    throw new Error("requested attribute " +
                           key + ": " + opts.attributes[key] +
                           " could not be satisfied");
                }
            }
        } else
            gl = WebGLUtils.setupWebGL(canvas);
        if (!gl)
            throw new Error("failed context creation");
        initialize_context_globals(gl);
        if ("interactor" in opts) {
            for (var key in opts.interactor.events) {
                if (opts[key]) {
                    opts[key] = (function(handler, interactor_handler) {
                        return function(event) {
                            var v = handler(event);
                            return v && interactor_handler(event);
                        };
                    })(opts[key], opts.interactor.events[key]);
                } else {
                    opts[key] = opts.interactor.events[key];
                }
            }
        }

        if (opts.debugging) {
            var throwOnGLError = function(err, funcName, args) {
                throw new Error(WebGLDebugUtils.glEnumToString(err) +
                    " was caused by call to " + funcName);
            };
            gl = WebGLDebugUtils.makeDebugContext(gl, throwOnGLError, opts.tracing);
        }

        gl.viewportWidth = canvas.width;
        gl.viewportHeight = canvas.height;

        //////////////////////////////////////////////////////////////////////
        // event handling

        var canvas_events = ["mouseover", "mousemove", "mousedown", "mouseout", "mouseup"];
        _.each(canvas_events, function(ename) {
            var listener = opts[ename];
            function internal_listener(event) {
                polyfill_event(event, gl);
                if (!Lux.Scene.on(ename, event, gl))
                    return false;
                if (listener)
                    return listener(event);
                return true;
            }
            canvas.addEventListener(ename, Lux.on_context(gl, internal_listener), false);
        });

        if (!_.isUndefined(opts.mousewheel)) {
            $(canvas).bind('mousewheel', function(event, delta, deltaX, deltaY) {
                polyfill_event(event, gl);
                return opts.mousewheel(event, delta, deltaX, deltaY);
            });
        };

        //////////////////////////////////////////////////////////////////////

        var ext;
        var exts = gl.getSupportedExtensions();
        _.each(["OES_texture_float", "OES_standard_derivatives"], function(ext) {
            if (exts.indexOf(ext) === -1 ||
                (gl.getExtension(ext)) === null) { // must call this to enable extension
                alert(ext + " is not available on your browser/computer! " +
                      "Lux will not work, sorry.");
                throw new Error("insufficient GPU support");
            }
        });
        _.each(["WEBKIT_EXT_texture_filter_anisotropic",
                "EXT_texture_filter_anisotropic"],
               function(ext) {
                   if (exts.indexOf(ext) !== -1 && (gl.getExtension(ext) !== null)) {
                       gl._lux_globals.webgl_extensions.EXT_texture_filter_anisotropic = true;
                       gl.TEXTURE_MAX_ANISOTROPY_EXT     = 0x84FE;
                       gl.MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
                   }
               });
        if (exts.indexOf("OES_element_index_uint") !== -1 &&
            gl.getExtension("OES_element_index_uint") !== null) {
            gl._lux_globals.webgl_extensions.OES_element_index_uint = true;
        }
    } catch(e) {
        alert(e);
        throw e;
    }
    if (!gl) {
        alert("Could not initialize WebGL, sorry :-(");
        throw new Error("failed initalization");
    }

    gl._lux_globals.devicePixelRatio = devicePixelRatio;

    Lux.set_context(gl);

    gl.resize = function(width, height) {
        this.parameters.width.set(width);
        this.parameters.height.set(height);
        if (opts.highDPS) {
            this.viewportWidth = width * devicePixelRatio;
            this.viewportHeight = height * devicePixelRatio;
            this.canvas.style.width = width;
            this.canvas.style.height = height;
            this.canvas.width = this.canvas.clientWidth * devicePixelRatio;
            this.canvas.height = this.canvas.clientHeight * devicePixelRatio;
            if (opts.resize)
                opts.resize(width, height);
        } else {
            this.viewportWidth = width;
            this.viewportHeight = height;
            this.canvas.width = width;
            this.canvas.height = height;
            if (opts.resize)
                opts.resize(width, height);
        }
    };
    gl.parameters = {};
    if (opts.highDPS) {
        gl.parameters.width = Shade.parameter("float", gl.viewportWidth / devicePixelRatio);
        gl.parameters.height = Shade.parameter("float", gl.viewportHeight / devicePixelRatio);
    } else {
        gl.parameters.width = Shade.parameter("float", gl.viewportWidth);
        gl.parameters.height = Shade.parameter("float", gl.viewportHeight);
    }
    gl.parameters.now = Shade.parameter("float", gl._lux_globals.epoch);
    gl.parameters.frame_duration = Shade.parameter("float", 0);

    gl._lux_globals.scene = Lux.default_scene({
        context: gl,
        clearColor: opts.clearColor,
        clearDepth: opts.clearDepth,
        pre_draw: function() {
            var raw_t = new Date().getTime() / 1000;
            var new_t = raw_t - gl._lux_globals.epoch;
            var old_t = gl.parameters.now.get();
            gl.parameters.frame_duration.set(new_t - old_t);
            gl.parameters.now.set(new_t);
            gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
        }
    });

    if ("interactor" in opts) {
        gl._lux_globals.scene.add(opts.interactor.scene);
        gl._lux_globals.scene = opts.interactor.scene;
    }

    return gl;
};

})();
<|endoftext|>


<commit_before>'use strict';

import React, { Component } from 'react';
import {
	AppRegistry,
	NavigatorIOS,
	BackAndroid,
	StatusBar,
	AppState
} from 'react-native';
import TimerMixin from 'react-timer-mixin';

// SETUP / UTIL / NAV
var AppSettings = 			require('./AppSettings'),
	general = 				require('./util/general'),
	logger = 				require('./util/logger'),

// VIEWS
	Home = 					require('./views/Home'),
	ShuttleStop = 			require('./views/ShuttleStop'),
	SurfReport = 			require('./views/weather/SurfReport'),
	DiningList = 			require('./views/dining/DiningList'),
	DiningDetail = 			require('./views/dining/DiningDetail'),
	DiningNutrition = 		require('./views/dining/DiningNutrition'),
	NewsDetail = 			require('./views/news/NewsDetail'),
	EventDetail = 			require('./views/events/EventDetail'),
	WebWrapper = 			require('./views/WebWrapper');

import GeoLocationContainer from './containers/geoLocationContainer';

import WelcomeWeekView from './views/welcomeWeek/WelcomeWeekView';
import EventListView from './views/events/EventListView';
import NewsListView from './views/news/NewsListView';
import DiningListView from './views/dining/DiningListView';
import FeedbackView from './views/FeedbackView';

// NAV
import NavigationBarWithRouteMapper from './views/NavigationBarWithRouteMapper';

// REDUX
import { Provider } from 'react-redux';
import configureStore from './store/configureStore';

/**
 * Timeout that allows for pause and resume
**/
function Timer(callback, delay) {
	var timerId, start, remaining = delay;

	this.pause = function() {
		clearTimeout(timerId);
		remaining -= new Date() - start;
	};

	this.resume = function() {
		start = new Date();
		clearTimeout(timerId);
		timerId = setTimeout(callback, remaining);
	};

	this.do = function() {
		clearTimeout(timerId);
		callback();
	}

	this.getID = function() {
		return timerId;
	};

	this.resume();
}
var timers = {};

var nowucsandiego = React.createClass({

	mixins: [TimerMixin],
	store: configureStore(),

	getInitialState() {
		return {
			inHome: true,
		};
	},

	componentWillMount() {
		AppState.addEventListener('change', this.handleAppStateChange);
	},

	componentDidMount() {
		if (general.platformAndroid() || AppSettings.NAVIGATOR_ENABLED) {
			// Listen to route focus changes
			// Should be a better way to do this...
			this.refs.navRef.refs.navRef.navigationContext.addListener('willfocus', (event) => {

				const route = event.data.route;

				// Make sure renders/card refreshes are only happening when in home route
				if (route.id === "Home") {
					this.setState({inHome: true});
					this._resumeTimeout();
				} else {
					this.setState({inHome: false});
					this._pauseTimeout();
				}
			});

			// Listen to back button on Android
			BackAndroid.addEventListener('hardwareBackPress', () => {
				//console.log(util.inspect(this.refs.navRef.refs.navRef.getCurrentRoutes()));
				//var route = this.refs.navRef.refs.navRef.getCurrentRoutes()[0];

				if(this.state.inHome) {
					BackAndroid.exitApp();
					return false;

				} else {
					this.refs.navRef.refs.navRef.pop();
					return true;
				}
			});
		}
		else {
			// Pause/resume timeouts
			this.refs.navRef.navigationContext.addListener('didfocus', (event) => {
				const route = event.data.route;

				// Make sure renders/card refreshes are only happening when in home route
				if (route.id === undefined) { //undefined is foxusing "Home"... weird I know
					this.setState({inHome: true});
					this._resumeTimeout();
				} else {
					this.setState({inHome: false});
					this._pauseTimeout();
				}
			});

			// Make all back buttons use text "Back"
			this.refs.navRef.navigationContext.addListener('willfocus', (event) => {
				const route = event.data.route;
				route.backButtonTitle = "Back";
			});
		}
	},

	componentWillUnmount() {
		AppState.removeEventListener('change', this.handleAppStateChange);
		this._pauseTimeout();
	},

	newTimeout: function(key, callback, delay) {
		timers[key] = (new Timer(callback, delay));
	},

	_pauseTimeout: function() {
		for (var key in timers) {
			timers[key].pause();
		}
	},

	_resumeTimeout: function() {
		for (var key in timers) {
			timers[key].resume();
		}
	},

	doTimeout: function() {
		for (var key in timers) {
			timers[key].do();
		}
	},

	render: function() {

		if (general.platformIOS()) {
			StatusBar.setBarStyle('light-content');
		}

		if (general.platformAndroid() || AppSettings.NAVIGATOR_ENABLED) {
			return (
				<Provider store={this.store}>
					<GeoLocationContainer />
					<NavigationBarWithRouteMapper
						ref="navRef"
						route={{id: 'Home', name: 'Home', title: 'now@ucsandiego'}}
						renderScene={this.renderScene}
					/>
				</Provider>
			);
		} else {
			return (
				<Provider store={this.store}>
					<GeoLocationContainer />
					<NavigatorIOS
						initialRoute={{
							component: Home,
							title: AppSettings.APP_NAME,
							passProps: {
								isSimulator: this.props.isSimulator,
								new_timeout: this.newTimeout,
								do_timeout: this.doTimeout
							},
							backButtonTitle: "Back"
						}}
						style={{flex: 1}}
						tintColor='#FFFFFF'
						barTintColor='#006C92'
						titleTextColor='#FFFFFF'
						navigationBarHidden={false}
						translucent={true}
						ref="navRef"
					/>
				</Provider>
			);
		}
	},

	renderScene: function(route, navigator, index, navState) {

		switch (route.id) {
			case 'Home': 				return (<Home route={route} navigator={navigator} new_timeout={this.newTimeout} do_timeout={this.doTimeout}/>);
			case 'ShuttleStop': 		return (<ShuttleStop route={route} navigator={navigator} />);
			case 'SurfReport': 			return (<SurfReport route={route} navigator={navigator} />);
			case 'DiningListView': 		return (<DiningListView route={route} navigator={navigator} />);
			case 'DiningDetail': 		return (<DiningDetail route={route} navigator={navigator} />);
			case 'DiningNutrition': 	return (<DiningNutrition route={route} navigator={navigator} />);
			case 'NewsDetail': 			return (<NewsDetail route={route} navigator={navigator} />);
			case 'EventDetail': 		return (<EventDetail route={route} navigator={navigator} />);
			case 'WebWrapper': 			return (<WebWrapper route={route} navigator={navigator} />);
			case 'WelcomeWeekView': 	return (<WelcomeWeekView route={route} navigator={navigator} />);
			case 'EventListView': 		return (<EventListView route={route} navigator={navigator} />);
			case 'NewsListView': 		return (<NewsListView route={route} navigator={navigator} />);
			case 'FeedbackView': 		return (<FeedbackView route={route} navigator={navigator} />);
			default: 					return (<Home route={route} navigator={navigator} new_timeout={this.newTimeout} do_timeout={this.doTimeout}/>);
		}
	},

	handleAppStateChange(currentAppState) {
		if (currentAppState === 'active') {
			if(this.state.inHome) {
				this._resumeTimeout();
			}
		}
		else if(currentAppState === 'background') {
			this._pauseTimeout();
		}
	},
});

module.exports = nowucsandiego;
<commit_msg>Provider requires single child<commit_after>'use strict';

import React, { Component } from 'react';
import {
	AppRegistry,
	NavigatorIOS,
	BackAndroid,
	StatusBar,
	AppState,
	View
} from 'react-native';
import TimerMixin from 'react-timer-mixin';

// SETUP / UTIL / NAV
var AppSettings = 			require('./AppSettings'),
	general = 				require('./util/general'),
	logger = 				require('./util/logger'),

// VIEWS
	Home = 					require('./views/Home'),
	ShuttleStop = 			require('./views/ShuttleStop'),
	SurfReport = 			require('./views/weather/SurfReport'),
	DiningList = 			require('./views/dining/DiningList'),
	DiningDetail = 			require('./views/dining/DiningDetail'),
	DiningNutrition = 		require('./views/dining/DiningNutrition'),
	NewsDetail = 			require('./views/news/NewsDetail'),
	EventDetail = 			require('./views/events/EventDetail'),
	WebWrapper = 			require('./views/WebWrapper');

import GeoLocationContainer from './containers/geoLocationContainer';

import WelcomeWeekView from './views/welcomeWeek/WelcomeWeekView';
import EventListView from './views/events/EventListView';
import NewsListView from './views/news/NewsListView';
import DiningListView from './views/dining/DiningListView';
import FeedbackView from './views/FeedbackView';

// NAV
import NavigationBarWithRouteMapper from './views/NavigationBarWithRouteMapper';

// REDUX
import { Provider } from 'react-redux';
import configureStore from './store/configureStore';

/**
 * Timeout that allows for pause and resume
**/
function Timer(callback, delay) {
	var timerId, start, remaining = delay;

	this.pause = function() {
		clearTimeout(timerId);
		remaining -= new Date() - start;
	};

	this.resume = function() {
		start = new Date();
		clearTimeout(timerId);
		timerId = setTimeout(callback, remaining);
	};

	this.do = function() {
		clearTimeout(timerId);
		callback();
	}

	this.getID = function() {
		return timerId;
	};

	this.resume();
}
var timers = {};

var nowucsandiego = React.createClass({

	mixins: [TimerMixin],
	store: configureStore(),

	getInitialState() {
		return {
			inHome: true,
		};
	},

	componentWillMount() {
		AppState.addEventListener('change', this.handleAppStateChange);
	},

	componentDidMount() {
		if (general.platformAndroid() || AppSettings.NAVIGATOR_ENABLED) {
			// Listen to route focus changes
			// Should be a better way to do this...
			this.refs.navRef.refs.navRef.navigationContext.addListener('willfocus', (event) => {

				const route = event.data.route;

				// Make sure renders/card refreshes are only happening when in home route
				if (route.id === "Home") {
					this.setState({inHome: true});
					this._resumeTimeout();
				} else {
					this.setState({inHome: false});
					this._pauseTimeout();
				}
			});

			// Listen to back button on Android
			BackAndroid.addEventListener('hardwareBackPress', () => {
				//console.log(util.inspect(this.refs.navRef.refs.navRef.getCurrentRoutes()));
				//var route = this.refs.navRef.refs.navRef.getCurrentRoutes()[0];

				if(this.state.inHome) {
					BackAndroid.exitApp();
					return false;

				} else {
					this.refs.navRef.refs.navRef.pop();
					return true;
				}
			});
		}
		else {
			// Pause/resume timeouts
			this.refs.navRef.navigationContext.addListener('didfocus', (event) => {
				const route = event.data.route;

				// Make sure renders/card refreshes are only happening when in home route
				if (route.id === undefined) { //undefined is foxusing "Home"... weird I know
					this.setState({inHome: true});
					this._resumeTimeout();
				} else {
					this.setState({inHome: false});
					this._pauseTimeout();
				}
			});

			// Make all back buttons use text "Back"
			this.refs.navRef.navigationContext.addListener('willfocus', (event) => {
				const route = event.data.route;
				route.backButtonTitle = "Back";
			});
		}
	},

	componentWillUnmount() {
		AppState.removeEventListener('change', this.handleAppStateChange);
		this._pauseTimeout();
	},

	newTimeout: function(key, callback, delay) {
		timers[key] = (new Timer(callback, delay));
	},

	_pauseTimeout: function() {
		for (var key in timers) {
			timers[key].pause();
		}
	},

	_resumeTimeout: function() {
		for (var key in timers) {
			timers[key].resume();
		}
	},

	doTimeout: function() {
		for (var key in timers) {
			timers[key].do();
		}
	},

	render: function() {

		if (general.platformIOS()) {
			StatusBar.setBarStyle('light-content');
		}

		if (general.platformAndroid() || AppSettings.NAVIGATOR_ENABLED) {
			return (
				<Provider store={this.store}>
					<View style={{ flex: 1 }}>
						<GeoLocationContainer />
						<NavigationBarWithRouteMapper
							ref="navRef"
							route={{ id: 'Home', name: 'Home', title: 'now@ucsandiego' }}
							renderScene={this.renderScene}
						/>
					</View>
				</Provider>
			);
		} else {
			return (
				<Provider store={this.store}>
					<View style={{ flex: 1 }}>
						<GeoLocationContainer />
						<NavigatorIOS
							initialRoute={{
								component: Home,
								title: AppSettings.APP_NAME,
								passProps: {
									isSimulator: this.props.isSimulator,
									new_timeout: this.newTimeout,
									do_timeout: this.doTimeout
								},
								backButtonTitle: 'Back'
							}}
							style={{ flex: 1 }}
							tintColor='#FFFFFF'
							barTintColor='#006C92'
							titleTextColor='#FFFFFF'
							navigationBarHidden={false}
							translucent={true}
							ref="navRef"
						/>
					</View>
				</Provider>
			);
		}
	},

	renderScene: function(route, navigator, index, navState) {

		switch (route.id) {
			case 'Home': 				return (<Home route={route} navigator={navigator} new_timeout={this.newTimeout} do_timeout={this.doTimeout}/>);
			case 'ShuttleStop': 		return (<ShuttleStop route={route} navigator={navigator} />);
			case 'SurfReport': 			return (<SurfReport route={route} navigator={navigator} />);
			case 'DiningListView': 		return (<DiningListView route={route} navigator={navigator} />);
			case 'DiningDetail': 		return (<DiningDetail route={route} navigator={navigator} />);
			case 'DiningNutrition': 	return (<DiningNutrition route={route} navigator={navigator} />);
			case 'NewsDetail': 			return (<NewsDetail route={route} navigator={navigator} />);
			case 'EventDetail': 		return (<EventDetail route={route} navigator={navigator} />);
			case 'WebWrapper': 			return (<WebWrapper route={route} navigator={navigator} />);
			case 'WelcomeWeekView': 	return (<WelcomeWeekView route={route} navigator={navigator} />);
			case 'EventListView': 		return (<EventListView route={route} navigator={navigator} />);
			case 'NewsListView': 		return (<NewsListView route={route} navigator={navigator} />);
			case 'FeedbackView': 		return (<FeedbackView route={route} navigator={navigator} />);
			default: 					return (<Home route={route} navigator={navigator} new_timeout={this.newTimeout} do_timeout={this.doTimeout}/>);
		}
	},

	handleAppStateChange(currentAppState) {
		if (currentAppState === 'active') {
			if(this.state.inHome) {
				this._resumeTimeout();
			}
		}
		else if(currentAppState === 'background') {
			this._pauseTimeout();
		}
	},
});

module.exports = nowucsandiego;
<|endoftext|>


<commit_before>import React from 'react'
import Avatar from '@material-ui/core/Avatar'
import ChevronLeft from '@material-ui/icons/ChevronLeft'
import ChevronRight from '@material-ui/icons/ChevronRight'
import ChromeReaderMode from '@material-ui/icons/ChromeReaderMode'
import IconButton from '@material-ui/core/IconButton'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemAvatar from '@material-ui/core/ListItemAvatar'
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'
import ListItemText from '@material-ui/core/ListItemText'
import Paper from '@material-ui/core/Paper'
import PersonIcon from '@material-ui/icons/Person'
import { useAuth } from 'base-shell/lib/providers/Auth'
import { useMenu } from 'material-ui-shell/lib/providers/Menu'
import { useTheme as useAppTheme } from 'material-ui-shell/lib/providers/Theme'
import { makeStyles, useTheme } from '@material-ui/core/styles'
import clsx from 'clsx'
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'
import ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp'
import Brightness4Icon from '@material-ui/icons/Brightness4'
import BrightnessHighIcon from '@material-ui/icons/BrightnessHigh'

const useStyles = makeStyles((theme) => ({
  paper: {
    backgroundColor: theme.palette.primary.dark,
    margin: 0,
    padding: 0,
  },
  listItem: {
    color: theme.palette.primary.contrastText,
    cursor: 'pointer',
  },
  icon: {
    color: theme.palette.primary.contrastText,
    cursor: 'pointer',
  },
  toolbar: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 2),
    // necessary for content to be below app bar
    ...theme.mixins.toolbar,
  },
}))

const MenuHeader = () => {
  const theme = useTheme()
  const { auth } = useAuth()
  const { type, setType } = useAppTheme()
  const authData = auth
  const classes = useStyles()
  const {
    isDesktop,
    setMenuOpen,
    setMiniMode,
    isMiniMode,
    isMenuOpen,
    isMiniSwitchVisibility,
    isAuthMenuOpen,
    setAuthMenuOpen,
  } = useMenu()

  const isAuthenticated = auth.isAuthenticated

  return (
    <Paper square={true} className={classes.paper}>
      {isMiniMode && isAuthenticated &&

}
      <List className={clsx(!isAuthenticated && classes.toolbar)}>
        {!isMiniMode && (
          <ListItem className={classes.listItem}>
            {isAuthenticated && !isMiniMode && (
              authData.photoURL ? (
                <ListItemAvatar
                  onClick={() => {
                    setAuthMenuOpen(!isAuthMenuOpen)
                  }}
                >
                  <Avatar src={authData.photoURL} alt="user" />
                </ListItemAvatar>
              ) : (
                <ListItemAvatar
                  onClick={() => {
                    setAuthMenuOpen(!isAuthMenuOpen)
                  }}
                >
                  <Avatar>
                    {authData.displayName ? (
                      authData.displayName[0].toUpperCase()
                    ) : (
                      <PersonIcon />
                    )}
                  </Avatar>
                </ListItemAvatar>
              )
            )}
            {!isMiniMode && (
              <ListItemSecondaryAction>
                <IconButton
                  onClick={() => {
                    setType(type === 'light' ? 'dark' : 'light')
                  }}
                >
                  {type === 'light' && (
                    <Brightness4Icon classes={{ root: classes.icon }} />
                  )}
                  {type === 'dark' && (
                    <BrightnessHighIcon classes={{ root: classes.icon }} />
                  )}
                </IconButton>
                {isDesktop && (
                  <>
                    {isMiniSwitchVisibility && (
                      <IconButton
                        onClick={() => {
                          setMiniMode(true)
                          setMenuOpen(false)
                        }}
                      >
                        <ChromeReaderMode classes={{ root: classes.icon }} />
                      </IconButton>
                    )}
                    <IconButton
                      color="inherit"
                      onClick={() => {
                        setMenuOpen(false)
                      }}
                    >
                      {theme.direction === 'rtl' && (
                        <ChevronRight classes={{ root: classes.icon }} />
                      )}
                      {theme.direction !== 'rtl' && (
                        <ChevronLeft classes={{ root: classes.icon }} />
                      )}
                    </IconButton>{' '}
                  </>
                )}
              </ListItemSecondaryAction>
            )}
          </ListItem>
        )}

        {isAuthenticated && (
          <ListItem
            onClick={() => {
              setAuthMenuOpen(!isAuthMenuOpen)
            }}
          >
          {!isMenuOpen && isMiniMode && isDesktop && (
            authData.photoURL ? (
              <ListItemAvatar>
                <Avatar
                  src={authData.photoURL}
                  alt="person"
                  //style={{ marginLeft: 0, marginTop: 0 }}
                />
              </ListItemAvatar>) : (
              <ListItemAvatar>
                <Avatar> {
                  authData.displayName
                    ? authData.displayName[0].toUpperCase()
                    : <PersonIcon />}
                </Avatar>
              </ListItemAvatar>
            ))}
            {!isMiniMode && (
              <ListItemText
                classes={{
                  primary: classes.listItem,
                  secondary: classes.listItem,
                }}
                style={{
                  marginLeft:
                    !isMenuOpen && isDesktop && authData.photoURL
                      ? 7
                      : undefined,
                }}
                primary={authData.displayName}
                secondary={authData.email}
              />
            )}
            {isMenuOpen && (
              <ListItemSecondaryAction
                onClick={() => {
                  setAuthMenuOpen(!isAuthMenuOpen)
                }}
              >
                <IconButton> {
                  isAuthMenuOpen
                    ? <ArrowDropUpIcon classes={{ root: classes.icon }} />
                    : <ArrowDropDownIcon classes={{ root: classes.icon }} />}
                </IconButton>
              </ListItemSecondaryAction>
            )}
          </ListItem>
        )}
      </List>
    </Paper>
  )
}

export default MenuHeader
<commit_msg>remove: redundant conditional for !isminimode<commit_after>import React from 'react'
import Avatar from '@material-ui/core/Avatar'
import ChevronLeft from '@material-ui/icons/ChevronLeft'
import ChevronRight from '@material-ui/icons/ChevronRight'
import ChromeReaderMode from '@material-ui/icons/ChromeReaderMode'
import IconButton from '@material-ui/core/IconButton'
import List from '@material-ui/core/List'
import ListItem from '@material-ui/core/ListItem'
import ListItemAvatar from '@material-ui/core/ListItemAvatar'
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'
import ListItemText from '@material-ui/core/ListItemText'
import Paper from '@material-ui/core/Paper'
import PersonIcon from '@material-ui/icons/Person'
import { useAuth } from 'base-shell/lib/providers/Auth'
import { useMenu } from 'material-ui-shell/lib/providers/Menu'
import { useTheme as useAppTheme } from 'material-ui-shell/lib/providers/Theme'
import { makeStyles, useTheme } from '@material-ui/core/styles'
import clsx from 'clsx'
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'
import ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp'
import Brightness4Icon from '@material-ui/icons/Brightness4'
import BrightnessHighIcon from '@material-ui/icons/BrightnessHigh'

const useStyles = makeStyles((theme) => ({
  paper: {
    backgroundColor: theme.palette.primary.dark,
    margin: 0,
    padding: 0,
  },
  listItem: {
    color: theme.palette.primary.contrastText,
    cursor: 'pointer',
  },
  icon: {
    color: theme.palette.primary.contrastText,
    cursor: 'pointer',
  },
  toolbar: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 2),
    // necessary for content to be below app bar
    ...theme.mixins.toolbar,
  },
}))

const MenuHeader = () => {
  const theme = useTheme()
  const { auth } = useAuth()
  const { type, setType } = useAppTheme()
  const authData = auth
  const classes = useStyles()
  const {
    isDesktop,
    setMenuOpen,
    setMiniMode,
    isMiniMode,
    isMenuOpen,
    isMiniSwitchVisibility,
    isAuthMenuOpen,
    setAuthMenuOpen,
  } = useMenu()

  const isAuthenticated = auth.isAuthenticated

  return (
    <Paper square={true} className={classes.paper}>
      {isMiniMode && isAuthenticated &&

}
      <List className={clsx(!isAuthenticated && classes.toolbar)}>
        {!isMiniMode && (
          <ListItem className={classes.listItem}>
            {isAuthenticated && (
              authData.photoURL ? (
                <ListItemAvatar
                  onClick={() => {
                    setAuthMenuOpen(!isAuthMenuOpen)
                  }}
                >
                  <Avatar src={authData.photoURL} alt="user" />
                </ListItemAvatar>
              ) : (
                <ListItemAvatar
                  onClick={() => {
                    setAuthMenuOpen(!isAuthMenuOpen)
                  }}
                >
                  <Avatar>
                    {authData.displayName ? (
                      authData.displayName[0].toUpperCase()
                    ) : (
                      <PersonIcon />
                    )}
                  </Avatar>
                </ListItemAvatar>
              )
            )}
              <ListItemSecondaryAction>
                <IconButton
                  onClick={() => {
                    setType(type === 'light' ? 'dark' : 'light')
                  }}
                >
                  {type === 'light' && (
                    <Brightness4Icon classes={{ root: classes.icon }} />
                  )}
                  {type === 'dark' && (
                    <BrightnessHighIcon classes={{ root: classes.icon }} />
                  )}
                </IconButton>
                {isDesktop && (
                  <>
                    {isMiniSwitchVisibility && (
                      <IconButton
                        onClick={() => {
                          setMiniMode(true)
                          setMenuOpen(false)
                        }}
                      >
                        <ChromeReaderMode classes={{ root: classes.icon }} />
                      </IconButton>
                    )}
                    <IconButton
                      color="inherit"
                      onClick={() => {
                        setMenuOpen(false)
                      }}
                    >
                      {theme.direction === 'rtl' && (
                        <ChevronRight classes={{ root: classes.icon }} />
                      )}
                      {theme.direction !== 'rtl' && (
                        <ChevronLeft classes={{ root: classes.icon }} />
                      )}
                    </IconButton>{' '}
                  </>
                )}
              </ListItemSecondaryAction>
          </ListItem>
        )}

        {isAuthenticated && (
          <ListItem
            onClick={() => {
              setAuthMenuOpen(!isAuthMenuOpen)
            }}
          >
          {!isMenuOpen && isMiniMode && isDesktop && (
            authData.photoURL ? (
              <ListItemAvatar>
                <Avatar
                  src={authData.photoURL}
                  alt="person"
                  //style={{ marginLeft: 0, marginTop: 0 }}
                />
              </ListItemAvatar>) : (
              <ListItemAvatar>
                <Avatar> {
                  authData.displayName
                    ? authData.displayName[0].toUpperCase()
                    : <PersonIcon />}
                </Avatar>
              </ListItemAvatar>
            ))}
            {!isMiniMode && (
              <ListItemText
                classes={{
                  primary: classes.listItem,
                  secondary: classes.listItem,
                }}
                style={{
                  marginLeft:
                    !isMenuOpen && isDesktop && authData.photoURL
                      ? 7
                      : undefined
                }}
                primary={authData.displayName}
                secondary={authData.email}
              />
            )}
            {isMenuOpen && (
              <ListItemSecondaryAction
                onClick={() => {
                  setAuthMenuOpen(!isAuthMenuOpen)
                }}
              >
                <IconButton> {
                  isAuthMenuOpen
                    ? <ArrowDropUpIcon classes={{ root: classes.icon }} />
                    : <ArrowDropDownIcon classes={{ root: classes.icon }} />}
                </IconButton>
              </ListItemSecondaryAction>
            )}
          </ListItem>
        )}
      </List>
    </Paper>
  )
}

export default MenuHeader
<|endoftext|>