Skip to content

Commit

Permalink
Merge pull request #159 from redsolver/search
Browse files Browse the repository at this point in the history
Add search (text and genre), song preview now uses cdn directly
  • Loading branch information
dmarcos authored Jan 6, 2023
2 parents 4f19fb1 + 3cc1d87 commit 2f8167f
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 76 deletions.
99 changes: 63 additions & 36 deletions src/components/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ AFRAME.registerComponent('search', {
},

init: function () {
this.eventDetail = { query: '', results: topSearch };
this.eventDetail = { query: '', results: topSearch, url: '', page: 0 };
this.keyboardEl = document.getElementById('keyboard');
this.popularHits = topSearch;
shuffle(this.popularHits);
this.queryObject = { hitsPerPage: 0, query: '' };
this.el.sceneEl.addEventListener('searchclear', () => {
this.search('');});
this.search('');
});
},

update: function (oldData) {
Expand Down Expand Up @@ -78,49 +79,75 @@ AFRAME.registerComponent('search', {

// Favorites.
if (this.data.playlist === 'favorites') {
this.eventDetail.results = JSON.parse(localStorage.getItem('favorites'));
this.eventDetail.results = JSON.parse(localStorage.getItem('favorites-v2'));
this.el.sceneEl.emit('searchresults', this.eventDetail);
return;
}

if (this.data.difficultyFilter || this.data.genre || this.data.playlist) {
filters.length = 0;

// Difficulty filter.
if (this.data.difficultyFilter && this.data.difficultyFilter !== 'All') {
filters.push(`difficulties:"${this.data.difficultyFilter}"`);
}

// Genre filter.
if (this.data.genre === 'Video Games') {
filters.push(`genre:"Video Game" OR genre:"Video Games"`);
} else if (this.data.genre) {
filters.push(`genre:"${this.data.genre}"`);
}

// Playlist filter.
if (this.data.playlist) {
filters.push(`playlists:"${this.data.playlist}"`);
}

this.queryObject.filters = filters.join(' AND ');
/* if (this.data.difficultyFilter || this.data.genre || this.data.playlist) {
filters.length = 0
// Difficulty filter.
if (this.data.difficultyFilter && this.data.difficultyFilter !== 'All') {
filters.push(`difficulties:"${this.data.difficultyFilter}"`)
}
// Genre filter.
if (this.data.genre === 'Video Games') {
filters.push(`genre:"Video Game" OR genre:"Video Games"`)
} else if (this.data.genre) {
filters.push(`genre:"${this.data.genre}"`)
}
// Playlist filter.
if (this.data.playlist) {
filters.push(`playlists:"${this.data.playlist}"`)
}
this.queryObject.filters = filters.join(' AND ')
} else {
delete this.queryObject.filters
} */
let url = `https://beatsaver.com/api/search/text/CURRENT_PAGE_INDEX?sortOrder=Rating&automapper=true&q=${encodeURIComponent(query)}`;

if (this.data.genre) {
const genreMap = {
'Pop': 'pop',
'R&B': 'rb',
'Rap': 'hip-hop-rap',
'Rock': 'rock',
'Soundtrack': 'tv-movie-soundtrack',
'Video Games': 'video-game-soundtrack',
'Electronic': 'electronic',
'Hip Hop': 'hip-hop-rap',
'House': 'house',
'J-Pop': 'j-pop',
'K-Pop': 'k-pop',
'Meme': 'comedy-meme',
'Alternative': 'alternative',
'Anime': 'anime',
'Comedy': 'comedy-meme',
'Dubstep': 'dubstep',
'Dance': 'dance'
};
const tag = genreMap[this.data.genre];
url = `https://beatsaver.com/api/search/text/CURRENT_PAGE_INDEX?sortOrder=Rating&automapper=true&tags=${encodeURIComponent(tag)}`;
} else {
delete this.queryObject.filters;
if (query && query.length < 3) { return; }
}

if (query && query.length < 3) { return; }

algolia.search(this.queryObject, (err, content) => {
if (err) {
this.el.sceneEl.emit('searcherror', null, false);
console.error(err);
return;
}
fetch(url.replaceAll('CURRENT_PAGE_INDEX', 0))
.then(r => {
return r.json();})
.then(res => {
var hits = res['docs'].map(convertBeatmap);

this.eventDetail.results = content.hits;
this.eventDetail.results = hits;
this.eventDetail.url = url;
this.eventDetail.urlPage = 0;

this.el.sceneEl.emit('searchresults', this.eventDetail);
});
this.el.sceneEl.emit('searchresults', this.eventDetail);
});
}
});

Expand Down
38 changes: 10 additions & 28 deletions src/components/song-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,25 @@ const PREVIEW_VOLUME = 0.5;
*/
AFRAME.registerComponent('song-preview-system', {
schema: {
previewStartTime: { type: 'int' },
selectedChallengeId: { type: 'string' }
selectedChallengeId: { type: 'string' },
selectedChallengeVersion: { type: 'string' }
},

init: function () {
this.audio = document.createElement('audio');
this.audio.volume = PREVIEW_VOLUME;

function deepGet (obj, properties) {
if (obj === undefined || obj === null) {
return;
}
if (properties.length === 0) {
return obj;
}
var foundSoFar = obj[properties[0]];
var remainingProperties = properties.slice(1);
return deepGet(foundSoFar, remainingProperties);
}

this.el.addEventListener('ziploaderend', evt => {
const audioSrc = evt.detail.audio;
this.audio.pause();

const data = this.data;

if (data.selectedChallengeId /* && oldData.selectedChallengeId !== data.selectedChallengeId */) {
this.audio.setAttribute('src', audioSrc);
this.audio.currentTime = deepGet(evt.detail, ['info', '_previewStartTime']) || data.previewStartTime || 12;
this.audio.play();
}
});
},

update: function (oldData) {
const data = this.data;
if (!data.selectedChallengeId || oldData.selectedChallengeId !== data.selectedChallengeId) {
console.log('update-song', oldData, data);

if (data.selectedChallengeId && oldData.selectedChallengeId !== data.selectedChallengeId) {
this.audio.pause();
this.audio.setAttribute('src', 'https://cdn.beatsaver.com/' + data.selectedChallengeVersion + '.mp3');
this.audio.currentTime = 0;
this.audio.play();
} else if (!data.selectedChallengeId) {
this.audio.pause();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/constants/genres.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = [
{name: 'Alternative', row: 3, column: 1},
{name: 'Anime', row: 3, column: 2},
{name: 'Comedy', row: 3, column: 3},
{name: 'Disney', row: 3, column: 4},
/* {name: 'TODO', row: 3, column: 4}, */
{name: 'Dubstep', row: 3, column: 5},
{name: 'EDM', row: 3, column: 6}
{name: 'Dance', row: 3, column: 6}
];
2 changes: 1 addition & 1 deletion src/scene.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
bind__leaderboard="difficulty: menuSelectedChallenge.difficulty || challenge.difficulty; beatmapCharacteristic: menuSelectedChallenge.beatmapCharacteristic || challenge.beatmapCharacteristic; gameMode: gameMode; inVR: inVR; isVictory: isVictory; menuSelectedChallengeId: menuSelectedChallenge.id; challengeId: challenge.id"
bind__search="difficultyFilter: difficultyFilter; genre: genre; playlist: playlist; query: search.query"
bind__song="audio: challenge.audio; challengeId: challenge.id; isLoading: isLoading; isPlaying: isPlaying; isBeatsPreloaded: challenge.isBeatsPreloaded; isGameOver: isGameOver; isVictory: isVictory"
bind__song-preview-system="previewStartTime: menuSelectedChallenge.previewStartTime; selectedChallengeId: menuSelectedChallenge.id"
bind__song-preview-system="selectedChallengeId: menuSelectedChallenge.id; selectedChallengeVersion: menuSelectedChallenge.version"
bind__stage-colors="colorScheme: colorScheme"
bind__tunnels="isPlaying: isPlaying; songDuration: challenge.metadata.duration"
bind__zip-loader="difficulties: menuDifficulties; isLoading: isLoading; version: menuSelectedChallenge.version; directDownload: menuSelectedChallenge.directDownload; bpm: menuSelectedChallenge.metadata.bpm"
Expand Down
36 changes: 32 additions & 4 deletions src/state/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* global localStorage */
import COLORS from '../constants/colors';
const utils = require('../utils');
const convertBeatmap = require('../lib/convert-beatmap');

const challengeDataStore = {};
let HAS_LOGGED_VR = false;
Expand Down Expand Up @@ -38,7 +39,7 @@ const SKIP_INTRO = AFRAME.utils.getUrlParameter('skipintro') === 'true';

const colorScheme = localStorage.getItem('colorScheme') || 'default';

let favorites = localStorage.getItem('favorites');
let favorites = localStorage.getItem('favorites-v2');
if (favorites) {
try {
favorites = JSON.parse(favorites);
Expand Down Expand Up @@ -169,7 +170,10 @@ AFRAME.registerState({
queryText: '',
results: [],
songNameTexts: '', // All names in search results merged together.
songSubNameTexts: '' // All sub names in search results merged together.
songSubNameTexts: '', // All sub names in search results merged together.
// url and urlPage are used to load more results from the API when scrolling down
url: '',
urlPage: 0,
},
searchResultsPage: [],
speed: 10
Expand Down Expand Up @@ -353,7 +357,7 @@ AFRAME.registerState({
for (let i = 0; i < state.favorites.length; i++) {
if (state.favorites[i].id === id) {
state.favorites.splice(i, 1);
localStorage.setItem('favorites', JSON.stringify(state.favorites));
localStorage.setItem('favorites-v2', JSON.stringify(state.favorites));
return;
}
}
Expand All @@ -362,7 +366,7 @@ AFRAME.registerState({
state.menuSelectedChallenge.isFavorited = true;
if (state.favorites.filter(favorite => favorite.id === id).length) { return; }
state.favorites.push(challenge)
localStorage.setItem('favorites', JSON.stringify(state.favorites));
localStorage.setItem('favorites-v2', JSON.stringify(state.favorites));
}
},

Expand Down Expand Up @@ -675,6 +679,28 @@ AFRAME.registerState({
}
state.search.page++;
computeSearchPagination(state);

if (state.search.url === undefined) {
return;
}

if ((state.search.page + 3) > Math.floor(state.search.results.length / SEARCH_PER_PAGE)) {

state.search.urlPage = state.search.urlPage + 1;

fetch(state.search.url.replaceAll('CURRENT_PAGE_INDEX', state.search.urlPage))
.then(r => { return r.json() })
.then(res => {
var hits = res['docs'].map(convertBeatmap)

state.search.results.push(...hits);

for (i = 0; i < hits.length; i++) {
let result = hits[i];
challengeDataStore[result.id] = result;
}
})
}
},

/**
Expand All @@ -684,6 +710,8 @@ AFRAME.registerState({
var i;
state.search.hasError = false;
state.search.page = 0;
state.search.url = payload.url;
state.search.urlPage = payload.urlPage;
state.search.query = payload.query;
state.search.queryText = truncate(payload.query, 10);
state.search.results = payload.results;
Expand Down
10 changes: 5 additions & 5 deletions src/templates/menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@
<!-- Search. -->
<a-entity id="keyboard"
bind__super-keyboard="{% if not DEBUG_KEYBOARD %}hand: activeHand === 'left' && '#leftHand' || '#rightHand'; {% endif %}show: isSearching"
super-keyboard="label: Search 15000 Community Songs; inputColor: #fff; labelColor: {{ COLORS.WHITE }}; width: 1.5; hand: {{ DEBUG_KEYBOARD and '#mouseCursor' or '#rightHand' }}; imagePath: assets/img/keyboard; font: assets/fonts/Viga-Regular.json; align: center; model: superkeyboard; keyColor: #fff; injectToRaycasterObjects: false; filters: allupper; keyHoverColor: #fff"
super-keyboard="label: Search on beatsaver.com; inputColor: #fff; labelColor: {{ COLORS.WHITE }}; width: 1.5; hand: {{ DEBUG_KEYBOARD and '#mouseCursor' or '#rightHand' }}; imagePath: assets/img/keyboard; font: assets/fonts/Viga-Regular.json; align: center; model: superkeyboard; keyColor: #fff; injectToRaycasterObjects: false; filters: allupper; keyHoverColor: #fff"
position="0.58 1.2 -1.95" keyboard-raycastable="condition: isSearching" search
proxy-event__dismiss="event: superkeyboarddismiss; to: a-scene; as: keyboardclose"
proxy-event__accept="event: superkeyboardinput; to: a-scene; as: keyboardclose" render-order="menubutton"
Expand Down Expand Up @@ -256,7 +256,7 @@
</a-entity> -->

<!-- Search toggle. -->
<!-- <a-entity id="searchButtons">
<a-entity id="searchButtons">
<a-entity
id="searchButton"
mixin="bigMenuTopButton"
Expand Down Expand Up @@ -286,7 +286,7 @@
text="align: center; wrapCount: 20"
position="0 0.1 0.035"
render-order="menutext"></a-entity>
</a-entity> -->
</a-entity>

<!-- Difficulty menu toggle. -->
<!-- <a-entity id="difficultyFilter">
Expand All @@ -312,7 +312,7 @@
</a-entity> -->

<!-- Genre menu toggle. -->
<!-- <a-entity id="genreButtons">
<a-entity id="genreButtons">
<a-entity id="genreButton"
mixin="bigMenuTopButton"
bind__visible-raycastable="mainMenuActive && !genre"
Expand Down Expand Up @@ -341,7 +341,7 @@
text="align: center; wrapCount: 20"
position="0 0.1 0.035"
render-order="menutext"></a-entity>
</a-entity> -->
</a-entity>
</a-entity>

<!-- Options menu toggle. -->
Expand Down

0 comments on commit 2f8167f

Please sign in to comment.