add radio support
This commit is contained in:
		
							parent
							
								
									4fca9f417b
								
							
						
					
					
						commit
						c3a5136f0f
					
				| @ -38,6 +38,10 @@ | |||||||
|         <Icon icon="star" /> Starred |         <Icon icon="star" /> Starred | ||||||
|       </router-link> |       </router-link> | ||||||
| 
 | 
 | ||||||
|  |       <router-link class="nav-link" :to="{name: 'radio'}"> | ||||||
|  |         <Icon icon="broadcast" /> Radio | ||||||
|  |       </router-link> | ||||||
|  | 
 | ||||||
|       <PlaylistNav /> |       <PlaylistNav /> | ||||||
|     </nav> |     </nav> | ||||||
|   </div> |   </div> | ||||||
|  | |||||||
							
								
								
									
										66
									
								
								src/library/radio/RadioStations.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/library/radio/RadioStations.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | |||||||
|  | <template> | ||||||
|  |   <div v-if="items"> | ||||||
|  |     <h1>Radio</h1> | ||||||
|  |     <table class="table table-hover table-borderless"> | ||||||
|  |       <thead> | ||||||
|  |         <tr> | ||||||
|  |           <th class="text-left"> | ||||||
|  |             Title | ||||||
|  |           </th> | ||||||
|  |           <th class="text-right"> | ||||||
|  |             Actions | ||||||
|  |           </th> | ||||||
|  |         </tr> | ||||||
|  |       </thead> | ||||||
|  |       <tbody> | ||||||
|  |         <tr v-for="(item, index) in items" :key="index" | ||||||
|  |             :class="{'active': item.id === playingTrackId}"> | ||||||
|  |           <td @click="play(index)"> | ||||||
|  |             {{ item.title }} | ||||||
|  |             <div> | ||||||
|  |               <small class="text-muted"> | ||||||
|  |                 {{ item.description }} | ||||||
|  |               </small> | ||||||
|  |             </div> | ||||||
|  |           </td> | ||||||
|  |           <td class="text-right"> | ||||||
|  |             <TrackContextMenu :track="item" /> | ||||||
|  |           </td> | ||||||
|  |         </tr> | ||||||
|  |       </tbody> | ||||||
|  |     </table> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  | <script lang="ts"> | ||||||
|  |   import Vue from 'vue' | ||||||
|  |   import TrackContextMenu from '@/library/TrackContextMenu.vue' | ||||||
|  |   import { RadioStation } from '@/shared/api' | ||||||
|  |   import { mapGetters } from 'vuex' | ||||||
|  | 
 | ||||||
