fuzzyworld

hawk / time-arrows / files / public / main.js

Branch time-arrows · default branch · all branches

main.js

5.5 KB · history · blame

1document.getElementById('version').innerText = hawkInfo.version;
2document.getElementById('updated').innerText = hawkInfo.updated;
3
4const urlParams = new URLSearchParams(window.location.search);
5const code = urlParams.get('code');
6const error = urlParams.get('error');
7if (code) {
8 getToken(code).then(() => {
9 window.history.replaceState({}, document.title, '/');
10 window.location = getSpotifyRedirectURL();
11 })
12} else if (error) {
13 console.error(error);
14 window.history.replaceState({}, document.title, '/');
15 window.location = getSpotifyRedirectURL();
16}
17
18const accessToken = localStorage.getItem('access_token');
19const showSignInButton = !accessToken
20
21const signInButton = document.getElementById('signin');
22const signOutButton = document.getElementById('signout');
23const controlsDiv = document.getElementById('controls');
24const clearCacheButton = document.getElementById('clear-cache');
25if (showSignInButton) {
26 signInButton.setAttribute('style', 'display: block');
27 signInButton.addEventListener('click', signIn);
28 signOutButton.setAttribute('style', 'display: none');
29 clearCacheButton.setAttribute('style', 'display: none');
30 controlsDiv.setAttribute('style', 'display: none');
31} else {
32 signInButton.setAttribute('style', 'display: none');
33 controlsDiv.setAttribute('style', 'display: block');
34 signOutButton.setAttribute('style', 'display: block');
35 clearCacheButton.setAttribute('style', 'display: block');
36 setCurrentPlayingSong();
37 setInterval(setCurrentPlayingSong, 5 * 1000);
38}
39
40async function setCurrentPlayingSong() {
41 const currentSongSpan = document.getElementById('current-song');
42 const currentTrack = await getPlayingTrack();
43 if (currentTrack && currentTrack.is_playing) {
44 currentSongSpan.innerText = `${currentTrack.item.name} by ${currentTrack.item.artists[0].name}`;
45 } else {
46 currentSongSpan.innerText = 'Nothing playing';
47 }
48}
49
50function formatDuration(ms) {
51 // Convert milliseconds to total seconds
52 let totalSeconds = Math.floor(ms / 1000);
53
54 // Calculate minutes and seconds
55 let minutes = Math.floor(totalSeconds / 60);
56 let seconds = totalSeconds % 60;
57
58 // Ensure seconds are always 2 digits
59 let formattedSeconds = seconds.toString().padStart(2, '0');
60
61 // Return formatted string
62 return `${minutes}:${formattedSeconds}`;
63}
64
65async function searchForMatch() {
66 const searchButton = document.getElementById('search');
67 searchButton.setAttribute('disabled', 'disabled');
68 try {
69 const minutes = document.getElementById('minutes-input').value;
70 const seconds = document.getElementById('seconds-input').value;
71 const tracks = await search(minutes, seconds);
72 const resultsDiv = document.getElementById('results');
73 if (tracks.length == 0) {
74 resultsDiv.innerHTML = 'No songs found for that duration.';
75 } else {
76 resultsDiv.innerHTML = '';
77 tracks.forEach(track => {
78 const songItem = document.querySelector('#song-item');
79 const html = interpolate(songItem.innerHTML, {
80 name: track.name,
81 artist: track.artists[0].name,
82 duration: formatDuration(track.duration_ms),
83 trackId: track.id,
84 trackHref: track.external_urls.spotify
85 });
86 resultsDiv.innerHTML += html;
87 });
88 }
89 } catch (e) {
90 console.error(e);
91 reportStatus(`Encountered error while searching: ${e}`);
92 } finally {
93 searchButton.removeAttribute('disabled');
94 }
95}
96
97async function search(minutes, seconds) {
98 reportStatus(`Retrieving albums`);
99 const albums = await getAlbums((state) => {
100 const { processedCount, totalCount } = state;
101 if (totalCount <= 0) {
102 totalCount = "???"
103 }
104 reportStatus(`Retrieving albums: ${processedCount} of ${totalCount}`);
105 });
106
107 const foundTracks = [];
108 for (let i = 0; i < albums.length; i++) {
109 const album = albums[i];
110 const tracks = await getTracks(album.album.id, (state) => {
111 const { processedCount, totalCount } = state;
112 if (totalCount <= 0) {
113 totalCount = "???"
114 }
115 reportStatus(`Retrieving tracks for album ${i + 1} of ${albums.length}: ${processedCount} of ${totalCount}`);
116 });
117
118 for (let j = 0; j < tracks.length; j++) {
119 const track = tracks[j];
120 const duration = track.duration_ms;
121 const durationInSeconds = Math.floor(duration / 1000);
122 const durationInMinutes = Math.floor(durationInSeconds / 60);
123 const durationInRemainingSeconds = durationInSeconds % 60;
124
125 if (durationInMinutes == minutes && durationInRemainingSeconds == seconds) {
126 foundTracks.push(track);
127 }
128 }
129 }
130
131 reportStatus(`Found ${foundTracks.length} track(s)`);
132 return foundTracks;
133}
134
135async function pauseOrPlay() {
136 const currentTrack = await getPlayingTrack();
137 if (currentTrack && currentTrack.is_playing) {
138 await pause();
139 } else {
140 await play();
141 }
142 setCurrentPlayingSong();
143}
144
145async function playChosenSong(trackId) {
146 await playTrack(trackId);
147 setCurrentPlayingSong();
148}
149
150let statusText = '';
151setInterval(() => {
152 const statusDiv = document.getElementById('status');
153 statusDiv.innerText = statusText;
154}, 100);
155
156function reportStatus(text) {
157 statusText = text;
158}
159
160async function clearDb() {
161 await deleteDb();
162 window.location.reload();
163}