Skip to content

Commit a95ef57

Browse files
committed
- Added feedback when fetching metadata
1 parent 722439a commit a95ef57

File tree

8 files changed

+256
-46
lines changed

8 files changed

+256
-46
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"webpack": "4.41.0",
6565
"webpack-cli": "^3.3.10",
6666
"webpack-extension-reloader": "^1.1.4",
67+
"concurrently": "^6.0.2",
6768
"webpack-merge": "^4.2.2"
6869
},
6970
"dependencies": {

src/@types/events.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export type RuntimeMessage =
55
| { type: 'ON_BG_RECORDING_START' }
66
| { type: 'ON_BG_RECORDING_STOP'; payload: { match: LocalSong | null } }
77
| { type: 'INIT_RECORDING' }
8+
| { type: 'START_FETCHING_METADATA' }
9+
| { type: 'STOP_FETCHING_METADATA' }
810
| { type: 'STOP_RECORDING' }
911
| { type: 'MATCH_FOUND'; payload: { match: Song } }
1012
| { type: 'NO_MATCH_FOUND' }

src/popup/PopupApp.tsx

+9-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { observer } from 'mobx-react-lite'
77
import useStores from '~popup/hooks/useStores'
88
import SearchButton from '~popup/components/search-button'
99
import AppButton from '~popup/components/ui/AppButton'
10-
import { FiSun, FiMoon, FiList } from 'react-icons/fi'
10+
import { FiList, FiMoon, FiSun } from 'react-icons/fi'
1111
import AppToolbar from '~popup/components/AppToolbar'
1212
import HistoryView from '~popup/views/history-view'
1313
import useChromeOnMessage from '~popup/hooks/useChromeOnMessage'
@@ -25,14 +25,16 @@ const PopupApp: React.FC<Props> = () => {
2525
requestRecording,
2626
stopRecording,
2727
markUnreadAsRead,
28+
fetchingMetadatas,
2829
recording,
2930
hasUnreadMatches
3031
},
3132
app: { clearBadge, toggleTheme, theme }
3233
} = useStores()
3334
const onClick = useCallback(() => {
35+
if (fetchingMetadatas) return
3436
recording ? stopRecording() : requestRecording()
35-
}, [recording])
37+
}, [recording, fetchingMetadatas])
3638
const [showHistory, setShowHistory] = useState(false)
3739
useChromeOnMessage(
3840
'MATCH_FOUND',
@@ -76,7 +78,11 @@ const PopupApp: React.FC<Props> = () => {
7678
setShowHistory(history => !history)
7779
}}
7880
/>
79-
<SearchButton recording={recording} onClick={onClick} />
81+
<SearchButton
82+
fetchingMetadatas={fetchingMetadatas}
83+
recording={recording}
84+
onClick={onClick}
85+
/>
8086
<MainAppToolbar>
8187
<AppButton
8288
onClick={() => {

src/popup/components/search-button/index.tsx

+12-2
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,27 @@ import { HTMLMotionProps } from 'framer-motion'
55

66
interface Props extends HTMLMotionProps<'div'> {
77
readonly recording: boolean
8+
readonly fetchingMetadatas: boolean
89
}
910

10-
const SearchButton: React.FC<Props> = ({ recording, ...props }) => {
11+
const SearchButton: React.FC<Props> = ({
12+
recording,
13+
fetchingMetadatas,
14+
...props
15+
}) => {
1116
return (
1217
<SearchButtonInner
18+
disabled={fetchingMetadatas}
1319
recording={recording}
1420
{...props}
1521
initial={recording ? 'recording' : 'initial'}
1622
animate={recording ? 'recording' : 'initial'}
1723
variants={variants.SearchButtonInner}>
18-
{recording ? 'Stop' : 'Record'}
24+
{fetchingMetadatas
25+
? 'Fetching metadata...'
26+
: recording
27+
? 'Stop'
28+
: 'Record'}
1929
</SearchButtonInner>
2030
)
2131
}

src/popup/components/search-button/styled.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ export const SearchButtonInner = styled(motion.div).attrs<{
88
recording: boolean
99
}>(props => ({
1010
className: props.recording ? 'is-recording' : null
11-
}))<{ recording: boolean }>`
12-
transition: all 0.3s;
11+
}))<{ recording: boolean; disabled: boolean }>`
12+
transition: all 0.3s, font-size 0s;
1313
align-items: center;
1414
background: ${props => theme(props).colors.primary};
1515
box-shadow: 0 5px 6px rgba(0, 0, 0, 0.18), 0 10px 20px rgba(0, 0, 0, 0.07);
@@ -35,4 +35,11 @@ export const SearchButtonInner = styled(motion.div).attrs<{
3535
css`
3636
animation: ${blink} 0.5s infinite alternate;
3737
`}
38+
${props =>
39+
props.disabled &&
40+
css`
41+
font-size: 16px;
42+
opacity: 0.4;
43+
pointer-events: none;
44+
`}
3845
`

src/popup/stores/SongStore.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const SONG_STORAGE_KEY = 'song-store'
1717
export class SongStore {
1818
public history = observable.array<LocalSong>([], { deep: false })
1919

20+
@observable public fetchingMetadatas = false
2021
@observable public recording =
2122
chrome.extension.getBackgroundPage()?.recorder.isRecording || false
2223

@@ -26,10 +27,19 @@ export class SongStore {
2627
StorageHelper.set(SONG_STORAGE_KEY, this.serialized)
2728
})
2829
chrome.runtime.onMessage.addListener(message => {
29-
if (message.type === 'STOP_RECORDING') {
30-
this.recording = false
31-
} else if (message.type === 'MATCH_FOUND') {
32-
this.populateFromStorage()
30+
switch (message.type) {
31+
case 'START_FETCHING_METADATA':
32+
this.fetchingMetadatas = true
33+
break
34+
case 'STOP_FETCHING_METADATA':
35+
this.fetchingMetadatas = false
36+
break
37+
case 'STOP_RECORDING':
38+
this.recording = false
39+
break
40+
case 'MATCH_FOUND':
41+
this.populateFromStorage()
42+
break
3343
}
3444
})
3545
}

src/services/AudioRecorder.ts

+44-33
Original file line numberDiff line numberDiff line change
@@ -93,55 +93,66 @@ export class AudioRecorder {
9393
: null
9494
: null
9595
if (match) {
96-
const html = await (
97-
await fetch(`https://www.aha-music.com/${match.acr_id}`)
98-
).text()
99-
const parser = new ACRPageParser(html)
100-
match.spotify_id = parser.getSpotifyId()
101-
match.youtube_id = parser.getYoutubeId()
102-
match.deezer_id = parser.getDeezerId()
10396
let thumbnail: string | null = null
10497
let title: string | null = null
10598
try {
99+
chrome.runtime.sendMessage({
100+
type: 'START_FETCHING_METADATA'
101+
})
102+
const html = await (
103+
await fetch(`https://www.aha-music.com/${match.acr_id}`)
104+
).text()
105+
const parser = new ACRPageParser(html)
106+
match.spotify_id = parser.getSpotifyId()
107+
match.youtube_id = parser.getYoutubeId()
108+
match.deezer_id = parser.getDeezerId()
106109
if (match.spotify_id) {
107110
const response = await SpotifyOEmbedClient.oembed(
108111
match.spotify_id
109112
)
110113
thumbnail = response.thumbnail_url
111114
title = response.title
112115
}
113-
} catch {
116+
chrome.runtime.sendMessage({
117+
type: 'STOP_FETCHING_METADATA'
118+
})
119+
const entry = this.buildLocalMatch({ match, thumbnail, title })
120+
StorageHelper.get<SongSerializedState>(SONG_STORAGE_KEY).then(
121+
state => {
122+
StorageHelper.set<SongSerializedState>(SONG_STORAGE_KEY, {
123+
history: [entry, ...state.history.slice(0, MAX_MATCHES_ENTRY)]
124+
}).then(() => {
125+
if (
126+
chrome.extension.getViews({ type: 'popup' }).length === 0
127+
) {
128+
window.unreadMatches++
129+
chrome.browserAction.setBadgeText({
130+
text: window.unreadMatches.toString()
131+
})
132+
chrome.tabs.sendMessage(tabs[0].id!, {
133+
type: 'ON_BG_RECORDING_STOP',
134+
payload: { match: entry }
135+
})
136+
}
137+
chrome.runtime.sendMessage({
138+
type: 'MATCH_FOUND',
139+
payload: {
140+
match: entry
141+
}
142+
})
143+
})
144+
}
145+
)
146+
} catch (e) {
147+
chrome.runtime.sendMessage({
148+
type: 'STOP_FETCHING_METADATA'
149+
})
114150
console.log(
115151
'An error occured while fetching informations from Spotify'
116152
)
117153
thumbnail = null
118154
title = null
119155
}
120-
const entry = this.buildLocalMatch({ match, thumbnail, title })
121-
StorageHelper.get<SongSerializedState>(SONG_STORAGE_KEY).then(
122-
state => {
123-
StorageHelper.set<SongSerializedState>(SONG_STORAGE_KEY, {
124-
history: [entry, ...state.history.slice(0, MAX_MATCHES_ENTRY)]
125-
}).then(() => {
126-
if (chrome.extension.getViews({ type: 'popup' }).length === 0) {
127-
window.unreadMatches++
128-
chrome.browserAction.setBadgeText({
129-
text: window.unreadMatches.toString()
130-
})
131-
chrome.tabs.sendMessage(tabs[0].id!, {
132-
type: 'ON_BG_RECORDING_STOP',
133-
payload: { match: entry }
134-
})
135-
}
136-
chrome.runtime.sendMessage({
137-
type: 'MATCH_FOUND',
138-
payload: {
139-
match: entry
140-
}
141-
})
142-
})
143-
}
144-
)
145156
} else {
146157
if (chrome.extension.getViews({ type: 'popup' }).length === 0) {
147158
chrome.tabs.sendMessage(tabs[0].id!, {

0 commit comments

Comments
 (0)