|  |   export default Vue.extend({ | ||||||
|  |     components: { | ||||||
|  |       TrackContextMenu, | ||||||
|  |     }, | ||||||
|  |     data() { | ||||||
|  |       return { | ||||||
|  |         items: [] as RadioStation[], | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     computed: { | ||||||
|  |       ...mapGetters({ | ||||||
|  |         playingTrackId: 'player/trackId', | ||||||
|  |       }), | ||||||
|  |     }, | ||||||
|  |     async created() { | ||||||
|  |       this.items = await this.$api.getRadioStations() | ||||||
|  |     }, | ||||||
|  |     methods: { | ||||||
|  |       play(index: number) { | ||||||
|  |         if (this.items[index].id === this.playingTrackId) { | ||||||
|  |           return this.$store.dispatch('player/playPause') | ||||||
|  |         } | ||||||
|  |         return this.$store.dispatch('player/playQueue', { index, queue: this.items }) | ||||||
|  |       }, | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | </script> | ||||||
| @ -52,6 +52,13 @@ export interface SearchResult { | |||||||
|   tracks: Track[] |   tracks: Track[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export interface RadioStation { | ||||||
|  |   id: string | ||||||
|  |   title: string | ||||||
|  |   description: string | ||||||
|  |   url: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export class API { | export class API { | ||||||
|   readonly http: AxiosInstance; |   readonly http: AxiosInstance; | ||||||
|   readonly get: (path: string, params?: any) => Promise<any>; |   readonly get: (path: string, params?: any) => Promise<any>; | ||||||
| @ -274,6 +281,48 @@ export class API { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   async getRadioStations(): Promise<RadioStation[]> { | ||||||
|  |     const response = await this.get('rest/getInternetRadioStations') | ||||||
|  |     return (response?.internetRadioStations?.internetRadioStation || []) | ||||||
|  |       .map(this.normalizeRadioStation, this) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async addRadioStation(title: string, url: string): Promise<RadioStation> { | ||||||
|  |     const params = { | ||||||
|  |       name: title, | ||||||
|  |       streamUrl: url, | ||||||
|  |     } | ||||||
|  |     return this | ||||||
|  |       .get('rest/createInternetRadioStation', params) | ||||||
|  |       .then(this.normalizeRadioStation) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async updateRadioStation(item: RadioStation): Promise<RadioStation> { | ||||||
|  |     const params = { | ||||||
|  |       id: item.id, | ||||||
|  |       name: item.title, | ||||||
|  |       streamUrl: item.url, | ||||||
|  |     } | ||||||
|  |     return this | ||||||
|  |       .get('rest/updateInternetRadioStation', params) | ||||||
|  |       .then(this.normalizeRadioStation) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async deleteRadioStation(id: string): Promise<void> { | ||||||
|  |     return this.get('rest/deleteInternetRadioStation', { id }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private normalizeRadioStation(item: any): Track & RadioStation { | ||||||
|  |     return { | ||||||
|  |       id: `radio-${item.id}`, | ||||||
|  |       title: item.name, | ||||||
|  |       description: item.homePageUrl, | ||||||
|  |       url: item.streamUrl, | ||||||
|  |       duration: 0, | ||||||
|  |       starred: false, | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   private normalizeTrack(item: any): Track { |   private normalizeTrack(item: any): Track { | ||||||
|     return { |     return { | ||||||
|       id: item.id, |       id: item.id, | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ | |||||||
|   import Vue from 'vue' |   import Vue from 'vue' | ||||||
|   import { |   import { | ||||||
|     BIcon, |     BIcon, | ||||||
|  |     BIconBroadcast, | ||||||
|     BIconCardText, |     BIconCardText, | ||||||
|     BIconChevronCompactRight, |     BIconChevronCompactRight, | ||||||
|     BIconMusicNoteList, |     BIconMusicNoteList, | ||||||
| @ -28,6 +29,7 @@ | |||||||
|   export default Vue.extend({ |   export default Vue.extend({ | ||||||
|     components: { |     components: { | ||||||
|       BIcon, |       BIcon, | ||||||
|  |       BIconBroadcast, | ||||||
|       BIconCardText, |       BIconCardText, | ||||||
|       BIconChevronCompactRight, |       BIconChevronCompactRight, | ||||||
|       BIconMusicNoteList, |       BIconMusicNoteList, | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ import RandomSongs from '@/playlist/RandomSongs.vue' | |||||||
| import GenreDetails from '@/library/genre/GenreDetails.vue' | import GenreDetails from '@/library/genre/GenreDetails.vue' | ||||||
| import GenreLibrary from '@/library/genre/GenreLibrary.vue' | import GenreLibrary from '@/library/genre/GenreLibrary.vue' | ||||||
| import Starred from '@/library/starred/Starred.vue' | import Starred from '@/library/starred/Starred.vue' | ||||||
|  | import RadioStations from '@/library/radio/RadioStations.vue' | ||||||
| import Playlist from '@/playlist/Playlist.vue' | import Playlist from '@/playlist/Playlist.vue' | ||||||
| import PlaylistList from '@/playlist/PlaylistList.vue' | import PlaylistList from '@/playlist/PlaylistList.vue' | ||||||
| import SearchResult from '@/search/SearchResult.vue' | import SearchResult from '@/search/SearchResult.vue' | ||||||
| @ -78,6 +79,11 @@ export function setupRouter(auth: AuthService) { | |||||||
|         path: '/starred', |         path: '/starred', | ||||||
|         component: Starred, |         component: Starred, | ||||||
|       }, |       }, | ||||||
|  |       { | ||||||
|  |         name: 'radio', | ||||||
|  |         path: '/radio', | ||||||
|  |         component: RadioStations, | ||||||
|  |       }, | ||||||
|       { |       { | ||||||
|         name: 'playlists', |         name: 'playlists', | ||||||
|         path: '/playlists', |         path: '/playlists', | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user