├── .editorconfig ├── .eslintrc ├── .gitignore ├── README.md ├── bin ├── runApp.js └── runWebpackDevServer.js ├── config ├── development.config.js └── production.config.js ├── package.json ├── public ├── assets │ └── soundcloud.png ├── index.hot.html └── index.html ├── screens └── soundcloud.jpg ├── src ├── main │ └── app.js └── ui │ ├── app.css │ ├── app.js │ └── child.js ├── webpack.config.base.js ├── webpack.config.main.js ├── webpack.config.ui.dev.js └── webpack.config.ui.prod.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [package.json] 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/rules 2 | { 3 | "parser": "babel-eslint", 4 | "env": { 5 | "browser": true, 6 | "node": true, 7 | "mocha": true 8 | }, 9 | "plugins": [ 10 | "react" 11 | ], 12 | "rules": { 13 | "strict": 0, 14 | "quotes": [2, "single"], 15 | "no-underscore-dangle": 0, 16 | "no-unused-vars": 1, 17 | "no-unused-expressions": 0, 18 | "react/jsx-no-undef": 2, 19 | "new-cap": 0, 20 | "no-extra-boolean-cast": 0, 21 | "yoda": 0, 22 | "no-empty": 0, 23 | "no-use-before-define": 0, 24 | "camelcase": 0 25 | }, 26 | "globals": { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log 4 | *.map 5 | 6 | dist 7 | lib 8 | 9 | public/build 10 | /index.js 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Soundplayer 2 | 3 | ![](http://img.shields.io/badge/Status-Work%20In%20Progress-ff69b4.svg?style=flat) 4 | 5 | 6 | 7 | ## Userflow 8 | 9 | 1. Login screen 10 | 2. Dashboard - Stream screen as main one (menu with Explore and Likes) 11 | -------------------------------------------------------------------------------- /bin/runApp.js: -------------------------------------------------------------------------------- 1 | require('../index.js')(require('path').join(__dirname, '../')); 2 | -------------------------------------------------------------------------------- /bin/runWebpackDevServer.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var WebpackDevServer = require('webpack-dev-server'); 3 | var webpackDevConfig = require('../webpack.config.ui.dev.js'); 4 | 5 | new WebpackDevServer(webpack(webpackDevConfig), { 6 | publicPath: webpackDevConfig.output.publicPath, 7 | hot: true, 8 | stats: { colors: true }, 9 | historyApiFallback: true, 10 | headers: {'Access-Control-Allow-Origin': '*'}, 11 | inline: true 12 | }).listen(webpackDevConfig.hotReloadPort, function (err) { 13 | if (err) { 14 | throw err; 15 | } 16 | console.log('Webpack dev server listening on %s', webpackDevConfig.hotReloadPort); 17 | }); 18 | -------------------------------------------------------------------------------- /config/development.config.js: -------------------------------------------------------------------------------- 1 | var host = require('network-address')(); 2 | 3 | module.exports = { 4 | env: process.env.NODE_ENV || 'development', 5 | host: host, 6 | hotReloadPort: process.env.HOT_RELOAD_PORT || 3993, 7 | hotReloadUrl: 'http://$(host):$(hotReloadPort)/', 8 | soundcloud: { 9 | clientId: '08f79801a998c381762ec5b15e4914d5' 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /config/production.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: process.env.NODE_ENV || 'production', 3 | soundcloud: { 4 | clientId: process.env.SOUNDCLOUD_CLIENT_ID 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "soundplayer", 3 | "productName": "Soundplayer", 4 | "version": "0.0.0", 5 | "electronVersion": "0.33.7", 6 | "main": "./bin/runApp.js", 7 | "scripts": { 8 | "start": "electron .", 9 | "start-dev": "DEV_TOOLS=1 npm run watch", 10 | "start-hot": "HOT_RELOAD=1 electron .", 11 | "start-wds": "node bin/runWebpackDevServer", 12 | "watch-main": "webpack --config webpack.config.main.js --progress --colors --watch", 13 | "watch": "npm run watch-main & npm run start-wds & npm run start-hot", 14 | "build-ui": "NODE_ENV=production webpack -p --config webpack.config.ui.prod.js --progress --colors", 15 | "build-main": "webpack -p --config webpack.config.main.js --progress --colors", 16 | "package": "./node_modules/electron-packager/cli.js . $npm_package_productName --platform=darwin --arch=x64 --version=$npm_package_electronVersion --overwrite --out=dist --ignore='^/(dist|screens|src|config|node_modules)$' --ignore='^/webpack.*$' --asar --prune", 17 | "rebuild": "./node_modules/.bin/electron-rebuild", 18 | "deploy": "npm run build-main && npm run build-ui && npm run package" 19 | }, 20 | "devDependencies": { 21 | "babel": "^5.8.23", 22 | "babel-core": "^5.8.25", 23 | "babel-loader": "^5.3.2", 24 | "css-loader": "^0.19.0", 25 | "cssnext-loader": "^1.0.1", 26 | "electron-packager": "^5.1.0", 27 | "electron-prebuilt": "^0.33.7", 28 | "electron-rebuild": "^1.0.1", 29 | "envify": "^3.4.0", 30 | "extract-text-webpack-plugin": "^0.8.2", 31 | "html-webpack-plugin": "^1.6.2", 32 | "object-assign": "^4.0.1", 33 | "react-hot-loader": "^1.3.0", 34 | "style-loader": "^0.12.4", 35 | "transform-loader": "^0.2.3", 36 | "uglify-js": "^2.5.0", 37 | "webpack": "^1.12.2", 38 | "webpack-dev-server": "^1.12.0", 39 | "webpack-target-electron-renderer": "^0.1.0" 40 | }, 41 | "dependencies": { 42 | "basscss": "^7.0.4", 43 | "basscss-background-images": "0.0.9", 44 | "basscss-button-outline": "^1.1.1", 45 | "basscss-button-sizes": "^1.0.7", 46 | "basscss-button-transparent": "^1.1.1", 47 | "basscss-utility-headings": "0.0.6", 48 | "c0nfig": "^0.2.2", 49 | "electron-prebuilt": "^0.36.2", 50 | "minigrid": "^1.6.5", 51 | "network-address": "^1.0.0", 52 | "react": "^0.14.0", 53 | "react-dom": "^0.14.0", 54 | "react-router": "^1.0.0-rc3", 55 | "soundcloud": "^3.0.1", 56 | "soundcloud-audio": "^0.1.6" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /public/assets/soundcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosmetism/soundplayer-electron/ecabf368b8e0fb642cea6cca1d5fbbe30f4ab133/public/assets/soundcloud.png -------------------------------------------------------------------------------- /public/index.hot.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /screens/soundcloud.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kosmetism/soundplayer-electron/ecabf368b8e0fb642cea6cca1d5fbbe30f4ab133/screens/soundcloud.jpg -------------------------------------------------------------------------------- /src/main/app.js: -------------------------------------------------------------------------------- 1 | import app from 'app'; 2 | import { ipcMain } from 'electron'; 3 | import BrowserWindow from 'browser-window'; 4 | 5 | const HOT_RELOAD = process.env.HOT_RELOAD || false; 6 | const DEV_TOOLS = process.env.DEV_TOOLS || false; 7 | 8 | export default function init (startDir) { 9 | app.on('window-all-closed', () => { 10 | if (process.platform !== 'darwin') { 11 | app.quit(); 12 | } 13 | }); 14 | 15 | let mainWindow; 16 | 17 | app.on('ready', () => { 18 | mainWindow = new BrowserWindow({ 19 | title: 'Soundplayer', 20 | 'min-width': 800, 21 | 'min-height': 600, 22 | width: 1000, 23 | height: 750, 24 | 'title-bar-style': 'hidden', 25 | show: false 26 | }); 27 | 28 | console.log(HOT_RELOAD, startDir) 29 | mainWindow.loadURL(`file://${startDir}/public/index${HOT_RELOAD ? '.hot' : ''}.html`); 30 | 31 | if (DEV_TOOLS) { 32 | mainWindow.openDevTools(); 33 | } 34 | 35 | mainWindow.on('closed', () => { 36 | mainWindow = null 37 | }); 38 | 39 | ipcMain.on('ready', () => { 40 | mainWindow.show(); 41 | }); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /src/ui/app.css: -------------------------------------------------------------------------------- 1 | @import 'basscss'; 2 | @import 'basscss-utility-headings'; 3 | @import 'basscss-background-images'; 4 | @import 'basscss-button-sizes'; 5 | @import 'basscss-button-transparent'; 6 | @import 'basscss-button-outline'; 7 | 8 | /* globals */ 9 | body { 10 | background-color: #19191D; 11 | color: #fff; 12 | } 13 | 14 | html { 15 | box-sizing: border-box; 16 | } 17 | *, *:before, *:after { 18 | box-sizing: inherit; 19 | } 20 | 21 | .uppercase { 22 | text-transform: uppercase; 23 | } 24 | .capitalize { 25 | text-transform: capitalize; 26 | } 27 | .noselect { 28 | -webkit-touch-callout: none; 29 | -webkit-user-select: none; 30 | -moz-user-select: none; 31 | -ms-user-select: none; 32 | user-select: none; 33 | } 34 | textarea.vert { 35 | resize: vertical; 36 | } 37 | textarea.hor { 38 | resize: horizontal; 39 | } 40 | textarea.no-resize { 41 | resize:none; 42 | } 43 | .overlay { 44 | width: 100%; 45 | height: 100%; 46 | position: absolute; 47 | top: 0; 48 | left: 0; 49 | right: 0; 50 | bottom: 0; 51 | } 52 | 53 | .sc-button { 54 | font-weight: 400; 55 | padding-left: 50px; 56 | } 57 | .sc-button:after { 58 | content: ''; 59 | position: absolute; 60 | background: url('https://a-v2.sndcdn.com/assets/images/header/cloud@2x-e5fba4.png') no-repeat center; 61 | background-size: cover; 62 | width: 30px; 63 | height: 13px; 64 | left: 14px; 65 | top: 10px; 66 | } 67 | 68 | /* variables */ 69 | :root { 70 | --font-family: 'Avenir Next', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Garuda, Verdana, Tahoma, sans-serif; 71 | --orange: #f50; 72 | } 73 | -------------------------------------------------------------------------------- /src/ui/app.js: -------------------------------------------------------------------------------- 1 | import './app.css'; 2 | 3 | import { ipcRenderer } from 'electron'; 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | 7 | class App extends React.Component { 8 | render() { 9 | return ( 10 |
11 |

SoundPlayer

12 | {/* 13 | */} 14 | 17 |
18 | ); 19 | } 20 | } 21 | 22 | ReactDOM.render( 23 | , 24 | document.getElementById('root') 25 | ); 26 | 27 | setTimeout(() => { 28 | ipcRenderer.send('ready'); 29 | }, 10); 30 | -------------------------------------------------------------------------------- /src/ui/child.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import webFrame from 'web-frame'; 3 | import { env } from 'c0nfig'; 4 | 5 | class Child extends React.Component { 6 | render() { 7 | return ( 8 |
15 | Hello World React - {env}! 16 | 17 | {process.versions['electron']} 18 |   {webFrame.getZoomLevel()} 19 |
20 | ); 21 | } 22 | } 23 | 24 | export default Child; 25 | -------------------------------------------------------------------------------- /webpack.config.base.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | node: { 5 | __dirname: true 6 | }, 7 | 8 | resolve: { 9 | extensions: ['', '.js', '.jsx', 'json'], 10 | packageMains: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main'] 11 | }, 12 | 13 | externals: ['web-frame', 'electron'] 14 | }; 15 | -------------------------------------------------------------------------------- /webpack.config.main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var webpack = require('webpack'); 4 | var path = require('path'); 5 | var assign = require('object-assign'); 6 | var baseConfig = require('./webpack.config.base'); 7 | 8 | var config = assign(baseConfig, { 9 | entry: './src/main/app', 10 | 11 | output: { 12 | path: path.join(__dirname, '.'), 13 | filename: 'index.js', 14 | libraryTarget: 'commonjs2' 15 | }, 16 | 17 | plugins: [ 18 | new webpack.optimize.OccurenceOrderPlugin() 19 | ], 20 | 21 | module: { 22 | loaders: [{ 23 | test: /\.js?$/, 24 | exclude: /node_modules/, 25 | loaders: ['babel?stage=0'] 26 | }] 27 | }, 28 | 29 | target: 'atom' 30 | }); 31 | 32 | module.exports = config; 33 | -------------------------------------------------------------------------------- /webpack.config.ui.dev.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var webpack = require('webpack'); 4 | var path = require('path'); 5 | var assign = require('object-assign'); 6 | var config = require('c0nfig'); 7 | var webpackTargetElectronRenderer = require('webpack-target-electron-renderer'); 8 | var baseConfig = require('./webpack.config.base'); 9 | 10 | var hotReloadUrl = config.hotReloadUrl; 11 | var hotReloadPort = config.hotReloadPort; 12 | 13 | var config = assign(baseConfig, { 14 | hotReloadPort: hotReloadPort, 15 | 16 | devtool: 'cheap-module-eval-source-map', 17 | 18 | entry: [ 19 | 'webpack-dev-server/client?' + hotReloadUrl, 20 | 'webpack/hot/only-dev-server', 21 | './src/ui/app' 22 | ], 23 | 24 | output: { 25 | path: path.join(__dirname, 'public', 'build'), 26 | filename: 'bundle.js', 27 | publicPath: hotReloadUrl, 28 | libraryTarget: 'commonjs2' 29 | }, 30 | 31 | plugins: [ 32 | new webpack.HotModuleReplacementPlugin(), 33 | new webpack.NoErrorsPlugin() 34 | ], 35 | 36 | module: { 37 | loaders: [{ 38 | test: /\.jsx?$/, 39 | exclude: /node_modules/, 40 | loaders: ['react-hot', 'babel?stage=0'] 41 | }, { 42 | test: /\.css$/, 43 | loaders: ['style', 'css', 'cssnext'] 44 | }] 45 | } 46 | }); 47 | 48 | config.target = webpackTargetElectronRenderer(config); 49 | 50 | module.exports = config; 51 | -------------------------------------------------------------------------------- /webpack.config.ui.prod.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var assign = require('object-assign'); 5 | var webpack = require('webpack'); 6 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 7 | var webpackTargetElectronRenderer = require('webpack-target-electron-renderer'); 8 | var baseConfig = require('./webpack.config.base'); 9 | 10 | var config = assign(baseConfig, { 11 | entry: './src/ui/app', 12 | 13 | output: { 14 | path: path.join(__dirname, 'public', 'build'), 15 | filename: 'bundle.min.js', 16 | publicPath: './', 17 | libraryTarget: 'commonjs2' 18 | }, 19 | 20 | plugins: [ 21 | new webpack.optimize.OccurenceOrderPlugin(), 22 | new webpack.optimize.UglifyJsPlugin({ 23 | compress: { warnings: false } 24 | }), 25 | new ExtractTextPlugin('app.min.css') 26 | ], 27 | 28 | module: { 29 | loaders: [{ 30 | test: /\.jsx?$/, 31 | exclude: /node_modules/, 32 | loader: 'babel', 33 | query: { 34 | stage: 0 35 | } 36 | }, { 37 | test: /\.css$/, 38 | loader: ExtractTextPlugin.extract('style-loader', 'css-loader!cssnext-loader') 39 | }], 40 | postLoaders: [{ 41 | loader: 'transform?envify' 42 | }] 43 | } 44 | }); 45 | 46 | config.target = webpackTargetElectronRenderer(config); 47 | 48 | module.exports = config; 49 | --------------------------------------------------------------------------------