Files
Iris/src/js/helpers.js

433 lines
9.5 KiB
JavaScript
Executable File

export let isTouchDevice = function(){
return 'ontouchstart' in document.documentElement
}
export let sizedImages = function( images ){
var sizes = {
small: false,
medium: false,
large: false,
huge: false
}
if( images.length <= 0 ) return sizes;
for( var i = 0; i < images.length; i++ ){
// Mopidy image object
if (typeof(images[i].__model__) !== 'undefined' && images[i].__model__ == 'Image'){
sizes.small = images[i].uri
// Mopidy image string
} else if (typeof(images[i]) == 'string'){
sizes.small = images[i]
// spotify-styled images
} else if (typeof(images[i].width) !== 'undefined'){
if( images[i].width < 400 ){
sizes.small = images[i].url;
}else if( images[i].width < 800 ){
sizes.medium = images[i].url;
}else if( images[i].width < 1000 ){
sizes.large = images[i].url;
}else{
sizes.huge = images[i].url;
}
// lastfm-styled images
} else if (typeof(images[i].size) !== 'undefined'){
switch( images[i].size ){
case 'mega':
case 'extralarge':
sizes.huge = images[i]['#text']
break
case 'large':
sizes.large = images[i]['#text']
break
case 'medium':
sizes.medium = images[i]['#text']
break
case 'small':
sizes.small = images[i]['#text']
break
}
}
}
if (!sizes.medium){
if (sizes.large) sizes.medium = sizes.large
else if (sizes.huge) sizes.medium = sizes.huge
else sizes.medium = sizes.small
}
if (!sizes.large) sizes.large = sizes.medium;
if (!sizes.huge) sizes.huge = sizes.large;
return sizes;
}
export let generateGuid = function(format = 'xxxxxxxxxxxx'){
return format.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
export let getCurrentPusherConnection = function( connections, connectionid ){
function isCurrentConnection(connection){
return connection.connectionid == newProps.pusher.connectionid;
}
var currentConnection = newProps.pusher.connections.find(isCurrentConnection);
if( !currentConnection ) return false;
return currentConnection;
}
/**
* Get a track's icon
* @param track object
* @return string
**/
export let getTrackIcon = function( track = false ){
if( !track ) return false
if( !track.album ) return false
if( !track.album.images ) return false
return sizedImages( track.album.images ).small
}
/**
* Get a track's icon
* @param track object
* @return string
**/
export let flattenTracks = function( tracks ){
var flattened = []
for( var i = 0; i < tracks.length; i++ ){
flattened.push( Object.assign(
{},
tracks[i].track,
{
added_by: tracks[i].added_by,
added_at: tracks[i].added_at
}
))
}
return flattened
}
/**
* Figure out a URI's source namespace
* @param uri = string
**/
export let uriSource = function(uri){
var exploded = uri.split(':');
return exploded[0]
}
export let sourceIcon = function(uri,source = null){
if (uri) source = uriSource(uri)
switch( source ){
case 'local':
case 'm3u':
return 'folder'
break
case 'gmusic':
return 'google'
break
default:
return source
}
}
/**
* Get an element from a URI
* @param element = string, the element we wish to extract
* @param uri = string
**/
export let getFromUri = function(element,uri){
var exploded = uri.split(':');
var namespace = exploded[0]
switch (element){
case 'mbid':
var index = exploded.indexOf('mbid')
if( index > -1 ) return exploded[index+1]
break
case 'artistid':
if (exploded[1] == 'artist'){
return exploded[2]
}
break
case 'albumid':
if (exploded[1] == 'album'){
return exploded[2]
}
break
case 'playlistid':
if (exploded[1] == 'playlist'){
return exploded[2]
} else if (exploded[1] == 'user' && exploded[3] == 'playlist'){
return exploded[4]
}
break
case 'playlistowner':
if (exploded[1] == 'user' && exploded[3] == 'playlist'){
return exploded[2]
}
break
case 'trackid':
if (exploded[1] == 'track'){
return exploded[2]
}
break
case 'userid':
if (exploded[1] == 'user'){
return exploded[2]
}
break
}
return null
}
/**
* Identify what kind of asset a URI is (playlist, album, etc)
* @param uri = string
* @return string
**/
export let uriType = function( uri ){
var exploded = uri.split(':')
switch (exploded[1]){
case 'track':
case 'artist':
case 'album':
case 'playlist':
return exploded[1]
break
case 'user':
if (exploded.length > 3 && exploded[3] == 'playlist'){
return 'playlist'
}
return exploded[1]
break
}
return null;
}
/**
* Convert a raw URI into a object index-friendly format. Primarily used for loading local playlists
* @param $uri = string
* @return string
**/
export let indexFriendlyUri = function (uri){
var output = encodeURI(uri)
output = output.replace("'",'%27')
return output
}
/**
* Digest an array of objects, and pull into simple array of uris
*
* @param items Array
* @return Array
**/
export let asURIs = function(items){
var uris = []
for( var i = 0; i < items.length; i++ ){
uris.push( items[i].uri )
}
return uris
}
/**
* Merge duplicated items in an array
*
* @param list Array the unclean array
* @param key string = the unique key (id, uri, tlid, etc)
**/
export let mergeDuplicates = function(list, key){
var clean_list = [];
var keyed_list = {};
for( var i in list ){
var item = list[i]
if( item[key] in keyed_list ){
item = Object.assign({}, keyed_list[item[key]], item)
}
keyed_list[item[key]] = item;
}
for( i in keyed_list ){
clean_list.push(keyed_list[i]);
}
return clean_list;
}
/**
* Remove duplicate items in a simple array
*
* @param list Array the unclean array
**/
export let removeDuplicates = function(array){
var unique = [];
for( var i in array ){
if (unique.indexOf(array[i]) <= -1 ){
unique.push(array[i])
}
}
return unique;
}
/**
* Convert a list of indexes to a useable range
* We ignore stragglers, and only attend to the first 'bunch' of consecutive indexes
*
* @param indexes array of int
**/
export let createRange = function (indexes){
// sort our indexes smallest to largest
function sortAsc(a,b){
return a - b
}
indexes.sort(sortAsc);
// iterate indexes to build the first 'bunch'
var first_bunch = []
var previous_index = false
for( var i = 0; i < indexes.length; i++ ){
if( !previous_index || previous_index == indexes[i]-1 ){
first_bunch.push(indexes[i])
previous_index = indexes[i]
}
// TODO: break when we find an integer step for better performance
}
return {
start: first_bunch[0],
length: first_bunch.length
}
}
/**
* Sort an array of objects
* @param array = array to sort
* @param property = string to sort by
* @param reverse = boolean
* @return array
**/
export let sortItems = function (array, property, reverse = false){
function compare(a,b) {
var a_value = a
var a_property_split = property.split('.')
for (var i = 0; i < a_property_split.length; i++) {
if (typeof(a_value[a_property_split[i]]) === 'undefined') {
a_value = false
break
}else{
a_value = a_value[a_property_split[i]]
}
}
var b_value = b
var b_property_split = property.split('.')
for( var i = 0; i < b_property_split.length; i++ ){
if (typeof(b_value[b_property_split[i]]) === 'undefined') {
b_value = false
break
} else {
b_value = b_value[b_property_split[i]]
}
}
if( typeof(a_value) === 'boolean'){
if (a_value && !b_value) return -1
if (!a_value && b_value) return 1
return 0
}else if( typeof(a_value) === 'string'){
if ( !a_value || !b_value ) return 0
if (a_value.toLowerCase() > b_value.toLowerCase()) return 1
if (a_value.toLowerCase() < b_value.toLowerCase()) return -1
return 0
}else{
if (parseInt(a_value) > parseInt(b_value)) return 1
if (parseInt(a_value) < parseInt(b_value)) return -1
return 0
}
}
var sorted = Object.assign([], array.sort(compare))
if( reverse ) sorted.reverse()
return sorted
}
/**
* Figure out if a value is a number
* @param data = mixed
* @return boolean
**/
export let isNumeric = function (data) {
return !isNaN(parseFloat(data)) && isFinite(data)
}
/**
* Set window title
* @param track
**/
export let setWindowTitle = function (track = false, play_state = false){
var title = 'No track playing'
if (track) {
var icon = '\u25A0 '
var artistString = ''
if (track.artists) {
for( var i = 0; i < track.artists.length; i++) {
if (artistString != '') artistString += ', '
artistString += track.artists[i].name
}
}
if (play_state && play_state == 'playing') icon = '\u25B6 '
title = icon +' '+ track.name +' - '+ artistString
}
document.title = title
}