Skip to content

Commit

Permalink
add: Search Modal, enhance music open logic
Browse files Browse the repository at this point in the history
fix: renew discogs token
  • Loading branch information
jin60641 committed Nov 20, 2022
1 parent b48ef60 commit 210f44e
Show file tree
Hide file tree
Showing 33 changed files with 872 additions and 405 deletions.
1 change: 1 addition & 0 deletions .env → .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
REACT_APP_SENTRY_DSN=YOUR_SENTRY_DSN
REACT_APP_DOMAIN=MP3TAG
DISCOGS_API_TOKEN=YOUR_DISCOGS_API_TOKEN
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ module.exports = {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'react/jsx-no-duplicate-props': ['error', { 'ignoreCase': false }],
'jsx-a11y/label-has-associated-control': [ 2, {
'labelComponents': ['CustomInputLabel'],
'labelAttributes': ['label'],
'controlComponents': ['CustomInput'],
'depth': 3,
}],
},
globals: {
Atomics: 'readonly',
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# env
.env

# dependencies
/node_modules
/.pnp
Expand Down
58 changes: 42 additions & 16 deletions electron/apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,54 @@ export const setCount = (win: BrowserWindow, count: number) => {
win.webContents.send('MUSIC.SET_COUNT', count);
};

export const removeMusic = (win: BrowserWindow, filePath: string) => {
win.webContents.send('MUSIC.REMOVE_MUSIC', ({ filePaths: [filePath] }));
export const removeMusics = (win: BrowserWindow, filePaths: string[]) => {
win.webContents.send('MUSIC.REMOVE_MUSICS', ({ filePaths }));
};

export const addMusic = (win: BrowserWindow, filePath: string) => {
if (!fs.existsSync(filePath)) {
return removeMusic(win, filePath);
export const searchMusic = (win: BrowserWindow, result: any[]) => {
if (result.length) {
win.webContents.send('MUSIC.SEARCH_MUSIC#SUCCESS', result);
} else {
win.webContents.send('MUSIC.SEARCH_MUSIC#FAILURE');
}
win.webContents.send('MUSIC.ADD_MUSIC', ({
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath,
}));
};

export const saveMusic = (win: BrowserWindow, filePath: string) => {
if (!fs.existsSync(filePath)) {
return removeMusic(win, filePath);
export const addMusics = (win: BrowserWindow, filePaths: string[]) => {
const removedPaths: any = [];
const musics = filePaths.reduce((arr: any, filePath) => {
const isExist = fs.existsSync(filePath);
if (!isExist) {
removedPaths.push(filePath);
return arr;
}
return arr.concat([{
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath,
}]);
}, []);
removeMusics(win, removedPaths);
if (musics.length) {
win.webContents.send('MUSIC.ADD_MUSICS', musics);
}
};

export const saveMusics = (win: BrowserWindow, filePaths: string[]) => {
const removedPaths: any = [];
const musics = filePaths.reduce((arr: any, filePath) => {
const isExist = fs.existsSync(filePath);
if (!isExist) {
removedPaths.push(filePath);
return arr;
}
return arr.concat([{
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath,
}]);
}, []);
removeMusics(win, removedPaths);
if (musics.length) {
win.webContents.send('MUSIC.UPDATE_MUSIC', musics);
}
win.webContents.send('MUSIC.UPDATE_MUSIC', ({
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath,
}));
};

export const openPreference = (win: BrowserWindow) => {
Expand Down
52 changes: 33 additions & 19 deletions electron/electron.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import axios from 'axios';
import {
app,
BrowserWindow,
Expand All @@ -15,13 +16,17 @@ import * as NodeID3 from 'node-id3';
import * as path from 'path';

import {
addMusic,
addMusics,
openPreference,
resetMusic,
saveMusic,
saveMusics,
searchMusic,
setCount,
} from './apis';

axios.defaults.baseURL = 'https://api.discogs.com';
axios.defaults.headers.common = { Authorization: `Discogs token=${process.env.DISCOGS_API_TOKEN}` };

const close = () => null;

const isMac = process.platform === 'darwin';
Expand Down Expand Up @@ -54,7 +59,7 @@ const createWindow = () => {
resetMusic(win);
setCount(win, filePaths.length);
}
filePaths.forEach((filePath) => addMusic(win, filePath));
addMusics(win, filePaths);
});
};

Expand All @@ -64,7 +69,7 @@ const createWindow = () => {
filters: [{ name: 'Musics', extensions: ['mp3'] }], // TODO: support more music formats (ex. wav, flac, m4p, m4a)
}).then(({ filePaths }) => {
setCount(win, filePaths.length);
filePaths.forEach((filePath) => addMusic(win, filePath));
addMusics(win, filePaths);
});
};

Expand All @@ -73,13 +78,12 @@ const createWindow = () => {
if (dirPaths.length) {
resetMusic(win);
}
dirPaths.forEach((dirPath) => {
const paths = dirPaths.reduce((arr, dirPath) => {
const filePaths = glob.sync(path.join(dirPath, '**/*.mp3')); // TODO: support more music formats (ex. wav, flac, m4p, m4a)
setCount(win, filePaths.length);
filePaths.forEach((filePath) => {
addMusic(win, filePath);
});
});
return arr.concat(filePaths);
}, [] as string[]);
setCount(win, paths.length);
addMusics(win, paths);
});
};

Expand All @@ -88,9 +92,7 @@ const createWindow = () => {
dirPaths.forEach((dirPath) => {
const filePaths = glob.sync(path.join(dirPath, '**/*.mp3')); // TODO: support more music formats (ex. wav, flac, m4p, m4a)
setCount(win, filePaths.length);
filePaths.forEach((filePath) => {
addMusic(win, filePath);
});
addMusics(win, filePaths);
});
});
};
Expand Down Expand Up @@ -228,17 +230,29 @@ const createWindow = () => {
if (fs.lstatSync(dirPath).isDirectory()) {
const filePaths = glob.sync(path.join(dirPath, '**/*.mp3'));
setCount(win, filePaths.length);
filePaths.forEach((filePath) => addMusic(win, filePath));
addMusics(win, filePaths);
} else {
setCount(win, 1);
addMusic(win, dirPath);
addMusics(win, [dirPath]);
}
});
});

