diff --git a/js/components/desktop-app-item.jsx b/js/components/desktop-app-item.jsx index e70e8f8..afb4b09 100644 --- a/js/components/desktop-app-item.jsx +++ b/js/components/desktop-app-item.jsx @@ -2,20 +2,37 @@ var React = require('react'); var Util = require('../util'); var LazyLoad = require('./mixins/lazy-load'); +var LOADING_ICON = 'img/hourglass.svg'; + module.exports = React.createClass({ mixins: [LazyLoad], getInitialState: function() { - return { icon: 'img/hourglass.svg', loading: false }; + return { icon: LOADING_ICON, currentTheme: undefined }; }, onInViewport: function() { - if(!this.state.loading) { - this.setState({ loading: true }); - var desktopEntry = this.props.desktopEntry; - this._findIcon(desktopEntry.Icon); - } + this.updateIconIfInViewport(); + }, + + updateIconIfInViewport: function() { + + var currentTheme = this.state.currentTheme; + var newTheme = this.props.theme; + + if( !this.isInViewport() || newTheme === currentTheme ) return; + + this.setState({ icon: LOADING_ICON, currentTheme: newTheme }); + + var desktopEntry = this.props.desktopEntry; + + this._findIcon(desktopEntry.Icon, newTheme); + + }, + + componentDidUpdate: function() { + this.updateIconIfInViewport(); }, render: function() { @@ -33,11 +50,12 @@ module.exports = React.createClass({ }, - _findIcon: function(iconPath) { + _findIcon: function(iconPath, theme) { var self = this; var DEFAULT_ICON = 'application-default-icon'; - var theme = null; + + console.log('Search icon %s:%s', iconPath, theme); Util.DesktopApps.findIcon(iconPath || DEFAULT_ICON, theme) .then(function(iconPath) { @@ -47,7 +65,9 @@ module.exports = React.createClass({ return iconPath; }) .then(function(iconPath) { - self.setState({ icon: iconPath }); + global.window.requestAnimationFrame(function() { + self.setState({ icon: iconPath }); + }); }) ; diff --git a/js/components/desktop-app-list.jsx b/js/components/desktop-app-list.jsx index 7a0d7ba..07b5dca 100644 --- a/js/components/desktop-app-list.jsx +++ b/js/components/desktop-app-list.jsx @@ -1,17 +1,21 @@ var React = require('react'); var Util = require('../util'); var DesktopAppItem = require('./desktop-app-item.jsx'); +var IconThemeSelector = require('./icon-theme-selector.jsx'); var path = require('path'); +var debug = require('debug')('pitaya:desktop-app-list'); module.exports = React.createClass({ getInitialState: function() { return { - desktopFiles: [] + desktopFiles: [], + selectedTheme: null }; }, componentDidMount: function() { + // Load system desktop apps var baseDirs = global.process.env.XDG_DATA_DIRS.split(':').map(function(baseDir){ return path.join(baseDir, 'applications'); @@ -28,15 +32,23 @@ module.exports = React.createClass({ var items = this.state.desktopFiles.map(function(desktopFile, i) { var desktopEntry = desktopFile.content['Desktop Entry']; - return ; - }); + return ; + }.bind(this)); return ( - +
+ +
    + {items} +
+
); + }, + + onThemeSelected: function(theme) { + console.log('Selected theme %s', theme); + this.setState({ selectedTheme: theme }); } }); diff --git a/js/components/icon-theme-selector.jsx b/js/components/icon-theme-selector.jsx new file mode 100644 index 0000000..7c8c8e4 --- /dev/null +++ b/js/components/icon-theme-selector.jsx @@ -0,0 +1,45 @@ +var React = require('react'); +var Util = require('../util'); + +module.exports = React.createClass({ + + propsType: { + onThemeSelected: React.PropTypes.func.isRequired, + }, + + getInitialState: function() { + return { selectedTheme: null, availableThemes: [] }; + }, + + componentDidMount: function() { + Util.DesktopApps.findIconThemes() + .then(function(themes) { + this.setState({ availableThemes: themes }); + }.bind(this)) + ; + }, + + onChange: function(evt) { + var selectedTheme = evt.target.value; + this.setState({ selectedTheme: selectedTheme }); + this.props.onThemeSelected(selectedTheme); + }, + + render: function() { + + var selectedTheme = this.state.selectedTheme; + var options = this.state.availableThemes.map(function(theme) { + return ( + + ); + }); + + return ( + + ); + + } + +}); diff --git a/js/components/mixins/lazy-load.js b/js/components/mixins/lazy-load.js index 4879829..dcb6075 100644 --- a/js/components/mixins/lazy-load.js +++ b/js/components/mixins/lazy-load.js @@ -30,7 +30,7 @@ module.exports = { var el = React.findDOMNode(this); if(typeof this.onInViewport === 'function') { - el.parentNode.addEventListener('scroll', debounce(_onInViewport.bind(this), 250)); + window.document.addEventListener('scroll', debounce(_onInViewport.bind(this), 250), true); } _onInViewport.call(this); diff --git a/js/util/desktop-apps.js b/js/util/desktop-apps.js index 2166664..1821a3a 100644 --- a/js/util/desktop-apps.js +++ b/js/util/desktop-apps.js @@ -79,6 +79,7 @@ exports.findIcon = function(iconName, themeName, size, themeIgnore) { themeIgnore = themeIgnore || []; if(themeIgnore.indexOf(themeIgnore) !== -1) { + debug('Theme %s already processed, ignoring...', themeName); return Promise.resolve(null); } themeIgnore.push(themeName); diff --git a/js/util/system.js b/js/util/system.js index 8e14ad5..8335a92 100644 --- a/js/util/system.js +++ b/js/util/system.js @@ -52,28 +52,12 @@ exports.runApp = function(execPath) { }); }; - -var _globCache = { - statCache: {}, - cache: {}, - realpathCache: {}, - symlinks: {} -}; - exports.findFiles = function(pattern, opts) { return new Promise(function(resolve, reject) { - - opts = opts || {}; - opts.cache = _globCache.cache; - opts.statCache = _globCache.statCache; - opts.realpathCache = _globCache.realpathCache; - opts.symlinks = _globCache.symlinks; - glob(pattern, opts, function(err, files) { if(err) return reject(err); return resolve(files); }); - }); }; diff --git a/package.json b/package.json index 8c45c6c..2b019cf 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "ini": "^1.3.4", "minimist": "^1.1.3", "node-jsx": "^0.13.3", - "react": "^0.13.3" + "react": "^0.13.3", + "react-dnd": "^1.1.5" } } diff --git a/test/desktop.js b/test/desktop.js index defc08b..9de8bef 100644 --- a/test/desktop.js +++ b/test/desktop.js @@ -21,7 +21,7 @@ DesktopSuite.findIconThemes = function(test) { DesktopSuite.findIcon = function(test) { - DesktopApps.findIcon('atom') + DesktopApps.findIcon('phpmyadmin') .then(function(iconPath) { console.log('findIcon', iconPath); test.done();