From 7a9efb24c94761675b050498049531c8768fb86a Mon Sep 17 00:00:00 2001 From: nukeop Date: Mon, 27 Apr 2020 01:29:00 +0200 Subject: [PATCH 01/63] Enable typescript in app package --- packages/app/app/actions/{search.js => search.ts} | 0 packages/app/app/reducers/search.js | 1 + packages/app/babel.config.js | 3 ++- packages/app/package.json | 12 +++++++----- packages/app/webpack.config.js | 8 ++++++-- 5 files changed, 16 insertions(+), 8 deletions(-) rename packages/app/app/actions/{search.js => search.ts} (100%) diff --git a/packages/app/app/actions/search.js b/packages/app/app/actions/search.ts similarity index 100% rename from packages/app/app/actions/search.js rename to packages/app/app/actions/search.ts diff --git a/packages/app/app/reducers/search.js b/packages/app/app/reducers/search.js index c25659da01..da416a9773 100644 --- a/packages/app/app/reducers/search.js +++ b/packages/app/app/reducers/search.js @@ -28,6 +28,7 @@ const initialState = { playlistSearchResults: [], albumDetails: {}, artistDetails: {}, + searchHistory: [], unifiedSearchStarted: false, playlistSearchStarted: false, isFocused: false diff --git a/packages/app/babel.config.js b/packages/app/babel.config.js index a382d9d9ad..a04fdf50e1 100644 --- a/packages/app/babel.config.js +++ b/packages/app/babel.config.js @@ -5,7 +5,8 @@ module.exports = { electron: '4.2' } }], - '@babel/preset-react' + '@babel/preset-react', + '@babel/preset-typescript' ], plugins: [ ['@babel/plugin-proposal-decorators', { 'legacy': true }], diff --git a/packages/app/package.json b/packages/app/package.json index 3cf22acc5d..8daa848034 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -79,16 +79,17 @@ "ytdl-core": "^1.0.7" }, "devDependencies": { - "@babel/core": "^7.5.5", + "@babel/core": "^7.9.0", "@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-decorators": "^7.4.4", "@babel/plugin-proposal-object-rest-spread": "^7.5.5", "@babel/polyfill": "^7.4.4", - "@babel/preset-env": "^7.5.5", - "@babel/preset-react": "^7.0.0", - "@babel/register": "^7.5.5", + "@babel/preset-env": "^7.9.5", + "@babel/preset-react": "^7.9.4", + "@babel/preset-typescript": "^7.9.0", + "@babel/register": "^7.9.0", "ava": "^2.4.0", - "babel-loader": "^8.0.6", + "babel-loader": "^8.1.0", "chai": "^4.1.2", "chai-spies": "^1.0.0", "css-loader": "^1.0.0", @@ -110,6 +111,7 @@ "sass-loader": "^6.0.7", "style-loader": "^0.23.0", "svg-inline-loader": "^0.8.0", + "ts-loader": "^7.0.1", "url-loader": "^1.0.1", "utf-8-validate": "^5.0.2", "webpack": "^4.41.2", diff --git a/packages/app/webpack.config.js b/packages/app/webpack.config.js index cda93190bb..2b07da043c 100644 --- a/packages/app/webpack.config.js +++ b/packages/app/webpack.config.js @@ -32,7 +32,7 @@ module.exports = (env) => { namedModules: true }; const jsxRule = { - test: /.jsx?$/, + test: /\.(js|jsx|tsx|ts)$/, loader: 'babel-loader', options: { cacheDirectory: true, @@ -42,7 +42,8 @@ module.exports = (env) => { electron: '4.2' } }], - '@babel/preset-react' + '@babel/preset-react', + '@babel/preset-typescript' ], plugins: [ ['@babel/plugin-proposal-decorators', { 'legacy': true }], @@ -93,6 +94,8 @@ module.exports = (env) => { ]; if (IS_PROD) { + jsxRule.loader = 'ts-loader'; + jsxRule.options = {}; jsxRule.include = [ APP_DIR, UI_DIR @@ -124,6 +127,7 @@ module.exports = (env) => { mode: IS_PROD ? 'production' : 'development', optimization, resolve: { + extensions: ['*', '.js', '.ts', '.jsx', '.tsx', '.json'], alias: { react: path.resolve(__dirname, 'node_modules/react'), 'styled-component': path.resolve(__dirname, 'node_modules/styled-component') From c6d289974763b6fc97ad3722be46e05a63669853 Mon Sep 17 00:00:00 2001 From: nukeop Date: Mon, 27 Apr 2020 22:21:50 +0200 Subject: [PATCH 02/63] Add tsconfig.json --- packages/app/tsconfig.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/app/tsconfig.json diff --git a/packages/app/tsconfig.json b/packages/app/tsconfig.json new file mode 100644 index 0000000000..fe01f51323 --- /dev/null +++ b/packages/app/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "lib": ["DOM"], + "outDir": "dist", + "esModuleInterop": true, + "skipLibCheck": true, + "strict": false, + "allowJs": true, + "typeRoots": [ + "node_modules/@types" + ], + "jsx": "react" + }, + "include": [ + "app" + ] +} \ No newline at end of file From a5cce6f80caa65d0ffb9b7828fdaa46075671977 Mon Sep 17 00:00:00 2001 From: nukeop Date: Tue, 5 May 2020 01:12:08 +0200 Subject: [PATCH 03/63] Remove tsc step from start/build --- packages/app/app/actions/search.ts | 2 +- packages/app/app/reducers/queue.js | 12 ------------ packages/core/package.json | 2 -- packages/i18n/package.json | 2 -- packages/ui/package.json | 2 -- 5 files changed, 1 insertion(+), 19 deletions(-) diff --git a/packages/app/app/actions/search.ts b/packages/app/app/actions/search.ts index 44895df788..348d025089 100644 --- a/packages/app/app/actions/search.ts +++ b/packages/app/app/actions/search.ts @@ -279,7 +279,7 @@ export const artistInfoSearchByName = (artistName, history) => async (dispatch, dispatch(error( `Failed to find artist ${artistName}`, `Using ${selectedProvider.sourceName}`, - null, null, settings + null, settings )); } }; diff --git a/packages/app/app/reducers/queue.js b/packages/app/app/reducers/queue.js index 4f04b79cdd..ff0e1c5afd 100644 --- a/packages/app/app/reducers/queue.js +++ b/packages/app/app/reducers/queue.js @@ -6,7 +6,6 @@ import { UPDATE_QUEUE_ITEM, CLEAR_QUEUE, ADD_STREAMS_TO_QUEUE_ITEM, - REPLACE_STREAMS_IN_QUEUE_ITEM, NEXT_SONG, PREVIOUS_SONG, SELECT_SONG, @@ -52,15 +51,6 @@ function reduceAddStreamsToQueueItem(state, action) { }); } -function reduceReplaceStreamsInQueueItem(state, action) { - const replaceIx = findQueueItemIndex(state.queueItems, action.payload); - const newQueue = _.cloneDeep(state.queueItems); - newQueue[replaceIx] = action.payload; - return Object.assign({}, state, { - queueItems: newQueue - }); -} - function reduceSelectSong(state, action) { return Object.assign({}, state, { currentSong: action.payload @@ -186,8 +176,6 @@ export default function QueueReducer(state = initialState, action) { return { ...state, queueItems: [] }; case ADD_STREAMS_TO_QUEUE_ITEM: return reduceAddStreamsToQueueItem(state, action); - case REPLACE_STREAMS_IN_QUEUE_ITEM: - return reduceReplaceStreamsInQueueItem(state, action); case NEXT_SONG: return reduceNextSong(state); case PREVIOUS_SONG: diff --git a/packages/core/package.json b/packages/core/package.json index 5ea803cd99..7b4d27327e 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -14,8 +14,6 @@ "main": "lib/index.js", "typings": "lib/index.d.ts", "scripts": { - "start": "tsc", - "build": "tsc", "lint": "eslint src/**/*.ts --fix", "test": "eslint src/**/**/**/**/*.ts test/**/*.ts && ava -v" }, diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 68121b9e6c..6291ee6bcd 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -14,8 +14,6 @@ "main": "lib/index.js", "typings": "lib/index.d.ts", "scripts": { - "start": "tsc", - "build": "tsc", "lint": "eslint src/**/*.ts", "i18n-sync": "ts-node scripts/sync" }, diff --git a/packages/ui/package.json b/packages/ui/package.json index e5db270b36..4067bdf084 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -19,8 +19,6 @@ }, "scripts": { "storybook": "start-storybook -p 9001 -c .storybook", - "start": "tsc && copyfiles -u 1 ./lib/**/*.scss ./dist", - "build": "tsc && copyfiles -u 1 ./lib/**/*.scss ./dist", "lint": "eslint lib stories --fix", "test": "eslint lib && ava" }, From d257fbca966cc349046b95a6577a3bfa8c94ba39 Mon Sep 17 00:00:00 2001 From: nukeop Date: Tue, 5 May 2020 01:23:30 +0200 Subject: [PATCH 04/63] Don't exclude nuclear packages in main --- packages/main/webpack.config.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/main/webpack.config.ts b/packages/main/webpack.config.ts index 520380b44b..d2fa4e20ba 100644 --- a/packages/main/webpack.config.ts +++ b/packages/main/webpack.config.ts @@ -27,16 +27,11 @@ module.exports = (env: BuildEnv): import('webpack').Configuration => { const tsRule = { test: /.ts?$/, loader: 'ts-loader', - exclude: /node_modules\/(?!@nuclear).*/, options: { configFile: path.join(__dirname, `/config/tsconfig.${env.TARGET}.json`) } }; - if (IS_PROD) { - delete tsRule.exclude; - } - return { entry: './src/main.ts', resolve: { From 732af40b3656b34644dd6ab1bb4334944d7a0dfb Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 6 May 2020 00:10:59 +0200 Subject: [PATCH 05/63] Add typings for png resources --- packages/app/tsconfig.json | 3 ++- packages/app/typings/import-resources.d.ts | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 packages/app/typings/import-resources.d.ts diff --git a/packages/app/tsconfig.json b/packages/app/tsconfig.json index fe01f51323..3c960de196 100644 --- a/packages/app/tsconfig.json +++ b/packages/app/tsconfig.json @@ -9,7 +9,8 @@ "strict": false, "allowJs": true, "typeRoots": [ - "node_modules/@types" + "node_modules/@types", + "typings" ], "jsx": "react" }, diff --git a/packages/app/typings/import-resources.d.ts b/packages/app/typings/import-resources.d.ts new file mode 100644 index 0000000000..a0993ed6b6 --- /dev/null +++ b/packages/app/typings/import-resources.d.ts @@ -0,0 +1,4 @@ +declare module '*.png' { + const value: any; + export = value; +} From 3ef21edbf8392270e2866c365cf9a40c318c068e Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 7 May 2020 00:49:44 +0200 Subject: [PATCH 06/63] Change main path --- packages/core/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 7b4d27327e..674efec42d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -11,8 +11,7 @@ "url": "https://github.com/nukeop/nuclear/issues" }, "homepage": "https://github.com/nukeop/nuclear#readme", - "main": "lib/index.js", - "typings": "lib/index.d.ts", + "main": "src/index.ts", "scripts": { "lint": "eslint src/**/*.ts --fix", "test": "eslint src/**/**/**/**/*.ts test/**/*.ts && ava -v" From a622a1cb42b4206d584e9999add03648174a3b24 Mon Sep 17 00:00:00 2001 From: nukeop Date: Mon, 11 May 2020 00:48:39 +0200 Subject: [PATCH 07/63] Fix issues with iomporting core in main package --- packages/main/package.json | 1 + packages/main/tsconfig.json | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/main/package.json b/packages/main/package.json index 8b1ff7d1ff..547b219ba0 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -65,6 +65,7 @@ "@types/tiny-async-pool": "^1.0.0", "@types/uuid": "^3.4.6", "@types/webpack": "^4.41.0", + "babel-loader": "^8.1.0", "copy-webpack-plugin": "^5.1.1", "eslint": "^6.8.0", "node-loader": "^0.6.0", diff --git a/packages/main/tsconfig.json b/packages/main/tsconfig.json index 872d414c0e..009a3bbb42 100644 --- a/packages/main/tsconfig.json +++ b/packages/main/tsconfig.json @@ -1,7 +1,10 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + "lib": ["DOM"], "outDir": "dist", + "strict": false, + "allowJs": true, "typeRoots": [ "./typings", "node_modules/@types" From 93f627eb73ebc57819b2b30411bf7f079d954c16 Mon Sep 17 00:00:00 2001 From: nukeop Date: Mon, 11 May 2020 23:54:08 +0200 Subject: [PATCH 08/63] Load @nuclear modules through babel --- packages/app/tsconfig.json | 4 +++- packages/app/typings/import-resources.d.ts | 4 ++-- packages/app/webpack.config.js | 10 +++++++--- packages/main/package.json | 1 + packages/main/tsconfig.json | 2 +- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/app/tsconfig.json b/packages/app/tsconfig.json index 3c960de196..691b45fb16 100644 --- a/packages/app/tsconfig.json +++ b/packages/app/tsconfig.json @@ -15,6 +15,8 @@ "jsx": "react" }, "include": [ - "app" + "app", + "resources", + "typings" ] } \ No newline at end of file diff --git a/packages/app/typings/import-resources.d.ts b/packages/app/typings/import-resources.d.ts index a0993ed6b6..fc781e8809 100644 --- a/packages/app/typings/import-resources.d.ts +++ b/packages/app/typings/import-resources.d.ts @@ -1,4 +1,4 @@ declare module '*.png' { - const value: any; - export = value; + const src: string; + export default src; } diff --git a/packages/app/webpack.config.js b/packages/app/webpack.config.js index 2b07da043c..e048333a17 100644 --- a/packages/app/webpack.config.js +++ b/packages/app/webpack.config.js @@ -50,7 +50,7 @@ module.exports = (env) => { '@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread' ], - ignore: [/node_modules/] + ignore: [/node_modules\/(?!@nuclear).*/] } }; const contentSecurity = 'connect-src *; style-src \'unsafe-inline\' https:; font-src https: data:; img-src https: data: file:;'; @@ -98,9 +98,12 @@ module.exports = (env) => { jsxRule.options = {}; jsxRule.include = [ APP_DIR, - UI_DIR + path.resolve('..') + ]; + jsxRule.exclude = [ + /node_modules\/electron-timber\/preload\.js/, + /node_modules\/(?!@nuclear).*/ ]; - jsxRule.exclude = /node_modules\/electron-timber\/preload\.js/; optimization.splitChunks = { chunks: 'all', cacheGroups: { @@ -199,5 +202,6 @@ module.exports = (env) => { }; } + return config; }; diff --git a/packages/main/package.json b/packages/main/package.json index 547b219ba0..29e84e70cf 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -69,6 +69,7 @@ "copy-webpack-plugin": "^5.1.1", "eslint": "^6.8.0", "node-loader": "^0.6.0", + "shx": "^0.3.2", "ts-loader": "^6.2.1", "ts-node": "^8.5.4", "type-fest": "^0.8.1", diff --git a/packages/main/tsconfig.json b/packages/main/tsconfig.json index 009a3bbb42..b3cd88c6c2 100644 --- a/packages/main/tsconfig.json +++ b/packages/main/tsconfig.json @@ -6,7 +6,7 @@ "strict": false, "allowJs": true, "typeRoots": [ - "./typings", + "typings", "node_modules/@types" ] }, From efc4b5ec14d8255980c7ced6dbf101e3714c4aae Mon Sep 17 00:00:00 2001 From: nukeop Date: Tue, 12 May 2020 00:24:33 +0200 Subject: [PATCH 09/63] Include i18n and core --- packages/app/webpack.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/app/webpack.config.js b/packages/app/webpack.config.js index e048333a17..b3ae227365 100644 --- a/packages/app/webpack.config.js +++ b/packages/app/webpack.config.js @@ -9,6 +9,8 @@ const BUILD_DIR = path.resolve(__dirname, '../../dist'); const APP_DIR = path.resolve(__dirname, 'app'); const RESOURCES_DIR = path.resolve(__dirname, 'resources'); +const CORE_DIR = path.resolve(__dirname, '..', 'core'); +const I18N_DIR = path.resolve(__dirname, '..', 'i18n'); const UI_DIR = path.resolve(__dirname, '..', 'ui'); const VENDOR_DIR = path.resolve(__dirname, 'node_modules'); @@ -98,7 +100,9 @@ module.exports = (env) => { jsxRule.options = {}; jsxRule.include = [ APP_DIR, - path.resolve('..') + CORE_DIR, + I18N_DIR, + UI_DIR ]; jsxRule.exclude = [ /node_modules\/electron-timber\/preload\.js/, From 177959e41579e90716a6d30e48edceca80115138 Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 13 May 2020 00:50:43 +0200 Subject: [PATCH 10/63] Fix i18n main --- packages/i18n/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 6291ee6bcd..e95175e6ff 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -11,8 +11,7 @@ "url": "https://github.com/nukeop/nuclear/issues" }, "homepage": "https://github.com/nukeop/nuclear#readme", - "main": "lib/index.js", - "typings": "lib/index.d.ts", + "main": "src/index.js", "scripts": { "lint": "eslint src/**/*.ts", "i18n-sync": "ts-node scripts/sync" From 06b6aae719407cf530b357abdeb4f43b6332fd66 Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 13 May 2020 01:01:37 +0200 Subject: [PATCH 11/63] Fix i18n main --- packages/i18n/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index e95175e6ff..8f1cb02666 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -11,7 +11,7 @@ "url": "https://github.com/nukeop/nuclear/issues" }, "homepage": "https://github.com/nukeop/nuclear#readme", - "main": "src/index.js", + "main": "src/index.ts", "scripts": { "lint": "eslint src/**/*.ts", "i18n-sync": "ts-node scripts/sync" From eca7bfd8226f8dbd9a02c657b60d80c7a4062232 Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 13 May 2020 23:32:18 +0200 Subject: [PATCH 12/63] Mocha test setup for ts --- packages/app/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/app/package.json b/packages/app/package.json index 8daa848034..a01913e221 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -5,7 +5,7 @@ "scripts": { "start": "webpack-dev-server --inline --env.NODE_ENV=development", "build": "webpack --colors --env.NODE_ENV=production", - "test": "mocha --require @babel/register --require ignore-styles --require regenerator-runtime --timeout 10000 --prof --recursive", + "test": "mocha --require ts-node/register --require @babel/register --require ignore-styles --require regenerator-runtime --timeout 10000 --prof --recursive", "lint": "eslint app test --fix", "i18n": "sync-i18n --files 'app/locales/*.json' --primary en --languages fr tl nl de dk es pl zh ru tr id sk ko zh_tw se --space 2" }, @@ -88,6 +88,7 @@ "@babel/preset-react": "^7.9.4", "@babel/preset-typescript": "^7.9.0", "@babel/register": "^7.9.0", + "@types/mocha": "^7.0.2", "ava": "^2.4.0", "babel-loader": "^8.1.0", "chai": "^4.1.2", @@ -112,6 +113,7 @@ "style-loader": "^0.23.0", "svg-inline-loader": "^0.8.0", "ts-loader": "^7.0.1", + "ts-node": "^8.10.1", "url-loader": "^1.0.1", "utf-8-validate": "^5.0.2", "webpack": "^4.41.2", From 26ddb86001036e1a56e332dbabd5564bd48a1f9c Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 14 May 2020 00:09:51 +0200 Subject: [PATCH 13/63] Raise timeout limit for windows --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 033027af2b..f50a74b9cc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - timeout-minutes: 20 + timeout-minutes: 30 steps: - uses: actions/checkout@master From f1e9f5752e3e81dd8c1252fa5e3768b38201d284 Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 24 Jun 2020 01:29:38 +0200 Subject: [PATCH 14/63] Add menu to cards --- packages/app/app/store/middlewares/ipc.js | 4 +- packages/ui/.storybook/webpack.config.js | 6 +- packages/ui/lib/components/Card/index.js | 46 ----------- packages/ui/lib/components/Card/index.tsx | 85 +++++++++++++++++++++ packages/ui/lib/components/Card/styles.scss | 12 ++- packages/ui/lib/typings/import-types.ts | 8 ++ packages/ui/stories/card.stories.js | 35 ++++++++- packages/ui/tsconfig.json | 4 +- 8 files changed, 138 insertions(+), 62 deletions(-) delete mode 100644 packages/ui/lib/components/Card/index.js create mode 100644 packages/ui/lib/components/Card/index.tsx create mode 100644 packages/ui/lib/typings/import-types.ts diff --git a/packages/app/app/store/middlewares/ipc.js b/packages/app/app/store/middlewares/ipc.js index 8426bfdb02..23140a1583 100644 --- a/packages/app/app/store/middlewares/ipc.js +++ b/packages/app/app/store/middlewares/ipc.js @@ -89,9 +89,9 @@ const ipcConnect = () => next => { let maxDownloads; try { - maxDownloads=parseInt(getOption('max.downloads')); + maxDownloads = Number(getOption('max.downloads')); } catch (err){ - maxDownloads=1; + maxDownloads = 1; } if (payload.downloads.filter(({status}) => status === 'Started' || status === 'Waiting').length > maxDownloads) { break; diff --git a/packages/ui/.storybook/webpack.config.js b/packages/ui/.storybook/webpack.config.js index cb82c428b9..4dd5a49f18 100644 --- a/packages/ui/.storybook/webpack.config.js +++ b/packages/ui/.storybook/webpack.config.js @@ -19,8 +19,7 @@ module.exports = { test: /\.(ttf|eot|woff|woff2|svg)$/, loader: 'url-loader', include: [ - path.resolve(__dirname, '../resources'), - path.resolve(__dirname, '../node_modules/boxicons') + path.resolve(__dirname, '../resources') ] }, { @@ -30,8 +29,7 @@ module.exports = { 'css-loader?importLoaders=1&modules=true&localIdentName=[local]' ], include: [ - path.resolve(__dirname, '../resources'), - path.resolve(__dirname, '../node_modules/boxicons') + path.resolve(__dirname, '../resources') ] }, { diff --git a/packages/ui/lib/components/Card/index.js b/packages/ui/lib/components/Card/index.js deleted file mode 100644 index 0b71a699a2..0000000000 --- a/packages/ui/lib/components/Card/index.js +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import cx from 'classnames'; -import _ from 'lodash'; - -import artPlaceholder from '../../../resources/media/art_placeholder.png'; -import common from '../../common.scss'; -import styles from './styles.scss'; - -const Card = ({ - header, - content, - image, - onClick -}) => ( -
-
-
-
-

{header}

- { - _.isNil(content) - ? null - :

{content}

- } -
-
-
-); - -Card.propTypes = { - header: PropTypes.string, - content: PropTypes.string, - image: PropTypes.arrayOf(PropTypes.string), - onClick: PropTypes.func -}; - -export default Card; diff --git a/packages/ui/lib/components/Card/index.tsx b/packages/ui/lib/components/Card/index.tsx new file mode 100644 index 0000000000..0ab6febf0d --- /dev/null +++ b/packages/ui/lib/components/Card/index.tsx @@ -0,0 +1,85 @@ +import React from 'react'; +import cx from 'classnames'; +import _ from 'lodash'; +import { Dropdown, DropdownItemProps, DropdownHeaderProps, DropdownDividerProps } from 'semantic-ui-react'; + +import artPlaceholder from '../../../resources/media/art_placeholder.png'; +import common from '../../common.scss'; +import styles from './styles.scss'; + +export type CardMenuEntry = { + type: 'header' | 'item' | 'divider'; + props: DropdownItemProps | DropdownHeaderProps | DropdownDividerProps +}; + +type CardProps = { + header: string; + content: string; + image: string; + onClick: (event: React.MouseEvent) => void; + withMenu?: boolean; + animated?: boolean; + menuEntries?: CardMenuEntry[]; +}; + +const Card: React.FC = ({ + header, + content, + image, + onClick, + withMenu = false, + animated = true, + menuEntries +}) => ( +
+
+ { + withMenu && + + { + _.isArray(menuEntries) && !_.isEmpty(menuEntries) && + + { + menuEntries.map(entry => { + switch (entry.type) { + case 'header': + return ; + case 'item': + return ; + case 'divider': + return ; + } + }) + } + + } + + } +
+
+

{header}

+ { + _.isNil(content) + ? null + :

{content}

+ } +
+
+
+ ); +export default Card; diff --git a/packages/ui/lib/components/Card/styles.scss b/packages/ui/lib/components/Card/styles.scss index fc224c99b3..032e385006 100644 --- a/packages/ui/lib/components/Card/styles.scss +++ b/packages/ui/lib/components/Card/styles.scss @@ -1,4 +1,4 @@ -@import '../../common'; +@import "../../common"; .card_container { width: 100%; @@ -15,7 +15,7 @@ transition: $short-duration ease-in-out; cursor: pointer; - &:hover { + &.animated:hover { box-shadow: 0 0.5rem 1rem 0 rgba(0, 0, 0, 0.2); transform: scale(1.1); } @@ -42,7 +42,11 @@ color: rgba($white, 0.6); } } - - + .menu_button { + position: absolute; + z-index: 10; + margin: 1em; + align-self: flex-end; + } } } diff --git a/packages/ui/lib/typings/import-types.ts b/packages/ui/lib/typings/import-types.ts new file mode 100644 index 0000000000..93be86e1ca --- /dev/null +++ b/packages/ui/lib/typings/import-types.ts @@ -0,0 +1,8 @@ +declare module '*.scss' { + const content: {[className: string]: string}; + export default content; +} + +declare module '*.png' { + export = module; +} diff --git a/packages/ui/stories/card.stories.js b/packages/ui/stories/card.stories.js index 002be7843e..dd072c535b 100644 --- a/packages/ui/stories/card.stories.js +++ b/packages/ui/stories/card.stories.js @@ -24,7 +24,7 @@ storiesOf('Cards', module) .add('With rectangular album cover', () => (
(
{ _.map(_.range(5), () => (
{ _.map(_.range(5), () => (
{ _.map(_.range(5), () => ) }
+ )) + .add('Card with a menu', () => ( +
+ alert('item clicked') + } + } + ]} + /> +
)); diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index a4d1983fcc..60bb440afc 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -3,14 +3,14 @@ "compilerOptions": { "module": "commonjs", "lib": ["DOM"], - "declaration": true, "outDir": "dist", "esModuleInterop": true, "skipLibCheck": true, "strict": false, "allowJs": true, "typeRoots": [ - "node_modules/@types" + "node_modules/@types", + "lib/typings" ], "jsx": "react" }, From 47c24fce2c7faa3bb399963c16f23fdbe5d8e346 Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 1 Jul 2020 02:08:26 +0200 Subject: [PATCH 15/63] Player bar overhaul wip --- packages/app/app/actions/downloads.js | 27 ++++-- .../components/Cover/{index.js => index.tsx} | 15 ++-- .../ui/lib/components/PlayerBar/index.tsx | 87 +++++++++++++++++++ .../ui/lib/components/PlayerBar/styles.scss | 24 +++++ .../ui/lib/components/PlayerButton/index.tsx | 30 +++++++ .../lib/components/PlayerButton/styles.scss | 4 + .../lib/components/PlayerControls/index.tsx | 47 ++++++++++ .../lib/components/PlayerControls/styles.scss | 12 +++ .../Seekbar/{index.js => index.tsx} | 35 +++++--- .../ui/lib/components/Seekbar/styles.scss | 2 +- .../ui/lib/components/TrackInfo/index.tsx | 46 ++++++++++ .../ui/lib/components/TrackInfo/styles.scss | 33 +++++++ .../VolumeControls/PlayOptions/index.tsx | 40 +++++++++ .../VolumeControls/PlayOptions/styles.scss | 5 ++ .../VolumeControls/VolumeSlider/index.tsx | 30 +++++++ .../VolumeControls/VolumeSlider/styles.scss | 7 ++ .../lib/components/VolumeControls/index.tsx | 42 +++++++++ .../lib/components/VolumeControls/styles.scss | 11 +++ packages/ui/lib/index.js | 2 + packages/ui/stories/playerBar.stories.tsx | 30 +++++++ packages/ui/stories/playerButton.stories.tsx | 46 ++++++++++ 21 files changed, 545 insertions(+), 30 deletions(-) rename packages/ui/lib/components/Cover/{index.js => index.tsx} (67%) create mode 100644 packages/ui/lib/components/PlayerBar/index.tsx create mode 100644 packages/ui/lib/components/PlayerBar/styles.scss create mode 100644 packages/ui/lib/components/PlayerButton/index.tsx create mode 100644 packages/ui/lib/components/PlayerButton/styles.scss create mode 100644 packages/ui/lib/components/PlayerControls/index.tsx create mode 100644 packages/ui/lib/components/PlayerControls/styles.scss rename packages/ui/lib/components/Seekbar/{index.js => index.tsx} (53%) create mode 100644 packages/ui/lib/components/TrackInfo/index.tsx create mode 100644 packages/ui/lib/components/TrackInfo/styles.scss create mode 100644 packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx create mode 100644 packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss create mode 100644 packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx create mode 100644 packages/ui/lib/components/VolumeControls/VolumeSlider/styles.scss create mode 100644 packages/ui/lib/components/VolumeControls/index.tsx create mode 100644 packages/ui/lib/components/VolumeControls/styles.scss create mode 100644 packages/ui/stories/playerBar.stories.tsx create mode 100644 packages/ui/stories/playerButton.stories.tsx diff --git a/packages/app/app/actions/downloads.js b/packages/app/app/actions/downloads.js index daa540fa04..74e4a5e075 100644 --- a/packages/app/app/actions/downloads.js +++ b/packages/app/app/actions/downloads.js @@ -13,6 +13,14 @@ export const DOWNLOAD_FINISHED = 'DOWNLOAD_FINISHED'; export const DOWNLOAD_ERROR = 'DOWNLOAD_ERROR'; export const CLEAR_FINISHED_DOWNLOADS = 'CLEAR_FINISHED_DOWNLOADS'; +export const DownloadStatus = { + WAITING: 'Waiting', + STARTED: 'Started', + PAUSED: 'Paused', + FINISHED: 'Finished', + ERROR: 'Error' +}; + const changePropertyForItem = ({downloads, uuid, propertyName='status', value}) => { const changedItem = _.find(downloads, (item) => item.track.uuid === uuid); _.set(changedItem, propertyName, value); @@ -36,7 +44,7 @@ export function addToDownloads(streamProviders, track) { }); if (!existingTrack ){ const newDownload = { - status: 'Waiting', + status: DownloadStatus.WAITING, completion: 0, track: clonedTrack }; @@ -68,7 +76,7 @@ export function onDownloadPause(uuid) { const payload = changePropertyForItem({ downloads, uuid, - value: 'Paused' + value: DownloadStatus.PAUSED }); return { type: DOWNLOAD_PAUSED, @@ -81,7 +89,7 @@ export function onDownloadResume(uuid) { const payload = changePropertyForItem({ downloads, uuid, - value: 'Waiting' + value: DownloadStatus.WAITING }); return { @@ -92,12 +100,17 @@ export function onDownloadResume(uuid) { export function onDownloadProgress(uuid, progress) { const downloads = store.get('downloads'); - const payload = changePropertyForItem({ + let payload = changePropertyForItem({ downloads, uuid, propertyName: 'completion', value: progress }); + payload = changePropertyForItem({ + payload, + uuid, + value: DownloadStatus.STARTED + }); return { type: DOWNLOAD_PROGRESS, payload @@ -109,7 +122,7 @@ export function onDownloadError(uuid){ const payload = changePropertyForItem({ downloads, uuid, - value: 'Error' + value: DownloadStatus.ERROR }); return { @@ -123,7 +136,7 @@ export function onDownloadFinished(uuid) { const payload = changePropertyForItem({ downloads, uuid, - value: 'Finished' + value: DownloadStatus.FINISHED }); return { @@ -136,7 +149,7 @@ export function clearFinishedDownloads() { const downloads = store.get('downloads'); const filteredTracks = downloads.filter(( item ) => - item.status !== 'Finished' && item.status !== 'Error' + item.status !== DownloadStatus.FINISHED && item.status !== DownloadStatus.ERROR ); return { diff --git a/packages/ui/lib/components/Cover/index.js b/packages/ui/lib/components/Cover/index.tsx similarity index 67% rename from packages/ui/lib/components/Cover/index.js rename to packages/ui/lib/components/Cover/index.tsx index c02255b784..b7a84ce67d 100644 --- a/packages/ui/lib/components/Cover/index.js +++ b/packages/ui/lib/components/Cover/index.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; import cx from 'classnames'; import artPlaceholder from '../../../resources/media/art_placeholder.png'; @@ -7,7 +6,11 @@ import artPlaceholder from '../../../resources/media/art_placeholder.png'; import common from '../../common.scss'; import styles from './styles.scss'; -const Cover = ({ cover }) => ( +type CoverProps = { + cover?: string +} + +const Cover: React.FC = ({ cover = String(artPlaceholder) }) => (
(
); -Cover.propTypes = { - cover: PropTypes.string -}; - -Cover.defaultProps = { - cover: artPlaceholder -}; - export default Cover; diff --git a/packages/ui/lib/components/PlayerBar/index.tsx b/packages/ui/lib/components/PlayerBar/index.tsx new file mode 100644 index 0000000000..e3979d3afa --- /dev/null +++ b/packages/ui/lib/components/PlayerBar/index.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import cx from 'classnames'; + +import Seekbar, { SeekbarProps } from '../Seekbar'; +import PlayerControls, { PlayerControlsProps } from '../PlayerControls'; +import TrackInfo, { TrackInfoProps } from '../TrackInfo'; +import VolumeControls, { VolumeControlsProps } from '../VolumeControls'; + +import common from '../../common.scss'; +import styles from './styles.scss'; + +export type PlayerBarProps = PlayerControlsProps & + Omit & + TrackInfoProps & + VolumeControlsProps & { + renderTrackDuration?: boolean; + }; + +const PlayerBar: React.FC = ({ + cover, + track, + artist, + onTrackClick, + onArtistClick, + addToFavorites, + isFavorite, + + volume, + setVolume, + toggleMute, + isMuted, + playOptions, + + goForward, + goBack, + togglePlay, + isPlaying = false, + isLoading = false, + + queue, + fill = 0, + renderTrackDuration = false, + seek +}) => ( +
+ + { + renderTrackDuration && 'trackDuration' + + } + +
+ + + +
+
+ ); + +export default PlayerBar; \ No newline at end of file diff --git a/packages/ui/lib/components/PlayerBar/styles.scss b/packages/ui/lib/components/PlayerBar/styles.scss new file mode 100644 index 0000000000..18f2547229 --- /dev/null +++ b/packages/ui/lib/components/PlayerBar/styles.scss @@ -0,0 +1,24 @@ +@import "../../common.scss"; + +.player_bar { + display: flex; + flex: 0 0 auto; + flex-flow: column; + + width: 100%; + max-width: 100%; + + background: $background3; + user-select: none; + + .player_bar_bottom { + position: relative; + display: flex; + align-items: center; + flex: 1 1 auto; + flex-flow: row; + justify-content: space-between; + width: 100%; + max-width: 100%; + } +} diff --git a/packages/ui/lib/components/PlayerButton/index.tsx b/packages/ui/lib/components/PlayerButton/index.tsx new file mode 100644 index 0000000000..a1b4b7a7ac --- /dev/null +++ b/packages/ui/lib/components/PlayerButton/index.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Icon, SemanticICONS, SemanticSIZES } from 'semantic-ui-react'; + +import styles from './styles.scss'; + +export type PlayerButtonProps = { + icon: SemanticICONS; + size?: Exclude; + ariaLabel?: string; + onClick?: (e: React.MouseEvent) => void; + loading?: boolean; +}; + +const PlayerButton: React.FC = ({ + icon, + size = 'big', + ariaLabel, + onClick, + loading = false +}) => ( + + ); + +export default PlayerButton; \ No newline at end of file diff --git a/packages/ui/lib/components/PlayerButton/styles.scss b/packages/ui/lib/components/PlayerButton/styles.scss new file mode 100644 index 0000000000..b286288d22 --- /dev/null +++ b/packages/ui/lib/components/PlayerButton/styles.scss @@ -0,0 +1,4 @@ +.player_button { + background: transparent; + border: none; +} \ No newline at end of file diff --git a/packages/ui/lib/components/PlayerControls/index.tsx b/packages/ui/lib/components/PlayerControls/index.tsx new file mode 100644 index 0000000000..3b2b87f50b --- /dev/null +++ b/packages/ui/lib/components/PlayerControls/index.tsx @@ -0,0 +1,47 @@ +import React from 'react'; + +import PlayerButton from '../PlayerButton'; + +import styles from './styles.scss'; + +export type PlayerControlsProps = { + goForward?: () => void; + goBack?: () => void; + togglePlay?: () => void; + isPlaying?: boolean; + isLoading?: boolean; +}; + +const PlayerControls: React.FC = ({ + goForward, + goBack, + togglePlay, + isPlaying, + isLoading +}) => ( +
+ + + +
+ ) + +export default PlayerControls; \ No newline at end of file diff --git a/packages/ui/lib/components/PlayerControls/styles.scss b/packages/ui/lib/components/PlayerControls/styles.scss new file mode 100644 index 0000000000..cfe81ad725 --- /dev/null +++ b/packages/ui/lib/components/PlayerControls/styles.scss @@ -0,0 +1,12 @@ +.player_controls { + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + + &>* { + flex: 1 1 33.3%; + width: 33.3%; + min-width: 33.3%; + } +} \ No newline at end of file diff --git a/packages/ui/lib/components/Seekbar/index.js b/packages/ui/lib/components/Seekbar/index.tsx similarity index 53% rename from packages/ui/lib/components/Seekbar/index.js rename to packages/ui/lib/components/Seekbar/index.tsx index 26d906a8d5..0b9f01d866 100644 --- a/packages/ui/lib/components/Seekbar/index.js +++ b/packages/ui/lib/components/Seekbar/index.tsx @@ -1,42 +1,53 @@ import React from 'react'; -import PropTypes from 'prop-types'; import cx from 'classnames'; import common from '../../common.scss'; import styles from './styles.scss'; +type QueueItem = { + streams: { duration: number }[]; +}; + +export type SeekbarProps = { + children: React.ReactNode; + fill: number; + seek: (arg0: number) => void; + queue: { queueItems: QueueItem[] }; +}; + const handleClick = (seek, queue) => { return event => { - const percent = (event.pageX - event.target.offsetLeft)/document.body.clientWidth; + const percent = (event.pageX - event.target.offsetLeft) / document.body.clientWidth; const duration = queue.queueItems[queue.currentSong].streams[0].duration; seek(percent * duration * 1000); }; }; -const Seekbar = props => { +const Seekbar: React.FC = ({ + children, + fill, + seek, + queue +}) => { return (
+ > + {children} +
); }; -Seekbar.propTypes = { - fill: PropTypes.string, - seek: PropTypes.func, - queue: PropTypes.object -}; - export default Seekbar; diff --git a/packages/ui/lib/components/Seekbar/styles.scss b/packages/ui/lib/components/Seekbar/styles.scss index 2c25328582..3c3dd1f39c 100644 --- a/packages/ui/lib/components/Seekbar/styles.scss +++ b/packages/ui/lib/components/Seekbar/styles.scss @@ -1,7 +1,7 @@ @import '../../common.scss'; .seekbar_container { - height: 4px; + height: 1em; cursor: pointer; background-color: transparent; flex: 0 0 auto; diff --git a/packages/ui/lib/components/TrackInfo/index.tsx b/packages/ui/lib/components/TrackInfo/index.tsx new file mode 100644 index 0000000000..3cd74efbc3 --- /dev/null +++ b/packages/ui/lib/components/TrackInfo/index.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import { Icon } from 'semantic-ui-react'; + +import Cover from '../Cover'; +import styles from './styles.scss'; + +export type TrackInfoProps = { + cover?: string; + track: string; + artist: string; + onTrackClick: () => void; + onArtistClick: () => void; + addToFavorites: () => void; + isFavorite?: boolean; +}; + +const TrackInfo: React.FC = ({ + cover, + track, + artist, + onTrackClick, + onArtistClick, + addToFavorites, + isFavorite +}) => ( +
+ +
+
+ {track} +
+
+ {artist} +
+
+
+ +
+
+ ); + +export default TrackInfo; \ No newline at end of file diff --git a/packages/ui/lib/components/TrackInfo/styles.scss b/packages/ui/lib/components/TrackInfo/styles.scss new file mode 100644 index 0000000000..6c66e901c0 --- /dev/null +++ b/packages/ui/lib/components/TrackInfo/styles.scss @@ -0,0 +1,33 @@ +@import '../../common.scss'; + +.track_info { + display: flex; + flex-flow: row; + flex: 1 1 50%; + + &>*:not(:first-child) { + padding-left: 1em; + } + + .artist_part { + display: flex; + flex-flow: column; + justify-content: space-evenly; + align-items: flex-start; + } + + .track_name { + font-size: 22px; + } + + .artist_name { + font-size: 14px; + color: rgba($white, 0.6); + } + + .favorite_part { + display: flex; + flex-flow: column; + justify-content: center; + } +} diff --git a/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx b/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx new file mode 100644 index 0000000000..1e2751b6db --- /dev/null +++ b/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { Icon, SemanticICONS } from 'semantic-ui-react'; + +import styles from './styles.scss'; + +export type PlayOptionControlProps = { + icon: SemanticICONS; + enabled?: boolean; + onToggle?: () => void; +}; + +const PlayOptionControl: React.FC = ({ + icon, + enabled = true, + onToggle +}) => ( + + ); + +export type PlayOptionsProps = { + playOptions: PlayOptionControlProps[] +}; + +const PlayOptions: React.FC = ({ + playOptions +}) => ( +
+ { + playOptions.map(playOption => ) + } +
+ ) + +export default PlayOptions; \ No newline at end of file diff --git a/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss b/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss new file mode 100644 index 0000000000..1cdb2fcd14 --- /dev/null +++ b/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss @@ -0,0 +1,5 @@ +.play_options { + .play_option_icon { + margin-right: 1em; + } +} \ No newline at end of file diff --git a/packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx b/packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx new file mode 100644 index 0000000000..8d141dd877 --- /dev/null +++ b/packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +import Range from '../../Range'; + +import styles from './styles.scss'; + +export type VolumeSliderProps = { + setVolume: (value: number) => void; + toggleMute: () => void; + isMuted: boolean; +}; + +const VolumeSlider: React.FC = ({ + setVolume, + toggleMute, + isMuted +}) => ( +
{ }} + > + +
+ ) + +export default VolumeSlider; \ No newline at end of file diff --git a/packages/ui/lib/components/VolumeControls/VolumeSlider/styles.scss b/packages/ui/lib/components/VolumeControls/VolumeSlider/styles.scss new file mode 100644 index 0000000000..0fc52009bd --- /dev/null +++ b/packages/ui/lib/components/VolumeControls/VolumeSlider/styles.scss @@ -0,0 +1,7 @@ +.volume_slider { + position: relative; + display: flex; + align-items: center; + cursor: pointer; + flex: 0 0 150px; +} \ No newline at end of file diff --git a/packages/ui/lib/components/VolumeControls/index.tsx b/packages/ui/lib/components/VolumeControls/index.tsx new file mode 100644 index 0000000000..b1ae9615a9 --- /dev/null +++ b/packages/ui/lib/components/VolumeControls/index.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { Icon } from 'semantic-ui-react'; + +import VolumeSlider, { VolumeSliderProps } from './VolumeSlider'; +import PlayOptions, { PlayOptionsProps } from './PlayOptions'; + +import styles from './styles.scss'; + +export type VolumeControlsProps = VolumeSliderProps & PlayOptionsProps & { + volume: number; +}; + +const VolumeControls: React.FC = ({ + volume, + setVolume, + toggleMute, + isMuted, + playOptions +}) => ( +
+ + 40 + ? 'volume up' + : 'volume down' + } + /> + +
+ ); + +export default VolumeControls; \ No newline at end of file diff --git a/packages/ui/lib/components/VolumeControls/styles.scss b/packages/ui/lib/components/VolumeControls/styles.scss new file mode 100644 index 0000000000..888a7830ea --- /dev/null +++ b/packages/ui/lib/components/VolumeControls/styles.scss @@ -0,0 +1,11 @@ +.volume_controls { + display: flex; + justify-content: flex-end; + + padding-right: 1em; + flex: 1 1 50%; + + .volume_icon { + cursor: pointer; + } +} diff --git a/packages/ui/lib/index.js b/packages/ui/lib/index.js index 02602e4fe4..a18ac6488c 100644 --- a/packages/ui/lib/index.js +++ b/packages/ui/lib/index.js @@ -10,6 +10,8 @@ export { default as Cover } from './components/Cover'; export { default as SmoothImage } from './components/SmoothImage'; export { default as LibraryListTypeToggle } from './components/LibraryListTypeToggle'; export { default as Loader } from './components/Loader'; +export { default as PlayerBar } from './components/PlayerBar'; +export { default as PlayerButton } from './components/PlayerButton'; export { default as PopupButton } from './components/PopupButton'; export { default as PopupDropdown } from './components/PopupDropdown'; export { default as QueueItem } from './components/QueueItem'; diff --git a/packages/ui/stories/playerBar.stories.tsx b/packages/ui/stories/playerBar.stories.tsx new file mode 100644 index 0000000000..04729439cc --- /dev/null +++ b/packages/ui/stories/playerBar.stories.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +import { PlayerBar } from '..'; + +export default { + title: 'Player bar' +}; + +export const DefaultStyle = () =>
+ + {}} + queue={{ queueItems: [] }} + playOptions={[ + {icon: 'repeat', enabled: false}, + {icon: 'magic'}, + {icon: 'random', enabled: false} + ]} + /> +
; \ No newline at end of file diff --git a/packages/ui/stories/playerButton.stories.tsx b/packages/ui/stories/playerButton.stories.tsx new file mode 100644 index 0000000000..6e6358c3f5 --- /dev/null +++ b/packages/ui/stories/playerButton.stories.tsx @@ -0,0 +1,46 @@ +import React, { useState } from 'react'; + +import { PlayerButton } from '..'; + +export default { + title: 'Player button' +} + +export const PlayButton = () => { + const [icon, setIcon] = useState('play'); + const onClick = () => { + if (icon === 'play') { + setIcon('pause'); + } else { + setIcon('play'); + } + } + + return
+ +
; +} + +export const PlayerControls = () =>
+ + + +
\ No newline at end of file From c30e02aa0d51d9d0e6d33b7252fcceff0a4b2604 Mon Sep 17 00:00:00 2001 From: advaithm <30698906+advaithm@users.noreply.github.com> Date: Sun, 5 Jul 2020 16:44:23 +0530 Subject: [PATCH 16/63] updated to flatpak spec (#732) * created manifst file * flatpak support * fixing configs * fixing configs * fixing configs * trying to use network to fix the caching issues * fixed npm cache issuesgit add .git add . * fixed sandbox perms * removed uneeded files * working on the build stage * typo * typo * install lerna gloably * fixing stuff * fixing path * fixing path * updated readme * updated name * renamed app * updated to flathub version * Delete CHANGELOG.md * reworked to use binaries * added appstream.xml * added appstream.xml.gz * updated appstream.xml.gz * renamed files * renamed files * added desktop file * added icons * fixed path in desktop file * set varible path * Update org.js.nuclear.Nuclear.desktop * set icon * Update org.js.nuclear.Nuclear.desktop * fixed wrong binary path * Revert "fixed wrong binary path" This reverts commit 6dc09322721f130e4af54dea277ebfba2e21e6e3. * fixed wrong binary path * updated files --- flatpak/flathub.json | 3 + flatpak/org.js.nuclear.Nuclear.desktop | 9 +++ flatpak/org.js.nuclear.Nuclear.json | 76 ++++++++++----------- flatpak/org.js.nuclear.Nuclear.metainfo.xml | 75 ++++++++++++++++++++ 4 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 flatpak/flathub.json create mode 100644 flatpak/org.js.nuclear.Nuclear.desktop create mode 100644 flatpak/org.js.nuclear.Nuclear.metainfo.xml diff --git a/flatpak/flathub.json b/flatpak/flathub.json new file mode 100644 index 0000000000..2d2a0caee5 --- /dev/null +++ b/flatpak/flathub.json @@ -0,0 +1,3 @@ +{ + "only-arches":["x86_64"] +} diff --git a/flatpak/org.js.nuclear.Nuclear.desktop b/flatpak/org.js.nuclear.Nuclear.desktop new file mode 100644 index 0000000000..e2b7d28b89 --- /dev/null +++ b/flatpak/org.js.nuclear.Nuclear.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Nuclear +Comment=Streaming music player that finds music sources automatically. +Comment[es]=Reproductor que retransmite música desde fuentes encontradas automáticamente. +Exec="/app/bin/run.sh" +Terminal=false +Type=Application +Icon=org.js.nuclear.Nuclear +Categories=Audio;AudioVideo;Network;Player;Music; diff --git a/flatpak/org.js.nuclear.Nuclear.json b/flatpak/org.js.nuclear.Nuclear.json index dd6a1e162f..5f3f870d7e 100644 --- a/flatpak/org.js.nuclear.Nuclear.json +++ b/flatpak/org.js.nuclear.Nuclear.json @@ -1,59 +1,51 @@ { - "app-id": "org.js,nuclear.Nuclear", + "app-id": "org.js.nuclear.Nuclear", "runtime": "org.freedesktop.Platform", "runtime-version": "19.08", "branch": "19.08", "sdk": "org.freedesktop.Sdk", "base": "io.atom.electron.BaseApp", + "separate-locales": "false", "command": "run.sh", "finish-args": [ "--share=network", "--share=ipc", "--socket=x11", - "--filesystem=host" + "--filesystem=host", + "--socket=pulseaudio" ], "build-options" : { - "build-args": [ "--share=network" ], - "cflags": "-O2 -g", - "cxxflags": "-O2 -g", "env": { "NPM_CONFIG_LOGLEVEL": "info" } }, "modules": [ - { - "name": "nodejs", - "cleanup": [ - "/include", - "/share", - "/app/lib/node_modules/npm/changelogs", - "/app/lib/node_modules/npm/doc", - "/app/lib/node_modules/npm/html", - "/app/lib/node_modules/npm/man", - "/app/lib/node_modules/npm/scripts" - ], - "sources": [ - { - "type": "archive", - "url": "https://github.com/nodejs/node/archive/v14.5.0.zip", - "sha256": "b7e6ec14abc67879460d3693d95d6b0e8cc0beedbb6b946d61989575f7b544a7" - } - ] - }, { "name": "nuclear", - "build-options" : { - "env": { - "electron_config_cache": "/run/build/nuclear/npm-cache" - } - }, - "buildsystem": "simple", - "sources": [ + "buildsystem": "simple", + "sources": [ { "type": "archive", - "url": "https://github.com/nukeop/nuclear/archive/v0.6.3.zip", - "sha256": "88101d4cacce0b9e9e7389656a8bd7a039e77fa16214a75c5c960f4052a3ed74", - "dest":"main" + "url": "https://github.com/nukeop/nuclear/releases/download/v0.6.3/nuclear-fca030.tar.gz", + "sha256": "5b90a1064736c158f62ea74c5814dffdd25f8b6a3877dfeed065377e744cdd2e" + }, + { + "type":"file", + "url":"https://raw.githubusercontent.com/advaithm/nuclear/master/flatpak/org.js.nuclear.Nuclear.metainfo.xml", + "sha256":"17f2d8221f3cfec579457c05a4a56b85dcff2dd44bc86d5a2bca85e088af7c39", + "dest-filename":"org.js.nuclear.Nuclear.metainfo.xml" + }, + { + "type":"file", + "url":"https://raw.githubusercontent.com/advaithm/nuclear/master/flatpak/org.js.nuclear.Nuclear.desktop", + "sha256":"61256cb50cbfa54d93b9c344f4795f42f7dc73cd195be17915403d0ac281ce88", + "dest-filename":"org.js.nuclear.Nuclear.desktop" + }, + { + "type":"file", + "url":"https://github.com/nukeop/nuclear/raw/master/build/512.png", + "sha1":"f7568bc736304246d054faa7cf528c3e8bc0a6d5", + "dest-filename":"org.js.nuclear.Nuclear.png" }, { "type": "script", @@ -63,13 +55,15 @@ ], "build-commands": [ - "npm install --prefix=main", - "npm install -g lerna", - "cd main && lerna bootstrap", - "cd ..", - "npm run build --prefix=main", - "mkdir -p /app/main /app/bin", - "cp -ra main/release/linux-unpacked/* /app/main/", + "mkdir -p /app/main /app/bin", + "cp -ra * /app/main/", + "mkdir -p /app/share/metainfo/", + "mkdir -p /app/share/icons/hicolor/512x512/apps/", + "mkdir -p /app/share/applications/", + "cp -r org.js.nuclear.Nuclear.png /app/share/icons/hicolor/512x512/apps/", + "ls /app/share/icons/hicolor/512x512/apps/", + "cp -r org.js.nuclear.Nuclear.metainfo.xml /app/share/metainfo/", + "cp -r org.js.nuclear.Nuclear.desktop /app/share/applications/", "install run.sh /app/bin/" ] } diff --git a/flatpak/org.js.nuclear.Nuclear.metainfo.xml b/flatpak/org.js.nuclear.Nuclear.metainfo.xml new file mode 100644 index 0000000000..a4cc1abfd0 --- /dev/null +++ b/flatpak/org.js.nuclear.Nuclear.metainfo.xml @@ -0,0 +1,75 @@ + + + org.js.nuclear.Nuclear + FSFAP + GPL-3.0+ + nuclear music player + A electron based music player + + +

nuclear is a free music streaming program that pulls content from free sources all over the internet.

+ +

If you know mps-youtube, this is a similar music player but with a GUI. + It's also focusing more on audio. Imagine Spotify which you don't have to pay for and with a bigger library.

+ +

Features

+
    +
  • - Searching for and playing music from YouTube (including integration with playlists), Jamendo, and SoundCloud
  • +
  • - Searching for albums (powered by Last.fm and Discogs), album view, automatic song lookup based on artist and track name (in progress, can be dodgy sometimes)
  • +
  • - Song queue, which can be exported as a playlist
  • +
  • - Loading saved playlists (stored in json files)
  • +
  • - Scrobbling to last.fm (along with updating the 'now playing' status)
  • +
  • - Newest releases with reviews - tracks and albums
  • +
  • - Browsing by genre
  • +
  • - Radio mode (automatically queue similar tracks)
  • +
  • - Unlimited downloads (powered by youtube)
  • +
  • - Realtime lyrics
  • +
  • - Browsing by popularity
  • +
  • - List of favorite tracks
  • +
  • - Listening from local library
  • +
+
+ org.js.nuclear.Nuclear.desktop + + + Album Search + https://i.imgur.com/idFVnAF.png + + + Album Display + https://i.imgur.com/Kvzo3q7.png + + + Dashboard Best New Music + https://i.imgur.com/bMDrR4M.png + + + Dashboard Genres + https://i.imgur.com/g0aCmKx.png) + + + Playlist View + https://i.imgur.com/2VMXHDC.png + + + Lyrics View + https://i.imgur.com/7e3DJKJ.png + + + Equalizer View + https://i.imgur.com/WreRL0w.png + + + https://nuclear.js.org + Nuclear + + Nuclear + + + + +

This release fixes the recent issues where queue items would keep loading indefinitely.

+
+
+
+
From 35a35cd90be2548693e23e2f060a0a83dbdba9af Mon Sep 17 00:00:00 2001 From: nukeop <12746779+nukeop@users.noreply.github.com> Date: Sun, 5 Jul 2020 11:37:55 +0000 Subject: [PATCH 17/63] Update README.md --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2885020238..3a1a6fa5ab 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,10 @@ Here's a list of packages for various managers, most of which are maintained by | Choco (Win) | https://chocolatey.org/packages/nuclear/ | [JourneyOver](https://github.com/JourneyOver) | | Homebrew (Mac) | https://formulae.brew.sh/cask/nuclear | Homebrew | | Snap | https://snapcraft.io/nuclear | [nukeop](https://github.com/nukeop) | -|flatpak |(to be publised) | [advaithm](https://github.com/advaithm) +| + + +|(to be publised) | [advaithm](https://github.com/advaithm) big thanks to [ayyeve](https://github.com/ayyEve) for letting me (advaithm) use her server as a compile machince. ## Community translations Nuclear has already been translated to several languages, and we're always looking for contributors who would like to add more. Below is a list of currently available languages, along with contributors who helped to translate Nuclear to that language. @@ -113,21 +116,21 @@ You will need docker and docker-compose. You need to allow the root user to conn $ xhost SI:localuser:root $ sudo docker-compose up dev ``` -as of now you can build a flatpak version. you will need to install gobject-introspection, and flatpak-builder. after this you will need to install the runtimes and depedencies required by flatapk-builder for the compile process. when this was written you will need the 19.08 version of these flatpaks. +As of now you can also build a flatpak version. You will need to install gobject-introspection, and flatpak-builder. After this you will need to install the runtimes and depedencies required by flatapk-builder for the compile process. You will need the 19.08 version of these flatpaks. ```shell $ flatpak install flathub org.freedesktop.Platform $ flatpak install flathub org.freedesktop.Sdk $ flatpak install flathub io.atom.electron.BaseApp ``` -next to build the project use the `--verbose` to get more out put +Next, to build the project (use the `--verbose` flag to get more output): ```shell -$ flatpak-builder build-dir org.flathub.nuclear.json +$ flatpak-builder build-dir org.js.nuclear.Nuclear.json ``` -to run the built app +To run the built app: ```shell -$ flatpak-builder --run build-dir org.flathub.nuclear.json run.sh +$ flatpak-builder --run build-dir org.js.nuclear.Nuclear.json run.sh ``` -you can turn the app to a local repo. currently the file builds the latest release. +You can turn the app to a local repo. currently the file builds the latest release. ## Screenshots This will be updated as the program evolves. From ee9c9c416984e77f327a72c3bbd119ae38586def Mon Sep 17 00:00:00 2001 From: nukeop <12746779+nukeop@users.noreply.github.com> Date: Sun, 5 Jul 2020 11:44:15 +0000 Subject: [PATCH 18/63] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a1a6fa5ab..ebaa25c215 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,9 @@ Here's a list of packages for various managers, most of which are maintained by | Choco (Win) | https://chocolatey.org/packages/nuclear/ | [JourneyOver](https://github.com/JourneyOver) | | Homebrew (Mac) | https://formulae.brew.sh/cask/nuclear | Homebrew | | Snap | https://snapcraft.io/nuclear | [nukeop](https://github.com/nukeop) | -| +|Flatpak |(to be published) | [advaithm](https://github.com/advaithm) | - -|(to be publised) | [advaithm](https://github.com/advaithm) -big thanks to [ayyeve](https://github.com/ayyEve) for letting me (advaithm) use her server as a compile machince. +big thanks to [ayyeve](https://github.com/ayyEve) for letting me (advaithm) use her server as a compile machine. ## Community translations Nuclear has already been translated to several languages, and we're always looking for contributors who would like to add more. Below is a list of currently available languages, along with contributors who helped to translate Nuclear to that language. From 2347e5e7d601aecc861979e73382e681d512c97a Mon Sep 17 00:00:00 2001 From: nukeop <12746779+nukeop@users.noreply.github.com> Date: Sun, 5 Jul 2020 11:47:16 +0000 Subject: [PATCH 19/63] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebaa25c215..06ce13a302 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Here's a list of packages for various managers, most of which are maintained by | Choco (Win) | https://chocolatey.org/packages/nuclear/ | [JourneyOver](https://github.com/JourneyOver) | | Homebrew (Mac) | https://formulae.brew.sh/cask/nuclear | Homebrew | | Snap | https://snapcraft.io/nuclear | [nukeop](https://github.com/nukeop) | -|Flatpak |(to be published) | [advaithm](https://github.com/advaithm) | +|Flatpak |(to be approved) | [advaithm](https://github.com/advaithm) | big thanks to [ayyeve](https://github.com/ayyEve) for letting me (advaithm) use her server as a compile machine. ## Community translations From f619026606ed8f81ba98eb9496e24cfaacdfd1db Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 16 Jul 2020 02:25:56 +0200 Subject: [PATCH 20/63] Player bar replacement wip --- packages/app/app/App.js | 40 ++++++++++--------- .../containers/PlayerBarContainer/hooks.js | 30 ++++++++++++++ .../containers/PlayerBarContainer/index.js | 38 ++++++++++++++++++ packages/app/app/selectors/player.js | 11 +++++ packages/app/app/selectors/queue.js | 1 + .../ui/lib/components/PlayerBar/index.tsx | 12 ++++-- .../ui/lib/components/PlayerBar/styles.scss | 12 ++++++ packages/ui/lib/components/Seekbar/index.tsx | 4 +- .../ui/lib/components/Seekbar/styles.scss | 19 +++++---- packages/ui/stories/playerBar.stories.tsx | 39 +++++++++--------- tsconfig.json | 1 + 11 files changed, 159 insertions(+), 48 deletions(-) create mode 100644 packages/app/app/containers/PlayerBarContainer/hooks.js create mode 100644 packages/app/app/containers/PlayerBarContainer/index.js create mode 100644 packages/app/app/selectors/player.js create mode 100644 packages/app/app/selectors/queue.js diff --git a/packages/app/app/App.js b/packages/app/app/App.js index 77228978b6..9f0ff2627e 100644 --- a/packages/app/app/App.js +++ b/packages/app/app/App.js @@ -42,6 +42,7 @@ import HelpModalContainer from './containers/HelpModalContainer'; import MainContentContainer from './containers/MainContentContainer'; import PlayQueueContainer from './containers/PlayQueueContainer'; import SearchBoxContainer from './containers/SearchBoxContainer'; +import PlayerBarContainer from './containers/PlayerBarContainer'; import IpcContainer from './containers/IpcContainer'; import SoundContainer from './containers/SoundContainer'; @@ -250,27 +251,30 @@ class App extends React.PureComponent { renderFooter () { return ( -
- - { - this.props.settings.trackDuration && + <> + +
+ + { + this.props.settings.trackDuration && !_.isNil(this.props.queue.queueItems[this.props.queue.currentSong]) && this.renderTrackDuration() - } - -
-
- {this.renderCover()} - {this.renderTrackInfo()} + } + +
+
+ {this.renderCover()} + {this.renderTrackInfo()} +
+ {this.renderPlayerControls()} + {this.renderVolumeControl()}
- {this.renderPlayerControls()} - {this.renderVolumeControl()} -
-
+
+ ); } diff --git a/packages/app/app/containers/PlayerBarContainer/hooks.js b/packages/app/app/containers/PlayerBarContainer/hooks.js new file mode 100644 index 0000000000..cb6f6b03a5 --- /dev/null +++ b/packages/app/app/containers/PlayerBarContainer/hooks.js @@ -0,0 +1,30 @@ +import { formatDuration } from '@nuclear/ui'; +import { useSelector } from 'react-redux'; + +import { playerSelectors } from '../../selectors/player'; +import { queue as queueSelector } from '../../selectors/queue'; + +export const useSeekbarProps = () => { + const queue = useSelector(queueSelector); + const seek = useSelector(playerSelectors.seek); + const currentTrackStream = _.head( + _.get( + queue.queueItems[queue.currentSong], + 'streams' + ) + ); + + const currentTrackDuration = _.get( + currentTrackStream, + 'duration' + ); + + const timeToEnd = currentTrackDuration - seek; + + return { + queue, + timePlayed: formatDuration(seek), + timeToEnd: formatDuration(timeToEnd) + }; +}; + diff --git a/packages/app/app/containers/PlayerBarContainer/index.js b/packages/app/app/containers/PlayerBarContainer/index.js new file mode 100644 index 0000000000..bd1e2ce798 --- /dev/null +++ b/packages/app/app/containers/PlayerBarContainer/index.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { useSelector /* useDispatch*/ } from 'react-redux'; +import Sound from 'react-hifi'; +import { PlayerBar } from '@nuclear/ui'; + +// import * as PlayerActions from '../../actions/player'; +import { playerSelectors } from '../../selectors/player'; +import { useSeekbarProps } from './hooks'; + +const PlayerBarContainer = () => { + // const dispatch = useDispatch(); + const playbackProgress = useSelector(playerSelectors.playbackProgress); + const playbackStatus = useSelector(playerSelectors.playbackStatus); + const playbackStreamLoading = useSelector(playerSelectors.playbackStreamLoading); + + const seekbarProps = useSeekbarProps(); + + return ( + + ); +}; + +export default PlayerBarContainer; diff --git a/packages/app/app/selectors/player.js b/packages/app/app/selectors/player.js new file mode 100644 index 0000000000..acf997d196 --- /dev/null +++ b/packages/app/app/selectors/player.js @@ -0,0 +1,11 @@ +import { createStateSelectors } from './helpers'; + +export const playerSelectors = createStateSelectors( + 'player', + [ + 'playbackProgress', + 'playbackStatus', + 'playbackStreamLoading', + 'seek' + ] +); diff --git a/packages/app/app/selectors/queue.js b/packages/app/app/selectors/queue.js new file mode 100644 index 0000000000..cd6506e8a1 --- /dev/null +++ b/packages/app/app/selectors/queue.js @@ -0,0 +1 @@ +export const queue = s => s.queue; diff --git a/packages/ui/lib/components/PlayerBar/index.tsx b/packages/ui/lib/components/PlayerBar/index.tsx index e3979d3afa..7c631ed4c0 100644 --- a/packages/ui/lib/components/PlayerBar/index.tsx +++ b/packages/ui/lib/components/PlayerBar/index.tsx @@ -14,6 +14,8 @@ export type PlayerBarProps = PlayerControlsProps & TrackInfoProps & VolumeControlsProps & { renderTrackDuration?: boolean; + timePlayed?: string; + timeToEnd?: string; }; const PlayerBar: React.FC = ({ @@ -24,7 +26,7 @@ const PlayerBar: React.FC = ({ onArtistClick, addToFavorites, isFavorite, - + volume, setVolume, toggleMute, @@ -40,6 +42,8 @@ const PlayerBar: React.FC = ({ queue, fill = 0, renderTrackDuration = false, + timePlayed, + timeToEnd, seek }) => (
= ({ queue={queue} > { - renderTrackDuration && 'trackDuration' - + renderTrackDuration &&
+
{timePlayed}
+
{timeToEnd}
+
}
diff --git a/packages/ui/lib/components/PlayerBar/styles.scss b/packages/ui/lib/components/PlayerBar/styles.scss index 18f2547229..303ec690a0 100644 --- a/packages/ui/lib/components/PlayerBar/styles.scss +++ b/packages/ui/lib/components/PlayerBar/styles.scss @@ -21,4 +21,16 @@ width: 100%; max-width: 100%; } + + .track_duration { + position: absolute; + display: flex; + flex-flow: row; + justify-content: space-between; + align-items: center; + + padding: 0 .5em; + height: 100%; + width: 100%; + } } diff --git a/packages/ui/lib/components/Seekbar/index.tsx b/packages/ui/lib/components/Seekbar/index.tsx index 0b9f01d866..1d48fe0a9d 100644 --- a/packages/ui/lib/components/Seekbar/index.tsx +++ b/packages/ui/lib/components/Seekbar/index.tsx @@ -33,7 +33,7 @@ const Seekbar: React.FC = ({
@@ -41,7 +41,7 @@ const Seekbar: React.FC = ({ style={{ width: `${fill}%` }} className={cx( common.nuclear, - styles.seekbar_fill + styles.seekbar_progress )} > {children} diff --git a/packages/ui/lib/components/Seekbar/styles.scss b/packages/ui/lib/components/Seekbar/styles.scss index 3c3dd1f39c..4dd4a009a8 100644 --- a/packages/ui/lib/components/Seekbar/styles.scss +++ b/packages/ui/lib/components/Seekbar/styles.scss @@ -1,13 +1,18 @@ @import '../../common.scss'; -.seekbar_container { - height: 1em; +.seekbar { + position: relative; + height: 1.25em; cursor: pointer; - background-color: transparent; + background-color: $background2; flex: 0 0 auto; -} -.seekbar_fill { - height: 100%; - background-color: $pink; + &:hover { + height: 1.5em; + } + + .seekbar_progress { + height: 100%; + background-color: $pink; + } } diff --git a/packages/ui/stories/playerBar.stories.tsx b/packages/ui/stories/playerBar.stories.tsx index 04729439cc..812a1ddf69 100644 --- a/packages/ui/stories/playerBar.stories.tsx +++ b/packages/ui/stories/playerBar.stories.tsx @@ -6,25 +6,28 @@ export default { title: 'Player bar' }; -export const DefaultStyle = () =>
- + {}} - queue={{ queueItems: [] }} - playOptions={[ - {icon: 'repeat', enabled: false}, - {icon: 'magic'}, - {icon: 'random', enabled: false} - ]} + renderTrackDuration + timePlayed='-3:14' + timeToEnd='2:43' + fill={66} + track='Test song' + artist='Test artist' + volume={60} + seek={() => { }} + queue={{ queueItems: [] }} + playOptions={[ + { icon: 'repeat', enabled: false }, + { icon: 'magic' }, + { icon: 'random', enabled: false } + ]} />
; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7f9e47bdbd..640b1e43bf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "jsx": "react", "moduleResolution": "node", "target": "ESNext", "module":"ESNext", From 2186aa61a9b4887d76c3dccc79b745d52864e1cd Mon Sep 17 00:00:00 2001 From: michaelding123 <42223220+michaelding123@users.noreply.github.com> Date: Thu, 16 Jul 2020 13:08:00 -0700 Subject: [PATCH 21/63] Deleting tracks from playlist #337 (#734) --- .../components/FavoriteTracksView/index.js | 1 + .../app/app/components/PlaylistView/index.js | 29 +++++++++++++------ packages/app/app/components/TrackRow/index.js | 1 + 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/app/app/components/FavoriteTracksView/index.js b/packages/app/app/components/FavoriteTracksView/index.js index 57497e2f37..34e865d3a3 100644 --- a/packages/app/app/components/FavoriteTracksView/index.js +++ b/packages/app/app/components/FavoriteTracksView/index.js @@ -150,3 +150,4 @@ FavoriteTracksView.defaultProps = { }; export default FavoriteTracksView; + diff --git a/packages/app/app/components/PlaylistView/index.js b/packages/app/app/components/PlaylistView/index.js index bb58e9c6ab..d1d197f9cb 100644 --- a/packages/app/app/components/PlaylistView/index.js +++ b/packages/app/app/components/PlaylistView/index.js @@ -26,12 +26,17 @@ class PlaylistView extends React.Component { this.props.startPlayback(); } + removeTrack(playlist, trackToRemove) { + const newPlaylist = _.cloneDeep(playlist); + newPlaylist.tracks = _.filter(newPlaylist.tracks, track => track.uuid !== trackToRemove.uuid); + this.props.updatePlaylist(newPlaylist); + } + deletePlaylist(playlist) { const { history, deletePlaylist } = this.props; - deletePlaylist(playlist.id); history.push('/playlists'); } @@ -74,7 +79,6 @@ class PlaylistView extends React.Component { } renderPlayButton (playlist) { - return ( + {this.props.t('')} {this.props.t('artist')} {this.props.t('title')} @@ -155,13 +160,19 @@ class PlaylistView extends React.Component { _.set(newTrack, 'artist.name', newTrack.artist); _.set(newTrack, 'image[0][\'#text\']', newTrack.thumbnail); - return (< TrackRow - key={'playlist-track-row-' + index} - track={newTrack} - index={'playlist-track-' + index} - displayCover - displayArtist - /> + return ( + < TrackRow + key={'playlist-track-row-' + index} + track={newTrack} + index={'playlist-track-' + index} + displayCover + displayArtist + withDeleteButton + onDelete={e => { + e.stopPropagation(); + this.removeTrack(this.props.playlist, track); + }} + /> ); } diff --git a/packages/app/app/components/TrackRow/index.js b/packages/app/app/components/TrackRow/index.js index 30211128bb..3239c607ab 100644 --- a/packages/app/app/components/TrackRow/index.js +++ b/packages/app/app/components/TrackRow/index.js @@ -186,3 +186,4 @@ export default connect( mapStateToProps, mapDispatchToProps )(TrackRow); + From 9ca53efd5ebbb36fbb43c6cfa54390ad09e5a67d Mon Sep 17 00:00:00 2001 From: Sandeep Reddy Date: Fri, 17 Jul 2020 03:27:40 +0530 Subject: [PATCH 22/63] Fix genre images out of sync (#740) * fix: text overflow in genres * fix: genre images not showing up * fix: build failure in linux env --- .travis.yml | 2 +- .../app/app/components/Dashboard/GenresTab/mapGenres.js | 6 ++---- packages/app/app/components/Dashboard/GenresTab/styles.scss | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa0f6ec9c3..9f11217a2f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ env: - GITHASH=${TRAVIS_COMMIT::6} before_install: - - if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get install libdbus-1-dev -y; fi + - if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get install libdbus-1-dev rpm -y; fi script: - if [ "$TRAVIS_OS_NAME" == "linux" ]; then npm test && npm run build:linux; fi diff --git a/packages/app/app/components/Dashboard/GenresTab/mapGenres.js b/packages/app/app/components/Dashboard/GenresTab/mapGenres.js index 88cb5f8ec3..ab77d34169 100644 --- a/packages/app/app/components/Dashboard/GenresTab/mapGenres.js +++ b/packages/app/app/components/Dashboard/GenresTab/mapGenres.js @@ -27,14 +27,13 @@ import trending from '../../../../resources/musicgenresicons/outline/trending.sv import vocal from '../../../../resources/musicgenresicons/outline/vocal.svg'; export default genre => { - switch (genre) { + switch (genre.toLowerCase()) { case 'blues': return blues; case 'rock': case 'classic rock': case 'post-rock': case 'progressive rock': - case 'Progressive rock': return rock; case 'country': return country; @@ -82,12 +81,11 @@ export default genre => { case 'punk rock': case 'hardcore': return punk; - case 'Hip-Hop': + case 'hip-hop': case 'hip hop': case 'rap': return hiphop; case 'classical': - case 'Classical': case 'instrumental': case 'soundtrack': return classical; diff --git a/packages/app/app/components/Dashboard/GenresTab/styles.scss b/packages/app/app/components/Dashboard/GenresTab/styles.scss index 36b501b521..da433495fa 100644 --- a/packages/app/app/components/Dashboard/GenresTab/styles.scss +++ b/packages/app/app/components/Dashboard/GenresTab/styles.scss @@ -62,7 +62,7 @@ flex-flow: column; justify-content: center; align-items: center; - font-size: 1.5rem; + font-size: 1rem; letter-spacing: 4px; text-transform: uppercase; text-align: center; From fcba451e88677ee270f421e72b299f793fca88e4 Mon Sep 17 00:00:00 2001 From: nukeop Date: Fri, 17 Jul 2020 02:05:06 +0200 Subject: [PATCH 23/63] Player bar hooks --- .../containers/PlayerBarContainer/hooks.js | 71 +++++++++++++++++-- .../containers/PlayerBarContainer/index.js | 24 +++---- packages/app/package.json | 1 + .../ui/lib/components/PlayerBar/index.tsx | 6 ++ .../ui/lib/components/PlayerButton/index.tsx | 10 ++- .../lib/components/PlayerButton/styles.scss | 7 ++ .../lib/components/PlayerControls/index.tsx | 12 +++- 7 files changed, 109 insertions(+), 22 deletions(-) diff --git a/packages/app/app/containers/PlayerBarContainer/hooks.js b/packages/app/app/containers/PlayerBarContainer/hooks.js index cb6f6b03a5..5a7aecafb3 100644 --- a/packages/app/app/containers/PlayerBarContainer/hooks.js +++ b/packages/app/app/containers/PlayerBarContainer/hooks.js @@ -1,30 +1,93 @@ +import Sound from 'react-hifi'; +import { useDispatch, useSelector } from 'react-redux'; +import _ from 'lodash'; import { formatDuration } from '@nuclear/ui'; -import { useSelector } from 'react-redux'; +import * as playerActions from '../../actions/player'; +import * as queueActions from '../../actions/queue'; import { playerSelectors } from '../../selectors/player'; import { queue as queueSelector } from '../../selectors/queue'; +import { useCallback } from 'react'; export const useSeekbarProps = () => { + const dispatch = useDispatch(); const queue = useSelector(queueSelector); const seek = useSelector(playerSelectors.seek); + const playbackProgress = useSelector(playerSelectors.playbackProgress); const currentTrackStream = _.head( _.get( queue.queueItems[queue.currentSong], 'streams' ) ); - const currentTrackDuration = _.get( currentTrackStream, 'duration' ); - const timeToEnd = currentTrackDuration - seek; + const seekCallback = useCallback( + (place) => dispatch(playerActions.updateSeek(place)), + [dispatch] + ); + return { queue, timePlayed: formatDuration(seek), - timeToEnd: formatDuration(timeToEnd) + timeToEnd: formatDuration(timeToEnd), + fill: playbackProgress, + seek: seekCallback }; }; +export const usePlayerControlsProps = () => { + const dispatch = useDispatch(); + const queue = useSelector(queueSelector); + const playbackStatus = useSelector(playerSelectors.playbackStatus); + const playbackStreamLoading = useSelector(playerSelectors.playbackStreamLoading); + + const couldPlay = queue.queueItems.length > 0; + const couldForward = couldPlay && queue.currentSong + 1 < queue.queueItems.length; + const couldBack = couldPlay && queue.currentSong > 0; + + const togglePlay = useCallback( + () => dispatch(playerActions.togglePlayback(playbackStatus)), + [dispatch, playbackStatus] + ); + + const goForward = useCallback( + () => dispatch(queueActions.nextSong()), + [dispatch] + ); + + const goBack = useCallback( + () => dispatch(queueActions.previousSong()), + [dispatch] + ); + + return { + goBackDisabled: !couldBack, + goForwardDisabled: !couldForward, + playDisabled: !couldPlay, + isPlaying: playbackStatus === Sound.status.PLAYING, + isLoading: playbackStreamLoading, + togglePlay, + goForward, + goBack + }; +}; + +export const useTrackInfoProps = () => { + const queue = useSelector(queueSelector); + const currentSong = _.get(queue.queueItems, queue.currentSong); + + const track = _.get(currentSong, 'name'); + const artist = _.get(currentSong, 'artist'); + const cover = _.get(currentSong, 'thumbnail'); + + return { + track, + artist, + cover + }; +}; diff --git a/packages/app/app/containers/PlayerBarContainer/index.js b/packages/app/app/containers/PlayerBarContainer/index.js index bd1e2ce798..d5777a6248 100644 --- a/packages/app/app/containers/PlayerBarContainer/index.js +++ b/packages/app/app/containers/PlayerBarContainer/index.js @@ -1,27 +1,23 @@ import React from 'react'; -import { useSelector /* useDispatch*/ } from 'react-redux'; -import Sound from 'react-hifi'; import { PlayerBar } from '@nuclear/ui'; -// import * as PlayerActions from '../../actions/player'; -import { playerSelectors } from '../../selectors/player'; -import { useSeekbarProps } from './hooks'; +import { + usePlayerControlsProps, + useSeekbarProps, + useTrackInfoProps +} from './hooks'; const PlayerBarContainer = () => { - // const dispatch = useDispatch(); - const playbackProgress = useSelector(playerSelectors.playbackProgress); - const playbackStatus = useSelector(playerSelectors.playbackStatus); - const playbackStreamLoading = useSelector(playerSelectors.playbackStreamLoading); - const seekbarProps = useSeekbarProps(); + const playerControlsProps = usePlayerControlsProps(); + const trackInfoProps = useTrackInfoProps(); return ( { { icon: 'magic' }, { icon: 'random', enabled: false } ]} - isPlaying={playbackStatus === Sound.status.PLAYING} - isLoading={playbackStreamLoading} /> ); }; diff --git a/packages/app/package.json b/packages/app/package.json index a711f95a4e..9ffc33a37f 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -73,6 +73,7 @@ "redux-promise": "^0.6.0", "redux-thunk": "^2.2.0", "regenerator-runtime": "^0.13.2", + "reselect": "^4.0.0", "semantic-ui-css": "^2.4.1", "semantic-ui-react": "^0.88.2", "simple-get-lyrics": "0.0.4", diff --git a/packages/ui/lib/components/PlayerBar/index.tsx b/packages/ui/lib/components/PlayerBar/index.tsx index 7c631ed4c0..839f382bbb 100644 --- a/packages/ui/lib/components/PlayerBar/index.tsx +++ b/packages/ui/lib/components/PlayerBar/index.tsx @@ -36,6 +36,9 @@ const PlayerBar: React.FC = ({ goForward, goBack, togglePlay, + goBackDisabled, + goForwardDisabled, + playDisabled, isPlaying = false, isLoading = false, @@ -78,6 +81,9 @@ const PlayerBar: React.FC = ({ togglePlay={togglePlay} isPlaying={isPlaying} isLoading={isLoading} + goBackDisabled={goBackDisabled} + goForwardDisabled={goForwardDisabled} + playDisabled={playDisabled} /> ; ariaLabel?: string; onClick?: (e: React.MouseEvent) => void; + disabled?: boolean; loading?: boolean; }; @@ -16,12 +18,16 @@ const PlayerButton: React.FC = ({ size = 'big', ariaLabel, onClick, + disabled = false, loading = false }) => ( diff --git a/packages/ui/lib/components/PlayerButton/styles.scss b/packages/ui/lib/components/PlayerButton/styles.scss index b286288d22..81e0077545 100644 --- a/packages/ui/lib/components/PlayerButton/styles.scss +++ b/packages/ui/lib/components/PlayerButton/styles.scss @@ -1,4 +1,11 @@ .player_button { background: transparent; border: none; + cursor: pointer; + outline: none; + + &.disabled { + opacity: 0.2; + cursor: not-allowed; + } } \ No newline at end of file diff --git a/packages/ui/lib/components/PlayerControls/index.tsx b/packages/ui/lib/components/PlayerControls/index.tsx index 3b2b87f50b..19a5bfc78a 100644 --- a/packages/ui/lib/components/PlayerControls/index.tsx +++ b/packages/ui/lib/components/PlayerControls/index.tsx @@ -10,6 +10,10 @@ export type PlayerControlsProps = { togglePlay?: () => void; isPlaying?: boolean; isLoading?: boolean; + + goBackDisabled?: boolean; + goForwardDisabled?: boolean; + playDisabled?: boolean; }; const PlayerControls: React.FC = ({ @@ -17,13 +21,17 @@ const PlayerControls: React.FC = ({ goBack, togglePlay, isPlaying, - isLoading + isLoading, + goBackDisabled=false, + goForwardDisabled=false, + playDisabled=false }) => (
= ({ : 'play' } onClick={togglePlay} + disabled={playDisabled} />
) From 906a640e1b0cd1a428d42255b2ed7b2953ac2a75 Mon Sep 17 00:00:00 2001 From: nukeop Date: Sat, 18 Jul 2020 02:09:07 +0200 Subject: [PATCH 24/63] Play options --- .../containers/PlayerBarContainer/hooks.js | 59 ++++++++++++++++++- .../containers/PlayerBarContainer/index.js | 12 ++-- packages/app/app/selectors/player.js | 4 +- packages/app/app/selectors/settings.js | 1 + .../ui/lib/components/PlayerBar/index.tsx | 6 +- .../ui/lib/components/Seekbar/styles.scss | 1 + .../ui/lib/components/TrackInfo/index.tsx | 39 +++++++----- .../VolumeControls/PlayOptions/index.tsx | 8 ++- .../VolumeControls/PlayOptions/styles.scss | 5 ++ 9 files changed, 106 insertions(+), 29 deletions(-) create mode 100644 packages/app/app/selectors/settings.js diff --git a/packages/app/app/containers/PlayerBarContainer/hooks.js b/packages/app/app/containers/PlayerBarContainer/hooks.js index 5a7aecafb3..b0595da4b0 100644 --- a/packages/app/app/containers/PlayerBarContainer/hooks.js +++ b/packages/app/app/containers/PlayerBarContainer/hooks.js @@ -1,12 +1,16 @@ import Sound from 'react-hifi'; +import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; import _ from 'lodash'; import { formatDuration } from '@nuclear/ui'; +import settingsConst from '../../constants/settings'; import * as playerActions from '../../actions/player'; import * as queueActions from '../../actions/queue'; +import * as settingsActions from '../../actions/settings'; import { playerSelectors } from '../../selectors/player'; import { queue as queueSelector } from '../../selectors/queue'; +import { settingsSelector } from '../../selectors/settings'; import { useCallback } from 'react'; export const useSeekbarProps = () => { @@ -79,6 +83,7 @@ export const usePlayerControlsProps = () => { export const useTrackInfoProps = () => { const queue = useSelector(queueSelector); + const hasTracks = queue.queueItems.length > 0; const currentSong = _.get(queue.queueItems, queue.currentSong); const track = _.get(currentSong, 'name'); @@ -88,6 +93,58 @@ export const useTrackInfoProps = () => { return { track, artist, - cover + cover, + hasTracks + }; +}; + +export const useToggleOptionCallback = ( + toggleOption, + name, + settings +) => useCallback( + () => toggleOption( + _.find(settingsConst, { name }), + settings + ), + [name, settings, toggleOption] +); + +export const useVolumeControlsProps = () => { + const { t } = useTranslation('option-control'); + const dispatch = useDispatch(); + const volume = useSelector(playerSelectors.volume); + const muted = useSelector(playerSelectors.muted); + const settings = useSelector(settingsSelector); + + const toggleOption = useCallback( + (option, state) => dispatch(settingsActions.toggleOption(option, state)), [dispatch] + ); + + const playOptions = [ + { + name: t('loop'), + icon: 'repeat', + enabled: _.get(settings, 'loopAfterQueueEnd'), + onToggle: useToggleOptionCallback(toggleOption, 'loopAfterQueueEnd', settings) + }, + { + name: t('shuffle'), + icon: 'random', + enabled: _.get(settings, 'shuffleQueue'), + onToggle: useToggleOptionCallback(toggleOption, 'shuffleQueue', settings) + }, + { + name: t('autoradio'), + icon: 'magic', + enabled: _.get(settings, 'autoradio'), + onToggle: useToggleOptionCallback(toggleOption, 'autoradio', settings) + } + ]; + + return { + volume, + isMuted: muted, + playOptions }; }; diff --git a/packages/app/app/containers/PlayerBarContainer/index.js b/packages/app/app/containers/PlayerBarContainer/index.js index d5777a6248..4e00b61514 100644 --- a/packages/app/app/containers/PlayerBarContainer/index.js +++ b/packages/app/app/containers/PlayerBarContainer/index.js @@ -4,27 +4,23 @@ import { PlayerBar } from '@nuclear/ui'; import { usePlayerControlsProps, useSeekbarProps, - useTrackInfoProps + useTrackInfoProps, + useVolumeControlsProps } from './hooks'; const PlayerBarContainer = () => { const seekbarProps = useSeekbarProps(); const playerControlsProps = usePlayerControlsProps(); const trackInfoProps = useTrackInfoProps(); + const volumeControlsProps = useVolumeControlsProps(); return ( ); }; diff --git a/packages/app/app/selectors/player.js b/packages/app/app/selectors/player.js index acf997d196..f12008c3c2 100644 --- a/packages/app/app/selectors/player.js +++ b/packages/app/app/selectors/player.js @@ -6,6 +6,8 @@ export const playerSelectors = createStateSelectors( 'playbackProgress', 'playbackStatus', 'playbackStreamLoading', - 'seek' + 'seek', + 'volume', + 'muted' ] ); diff --git a/packages/app/app/selectors/settings.js b/packages/app/app/selectors/settings.js new file mode 100644 index 0000000000..8ab666d7f8 --- /dev/null +++ b/packages/app/app/selectors/settings.js @@ -0,0 +1 @@ +export const settingsSelector = s => s.settings; diff --git a/packages/ui/lib/components/PlayerBar/index.tsx b/packages/ui/lib/components/PlayerBar/index.tsx index 839f382bbb..cfb87198c2 100644 --- a/packages/ui/lib/components/PlayerBar/index.tsx +++ b/packages/ui/lib/components/PlayerBar/index.tsx @@ -26,6 +26,7 @@ const PlayerBar: React.FC = ({ onArtistClick, addToFavorites, isFavorite, + hasTracks, volume, setVolume, @@ -59,7 +60,9 @@ const PlayerBar: React.FC = ({ queue={queue} > { - renderTrackDuration &&
+ hasTracks && + renderTrackDuration && +
{timePlayed}
{timeToEnd}
@@ -74,6 +77,7 @@ const PlayerBar: React.FC = ({ onArtistClick={onArtistClick} addToFavorites={addToFavorites} isFavorite={isFavorite} + hasTracks={hasTracks} /> void; addToFavorites: () => void; isFavorite?: boolean; + hasTracks?: boolean; }; const TrackInfo: React.FC = ({ @@ -21,25 +22,31 @@ const TrackInfo: React.FC = ({ onTrackClick, onArtistClick, addToFavorites, - isFavorite + isFavorite = false, + hasTracks = false }) => (
-
-
- {track} -
-
- {artist} -
-
-
- -
+ { + hasTracks && + <> +
+
+ {track} +
+
+ {artist} +
+
+
+ +
+ + }
); diff --git a/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx b/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx index 1e2751b6db..5d465e1842 100644 --- a/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx +++ b/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx @@ -1,9 +1,11 @@ import React from 'react'; +import cx from 'classnames'; import { Icon, SemanticICONS } from 'semantic-ui-react'; import styles from './styles.scss'; export type PlayOptionControlProps = { + name: string; icon: SemanticICONS; enabled?: boolean; onToggle?: () => void; @@ -15,9 +17,11 @@ const PlayOptionControl: React.FC = ({ onToggle }) => ( diff --git a/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss b/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss index 1cdb2fcd14..acbfdbb9cf 100644 --- a/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss +++ b/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss @@ -1,5 +1,10 @@ .play_options { .play_option_icon { margin-right: 1em; + cursor: pointer; + + &.disabled { + opacity: 0.2; + } } } \ No newline at end of file From 90c785c98df28dfceb5e9f6f5bdbe76c11b34793 Mon Sep 17 00:00:00 2001 From: nukeop Date: Sat, 18 Jul 2020 14:30:07 +0200 Subject: [PATCH 25/63] Update styles for volume components --- .../VolumeControls/PlayOptions/index.tsx | 2 +- .../VolumeControls/PlayOptions/styles.scss | 1 + .../lib/components/VolumeControls/index.tsx | 9 ++++++--- .../lib/components/VolumeControls/styles.scss | 20 +++++++++++++++++-- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx b/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx index 5d465e1842..fc0ff8074b 100644 --- a/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx +++ b/packages/ui/lib/components/VolumeControls/PlayOptions/index.tsx @@ -23,7 +23,7 @@ const PlayOptionControl: React.FC = ({ )} name={icon} onClick={onToggle} - size='big' + size='large' /> ); diff --git a/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss b/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss index acbfdbb9cf..7295e17ea0 100644 --- a/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss +++ b/packages/ui/lib/components/VolumeControls/PlayOptions/styles.scss @@ -1,4 +1,5 @@ .play_options { + display: flex; .play_option_icon { margin-right: 1em; cursor: pointer; diff --git a/packages/ui/lib/components/VolumeControls/index.tsx b/packages/ui/lib/components/VolumeControls/index.tsx index b1ae9615a9..05d2963641 100644 --- a/packages/ui/lib/components/VolumeControls/index.tsx +++ b/packages/ui/lib/components/VolumeControls/index.tsx @@ -17,12 +17,13 @@ const VolumeControls: React.FC = ({ isMuted, playOptions }) => ( -
+
+
+
= ({ : 'volume down' } /> +
+
); diff --git a/packages/ui/lib/components/VolumeControls/styles.scss b/packages/ui/lib/components/VolumeControls/styles.scss index 888a7830ea..6d08f0bdf0 100644 --- a/packages/ui/lib/components/VolumeControls/styles.scss +++ b/packages/ui/lib/components/VolumeControls/styles.scss @@ -1,11 +1,27 @@ -.volume_controls { +.volume_controls_container { display: flex; justify-content: flex-end; padding-right: 1em; - flex: 1 1 50%; + flex: 1 0 50%; + + .volume_controls { + display: flex; + flex-flow: row; + justify-content: flex-end; + width: 175px; + } .volume_icon { + display: flex; + justify-content: flex-start; + width: 2em; cursor: pointer; + flex: 0 0 auto; + + .icon { + display: flex; + justify-content: flex-start; + } } } From 45de3221358485022969b2330c5dcf1a2a62fb68 Mon Sep 17 00:00:00 2001 From: nukeop Date: Sat, 18 Jul 2020 20:01:52 +0200 Subject: [PATCH 26/63] Volume slider fix --- .../containers/PlayerBarContainer/hooks.js | 16 +++++++- .../ui/lib/components/PlayerBar/index.tsx | 4 +- packages/ui/lib/components/Range/index.js | 11 +++-- .../VolumeControls/VolumeSlider/index.tsx | 18 ++++++-- .../lib/components/VolumeControls/index.tsx | 41 +++++++++---------- 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/packages/app/app/containers/PlayerBarContainer/hooks.js b/packages/app/app/containers/PlayerBarContainer/hooks.js index b0595da4b0..0cf1457268 100644 --- a/packages/app/app/containers/PlayerBarContainer/hooks.js +++ b/packages/app/app/containers/PlayerBarContainer/hooks.js @@ -114,7 +114,7 @@ export const useVolumeControlsProps = () => { const { t } = useTranslation('option-control'); const dispatch = useDispatch(); const volume = useSelector(playerSelectors.volume); - const muted = useSelector(playerSelectors.muted); + const isMuted = useSelector(playerSelectors.muted); const settings = useSelector(settingsSelector); const toggleOption = useCallback( @@ -142,9 +142,21 @@ export const useVolumeControlsProps = () => { } ]; + const updateVolume = useCallback( + (value) => dispatch(playerActions.updateVolume(value)), + [dispatch] + ); + + const toggleMute = useCallback( + () => dispatch(playerActions.toggleMute(!isMuted)), + [dispatch, isMuted] + ); + return { volume, - isMuted: muted, + updateVolume, + isMuted, + toggleMute, playOptions }; }; diff --git a/packages/ui/lib/components/PlayerBar/index.tsx b/packages/ui/lib/components/PlayerBar/index.tsx index cfb87198c2..0de4b71bfa 100644 --- a/packages/ui/lib/components/PlayerBar/index.tsx +++ b/packages/ui/lib/components/PlayerBar/index.tsx @@ -29,7 +29,7 @@ const PlayerBar: React.FC = ({ hasTracks, volume, - setVolume, + updateVolume, toggleMute, isMuted, playOptions, @@ -91,7 +91,7 @@ const PlayerBar: React.FC = ({ /> { - const [state, setValue] = useState(0); const handleChange = useCallback( e => { if (!readOnly) { const newVal = parseInt(e.nativeEvent ? e.nativeEvent.target.value : e, 10); - setValue(newVal); onChange && onChange(newVal); } }, - [setValue, onChange, readOnly] + [onChange, readOnly] ); - const val = Math.min(max, state || value); + const val = Math.min(max, _.defaultTo(value, 0)); const percentProgress = val / (max - min); const componentHeight = Math.max(height, thumbSize); const trackPosition = getTrackPosition({ thumbSize, height }); @@ -107,7 +106,7 @@ Range.defaultProps = { max: 100, width: 300, value: 0, - onChange: () => {} + onChange: () => { } }; const colorWithAlpha = { diff --git a/packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx b/packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx index 8d141dd877..950b7d70e0 100644 --- a/packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx +++ b/packages/ui/lib/components/VolumeControls/VolumeSlider/index.tsx @@ -5,13 +5,21 @@ import Range from '../../Range'; import styles from './styles.scss'; export type VolumeSliderProps = { - setVolume: (value: number) => void; + volume: number; + updateVolume: (value: number) => void; toggleMute: () => void; isMuted: boolean; }; +const volumeSliderColors = { + fillColor: { r: 248, g: 248, b: 242, a: 1 }, + trackColor: { r: 68, g: 71, b: 90, a: 1 }, + thumbColor: { r: 248, g: 248, b: 242, a: 1 } +}; + const VolumeSlider: React.FC = ({ - setVolume, + volume, + updateVolume, toggleMute, isMuted }) => ( @@ -20,9 +28,13 @@ const VolumeSlider: React.FC = ({ onClick={isMuted ? toggleMute : () => { }} >
) diff --git a/packages/ui/lib/components/VolumeControls/index.tsx b/packages/ui/lib/components/VolumeControls/index.tsx index 05d2963641..68586b94b0 100644 --- a/packages/ui/lib/components/VolumeControls/index.tsx +++ b/packages/ui/lib/components/VolumeControls/index.tsx @@ -6,13 +6,11 @@ import PlayOptions, { PlayOptionsProps } from './PlayOptions'; import styles from './styles.scss'; -export type VolumeControlsProps = VolumeSliderProps & PlayOptionsProps & { - volume: number; -}; +export type VolumeControlsProps = VolumeSliderProps & PlayOptionsProps; const VolumeControls: React.FC = ({ volume, - setVolume, + updateVolume, toggleMute, isMuted, playOptions @@ -21,23 +19,24 @@ const VolumeControls: React.FC = ({
- 40 - ? 'volume up' - : 'volume down' - } - /> -
- + 40 + ? 'volume up' + : 'volume down' + } + /> +
+
); From 4cd98a061743bcbb0233f87040113b19aebd8605 Mon Sep 17 00:00:00 2001 From: nukeop Date: Sun, 19 Jul 2020 02:03:15 +0200 Subject: [PATCH 27/63] Handle adding/removing favorites --- .../containers/PlayerBarContainer/hooks.js | 19 ++++++++++++++++++- .../ui/lib/components/PlayerBar/index.tsx | 4 +++- .../ui/lib/components/PlayerBar/styles.scss | 2 ++ packages/ui/lib/components/Seekbar/index.tsx | 19 +++++++++++-------- .../ui/lib/components/TrackInfo/index.tsx | 7 +++++++ .../ui/lib/components/TrackInfo/styles.scss | 4 ++++ 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/packages/app/app/containers/PlayerBarContainer/hooks.js b/packages/app/app/containers/PlayerBarContainer/hooks.js index 0cf1457268..5bd68c56d7 100644 --- a/packages/app/app/containers/PlayerBarContainer/hooks.js +++ b/packages/app/app/containers/PlayerBarContainer/hooks.js @@ -8,9 +8,11 @@ import settingsConst from '../../constants/settings'; import * as playerActions from '../../actions/player'; import * as queueActions from '../../actions/queue'; import * as settingsActions from '../../actions/settings'; +import * as favoritesActions from '../../actions/favorites'; import { playerSelectors } from '../../selectors/player'; import { queue as queueSelector } from '../../selectors/queue'; import { settingsSelector } from '../../selectors/settings'; +import { getFavoriteTrack } from '../../selectors/favorites'; import { useCallback } from 'react'; export const useSeekbarProps = () => { @@ -82,6 +84,7 @@ export const usePlayerControlsProps = () => { }; export const useTrackInfoProps = () => { + const dispatch = useDispatch(); const queue = useSelector(queueSelector); const hasTracks = queue.queueItems.length > 0; const currentSong = _.get(queue.queueItems, queue.currentSong); @@ -90,11 +93,25 @@ export const useTrackInfoProps = () => { const artist = _.get(currentSong, 'artist'); const cover = _.get(currentSong, 'thumbnail'); + const favorite = useSelector(s => getFavoriteTrack(s, artist, track)); + const isFavorite = !_.isNil(favorite); + const addToFavorites = useCallback( + () => dispatch(favoritesActions.addFavoriteTrack(currentSong)), + [dispatch, currentSong] + ); + const removeFromFavorites = useCallback( + () => dispatch(favoritesActions.removeFavoriteTrack(favorite)), + [dispatch, favorite] + ); + return { track, artist, cover, - hasTracks + hasTracks, + isFavorite, + addToFavorites, + removeFromFavorites }; }; diff --git a/packages/ui/lib/components/PlayerBar/index.tsx b/packages/ui/lib/components/PlayerBar/index.tsx index 0de4b71bfa..440a26a59d 100644 --- a/packages/ui/lib/components/PlayerBar/index.tsx +++ b/packages/ui/lib/components/PlayerBar/index.tsx @@ -25,6 +25,7 @@ const PlayerBar: React.FC = ({ onTrackClick, onArtistClick, addToFavorites, + removeFromFavorites, isFavorite, hasTracks, @@ -64,7 +65,7 @@ const PlayerBar: React.FC = ({ renderTrackDuration &&
{timePlayed}
-
{timeToEnd}
+
-{timeToEnd}
} @@ -76,6 +77,7 @@ const PlayerBar: React.FC = ({ onTrackClick={onTrackClick} onArtistClick={onArtistClick} addToFavorites={addToFavorites} + removeFromFavorites={removeFromFavorites} isFavorite={isFavorite} hasTracks={hasTracks} /> diff --git a/packages/ui/lib/components/PlayerBar/styles.scss b/packages/ui/lib/components/PlayerBar/styles.scss index 303ec690a0..daf9567b95 100644 --- a/packages/ui/lib/components/PlayerBar/styles.scss +++ b/packages/ui/lib/components/PlayerBar/styles.scss @@ -32,5 +32,7 @@ padding: 0 .5em; height: 100%; width: 100%; + + pointer-events: none; } } diff --git a/packages/ui/lib/components/Seekbar/index.tsx b/packages/ui/lib/components/Seekbar/index.tsx index 1d48fe0a9d..2db4157922 100644 --- a/packages/ui/lib/components/Seekbar/index.tsx +++ b/packages/ui/lib/components/Seekbar/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import cx from 'classnames'; import common from '../../common.scss'; @@ -15,13 +15,7 @@ export type SeekbarProps = { queue: { queueItems: QueueItem[] }; }; -const handleClick = (seek, queue) => { - return event => { - const percent = (event.pageX - event.target.offsetLeft) / document.body.clientWidth; - const duration = queue.queueItems[queue.currentSong].streams[0].duration; - seek(percent * duration * 1000); - }; -}; + const Seekbar: React.FC = ({ children, @@ -29,6 +23,15 @@ const Seekbar: React.FC = ({ seek, queue }) => { + + const handleClick = useCallback((seek, queue) => { + return event => { + const percent = (event.pageX - event.target.offsetLeft) / document.body.clientWidth; + const duration = queue.queueItems[queue.currentSong].streams[0].duration; + seek(percent * duration); + }; + }, []); + return (
void; onArtistClick: () => void; addToFavorites: () => void; + removeFromFavorites: () => void; isFavorite?: boolean; hasTracks?: boolean; }; @@ -22,6 +23,7 @@ const TrackInfo: React.FC = ({ onTrackClick, onArtistClick, addToFavorites, + removeFromFavorites, isFavorite = false, hasTracks = false }) => ( @@ -43,6 +45,11 @@ const TrackInfo: React.FC = ({ isFavorite ? 'heart' : 'heart outline' } size='large' + onClick={ + isFavorite + ? removeFromFavorites + : addToFavorites + } />
diff --git a/packages/ui/lib/components/TrackInfo/styles.scss b/packages/ui/lib/components/TrackInfo/styles.scss index 6c66e901c0..dd4d899dd3 100644 --- a/packages/ui/lib/components/TrackInfo/styles.scss +++ b/packages/ui/lib/components/TrackInfo/styles.scss @@ -29,5 +29,9 @@ display: flex; flex-flow: column; justify-content: center; + + .icon { + cursor: pointer; + } } } From 9127d4f6a0e5a2fd1287dd7e29ab0d866aee1edc Mon Sep 17 00:00:00 2001 From: nukeop Date: Tue, 21 Jul 2020 02:18:19 +0200 Subject: [PATCH 28/63] Normalize track before adding to favorites --- packages/app/app/containers/PlayerBarContainer/hooks.js | 3 ++- packages/app/app/selectors/favorites.js | 2 +- packages/ui/lib/components/PlayerButton/index.tsx | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/app/app/containers/PlayerBarContainer/hooks.js b/packages/app/app/containers/PlayerBarContainer/hooks.js index 5bd68c56d7..f4665da73f 100644 --- a/packages/app/app/containers/PlayerBarContainer/hooks.js +++ b/packages/app/app/containers/PlayerBarContainer/hooks.js @@ -4,6 +4,7 @@ import { useDispatch, useSelector } from 'react-redux'; import _ from 'lodash'; import { formatDuration } from '@nuclear/ui'; +import { normalizeTrack } from '../../utils'; import settingsConst from '../../constants/settings'; import * as playerActions from '../../actions/player'; import * as queueActions from '../../actions/queue'; @@ -96,7 +97,7 @@ export const useTrackInfoProps = () => { const favorite = useSelector(s => getFavoriteTrack(s, artist, track)); const isFavorite = !_.isNil(favorite); const addToFavorites = useCallback( - () => dispatch(favoritesActions.addFavoriteTrack(currentSong)), + () => dispatch(favoritesActions.addFavoriteTrack(normalizeTrack(currentSong))), [dispatch, currentSong] ); const removeFromFavorites = useCallback( diff --git a/packages/app/app/selectors/favorites.js b/packages/app/app/selectors/favorites.js index f8106a3b0e..c600c1f332 100644 --- a/packages/app/app/selectors/favorites.js +++ b/packages/app/app/selectors/favorites.js @@ -9,7 +9,7 @@ export function getFavoriteTrack(state, artist, title) { const normalizedTitle = _.deburr(title.toLowerCase()); return _.find(state.favorites.tracks, track => { - const normalizedStoreArtist = _.deburr(track.artist.name.toLowerCase()); + const normalizedStoreArtist = _.deburr(_.defaultTo(track.artist.name, track.artist).toLowerCase()); const normalizedStoreTitle = _.deburr(track.name.toLowerCase()); return normalizedStoreArtist === normalizedArtist && normalizedStoreTitle === normalizedTitle; diff --git a/packages/ui/lib/components/PlayerButton/index.tsx b/packages/ui/lib/components/PlayerButton/index.tsx index 503a8f58fb..7a4440c63a 100644 --- a/packages/ui/lib/components/PlayerButton/index.tsx +++ b/packages/ui/lib/components/PlayerButton/index.tsx @@ -27,7 +27,7 @@ const PlayerButton: React.FC = ({ { [styles.disabled]: disabled } )} aria-label={ariaLabel} - onClick={!disabled && onClick} + onClick={disabled ? undefined : onClick} > From 6f09a5bad68990c3a6e86b7eb51ecfe2b2c4333f Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 22 Jul 2020 01:19:52 +0200 Subject: [PATCH 29/63] Remove unused, refactored code --- packages/app/app/App.js | 119 +----------------- .../PlayerControls/PlayPauseButton/index.js | 40 ------ .../PlayPauseButton/styles.scss | 42 ------- .../PlayerControls/PlayerButton/index.js | 21 ---- .../PlayerControls/PlayerButton/styles.scss | 37 ------ .../app/components/PlayerControls/index.js | 64 ---------- .../app/components/PlayerControls/styles.scss | 6 - .../app/app/components/TrackDuration/index.js | 29 ----- .../app/components/TrackDuration/styles.scss | 20 --- .../app/app/components/TrackInfo/index.js | 20 --- .../app/app/components/TrackInfo/styles.scss | 29 ----- .../VolumeControls/VolumeSlider/index.js | 37 ------ .../VolumeControls/VolumeSlider/styles.scss | 8 -- .../app/components/VolumeControls/index.js | 43 ------- .../app/components/VolumeControls/styles.scss | 34 ----- .../containers/PlayerBarContainer/hooks.js | 15 +++ .../app/test/enzyme.playercontrols.test.js | 71 ----------- .../lib/components/PlayerControls/index.tsx | 2 +- .../ui/lib/components/TrackInfo/styles.scss | 5 + 19 files changed, 22 insertions(+), 620 deletions(-) delete mode 100644 packages/app/app/components/PlayerControls/PlayPauseButton/index.js delete mode 100644 packages/app/app/components/PlayerControls/PlayPauseButton/styles.scss delete mode 100644 packages/app/app/components/PlayerControls/PlayerButton/index.js delete mode 100644 packages/app/app/components/PlayerControls/PlayerButton/styles.scss delete mode 100644 packages/app/app/components/PlayerControls/index.js delete mode 100644 packages/app/app/components/PlayerControls/styles.scss delete mode 100644 packages/app/app/components/TrackDuration/index.js delete mode 100644 packages/app/app/components/TrackDuration/styles.scss delete mode 100644 packages/app/app/components/TrackInfo/index.js delete mode 100644 packages/app/app/components/TrackInfo/styles.scss delete mode 100644 packages/app/app/components/VolumeControls/VolumeSlider/index.js delete mode 100644 packages/app/app/components/VolumeControls/VolumeSlider/styles.scss delete mode 100644 packages/app/app/components/VolumeControls/index.js delete mode 100644 packages/app/app/components/VolumeControls/styles.scss delete mode 100644 packages/app/test/enzyme.playercontrols.test.js diff --git a/packages/app/app/App.js b/packages/app/app/App.js index 9f0ff2627e..1fb120d538 100644 --- a/packages/app/app/App.js +++ b/packages/app/app/App.js @@ -7,7 +7,6 @@ import classnames from 'classnames'; import _ from 'lodash'; import Sound from 'react-hifi'; import { withTranslation } from 'react-i18next'; -import { Cover, formatDuration } from '@nuclear/ui'; import { PluginConfig } from '@nuclear/core'; import * as SearchActions from './actions/search'; @@ -28,12 +27,10 @@ import compact from './compact.scss'; import logoImg from '../resources/media/logo_full_light.png'; import logoIcon from '../resources/media/512x512.png'; -import artPlaceholder from '../resources/media/art_placeholder.png'; import settingsConst from './constants/settings'; import PlaylistsSubMenu from './components/PlaylistsSubMenu'; -import Footer from './components/Footer'; import Navbar from './components/Navbar'; import VerticalPanel from './components/VerticalPanel'; import Spacer from './components/Spacer'; @@ -51,15 +48,10 @@ import ShortcutsContainer from './containers/ShortcutsContainer'; import ErrorBoundary from './containers/ErrorBoundary'; import NavButtons from './components/NavButtons'; -import PlayerControls from './components/PlayerControls'; -import Seekbar from './components/Seekbar'; import SidebarMenu from './components/SidebarMenu'; import SidebarMenuItem from './components/SidebarMenu/SidebarMenuItem'; import SidebarMenuCategoryHeader from './components/SidebarMenu/SidebarMenuCategoryHeader'; -import TrackDuration from './components/TrackDuration'; -import TrackInfo from './components/TrackInfo'; import WindowControls from './components/WindowControls'; -import VolumeControls from './components/VolumeControls'; @withTranslation('app') class App extends React.PureComponent { @@ -249,121 +241,12 @@ class App extends React.PureComponent { ); } - renderFooter () { - return ( - <> - -
- - { - this.props.settings.trackDuration && - !_.isNil(this.props.queue.queueItems[this.props.queue.currentSong]) && - this.renderTrackDuration() - } - -
-
- {this.renderCover()} - {this.renderTrackInfo()} -
- {this.renderPlayerControls()} - {this.renderVolumeControl()} -
-
- - ); - } - - renderTrackDuration() { - const currentTrackStream = _.head( - _.get( - this.props.queue.queueItems[this.props.queue.currentSong], - 'streams' - ) - ); - - const currentTrackDuration = _.get( - currentTrackStream, - 'duration' - ); - - const timeToEnd = currentTrackDuration - this.props.player.seek; - - return ( - - ); - } - - renderCover () { - return ( - - ); - } - getCurrentSongParameter (parameter) { return this.props.queue.queueItems[this.props.queue.currentSong] ? this.props.queue.queueItems[this.props.queue.currentSong][parameter] : null; } - renderTrackInfo () { - return ( - - ); - } - - renderPlayerControls () { - const { player, queue } = this.props; - const couldPlay = queue.queueItems.length > 0; - const couldForward = couldPlay && queue.currentSong + 1 < queue.queueItems.length; - const couldBack = couldPlay && queue.currentSong > 0; - - return ( - - ); - } - - renderVolumeControl () { - return ( - - ); - } - render () { return ( @@ -377,7 +260,7 @@ class App extends React.PureComponent { {this.renderRightPanel()}
- {this.renderFooter()} +
diff --git a/packages/app/app/components/PlayerControls/PlayPauseButton/index.js b/packages/app/app/components/PlayerControls/PlayPauseButton/index.js deleted file mode 100644 index aa80eb7523..0000000000 --- a/packages/app/app/components/PlayerControls/PlayPauseButton/index.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import FontAwesome from 'react-fontawesome'; -import { withTranslation } from 'react-i18next'; - -import styles from './styles.scss'; - -@withTranslation('player') -class PlayPauseButton extends React.Component { - getIcon() { - if (this.props.loading) { - return ; - } else if (this.props.playing) { - return ; - } else { - return ; - } - } - - render() { - return ( - - ); - } -} - -export default PlayPauseButton; diff --git a/packages/app/app/components/PlayerControls/PlayPauseButton/styles.scss b/packages/app/app/components/PlayerControls/PlayPauseButton/styles.scss deleted file mode 100644 index 90200dafac..0000000000 --- a/packages/app/app/components/PlayerControls/PlayPauseButton/styles.scss +++ /dev/null @@ -1,42 +0,0 @@ -@import '../../../vars.scss'; -.play_pause_button_container { - display: flex; - width: 56px; - height: 56px; - text-align: center; - font-size: 42px; - - flex: 0 0 auto; - flex-flow: row; - align-items: center; - - &.loading { - a { - padding: 0; - } - } - - &:hover:not(.player_button_disabled) { - a { - color: $white; - } - } - - a { - flex: 1 1 auto; - padding-left: 0.3rem; - color: rgba($white, 0.8); - transition: $short-duration ease-out; - - .fa-pause { - margin-left: -0.3rem; - } - } - - &.player_button_disabled { - a { - cursor: default; - color: rgba($white, 0.25); - } - } -} diff --git a/packages/app/app/components/PlayerControls/PlayerButton/index.js b/packages/app/app/components/PlayerControls/PlayerButton/index.js deleted file mode 100644 index 389b8ed1f8..0000000000 --- a/packages/app/app/components/PlayerControls/PlayerButton/index.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import FontAwesome from 'react-fontawesome'; -import classNames from 'classnames'; - -import styles from './styles.scss'; - -const PlayerButton = ({ ariaLabel, icon, onClick }) => ( -
- - - -
-); - -export default PlayerButton; diff --git a/packages/app/app/components/PlayerControls/PlayerButton/styles.scss b/packages/app/app/components/PlayerControls/PlayerButton/styles.scss deleted file mode 100644 index 9c3608e936..0000000000 --- a/packages/app/app/components/PlayerControls/PlayerButton/styles.scss +++ /dev/null @@ -1,37 +0,0 @@ -@import '../../../vars.scss'; -.player_button_container { - display: flex; - - width: 60px; - height: 60px; - - text-align: center; - - font-size: 30px; - - flex: 0 0 auto; - flex-flow: row; - align-items: center; - - transition: $short-duration ease all; - - a { - flex: 1 1 auto; - color: rgba($white, 0.8); - transition: $short-duration ease all; - } - - - &:hover:not(.player_button_disabled) { - a { - color: $white; - } - } - - &.player_button_disabled { - a { - cursor: default; - color: rgba($white, 0.25); - } - } -} diff --git a/packages/app/app/components/PlayerControls/index.js b/packages/app/app/components/PlayerControls/index.js deleted file mode 100644 index 0efb7da898..0000000000 --- a/packages/app/app/components/PlayerControls/index.js +++ /dev/null @@ -1,64 +0,0 @@ -import React, {useEffect, useCallback} from 'react'; - -import styles from './styles.scss'; - -import PlayerButton from './PlayerButton'; -import PlayPauseButton from './PlayPauseButton'; -import { useTranslation } from 'react-i18next'; - -const PlayerControls = ({ back, togglePlay, playing, loading, forward }) => { - const { t } = useTranslation('player'); - - const handleMediaKeys = useCallback(event => { - switch (event.key) { - case 'MediaPlayPause': { - if (togglePlay) { - togglePlay(); - } - return; - } - - case 'MediaTrackNext': { - if (forward) { - forward(); - } - return; - } - - case 'MediaTrackPrevious': { - if (back) { - back(); - } - return; - } - } - }, [back, forward, togglePlay]); - - useEffect(() => { - document.addEventListener('keydown', handleMediaKeys); - return () => - document.removeEventListener('keydown', handleMediaKeys); - }, [togglePlay, back, forward, handleMediaKeys]); - - return ( -
- - - -
- ); -}; - -export default PlayerControls; diff --git a/packages/app/app/components/PlayerControls/styles.scss b/packages/app/app/components/PlayerControls/styles.scss deleted file mode 100644 index 7e7da05016..0000000000 --- a/packages/app/app/components/PlayerControls/styles.scss +++ /dev/null @@ -1,6 +0,0 @@ -.player_controls_container { - display: flex; - flex: 0 0 20%; - align-items: center; - justify-content: center; -} diff --git a/packages/app/app/components/TrackDuration/index.js b/packages/app/app/components/TrackDuration/index.js deleted file mode 100644 index cbc310d953..0000000000 --- a/packages/app/app/components/TrackDuration/index.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import styles from './styles.scss'; - -const TrackDuration = ({ timePlayed, timeToEnd }) => { - return ( -
-
- { timePlayed } -
-
- { timeToEnd } -
-
- ); -}; - -TrackDuration.propTypes = { - timePlayed: PropTypes.string, - timeToEnd: PropTypes.string -}; - -TrackDuration.defaultProps = { - timePlayed: '', - timeToEnd: '' -}; - -export default TrackDuration; diff --git a/packages/app/app/components/TrackDuration/styles.scss b/packages/app/app/components/TrackDuration/styles.scss deleted file mode 100644 index 22bbcd01b2..0000000000 --- a/packages/app/app/components/TrackDuration/styles.scss +++ /dev/null @@ -1,20 +0,0 @@ -@import '../../vars.scss'; - -@mixin time { - display: flex; - flex-flow: row; - justify-content: space-between; - align-items: center; -} - -.track_duration_widget { - position: relative; - z-index: 2; - @include time; - padding: 0 14px; - pointer-events: none; - .time_played, - .time_to_end { - @include time; - } -} diff --git a/packages/app/app/components/TrackInfo/index.js b/packages/app/app/components/TrackInfo/index.js deleted file mode 100644 index 6f96d84564..0000000000 --- a/packages/app/app/components/TrackInfo/index.js +++ /dev/null @@ -1,20 +0,0 @@ -import React, { useCallback } from 'react'; - -import styles from './styles.scss'; - -const TrackInfo = ({ track, artist, artistInfoSearchByName, history }) => { - const handleInfoSearch = useCallback(() => { - artistInfoSearchByName(artist, history); - }, [artist, artistInfoSearchByName, history]); - - return ( -
-
{track}
- -
{artist}
-
-
- ); -}; - -export default TrackInfo; diff --git a/packages/app/app/components/TrackInfo/styles.scss b/packages/app/app/components/TrackInfo/styles.scss deleted file mode 100644 index 025a548441..0000000000 --- a/packages/app/app/components/TrackInfo/styles.scss +++ /dev/null @@ -1,29 +0,0 @@ -@import '../../vars'; -.track_info_container { - display: flex; - margin: 0 0 0 14px; - color: #f8f8f2; - flex-flow: column; - flex-wrap: wrap; - overflow: hidden; - justify-content: center; -} - -.track_name { - margin-bottom: 0.15em; - font-size: 22px; - overflow: visible; - white-space: nowrap; - text-overflow: ellipsis; -} - -.artist_name { - color: $lightbg; - &:hover { - color: $white; - } - font-size: 14px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} diff --git a/packages/app/app/components/VolumeControls/VolumeSlider/index.js b/packages/app/app/components/VolumeControls/VolumeSlider/index.js deleted file mode 100644 index c37dfd4057..0000000000 --- a/packages/app/app/components/VolumeControls/VolumeSlider/index.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react'; - -import styles from './styles.scss'; -import { Range } from '@nuclear/ui'; - -const volumeSliderColors = { - fillColor: { r: 248, g: 248, b: 242, a: 1 }, - trackColor: { r: 68, g: 71, b: 90, a: 1 }, - thumbColor: { r: 248, g: 248, b: 242, a: 1 } -}; - -class VolumeSlider extends React.Component { - handleClick (value) { - this.props.handleClick(value); - } - - render () { - return ( -
{}} - > - -
- ); - } -} - -export default VolumeSlider; diff --git a/packages/app/app/components/VolumeControls/VolumeSlider/styles.scss b/packages/app/app/components/VolumeControls/VolumeSlider/styles.scss deleted file mode 100644 index c413e5cfd0..0000000000 --- a/packages/app/app/components/VolumeControls/VolumeSlider/styles.scss +++ /dev/null @@ -1,8 +0,0 @@ -@import '../../../vars'; -.volume_slider_container { - position: relative; - - cursor: pointer; - - flex: 0 0 150px; -} \ No newline at end of file diff --git a/packages/app/app/components/VolumeControls/index.js b/packages/app/app/components/VolumeControls/index.js deleted file mode 100644 index d7adb1ec53..0000000000 --- a/packages/app/app/components/VolumeControls/index.js +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import FontAwesome from 'react-fontawesome'; - -import styles from './styles.scss'; - -import PlayOptionsControls from '../PlayOptionsControls'; -import VolumeSlider from './VolumeSlider'; - -class VolumeControls extends React.Component { - handleClick (value) { - return this.props.updateVolume(value); - } - - toggleMute () { - this.props.toggleMute(!this.props.muted); - } - - render () { - return ( -
- -
- 40 ? 'volume-up' : 'volume-down'}/> -
- - -
- ); - } -} - -export default VolumeControls; diff --git a/packages/app/app/components/VolumeControls/styles.scss b/packages/app/app/components/VolumeControls/styles.scss deleted file mode 100644 index aca7956f45..0000000000 --- a/packages/app/app/components/VolumeControls/styles.scss +++ /dev/null @@ -1,34 +0,0 @@ -@import '../../vars.scss'; -.volume_controls_container { - display: flex; - - height: 100%; - margin: 0 1rem; - - flex: 1 1 33%; - flex-flow: row; - align-items: center; - justify-content: flex-end; - - span { - margin: 1rem; - font-size: 24px; - } - - .volume_speaker_control { - display: flex; - - cursor: pointer; - - width: 50px; - height: 52px; - - color: rgba($white, 0.80); - - transition: $very-short-duration ease all; - - &:hover { - color: $white; - } - } -} diff --git a/packages/app/app/containers/PlayerBarContainer/hooks.js b/packages/app/app/containers/PlayerBarContainer/hooks.js index f4665da73f..6d99a249c0 100644 --- a/packages/app/app/containers/PlayerBarContainer/hooks.js +++ b/packages/app/app/containers/PlayerBarContainer/hooks.js @@ -1,11 +1,13 @@ import Sound from 'react-hifi'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; import _ from 'lodash'; import { formatDuration } from '@nuclear/ui'; import { normalizeTrack } from '../../utils'; import settingsConst from '../../constants/settings'; +import * as searchActions from '../../actions/search'; import * as playerActions from '../../actions/player'; import * as queueActions from '../../actions/queue'; import * as settingsActions from '../../actions/settings'; @@ -86,6 +88,7 @@ export const usePlayerControlsProps = () => { export const useTrackInfoProps = () => { const dispatch = useDispatch(); + const history = useHistory(); const queue = useSelector(queueSelector); const hasTracks = queue.queueItems.length > 0; const currentSong = _.get(queue.queueItems, queue.currentSong); @@ -105,9 +108,21 @@ export const useTrackInfoProps = () => { [dispatch, favorite] ); + const onTrackClick = useCallback( + () => {}, + [] + ); + + const onArtistClick = useCallback( + () => dispatch(searchActions.artistInfoSearchByName(artist, history)), + [dispatch, artist, history] + ); + return { track, artist, + onTrackClick, + onArtistClick, cover, hasTracks, isFavorite, diff --git a/packages/app/test/enzyme.playercontrols.test.js b/packages/app/test/enzyme.playercontrols.test.js deleted file mode 100644 index 410fb249cd..0000000000 --- a/packages/app/test/enzyme.playercontrols.test.js +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; -import chai from 'chai'; -import spies from 'chai-spies'; -import { shallow, mount } from 'enzyme'; -import { describe, it } from 'mocha'; -import FontAwesome from 'react-fontawesome'; - -import PlayerControls from '../app/components/PlayerControls'; -import PlayPauseButton from '../app/components/PlayerControls/PlayPauseButton'; -import PlayerButton from '../app/components/PlayerControls/PlayerButton'; - -chai.use(spies); -const { expect } = chai; - -describe('Rendering and its children', () => { - it('Should render the PlayPauseButton and two PlayerButton ', () => { - const wrapper = shallow(); - expect(wrapper.containsMatchingElement()).to.equal(true); - expect(wrapper.find(PlayerButton)).to.have.lengthOf(2); - expect(wrapper.find(PlayerButton).first().props().icon).to.equal('step-backward'); - expect(wrapper.find(PlayerButton).last().props().icon).to.equal('step-forward'); - }); -}); - -describe('Back button onClick', () => { - it('has an onclick event that gets triggered', () => { - const spy = chai.spy(); - const wrapper = shallow(); - wrapper.find(PlayerButton).first().simulate('click'); - expect(spy).to.have.been.called; - }); -}); - -describe('Forward button onClick', () => { - it('has an onclick event that gets triggered', () => { - const spy = chai.spy(); - const wrapper = shallow(); - wrapper.find(PlayerButton).last().simulate('click'); - expect(spy).to.have.been.called; - }); -}); - -describe(' loading', () => { - it('Loading indicator showing', () => { - const wrapper = mount(); - expect(wrapper.find(FontAwesome).prop('name')).to.equal('spinner'); - }); -}); - -describe(' playing', () => { - it('Shows pause button', () => { - const wrapper = mount(); - expect(wrapper.find(FontAwesome).prop('name')).to.equal('pause'); - }); -}); - -describe(' ready to play', () => { - it('Shows play button', () => { - const wrapper = mount(); - expect(wrapper.find(FontAwesome).prop('name')).to.equal('play'); - }); -}); - -describe(' onClick', () => { - it('Shows play button', () => { - const spy = chai.spy(); - const wrapper = mount(); - wrapper.find('a').simulate('click'); - expect(spy).to.have.been.called; - }); -}); diff --git a/packages/ui/lib/components/PlayerControls/index.tsx b/packages/ui/lib/components/PlayerControls/index.tsx index 19a5bfc78a..eaac749ac5 100644 --- a/packages/ui/lib/components/PlayerControls/index.tsx +++ b/packages/ui/lib/components/PlayerControls/index.tsx @@ -37,7 +37,7 @@ const PlayerControls: React.FC = ({ loading={isLoading} icon={ isLoading - ? 'spinner' + ? 'circle notch' : isPlaying ? 'pause' : 'play' diff --git a/packages/ui/lib/components/TrackInfo/styles.scss b/packages/ui/lib/components/TrackInfo/styles.scss index dd4d899dd3..2e15d98a9a 100644 --- a/packages/ui/lib/components/TrackInfo/styles.scss +++ b/packages/ui/lib/components/TrackInfo/styles.scss @@ -23,6 +23,11 @@ .artist_name { font-size: 14px; color: rgba($white, 0.6); + cursor: pointer; + + &:hover { + color: rgba($white, 0.8); + } } .favorite_part { From a5e86bf0ca7fa9b14320ddb8424b6033b7a56956 Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 22 Jul 2020 01:44:04 +0200 Subject: [PATCH 30/63] Update ytdl-core --- packages/app/package.json | 2 +- packages/core/package.json | 2 +- packages/main/package.json | 2 +- .../AlbumGrid/{index.js => index.tsx} | 0 packages/ui/test/enzyme.card.test.js | 40 ------------------- 5 files changed, 3 insertions(+), 43 deletions(-) rename packages/ui/lib/components/AlbumGrid/{index.js => index.tsx} (100%) delete mode 100644 packages/ui/test/enzyme.card.test.js diff --git a/packages/app/package.json b/packages/app/package.json index 9ffc33a37f..422b3f03bd 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -78,7 +78,7 @@ "semantic-ui-react": "^0.88.2", "simple-get-lyrics": "0.0.4", "youtube-playlist": "^1.0.2", - "ytdl-core": "^1.0.7" + "ytdl-core": "^1.0.9" }, "devDependencies": { "@babel/core": "^7.5.5", diff --git a/packages/core/package.json b/packages/core/package.json index 5ea803cd99..f0cc0efe28 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,7 +46,7 @@ "mock-require": "^3.0.3", "ts-node": "^8.5.4", "typescript": "^3.7.3", - "ytdl-core": "^1.0.7" + "ytdl-core": "^1.0.9" }, "ava": { "files": [ diff --git a/packages/main/package.json b/packages/main/package.json index 8b67522fa4..439572b188 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -51,7 +51,7 @@ "typeorm": "^0.2.22", "url": "^0.11.0", "uuid": "^3.3.3", - "ytdl-core": "^1.0.7" + "ytdl-core": "^1.0.9" }, "devDependencies": { "@types/body-parser": "^1.17.1", diff --git a/packages/ui/lib/components/AlbumGrid/index.js b/packages/ui/lib/components/AlbumGrid/index.tsx similarity index 100% rename from packages/ui/lib/components/AlbumGrid/index.js rename to packages/ui/lib/components/AlbumGrid/index.tsx diff --git a/packages/ui/test/enzyme.card.test.js b/packages/ui/test/enzyme.card.test.js deleted file mode 100644 index ea961b32a4..0000000000 --- a/packages/ui/test/enzyme.card.test.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import test from 'ava'; -import chai from 'chai'; -import spies from 'chai-spies'; -import { shallow, configure } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; - -import './helpers/setup'; -import {Card} from '..'; - -configure({ adapter: new Adapter() }); -chai.use(spies); -const { expect } = chai; - -test('Should render given image', t => { - const wrapper = shallow(); - t.is( - wrapper.find('div>div>div:first-child').prop('style').backgroundImage, - 'url(\'IMG\')' - ); -}); - -test('Check onClick event', t => { - const spy = chai.spy(); - const wrapper = shallow(); - - wrapper.find('div[onClick]').simulate('click'); - expect(spy).to.have.been.called(); - t.pass(); -}); - -test('Should display given header', t => { - const wrapper = shallow(); - t.is(wrapper.find('h4').text(), 'HEADER'); -}); - -test('Should display given content', t => { - const wrapper = shallow(); - t.is(wrapper.find('p').text(), 'TEXT'); -}); From ec8916df9781b86904727dbdacde5b063a0a234f Mon Sep 17 00:00:00 2001 From: nukeop Date: Wed, 22 Jul 2020 01:58:38 +0200 Subject: [PATCH 31/63] Fix scss imports --- .env | 2 +- packages/app/typings/import-resources.d.ts | 4 ---- packages/app/typings/import-types.d.ts | 9 +++++++++ .../lib/typings/{import-types.ts => import-types.d.ts} | 0 4 files changed, 10 insertions(+), 5 deletions(-) delete mode 100644 packages/app/typings/import-resources.d.ts create mode 100644 packages/app/typings/import-types.d.ts rename packages/ui/lib/typings/{import-types.ts => import-types.d.ts} (100%) diff --git a/.env b/.env index 5982c89f34..9859cab24c 100644 --- a/.env +++ b/.env @@ -7,4 +7,4 @@ JAMENDO_CLIENT_ID=836523a7 LAST_FM_API_KEY=2b75dcb291e2b0c9a2c994aca522ac14 LAST_FM_API_SECRET=2ee49e35f08b837d43b2824198171fc8 SOUNDCLOUD_API_KEY=22e8f71d7ca75e156d6b2f0e0a5172b3 -YOUTUBE_API_KEY=AIzaSyCIM4EzNqi1in22f4Z3Ru3iYvLaY8tc3bo \ No newline at end of file +YOUTUBE_API_KEY=AIzaSyCkMLHynwJgJYQoGaIResXZxKUbC2euFfw \ No newline at end of file diff --git a/packages/app/typings/import-resources.d.ts b/packages/app/typings/import-resources.d.ts deleted file mode 100644 index fc781e8809..0000000000 --- a/packages/app/typings/import-resources.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.png' { - const src: string; - export default src; -} diff --git a/packages/app/typings/import-types.d.ts b/packages/app/typings/import-types.d.ts new file mode 100644 index 0000000000..c5e2592729 --- /dev/null +++ b/packages/app/typings/import-types.d.ts @@ -0,0 +1,9 @@ +declare module '*.scss' { + const content: {[className: string]: string}; + export default content; +} + +declare module '*.png' { + const src: string; + export default src; +} diff --git a/packages/ui/lib/typings/import-types.ts b/packages/ui/lib/typings/import-types.d.ts similarity index 100% rename from packages/ui/lib/typings/import-types.ts rename to packages/ui/lib/typings/import-types.d.ts From aa1b334b91ffe3969f2c746bc60f15b31201cdcd Mon Sep 17 00:00:00 2001 From: Charles Jacquin Date: Wed, 22 Jul 2020 11:35:01 +0200 Subject: [PATCH 32/63] chore(build): add icon dir path to electron-builder linux config see simon brandner comment https://github.com/electron-userland/electron-builder/issues/2577 fix#737 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index abecf98e1e..8ff09f48ec 100644 --- a/package.json +++ b/package.json @@ -135,6 +135,7 @@ } ], "linux": { + "icon": "./build/", "desktop": { "Name": "Nuclear", "Name[es]": "Reproductor de música Nuclear", From 7ec30eee96d65acfc900e71719eb4b2e3c830337 Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 23 Jul 2020 01:31:59 +0200 Subject: [PATCH 33/63] add babel preset for typescript --- packages/ui/package.json | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/ui/package.json b/packages/ui/package.json index e5db270b36..73cb32ea19 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -18,12 +18,12 @@ "url": "https://github.com/nukeop/nuclear/issues" }, "scripts": { - "storybook": "start-storybook -p 9001 -c .storybook", - "start": "tsc && copyfiles -u 1 ./lib/**/*.scss ./dist", - "build": "tsc && copyfiles -u 1 ./lib/**/*.scss ./dist", - "lint": "eslint lib stories --fix", - "test": "eslint lib && ava" - }, + "storybook": "start-storybook -p 9001 -c .storybook", + "start": "tsc && copyfiles -u 1 ./lib/**/*.scss ./dist", + "build": "tsc && copyfiles -u 1 ./lib/**/*.scss ./dist", + "lint": "eslint lib stories --fix", + "test": "eslint lib && ava" + }, "peerDependencies": { "react": "^16.4.1", "react-dom": "^16.4.1" @@ -34,6 +34,7 @@ "@babel/polyfill": "^7.6.0", "@babel/preset-env": "^7.6.2", "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.10.4", "@babel/register": "^7.6.2", "@storybook/addon-actions": "^3.4.12", "@storybook/addon-info": "^5.3.17", @@ -89,7 +90,8 @@ "babel": { "testOptions": { "presets": [ - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], "plugins": [ "@babel/plugin-syntax-jsx", @@ -101,8 +103,8 @@ "require": [ "@babel/register", "@babel/polyfill", - "ts-node/register", - "ignore-styles" + "ignore-styles", + "ts-node/register" ], "files": [ "!test/helpers" From ed794581fa96370c7555d7b50e78be0d02b436ab Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 23 Jul 2020 02:27:00 +0200 Subject: [PATCH 34/63] Migrate from ava to jest --- packages/ui/.babelrc | 1 + packages/ui/__mocks__/fileMock.ts | 1 + packages/ui/package.json | 43 ++++++------------- .../__snapshots__/enzyme.cover.test.tsx.snap | 13 ++++++ packages/ui/test/enzyme.cover.test.js | 18 -------- packages/ui/test/enzyme.cover.test.tsx | 9 ++++ packages/ui/test/formatDuration.test.js | 42 ------------------ packages/ui/test/formatDuration.test.ts | 40 +++++++++++++++++ packages/ui/test/helpers/setup.js | 21 --------- 9 files changed, 77 insertions(+), 111 deletions(-) create mode 100644 packages/ui/__mocks__/fileMock.ts create mode 100644 packages/ui/test/__snapshots__/enzyme.cover.test.tsx.snap delete mode 100644 packages/ui/test/enzyme.cover.test.js create mode 100644 packages/ui/test/enzyme.cover.test.tsx delete mode 100644 packages/ui/test/formatDuration.test.js create mode 100644 packages/ui/test/formatDuration.test.ts delete mode 100644 packages/ui/test/helpers/setup.js diff --git a/packages/ui/.babelrc b/packages/ui/.babelrc index 2ff7cad942..f8d1651596 100644 --- a/packages/ui/.babelrc +++ b/packages/ui/.babelrc @@ -1,6 +1,7 @@ { "presets": [ "@babel/preset-env", + "@babel/preset-typescript", "@babel/preset-react" ], "plugins": [ diff --git a/packages/ui/__mocks__/fileMock.ts b/packages/ui/__mocks__/fileMock.ts new file mode 100644 index 0000000000..86059f3629 --- /dev/null +++ b/packages/ui/__mocks__/fileMock.ts @@ -0,0 +1 @@ +module.exports = 'test-file-stub'; diff --git a/packages/ui/package.json b/packages/ui/package.json index 7b778f1a13..35078c5847 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -18,10 +18,10 @@ "url": "https://github.com/nukeop/nuclear/issues" }, "scripts": { - "storybook": "start-storybook -p 9001 -c .storybook", - "lint": "eslint lib stories --fix", - "test": "eslint lib && ava" - }, + "storybook": "start-storybook -p 9001 -c .storybook", + "lint": "eslint lib stories --fix", + "test": "eslint lib && jest" + }, "peerDependencies": { "react": "^16.4.1", "react-dom": "^16.4.1" @@ -41,23 +41,24 @@ "@storybook/cli": "^5.3.17", "@storybook/preset-typescript": "^2.1.0", "@storybook/react": "^5.3.17", + "@testing-library/react": "^10.4.7", + "@types/jest": "^26.0.5", "@typescript-eslint/eslint-plugin": "^2.25.0", "@typescript-eslint/parser": "^2.25.0", - "ava": "^2.4.0", "babel-eslint": "^7.2.3", "babel-loader": "^8.0.6", "chai": "^4.2.0", "chai-spies": "^1.0.0", "copyfiles": "^2.2.0", "css-loader": "^1.0.0", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.1.1", "eslint": "^6.7.2", "eslint-plugin-import": "^2.14.0", "eslint-plugin-node": "^10.0.0", "eslint-plugin-react": "^7.11.0", "eslint-plugin-react-hooks": "^2.1.1", + "identity-obj-proxy": "^3.0.0", "ignore-styles": "^5.0.1", + "jest": "^26.1.0", "jsdom": "^11.12.0", "mini-css-extract-plugin": "^0.4.1", "node-sass": "^4.9.2", @@ -84,28 +85,10 @@ "semantic-ui-react": "^0.88.1", "styled-components": "^4.4.1" }, - "ava": { - "babel": { - "testOptions": { - "presets": [ - "@babel/preset-react", - "@babel/preset-typescript" - ], - "plugins": [ - "@babel/plugin-syntax-jsx", - "@babel/plugin-proposal-object-rest-spread" - ] - } - }, - "compileEnhancements": false, - "require": [ - "@babel/register", - "@babel/polyfill", - "ignore-styles", - "ts-node/register" - ], - "files": [ - "!test/helpers" - ] + "jest": { + "moduleNameMapper": { + "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.ts", + "\\.(css|scss)$": "identity-obj-proxy" + } } } diff --git a/packages/ui/test/__snapshots__/enzyme.cover.test.tsx.snap b/packages/ui/test/__snapshots__/enzyme.cover.test.tsx.snap new file mode 100644 index 0000000000..42e2e8b097 --- /dev/null +++ b/packages/ui/test/__snapshots__/enzyme.cover.test.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Cover snapshot 1`] = ` + +
+ +
+
+`; diff --git a/packages/ui/test/enzyme.cover.test.js b/packages/ui/test/enzyme.cover.test.js deleted file mode 100644 index 0176b423da..0000000000 --- a/packages/ui/test/enzyme.cover.test.js +++ /dev/null @@ -1,18 +0,0 @@ -import test from 'ava'; -import React from 'react'; -import { shallow, configure } from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; - -import './helpers/setup'; -import {Cover} from '..'; - -configure({ adapter: new Adapter() }); - -test('shallow', (t) => { - const wrapper = shallow(); - t.is(wrapper.containsMatchingElement( -
- -
- ), true); -}); diff --git a/packages/ui/test/enzyme.cover.test.tsx b/packages/ui/test/enzyme.cover.test.tsx new file mode 100644 index 0000000000..837d999fba --- /dev/null +++ b/packages/ui/test/enzyme.cover.test.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { render } from '@testing-library/react' + +import { Cover } from '../lib'; + +it('Cover snapshot', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); +}); diff --git a/packages/ui/test/formatDuration.test.js b/packages/ui/test/formatDuration.test.js deleted file mode 100644 index 2d9f9149f6..0000000000 --- a/packages/ui/test/formatDuration.test.js +++ /dev/null @@ -1,42 +0,0 @@ -import test from 'ava'; - -import { formatDuration } from '../lib/utils'; - -test('Should format 0 second duration as 00:00', t => { - t.is(formatDuration(0), '00:00'); -}); - -test('Should format negative numbers as 00:00', t => { - t.is(formatDuration(-30), '00:00'); - t.is(formatDuration(-3600), '00:00'); - t.is(formatDuration(-5425), '00:00'); -}); - -test('Should format non-number values as 00:00', t => { - t.is(formatDuration([]), '00:00'); - t.is(formatDuration(null), '00:00'); - t.is(formatDuration({}), '00:00'); - t.is(formatDuration('test'), '00:00'); -}); - -test('Should format hours', t => { - t.is(formatDuration(3600), '01:00:00'); - t.is(formatDuration(7200), '02:00:00'); - t.is(formatDuration(5400), '01:30:00'); - t.is(formatDuration(5425), '01:30:25'); - t.is(formatDuration(36000), '10:00:00'); -}); - -test('Should format minutes', t => { - t.is(formatDuration(60), '01:00'); - t.is(formatDuration(120), '02:00'); - t.is(formatDuration(3545), '59:05'); - t.is(formatDuration(1827), '30:27'); -}); - -test('Should format seconds', t => { - t.is(formatDuration(1), '00:01'); - t.is(formatDuration(59), '00:59'); - t.is(formatDuration(30), '00:30'); - t.is(formatDuration(11), '00:11'); -}); diff --git a/packages/ui/test/formatDuration.test.ts b/packages/ui/test/formatDuration.test.ts new file mode 100644 index 0000000000..3a76848dbd --- /dev/null +++ b/packages/ui/test/formatDuration.test.ts @@ -0,0 +1,40 @@ +import { formatDuration } from '../lib/utils'; + +it('Should format 0 second duration as 00:00', () => { + expect(formatDuration(0)).toBe('00:00'); +}); + +it('Should format negative numbers as 00:00', () => { + expect(formatDuration(-30)).toBe('00:00'); + expect(formatDuration(-3600)).toBe('00:00'); + expect(formatDuration(-5425)).toBe('00:00'); +}); + +it('Should format non-number values as 00:00', () => { + expect(formatDuration([])).toBe('00:00'); + expect(formatDuration(null)).toBe('00:00'); + expect(formatDuration({})).toBe('00:00'); + expect(formatDuration('test')).toBe('00:00'); +}); + +it('Should format hours', () => { + expect(formatDuration(3600)).toBe('01:00:00'); + expect(formatDuration(7200)).toBe('02:00:00'); + expect(formatDuration(5400)).toBe('01:30:00'); + expect(formatDuration(5425)).toBe('01:30:25'); + expect(formatDuration(36000)).toBe('10:00:00'); +}); + +it('Should format minutes', () => { + expect(formatDuration(60)).toBe('01:00'); + expect(formatDuration(120)).toBe('02:00'); + expect(formatDuration(3545)).toBe('59:05'); + expect(formatDuration(1827)).toBe('30:27'); +}); + +it('Should format seconds', () => { + expect(formatDuration(1)).toBe('00:01'); + expect(formatDuration(59)).toBe('00:59'); + expect(formatDuration(30)).toBe('00:30'); + expect(formatDuration(11)).toBe('00:11'); +}); diff --git a/packages/ui/test/helpers/setup.js b/packages/ui/test/helpers/setup.js deleted file mode 100644 index 1bb92e0a17..0000000000 --- a/packages/ui/test/helpers/setup.js +++ /dev/null @@ -1,21 +0,0 @@ -const { JSDOM } = require('jsdom'); - -const jsdom = new JSDOM(''); -const { window } = jsdom; - -function copyProps(src, target) { - const props = Object.getOwnPropertyNames(src) - .filter(prop => typeof target[prop] === 'undefined') - .reduce((result, prop) => ({ - ...result, - [prop]: Object.getOwnPropertyDescriptor(src, prop) - }), {}); - Object.defineProperties(target, props); -} - -global.window = window; -global.document = window.document; -global.navigator = { - userAgent: 'node.js' -}; -copyProps(window, global); From 09992fac6ccdf7297d548bc6ec37c4964fdab1fe Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 23 Jul 2020 02:43:05 +0200 Subject: [PATCH 35/63] Streamline snapshot tests --- packages/ui/package.json | 17 +-- .../__snapshots__/albumGrid.test.tsx.snap | 114 ++++++++++++++++++ ...over.test.tsx.snap => cover.test.tsx.snap} | 2 +- packages/ui/test/albumGrid.test.tsx | 15 +++ packages/ui/test/cover.test.tsx | 6 + packages/ui/test/enzyme.cover.test.tsx | 9 -- packages/ui/test/helpers.tsx | 19 +++ 7 files changed, 158 insertions(+), 24 deletions(-) create mode 100644 packages/ui/test/__snapshots__/albumGrid.test.tsx.snap rename packages/ui/test/__snapshots__/{enzyme.cover.test.tsx.snap => cover.test.tsx.snap} (77%) create mode 100644 packages/ui/test/albumGrid.test.tsx create mode 100644 packages/ui/test/cover.test.tsx delete mode 100644 packages/ui/test/enzyme.cover.test.tsx create mode 100644 packages/ui/test/helpers.tsx diff --git a/packages/ui/package.json b/packages/ui/package.json index 35078c5847..94b5b4a9d3 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -43,14 +43,12 @@ "@storybook/react": "^5.3.17", "@testing-library/react": "^10.4.7", "@types/jest": "^26.0.5", + "@types/lodash": "^4.14.158", + "@types/react": "^16.9.43", "@typescript-eslint/eslint-plugin": "^2.25.0", "@typescript-eslint/parser": "^2.25.0", "babel-eslint": "^7.2.3", - "babel-loader": "^8.0.6", - "chai": "^4.2.0", - "chai-spies": "^1.0.0", "copyfiles": "^2.2.0", - "css-loader": "^1.0.0", "eslint": "^6.7.2", "eslint-plugin-import": "^2.14.0", "eslint-plugin-node": "^10.0.0", @@ -59,20 +57,11 @@ "identity-obj-proxy": "^3.0.0", "ignore-styles": "^5.0.1", "jest": "^26.1.0", - "jsdom": "^11.12.0", - "mini-css-extract-plugin": "^0.4.1", - "node-sass": "^4.9.2", - "optimize-css-assets-webpack-plugin": "^5.0.0", "react-hot-loader": "^4.3.4", "sass-loader": "^6.0.7", "style-loader": "^0.21.0", - "ts-loader": "^6.2.2", "ts-node": "^8.8.1", - "typescript": "^3.8.3", - "uglifyjs-webpack-plugin": "^1.2.7", - "webpack": "^4.16.3", - "webpack-cli": "^3.1.0", - "webpack-dev-server": "^3.1.5" + "typescript": "^3.8.3" }, "dependencies": { "classnames": "^2.2.6", diff --git a/packages/ui/test/__snapshots__/albumGrid.test.tsx.snap b/packages/ui/test/__snapshots__/albumGrid.test.tsx.snap new file mode 100644 index 0000000000..3bc919013d --- /dev/null +++ b/packages/ui/test/__snapshots__/albumGrid.test.tsx.snap @@ -0,0 +1,114 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`(Snapshot) AlbumGrid (basic) should render correctly 1`] = ` + +
+
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+

+ test +

+
+
+
+
+
+ +`; + +exports[`(Snapshot) AlbumGrid (loading) should render correctly 1`] = ` + +
+
+
+
+
+
+
+
+ +`; diff --git a/packages/ui/test/__snapshots__/enzyme.cover.test.tsx.snap b/packages/ui/test/__snapshots__/cover.test.tsx.snap similarity index 77% rename from packages/ui/test/__snapshots__/enzyme.cover.test.tsx.snap rename to packages/ui/test/__snapshots__/cover.test.tsx.snap index 42e2e8b097..a3fa51bda0 100644 --- a/packages/ui/test/__snapshots__/enzyme.cover.test.tsx.snap +++ b/packages/ui/test/__snapshots__/cover.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Cover snapshot 1`] = ` +exports[`(Snapshot) Cover should render correctly 1`] = `
{ - const { asFragment } = render(); - expect(asFragment()).toMatchSnapshot(); -}); diff --git a/packages/ui/test/helpers.tsx b/packages/ui/test/helpers.tsx new file mode 100644 index 0000000000..cdeb4576f1 --- /dev/null +++ b/packages/ui/test/helpers.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { render } from '@testing-library/react'; + +type AnyProps = { + [key: string]: any; +} + +export const makeSnapshotTest = ( + Component: React.FC, + props: AnyProps, + snapshotName?: string +) => { + describe(snapshotName || `(Snapshot) ${Component.displayName}`, () => { + it('should render correctly', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }) + }); +} \ No newline at end of file From 6f402e93d13b539ed964141cce7e302f94521fe8 Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 23 Jul 2020 02:54:39 +0200 Subject: [PATCH 36/63] Fix tests in app --- packages/app/package.json | 2 +- packages/ui/lib/components/Card/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index 6670c3841e..7ea653b82d 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -5,7 +5,7 @@ "scripts": { "start": "webpack-dev-server --inline --env.NODE_ENV=development", "build": "webpack --colors --env.NODE_ENV=production", - "test": "mocha --require ts-node/register --require @babel/register --require ignore-styles --require regenerator-runtime --timeout 10000 --prof --recursive", + "test": "TS_NODE_FILES=true mocha --require ignore-styles --require ts-node/register --require @babel/register --require regenerator-runtime --timeout 10000 --prof --recursive", "lint": "eslint app test --fix", "i18n": "sync-i18n --files 'app/locales/*.json' --primary en --languages fr tl nl de dk es pl zh ru tr id sk ko zh_tw se --space 2" }, diff --git a/packages/ui/lib/components/Card/index.tsx b/packages/ui/lib/components/Card/index.tsx index 0ab6febf0d..86c2405bf8 100644 --- a/packages/ui/lib/components/Card/index.tsx +++ b/packages/ui/lib/components/Card/index.tsx @@ -16,7 +16,7 @@ type CardProps = { header: string; content: string; image: string; - onClick: (event: React.MouseEvent) => void; + onClick: React.DOMAttributes['onClick']; withMenu?: boolean; animated?: boolean; menuEntries?: CardMenuEntry[]; From fd4974aa962c91f1b914418031739e80cd23cb30 Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 23 Jul 2020 10:27:17 +0200 Subject: [PATCH 37/63] Include @nuclear dirs --- packages/app/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/app/tsconfig.json b/packages/app/tsconfig.json index 691b45fb16..2e80a4a00b 100644 --- a/packages/app/tsconfig.json +++ b/packages/app/tsconfig.json @@ -17,6 +17,7 @@ "include": [ "app", "resources", - "typings" + "typings", + "node_modules/@nuclear" ] } \ No newline at end of file From c32ae4a2ca88771fa1baae39c4488244927f913a Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 23 Jul 2020 10:48:18 +0200 Subject: [PATCH 38/63] Exclude tests and stories --- packages/app/tsconfig.json | 4 ++++ packages/ui/lib/components/PlayerButton/index.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/app/tsconfig.json b/packages/app/tsconfig.json index 2e80a4a00b..4bcd95103d 100644 --- a/packages/app/tsconfig.json +++ b/packages/app/tsconfig.json @@ -19,5 +19,9 @@ "resources", "typings", "node_modules/@nuclear" + ], + "exclude": [ + "node_modules/@nuclear/*/test", + "node_modules/@nuclear/ui/stories" ] } \ No newline at end of file diff --git a/packages/ui/lib/components/PlayerButton/index.tsx b/packages/ui/lib/components/PlayerButton/index.tsx index 7a4440c63a..468828ffa0 100644 --- a/packages/ui/lib/components/PlayerButton/index.tsx +++ b/packages/ui/lib/components/PlayerButton/index.tsx @@ -8,7 +8,7 @@ export type PlayerButtonProps = { icon: SemanticICONS; size?: Exclude; ariaLabel?: string; - onClick?: (e: React.MouseEvent) => void; + onClick?: React.DOMAttributes['onClick']; disabled?: boolean; loading?: boolean; }; From 7d32e0e972297c9b0aca252a08cc766b294edd06 Mon Sep 17 00:00:00 2001 From: nukeop Date: Thu, 23 Jul 2020 12:15:50 +0200 Subject: [PATCH 39/63] Explicitly include main and core --- packages/main/webpack.config.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/main/webpack.config.ts b/packages/main/webpack.config.ts index ae4e9b4c79..9225c74c7e 100644 --- a/packages/main/webpack.config.ts +++ b/packages/main/webpack.config.ts @@ -16,6 +16,9 @@ const osMapper: Record = { win32: 'windows' }; +const MAIN_DIR = path.resolve(__dirname, 'src'); +const CORE_DIR = path.resolve(__dirname, '..', 'core'); + module.exports = (env: BuildEnv): import('webpack').Configuration => { if (!env.TARGET) { env.TARGET = osMapper[os.platform() as string]; @@ -29,7 +32,8 @@ module.exports = (env: BuildEnv): import('webpack').Configuration => { loader: 'ts-loader', options: { configFile: path.join(__dirname, `/config/tsconfig.${env.TARGET}.json`) - } + }, + include: [MAIN_DIR, CORE_DIR] }; return { From 1619a3f8851d6c9ab471d71d63f7d13e10b49e5a Mon Sep 17 00:00:00 2001 From: nukeop Date: Fri, 24 Jul 2020 01:10:27 +0200 Subject: [PATCH 40/63] Test --- packages/main/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/main/package.json b/packages/main/package.json index 439572b188..24afd61920 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -4,7 +4,7 @@ "description": "Nuclear main process", "scripts": { "start": "shx rm -rf build && webpack --env.NODE_ENV=development && electron build/main.js", - "build": "webpack --colors --env.NODE_ENV=production", + "build": "webpack --colors", "lint": "eslint src/**/*.ts --fix" }, "repository": { From cd70deba8d0667aa1fc0619c30bef2c9f04a190c Mon Sep 17 00:00:00 2001 From: nukeop Date: Fri, 24 Jul 2020 01:12:39 +0200 Subject: [PATCH 41/63] Decrease timeout --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f50a74b9cc..2cae377aeb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - timeout-minutes: 30 + timeout-minutes: 12 steps: - uses: actions/checkout@master From 02831285e5d5b3ad9fb6e2e1377620a51286d2c6 Mon Sep 17 00:00:00 2001 From: nukeop Date: Fri, 24 Jul 2020 14:23:42 +0200 Subject: [PATCH 42/63] Add missing dependency --- packages/main/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/main/package.json b/packages/main/package.json index 24afd61920..721884ffd7 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -76,6 +76,7 @@ "ts-node": "^8.5.4", "type-fest": "^0.8.1", "typescript": "^3.7.3", + "utf-8-validate": "^5.0.2", "webpack": "^4.41.2", "webpack-cli": "^3.3.10" }, From 1bc93713a6291d60649e4fc8fd071b7e8b7192de Mon Sep 17 00:00:00 2001 From: nukeop Date: Fri, 24 Jul 2020 14:29:05 +0200 Subject: [PATCH 43/63] Add env --- packages/main/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/package.json b/packages/main/package.json index 721884ffd7..c48f2661ff 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -4,7 +4,7 @@ "description": "Nuclear main process", "scripts": { "start": "shx rm -rf build && webpack --env.NODE_ENV=development && electron build/main.js", - "build": "webpack --colors", + "build": "webpack --colors --env.NODE_ENV=production", "lint": "eslint src/**/*.ts --fix" }, "repository": { @@ -91,4 +91,4 @@ "mpris-service": "2.1.0", "x11": "^2.3.0" } -} +} \ No newline at end of file From 94457f1d1b6f2f04ee5f423c2a6d1cbd690a49e7 Mon Sep 17 00:00:00 2001 From: nukeop Date: Fri, 24 Jul 2020 15:24:55 +0200 Subject: [PATCH 44/63] Update lerna --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index abecf98e1e..37ed17a432 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "eslint-plugin-react": "^7.12.4", "eslint-plugin-react-hooks": "^1.6.1", "husky": "^3.1.0", - "lerna": "^3.16.4", + "lerna": "^3.22.1", "lint-staged": "^10.0.0-beta.14", "shx": "^0.3.2", "typescript": "^3.7.4" From d7623c35da223a06ce655e7d943c7f1b5d166701 Mon Sep 17 00:00:00 2001 From: nukeop Date: Sat, 25 Jul 2020 01:06:29 +0200 Subject: [PATCH 45/63] Allow windows workflow to fail --- .github/workflows/build.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2cae377aeb..733226d267 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,9 +6,14 @@ jobs: build: runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.experimental }} strategy: matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-latest, macOS-latest] + experimental: [false] + include: + - os: windows-latest + experimental: true timeout-minutes: 12 steps: From 25a43b1b3b3e99b013d52e094ec9d805953fd03a Mon Sep 17 00:00:00 2001 From: nukeop Date: Sun, 26 Jul 2020 01:42:41 +0200 Subject: [PATCH 46/63] Fix storybook config --- packages/ui/.storybook/webpack.config.js | 20 ++++++++++++++++++-- packages/ui/package.json | 4 ++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/ui/.storybook/webpack.config.js b/packages/ui/.storybook/webpack.config.js index 4dd5a49f18..35e6dedb50 100644 --- a/packages/ui/.storybook/webpack.config.js +++ b/packages/ui/.storybook/webpack.config.js @@ -7,7 +7,15 @@ module.exports = { test: /\.s?css$/, use: [ 'style-loader', - 'css-loader?importLoaders=1&modules=true&localIdentName=[local]', + { + loader: 'css-loader', + options: { + importLoaders: 1, + modules: { + localIdentName: '[local]' + } + } + }, 'sass-loader' ], include: [ @@ -26,7 +34,15 @@ module.exports = { test: /\.css$/, use: [ 'style-loader', - 'css-loader?importLoaders=1&modules=true&localIdentName=[local]' + { + loader: 'css-loader', + options: { + importLoaders: 1, + modules: { + localIdentName: '[local]' + } + } + } ], include: [ path.resolve(__dirname, '../resources') diff --git a/packages/ui/package.json b/packages/ui/package.json index 94b5b4a9d3..3b3be11030 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -48,7 +48,9 @@ "@typescript-eslint/eslint-plugin": "^2.25.0", "@typescript-eslint/parser": "^2.25.0", "babel-eslint": "^7.2.3", + "babel-loader": "^8.1.0", "copyfiles": "^2.2.0", + "css-loader": "^4.0.0", "eslint": "^6.7.2", "eslint-plugin-import": "^2.14.0", "eslint-plugin-node": "^10.0.0", @@ -57,9 +59,11 @@ "identity-obj-proxy": "^3.0.0", "ignore-styles": "^5.0.1", "jest": "^26.1.0", + "node-sass": "^4.14.1", "react-hot-loader": "^4.3.4", "sass-loader": "^6.0.7", "style-loader": "^0.21.0", + "ts-loader": "^8.0.1", "ts-node": "^8.8.1", "typescript": "^3.8.3" }, From b86a8059262de65754676cd9b832eb27c2656e66 Mon Sep 17 00:00:00 2001 From: nukeop Date: Mon, 27 Jul 2020 01:49:40 +0200 Subject: [PATCH 47/63] Fix loading css in storybook --- packages/ui/.storybook/main.js | 54 ++++++++++++++++- packages/ui/.storybook/webpack.config.js | 58 ------------------- .../AlbumPreview/{index.js => index.jsx} | 0 .../ContextPopup/{index.js => index.jsx} | 0 packages/ui/lib/components/Loader/index.js | 2 + .../QueueItem/{index.js => index.jsx} | 0 packages/ui/lib/index.js | 2 +- packages/ui/package.json | 2 +- packages/ui/resources/{Lato.css => Lato.scss} | 0 9 files changed, 56 insertions(+), 62 deletions(-) delete mode 100644 packages/ui/.storybook/webpack.config.js rename packages/ui/lib/components/AlbumPreview/{index.js => index.jsx} (100%) rename packages/ui/lib/components/ContextPopup/{index.js => index.jsx} (100%) rename packages/ui/lib/components/QueueItem/{index.js => index.jsx} (100%) rename packages/ui/resources/{Lato.css => Lato.scss} (100%) diff --git a/packages/ui/.storybook/main.js b/packages/ui/.storybook/main.js index bab6623507..4add66ac4e 100644 --- a/packages/ui/.storybook/main.js +++ b/packages/ui/.storybook/main.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { stories: [ '../stories/*.stories.js', @@ -7,5 +9,53 @@ module.exports = { '@storybook/preset-typescript', '@storybook/addon-actions', '@storybook/addon-links' - ] -} \ No newline at end of file + ], + webpackFinal: config => { + return { + ...config, + module: { + ...config.module, + rules: [ + ...[ + config.module.rules[0], + config.module.rules[2] + ], + { + test: /\.s?css$/, + use: [ + 'style-loader', + { + loader: 'css-loader', + options: { + importLoaders: 1, + modules: { + auto: /\.s?css/, + localIdentName: '[local]' + } + } + }, + 'sass-loader' + ], + include: [ + path.resolve(__dirname, '../lib'), + path.resolve(__dirname, '../stories'), + path.resolve(__dirname, '../resources') + ] + }, + { + test: /\.(ttf|eot|woff|woff2|svg)$/, + loader: 'url-loader', + include: [ + path.resolve(__dirname, '../resources') + ] + }, + { + test: /\.(png|jpg|gif)$/, + loader: 'url-loader', + include: path.resolve(__dirname, '../resources') + } + ] + } + }; + } +}; \ No newline at end of file diff --git a/packages/ui/.storybook/webpack.config.js b/packages/ui/.storybook/webpack.config.js deleted file mode 100644 index 35e6dedb50..0000000000 --- a/packages/ui/.storybook/webpack.config.js +++ /dev/null @@ -1,58 +0,0 @@ -const path = require('path'); - -module.exports = { - module: { - rules: [ - { - test: /\.s?css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1, - modules: { - localIdentName: '[local]' - } - } - }, - 'sass-loader' - ], - include: [ - path.resolve(__dirname, '../lib'), - path.resolve(__dirname, '../stories') - ] - }, - { - test: /\.(ttf|eot|woff|woff2|svg)$/, - loader: 'url-loader', - include: [ - path.resolve(__dirname, '../resources') - ] - }, - { - test: /\.css$/, - use: [ - 'style-loader', - { - loader: 'css-loader', - options: { - importLoaders: 1, - modules: { - localIdentName: '[local]' - } - } - } - ], - include: [ - path.resolve(__dirname, '../resources') - ] - }, - { - test: /\.(png|jpg|gif)$/, - loader: 'url-loader', - include: path.resolve(__dirname, '../resources') - } - ] - } -}; diff --git a/packages/ui/lib/components/AlbumPreview/index.js b/packages/ui/lib/components/AlbumPreview/index.jsx similarity index 100% rename from packages/ui/lib/components/AlbumPreview/index.js rename to packages/ui/lib/components/AlbumPreview/index.jsx diff --git a/packages/ui/lib/components/ContextPopup/index.js b/packages/ui/lib/components/ContextPopup/index.jsx similarity index 100% rename from packages/ui/lib/components/ContextPopup/index.js rename to packages/ui/lib/components/ContextPopup/index.jsx diff --git a/packages/ui/lib/components/Loader/index.js b/packages/ui/lib/components/Loader/index.js index 869b201eda..84842a59c9 100644 --- a/packages/ui/lib/components/Loader/index.js +++ b/packages/ui/lib/components/Loader/index.js @@ -6,6 +6,8 @@ import common from '../../common.scss'; import styles from './styles.scss'; const Loader = props => { + + console.log({common, styles}) return ( Date: Mon, 27 Jul 2020 02:00:31 +0200 Subject: [PATCH 48/63] Snapshot test for player bar --- package.json | 6 +- packages/ui/lib/components/Loader/index.js | 2 - packages/ui/package.json | 2 +- packages/ui/stories/playerBar.stories.tsx | 14 +- .../__snapshots__/playerBar.test.tsx.snap | 126 ++++++++++++++++++ packages/ui/test/playerBar.test.tsx | 26 ++++ 6 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 packages/ui/test/__snapshots__/playerBar.test.tsx.snap create mode 100644 packages/ui/test/playerBar.test.tsx diff --git a/package.json b/package.json index 907dc564f4..656c377914 100644 --- a/package.json +++ b/package.json @@ -37,11 +37,11 @@ }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^2.13.0", - "@typescript-eslint/parser": "^2.13.0", + "@typescript-eslint/parser": "^2.34.0", "babel-eslint": "^10.0.3", "electron": "^4.2.11", "electron-builder": "^22.2.0", - "eslint": "^6.7.2", + "eslint": "^6.8.0", "eslint-plugin-node": "^9.1.0", "eslint-plugin-react": "^7.12.4", "eslint-plugin-react-hooks": "^1.6.1", @@ -49,7 +49,7 @@ "lerna": "^3.22.1", "lint-staged": "^10.0.0-beta.14", "shx": "^0.3.2", - "typescript": "^3.7.4" + "typescript": "^3.9.7" }, "optionalDependencies": { "7zip-bin-mac": "^1.0.1" diff --git a/packages/ui/lib/components/Loader/index.js b/packages/ui/lib/components/Loader/index.js index 84842a59c9..869b201eda 100644 --- a/packages/ui/lib/components/Loader/index.js +++ b/packages/ui/lib/components/Loader/index.js @@ -6,8 +6,6 @@ import common from '../../common.scss'; import styles from './styles.scss'; const Loader = props => { - - console.log({common, styles}) return (
{ }} queue={{ queueItems: [] }} playOptions={[ - { icon: 'repeat', enabled: false }, - { icon: 'magic' }, - { icon: 'random', enabled: false } + { icon: ('repeat' as SemanticICONS), enabled: false, name: 'Repeat' }, + { icon: ('magic' as SemanticICONS), name: 'Autoradio' }, + { icon: ('random' as SemanticICONS), enabled: false, name: 'Shuffle' } ]} + onTrackClick={() => {}} + onArtistClick={() => {}} + addToFavorites={() => {}} + removeFromFavorites={() => {}} + updateVolume={() => {}} + toggleMute={() => {}} + isMuted={false} />
; \ No newline at end of file diff --git a/packages/ui/test/__snapshots__/playerBar.test.tsx.snap b/packages/ui/test/__snapshots__/playerBar.test.tsx.snap new file mode 100644 index 0000000000..4135c15b0b --- /dev/null +++ b/packages/ui/test/__snapshots__/playerBar.test.tsx.snap @@ -0,0 +1,126 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`(Snapshot) Player bar should render correctly 1`] = ` + +
+
+
+
+
+
+
+ +
+
+
+