src/utils/desktop.js
/*
* OS.js - JavaScript Cloud/Web Desktop Platform
*
* Copyright (c) Anders Evenrud <andersevenrud@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Anders Evenrud <andersevenrud@gmail.com>
* @license Simplified BSD License
*/
import logger from '../logger';
import {supportedMedia} from './dom';
const imageDropMimes = [
'image/png',
'image/jpe?g',
'image/webp',
'image/gif',
'image/svg(\\+xml)?'
];
/**
* Check if droppable data is a VFS type
* @return {boolean}
*/
export const validVfsDrop = data => data && data.path;
/**
* Check if droppable data contains image
* @return {boolean}
*/
export const isDroppingImage = data => validVfsDrop(data) &&
imageDropMimes.some(re => !!data.mime.match(re));
/**
* Creates a set of styles based on background settings
*/
export const applyBackgroundStyles = (core, background) => {
const {$root} = core;
const styles = {
backgroundRepeat: 'no-repeat',
backgroundPosition: '50% 50%',
backgroundSize: 'auto',
backgroundColor: background.color,
backgroundImage: 'none'
};
if (background.style === 'cover' || background.style === 'contain') {
styles.backgroundSize = background.style;
} else if (background.style === 'repeat') {
styles.backgroundRepeat = 'repeat';
}
if (background.style !== 'color') {
if (background.src === undefined) {
styles.backgroundImage = undefined;
} else if (typeof background.src === 'string') {
styles.backgroundImage = `url(${background.src})`;
} else if (background.src) {
core.make('osjs/vfs')
.url(background.src)
.then(src => {
setTimeout(() => ($root.style.backgroundImage = `url(${src})`), 1);
})
.catch(error => logger.warn('Error while setting wallpaper from VFS', error));
}
}
Object.keys(styles).forEach(k => ($root.style[k] = styles[k]));
};
/**
* Creates a rectangle with the realestate panels takes up
*/
export const createPanelSubtraction = (panel, panels) => {
const subtraction = {top: 0, left: 0, right: 0, bottom: 0};
const set = p => (subtraction[p.options.position] = p.$element.offsetHeight);
if (panels.length > 0) {
panels.forEach(set);
} else {
// Backward compability
set(panel);
}
return subtraction;
};
export const isVisible = w => w &&
!w.getState('minimized') &&
w.getState('focused');
/*
* Resolves various resources
* TODO: Move all of this (and related) stuff to a Theme class
*/
export const resourceResolver = (core) => {
const media = supportedMedia();
const getThemeName = (type) => {
const defaultTheme = core.config('desktop.settings.' + type);
return core.make('osjs/settings').get('osjs/desktop', type, defaultTheme);
};
const themeResource = path => {
const theme = getThemeName('theme');
return core.url(`themes/${theme}/${path}`); // FIXME: Use metadata ?
};
const getSoundThemeName = () => getThemeName('sounds');
const soundResource = path => {
if (!path.match(/\.([a-z]+)$/)) {
const defaultExtension = 'mp3';
const checkExtensions = ['oga', 'mp3'];
const found = checkExtensions.find(str => media.audio[str] === true);
const use = found || defaultExtension;
path += '.' + use;
}
const theme = getSoundThemeName();
return theme ? core.url(`sounds/${theme}/${path}`) : null; // FIXME: Use metadata ?
};
const soundsEnabled = () => !!getSoundThemeName();
const icon = (name) => {
name = name.replace(/\.(png|svg|gif)$/, '');
const {getMetadataFromName} = core.make('osjs/packages');
const theme = getThemeName('icons');
const metadata = getMetadataFromName(theme) || {};
const iconDefinitions = metadata.icons || {};
const extension = iconDefinitions[name] || 'png';
return core.url(`icons/${theme}/icons/${name}.${extension}`);
};
return {themeResource, soundResource, soundsEnabled, icon};
};