implement embed mode; add MePage
This commit is contained in:
		
							parent
							
								
									cf96264024
								
							
						
					
					
						commit
						27ab4c870d
					
				
							
								
								
									
										19
									
								
								src/Api.ts
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/Api.ts
									
									
									
									
									
								
							| @ -21,7 +21,11 @@ export class Api { | ||||
|     this.baseURL = baseURL; | ||||
|     this.authBaseURL = authBaseURL; | ||||
|     this.publicBaseURL = publicBaseURL; | ||||
|     this.accessToken = accessToken ?? localStorage.getItem("access-token"); | ||||
|     try{ | ||||
|       this.accessToken = accessToken ?? localStorage?.getItem("access-token"); | ||||
|     } catch (e) { | ||||
|       this.accessToken = null; | ||||
|     } | ||||
|     this.axios = axios.create({ baseURL }); | ||||
|     this.axios.interceptors.request.use(({ headers = {}, ...config }) => ({ | ||||
|       ...config, | ||||
| @ -63,11 +67,20 @@ export class Api { | ||||
|     return (await this.axiosPublic.get(`/users/${userId}/info`))?.data; | ||||
|   } | ||||
| 
 | ||||
|   async getSession() { | ||||
|     return (await this.axios.get(`/session`))?.data; | ||||
|   } | ||||
|   async createSession() { | ||||
|     return (await this.axios.post(`/session`))?.data; | ||||
|   } | ||||
|   async deleteSession() { | ||||
|     return (await this.axios.delete(`/session`))?.data; | ||||
|   } | ||||
|   async joinSession(hostId: string) { | ||||
|     return (await this.axios.post(`/session/join`, { hostId }))?.data; | ||||
|   } | ||||
|   async leaveSession(hostId: string) { | ||||
|     return (await this.axios.post(`/session/session`, { hostId }))?.data; | ||||
|   async leaveSession() { | ||||
|     return (await this.axios.post(`/session/leave`))?.data; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,8 @@ | ||||
| <template> | ||||
|   <div> | ||||
|   <div v-if="$route.meta.allowEmbed && $route.query.embed === 'true'" class="p-2"> | ||||
|     <router-view /> | ||||
|   </div> | ||||
|   <div v-else> | ||||
|     <div class="bg-secondary shadow"> | ||||
|       <nav class="navbar px-2 container"> | ||||
|         <router-link class="d-flex btn" to="/"> | ||||
|  | ||||
							
								
								
									
										25
									
								
								src/components/CurrentlyPlayingCompact.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/components/CurrentlyPlayingCompact.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| <script setup lang="ts"> | ||||
| import { defineProps } from "vue"; | ||||
| 
 | ||||
| defineProps({ | ||||
|   currentlyPlaying: Object, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <div class="card"> | ||||
|     <div class="card-body"> | ||||
|       <div class="row"> | ||||
|         <div class="col-3 col-md-2"> | ||||
|           <img :src="currentlyPlaying.item.album.images[0].url" alt="album cover" class="card-img"> | ||||
|         </div> | ||||
|         <div class="col"> | ||||
|           <b>{{ currentlyPlaying?.item.name }}</b> | ||||
|           <div> | ||||
|             {{ currentlyPlaying?.item.artists.map(artist => artist.name).join(', ') }} | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| @ -59,6 +59,7 @@ const update = async (promise: Promise | unknown) => { | ||||
|       : promise); | ||||
|   } catch (e) { | ||||
|     error.value = e; | ||||
|     console.error('PR', e); | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|     showThrobber.value = false; | ||||
|  | ||||
| @ -17,9 +17,21 @@ const routes: Array<RouteRecordRaw> = [ | ||||
|       requireAuth: true, | ||||
|     }, | ||||
|   }, | ||||
|   { | ||||
|     path: "/me", | ||||
|     name: "me", | ||||
|     component: () => | ||||
|       import(/* webpackChunkName: "me" */ "../views/MePage.vue"), | ||||
|     meta: { | ||||
|       requireAuth: false, | ||||
|     }, | ||||
|   }, | ||||
|   { | ||||
|     path: "/user/:id", | ||||
|     name: "user", | ||||
|     meta: { | ||||
|       allowEmbed: true, | ||||
|     }, | ||||
|     component: () => | ||||
|       import(/* webpackChunkName: "user" */ "../views/UserPage.vue"), | ||||
|   }, | ||||
| @ -33,7 +45,7 @@ const routes: Array<RouteRecordRaw> = [ | ||||
|     path: "/auth/callback", | ||||
|     name: "authCallback", | ||||
|     component: () => | ||||
|       import(/* webpackChunkName: "auth" */ "../views/AuthCallbackPage.vue"), | ||||
|       import(/* webpackChunkName: "authCallback" */ "../views/AuthCallbackPage.vue"), | ||||
|   }, | ||||
| ]; | ||||
| 
 | ||||
|  | ||||
| @ -14,7 +14,6 @@ const route = useRoute(); | ||||
|           code: route.query.code, | ||||
|           state: route.query.state, | ||||
|         })"> | ||||
|           {{ $route.query }} | ||||
|           <div class="alert alert-success"> | ||||
|             Authorization completed | ||||
|           </div> | ||||
|  | ||||
							
								
								
									
										39
									
								
								src/views/MePage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/views/MePage.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| <script setup lang="ts"></script> | ||||
| 
 | ||||
| <template> | ||||
|   <div> | ||||
|     <h1>Me</h1> | ||||
|     <PromiseResolver | ||||
|       :promise="$api.getSession()" | ||||
|       v-slot="slot" | ||||
|     > | ||||
|       <div class="card"> | ||||
|         <div class="card-header"> | ||||
|           Your session | ||||
|         </div> | ||||
|         <div class="card-body"> | ||||
|           <p> | ||||
|             {{ slot }} | ||||
|           </p> | ||||
|           <b>Clients</b> | ||||
|         </div> | ||||
|         <div class="card-footer"> | ||||
|           <button | ||||
|             class="btn btn-danger mx-1" | ||||
|             @click="$api.leaveSession().then(() => update($api.getSession()))" | ||||
|           > | ||||
|             leave Session | ||||
|           </button> | ||||
|           <button | ||||
|             class="btn btn-danger mx-1" | ||||
|             @click="$api.deleteSession().then(() => update($api.getSession()))" | ||||
|           > | ||||
|             delete Session | ||||
|           </button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </PromiseResolver> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <style scoped lang="scss"></style> | ||||
| @ -1,6 +1,7 @@ | ||||
| <script setup lang="ts"> | ||||
| import PromiseResolver from "@/components/PromiseResolver.vue"; | ||||
| import CurrentlyPlaying from "@/components/CurrentlyPlaying.vue"; | ||||
| import CurrentlyPlayingCompact from "@/components/CurrentlyPlayingCompact.vue"; | ||||
| import { useRoute } from "vue-router"; | ||||
| import { onBeforeUnmount, ref } from "vue"; | ||||
| import { useApi } from "@/Api"; | ||||
| @ -20,46 +21,66 @@ onBeforeUnmount(() => { | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <h1>User</h1> | ||||
|   <PromiseResolver | ||||
|     :promise="userInfo" | ||||
|     v-slot="{ data: { user, currentlyPlaying } }" | ||||
|     class="row" | ||||
|   > | ||||
|     <div class="col-md-4"> | ||||
|       <div class="card"> | ||||
|         <div class="card-header"> | ||||
|           {{ user.displayName }} | ||||
|         </div> | ||||
|         <div class="card-body"> | ||||
|           <div class="row"> | ||||
|             <div class="col-4"> | ||||
|               <img :src="user.images[0].url" alt="user image" class="card-img"> | ||||
|             </div> | ||||
|             <div class="col"> | ||||
|               <p>{{ user.totalFollowers }} followers on Spotify</p> | ||||
|   <div v-if="$route.query.embed === 'true'"> | ||||
|     <PromiseResolver | ||||
|       :promise="userInfo" | ||||
|       v-slot="{ data: { currentlyPlaying } }" | ||||
|     > | ||||
|       <CurrentlyPlayingCompact | ||||
|         v-if="currentlyPlaying?.item" | ||||
|         :currentlyPlaying="currentlyPlaying" | ||||
|         :compact="true" | ||||
|       /> | ||||
|       <p v-else class="alert alert-info"> | ||||
|         User is not listening to music. | ||||
|       </p> | ||||
|     </PromiseResolver> | ||||
|   </div> | ||||
|   <div v-else> | ||||
|     <h1>User</h1> | ||||
|     <PromiseResolver | ||||
|       :promise="userInfo" | ||||
|       v-slot="{ data: { user, currentlyPlaying } }" | ||||
|       class="row" | ||||
|     > | ||||
|       <div v-if="$route.query.embed === 'true'"> | ||||
| 
 | ||||
|       </div> | ||||
|       <div v-else class="col-md-4"> | ||||
|         <div class="card"> | ||||
|           <div class="card-header"> | ||||
|             {{ user.displayName }} | ||||
|           </div> | ||||
|           <div class="card-body"> | ||||
|             <div class="row"> | ||||
|               <div class="col-4"> | ||||
|                 <img :src="user.images[0].url" alt="user image" class="card-img"> | ||||
|               </div> | ||||
|               <div class="col"> | ||||
|                 <p>{{ user.totalFollowers }} followers on Spotify</p> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <button | ||||
|           v-if="$api.isAuthorized()" | ||||
|           @click="$api.joinSession($route.params.id)" | ||||
|           class="btn btn-primary my-2" | ||||
|         > | ||||
|           Join Session | ||||
|         </button> | ||||
|         <router-link | ||||
|           v-else | ||||
|           to="/auth" | ||||
|           class="btn btn-primary my-2" | ||||
|         > | ||||
|           login with Spotify and join session | ||||
|         </router-link> | ||||
|       </div> | ||||
|       <button | ||||
|         v-if="$api.isAuthorized()" | ||||
|         @click="$api.joinSession($route.params.id)" | ||||
|         class="btn btn-primary my-2" | ||||
|       > | ||||
|         Join Session | ||||
|       </button> | ||||
|       <router-link | ||||
|         v-else | ||||
|         to="/auth" | ||||
|         class="btn btn-primary my-2" | ||||
|       > | ||||
|         login with Spotify and join session | ||||
|       </router-link> | ||||
|     </div> | ||||
|     <div class="col"> | ||||
|       <h2>Currently listening to:</h2> | ||||
|       <CurrentlyPlaying v-if="currentlyPlaying?.item" :currently-playing="currentlyPlaying" /> | ||||
|     </div> | ||||
|   </PromiseResolver> | ||||
|       <div class="col"> | ||||
|         <h2>Currently listening to:</h2> | ||||
|         <CurrentlyPlaying v-if="currentlyPlaying?.item" :currently-playing="currentlyPlaying" /> | ||||
|       </div> | ||||
|     </PromiseResolver> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user