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.baseURL = baseURL; | ||||||
|     this.authBaseURL = authBaseURL; |     this.authBaseURL = authBaseURL; | ||||||
|     this.publicBaseURL = publicBaseURL; |     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 = axios.create({ baseURL }); | ||||||
|     this.axios.interceptors.request.use(({ headers = {}, ...config }) => ({ |     this.axios.interceptors.request.use(({ headers = {}, ...config }) => ({ | ||||||
|       ...config, |       ...config, | ||||||
| @ -63,11 +67,20 @@ export class Api { | |||||||
|     return (await this.axiosPublic.get(`/users/${userId}/info`))?.data; |     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) { |   async joinSession(hostId: string) { | ||||||
|     return (await this.axios.post(`/session/join`, { hostId }))?.data; |     return (await this.axios.post(`/session/join`, { hostId }))?.data; | ||||||
|   } |   } | ||||||
|   async leaveSession(hostId: string) { |   async leaveSession() { | ||||||
|     return (await this.axios.post(`/session/session`, { hostId }))?.data; |     return (await this.axios.post(`/session/leave`))?.data; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,8 @@ | |||||||
| <template> | <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"> |     <div class="bg-secondary shadow"> | ||||||
|       <nav class="navbar px-2 container"> |       <nav class="navbar px-2 container"> | ||||||
|         <router-link class="d-flex btn" to="/"> |         <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); |       : promise); | ||||||
|   } catch (e) { |   } catch (e) { | ||||||
|     error.value = e; |     error.value = e; | ||||||
|  |     console.error('PR', e); | ||||||
|   } finally { |   } finally { | ||||||
|     loading.value = false; |     loading.value = false; | ||||||
|     showThrobber.value = false; |     showThrobber.value = false; | ||||||
|  | |||||||
| @ -17,9 +17,21 @@ const routes: Array<RouteRecordRaw> = [ | |||||||
|       requireAuth: true, |       requireAuth: true, | ||||||
|     }, |     }, | ||||||
|   }, |   }, | ||||||
|  |   { | ||||||
|  |     path: "/me", | ||||||
|  |     name: "me", | ||||||
|  |     component: () => | ||||||
|  |       import(/* webpackChunkName: "me" */ "../views/MePage.vue"), | ||||||
|  |     meta: { | ||||||
|  |       requireAuth: false, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|   { |   { | ||||||
|     path: "/user/:id", |     path: "/user/:id", | ||||||
|     name: "user", |     name: "user", | ||||||
|  |     meta: { | ||||||
|  |       allowEmbed: true, | ||||||
|  |     }, | ||||||
|     component: () => |     component: () => | ||||||
|       import(/* webpackChunkName: "user" */ "../views/UserPage.vue"), |       import(/* webpackChunkName: "user" */ "../views/UserPage.vue"), | ||||||
|   }, |   }, | ||||||
| @ -33,7 +45,7 @@ const routes: Array<RouteRecordRaw> = [ | |||||||
|     path: "/auth/callback", |     path: "/auth/callback", | ||||||
|     name: "authCallback", |     name: "authCallback", | ||||||
|     component: () => |     component: () => | ||||||
|       import(/* webpackChunkName: "auth" */ "../views/AuthCallbackPage.vue"), |       import(/* webpackChunkName: "authCallback" */ "../views/AuthCallbackPage.vue"), | ||||||
|   }, |   }, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,7 +14,6 @@ const route = useRoute(); | |||||||
|           code: route.query.code, |           code: route.query.code, | ||||||
|           state: route.query.state, |           state: route.query.state, | ||||||
|         })"> |         })"> | ||||||
|           {{ $route.query }} |  | ||||||
|           <div class="alert alert-success"> |           <div class="alert alert-success"> | ||||||
|             Authorization completed |             Authorization completed | ||||||
|           </div> |           </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"> | <script setup lang="ts"> | ||||||
| import PromiseResolver from "@/components/PromiseResolver.vue"; | import PromiseResolver from "@/components/PromiseResolver.vue"; | ||||||
| import CurrentlyPlaying from "@/components/CurrentlyPlaying.vue"; | import CurrentlyPlaying from "@/components/CurrentlyPlaying.vue"; | ||||||
|  | import CurrentlyPlayingCompact from "@/components/CurrentlyPlayingCompact.vue"; | ||||||
| import { useRoute } from "vue-router"; | import { useRoute } from "vue-router"; | ||||||
| import { onBeforeUnmount, ref } from "vue"; | import { onBeforeUnmount, ref } from "vue"; | ||||||
| import { useApi } from "@/Api"; | import { useApi } from "@/Api"; | ||||||
| @ -20,13 +21,32 @@ onBeforeUnmount(() => { | |||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|  |   <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> |     <h1>User</h1> | ||||||
|     <PromiseResolver |     <PromiseResolver | ||||||
|       :promise="userInfo" |       :promise="userInfo" | ||||||
|       v-slot="{ data: { user, currentlyPlaying } }" |       v-slot="{ data: { user, currentlyPlaying } }" | ||||||
|       class="row" |       class="row" | ||||||
|     > |     > | ||||||
|     <div class="col-md-4"> |       <div v-if="$route.query.embed === 'true'"> | ||||||
|  | 
 | ||||||
|  |       </div> | ||||||
|  |       <div v-else class="col-md-4"> | ||||||
|         <div class="card"> |         <div class="card"> | ||||||
|           <div class="card-header"> |           <div class="card-header"> | ||||||
|             {{ user.displayName }} |             {{ user.displayName }} | ||||||
| @ -62,4 +82,5 @@ onBeforeUnmount(() => { | |||||||
|         <CurrentlyPlaying v-if="currentlyPlaying?.item" :currently-playing="currentlyPlaying" /> |         <CurrentlyPlaying v-if="currentlyPlaying?.item" :currently-playing="currentlyPlaying" /> | ||||||
|       </div> |       </div> | ||||||
|     </PromiseResolver> |     </PromiseResolver> | ||||||
|  |   </div> | ||||||
| </template> | </template> | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user