ipcMain.on('MUSIC.ADD_MUSIC', (_event, filePath) => {
setCount(win, 1);
addMusic(win, filePath);
ipcMain.on('MUSIC.ADD_MUSICS', (_event, filePaths) => {
setCount(win, filePaths.length);
addMusics(win, filePaths);
});

ipcMain.on('MUSIC.SEARCH_MUSIC', (_event, query) => {
axios.get<any>(`/database/search?q=${encodeURIComponent(query)}&page=1&per_page=5`)
.then(({ data }) => {
if (data?.results?.length) {
const result = data.results.map((item: any) => ({ picture: item.cover_image }));
searchMusic(win, result);
} else {
searchMusic(win, []);
}
}).catch((e) => { console.log(e); });
});

ipcMain.on('MUSIC.SAVE_MUSIC', async (_event, {
Expand Down Expand Up @@ -293,8 +307,8 @@ const createWindow = () => {
delete updatedTags.image.mime;
}
NodeID3.write(updatedTags, filePath);
saveMusic(win, filePath);
});
saveMusics(win, filePaths);
});
};

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@types/react-router-dom": "^5.1.5",
"@types/react-virtualized": "^9.21.10",
"@types/redux-logger": "^3.0.8",
"axios": "^0.21.1",
"babel-plugin-import": "^1.13.0",
"clsx": "^1.1.1",
"customize-cra": "^1.0.0",
Expand Down Expand Up @@ -79,10 +80,10 @@
]
},
"devDependencies": {
"electron": "^10.1.5",
"@typescript-eslint/eslint-plugin": "^4.11.0",
"concurrently": "^5.3.0",
"cross-env": "^7.0.2",
"electron": "^10.1.5",
"electron-builder": "^22.8.1",
"electron-reload": "^1.5.0",
"eslint-config-airbnb-typescript": "^12.0.0",
Expand Down
67 changes: 47 additions & 20 deletions public/apis.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";
exports.__esModule = true;
exports.openPreference = exports.saveMusic = exports.addMusic = exports.removeMusic = exports.setCount = exports.resetMusic = void 0;
exports.openPreference = exports.saveMusics = exports.addMusics = exports.searchMusic = exports.removeMusics = exports.setCount = exports.resetMusic = void 0;
var fs = require("fs");
var NodeID3 = require("node-id3");
var resetMusic = function (win) {
Expand All @@ -11,30 +11,57 @@ var setCount = function (win, count) {
win.webContents.send('MUSIC.SET_COUNT', count);
};
exports.setCount = setCount;
var removeMusic = function (win, filePath) {
win.webContents.send('MUSIC.REMOVE_MUSIC', ({ filePaths: [filePath] }));
var removeMusics = function (win, filePaths) {
win.webContents.send('MUSIC.REMOVE_MUSICS', ({ filePaths: filePaths }));
};
exports.removeMusic = removeMusic;
var addMusic = function (win, filePath) {
if (!fs.existsSync(filePath)) {
return exports.removeMusic(win, filePath);
exports.removeMusics = removeMusics;
var searchMusic = function (win, result) {
if (result.length) {
win.webContents.send('MUSIC.SEARCH_MUSIC#SUCCESS', result);
}
else {
win.webContents.send('MUSIC.SEARCH_MUSIC#FAILURE');
}
};
exports.searchMusic = searchMusic;
var addMusics = function (win, filePaths) {
var removedPaths = [];
var musics = filePaths.reduce(function (arr, filePath) {
var isExist = fs.existsSync(filePath);
if (!isExist) {
removedPaths.push(filePath);
return arr;
}
return arr.concat([{
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath
}]);
}, []);
exports.removeMusics(win, removedPaths);
if (musics.length) {
win.webContents.send('MUSIC.ADD_MUSICS', musics);
}
win.webContents.send('MUSIC.ADD_MUSIC', ({
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath
}));
};
exports.addMusic = addMusic;
var saveMusic = function (win, filePath) {
if (!fs.existsSync(filePath)) {
return exports.removeMusic(win, filePath);
exports.addMusics = addMusics;
var saveMusics = function (win, filePaths) {
var removedPaths = [];
var musics = filePaths.reduce(function (arr, filePath) {
var isExist = fs.existsSync(filePath);
if (!isExist) {
removedPaths.push(filePath);
return arr;
}
return arr.concat([{
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath
}]);
}, []);
exports.removeMusics(win, removedPaths);
if (musics.length) {
win.webContents.send('MUSIC.UPDATE_MUSIC', musics);
}
win.webContents.send('MUSIC.UPDATE_MUSIC', ({
metadata: NodeID3.read(filePath, { noRaw: true }),
path: filePath
}));
};
exports.saveMusic = saveMusic;
exports.saveMusics = saveMusics;
var openPreference = function (win) {
win.webContents.send('LAYOUT.SET_PREFERENCE', '');
};
Expand Down
19 changes: 18 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { useMemo } from 'react';

import { CssBaseline } from '@material-ui/core';
import { createMuiTheme, makeStyles, ThemeProvider } from '@material-ui/core/styles';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import { useSelector } from 'react-redux';
import {
Redirect,
Route,
Expand All @@ -14,6 +16,9 @@ import routes from 'constants/routes';
import { overrides, palettes } from 'constants/theme';
import Main from 'pages/Main';
import Preference from 'pages/Preference';
import Search from 'pages/Search';
import { Palette } from 'store/layout/types';
import { RootState } from 'store/types';

import 'vendor';

Expand All @@ -22,10 +27,21 @@ const useStyles = makeStyles({
content: { flexGrow: 1 },
});

const paletteSelector = ({ layout: { palette } }: RootState) => palette;

const App: React.FC = () => {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');

const palette = useSelector(paletteSelector);
const classes = useStyles();

const paletteType = 'light';
const paletteType = useMemo(() => {
if (palette === Palette.DEVICE) {
return prefersDarkMode ? 'dark' : 'light';
}
return palette;
}, [prefersDarkMode, palette]);

const theme = useMemo(() => createMuiTheme({
overrides,
palette: {
Expand Down Expand Up @@ -61,6 +77,7 @@ const App: React.FC = () => {
</Router>
<Alert />
<Preference />
<Search />
</ThemeProvider>
);
};
Expand Down
3 changes: 1 addition & 2 deletions src/components/Alert/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,13 @@ const Alert: React.FC = () => {
>
<SnackbarContent
className={type ? classes[type] : undefined}
aria-describedby='client-snackbar'
message={(
<span id='client-snackbar' className={classes.message}>
{message}
</span>
)}
action={[
<IconButton key='close' aria-label='close' color='inherit' onClick={handleClose}>
<IconButton key='close' color='inherit' onClick={handleClose}>
<Close className={classes.icon} />
</IconButton>,
]}
Expand Down
Loading

0 comments on commit 210f44e

Please sign in to comment.