Sélecteur pour le thème d'icone

This commit is contained in:
wpetit 2015-08-31 23:08:56 +02:00
parent 5cd3fafb5e
commit 1c0a4e9f13
8 changed files with 97 additions and 34 deletions

View File

@ -2,20 +2,37 @@ var React = require('react');
var Util = require('../util'); var Util = require('../util');
var LazyLoad = require('./mixins/lazy-load'); var LazyLoad = require('./mixins/lazy-load');
var LOADING_ICON = 'img/hourglass.svg';
module.exports = React.createClass({ module.exports = React.createClass({
mixins: [LazyLoad], mixins: [LazyLoad],
getInitialState: function() { getInitialState: function() {
return { icon: 'img/hourglass.svg', loading: false }; return { icon: LOADING_ICON, currentTheme: undefined };
}, },
onInViewport: function() { onInViewport: function() {
if(!this.state.loading) { this.updateIconIfInViewport();
this.setState({ loading: true }); },
var desktopEntry = this.props.desktopEntry;
this._findIcon(desktopEntry.Icon); 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() { render: function() {
@ -33,11 +50,12 @@ module.exports = React.createClass({
}, },
_findIcon: function(iconPath) { _findIcon: function(iconPath, theme) {
var self = this; var self = this;
var DEFAULT_ICON = 'application-default-icon'; var DEFAULT_ICON = 'application-default-icon';
var theme = null;
console.log('Search icon %s:%s', iconPath, theme);
Util.DesktopApps.findIcon(iconPath || DEFAULT_ICON, theme) Util.DesktopApps.findIcon(iconPath || DEFAULT_ICON, theme)
.then(function(iconPath) { .then(function(iconPath) {
@ -47,7 +65,9 @@ module.exports = React.createClass({
return iconPath; return iconPath;
}) })
.then(function(iconPath) { .then(function(iconPath) {
self.setState({ icon: iconPath }); global.window.requestAnimationFrame(function() {
self.setState({ icon: iconPath });
});
}) })
; ;

View File

@ -1,17 +1,21 @@
var React = require('react'); var React = require('react');
var Util = require('../util'); var Util = require('../util');
var DesktopAppItem = require('./desktop-app-item.jsx'); var DesktopAppItem = require('./desktop-app-item.jsx');
var IconThemeSelector = require('./icon-theme-selector.jsx');
var path = require('path'); var path = require('path');
var debug = require('debug')('pitaya:desktop-app-list');
module.exports = React.createClass({ module.exports = React.createClass({
getInitialState: function() { getInitialState: function() {
return { return {
desktopFiles: [] desktopFiles: [],
selectedTheme: null
}; };
}, },
componentDidMount: function() { componentDidMount: function() {
// Load system desktop apps // Load system desktop apps
var baseDirs = global.process.env.XDG_DATA_DIRS.split(':').map(function(baseDir){ var baseDirs = global.process.env.XDG_DATA_DIRS.split(':').map(function(baseDir){
return path.join(baseDir, 'applications'); return path.join(baseDir, 'applications');
@ -28,15 +32,23 @@ module.exports = React.createClass({
var items = this.state.desktopFiles.map(function(desktopFile, i) { var items = this.state.desktopFiles.map(function(desktopFile, i) {
var desktopEntry = desktopFile.content['Desktop Entry']; var desktopEntry = desktopFile.content['Desktop Entry'];
return <DesktopAppItem key={desktopFile.path} desktopEntry={desktopEntry} />; return <DesktopAppItem theme={this.state.selectedTheme} key={desktopFile.path} desktopEntry={desktopEntry} />;
}); }.bind(this));
return ( return (
<ul className="desktop-apps"> <div>
{items} <IconThemeSelector onThemeSelected={this.onThemeSelected} />
</ul> <ul className="desktop-apps">
{items}
</ul>
</div>
); );
},
onThemeSelected: function(theme) {
console.log('Selected theme %s', theme);
this.setState({ selectedTheme: theme });
} }
}); });

View File

@ -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 (
<option key={theme} value={theme}>{theme}</option>
);
});
return (
<select value={selectedTheme} onChange={this.onChange}>
{options}
</select>
);
}
});

View File

@ -30,7 +30,7 @@ module.exports = {
var el = React.findDOMNode(this); var el = React.findDOMNode(this);
if(typeof this.onInViewport === 'function') { 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); _onInViewport.call(this);

View File

@ -79,6 +79,7 @@ exports.findIcon = function(iconName, themeName, size, themeIgnore) {
themeIgnore = themeIgnore || []; themeIgnore = themeIgnore || [];
if(themeIgnore.indexOf(themeIgnore) !== -1) { if(themeIgnore.indexOf(themeIgnore) !== -1) {
debug('Theme %s already processed, ignoring...', themeName);
return Promise.resolve(null); return Promise.resolve(null);
} }
themeIgnore.push(themeName); themeIgnore.push(themeName);

View File

@ -52,28 +52,12 @@ exports.runApp = function(execPath) {
}); });
}; };
var _globCache = {
statCache: {},
cache: {},
realpathCache: {},
symlinks: {}
};
exports.findFiles = function(pattern, opts) { exports.findFiles = function(pattern, opts) {
return new Promise(function(resolve, reject) { 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) { glob(pattern, opts, function(err, files) {
if(err) return reject(err); if(err) return reject(err);
return resolve(files); return resolve(files);
}); });
}); });
}; };

View File

@ -28,6 +28,7 @@
"ini": "^1.3.4", "ini": "^1.3.4",
"minimist": "^1.1.3", "minimist": "^1.1.3",
"node-jsx": "^0.13.3", "node-jsx": "^0.13.3",
"react": "^0.13.3" "react": "^0.13.3",
"react-dnd": "^1.1.5"
} }
} }

View File

@ -21,7 +21,7 @@ DesktopSuite.findIconThemes = function(test) {
DesktopSuite.findIcon = function(test) { DesktopSuite.findIcon = function(test) {
DesktopApps.findIcon('atom') DesktopApps.findIcon('phpmyadmin')
.then(function(iconPath) { .then(function(iconPath) {
console.log('findIcon', iconPath); console.log('findIcon', iconPath);
test.done(); test.done();