├── .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 | 
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 |
--------------------------------------------------------------------------------