Skip to content

Commit

Permalink
Merge pull request #52 from mbaraa/fix/async-playlist-fetch
Browse files Browse the repository at this point in the history
Feat: Asynchronous Playlist fetch
  • Loading branch information
mbaraa authored May 27, 2024
2 parents 3f4b615 + 16845f5 commit 795dc5f
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 24 deletions.
1 change: 1 addition & 0 deletions cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func StartServer(staticFS embed.FS) error {
apisHandler.HandleFunc("GET /search-suggestion", apis.HandleSearchSuggestions)
apisHandler.HandleFunc("GET /song", gHandler.OptionalAuthApi(songDownloadApi.HandlePlaySong))
apisHandler.HandleFunc("PUT /song/playlist", gHandler.AuthApi(playlistsApi.HandleToggleSongInPlaylist))
apisHandler.HandleFunc("GET /playlist/all", gHandler.AuthApi(playlistsApi.HandleGetPlaylistsForPopover))
apisHandler.HandleFunc("POST /playlist", gHandler.AuthApi(playlistsApi.HandleCreatePlaylist))
apisHandler.HandleFunc("PUT /playlist/public", gHandler.AuthApi(playlistsApi.HandleTogglePublicPlaylist))
apisHandler.HandleFunc("PUT /playlist/join", gHandler.AuthApi(playlistsApi.HandleToggleJoinPlaylist))
Expand Down
25 changes: 25 additions & 0 deletions handlers/apis/playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"dankmuzikk/log"
"dankmuzikk/services/playlists"
"dankmuzikk/services/playlists/songs"
"dankmuzikk/views/components/playlist"
"dankmuzikk/views/pages"
"encoding/json"
"net/http"
Expand Down Expand Up @@ -160,3 +161,27 @@ func (p *playlistApi) HandleDeletePlaylist(w http.ResponseWriter, r *http.Reques

w.Header().Set("HX-Redirect", "/playlists")
}

func (p *playlistApi) HandleGetPlaylistsForPopover(w http.ResponseWriter, r *http.Request) {
profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
if !profileIdCorrect {
w.Write([]byte("🤷‍♂️"))
return
}

songId := r.URL.Query().Get("song-id")
if songId == "" {
w.WriteHeader(http.StatusBadRequest)
return
}

playlists, songsInPlaylists, err := p.service.GetAllMappedForAddPopover(profileId)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Errorln(err)
return
}

playlist.PlaylistsSelector(songId, playlists, songsInPlaylists).
Render(r.Context(), w)
}
10 changes: 2 additions & 8 deletions handlers/pages/pages.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,14 @@ func (p *pagesHandler) HandleSearchResultsPage(w http.ResponseWriter, r *http.Re
log.Info("downloading songs' meta data from search")
_ = p.downloadService.DownloadYoutubeSongsMetadata(results)
}
var songsInPlaylists map[string]bool
var playlists []entities.Playlist
profileId, profileIdCorrect := r.Context().Value(handlers.ProfileIdKey).(uint)
if profileIdCorrect {
playlists, songsInPlaylists, _ = p.playlistsService.GetAllMappedForAddPopover(profileId)
}

if handlers.IsNoLayoutPage(r) {
w.Header().Set("HX-Title", "Results for "+query)
w.Header().Set("HX-Push-Url", "/search?query="+query)
pages.SearchResults(results, playlists, songsInPlaylists).Render(r.Context(), w)
pages.SearchResults(results).Render(r.Context(), w)
return
}
layouts.Default("Results for "+query, pages.SearchResults(results, playlists, songsInPlaylists)).Render(r.Context(), w)
layouts.Default("Results for "+query, pages.SearchResults(results)).Render(r.Context(), w)
}

