diff --git a/css/style.css b/css/style.css index 33f1b4b..6f81888 100644 --- a/css/style.css +++ b/css/style.css @@ -13,13 +13,14 @@ html, body { padding: 0; margin: 0; font-family: 'sawasdeeregular'; - background-size: contain; - background-position: center; - background-color: rgb(34, 107, 160); width: 100%; height: 100%; color: white; overflow-x: hidden; + background: url('../img/background.svg'); + background-size: cover; + background-repeat: no-repeat; + background-position: center; } @@ -34,7 +35,6 @@ html, body { background-position: center center; background-size: contain; background-repeat: no-repeat; - transition: background-image 250ms ease-in-out; } .full-width { @@ -46,11 +46,6 @@ html, body { .launcher { display: flex; flex-direction: column; - background: url('../img/background.svg'); - background-repeat: no-repeat; - background-size: cover; - background-position: center center; - transition: background-image 250ms ease-in-out; position: absolute; left: 0; right: 0; @@ -58,6 +53,26 @@ html, body { top: 0; } +.launcher > .crossfade-image { + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; +} + +.launcher .crossfade-image .top, +.launcher .crossfade-image .bottom { + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; + background-position: center center; + background-size: cover; + background-repeat: no-repeat; +} + .launcher .main { flex-direction: row; display: flex; @@ -69,6 +84,7 @@ html, body { align-items: center; display: flex; width: 60px; + z-index: 10; } .launcher .nav a.goback { @@ -306,6 +322,15 @@ html, body { /* Animations */ +.crossfade-leave { + opacity: 1; +} + +.crossfade-leave.crossfade-leave-active { + opacity: 0.01; + transition: opacity 500ms ease-in-out; +} + .pulse { -webkit-animation: 1s pulse infinite; } @@ -322,6 +347,13 @@ html, body { 100% { transform: scale(1); } } +@-webkit-keyframes fade-out { + 0% { opacity: 1; } + 1% { opacity: 0.99; } + 99% { opacity: 0.01; } + 100% { opacity: 0; } +} + @-webkit-keyframes slide-in-left { 0% { transform: translateX(-100%); } 100% { transform: translateX(0%); } diff --git a/eleve.json b/eleve.json new file mode 100644 index 0000000..e0955a9 --- /dev/null +++ b/eleve.json @@ -0,0 +1,334 @@ +{ + "background": "./img/background2.jpg", + "items": [ + { + "label": "Mathématiques", + "icon": "./icone-maths.png", + "items": [ + { + "label": "À nous les nombres", + "icon": "chromium-browser", + "exec": "/usr/bin/anous" + }, + { + "label": "Calcul mental", + "icon": "chromium-browser", + "exec": "/usr/bin/leterrier-calcul-mental" + }, + { + "label": "Calculs", + "icon": "chromium-browser", + "exec": "/usr/bin/calculs" + }, + { + "label": "Carmetal", + "icon": "chromium-browser", + "exec": "carmetal" + }, + { + "label": "Kig", + "icon": "chromium-browser", + "exec": "kig" + }, + { + "label": "Labyrinthe", + "icon": "chromium-browser", + "exec": "/usr/bin/labyrinthe" + }, + { + "label": "OOo4Kids", + "icon": "chromium-browser", + "exec": "ooo4kids1.3 -math" + }, + { + "label": "Opérations", + "icon": "chromium-browser", + "exec": "/usr/bin/operations" + }, + { + "label": "TuxMath", + "icon": "chromium-browser", + "exec": "/usr/bin/tuxmath" + } + ] + }, + { + "label": "Français", + "icon": "./img/francais.png", + "items": [ + { + "label": "Aller", + "icon": "chromium-browser", + "exec": "/usr/bin/aller" + }, + { + "label": "Anki", + "icon": "chromium-browser", + "exec": "anki %f" + }, + { + "label": "Dicorime", + "icon": "chromium-browser", + "exec": "dicorime" + }, + { + "label": "Dictionnaire", + "icon": "chromium-browser", + "exec": "stardict" + }, + { + "label": "GConjugo", + "icon": "chromium-browser", + "exec": "/usr/bin/gconjugo" + }, + { + "label": "Kanagram", + "icon": "chromium-browser", + "exec": "kanagram" + }, + { + "label": "Verbiste", + "icon": "chromium-browser", + "exec": "verbiste" + } + ] + }, + { + "label": "Histoire, géographie", + "icon": "./img/histoire-geo.png", + "items": [ + { + "label": "KGeography", + "icon": "chromium-browser", + "exec": "kgeography" + } + ] + }, + { + "label": "Sciences", + "icon": "./img/sciences.png", + "items": [ + { + "label": "Celestia", + "icon": "chromium-browser", + "exec": "celestia-gnome" + }, + { + "label": "Kturtle", + "icon": "chromium-browser", + "exec": "kturtle" + }, + { + "label": "Stellarium", + "icon": "chromium-browser", + "exec": "stellarium" + }, + { + "label": "SunClock", + "icon": "chromium-browser", + "exec": "sunclock" + } + ] + }, + { + "label": "Autres matières", + "icon": "./img/divers.png", + "items": [ + { + "label": "Childsplay", + "icon": "chromium-browser", + "exec": "/usr/games/childsplay" + }, + { + "label": "GCompris", + "icon": "chromium-browser", + "exec": "/usr/games/gcompris" + }, + { + "label": "GNU Solfege", + "icon": "chromium-browser", + "exec": "solfege" + }, + { + "label": "Mulot", + "icon": "chromium-browser", + "exec": "/usr/bin/mulot" + }, + { + "label": "MyPaint", + "icon": "chromium-browser", + "exec": "mypaint %f" + }, + { + "label": "Omnitux", + "icon": "chromium-browser", + "exec": "/usr/bin/omnitux" + }, + { + "label": "OOo4Kids Dessin", + "icon": "chromium-browser", + "exec": "ooo4kids1.3 -draw" + }, + { + "label": "TuxPaint", + "icon": "chromium-browser", + "exec": "/usr/bin/tuxpaint" + }, + { + "label": "TuxTyping", + "icon": "chromium-browser", + "exec": "/usr/games/tuxtype" + } + ] + }, + { + "label": "Internet & messagerie", + "icon": "./img/internet.png", + "items": [ + { + "label": "Thunderbird", + "icon": "chromium-browser", + "exec": "/usr/bin/thunderbird" + }, + { + "label": "Navigateur internet", + "icon": "firefox", + "exec": "/usr/bin/firefox" + } + ] + }, + { + "label": "Bureautique", + "icon": "./img/bureautique.png", + "items": [ + { + "label": "LibreOffice Tableur", + "icon": "chromium-browser", + "exec": "/usr/bin/libreoffice --calc %U" + }, + { + "label": "LibreOffice Texte", + "icon": "chromium-browser", + "exec": "/usr/bin/libreoffice --impress %U" + }, + { + "label": "LibreOffice Présentation", + "icon": "chromium-browser", + "exec": "/usr/bin/libreoffice --impress %U" + }, + { + "label": "Lecteur PDF", + "icon": "chromium-browser", + "exec": "/usr/bin/evince" + }, + { + "label": "Diaporama", + "icon": "chromium-browser", + "exec": "ooo4kids1.3 -impress" + }, + { + "label": "Tableau", + "icon": "chromium-browser", + "exec": "ooo4kids1.3 -calc" + }, + { + "label": "Texte", + "icon": "chromium-browser", + "exec": "ooo4kids1.3 -writer" + } + ] + }, + { + "label": "Outils", + "icon": "./img/logoutil.png", + "items": [ + { + "label": "Graveur de CD-DVD", + "icon": "chromium-browser", + "exec": "brasero" + }, + { + "label": "Capture d'écran", + "icon": "chromium-browser", + "exec": "gnome-screenshot --interactive" + }, + { + "label": "Créateur de diagrammes", + "icon": "chromium-browser", + "exec": "dia" + }, + { + "label": "Calculatrice", + "icon": "chromium-browser", + "exec": "gcalctool" + }, + { + "label": "Enregistreur de son", + "icon": "chromium-browser", + "exec": "gnome-sound-recorder" + }, + { + "label": "Éditeur d'images", + "icon": "chromium-browser", + "exec": "pinta" + }, + { + "label": "Table de caractères", + "icon": "chromium-browser", + "exec": "gucharmap" + }, + { + "label": "Lecteur Multimédia", + "icon": "chromium-browser", + "exec": "/usr/bin/vlc" + }, + { + "label": "Montage Vidéo", + "icon": "chromium-browser", + "exec": "openshot %F" + }, + { + "label": "Créer des DVD", + "icon": "chromium-browser", + "exec": "2ManDVD" + }, + { + "label": "Éditeur audio", + "icon": "chromium-browser", + "exec": "audacity %F" + }, + { + "label": "Créer des diaporamas", + "icon": "chromium-browser", + "exec": "imagination %F" + } + ] + }, + { + "label": "Dossiers personnels", + "icon": "./img/dossier.png", + "items": [ + { + "label": "Documents", + "icon": "chromium-browser", + "exec": "/usr/bin/nautilus Documents/" + }, + { + "label": "Images", + "icon": "chromium-browser", + "exec": "/usr/bin/nautilus Images/" + }, + { + "label": "Musique", + "icon": "chromium-browser", + "exec": "/usr/bin/nautilus Musique/" + }, + { + "label": "Vidéos", + "icon": "chromium-browser", + "exec": "/usr/bin/nautilus Vidéos/" + } + ] + } + ] +} diff --git a/img/hourglass.svg b/img/hourglass.svg index f73d114..a75ae8a 100644 --- a/img/hourglass.svg +++ b/img/hourglass.svg @@ -7,9 +7,9 @@ xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="50px" - height="50px" - viewBox="0 0 100 100" + width="32.529999" + height="37.5" + viewBox="0 0 65.059998 75" preserveAspectRatio="xMidYMid" class="uil-hourglass" id="svg2" @@ -43,112 +43,47 @@ id="namedview30" showgrid="false" inkscape:zoom="13.350176" - inkscape:cx="-10.530194" - inkscape:cy="27.889305" + inkscape:cx="-3.9872051" + inkscape:cy="18.89309" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" - inkscape:current-layer="g6" /> + inkscape:current-layer="g6" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" /> + id="rect4" + style="fill:none" /> + id="g6" + transform="translate(-17.46875,-13)"> - - - - - - - - - - - - + style="fill:#a4a4a4;fill-opacity:1;stroke:#ffffff;stroke-width:5;stroke-miterlimit:10" + inkscape:connector-curvature="0" /> + style="fill:#ffffff;fill-opacity:1" + inkscape:connector-curvature="0" /> - + style="fill:#ffffff;fill-opacity:1" + inkscape:connector-curvature="0" /> diff --git a/package.json b/package.json index b0cb5f2..50c7061 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,10 @@ "glob": "^5.0.14", "ini": "^1.3.4", "lodash": "^3.10.1", - "react": "^0.13.3", + "react": "^0.14.0", + "react-addons-css-transition-group": "^0.14.0", "react-dnd": "^1.1.5", + "react-dom": "^0.14.0", "react-redux": "^2.0.0", "redux": "^2.0.0", "redux-thunk": "^0.1.0" diff --git a/src/app.js b/src/app.js index 00103b2..1498abb 100644 --- a/src/app.js +++ b/src/app.js @@ -1,4 +1,5 @@ var React = require('react'); +var ReactDOM = require('react-dom'); var LauncherView = require('./components/launcher/launcher-view.js'); var EditView = require('./components/edit/edit-view.js'); var Provider = require('react-redux').Provider; @@ -34,9 +35,9 @@ function select(state) { // Connect App to Redux store App = connect(select)(App); -React.render( +ReactDOM.render( - { function() { return ; } } + , document.body diff --git a/src/components/common/crossfade-image.js b/src/components/common/crossfade-image.js new file mode 100644 index 0000000..1456927 --- /dev/null +++ b/src/components/common/crossfade-image.js @@ -0,0 +1,59 @@ +/* jshint node: true */ +var React = require('react'); +var AnimateMixin = require('../mixins/animate'); +var ReactCSSTransitionGroup = require('react-addons-css-transition-group'); + +module.exports = React.createClass({ + + mixins: [AnimateMixin], + + propTypes: { + src: React.PropTypes.string + }, + + getInitialState: function() { + return { currSrc: null, prevSrc: null }; + }, + + componentWillReceiveProps: function(nextProps) { + this.setState({ nextSrc: nextProps.src, currSrc: this.state.currSrc }); + }, + + render: function() { + + var topStyle = { + backgroundImage: 'url('+this.state.currSrc+')' + }; + + var bottomStyle = { + backgroundImage: 'url('+this.state.nextSrc+')', + }; + + var bottom = this.state.nextSrc ? +
: + null + ; + + var top = this.state.currSrc ? +
: + null + ; + + return ( +
+ {bottom} + + {top} + +
+ ); + + }, + + componentDidUpdate: function() { + if(this.state.nextSrc !== this.state.currSrc) { + this.setState({ currSrc: this.state.nextSrc }); + } + } + +}); diff --git a/src/components/edit/tree-item.js b/src/components/edit/tree-item.js index 0d3c05a..fc5a6c9 100644 --- a/src/components/edit/tree-item.js +++ b/src/components/edit/tree-item.js @@ -1,4 +1,4 @@ -var React = require('react/addons'); +var React = require('react'); var classNames = require('classnames'); var AppIcon = require('../common/app-icon.js'); var DragSource = require('react-dnd').DragSource; @@ -10,7 +10,7 @@ var TreeItem = React.createClass({ render: function() { var data = this.props.data; - + var connectDragSource = this.props.connectDragSource; var connectDropTarget = this.props.connectDropTarget; diff --git a/src/components/launcher/launcher-view.js b/src/components/launcher/launcher-view.js index 5b42d4f..44a2748 100644 --- a/src/components/launcher/launcher-view.js +++ b/src/components/launcher/launcher-view.js @@ -6,9 +6,11 @@ var AnimateMixin = require('../mixins/animate'); var actions = require('../../store/actions'); var connect = require('react-redux').connect; var debug = require('../../util/debug')('launcher-view'); +var CrossfadeImage = require('../common/crossfade-image'); var path = require('path'); var DEFAULT_PROFILE = path.join(__dirname, '..', '..', '..', 'default-profile.json'); +var DEFAULT_BACKGROUND = path.join(__dirname, '..', '..', '..', 'img', 'background.svg'); var LauncherView = React.createClass({ @@ -52,14 +54,11 @@ var LauncherView = React.createClass({ null ; - var style = {}; - - if(currentItem && currentItem.background) { - style.backgroundImage = 'url('+currentItem.background+')'; - } + var background = currentItem && currentItem.background ? currentItem.background : DEFAULT_BACKGROUND; return ( -
+
+ {header}
{nav} diff --git a/src/components/mixins/animate.js b/src/components/mixins/animate.js index 37cf387..179f1f3 100644 --- a/src/components/mixins/animate.js +++ b/src/components/mixins/animate.js @@ -1,5 +1,6 @@ var Events = { - ANIMATION_END: 'webkitAnimationEnd' + ANIMATION_END: 'webkitAnimationEnd', + TRANSITION_END: 'webkitTransitionEnd' }; module.exports = { @@ -13,10 +14,51 @@ module.exports = { el.style.webkitAnimation = animation; function onAnimEnd(evt) { + el.style.webkitAnimation = ''; el.removeEventListener(Events.ANIMATION_END, onAnimEnd); return resolve(el); } + }); + }, + + transition: function(component, style, time, easing) { + return new Promise(function(resolve, reject) { + + console.log('transition start', style, time); + + time = time || '500ms'; + easing = easing || 'linear'; + + var props = Object.keys(style); + var el = component.getDOMNode(); + + el.style.transition = null; + + el.addEventListener(Events.TRANSITION_END, onTransitionEnd, false); + + props.forEach(function(styleProp) { + el.style[styleProp] = style[styleProp].start; + }); + + var transition = ''; + props.forEach(function(styleProp) { + if(transition) transition += ', '; + transition += styleProp + ' ' + time + ' ' + easing; + }); + el.style.transition = transition; + + props.forEach(function(styleProp) { + el.style[styleProp] = style[styleProp].end; + }); + + function onTransitionEnd(evt) { + console.log('transition end', evt); + el.style.transition = null; + el.removeEventListener(Events.TRANSITION_END, onTransitionEnd); + return resolve(el); + } + }); } diff --git a/src/components/mixins/lazy-load.js b/src/components/mixins/lazy-load.js index 7b3dd57..835a60a 100644 --- a/src/components/mixins/lazy-load.js +++ b/src/components/mixins/lazy-load.js @@ -1,4 +1,4 @@ -var React = require('react'); +var ReactDOM = require('react-dom'); var _listeners = []; @@ -6,7 +6,7 @@ module.exports = { isInViewport: function() { - var el = React.findDOMNode(this); + var el = ReactDOM.findDOMNode(this); if(!el) return false;