diff --git a/.eslintrc.yml b/.eslintrc.yml index c98a4a7db..2b7a7621d 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -40,6 +40,8 @@ rules: import/no-unresolved: off import/export: off import/named: off + no-use-before-define: off + import/no-webpack-loader-syntax: off overrides: - files: - '**/*.ts' @@ -47,5 +49,5 @@ overrides: rules: no-undef: off no-unused-vars: off - no-use-before-define: off + no-redeclare: off no-useless-constructor: off diff --git a/.github/workflows/todo.yml b/.github/workflows/todo.yml index b08a5e8e3..adfa7e241 100644 --- a/.github/workflows/todo.yml +++ b/.github/workflows/todo.yml @@ -8,12 +8,12 @@ jobs: name: Collect TODO runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - name: Set GitHub auth - run: | - git remote set-url origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.git" - - name: Collect TODO - uses: dtinth/todo-actions@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TODO_ACTIONS_MONGO_URL: ${{ secrets.TODO_ACTIONS_MONGO_URL }} + - uses: actions/checkout@master + - name: Set GitHub auth + run: | + git remote set-url origin "https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY.git" + - name: Collect TODO + uses: dtinth/todo-actions@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TODO_ACTIONS_MONGO_URL: ${{ secrets.TODO_ACTIONS_MONGO_URL }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e728ac87..486ad1d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,21 @@ [@pnkapadia64]: https://github.com/pnkapadia64 [@tsfreddie]: https://github.com/TsFreddie [@vishal5251]: https://github.com/vishal5251 +[@dimitrov-d]: https://github.com/dimitrov-d [@s-pace]: https://github.com/s-pace +## v49.0.1-pre.202110111207 + +### Internals + +- Improved the code readability of custom songs folder feature. [#699], by + [@dimitrov-d] +- Prepare the codebase for implementing the detection of removed custom song + folder and upgraded Prettier to v2. [#700], by [@dtinth] + +[#699]: https://github.com/bemusic/bemuse/pull/699 +[#700]: https://github.com/bemusic/bemuse/pull/700 + ## v49 (2021-10-09) ### New stuff diff --git a/bemuse/config/webpack.js b/bemuse/config/webpack.js index 3087c2f99..101408e1d 100644 --- a/bemuse/config/webpack.js +++ b/bemuse/config/webpack.js @@ -245,10 +245,7 @@ function applyKarmaConfig(config) { return config } -export const generateWebConfig = flowRight( - applyWebConfig, - generateBaseConfig -) +export const generateWebConfig = flowRight(applyWebConfig, generateBaseConfig) export const generateKarmaConfig = flowRight( applyKarmaConfig, @@ -259,7 +256,7 @@ export default generateWebConfig() function CompileProgressPlugin() { const gauge = new Gauge() - return new webpack.ProgressPlugin(function(percentage, message) { + return new webpack.ProgressPlugin(function (percentage, message) { if (percentage === 1) gauge.hide() else gauge.show(message, percentage) }) diff --git a/bemuse/gulpfile.js b/bemuse/gulpfile.js index 2ee304d51..5f65327e3 100644 --- a/bemuse/gulpfile.js +++ b/bemuse/gulpfile.js @@ -2,6 +2,6 @@ require('./node-environment') require('gulp').registry(require('undertaker-forward-reference')()) require('glob') .sync('./tasks/*.js') - .forEach(function(file) { + .forEach(function (file) { require(file) }) diff --git a/bemuse/karma.conf.js b/bemuse/karma.conf.js index 41c8881c5..73ebaffbf 100644 --- a/bemuse/karma.conf.js +++ b/bemuse/karma.conf.js @@ -3,7 +3,7 @@ require('./node-environment') if (!process.env.NODE_ENV) process.env.NODE_ENV = 'test' process.env.CHROME_BIN = require('puppeteer').executablePath() -module.exports = function(config) { +module.exports = function (config) { config.set({ basePath: '', frameworks: ['mocha'], diff --git a/bemuse/package.json b/bemuse/package.json index 0b4bfce34..07fada9e9 100644 --- a/bemuse/package.json +++ b/bemuse/package.json @@ -36,7 +36,7 @@ "@types/react-dom": "16", "@types/webpack-env": "^1.14.0", "@types/wicg-file-system-access": "^2020.9.4", - "@typescript-eslint/parser": "^2.0.0", + "@typescript-eslint/parser": "^4.33.0", "autoprefixer": "^9.1.5", "body-parser": "^1.18.3", "brfs": "^1.6.1", diff --git a/bemuse/src/app/analytics.js b/bemuse/src/app/analytics.js index 00904f54a..b2664916a 100644 --- a/bemuse/src/app/analytics.js +++ b/bemuse/src/app/analytics.js @@ -9,7 +9,7 @@ import * as Options from './entities/Options' import getLR2Score from './interactors/getLR2Score' import getNonMissedDeltas from './interactors/getNonMissedDeltas' -let ga = window.ga || function() {} +let ga = window.ga || function () {} const startTime = Date.now() const sid = ObjectID.generate() diff --git a/bemuse/src/app/entities/Collections.js b/bemuse/src/app/entities/Collections.js index 7d195e989..84b2cb820 100644 --- a/bemuse/src/app/entities/Collections.js +++ b/bemuse/src/app/entities/Collections.js @@ -3,13 +3,13 @@ import * as LoadState from './LoadState' export const initialState = Immutable.Map() -export const beginLoading = url => state => +export const beginLoading = (url) => (state) => state.set(url, LoadState.initLoading()) -export const completeLoading = (url, data) => state => +export const completeLoading = (url, data) => (state) => state.update(url, LoadState.completeWithValue(data)) -export const errorLoading = (url, error) => state => +export const errorLoading = (url, error) => (state) => state.update(url, LoadState.errorWithReason(error)) -export const getCollectionByUrl = url => state => state.get(url) +export const getCollectionByUrl = (url) => (state) => state.get(url) diff --git a/bemuse/src/app/entities/Collections.spec.js b/bemuse/src/app/entities/Collections.spec.js index 62a8ef5d9..35cdee67e 100644 --- a/bemuse/src/app/entities/Collections.spec.js +++ b/bemuse/src/app/entities/Collections.spec.js @@ -3,7 +3,7 @@ import * as LoadState from './LoadState' import { given, shouldEqual } from 'circumstance' -describe('Collections', function() { +describe('Collections', function () { it('should receive collection data', () => given(Collections.initialState) .when(Collections.beginLoading('https://test-server/')) diff --git a/bemuse/src/app/entities/LoadState.js b/bemuse/src/app/entities/LoadState.js index 39d015bc7..e7a18aa03 100644 --- a/bemuse/src/app/entities/LoadState.js +++ b/bemuse/src/app/entities/LoadState.js @@ -3,25 +3,28 @@ import u from 'updeep' // Initializers export const initLoading = () => ({ status: 'loading' }) -export const initCompletedWithValue = value => ({ status: 'completed', value }) +export const initCompletedWithValue = (value) => ({ + status: 'completed', + value, +}) // Queries -export const isLoading = state => state.status === 'loading' -export const isCompleted = state => state.status === 'completed' -export const isError = state => state.status === 'error' -export const value = state => state.value -export const error = state => isError(state) && state.error +export const isLoading = (state) => state.status === 'loading' +export const isCompleted = (state) => state.status === 'completed' +export const isError = (state) => state.status === 'error' +export const value = (state) => state.value +export const error = (state) => isError(state) && state.error // State Updaters -export const beginLoading = state => initLoading() +export const beginLoading = (state) => initLoading() -export const completeWithValue = value => +export const completeWithValue = (value) => u({ status: 'completed', value: () => value, }) -export const errorWithReason = error => +export const errorWithReason = (error) => u({ status: 'error', error: () => error, diff --git a/bemuse/src/app/entities/LoadState.spec.js b/bemuse/src/app/entities/LoadState.spec.js index 5c2b6addd..36ca2ecb2 100644 --- a/bemuse/src/app/entities/LoadState.spec.js +++ b/bemuse/src/app/entities/LoadState.spec.js @@ -2,7 +2,7 @@ import * as LoadState from './LoadState' import { given, shouldEqual } from 'circumstance' -describe('LoadState', function() { +describe('LoadState', function () { it('initLoading should be loading', () => given(LoadState.initLoading()).then(LoadState.isLoading, shouldEqual(true))) it('completeWithValue should turn it into completed', () => @@ -18,4 +18,4 @@ describe('LoadState', function() { .and(LoadState.error, errorMessage, shouldEqual('x'))) }) -const errorMessage = error => error.message +const errorMessage = (error) => error.message diff --git a/bemuse/src/app/entities/MusicSearchText.js b/bemuse/src/app/entities/MusicSearchText.js index 52249c2ba..40a6ebfeb 100644 --- a/bemuse/src/app/entities/MusicSearchText.js +++ b/bemuse/src/app/entities/MusicSearchText.js @@ -1,7 +1,7 @@ import u from 'updeep' // Initializers -export const initWithText = text => ({ +export const initWithText = (text) => ({ staged: text, committed: text, }) @@ -10,10 +10,10 @@ export const initWithText = text => ({ export const initialState = initWithText('') // Queries -export const searchText = state => state.committed -export const inputText = state => state.staged +export const searchText = (state) => state.committed +export const inputText = (state) => state.staged // Updaters -export const handleTextType = text => u({ staged: text }) -export const handleDebounce = state => ({ ...state, committed: state.staged }) -export const setText = text => () => initWithText(text) +export const handleTextType = (text) => u({ staged: text }) +export const handleDebounce = (state) => ({ ...state, committed: state.staged }) +export const setText = (text) => () => initWithText(text) diff --git a/bemuse/src/app/entities/MusicSearchText.spec.js b/bemuse/src/app/entities/MusicSearchText.spec.js index 7fbb2993a..0905ed1f8 100644 --- a/bemuse/src/app/entities/MusicSearchText.spec.js +++ b/bemuse/src/app/entities/MusicSearchText.spec.js @@ -1,7 +1,7 @@ import * as MusicSearchText from './MusicSearchText' import { given, shouldEqual } from 'circumstance' -describe('MusicSearchText', function() { +describe('MusicSearchText', function () { it('is initially blank', () => given(MusicSearchText.initialState) .then(MusicSearchText.searchText, shouldEqual('')) diff --git a/bemuse/src/app/entities/MusicSelection.js b/bemuse/src/app/entities/MusicSelection.js index ec279517b..889440208 100644 --- a/bemuse/src/app/entities/MusicSelection.js +++ b/bemuse/src/app/entities/MusicSelection.js @@ -8,22 +8,22 @@ export const initialState = { } // Queries -export const selectedSongGivenSongs = songs => state => { +export const selectedSongGivenSongs = (songs) => (state) => { const song = _.find(songs, { id: state.selectedSongId }) if (song) return song return songs[0] } -export const selectedChartGivenCharts = charts => state => { +export const selectedChartGivenCharts = (charts) => (state) => { charts = charts || [] const chart = _.find(charts, { file: state.selectedChartId }) if (chart) return chart - return _.minBy(charts, chart => + return _.minBy(charts, (chart) => Math.abs(chart.info.level - state.selectedChartLevel) ) } // Updater -export const selectSong = songId => +export const selectSong = (songId) => u({ selectedSongId: songId, }) diff --git a/bemuse/src/app/entities/MusicSelection.spec.js b/bemuse/src/app/entities/MusicSelection.spec.js index a8c270452..878ab042e 100644 --- a/bemuse/src/app/entities/MusicSelection.spec.js +++ b/bemuse/src/app/entities/MusicSelection.spec.js @@ -1,7 +1,7 @@ import * as MusicSelection from './MusicSelection' import { given, shouldEqual } from 'circumstance' -describe('MusicSelection', function() { +describe('MusicSelection', function () { it('allows selecting song', () => given(MusicSelection.initialState) .when(MusicSelection.selectSong('song1')) @@ -25,9 +25,9 @@ describe('MusicSelection', function() { it('should allow selecting chart', () => given(MusicSelection.initialState) .when(MusicSelection.selectChart('song1', 'chart1.bml', 8)) - .then(state => state.selectedSongId, shouldEqual('song1')) - .and(state => state.selectedChartId, shouldEqual('chart1.bml')) - .and(state => state.selectedChartLevel, shouldEqual(8))) + .then((state) => state.selectedSongId, shouldEqual('song1')) + .and((state) => state.selectedChartId, shouldEqual('chart1.bml')) + .and((state) => state.selectedChartLevel, shouldEqual(8))) const givenSelectedChart = given(MusicSelection.initialState).and( MusicSelection.selectChart('song1', 'chart1.bml', 8) diff --git a/bemuse/src/app/entities/Options.js b/bemuse/src/app/entities/Options.js index 3ba2b3694..c7f722b4b 100644 --- a/bemuse/src/app/entities/Options.js +++ b/bemuse/src/app/entities/Options.js @@ -5,17 +5,17 @@ import * as options from '../options' // Initializers export const initialState = options.DEFAULTS -export const initWithDataFromStorage = options => ({ +export const initWithDataFromStorage = (options) => ({ ...initialState, ...options, }) // Internal utils -const toggleOptionEnabled = value => value === '1' -const toggleOption = value => (toggleOptionEnabled(value) ? '0' : '1') +const toggleOptionEnabled = (value) => value === '1' +const toggleOption = (value) => (toggleOptionEnabled(value) ? '0' : '1') // Key mapping -export const getKeyMapping = (mode, key) => state => +export const getKeyMapping = (mode, key) => (state) => state['input.P1.keyboard.' + mode + '.' + key] export const changeKeyMapping = (mode, key, keyCode) => u({ @@ -23,57 +23,55 @@ export const changeKeyMapping = (mode, key, keyCode) => }) // Play mode -export const playMode = state => state['player.P1.mode'] -export const changePlayMode = mode => +export const playMode = (state) => state['player.P1.mode'] +export const changePlayMode = (mode) => u({ 'player.P1.mode': mode, - 'player.P1.panel': panel => + 'player.P1.panel': (panel) => panel === '3d' && mode !== 'KB' ? 'center' : panel, }) // Speed -export const speed = state => state['player.P1.speed'] -export const changeSpeed = speed => u({ 'player.P1.speed': speed }) +export const speed = (state) => state['player.P1.speed'] +export const changeSpeed = (speed) => u({ 'player.P1.speed': speed }) // Lead time -export const leadTime = state => { +export const leadTime = (state) => { const parsed = parseInt(state['player.P1.lead-time'], 10) if (!parsed) return 1685 if (parsed < 138) return 138 return parsed } -export const changeLeadTime = leadTime => u({ 'player.P1.lead-time': leadTime }) +export const changeLeadTime = (leadTime) => + u({ 'player.P1.lead-time': leadTime }) // Scratch position -export const scratchPosition = state => { +export const scratchPosition = (state) => { if (state['player.P1.mode'] === 'KB') { return 'off' } else { return state['player.P1.scratch'] } } -export const changeScratchPosition = position => { +export const changeScratchPosition = (position) => { if (position === 'off') { return changePlayMode('KB') } else { - return _.flow( - changePlayMode('BM'), - u({ 'player.P1.scratch': position }) - ) + return _.flow(changePlayMode('BM'), u({ 'player.P1.scratch': position })) } } // Panel -export const panelPlacement = state => state['player.P1.panel'] -export const changePanelPlacement = placement => +export const panelPlacement = (state) => state['player.P1.panel'] +export const changePanelPlacement = (placement) => u({ 'player.P1.panel': placement, - 'player.P1.mode': mode => + 'player.P1.mode': (mode) => placement === '3d' && mode !== 'KB' ? 'KB' : mode, }) // Lane cover -export const laneCover = state => { +export const laneCover = (state) => { return ( Math.min( 50, @@ -81,39 +79,39 @@ export const laneCover = state => { ) / 100 || 0 ) } -export const changeLaneCover = laneCover => +export const changeLaneCover = (laneCover) => u({ 'player.P1.lane-cover': laneCover }) // BGA -export const isBackgroundAnimationsEnabled = state => +export const isBackgroundAnimationsEnabled = (state) => toggleOptionEnabled(state['system.bga.enabled']) export const toggleBackgroundAnimations = u({ 'system.bga.enabled': toggleOption, }) // Auto-velocity -export const isAutoVelocityEnabled = state => +export const isAutoVelocityEnabled = (state) => toggleOptionEnabled(state['player.P1.auto-velocity']) export const toggleAutoVelocity = u({ 'player.P1.auto-velocity': toggleOption, }) // Song preview enabled -export const isPreviewEnabled = state => +export const isPreviewEnabled = (state) => toggleOptionEnabled(state['system.preview.enabled']) export const togglePreview = u({ 'system.preview.enabled': toggleOption, }) // Gauge -export const isGaugeEnabled = state => getGauge(state) !== 'off' -export const getGauge = state => state['player.P1.gauge'] +export const isGaugeEnabled = (state) => getGauge(state) !== 'off' +export const getGauge = (state) => state['player.P1.gauge'] export const toggleGauge = u({ - 'player.P1.gauge': gauge => (gauge === 'off' ? 'hope' : 'off'), + 'player.P1.gauge': (gauge) => (gauge === 'off' ? 'hope' : 'off'), }) // Queries -export const keyboardMapping = state => { +export const keyboardMapping = (state) => { let mapping = {} for (let control of ['1', '2', '3', '4', '5', '6', '7', 'SC', 'SC2']) { let key = 'input.P1.keyboard.' + playMode(state) + '.' + control @@ -123,35 +121,35 @@ export const keyboardMapping = state => { } // Feature acknowledgements -export const hasAcknowledged = featureKey => state => +export const hasAcknowledged = (featureKey) => (state) => state[`system.ack.${featureKey}`] === '1' -export const acknowledge = featureKey => +export const acknowledge = (featureKey) => u({ [`system.ack.${featureKey}`]: '1', }) // Audio-input latency -export const audioInputLatency = state => +state['system.offset.audio-input'] -export const changeAudioInputLatency = latency => +export const audioInputLatency = (state) => +state['system.offset.audio-input'] +export const changeAudioInputLatency = (latency) => u({ 'system.offset.audio-input': `${latency}`, }) // Gamepad Continuous Axis -export const isContinuousAxisEnabled = state => +export const isContinuousAxisEnabled = (state) => toggleOptionEnabled(state['gamepad.continuous']) export const toggleContinuousAxis = u({ 'gamepad.continuous': toggleOption, }) // Gamepad Sensitivity -export const sensitivity = state => state['gamepad.sensitivity'] -export const changeSensitivity = sensitivity => +export const sensitivity = (state) => state['gamepad.sensitivity'] +export const changeSensitivity = (sensitivity) => u({ 'gamepad.sensitivity': sensitivity }) // Latest version -export const lastSeenVersion = state => state['system.last-seen-version'] -export const updateLastSeenVersion = newVersion => +export const lastSeenVersion = (state) => state['system.last-seen-version'] +export const updateLastSeenVersion = (newVersion) => u({ 'system.last-seen-version': newVersion, }) diff --git a/bemuse/src/app/entities/Options.spec.js b/bemuse/src/app/entities/Options.spec.js index 6f151f865..c490ef457 100644 --- a/bemuse/src/app/entities/Options.spec.js +++ b/bemuse/src/app/entities/Options.spec.js @@ -25,13 +25,13 @@ describe('Options', () => { it('can be retrieved for current mode by column', () => { given(Options.initialState) .when(Options.changePlayMode('KB')) - .then(Options.keyboardMapping, mapping => { + .then(Options.keyboardMapping, (mapping) => { assert(mapping['4'] === '32') // KB mode, 4th button is space. }) given(Options.initialState) .when(Options.changePlayMode('BM')) - .then(Options.keyboardMapping, mapping => { + .then(Options.keyboardMapping, (mapping) => { assert(mapping['4'] === '68') // BM mode, 4th button is D. }) }) @@ -80,7 +80,7 @@ describe('Options', () => { given(Options.initialState) .when(Options.changeScratchPosition('off')) .then(Options.scratchPosition, shouldEqual('off')) - .and(state => { + .and((state) => { assert(state['player.P1.mode'] === 'KB') }) }) @@ -88,7 +88,7 @@ describe('Options', () => { given(Options.initialState) .when(Options.changeScratchPosition('right')) .then(Options.scratchPosition, shouldEqual('right')) - .and(state => { + .and((state) => { assert(state['player.P1.mode'] === 'BM') }) }) @@ -97,7 +97,7 @@ describe('Options', () => { .when(Options.changeScratchPosition('right')) .and(Options.changeScratchPosition('off')) .then(Options.scratchPosition, shouldEqual('off')) - .and(state => { + .and((state) => { assert(state['player.P1.mode'] === 'KB') assert(state['player.P1.scratch'] === 'right') }) diff --git a/bemuse/src/app/game-launcher.ts b/bemuse/src/app/game-launcher.ts index 76c099921..c250842a2 100644 --- a/bemuse/src/app/game-launcher.ts +++ b/bemuse/src/app/game-launcher.ts @@ -46,7 +46,7 @@ export async function launch(launchOptions: LaunchOptions) { await launchGame( launchOptions, sceneDisplayContext, - work => (currentWork = work) + (work) => (currentWork = work) ) } catch (e) { await new Promise((resolve, reject) => { diff --git a/bemuse/src/app/index.js b/bemuse/src/app/index.js index ab16949bc..e64a0f285 100644 --- a/bemuse/src/app/index.js +++ b/bemuse/src/app/index.js @@ -62,7 +62,7 @@ function bootUp() { }) run(OptionsIO.loadInitialOptions()) - getSongsFromCustomFolders(getDefaultCustomFolderContext()).then(songs => { + getSongsFromCustomFolders(getDefaultCustomFolderContext()).then((songs) => { if (songs.length > 0) { store.dispatch({ type: ReduxState.CUSTOM_SONGS_LOADED, @@ -79,9 +79,7 @@ export function main() { // setup service worker let promise = setupServiceWorker() if (promise && promise.then) { - Promise.resolve(promise) - .finally(displayFirstScene) - .done() + Promise.resolve(promise).finally(displayFirstScene).done() } else { displayFirstScene() } diff --git a/bemuse/src/app/interactors/createAutoVelocity.spec.js b/bemuse/src/app/interactors/createAutoVelocity.spec.js index dec4343f5..2f696f4e2 100644 --- a/bemuse/src/app/interactors/createAutoVelocity.spec.js +++ b/bemuse/src/app/interactors/createAutoVelocity.spec.js @@ -2,8 +2,8 @@ import assert from 'power-assert' import createAutoVelocity from './createAutoVelocity' -describe('createAutoVelocity', function() { - describe('when disabled', function() { +describe('createAutoVelocity', function () { + describe('when disabled', function () { it('initial speed should be from options', () => { const autoVelocity = createAutoVelocity({ enabled: false, @@ -28,7 +28,7 @@ describe('createAutoVelocity', function() { }) }) - describe('when enabled', function() { + describe('when enabled', function () { it('initial speed should be from song’s BPM', () => { const autoVelocity = createAutoVelocity({ enabled: true, diff --git a/bemuse/src/app/interactors/createAutoVelocity.ts b/bemuse/src/app/interactors/createAutoVelocity.ts index d75ce4eef..699932113 100644 --- a/bemuse/src/app/interactors/createAutoVelocity.ts +++ b/bemuse/src/app/interactors/createAutoVelocity.ts @@ -61,8 +61,9 @@ function autoVelocity({ }): VelocityController { const visiblePortion = 1 - Math.abs(laneCover) const nominalSpeedLeadTime = ((60000 * 5) / songBPM) * visiblePortion - const initialSpeed = _.minBy(_.range(1, 999).map(x => x / 10), speed => - Math.abs(desiredLeadTime - nominalSpeedLeadTime / speed) + const initialSpeed = _.minBy( + _.range(1, 999).map((x) => x / 10), + (speed) => Math.abs(desiredLeadTime - nominalSpeedLeadTime / speed) )! return { getInitialSpeed() { diff --git a/bemuse/src/app/interactors/createCollectionLoader.js b/bemuse/src/app/interactors/createCollectionLoader.js index d93506adb..60375af3d 100644 --- a/bemuse/src/app/interactors/createCollectionLoader.js +++ b/bemuse/src/app/interactors/createCollectionLoader.js @@ -11,15 +11,15 @@ export function createCollectionLoader({ }) { const collectionUrl川 = new Rx.Subject() const sideEffect川 = collectionUrl川 - .groupBy(url => url) - .flatMap(url川 => - url川.switchMap(url => + .groupBy((url) => url) + .flatMap((url川) => + url川.switchMap((url) => Rx.Observable.concat( Rx.Observable.of(() => onBeginLoading(url)), Rx.Observable.fromPromise( loadCollection(url, { fetch }).then( - data => () => onLoad(url, data), - error => () => onErrorLoading(url, error) + (data) => () => onLoad(url, data), + (error) => () => onErrorLoading(url, error) ) ) ) diff --git a/bemuse/src/app/interactors/createCollectionLoader.spec.js b/bemuse/src/app/interactors/createCollectionLoader.spec.js index d40c29238..33b40fd32 100644 --- a/bemuse/src/app/interactors/createCollectionLoader.spec.js +++ b/bemuse/src/app/interactors/createCollectionLoader.spec.js @@ -18,12 +18,12 @@ function setup({ fetch }) { } describe('createCollectionLoader', () => { - describe('load(url)', function() { + describe('load(url)', function () { it( 'should load the collection and call `onLoad`', - co.wrap(function*() { + co.wrap(function* () { const { collectionLoader, onBeginLoading, onLoad } = setup({ - fetch: url => { + fetch: (url) => { assert( url === '/src/app/test-fixtures/example-music-server/index.json' ) @@ -41,9 +41,9 @@ describe('createCollectionLoader', () => { it( 'should load the collection and call `onErrorLoading` when there is an error', - co.wrap(function*() { + co.wrap(function* () { const { collectionLoader, onErrorLoading } = setup({ - fetch: url => Promise.reject(new Error('???')), + fetch: (url) => Promise.reject(new Error('???')), }) collectionLoader.load('/src/app/test-fixtures/example-music-server') yield waitUntil(() => assert(onErrorLoading.called)) diff --git a/bemuse/src/app/interactors/findMatchingSong.js b/bemuse/src/app/interactors/findMatchingSong.js index de3591ef5..d86ff281d 100644 --- a/bemuse/src/app/interactors/findMatchingSong.js +++ b/bemuse/src/app/interactors/findMatchingSong.js @@ -10,12 +10,8 @@ function findMatchingSong({ songs, title, getTitle }) { function titleFullyMatches(haystack, needle) { return ( - String(haystack) - .toLowerCase() - .trim() === - String(needle) - .toLowerCase() - .trim() + String(haystack).toLowerCase().trim() === + String(needle).toLowerCase().trim() ) } diff --git a/bemuse/src/app/interactors/findMatchingSong.spec.js b/bemuse/src/app/interactors/findMatchingSong.spec.js index eae45861d..16238a65d 100644 --- a/bemuse/src/app/interactors/findMatchingSong.spec.js +++ b/bemuse/src/app/interactors/findMatchingSong.spec.js @@ -2,7 +2,7 @@ import assert from 'power-assert' import findMatchingSong from './findMatchingSong' -describe('selecting a song by title', function() { +describe('selecting a song by title', function () { // Using &song=... URL parameter, we can specify what song to be selected // at the beginning… const songs = [ @@ -12,7 +12,7 @@ describe('selecting a song by title', function() { 'Piece of Mine', 'Goliath', ] - const getTitle = song => song + const getTitle = (song) => song it('finds a matching song', () => { assert( diff --git a/bemuse/src/app/interactors/getLR2Score.spec.js b/bemuse/src/app/interactors/getLR2Score.spec.js index ae164b662..66f2da2fe 100644 --- a/bemuse/src/app/interactors/getLR2Score.spec.js +++ b/bemuse/src/app/interactors/getLR2Score.spec.js @@ -2,7 +2,7 @@ import assert from 'power-assert' import getLR2Score from './getLR2Score' -describe('Calculating LR2 score', function() { +describe('Calculating LR2 score', function () { const LR2_NORMAL_TIMEGATE = [18, 40] it('perfect great = 2 points', () => { assert(getLR2Score([0.001], LR2_NORMAL_TIMEGATE) === 2) diff --git a/bemuse/src/app/interactors/getNonMissedDeltas.js b/bemuse/src/app/interactors/getNonMissedDeltas.js index 342ee5b4e..869ec823e 100644 --- a/bemuse/src/app/interactors/getNonMissedDeltas.js +++ b/bemuse/src/app/interactors/getNonMissedDeltas.js @@ -4,7 +4,7 @@ import { timegate } from 'bemuse/game/judgments' // given an array of deltas, // we want to get filter it to contain only data for non-missed notes. export function getNonMissedDeltas(deltas) { - return deltas.filter(delta => Math.abs(delta) < timegate(4)) + return deltas.filter((delta) => Math.abs(delta) < timegate(4)) } export default getNonMissedDeltas diff --git a/bemuse/src/app/interactors/performSideEffects.js b/bemuse/src/app/interactors/performSideEffects.js index fbb1d7779..e4b3ece60 100644 --- a/bemuse/src/app/interactors/performSideEffects.js +++ b/bemuse/src/app/interactors/performSideEffects.js @@ -1,5 +1,5 @@ export function performSideEffects(sideEffect川) { - const subscription = sideEffect川.subscribe(f => f()) + const subscription = sideEffect川.subscribe((f) => f()) return { dispose: () => subscription.unsubscribe(), } diff --git a/bemuse/src/app/io/CustomSongsIO.js b/bemuse/src/app/io/CustomSongsIO.js index 7974780b8..0c538bd85 100644 --- a/bemuse/src/app/io/CustomSongsIO.js +++ b/bemuse/src/app/io/CustomSongsIO.js @@ -19,7 +19,7 @@ export function handleCustomSongFolderDrop(event) { export function handleCustomSongURLLoad(url) { return createIO(async ({ store, customSongLoader }) => { const resources = new CustomSongResources({ - getFiles: async log => [await downloadFileEntryFromURL(url, log)], + getFiles: async (log) => [await downloadFileEntryFromURL(url, log)], }) const initialLog = ['Loading from ' + url] return loadCustomSong(resources, initialLog, { store, customSongLoader }) diff --git a/bemuse/src/app/io/MusicSelectionIO.js b/bemuse/src/app/io/MusicSelectionIO.js index 08369b41e..772588c19 100644 --- a/bemuse/src/app/io/MusicSelectionIO.js +++ b/bemuse/src/app/io/MusicSelectionIO.js @@ -33,10 +33,10 @@ export function launchGame(server, song, chart) { song, chart, options: store.getState().options, - saveSpeed: speed => { + saveSpeed: (speed) => { run(OptionsIO.updateOptions(Options.changeSpeed(speed))) }, - saveLeadTime: leadTime => { + saveLeadTime: (leadTime) => { run(OptionsIO.updateOptions(Options.changeLeadTime(leadTime))) }, onRagequitted: () => { diff --git a/bemuse/src/app/io/ioContext.js b/bemuse/src/app/io/ioContext.js index f44a858b4..1788316c4 100644 --- a/bemuse/src/app/io/ioContext.js +++ b/bemuse/src/app/io/ioContext.js @@ -13,7 +13,7 @@ import { loadSongFromResources } from '../../custom-song-loader' // Configure a collection loader, which loads the Bemuse music collection. const collectionLoader = createCollectionLoader({ fetch: fetch, - onBeginLoading: url => + onBeginLoading: (url) => store.dispatch({ type: ReduxState.COLLECTION_LOADING_BEGAN, url: url, @@ -34,7 +34,7 @@ const collectionLoader = createCollectionLoader({ if (initiallySelectedSong) { const matchingSong = findMatchingSong({ songs: data.songs, - getTitle: song => song.title, + getTitle: (song) => song.title, title: initiallySelectedSong, }) if (matchingSong) { diff --git a/bemuse/src/app/redux/ReduxState.js b/bemuse/src/app/redux/ReduxState.js index a6ad26f82..a0c5c47d5 100644 --- a/bemuse/src/app/redux/ReduxState.js +++ b/bemuse/src/app/redux/ReduxState.js @@ -45,35 +45,36 @@ export const RAGEQUIT_DISMISSED = 'RAGEQUIT_DISMISSED' // Reducer export const reducer = combineReducers({ collections: createReducer(Collections.initialState, { - [COLLECTION_LOADING_BEGAN]: action => Collections.beginLoading(action.url), - [COLLECTION_LOADING_ERRORED]: action => + [COLLECTION_LOADING_BEGAN]: (action) => + Collections.beginLoading(action.url), + [COLLECTION_LOADING_ERRORED]: (action) => Collections.completeLoading(action.url, action.error), - [COLLECTION_LOADED]: action => + [COLLECTION_LOADED]: (action) => Collections.completeLoading(action.url, action.data), }), customSongLoadState: createReducer(LoadState.initCompletedWithValue(null), { - [CUSTOM_SONG_LOAD_STARTED]: action => LoadState.beginLoading, - [CUSTOM_SONG_LOADED]: action => LoadState.completeWithValue(), + [CUSTOM_SONG_LOAD_STARTED]: (action) => LoadState.beginLoading, + [CUSTOM_SONG_LOADED]: (action) => LoadState.completeWithValue(), }), customSongs: createReducer([], { - [CUSTOM_SONG_LOADED]: action => state => [action.song], - [CUSTOM_SONGS_LOADED]: action => state => action.songs, + [CUSTOM_SONG_LOADED]: (action) => (state) => [action.song], + [CUSTOM_SONGS_LOADED]: (action) => (state) => action.songs, }), currentCollection: createReducer('', { - [COLLECTION_LOADING_BEGAN]: action => state => + [COLLECTION_LOADING_BEGAN]: (action) => (state) => state === '' ? action.url : state, }), musicSearchText: createReducer(MusicSearchText.initialState, { - [MUSIC_SEARCH_TEXT_TYPED]: action => + [MUSIC_SEARCH_TEXT_TYPED]: (action) => MusicSearchText.handleTextType(action.text), - [MUSIC_SEARCH_DEBOUNCED]: action => MusicSearchText.handleDebounce, - [MUSIC_SEARCH_TEXT_INITIALIZED]: action => + [MUSIC_SEARCH_DEBOUNCED]: (action) => MusicSearchText.handleDebounce, + [MUSIC_SEARCH_TEXT_INITIALIZED]: (action) => MusicSearchText.setText(action.text), }), musicSelection: createReducer(MusicSelection.initialState, { - [CUSTOM_SONG_LOADED]: action => MusicSelection.selectSong(action.song.id), - [MUSIC_SONG_SELECTED]: action => MusicSelection.selectSong(action.songId), - [MUSIC_CHART_SELECTED]: action => + [CUSTOM_SONG_LOADED]: (action) => MusicSelection.selectSong(action.song.id), + [MUSIC_SONG_SELECTED]: (action) => MusicSelection.selectSong(action.songId), + [MUSIC_CHART_SELECTED]: (action) => MusicSelection.selectChart( action.songId, action.chartId, @@ -81,64 +82,63 @@ export const reducer = combineReducers({ ), }), options: createReducer(Options.initialState, { - [OPTIONS_LOADED_FROM_STORAGE]: action => state => + [OPTIONS_LOADED_FROM_STORAGE]: (action) => (state) => Options.initWithDataFromStorage(action.options), }), currentSongReadme: createReducer('Omachi kudasai…', { - [README_LOADING_STARTED]: action => state => 'Omachi kudasai…', - [README_LOADING_ERRORED]: action => state => + [README_LOADING_STARTED]: (action) => (state) => 'Omachi kudasai…', + [README_LOADING_ERRORED]: (action) => (state) => 'Cannot download ' + action.url, - [README_LOADED]: action => state => action.text, + [README_LOADED]: (action) => (state) => action.text, }), rageQuit: createReducer(false, { - [RAGEQUITTED]: action => state => true, - [RAGEQUIT_DISMISSED]: action => state => false, + [RAGEQUITTED]: (action) => (state) => true, + [RAGEQUIT_DISMISSED]: (action) => (state) => false, }), }) // Selectors -export const selectCurrentCollectionUrl = state => state.currentCollection +export const selectCurrentCollectionUrl = (state) => state.currentCollection export const selectCurrentCollection = createSelector( - state => state.collections, + (state) => state.collections, selectCurrentCollectionUrl, (collections, currentCollection) => Collections.getCollectionByUrl(currentCollection)(collections) ) -export const selectIsCurrentCollectionLoading = state => +export const selectIsCurrentCollectionLoading = (state) => LoadState.isLoading(selectCurrentCollection(state)) -export const selectCurrentCorrectionLoadError = state => +export const selectCurrentCorrectionLoadError = (state) => LoadState.error(selectCurrentCollection(state)) -export const selectRawCurrentCollectionValue = state => +export const selectRawCurrentCollectionValue = (state) => LoadState.value(selectCurrentCollection(state)) export const selectCurrentCollectionValue = createSelector( selectRawCurrentCollectionValue, - collection => collection && preprocessCollection(collection) + (collection) => collection && preprocessCollection(collection) ) -export const selectSearchInputText = state => +export const selectSearchInputText = (state) => MusicSearchText.inputText(state.musicSearchText) -export const selectSearchText = state => +export const selectSearchText = (state) => MusicSearchText.searchText(state.musicSearchText) export const { selectGroups, selectSongs } = (() => { const selectSongListFromCurrentCollection = createSelector( selectCurrentCollectionValue, - collectionData => (collectionData && collectionData.songs) || [] + (collectionData) => (collectionData && collectionData.songs) || [] ) const selectSongList = createSelector( selectSongListFromCurrentCollection, - state => state.customSongs, + (state) => state.customSongs, (songList, customSongs) => [...customSongs, ...songList] ) - const selectSortedSongList = createSelector( - selectSongList, - songList => sortSongs(songList) + const selectSortedSongList = createSelector(selectSongList, (songList) => + sortSongs(songList) ) const selectFilteredSongList = createSelector( selectSortedSongList, @@ -149,13 +149,8 @@ export const { selectGroups, selectSongs } = (() => { selectFilteredSongList, groupSongsIntoCategories ) - const selectSongs = createSelector( - selectGroups, - groups => - _(groups) - .map('songs') - .flatten() - .value() + const selectSongs = createSelector(selectGroups, (groups) => + _(groups).map('songs').flatten().value() ) return { selectGroups, selectSongs } })() @@ -165,7 +160,7 @@ export const { selectChartsForSelectedSong, selectSelectedChart, } = (() => { - const selectMusicSelection = state => state.musicSelection + const selectMusicSelection = (state) => state.musicSelection const selectSelectedSong = createSelector( selectMusicSelection, selectSongs, @@ -174,7 +169,7 @@ export const { ) const selectChartsForSelectedSong = createSelector( selectSelectedSong, - song => getPlayableCharts((song && song.charts) || []) + (song) => getPlayableCharts((song && song.charts) || []) ) const selectSelectedChart = createSelector( selectMusicSelection, @@ -189,8 +184,9 @@ export const { } })() -export const selectReadmeTextForSelectedSong = state => state.currentSongReadme +export const selectReadmeTextForSelectedSong = (state) => + state.currentSongReadme -export const selectPlayMode = store => Options.playMode(store.options) +export const selectPlayMode = (store) => Options.playMode(store.options) -export const selectRageQuittedFlag = store => store.rageQuit +export const selectRageQuittedFlag = (store) => store.rageQuit diff --git a/bemuse/src/app/redux/ReduxState.spec.js b/bemuse/src/app/redux/ReduxState.spec.js index fb0311397..30423c2de 100644 --- a/bemuse/src/app/redux/ReduxState.spec.js +++ b/bemuse/src/app/redux/ReduxState.spec.js @@ -3,8 +3,8 @@ import { given, shouldEqual, withReducer } from 'circumstance' const { dispatch, initialState } = withReducer(ReduxState.reducer) -describe('ReduxState', function() { - describe('integration test', function() { +describe('ReduxState', function () { + describe('integration test', function () { const givenLoadedCollection = given(initialState) .and( dispatch({ @@ -88,12 +88,12 @@ describe('ReduxState', function() { givenLoadedCollection .then( ReduxState.selectSelectedSong, - song => song.title, + (song) => song.title, shouldEqual('Anhedonia') ) .and( ReduxState.selectSelectedChart, - chart => chart.file, + (chart) => chart.file, shouldEqual('00_anhedonia_7b.bms') )) }) diff --git a/bemuse/src/app/redux/configureStore.js b/bemuse/src/app/redux/configureStore.js index 2c47c2754..c0eb38cfc 100644 --- a/bemuse/src/app/redux/configureStore.js +++ b/bemuse/src/app/redux/configureStore.js @@ -4,7 +4,7 @@ import { reducer } from './ReduxState' export default function configureStore(initialState) { const devTools = window.devToolsExtension ? window.devToolsExtension() - : f => f + : (f) => f const store = createStore(reducer, initialState, devTools) if (module.hot) { module.hot.accept('./ReduxState', () => { diff --git "a/bemuse/src/app/redux/reduxState\345\267\235.js" "b/bemuse/src/app/redux/reduxState\345\267\235.js" index 7f4d9f8fa..bc164bf89 100644 --- "a/bemuse/src/app/redux/reduxState\345\267\235.js" +++ "b/bemuse/src/app/redux/reduxState\345\267\235.js" @@ -1,7 +1,7 @@ import store from './instance' import Bacon from 'baconjs' -export default Bacon.fromBinder(sink => { +export default Bacon.fromBinder((sink) => { store.subscribe(() => sink({})) }) .toProperty({}) diff --git a/bemuse/src/app/service-worker.js b/bemuse/src/app/service-worker.js index 28ece896b..e37261c62 100644 --- a/bemuse/src/app/service-worker.js +++ b/bemuse/src/app/service-worker.js @@ -19,21 +19,21 @@ var RES_CACHE_KEY = 'site-v' + version var SKIN_CACHE_KEY = 'skin-v' + version var SONG_CACHE_KEY = 'songs' -self.addEventListener('install', function(event) { +self.addEventListener('install', function (event) { event.waitUntil( caches .open(SITE_CACHE_KEY) - .then(cache => cache.addAll(['/'])) + .then((cache) => cache.addAll(['/'])) .then(() => self.skipWaiting()) ) }) -self.addEventListener('activate', function() { +self.addEventListener('activate', function () { log('Service worker activated! Claiming clients now!') return self.clients.claim() }) -self.addEventListener('fetch', function(event) { +self.addEventListener('fetch', function (event) { if (event.request.headers.get('range')) { // https://bugs.chromium.org/p/chromium/issues/detail?id=575357 log('Bailing out for ranged request.', event.request.url) @@ -77,11 +77,11 @@ self.addEventListener('fetch', function(event) { function cacheForever(event, cacheName) { event.respondWith( - caches.open(cacheName).then(function(cache) { - return cache.match(event.request).then(function(cached) { + caches.open(cacheName).then(function (cache) { + return cache.match(event.request).then(function (cached) { return ( cached || - fetch(event.request).then(function(response) { + fetch(event.request).then(function (response) { log('Cache forever:', event.request.url) cache.put(event.request, response.clone()) return response @@ -94,9 +94,9 @@ function cacheForever(event, cacheName) { function fetchThenCache(event, cacheName) { event.respondWith( - caches.open(cacheName).then(function(cache) { + caches.open(cacheName).then(function (cache) { return fetch(event.request) - .then(function(response) { + .then(function (response) { if (response && response.ok) { log('Fetch OK:', event.request.url) cache.put(event.request, response.clone()) @@ -105,7 +105,7 @@ function fetchThenCache(event, cacheName) { return cache.match(event.request) } }) - .catch(function() { + .catch(function () { return cache.match(event.request) }) }) @@ -114,9 +114,9 @@ function fetchThenCache(event, cacheName) { function staleWhileRevalidate(event, cacheName) { event.respondWith( - caches.open(cacheName).then(function(cache) { - return cache.match(event.request).then(function(cached) { - var promise = fetch(event.request).then(function(response) { + caches.open(cacheName).then(function (cache) { + return cache.match(event.request).then(function (cached) { + var promise = fetch(event.request).then(function (response) { if (response && response.ok) { log('Updated:', event.request.url) cache.put(event.request, response.clone()) diff --git a/bemuse/src/app/ui/AboutScene.jsx b/bemuse/src/app/ui/AboutScene.jsx index d1fb5e0b3..ed44f58b4 100644 --- a/bemuse/src/app/ui/AboutScene.jsx +++ b/bemuse/src/app/ui/AboutScene.jsx @@ -14,9 +14,9 @@ class AboutScene extends React.Component { componentDidMount() { fetch('/music/artists.json') - .then(res => res.json()) - .then(a => this.setState({ artists: a })) - .catch(err => console.error(err)) + .then((res) => res.json()) + .then((a) => this.setState({ artists: a })) + .catch((err) => console.error(err)) } render() { diff --git a/bemuse/src/app/ui/ChangelogPanel.jsx b/bemuse/src/app/ui/ChangelogPanel.jsx index d460d6251..2a381d93f 100644 --- a/bemuse/src/app/ui/ChangelogPanel.jsx +++ b/bemuse/src/app/ui/ChangelogPanel.jsx @@ -11,10 +11,11 @@ class ChangelogPanel extends React.Component { componentDidMount() { const promise = import('!!raw-loader!../../../../CHANGELOG.md').then( - m => m.default + (m) => m.default ) promise.then( - changelog => this.setState({ data: { status: 'completed', changelog } }), + (changelog) => + this.setState({ data: { status: 'completed', changelog } }), () => this.setState({ data: { status: 'error' } }) ) } diff --git a/bemuse/src/app/ui/CustomBMS.jsx b/bemuse/src/app/ui/CustomBMS.jsx index 85382d872..47d067f2e 100644 --- a/bemuse/src/app/ui/CustomBMS.jsx +++ b/bemuse/src/app/ui/CustomBMS.jsx @@ -16,15 +16,16 @@ import { import { useCustomSongLoaderLog } from '../CustomSongs' const enhance = compose( - BaseComponent => + (BaseComponent) => function LogProvider(props) { const log = useCustomSongLoaderLog() return }, connectIO({ - onFileDrop: () => event => CustomSongsIO.handleCustomSongFolderDrop(event), - onPaste: () => e => CustomSongsIO.handleClipboardPaste(e), - loadFromURL: () => url => CustomSongsIO.handleCustomSongURLLoad(url), + onFileDrop: () => (event) => + CustomSongsIO.handleCustomSongFolderDrop(event), + onPaste: () => (e) => CustomSongsIO.handleClipboardPaste(e), + loadFromURL: () => (url) => CustomSongsIO.handleCustomSongURLLoad(url), }) ) @@ -45,7 +46,7 @@ class CustomBMS extends React.Component { componentDidMount() { window.addEventListener('paste', this.handlePaste) if (hasPendingArchiveToLoad()) { - this.props.loadFromURL(consumePendingArchiveURL()).then(song => { + this.props.loadFromURL(consumePendingArchiveURL()).then((song) => { if (this.props.onSongLoaded) this.props.onSongLoaded(song) }) } @@ -103,30 +104,30 @@ class CustomBMS extends React.Component { ) } - handleDragEnter = e => { + handleDragEnter = (e) => { e.preventDefault() } - handleDragOver = e => { + handleDragOver = (e) => { this.setState({ hover: true }) e.preventDefault() } - handleDragLeave = e => { + handleDragLeave = (e) => { this.setState({ hover: false }) e.preventDefault() } - handleDrop = e => { + handleDrop = (e) => { this.setState({ hover: false }) Analytics.send('CustomBMS', 'drop') e.preventDefault() - this.props.onFileDrop(e.nativeEvent).then(song => { + this.props.onFileDrop(e.nativeEvent).then((song) => { if (this.props.onSongLoaded) this.props.onSongLoaded(song) }) } - handlePaste = async e => { + handlePaste = async (e) => { const song = await this.props.onPaste(e) if (song) { if (this.props.onSongLoaded) this.props.onSongLoaded(song) diff --git a/bemuse/src/app/ui/FirstTimeTip.jsx b/bemuse/src/app/ui/FirstTimeTip.jsx index 5a2f8115d..1b909dd59 100644 --- a/bemuse/src/app/ui/FirstTimeTip.jsx +++ b/bemuse/src/app/ui/FirstTimeTip.jsx @@ -10,8 +10,10 @@ import connectIO from '../../impure-react/connectIO' export const FirstTimeTip = compose( connectIO({ - onClick: ({ featureKey }) => () => - OptionsIO.updateOptions(Options.acknowledge(featureKey)), + onClick: + ({ featureKey }) => + () => + OptionsIO.updateOptions(Options.acknowledge(featureKey)), }), connect((state, { featureKey }) => ({ tipVisible: !Options.hasAcknowledged(featureKey)(state.options), diff --git a/bemuse/src/app/ui/GenericErrorScene.tsx b/bemuse/src/app/ui/GenericErrorScene.tsx index 90a6f4193..281a35824 100644 --- a/bemuse/src/app/ui/GenericErrorScene.tsx +++ b/bemuse/src/app/ui/GenericErrorScene.tsx @@ -14,23 +14,20 @@ export default function GenericErrorScene(props: { onContinue: () => void }) { const { preamble, error, onContinue } = props - const details = React.useMemo( - () => { - return [ - preamble, - '', - '[Error]', - String(error), - '', - '[User agent]', - navigator.userAgent, - '', - '[Stack trace]', - String((error && error.stack) || error), - ].join('\n') - }, - [error, preamble] - ) + const details = React.useMemo(() => { + return [ + preamble, + '', + '[Error]', + String(error), + '', + '[User agent]', + navigator.userAgent, + '', + '[Stack trace]', + String((error && error.stack) || error), + ].join('\n') + }, [error, preamble]) return ( diff --git a/bemuse/src/app/ui/ModeSelectScene.scss b/bemuse/src/app/ui/ModeSelectScene.scss index 2f7d23af2..8304af4d9 100644 --- a/bemuse/src/app/ui/ModeSelectScene.scss +++ b/bemuse/src/app/ui/ModeSelectScene.scss @@ -1,4 +1,4 @@ -@use "sass:math"; +@use 'sass:math'; @import '~bemuse/ui/common'; .ModeSelectScene { diff --git a/bemuse/src/app/ui/MusicInfoTabInformation.jsx b/bemuse/src/app/ui/MusicInfoTabInformation.jsx index 240519323..93b739610 100644 --- a/bemuse/src/app/ui/MusicInfoTabInformation.jsx +++ b/bemuse/src/app/ui/MusicInfoTabInformation.jsx @@ -13,11 +13,11 @@ import Markdown from 'bemuse/ui/Markdown' import YouTube from 'bemuse/ui/YouTube' const enhance = compose( - connect(state => ({ + connect((state) => ({ readme: ReduxState.selectReadmeTextForSelectedSong(state), })), connectIO({ - onRequestReadme: () => song => ReadmeIO.requestReadme(song), + onRequestReadme: () => (song) => ReadmeIO.requestReadme(song), }) ) diff --git a/bemuse/src/app/ui/MusicList.jsx b/bemuse/src/app/ui/MusicList.jsx index b3649ea8d..6715f4e25 100644 --- a/bemuse/src/app/ui/MusicList.jsx +++ b/bemuse/src/app/ui/MusicList.jsx @@ -66,7 +66,7 @@ class MusicList extends React.PureComponent {
  • {title}
  • , - songs.map(song => ( + songs.map((song) => ( chart === selectedChart) + return _.find(song.charts, (chart) => chart === selectedChart) } } diff --git a/bemuse/src/app/ui/MusicListItemChart.jsx b/bemuse/src/app/ui/MusicListItemChart.jsx index ee6f2df40..42e86a1ad 100644 --- a/bemuse/src/app/ui/MusicListItemChart.jsx +++ b/bemuse/src/app/ui/MusicListItemChart.jsx @@ -52,7 +52,7 @@ export default class MusicListItemChart extends React.Component { ) } - handleClick = e => { + handleClick = (e) => { if (this.props.onClick) { this.props.onClick(this.props.chart, e) } diff --git a/bemuse/src/app/ui/MusicListItemChart.scss b/bemuse/src/app/ui/MusicListItemChart.scss index 1853d93fe..0e9cd4fae 100644 --- a/bemuse/src/app/ui/MusicListItemChart.scss +++ b/bemuse/src/app/ui/MusicListItemChart.scss @@ -1,4 +1,4 @@ -@use "sass:math"; +@use 'sass:math'; @import '~bemuse/ui/common'; .MusicListItemChart { diff --git a/bemuse/src/app/ui/MusicListItemChartContainer.jsx b/bemuse/src/app/ui/MusicListItemChartContainer.jsx index 156329c46..bacb0b5cf 100644 --- a/bemuse/src/app/ui/MusicListItemChartContainer.jsx +++ b/bemuse/src/app/ui/MusicListItemChartContainer.jsx @@ -7,7 +7,7 @@ import compose from 'recompose/compose' export default compose( withPersonalRecord, - withPropsOnChange(['record'], props => { + withPropsOnChange(['record'], (props) => { const record = props.record const played = !!record let grade = played ? getGrade(record) : null diff --git a/bemuse/src/app/ui/MusicSelectScene.jsx b/bemuse/src/app/ui/MusicSelectScene.jsx index 005751bef..ccfa655d6 100644 --- a/bemuse/src/app/ui/MusicSelectScene.jsx +++ b/bemuse/src/app/ui/MusicSelectScene.jsx @@ -40,12 +40,12 @@ import Toolbar from './Toolbar' const selectMusicSelectState = (() => { const selectLegacyServerObjectForCurrentCollection = createSelector( ReduxState.selectCurrentCollectionUrl, - url => ({ url }) + (url) => ({ url }) ) const selectIsCurrentCollectionUnofficial = createSelector( ReduxState.selectCurrentCollectionUrl, - url => url !== OFFICIAL_SERVER_URL + (url) => url !== OFFICIAL_SERVER_URL ) return createStructuredSelector({ @@ -66,7 +66,7 @@ const selectMusicSelectState = (() => { const enhance = compose( hot(module), connectToLegacyStore({ user: online && online.user川 }), - connect(state => ({ + connect((state) => ({ musicSelect: selectMusicSelectState(state), collectionUrl: ReduxState.selectCurrentCollectionUrl(state), musicPreviewEnabled: Options.isPreviewEnabled(state.options), @@ -74,14 +74,17 @@ const enhance = compose( connectIO({ onSelectChart: () => (song, chart) => MusicSelectionIO.selectChart(song, chart), - onSelectSong: () => song => MusicSelectionIO.selectSong(song), - onFilterTextChange: () => text => MusicSearchIO.handleSearchTextType(text), - onLaunchGame: ({ musicSelect }) => () => - MusicSelectionIO.launchGame( - musicSelect.server, - musicSelect.song, - musicSelect.chart - ), + onSelectSong: () => (song) => MusicSelectionIO.selectSong(song), + onFilterTextChange: () => (text) => + MusicSearchIO.handleSearchTextType(text), + onLaunchGame: + ({ musicSelect }) => + () => + MusicSelectionIO.launchGame( + musicSelect.server, + musicSelect.song, + musicSelect.chart + ), }) ) @@ -292,7 +295,7 @@ class MusicSelectScene extends React.PureComponent { handleMusicListTouch = () => { this.setState({ inSong: false }) } - handleChartClick = chart => { + handleChartClick = (chart) => { if (this.props.musicSelect.chart.md5 === chart.md5) { Analytics.send('MusicSelectScene', 'launch game') MusicPreviewer.go() @@ -302,7 +305,7 @@ class MusicSelectScene extends React.PureComponent { this.props.onSelectChart(this.props.musicSelect.song, chart) } } - handleFilter = e => { + handleFilter = (e) => { this.props.onFilterTextChange(e.target.value) } handleOptionsOpen = () => { @@ -319,7 +322,7 @@ class MusicSelectScene extends React.PureComponent { handleCustomBMSClose = () => { this.setState({ customBMSVisible: false }) } - handleCustomSong = song => { + handleCustomSong = (song) => { this.setState({ customBMSVisible: false }) } handleUnofficialClick = () => { diff --git a/bemuse/src/app/ui/OptionsAdvanced.jsx b/bemuse/src/app/ui/OptionsAdvanced.jsx index 4885c6cf0..15c2fc981 100644 --- a/bemuse/src/app/ui/OptionsAdvanced.jsx +++ b/bemuse/src/app/ui/OptionsAdvanced.jsx @@ -13,11 +13,11 @@ import OptionsButton from './OptionsButton' import OptionsInputField from './OptionsInputField' const enhance = compose( - connect(state => ({ + connect((state) => ({ options: state.options, })), connectIO({ - onUpdateOptions: () => updater => OptionsIO.updateOptions(updater), + onUpdateOptions: () => (updater) => OptionsIO.updateOptions(updater), }), pure ) @@ -59,7 +59,7 @@ class OptionsAdvanced extends React.Component { ) } - handleAudioInputLatencyChange = value => { + handleAudioInputLatencyChange = (value) => { this.props.onUpdateOptions(Options.changeAudioInputLatency(value)) } handleCalibrateButtonClick = () => { @@ -83,7 +83,7 @@ class LatencyMessageListener extends React.Component { componentWillUnmount() { window.removeEventListener('message', this.handleMessage) } - handleMessage = event => { + handleMessage = (event) => { if (event.data && typeof event.data.latency === 'number') { this.props.onLatency(event.data.latency) } diff --git a/bemuse/src/app/ui/OptionsInput.jsx b/bemuse/src/app/ui/OptionsInput.jsx index 3cafaf7ea..9af2ee469 100644 --- a/bemuse/src/app/ui/OptionsInput.jsx +++ b/bemuse/src/app/ui/OptionsInput.jsx @@ -19,17 +19,17 @@ import OptionsInputField from './OptionsInputField' import OptionsButton from './OptionsButton' const selectKeyboardMapping = createSelector( - state => state.options, - options => Options.keyboardMapping(options) + (state) => state.options, + (options) => Options.keyboardMapping(options) ) const selectKeyboardMappingTexts = createSelector( selectKeyboardMapping, - mapping => _.mapValues(mapping, getName) + (mapping) => _.mapValues(mapping, getName) ) const enhance = compose( - connect(state => ({ + connect((state) => ({ scratch: Options.scratchPosition(state.options), texts: selectKeyboardMappingTexts(state), mode: Options.playMode(state.options), @@ -38,24 +38,32 @@ const enhance = compose( })), withState('editing', 'setEditing', null), connectIO({ - onSetKeyCode: ({ mode, editing }) => keyCode => - OptionsIO.updateOptions(Options.changeKeyMapping(mode, editing, keyCode)), - onUpdateOptions: () => updater => OptionsIO.updateOptions(updater), + onSetKeyCode: + ({ mode, editing }) => + (keyCode) => + OptionsIO.updateOptions( + Options.changeKeyMapping(mode, editing, keyCode) + ), + onUpdateOptions: () => (updater) => OptionsIO.updateOptions(updater), }), withHandlers({ - onEdit: ({ editing, setEditing }) => key => { - if (editing === key) { - setEditing(null) - } else { - setEditing(key) - } - }, - onKey: ({ editing, onSetKeyCode, setEditing, scratch }) => keyCode => { - if (editing) { - onSetKeyCode(keyCode) - setEditing(Options.nextKeyToEdit(editing, scratch)) - } - }, + onEdit: + ({ editing, setEditing }) => + (key) => { + if (editing === key) { + setEditing(null) + } else { + setEditing(key) + } + }, + onKey: + ({ editing, onSetKeyCode, setEditing, scratch }) => + (keyCode) => { + if (editing) { + onSetKeyCode(keyCode) + setEditing(Options.nextKeyToEdit(editing, scratch)) + } + }, }) ) @@ -132,8 +140,8 @@ class OptionsInput extends React.Component { parseInt(str, 10) - 1} - stringify={value => String(parseInt(value, 10) + 1)} + parse={(str) => parseInt(str, 10) - 1} + stringify={(value) => String(parseInt(value, 10) + 1)} validator={/^[0-9]+$/} value={this.props.sensitivity} onChange={this.handleSensitivityChange} @@ -149,7 +157,7 @@ class OptionsInput extends React.Component { ) } - handleEdit = key => { + handleEdit = (key) => { this.props.onEdit(key) } componentDidMount() { @@ -169,17 +177,17 @@ class OptionsInput extends React.Component { if (this._input) this._input.dispose() window.removeEventListener('keydown', this.handleKeyboardEvent, true) } - handleKey = key => { + handleKey = (key) => { if (this.props.editing) { this.props.onKey(key) } } - handleKeyboardEvent = e => { + handleKeyboardEvent = (e) => { if (this.props.editing) { e.preventDefault() } } - handleSensitivityChange = sensitivity => { + handleSensitivityChange = (sensitivity) => { if (sensitivity < 0) sensitivity = 0 else if (sensitivity >= 10) sensitivity = 9 this._input.setGamepadSensitivity(sensitivity) diff --git a/bemuse/src/app/ui/OptionsInputField.jsx b/bemuse/src/app/ui/OptionsInputField.jsx index df1e87817..a6896e7e6 100644 --- a/bemuse/src/app/ui/OptionsInputField.jsx +++ b/bemuse/src/app/ui/OptionsInputField.jsx @@ -13,8 +13,8 @@ class OptionsInputField extends React.PureComponent { value: PropTypes.any, } static defaultProps = { - stringify: x => `${x}`, - parse: x => x, + stringify: (x) => `${x}`, + parse: (x) => x, onChange: () => {}, } @@ -38,7 +38,7 @@ class OptionsInputField extends React.PureComponent { /> ) } - handleInputChange = e => { + handleInputChange = (e) => { let input = e.target let valid = this.props.validator.test(input.value) input.classList[valid ? 'remove' : 'add']('is-invalid') diff --git a/bemuse/src/app/ui/OptionsInputKeys.scss b/bemuse/src/app/ui/OptionsInputKeys.scss index 66221bc52..709a15e1f 100644 --- a/bemuse/src/app/ui/OptionsInputKeys.scss +++ b/bemuse/src/app/ui/OptionsInputKeys.scss @@ -1,4 +1,4 @@ -@use "sass:math"; +@use 'sass:math'; @import '~bemuse/ui/common'; .OptionsInputKeys { diff --git a/bemuse/src/app/ui/OptionsPlayer.jsx b/bemuse/src/app/ui/OptionsPlayer.jsx index 6a63c4a84..f180ab159 100644 --- a/bemuse/src/app/ui/OptionsPlayer.jsx +++ b/bemuse/src/app/ui/OptionsPlayer.jsx @@ -15,11 +15,11 @@ import OptionsSpeed from './OptionsSpeed' import connectIO from '../../impure-react/connectIO' const SettingRow = compose( - connect(state => ({ options: state.options })), + connect((state) => ({ options: state.options })), connectIO({ - onUpdateOptions: () => updater => OptionsIO.updateOptions(updater), + onUpdateOptions: () => (updater) => OptionsIO.updateOptions(updater), }) -)(props => { +)((props) => { const { label, isVisible, help, renderControl } = props // user-supplied const { options, onUpdateOptions } = props // from higher-order component const visible = isVisible ? isVisible(options) : true @@ -41,11 +41,11 @@ class OptionsPlayer extends React.Component {
    !Options.isAutoVelocityEnabled(options)} + isVisible={(options) => !Options.isAutoVelocityEnabled(options)} renderControl={(options, onUpdateOptions) => ( onUpdateOptions(Options.changeSpeed(speed))} + onChange={(speed) => onUpdateOptions(Options.changeSpeed(speed))} /> )} help={ @@ -59,14 +59,14 @@ class OptionsPlayer extends React.Component { Options.isAutoVelocityEnabled(options)} + isVisible={(options) => Options.isAutoVelocityEnabled(options)} renderControl={(options, onUpdateOptions) => ( parseInt(str, 10)} - stringify={value => String(value) + 'ms'} + parse={(str) => parseInt(str, 10)} + stringify={(value) => String(value) + 'ms'} validator={/^\d+(ms)?$/} value={Options.leadTime(options)} - onChange={leadTime => + onChange={(leadTime) => onUpdateOptions(Options.changeLeadTime(leadTime)) } style={{ width: '5em' }} @@ -92,7 +92,7 @@ class OptionsPlayer extends React.Component { { value: 'off', label: 'Disabled' }, ]} value={Options.scratchPosition(options)} - onSelect={position => + onSelect={(position) => onUpdateOptions(Options.changeScratchPosition(position)) } /> @@ -110,7 +110,7 @@ class OptionsPlayer extends React.Component { { value: 'right', label: 'Right' }, { value: '3d', label: '3D [Beta]' }, ]} - onSelect={value => + onSelect={(value) => onUpdateOptions(Options.changePanelPlacement(value)) } value={Options.panelPlacement(options)} @@ -122,11 +122,11 @@ class OptionsPlayer extends React.Component { label='Cover' renderControl={(options, onUpdateOptions) => ( parseInt(str, 10) / 100} - stringify={value => Math.round(value * 100 || 0) + '%'} + parse={(str) => parseInt(str, 10) / 100} + stringify={(value) => Math.round(value * 100 || 0) + '%'} validator={/^-?\d+(%)?$/} value={Options.laneCover(options)} - onChange={laneCover => + onChange={(laneCover) => onUpdateOptions(Options.changeLaneCover(laneCover)) } style={{ width: '5em' }} diff --git a/bemuse/src/app/ui/OptionsPlayerGraphics.jsx b/bemuse/src/app/ui/OptionsPlayerGraphics.jsx index e140de68d..2a3593f79 100644 --- a/bemuse/src/app/ui/OptionsPlayerGraphics.jsx +++ b/bemuse/src/app/ui/OptionsPlayerGraphics.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types' import React from 'react' import c from 'classnames' -const PANEL_PATH = (function() { +const PANEL_PATH = (function () { const x = 48 const w = 14 const y = 20 @@ -22,7 +22,7 @@ const PANEL_PATH = (function() { L${x4} ${y4} L${x4} ${y3} L${x3} ${y2} L${x3} ${y1}` })() -const PANEL_3D_PATH = (function() { +const PANEL_3D_PATH = (function () { const down = [] const up = [] for (let i = 0; i <= 11; i++) { @@ -64,7 +64,7 @@ export default class OptionsPlayerGraphics extends React.Component { return ( - {[0, 1, 2, 3, 4, 5, 6].map(i => ( + {[0, 1, 2, 3, 4, 5, 6].map((i) => ( { + handleSpeedInputChange = (nextSpeed) => { this.props.onChange(this.stringifySpeed(nextSpeed)) } render() { diff --git a/bemuse/src/app/ui/RageQuitPopup.jsx b/bemuse/src/app/ui/RageQuitPopup.jsx index 52dd305e7..0a8a392a2 100644 --- a/bemuse/src/app/ui/RageQuitPopup.jsx +++ b/bemuse/src/app/ui/RageQuitPopup.jsx @@ -9,10 +9,10 @@ import * as ReduxState from '../redux/ReduxState' import OptionsButton from './OptionsButton' const enhance = connect( - state => ({ + (state) => ({ visible: ReduxState.selectRageQuittedFlag(state), }), - dispatch => ({ + (dispatch) => ({ onClose: () => dispatch({ type: ReduxState.RAGEQUIT_DISMISSED }), }) ) diff --git a/bemuse/src/app/ui/RankingContainer.jsx b/bemuse/src/app/ui/RankingContainer.jsx index edb598f90..8f6c48118 100644 --- a/bemuse/src/app/ui/RankingContainer.jsx +++ b/bemuse/src/app/ui/RankingContainer.jsx @@ -67,7 +67,7 @@ export default class RankingContainer extends React.Component { if (this.unsubscribe) this.unsubscribe() } - onStoreTrigger = state => { + onStoreTrigger = (state) => { if (this.mounted) this.setState(state) } diff --git a/bemuse/src/app/ui/ResultDeltasView.jsx b/bemuse/src/app/ui/ResultDeltasView.jsx index ac879404c..f4e01bbb3 100644 --- a/bemuse/src/app/ui/ResultDeltasView.jsx +++ b/bemuse/src/app/ui/ResultDeltasView.jsx @@ -11,12 +11,12 @@ import { timegate } from 'bemuse/game/judgments' import getNonMissedDeltas from '../interactors/getNonMissedDeltas' -const ms = delta => `${(delta * 1000).toFixed(1)} ms` +const ms = (delta) => `${(delta * 1000).toFixed(1)} ms` -const group = deltas => +const group = (deltas) => _(deltas) - .map(delta => Math.floor(delta * 100)) - .countBy(bucket => bucket) + .map((delta) => Math.floor(delta * 100)) + .countBy((bucket) => bucket) .value() export default class ResultDeltasView extends React.Component { @@ -27,18 +27,16 @@ export default class ResultDeltasView extends React.Component { render() { const deltas = this.props.deltas const nonMissDeltas = getNonMissedDeltas(deltas) - const offDeltas = deltas.filter(delta => timegate(1) <= Math.abs(delta)) - const earlyCount = offDeltas.filter(delta => delta < 0).length - const lateCount = offDeltas.filter(delta => delta > 0).length + const offDeltas = deltas.filter((delta) => timegate(1) <= Math.abs(delta)) + const earlyCount = offDeltas.filter((delta) => delta < 0).length + const lateCount = offDeltas.filter((delta) => delta > 0).length const groups = group(deltas) - const stats = _.range(-20, 20).map(bucket => ({ + const stats = _.range(-20, 20).map((bucket) => ({ bucket, count: groups[bucket] || 0, })) - const max = _(stats) - .map('count') - .max() - const height = value => Math.ceil((value / Math.max(max, 1)) * 128) + const max = _(stats).map('count').max() + const height = (value) => Math.ceil((value / Math.max(max, 1)) * 128) return (
    diff --git a/bemuse/src/app/ui/ResultExpertInfo.jsx b/bemuse/src/app/ui/ResultExpertInfo.jsx index 2744448c8..62b1f0f9c 100644 --- a/bemuse/src/app/ui/ResultExpertInfo.jsx +++ b/bemuse/src/app/ui/ResultExpertInfo.jsx @@ -15,16 +15,15 @@ export default class ResultExpertInfo extends React.Component { } getStats = (() => { const selectNonMissedDeltas = createSelector( - props => props.deltas, - deltas => getNonMissedDeltas(deltas) + (props) => props.deltas, + (deltas) => getNonMissedDeltas(deltas) ) - const selectMean = createSelector( - selectNonMissedDeltas, - deltas => mean(deltas) + const selectMean = createSelector(selectNonMissedDeltas, (deltas) => + mean(deltas) ) const selectStandardDeviation = createSelector( selectNonMissedDeltas, - deltas => Math.sqrt(variance(deltas)) + (deltas) => Math.sqrt(variance(deltas)) ) const selectStats = createStructuredSelector({ mean: selectMean, diff --git a/bemuse/src/app/ui/ResultScene.jsx b/bemuse/src/app/ui/ResultScene.jsx index 7375c1ebe..0c23b7921 100644 --- a/bemuse/src/app/ui/ResultScene.jsx +++ b/bemuse/src/app/ui/ResultScene.jsx @@ -124,13 +124,13 @@ export default class ResultScene extends React.Component { encodeURIComponent(text) ) } - onTweet = e => { + onTweet = (e) => { e.preventDefault() e.stopPropagation() Analytics.send('ResultScene', 'tweet') window.open(this.getTweetLink(), 'intent', 'width=550,height=420') } - handleExit = e => { + handleExit = (e) => { this.props.onExit(e) Analytics.send('ResultScene', 'exit') } diff --git a/bemuse/src/app/ui/TitleScene.jsx b/bemuse/src/app/ui/TitleScene.jsx index 36d8b877f..d81e2d0cf 100644 --- a/bemuse/src/app/ui/TitleScene.jsx +++ b/bemuse/src/app/ui/TitleScene.jsx @@ -35,7 +35,7 @@ const enhance = compose( onMarkChangelogAsSeen: () => () => OptionsIO.updateOptions(Options.updateLastSeenVersion(version)), }), - connect(state => ({ + connect((state) => ({ hasSeenChangelog: Options.lastSeenVersion(state.options) === version, })) ) @@ -136,17 +136,12 @@ class TitleScene extends React.Component { ) } - openLink = e => { + openLink = (e) => { e.preventDefault() - window.open( - $(e.target) - .closest('a') - .get(0).href, - '_blank' - ) + window.open($(e.target).closest('a').get(0).href, '_blank') } - openTwitterLink = e => { + openTwitterLink = (e) => { this.openLink(e) if (this.props.onTwitterButtonClick) this.props.onTwitterButtonClick() } diff --git a/bemuse/src/app/ui/Toolbar.jsx b/bemuse/src/app/ui/Toolbar.jsx index b55dd20b3..cac5556e6 100644 --- a/bemuse/src/app/ui/Toolbar.jsx +++ b/bemuse/src/app/ui/Toolbar.jsx @@ -143,12 +143,7 @@ class MobileToolbar extends React.PureComponent { function openLink(e) { e.preventDefault() - window.open( - $(e.target) - .closest('a') - .get(0).href, - '_blank' - ) + window.open($(e.target).closest('a').get(0).href, '_blank') } export default Toolbar diff --git a/bemuse/src/app/ui/withPersonalRecord.jsx b/bemuse/src/app/ui/withPersonalRecord.jsx index 4c4074b90..35a48da8e 100644 --- a/bemuse/src/app/ui/withPersonalRecord.jsx +++ b/bemuse/src/app/ui/withPersonalRecord.jsx @@ -42,7 +42,7 @@ export function withPersonalRecord(Component) { user: online.user川, onlineRecords: online.records川, }), - connect(state => ({ + connect((state) => ({ playMode: ReduxState.selectPlayMode(state), })) ) diff --git a/bemuse/src/auto-synchro/index.js b/bemuse/src/auto-synchro/index.js index cf890f32a..8c9bbb306 100644 --- a/bemuse/src/auto-synchro/index.js +++ b/bemuse/src/auto-synchro/index.js @@ -46,7 +46,7 @@ export function main(bootContext) { } function getLatency(samples) { - let data = samples.map(d => d[1]) + let data = samples.map((d) => d[1]) data.sort((a, b) => a - b) let count = 0 let sum = 0 @@ -58,7 +58,7 @@ export function main(bootContext) { return Math.round((sum / count) * 1000) } - return Music.load().then(music => { + return Music.load().then((music) => { let bound = 56 let samples = [] state口.push({ loading: false }) @@ -79,12 +79,12 @@ export function main(bootContext) { } setTimeout(() => { state口.push({ listening: true }) - window.addEventListener('keydown', e => { + window.addEventListener('keydown', (e) => { if (e.which !== 32) return e.preventDefault() tap() }) - window.addEventListener('touchstart', e => { + window.addEventListener('touchstart', (e) => { if (e.touches.length !== 1) return e.preventDefault() tap() diff --git a/bemuse/src/auto-synchro/music/index.js b/bemuse/src/auto-synchro/music/index.js index 45b7fff74..ade4162c4 100644 --- a/bemuse/src/auto-synchro/music/index.js +++ b/bemuse/src/auto-synchro/music/index.js @@ -19,14 +19,14 @@ let ASSET_URLS = { export async function load() { let master = new SamplingMaster(context) - let sample = name => + let sample = (name) => download(ASSET_URLS[`${name}.ogg`]) .as('arraybuffer') - .then(buf => master.sample(buf)) + .then((buf) => master.sample(buf)) let samples = _.fromPairs( await Promise.all( - ['bgm', 'intro', 'kick', 'snare'].map(name => - sample(name).then(sampleObj => [name, sampleObj]) + ['bgm', 'intro', 'kick', 'snare'].map((name) => + sample(name).then((sampleObj) => [name, sampleObj]) ) ) ) @@ -94,7 +94,7 @@ function music(master, samples) { function beatSequencer(bpm, f) { let beat = -1 - return time => { + return (time) => { let nowBeat = Math.floor(((time + 0.1) * bpm) / 60) while (beat < nowBeat) { beat += 1 diff --git a/bemuse/src/auto-synchro/ui/ExperimentScene.jsx b/bemuse/src/auto-synchro/ui/ExperimentScene.jsx index 2c4a0d36a..a521249a4 100644 --- a/bemuse/src/auto-synchro/ui/ExperimentScene.jsx +++ b/bemuse/src/auto-synchro/ui/ExperimentScene.jsx @@ -53,7 +53,7 @@ export default class ExperimentScene extends React.Component { ) } - renderMessage = text => { + renderMessage = (text) => { return
    {text}
    } diff --git a/bemuse/src/boot/index.js b/bemuse/src/boot/index.js index 1905c3740..bb7bb02b2 100644 --- a/bemuse/src/boot/index.js +++ b/bemuse/src/boot/index.js @@ -15,7 +15,7 @@ import * as Boot from './ui/Boot' import * as ErrorDialog from './ui/ErrorDialog' import loadModule from './loader' -window.onerror = function(message, url, line, col, e) { +window.onerror = function (message, url, line, col, e) { ErrorDialog.show(message, e, url, line, col) } @@ -28,7 +28,7 @@ window.onerror = function(message, url, line, col, e) { let mode = query.mode || 'app' import(/* webpackChunkName: 'environment' */ './environment') - .then(_ => { + .then((_) => { if (loadModule[mode]) { // >> // The main script is then loaded and imported into the environment, @@ -42,12 +42,12 @@ import(/* webpackChunkName: 'environment' */ './environment') // Boot.setStatus(`Loading ${mode} bundle`) loadModule[mode]() - .then(loadedModule => { + .then((loadedModule) => { Boot.setStatus(`Initializing`) return loadedModule.main({ setStatus: Boot.setStatus }) }) .then(() => Boot.hide()) - .catch(err => { + .catch((err) => { ErrorDialog.show( `An error occurred while initializing "${mode}"`, err @@ -57,7 +57,7 @@ import(/* webpackChunkName: 'environment' */ './environment') ErrorDialog.show(`Invalid mode: ${mode}`) } }) - .catch(err => { + .catch((err) => { ErrorDialog.show( 'Failed to load environment bundle. Please refresh the page to try again.', err diff --git a/bemuse/src/boot/ui/ErrorDialog.js b/bemuse/src/boot/ui/ErrorDialog.js index 3b70e7382..866d4320e 100644 --- a/bemuse/src/boot/ui/ErrorDialog.js +++ b/bemuse/src/boot/ui/ErrorDialog.js @@ -10,7 +10,7 @@ function show(message, e, url, line, col) { if (close) { close.addEventListener( 'click', - function() { + function () { div.parentNode.removeChild(div) }, false diff --git a/bemuse/src/bootstrap/index.js b/bemuse/src/bootstrap/index.js index 046fb1afc..8154b45d6 100644 --- a/bemuse/src/bootstrap/index.js +++ b/bemuse/src/bootstrap/index.js @@ -28,6 +28,6 @@ global.Promise = Bluebird // // The Promise class is augmented with a ``log`` method that simply // logs the value of the promise. -Promise.prototype.log = function(...args) { - return this.tap(value => console.log(...args.concat([value]))) +Promise.prototype.log = function (...args) { + return this.tap((value) => console.log(...args.concat([value]))) } diff --git a/bemuse/src/coming-soon/demo/index.js b/bemuse/src/coming-soon/demo/index.js index bf38be09f..9b50d5764 100644 --- a/bemuse/src/coming-soon/demo/index.js +++ b/bemuse/src/coming-soon/demo/index.js @@ -9,9 +9,7 @@ import ctx from 'bemuse/audio-context' import template from './template.jade' export function main(element) { - $(element) - .text('Technical Demo!') - .on('click', handler) + $(element).text('Technical Demo!').on('click', handler) function handler() { ui() @@ -23,7 +21,7 @@ export function main(element) { function ui() { var el = $(template()).appendTo('body') el.find('.js-play').hide() - el.on('dragover', () => false).on('drop', e => { + el.on('dragover', () => false).on('drop', (e) => { e.preventDefault() let dndLoader = new DndResources(e.originalEvent) go(dndLoader, el) @@ -40,7 +38,7 @@ async function go(loader, element) { log('Loading file list') let list = await loader.fileList - let bmsFile = list.filter(f => f.match(/\.(?:bms|bme|bml|pms)$/i))[0] + let bmsFile = list.filter((f) => f.match(/\.(?:bms|bme|bml|pms)$/i))[0] log('Loading ' + bmsFile) let loadedFile = await loader.file(bmsFile) @@ -51,14 +49,12 @@ async function go(loader, element) { var timing = Timing.fromBMSChart(chart) var notes = Notes.fromBMSChart(chart) var info = SongInfo.fromBMSChart(chart) - $('
    ')
    -    .text(JSON.stringify(info, null, 2))
    -    .appendTo($sampler)
    +  $('
    ').text(JSON.stringify(info, null, 2)).appendTo($sampler)
       log('Loading samples')
       var loadedSamples = await loadSamples(notes, chart)
       log('Click the button to play!')
       await waitForPlay()
    -  void (function() {
    +  void (function () {
         master.unmute()
         for (let note of notes.all()) {
           setTimeout(() => {
    @@ -72,7 +68,7 @@ async function go(loader, element) {
               .appendTo($sampler)
             let instance = sample.play()
             $sampler[0].scrollTop = $sampler[0].scrollHeight
    -        instance.onstop = function() {
    +        instance.onstop = function () {
               span.addClass('is-off')
             }
           }, timing.beatToSeconds(note.beat) * 1000)
    @@ -81,7 +77,7 @@ async function go(loader, element) {
       })()
     
       function waitForPlay() {
    -    return new Promise(function(resolve) {
    +    return new Promise(function (resolve) {
           $play.show()
           $play.on('click', () => {
             resolve()
    @@ -105,9 +101,11 @@ async function go(loader, element) {
             samples[keysound] = null
             promises.push(
               loadKeysound(_chart.headers.get('wav' + keysound))
    -            .then(blob => master.sample(blob))
    -            .then(sample => (samples[keysound] = sample))
    -            .catch(e => console.error('Unable to load ' + keysound + ': ' + e))
    +            .then((blob) => master.sample(blob))
    +            .then((sample) => (samples[keysound] = sample))
    +            .catch((e) =>
    +              console.error('Unable to load ' + keysound + ': ' + e)
    +            )
                 .tap(() =>
                   log(
                     '[loaded ' + ++completed + '/' + promises.length + ' samples]'
    @@ -127,6 +125,6 @@ async function go(loader, element) {
           .catch(() => loader.file(name.replace(/\.\w+$/, '.ogg')))
           .catch(() => loader.file(name.replace(/\.\w+$/, '.mp3')))
           .catch(() => loader.file(name.replace(/\.\w+$/, '.wav')))
    -      .then(file => file.read())
    +      .then((file) => file.read())
       }
     }
    diff --git a/bemuse/src/coming-soon/index.js b/bemuse/src/coming-soon/index.js
    index a28f37bc4..0e3d297e9 100644
    --- a/bemuse/src/coming-soon/index.js
    +++ b/bemuse/src/coming-soon/index.js
    @@ -10,7 +10,7 @@ export function main() {
       div.innerHTML = template()
     
       import(/* webpackChunkName: 'comingSoonDemo' */ './demo').then(
    -    loadedModule => {
    +    (loadedModule) => {
           const button = div.querySelector('.coming-soon--demo')
           loadedModule.main(button)
         }
    diff --git a/bemuse/src/custom-folder/index.spec.ts b/bemuse/src/custom-folder/index.spec.ts
    index 271b088aa..5033c5e79 100644
    --- a/bemuse/src/custom-folder/index.spec.ts
    +++ b/bemuse/src/custom-folder/index.spec.ts
    @@ -10,10 +10,10 @@ import { CustomFolderState } from './types'
     const debugging = false
     
     const mockFolderScanIO: CustomFolderScanIO = {
    -  log: text => {
    +  log: (text) => {
         debugging && console.log('scanFolder: [log]', text)
       },
    -  setStatus: text => {
    +  setStatus: (text) => {
         debugging && console.debug('scanFolder: [setStatus]', text)
       },
       updateState: () => {},
    @@ -46,12 +46,12 @@ it('allows setting custom folder and loading it in-game', async () => {
       const folder: MockFolder = { song1, song2 }
       const tester = new CustomFolderTestHarness()
       await tester.setFolder(folder)
    -  await tester.checkState(async state => {
    +  await tester.checkState(async (state) => {
         expect(state.chartFilesScanned).not.to.equal(true)
       })
     
       await tester.scan()
    -  await tester.checkState(async state => {
    +  await tester.checkState(async (state) => {
         expect(state.songs).to.have.length(2)
       })
     })
    @@ -61,17 +61,32 @@ it('can scan for new songs', async () => {
       const tester = new CustomFolderTestHarness()
       await tester.setFolder(folder)
       await tester.scan()
    -  await tester.checkState(async state => {
    +  await tester.checkState(async (state) => {
         expect(state.songs).to.have.length(1)
       })
     
       folder['song2'] = song2
       await tester.scan()
    -  await tester.checkState(async state => {
    +  await tester.checkState(async (state) => {
         expect(state.songs).to.have.length(2)
       })
     })
     
    +xit('detects deleted folders', async () => {
    +  const folder: MockFolder = { song1, song2 }
    +  const tester = new CustomFolderTestHarness()
    +  await tester.setFolder(folder)
    +  await tester.scan()
    +  await tester.checkState(async (state) => {
    +    expect(state.songs).to.have.length(2)
    +  })
    +
    +  delete folder['song1']
    +  await tester.scan()
    +  await tester.checkState(async (state) => {
    +    expect(state.songs).to.have.length(1)
    +  })
    +})
     class CustomFolderTestHarness {
       private context = new CustomFolderContextMock()
     
    @@ -107,7 +122,7 @@ function createMockFileSystemDirectoryHandle(
       return {
         kind: 'directory',
         queryPermission: async () => 'granted',
    -    [Symbol.asyncIterator]: async function*() {
    +    [Symbol.asyncIterator]: async function* () {
           for (const [name, value] of Object.entries(data)) {
             if (typeof value === 'string') {
               yield [name, createMockFileSystemFileHandle(name, value)] as const
    diff --git a/bemuse/src/custom-folder/index.ts b/bemuse/src/custom-folder/index.ts
    index b488b82dc..f3855ab25 100644
    --- a/bemuse/src/custom-folder/index.ts
    +++ b/bemuse/src/custom-folder/index.ts
    @@ -61,7 +61,7 @@ export async function scanFolder(
       const { log, setStatus, updateState } = io
       for (let i = 1; ; i++) {
         log(`Iteration #${i} start`)
    -    const result = await scanIteration(state, context, io)
    +    const result = await scanIteration(state, io)
     
         // If there is nothing to be done in the very first iteration, let’s rescan the folder for new chart files.
         if (!result && i === 1) {
    @@ -86,25 +86,50 @@ export async function scanFolder(
     }
     
     async function scanIteration(
    -  state: CustomFolderState | undefined,
    -  context: CustomFolderContext,
    +  inputState: CustomFolderState | undefined,
       io: CustomFolderScanIO
     ): Promise {
    +  const result = await checkFolderStateAndPermissions(inputState, io)
    +  if (!result) {
    +    return
    +  }
    +  const { state, handle } = result
    +
    +  if (!state.chartFilesScanned) {
    +    return scanAllChartFiles(state, handle, io)
    +  }
    +
    +  if ((state?.foldersToUpdate?.length ?? 0) > 0) {
    +    return updateFolders(state, handle, io)
    +  }
    +}
    +
    +async function checkFolderStateAndPermissions(
    +  state: CustomFolderState | undefined,
    +  io: CustomFolderScanIO
    +): Promise<
    +  | {
    +      state: CustomFolderState
    +      handle: FileSystemDirectoryHandle
    +    }
    +  | undefined
    +> {
       const { log, setStatus } = io
       if (!state) {
    -    log('No custom folder set.')
    -    setStatus('No custom folder set.')
    +    const message = 'No custom folder set.'
    +    log(message)
    +    setStatus(message)
         return
       }
     
       const { handle } = state
       if (!handle) {
    -    log('No folder selected.')
    -    setStatus('No folder selected.')
    +    const message = 'No folder selected.'
    +    log(message)
    +    setStatus(message)
         return
       }
     
    -  // Check permissions.
       let permission = await handle.queryPermission({ mode: 'read' })
       if (permission === 'prompt') {
         setStatus('Waiting for permission — please grant access to the folder.')
    @@ -116,69 +141,86 @@ async function scanIteration(
         return
       }
     
    -  // Enumerate all the files.
    -  if (!state.chartFilesScanned) {
    -    const chartFileScanner = new ChartFileScanner(state.chartFiles, true)
    -    let entriesRead = 0
    -    const searchForChartFiles = async (
    -      directoryHandle: FileSystemDirectoryHandle,
    -      parentPath: string[] = []
    -    ) => {
    -      for await (let [name, handle] of directoryHandle) {
    -        const childPath = [...parentPath, name]
    -        try {
    -          if (handle.kind === 'directory') {
    -            await searchForChartFiles(handle, childPath)
    -          } else if (/\.(bms|bme|bml|bmson)$/i.test(name)) {
    -            const fileHandle = handle
    -            await chartFileScanner.addPath(childPath, {
    -              getModifiedDate: async () => {
    -                const file = await fileHandle.getFile()
    -                return file.lastModified
    -              },
    -            })
    -          }
    -        } catch (error) {
    -          log(`Error while processing ${childPath.join('/')}: ${error}`)
    -          console.error(error)
    -        }
    -        entriesRead++
    -        const childPathStr = formatPath(childPath)
    -        setStatus(
    -          `Scanning for chart files. ${entriesRead} entries read. Just processed: ${childPathStr}`
    -        )
    -      }
    -    }
    -    await searchForChartFiles(handle)
    -
    -    const newChartFiles = chartFileScanner.getNewChartFiles()
    -    const foldersToUpdate = chartFileScanner.getFoldersToUpdate()
    -    const foldersToRemove = chartFileScanner.getFoldersToRemove()
    -    const message =
    -      'Scanning done. ' +
    -      [
    -        `Charts: ${newChartFiles.length}`,
    -        `Folders: ${chartFileScanner.getFolderCount()}`,
    -        `Folders to update: ${foldersToUpdate.length}`,
    -        `Folders to remove: ${foldersToRemove.length}`,
    -      ].join('; ')
    -    log(message)
    -    setStatus(message)
    +  return { state, handle }
    +}
     
    -    return {
    -      nextState: {
    -        ...state,
    -        chartFiles: newChartFiles,
    -        chartFilesScanned: true,
    -        foldersToUpdate,
    -        foldersToRemove,
    -      },
    -      moreIterationsNeeded: true,
    +async function scanAllChartFiles(
    +  state: CustomFolderState,
    +  handle: FileSystemDirectoryHandle,
    +  io: CustomFolderScanIO
    +): Promise {
    +  const { log, setStatus } = io
    +  const chartFileScanner = new ChartFileScanner(state.chartFiles, true)
    +  await searchForChartFiles(handle, chartFileScanner, io)
    +
    +  const newChartFiles = chartFileScanner.getNewChartFiles()
    +  const foldersToUpdate = chartFileScanner.getFoldersToUpdate()
    +  const foldersToRemove = chartFileScanner.getFoldersToRemove()
    +  const message =
    +    'Scanning done. ' +
    +    [
    +      `Charts: ${newChartFiles.length}`,
    +      `Folders: ${chartFileScanner.getFolderCount()}`,
    +      `Folders to update: ${foldersToUpdate.length}`,
    +      `Folders to remove: ${foldersToRemove.length}`,
    +    ].join('; ')
    +  log(message)
    +  setStatus(message)
    +
    +  return {
    +    nextState: {
    +      ...state,
    +      chartFiles: newChartFiles,
    +      chartFilesScanned: true,
    +      foldersToUpdate,
    +      foldersToRemove,
    +    },
    +    moreIterationsNeeded: true,
    +  }
    +}
    +
    +async function searchForChartFiles(
    +  directoryHandle: FileSystemDirectoryHandle,
    +  chartFileScanner: ChartFileScanner,
    +  io: CustomFolderScanIO,
    +  parentPath: string[] = []
    +): Promise {
    +  let entriesRead = 0
    +  const { log, setStatus } = io
    +  for await (let [name, handle] of directoryHandle) {
    +    const childPath = [...parentPath, name]
    +    try {
    +      if (handle.kind === 'directory') {
    +        await searchForChartFiles(handle, chartFileScanner, io, childPath)
    +      } else if (/\.(bms|bme|bml|bmson)$/i.test(name)) {
    +        const fileHandle = handle
    +        await chartFileScanner.addPath(childPath, {
    +          getModifiedDate: async () => {
    +            const file = await fileHandle.getFile()
    +            return file.lastModified
    +          },
    +        })
    +      }
    +    } catch (error) {
    +      log(`Error while processing ${childPath.join('/')}: ${error}`)
    +      console.error(error)
         }
    +    entriesRead++
    +    const childPathStr = formatPath(childPath)
    +    setStatus(
    +      `Scanning for chart files. ${entriesRead} entries read. Just processed: ${childPathStr}`
    +    )
       }
    +}
     
    -  if (state.foldersToUpdate && state.foldersToUpdate.length > 0) {
    -    const foldersToUpdate = [...state.foldersToUpdate]
    +async function updateFolders(
    +  state: CustomFolderState,
    +  handle: FileSystemDirectoryHandle,
    +  io: CustomFolderScanIO
    +): Promise {
    +  const { log, setStatus } = io
    +  if ((state?.foldersToUpdate?.length || 0) > 0) {
    +    const foldersToUpdate = [...state.foldersToUpdate!]
         const n = foldersToUpdate.length
         const songsToSave: CustomFolderSong[] = []
         const updatedPathSet = new Set()
    @@ -201,7 +243,7 @@ async function scanIteration(
           const { resources: _unused, ...song } = await loadSongFromResources(
             resources,
             {
    -          onMessage: text => {
    +          onMessage: (text) => {
                 log(text)
                 setStatus(`${statusPrefix} ${text}`)
               },
    @@ -210,7 +252,7 @@ async function scanIteration(
           if (song.charts.length > 0) {
             songsToSave.push({
               path: folder.path,
    -          song: song,
    +          song,
             })
           }
           if (Date.now() > deadline) {
    @@ -219,16 +261,16 @@ async function scanIteration(
         }
     
         const songsToSavePathSet = new Set(
    -      songsToSave.map(song => JSON.stringify(song.path))
    +      songsToSave.map((song) => JSON.stringify(song.path))
         )
         const newSongs = [
           ...(state.songs || []).filter(
    -        song => !songsToSavePathSet.has(JSON.stringify(song.path))
    +        (song) => !songsToSavePathSet.has(JSON.stringify(song.path))
           ),
           ...songsToSave,
         ]
         const newFoldersToUpdate = foldersToUpdate.filter(
    -      folder => !updatedPathSet.has(JSON.stringify(folder.path))
    +      (folder) => !updatedPathSet.has(JSON.stringify(folder.path))
         )
         return {
           nextState: {
    @@ -248,13 +290,13 @@ async function getResourcesForFolder(
     ): Promise {
       const folderHandle = await getFolderHandleByPath(rootFolderHandle, path)
       const files = chartFiles.filter(
    -    file =>
    +    (file) =>
           file.path.length === path.length + 1 &&
           path.every((p, i) => p === file.path[i])
       )
       return {
         fileList: Promise.resolve(
    -      files.map(file => file.path[file.path.length - 1])
    +      files.map((file) => file.path[file.path.length - 1])
         ),
         async file(name) {
           const fileHandle = await folderHandle.getFileHandle(name)
    @@ -290,13 +332,13 @@ class ChartFileScanner {
     
       constructor(
         private previous: CustomFolderState['chartFiles'] = [],
    -    private fast: boolean
    +    private fast = false
       ) {
         this.existingMap = new Map(
    -      _.map(this.previous, file => [JSON.stringify(file.path), file])
    +      _.map(this.previous, (file) => [JSON.stringify(file.path), file])
         )
         this.existingFolderSet = new Set(
    -      _.map(this.previous, file => JSON.stringify(file.path.slice(0, -1)))
    +      _.map(this.previous, (file) => JSON.stringify(file.path.slice(0, -1)))
         )
       }
     
    @@ -336,15 +378,15 @@ class ChartFileScanner {
       }
     
       getFoldersToUpdate(): CustomFolderFolderEntry[] {
    -    return [...this.updatedFolderSet].map(folderKey => ({
    +    return [...this.updatedFolderSet].map((folderKey) => ({
           path: JSON.parse(folderKey) as string[],
         }))
       }
     
       getFoldersToRemove(): CustomFolderFolderEntry[] {
         return [...this.existingFolderSet]
    -      .filter(folderKey => !this.foundFolderSet.has(folderKey))
    -      .map(folderKey => ({
    +      .filter((folderKey) => !this.foundFolderSet.has(folderKey))
    +      .map((folderKey) => ({
             path: JSON.parse(folderKey) as string[],
           }))
       }
    @@ -375,7 +417,7 @@ export async function getSongsFromCustomFolders(
             ...customFolderSong.song,
             resources,
             custom: true,
    -        id: '__custom_' + i,
    +        id: `__custom_${i}`,
           })
         } catch (e) {
           console.error(e)
    diff --git a/bemuse/src/custom-song-loader/index.spec.js b/bemuse/src/custom-song-loader/index.spec.js
    index 0c5d9e729..fb59fba42 100644
    --- a/bemuse/src/custom-song-loader/index.spec.js
    +++ b/bemuse/src/custom-song-loader/index.spec.js
    @@ -1,6 +1,6 @@
     import { loadSongFromResources } from './'
     
    -describe('SongLoader', function() {
    +describe('SongLoader', function () {
       function buffer(text) {
         return Promise.resolve(Buffer.from(text).buffer)
       }
    @@ -14,7 +14,7 @@ describe('SongLoader', function() {
         }
       }
     
    -  describe('with BMS files', function() {
    +  describe('with BMS files', function () {
         let resources = createResources({
           '01.bme': {
             read() {
    @@ -33,24 +33,24 @@ describe('SongLoader', function() {
           },
         })
         let song
    -    before(function() {
    -      let options = { onMessage: msg => console.log(msg) }
    +    before(function () {
    +      let options = { onMessage: (msg) => console.log(msg) }
           return Promise.resolve(loadSongFromResources(resources, options)).tap(
    -        x => (song = x)
    +        (x) => (song = x)
           )
         })
    -    it('should have correct title', function() {
    +    it('should have correct title', function () {
           expect(song.title).to.equal('meow')
         })
    -    it('should have correct number of charts', function() {
    +    it('should have correct number of charts', function () {
           expect(song.charts).to.have.length(3)
         })
    -    it('should have resources key pointing to the resources', function() {
    +    it('should have resources key pointing to the resources', function () {
           expect(song.resources).to.equal(resources)
         })
       })
     
    -  describe('with bmson files', function() {
    +  describe('with bmson files', function () {
         let resources = createResources({
           '01.bmson': {
             read() {
    @@ -59,15 +59,15 @@ describe('SongLoader', function() {
           },
         })
         let song
    -    before(function() {
    +    before(function () {
           return Promise.resolve(loadSongFromResources(resources)).tap(
    -        x => (song = x)
    +        (x) => (song = x)
           )
         })
    -    it('should have correct title', function() {
    +    it('should have correct title', function () {
           expect(song.title).to.equal('meow')
         })
    -    it('should have correct number of charts', function() {
    +    it('should have correct number of charts', function () {
           expect(song.charts).to.have.length(1)
         })
       })
    diff --git a/bemuse/src/custom-song-loader/index.ts b/bemuse/src/custom-song-loader/index.ts
    index b2ada4c07..76951b2d5 100644
    --- a/bemuse/src/custom-song-loader/index.ts
    +++ b/bemuse/src/custom-song-loader/index.ts
    @@ -12,34 +12,34 @@ export function loadSongFromResources(
         resources.setLoggingFunction(onMessage)
       }
       return resources.fileList
    -    .then(fileList => {
    +    .then((fileList) => {
           console.log(fileList)
    -      return fileList.filter(filename =>
    +      return fileList.filter((filename) =>
             /\.(bms|bme|bml|bmson)$/i.test(filename)
           )
         })
    -    .then(bmsFileList => {
    +    .then((bmsFileList) => {
           onMessage(bmsFileList.length + ' file(s) found. Reading them...')
    -      return Promise.map(bmsFileList, filename => {
    +      return Promise.map(bmsFileList, (filename) => {
             const start = Date.now()
             return resources
               .file(filename)
    -          .then(file => file.read())
    -          .then(x => {
    +          .then((file) => file.read())
    +          .then((x) => {
                 const elapsed = Date.now() - start
                 if (elapsed > 1000) onMessage('Read: ' + filename)
                 return x
               })
    -          .then(arrayBuffer => ({
    +          .then((arrayBuffer) => ({
                 name: filename,
                 data: arrayBuffer,
               }))
           })
         })
    -    .then(files => {
    +    .then((files) => {
           return new Promise((resolve, reject) => {
             let worker = new Worker()
    -        worker.onmessage = function({ data }) {
    +        worker.onmessage = function ({ data }) {
               if (data.type === 'result') {
                 resolve(data.song)
                 worker.terminate()
    @@ -58,7 +58,7 @@ export function loadSongFromResources(
                 )
               }
             }
    -        worker.onerror = function(e) {
    +        worker.onerror = function (e) {
               onMessage('Worker error: ' + e)
               console.error('Worker error: ' + e)
               reject(e.error)
    @@ -66,7 +66,7 @@ export function loadSongFromResources(
             worker.postMessage({ files })
           })
         })
    -    .then(song => {
    +    .then((song) => {
           song.resources = resources
           return song
         })
    diff --git a/bemuse/src/custom-song-loader/song-loader.worker.js b/bemuse/src/custom-song-loader/song-loader.worker.js
    index 95f38c249..4cecf7269 100644
    --- a/bemuse/src/custom-song-loader/song-loader.worker.js
    +++ b/bemuse/src/custom-song-loader/song-loader.worker.js
    @@ -24,24 +24,24 @@ if (
       }
     }
     
    -addEventListener('message', function({ data }) {
    +addEventListener('message', function ({ data }) {
       let files = data.files.map(convertBuffer)
       postMessage({ type: 'started' })
       function onProgress(current, total, file) {
         postMessage({ type: 'progress', current, total, file })
       }
    -  Promise.try(function() {
    +  Promise.try(function () {
         return indexer.getSongInfo(files, { onProgress })
       })
    -    .then(function(song) {
    -      song.warnings.forEach(function(warning) {
    +    .then(function (song) {
    +      song.warnings.forEach(function (warning) {
             if (global.console && console.warn) {
               console.warn(warning)
             }
           })
           postMessage({ type: 'result', song: song })
         })
    -    .catch(function(e) {
    +    .catch(function (e) {
           console.error('CAUGHT', e)
         })
         .done()
    diff --git a/bemuse/src/devtools/benchmark.js b/bemuse/src/devtools/benchmark.js
    index 14097ed54..04a9935a1 100644
    --- a/bemuse/src/devtools/benchmark.js
    +++ b/bemuse/src/devtools/benchmark.js
    @@ -12,7 +12,7 @@ function Stat() {
       let lastSec = 0
       let secAvg = 0
       return {
    -    push: function(delta) {
    +    push: function (delta) {
           let t = now()
           sum += delta
           count += 1
    @@ -40,7 +40,7 @@ function Benchmarker() {
         enabled: true,
         stats,
         wrap(title, f) {
    -      return function() {
    +      return function () {
             try {
               var start = now()
               return f.apply(this, arguments)
    @@ -56,7 +56,7 @@ function Benchmarker() {
         },
         toString() {
           var lines = []
    -      Object.keys(stats).forEach(function(key) {
    +      Object.keys(stats).forEach(function (key) {
             lines.push('- ' + key + ': ' + stats[key])
           })
           return lines.join('\n')
    @@ -76,6 +76,6 @@ function FakeBenchmarker() {
       }
     }
     
    -export default (window.BEMUSE_BENCHMARK = shouldEnableBenchmark()
    +export default window.BEMUSE_BENCHMARK = shouldEnableBenchmark()
       ? new Benchmarker()
    -  : new FakeBenchmarker())
    +  : new FakeBenchmarker()
    diff --git a/bemuse/src/devtools/playground.js b/bemuse/src/devtools/playground.js
    index b5a2e9469..15097c10e 100644
    --- a/bemuse/src/devtools/playground.js
    +++ b/bemuse/src/devtools/playground.js
    @@ -3,7 +3,7 @@ import React from 'react'
     import ReactDOM from 'react-dom'
     import query from 'bemuse/utils/query'
     
    -const availablePlaygrounds = (function(context) {
    +const availablePlaygrounds = (function (context) {
       let playgrounds = {}
       for (let key of context.keys()) {
         let name = key.match(/\w[^.]+/)[0]
    @@ -24,7 +24,7 @@ class DefaultPlayground extends React.Component {
             

    Bemuse Playground

    Please select a playground