func (p *pagesHandler) HandleSignupPage(w http.ResponseWriter, r *http.Request) {
Expand Down
35 changes: 29 additions & 6 deletions views/components/playlist/popup.templ
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,26 @@ import (
"dankmuzikk/views/icons"
)

templ PlaylistsPopup(index int, songId string, playlists []entities.Playlist, songsInPlaylists map[string]bool) {
@popup.Popup(fmt.Sprint(index), "Add to playlist", popoverButton(), playlistsSelector(songId, playlists, songsInPlaylists))
templ PlaylistsPopup(index int, songId string) {
@popup.Popup(fmt.Sprint(index), "Add to playlist", popupButton(songId), playlistSelector(songId))
}

templ playlistsSelector(songId string, playlists []entities.Playlist, songsInPlaylists map[string]bool) {
templ playlistSelector(songId string) {
<div
id={ "playlists-" + songId }
class={
"min-w-[350px]", "bg-accent-trans-30", "backdrop-blur-xl", "p-3", "text-secondary",
"rounded-b-[10px]", "rounded-l-[10px]",
}
>
<div id="playlist-loading" class={ "w-full", "flex", "justify-center" }>
<div class={ "loader", "!h-20", "!w-20" }></div>
</div>
<span class={ "text-secondary", "text-xl" }>Loading playlists...</span>
</div>
}

templ PlaylistsSelector(songId string, playlists []entities.Playlist, songsInPlaylists map[string]bool) {
<div
class={
"min-w-[350px]", "bg-accent-trans-30", "backdrop-blur-xl", "p-3", "text-secondary",
Expand Down Expand Up @@ -71,7 +86,15 @@ templ playlistsSelector(songId string, playlists []entities.Playlist, songsInPla
</div>
}

templ popoverButton() {
@icons.AddToPlaytlist()
<span>Save to a playlist</span>
templ popupButton(songId string) {
<div
class={ "flex", "gap-x-2", "items-center", "p-2", "w-full" }
hx-get={ "/api/playlist/all?song-id=" + songId }
hx-swap="outerHTML"
hx-trigger="click"
hx-target={ "#playlists-" + songId }
>
@icons.AddToPlaytlist()
<span>Save to a playlist</span>
</div>
}
2 changes: 1 addition & 1 deletion views/components/popup/popup.templ
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "fmt"
templ Popup(id, title string, button, child templ.Component) {
<button
class={
"popup-trigger", "p-2", "rounded-md", "hover:bg-accent-trans-20",
"popup-trigger", "rounded-md", "hover:bg-accent-trans-20",
"flex", "items-center", "gap-x-2", "w-full",
}
title={ title }
Expand Down
5 changes: 3 additions & 2 deletions views/pages/index.templ
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"dankmuzikk/entities"
"dankmuzikk/views/components/song"
"dankmuzikk/views/components/page"
"dankmuzikk/views/components/playlist"
)

templ Index(recentPlays []entities.Song) {
Expand Down Expand Up @@ -45,8 +46,8 @@ templ historyContent(recentPlays []entities.Song) {
"flex", "flex-col", "gap-5", "lg:mb-5",
}
>
for _, s := range recentPlays {
@song.Song(s, []string{"Played " + s.AddedAt}, nil, entities.Playlist{})
for idx, s := range recentPlays {
@song.Song(s, []string{"Played " + s.AddedAt}, []templ.Component{playlist.PlaylistsPopup(idx, s.YtId)}, entities.Playlist{})
}
<div
class={ "h-[10px]", "mb-[20px]" }
Expand Down
13 changes: 10 additions & 3 deletions views/pages/playlist.templ
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,16 @@ templ playlistContent(pl entities.Playlist) {
"flex", "flex-col", "gap-y-1", "lg:gap-y-4",
}
>
for _, s := range pl.Songs {
for idx, s := range pl.Songs {
if isMobile, ok := ctx.Value("is-mobile").(bool); ok && isMobile {
@song.Song(
s,
[]string{},
[]templ.Component{songOptionsMobile(s), removeSong(s, pl.PublicId)},
[]templ.Component{
songOptionsMobile(s),
removeSong(s, pl.PublicId),
playlist.PlaylistsPopup(idx, s.YtId),
},
pl,
)
} else {
Expand All @@ -81,7 +85,10 @@ templ playlistContent(pl entities.Playlist) {
playedTimes(s.PlayTimes),
"Added on " + s.AddedAt,
},
[]templ.Component{removeSong(s, pl.PublicId)},
[]templ.Component{
removeSong(s, pl.PublicId),
playlist.PlaylistsPopup(idx, s.YtId),
},
pl,
)
}
Expand Down
8 changes: 4 additions & 4 deletions views/pages/search_results.templ
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
"dankmuzikk/views/components/page"
)

templ SearchResults(results []entities.Song, playlists []entities.Playlist, songsInPlaylists map[string]bool) {
templ SearchResults(results []entities.Song) {
if len(results) == 0 {
@page.Container(templ.NopComponent, noResultsHeader())
} else {
@page.Container(searchHeader(), searchContent(results, playlists, songsInPlaylists))
@page.Container(searchHeader(), searchContent(results))
}
}

Expand All @@ -23,15 +23,15 @@ templ searchHeader() {
<h1 class={ "text-secondary", "text-3xl", "lg:text-4xl", "mb-4" }>Search results</h1>
}

templ searchContent(results []entities.Song, playlists []entities.Playlist, songsInPlaylists map[string]bool) {
templ searchContent(results []entities.Song) {
<div
class={
"w-full", "overflow-y-scroll", "min-h-[40vh]", "max-h-[50vh]", "md:max-h-[65vh]",
"flex", "flex-col", "gap-5", "lg:mb-5",
}
>
for idx, res := range results {
@song.Song(res, nil, []templ.Component{playlist.PlaylistsPopup(idx, res.YtId, playlists, songsInPlaylists)}, entities.Playlist{})
@song.Song(res, nil, []templ.Component{playlist.PlaylistsPopup(idx, res.YtId)}, entities.Playlist{})
}
</div>
}

0 comments on commit 795dc5f

Please sign in to comment.