@christianriedl/media 1.0.302 → 1.0.303

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/iMedia.d.ts CHANGED
@@ -317,15 +317,33 @@ export interface IMediaService {
317
317
  getCloudUrl(folder: string, name: string): Promise<string>;
318
318
  getStatus(): Promise<Dictionary<boolean | number | string> | null>;
319
319
  }
320
- export interface IRssFeed {
320
+ export interface IRssItem {
321
321
  title: string;
322
- description: string;
322
+ description?: string;
323
323
  link: string;
324
- copyright?: string;
325
- items?: IRssFeed[];
326
324
  mediaType?: string;
327
325
  duration?: number;
328
326
  }
327
+ export declare enum EFeedType {
328
+ Unknown = 0,
329
+ Movie = 1,
330
+ Podcast = 2,
331
+ Music = 3,
332
+ MusicVideo = 4,
333
+ Audiobook = 5,
334
+ ShortFilm = 6,
335
+ TvShow = 7,
336
+ Ebook = 8
337
+ }
338
+ export interface IRssFeed extends IRssItem {
339
+ rssUrl: string;
340
+ genre?: string;
341
+ country?: string;
342
+ copyright?: string;
343
+ owner?: string;
344
+ imageUrl?: string;
345
+ items?: IRssItem[];
346
+ }
329
347
  export declare const getPlaylistSymbol: InjectionKey<() => IPlaylistService>;
330
348
  export declare enum EPlaylistCommand {
331
349
  None = 0,
@@ -346,11 +364,8 @@ export interface IPlaylistState {
346
364
  export interface IPlaylistService {
347
365
  log: ILogger;
348
366
  soundbarOn: boolean;
349
- getTitles(): Promise<string[]>;
350
- getFeed(title: string): Promise<IRssFeed | null>;
351
- getFeeds(): Promise<IRssFeed[]>;
352
- addFeed(url: string, save: boolean): Promise<IRssFeed | null>;
353
- deleteFeed(title: string): Promise<boolean>;
367
+ searchFeeds(query: Dictionary<any>, limit?: number): Promise<IRssFeed[]>;
368
+ getFeed(rssUrl: string): Promise<IRssFeed | null>;
354
369
  play(url: string): Promise<boolean>;
355
370
  playList(urls: string[], clear: boolean, index?: number): Promise<boolean>;
356
371
  playCommand(cmd: EPlaylistCommand): Promise<boolean>;
package/dist/iMedia.js CHANGED
@@ -121,6 +121,18 @@ export var EPictureFlags;
121
121
  EPictureFlags[EPictureFlags["Mask"] = 240] = "Mask";
122
122
  })(EPictureFlags || (EPictureFlags = {}));
123
123
  export const getMediaSymbol = Symbol("get-media");
124
+ export var EFeedType;
125
+ (function (EFeedType) {
126
+ EFeedType[EFeedType["Unknown"] = 0] = "Unknown";
127
+ EFeedType[EFeedType["Movie"] = 1] = "Movie";
128
+ EFeedType[EFeedType["Podcast"] = 2] = "Podcast";
129
+ EFeedType[EFeedType["Music"] = 3] = "Music";
130
+ EFeedType[EFeedType["MusicVideo"] = 4] = "MusicVideo";
131
+ EFeedType[EFeedType["Audiobook"] = 5] = "Audiobook";
132
+ EFeedType[EFeedType["ShortFilm"] = 6] = "ShortFilm";
133
+ EFeedType[EFeedType["TvShow"] = 7] = "TvShow";
134
+ EFeedType[EFeedType["Ebook"] = 8] = "Ebook";
135
+ })(EFeedType || (EFeedType = {}));
124
136
  export const getPlaylistSymbol = Symbol("get-playlist");
125
137
  export var EPlaylistCommand;
126
138
  (function (EPlaylistCommand) {
@@ -1 +1 @@
1
- {"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { IRest } from '@christianriedl/rest';
2
- import { ILogger } from '@christianriedl/utils';
2
+ import { ILogger, Dictionary } from '@christianriedl/utils';
3
3
  import { IRssFeed, EPlaylistCommand, IPlaylistState, IPlaylistService } from "./iMedia";
4
4
  export declare class PlaylistService implements IPlaylistService {
5
5
  rest: IRest;
@@ -7,13 +7,10 @@ export declare class PlaylistService implements IPlaylistService {
7
7
  log: ILogger;
8
8
  soundbarOn: boolean;
9
9
  setSoundbar: (name: string, value: string) => Promise<boolean>;
10
- getSoundbarValue: (name: string) => string;
11
- constructor(rest: IRest, log: ILogger, getSoundbarValue: (name: string) => string, setSoundbar: (name: string, value: string) => Promise<boolean>);
12
- getTitles(): Promise<string[]>;
13
- getFeed(title: string): Promise<IRssFeed | null>;
14
- getFeeds(): Promise<IRssFeed[]>;
15
- addFeed(url: string, save: boolean): Promise<IRssFeed | null>;
16
- deleteFeed(title: string): Promise<boolean>;
10
+ getSoundbarValue: (name: string) => any;
11
+ constructor(rest: IRest, log: ILogger, getSoundbarValue: (name: string) => any, setSoundbar: (name: string, value: string) => Promise<boolean>);
12
+ searchFeeds(query: Dictionary<any>, limit?: number): Promise<IRssFeed[]>;
13
+ getFeed(rssUrl: string): Promise<IRssFeed | null>;
17
14
  play(url: string): Promise<boolean>;
18
15
  playList(urls: string[], clear: boolean, index?: number): Promise<boolean>;
19
16
  playCommand(cmd: EPlaylistCommand): Promise<boolean>;
@@ -15,26 +15,37 @@ export class PlaylistService {
15
15
  this.setSoundbar = setSoundbar;
16
16
  this.soundbarOn = false;
17
17
  }
18
- async getTitles() {
19
- const res = await this.rest.getData('apiplaylist/title');
18
+ async searchFeeds(query, limit) {
19
+ query['limit'] = limit ?? 50;
20
+ const res = await this.rest.getData('apiplaylist/feed/search', query);
20
21
  return res.ok ? res.result : [];
21
22
  }
22
- async getFeed(title) {
23
- const res = await this.rest.getData('apiplaylist/feed', { title: title });
23
+ async getFeed(rssUrl) {
24
+ const res = await this.rest.getData('apiplaylist/feed', { rssUrl: rssUrl });
24
25
  return res.ok ? res.result : null;
25
26
  }
26
- async getFeeds() {
27
- const res = await this.rest.getData('apiplaylist/feed');
28
- return res.ok ? res.result : [];
27
+ /*
28
+ async getTitles(): Promise<string[]> {
29
+ const res = await this.rest.getData<string[]>('apiplaylist/title');
30
+ return res.ok ? res.result as string[] : [];
29
31
  }
30
- async addFeed(url, save) {
31
- const res = await this.rest.postDataEx(`apiplaylist/feed?url=${encodeURIComponent(url)}&save=${save}`);
32
- return res.ok ? res.result.result : null;
32
+ async getFeed(title: string): Promise<IRssFeed|null> {
33
+ const res = await this.rest.getData<IRssFeed>('apiplaylist/feed', { title: title });
34
+ return res.ok ? res.result as IRssFeed : null;
33
35
  }
34
- async deleteFeed(title) {
35
- const res = await this.rest.deleteData(`apiplaylist/feed?title=${encodeURIComponent(title)}`);
36
- return res.ok ? res.result : false;
36
+ async getFeeds(): Promise<IRssFeed[]> {
37
+ const res = await this.rest.getData<IRssFeed[]>('apiplaylist/feed');
38
+ return res.ok ? res.result as IRssFeed[] : [];
39
+ }
40
+ async addFeed(url: string, save: boolean): Promise<IRssFeed|null> {
41
+ const res = await this.rest.postDataEx<boolean,IRssFeed>(`apiplaylist/feed?url=${encodeURIComponent(url)}&save=${save}`);
42
+ return res.ok ? (res.result as IValueResult<IRssFeed>).result : null;
43
+ }
44
+ async deleteFeed(title: string): Promise<boolean> {
45
+ const res = await this.rest.deleteData<any, boolean>(`apiplaylist/feed?title=${encodeURIComponent(title)}`);
46
+ return res.ok ? res.result as boolean : false;
37
47
  }
48
+ */
38
49
  async play(url) {
39
50
  this.soundbarOn = await this.ensureOn();
40
51
  if (!this.soundbarOn)
@@ -67,9 +78,9 @@ export class PlaylistService {
67
78
  async ensureOn() {
68
79
  let i = 0;
69
80
  for (i = 0; i < 5; i++) {
70
- if (this.getSoundbarValue('ON') === 'ON')
81
+ if (this.getSoundbarValue('On') === true)
71
82
  break;
72
- const result = await this.setSoundbar('POWER', 'on');
83
+ const result = await this.setSoundbar('POWERON', '1');
73
84
  await Helper.delay(1000);
74
85
  }
75
86
  if (i >= 5)
@@ -1 +1 @@
1
- {"version":3,"file":"playlistService.js","sourceRoot":"","sources":["../src/playlistService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"playlistService.js","sourceRoot":"","sources":["../src/playlistService.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/media",
3
- "version": "1.0.302",
3
+ "version": "1.0.303",
4
4
  "description": "RIC media interfaces",
5
5
 
6
6
  "main": "dist/index.js",
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, ref, reactive, computed, onMounted, onUnmounted, nextTick, watch, StyleValue } from 'vue';
3
3
  import type { ComponentPublicInstance } from 'vue';
4
- import { useRouter } from 'vue-router';
5
- import { IAppState, EScope, EDevice, appStateSymbol, appConfigSymbol } from '@christianriedl/utils';
6
- import { getPlaylistSymbol, IPlaylistService, IPlaylistState, IRssFeed, EPlaylistCommand } from '@christianriedl/media';
4
+ import { useRouter, useRoute } from 'vue-router';
5
+ import { IAppState, EScope, EDevice, Helper, appStateSymbol, appConfigSymbol, Dictionary } from '@christianriedl/utils';
6
+ import { getPlaylistSymbol, IPlaylistService, IPlaylistState, IRssFeed, IRssItem, EPlaylistCommand, EFeedType } from '@christianriedl/media';
7
7
 
8
8
  const appState = inject(appStateSymbol)!;
9
9
  const getPlaylistService = inject(getPlaylistSymbol)!;
@@ -11,31 +11,45 @@
11
11
  const heightStyle = computed<StyleValue>(() => { return { height: appState.bodyHeight.value + 'px', overflowY: 'auto' } });
12
12
  const isMobile = appState.isMobile && (appState.device != EDevice.iPad);
13
13
  const router = useRouter();
14
+ const route = useRoute();
14
15
  const feeds: IRssFeed[] = reactive([]);
15
- const selected = ref<IRssFeed|null>(null);
16
+ const items: IRssItem[] = reactive([]);
17
+ const selectedItem = ref<IRssItem|null>(null);
18
+ const selectedFeed = ref<IRssFeed|null>(null);
16
19
  const status = ref<IPlaylistState|null>(null);
17
20
  const audio = ref<HTMLAudioElement | null>(null);
18
21
  const listhead = ref<ComponentPublicInstance | null>(null);
19
22
  const listHeight = ref(0);
20
23
  const playerNames = ['Local', 'Soundbar'];
24
+ const backVisible = computed(() => !!route.query?.feed);
21
25
  const currentPlayer = ref<string>(playerNames[0]);
22
26
  const playLocal = computed(() => currentPlayer.value == 'Local');
23
27
  const playIndex = ref(-1);
24
28
  const itemIndex = ref(0);
25
- const playingFeed = ref<IRssFeed|null>(null);
29
+ const playingItem = ref<IRssItem|null>(null);
26
30
  const position = ref(0);
27
31
  const positionLength = ref(0);
28
32
  const volume = ref(0);
29
33
  const paused = ref(false);
34
+ const search = ref(true);
30
35
  let statusTimer = 0;
36
+ const positionText = computed(() => {
37
+ if (playingItem.value?.duration)
38
+ return toTime(position.value) + '/' + toTime(playingItem.value.duration);
39
+ else
40
+ return toTime(position.value);
41
+ });
31
42
 
32
-
43
+ const feedTypes = Helper.getEnumOptions(EFeedType);
44
+ const feedType = ref<EFeedType>(0);
45
+ const countries = ["", "AT", "DE", "US"];
46
+ const country = ref("");
47
+ const query = ref("");
48
+ const limit = ref(50);
33
49
 
34
50
  onMounted(async () => {
35
- playlistService.log.info('OnlineBroadcast created');
36
- const f = await playlistService.getFeeds();
37
- feeds.splice(0, feeds.length, ...f);
38
- computeListHeight();
51
+ playlistService.log.info('OnlinePodcastsPage created');
52
+ await start();
39
53
  });
40
54
  onUnmounted(() => {
41
55
  if (statusTimer > 0) {
@@ -43,6 +57,23 @@
43
57
  statusTimer = 0;
44
58
  }
45
59
  });
60
+ async function start() {
61
+ if (route.query?.rssUrl) {
62
+ const rssUrl = decodeURIComponent(route.query.rssUrl.toString());
63
+ const f = await playlistService.getFeed(rssUrl);
64
+ if (f && f.items) {
65
+ selectedFeed.value = f;
66
+ items.splice(0, items.length, ...f.items);
67
+ search.value = false;
68
+ }
69
+ }
70
+ else {
71
+ search.value = true;
72
+ }
73
+ computeListHeight();
74
+ }
75
+ watch(appState.bodyHeight, () => computeListHeight());
76
+ watch(() => route.query, () => start());
46
77
 
47
78
  function computeListHeight() {
48
79
  nextTick(() => {
@@ -53,43 +84,66 @@
53
84
  listHeight.value = height;
54
85
  })
55
86
  }
87
+
88
+ async function onSearch() {
89
+ const dict: Dictionary<any> = {};
90
+ if (feedType.value != EFeedType.None)
91
+ dict["media"] = EFeedType[feedType];
92
+ if (country.value != "")
93
+ dict["country"] = country.value;;
94
+ dict["query"] = query.value;
95
+ const fds = await playlistService.searchFeeds(dict, limit.value);;
96
+ feeds.splice (0, feeds.length, ...fds);
97
+ }
56
98
  async function play() {
57
99
  if (playLocal.value) {
58
- audio.value!.src = selected.value!.link;
100
+ audio.value!.src = selectedItem.value!.link;
59
101
  audio.value!.load();
60
102
  audio.value!.play().then(() => {
61
- playlistService.log.trace(`play local ${selected.value!.title}`)
103
+ playlistService.log.trace(`play local ${selectedItem.value!.title}`)
62
104
  });
105
+ playingItem.value = selectedItem.value;
63
106
  }
64
107
  else {
65
- const rc = await playlistService.play(selected.value!.link);
108
+ const rc = await playlistService.play(selectedItem.value!.link);
66
109
  if (!rc)
67
110
  return;
111
+ playingItem.value = selectedItem.value;
68
112
  await getStatus();
69
- playlistService.log.trace(`play remote ${selected.value!.title}`)
113
+ playlistService.log.trace(`play remote ${selectedItem.value!.title}`)
70
114
  }
71
- playingFeed.value = selected.value;
72
- itemIndex.value = playIndex.value = feeds.findIndex((f) => f.link == selected.value!.link);
115
+ itemIndex.value = playIndex.value = feeds.findIndex((f) => f.link == selectedItem.value!.link);
73
116
  }
74
- function listItem(item: IRssFeed) {
75
- selected.value = item;
76
- computeListHeight();
117
+ function listFeed(feed: IRssFeed) {{
118
+ router.push ({path: 'onlinePodcasts', query: { rssUrl: feed.rssUrl }});
119
+ }
120
+
121
+ function listItem(item: IRssItem) {
122
+ selectedItem.value = item;
123
+ play();
124
+ computeListHeight();
77
125
  }
78
126
  function listBack() {
79
127
  router.back();
80
128
  }
81
129
  async function getStatus() {
82
- const status = await playlistService.getState();
83
- status.value = status;
84
- setPosition(status.position.toNumber());
85
- statusTimer = setTimeout(async () => getStatus(), 1000);
130
+ const state = await playlistService.getState();
131
+ status.value = state;
132
+ if (state)
133
+ setPosition(Number(state.position));
134
+ statusTimer = window.setTimeout(async () => getStatus(), 1000);
86
135
  }
87
136
 
88
137
  function toSubTitle(f: IRssFeed): string {
89
- if (!f.duration)
138
+ if (!f || !f.duration)
90
139
  return "";
91
- let s = f.duration;
92
- var r = "";
140
+ return toTime(f.duration);
141
+ }
142
+
143
+ function toTime(s: number): string {
144
+ if (!s)
145
+ return "";
146
+ let r = "";
93
147
  s = Math.floor(s);
94
148
  if (s >= 3600) {
95
149
  r += Math.floor(s / 3600).toString() + ":"; s = s % 3600;
@@ -116,8 +170,8 @@
116
170
  }
117
171
  function setPosition(value: number) {
118
172
  position.value = value;
119
- if (playingFeed.value!.duration)
120
- positionLength.value = position.value * 100 / playingFeed.value!.duration;
173
+ if (playingItem.value?.duration)
174
+ positionLength.value = position.value * 100 / playingItem.value!.duration;
121
175
  else
122
176
  positionLength.value = 0;
123
177
  }
@@ -127,7 +181,7 @@
127
181
  statusTimer = 0;
128
182
  }
129
183
  if (!playLocal.value) {
130
- statusTimer = setTimeout(() => getStatus(), 1000);
184
+ statusTimer = window.setTimeout(() => getStatus(), 1000);
131
185
  }
132
186
  }
133
187
  function playpause() {
@@ -154,13 +208,13 @@
154
208
  function previous() {
155
209
  if (playIndex.value <= 0)
156
210
  return;
157
- selected.value = feeds[playIndex.value - 1];
211
+ selectedItem.value = feeds[playIndex.value - 1];
158
212
  play();
159
213
  }
160
214
  function next() {
161
215
  if (playIndex.value >= feeds.length - 1)
162
216
  return;
163
- selected.value = feeds[playIndex.value + 1];
217
+ selectedItem.value = feeds[playIndex.value + 1];
164
218
  play();
165
219
  }
166
220
  function changeVolume() {
@@ -170,20 +224,118 @@
170
224
 
171
225
  <template>
172
226
  <v-card ref="listhead" class="bg-media_head">
227
+ <audio ref="audio" preload="none" @ended="onEnded" @timeupdate="onTimeUpdate">
228
+ </audio>
229
+ <v-container v-if="search" fluid>
230
+ <v-row class="align-center">
231
+ <v-col cols="1"></v-col>
232
+ <v-col cols="2">Type</v-col>
233
+ <v-col cols="1">Country</v-col>
234
+ <v-col cols="6">Query</v-col>
235
+ <v-col cols="1">Limit</v-col>
236
+ </v-row>
237
+ <v-row class="align-center">
238
+ <v-col cols="1">
239
+ <v-btn v-if="backVisible" icon="$back" class="bg-media_head" variant="tonal" @click="listBack">
240
+ </v-btn>
241
+ </v-col>
242
+ <v-col cols="2">
243
+ <v-select density="compact" v-model="feedType"
244
+ :items="feedTypes"
245
+ persistent-hint hide-details single-line>
246
+ </v-select>
247
+ </v-col>
248
+ <v-col cols="1">
249
+ <v-combobox density="compact" v-model="country"
250
+ :items="countries"
251
+ persistent-hint hide-details single-line>
252
+ </v-combobox>
253
+ </v-col>
254
+ <v-col cols="6">
255
+ <v-text-field v-model="query" hide-details density="compact"></v-text-field>
256
+ </v-col>
257
+ <v-col cols="1">
258
+ <v-text-field v-model="limit" hide-details type="number" density="compact"></v-text-field>
259
+ </v-col>
260
+ <v-col cols="1">
261
+ <v-btn icon="$search" class="bg-media_head" variant="tonal" @click="onSearch">
262
+ </v-btn>
263
+ </v-col>
264
+ </v-row>
265
+ </v-container>
266
+ <v-container v-else fluid>
267
+ <v-row class="align-center">
268
+ <v-col cols="1">
269
+ <v-btn v-if="backVisible" icon="$back" class="bg-media_head" variant="tonal" @click="listBack">
270
+ </v-btn>
271
+ </v-col>
272
+ <v-col cols="1">
273
+ <v-img :src="selectedFeed.imageUrl"></v-img>
274
+ </v-col>
275
+ <v-col cols="1">{{selectedFeed.country}}</v-col>
276
+ <v-col cols="2">{{selectedFeed.genre}}</v-col>
277
+ <v-col cols="2">{{selectedFeed.owner}}</v-col>
278
+ <v-col cols="5">{{selectedFeed.title}}</v-col>
279
+ <v-col cols="2">
280
+ <v-select v-model="currentPlayer" density="compact" :items="playerNames" persistent-hint
281
+ @update:modelValue="onPlayerChange" hide-details single-line>
282
+ </v-select>
283
+ </v-col>
284
+ </v-row>
285
+ <v-row v-if="playingItem" class="align-center">
286
+ <v-col cols="4">
287
+ <v-btn :icon="paused ? '$play' : '$pause'" @click="playpause">
288
+ <v-btn icon="$prev" @click="previous">
289
+ <v-btn icon="$next" @click="next">
290
+ </v-col>
291
+ <v-col cols ="8">
292
+ <v-slider v-if="!playLocal" style="width:30%" color="red" track-color="blue" track-fill-color="red" v-model="volume" hide-details density="compact"
293
+ min="0" max="100" step="5" @update:modelValue="changeVolume">
294
+ </v-slider>
295
+ </v-col>
296
+ </v-row>
297
+ <v-row v-if="playingItem">
298
+ <v-col cols="12">
299
+ <v-progress-linear v-model="positionLength" color="blue" height="25"><strong>{{positionText}}</strong></v-progress-linear>
300
+ </v-col>
301
+ </v-row>
302
+ </v-container>
303
+ </v-card>
304
+ <v-card :height="listHeight" density="compact" class="overflow-y-auto bg-media">
305
+ <v-container v-if="search" fluid>
306
+ <v-row v-for="(feed,index) in feeds" :key="feed.rssUrl" @click="listFeed(feed)">
307
+ <v-col cols="1">{{feed.country}}</v-col>
308
+ <v-col cols="2">{{feed.genre}}</v-col>
309
+ <v-col cols="2">{{feed.owner}}</v-col>
310
+ <v-col cols="5">{{feed.title}}</v-col>
311
+ </v-row>
312
+ </v-container>
313
+ <v-container v-else>
314
+ <v-row v-for="(item,index) in items" :key="item.rssUrl" @click="listItem(item)">
315
+ <v-col cols="1">{{item.title}}</v-col>
316
+ <v-col cols="2">{{toTime(item.duration)}}</v-col>
317
+ <v-col cols="2">{{feed.owner}}</v-col>
318
+ <v-col cols="5">{{item.title}}</v-col>
319
+ </v-row>
320
+ </v-container>
321
+ </v-card>
322
+
323
+ <!--
324
+ <v-card class="bg-media_head">
173
325
  <audio ref="audio" preload="none" @ended="onEnded" @timeupdate="onTimeUpdate">
174
326
  </audio>
175
327
  <v-list-item lines="three">
176
328
  <v-list-item-content>
177
- <v-list-item-title text-h6>{{selected!.title}}</v-list-item-title>
329
+ <v-list-item-title text-h6>{{selected?.title}}</v-list-item-title>
178
330
  <v-list-item-subtitle>{{toSubTitle(selected!)}}</v-list-item-subtitle>
179
331
  </v-list-item-content>
180
332
  <template v-slot:append>
181
- <v-select v-model="currentPlayer"
333
+ <v-select v-model="currentPlayer" density="compact"
182
334
  :items="playerNames"
183
335
  persistent-hint
184
336
  @update:modelValue="onPlayerChange"
185
337
  hide-details single-line>
186
- </v-select>!
338
+ </v-select>
187
339
  </template>
188
340
  </v-list-item>
189
341
  <v-card-actions>
@@ -209,11 +361,12 @@
209
361
  <v-card :height="listHeight" density="compact" class="overflow-y-auto bg-media">
210
362
  <v-list lines="two" class="bg-media">
211
363
  <v-list-item-group v-model="itemIndex">
212
- <v-list-item v-for="(item,index) in items" :key="item.title" density="compact" :title="item.title" :subtitle="toSubTitle(item)"
213
- active-color="blue" :active="index == playIndex" @click="listItem(item)">
364
+ <v-list-item v-for="(feed,index) in feeds" :key="feed.title" density="compact" :title="feed.title" :subtitle="toSubTitle(feed)"
365
+ active-color="blue" :active="index == playIndex" @click="listItem(feed)">
214
366
  </v-list-item>
215
367
  </v-list-item-group>
216
368
  </v-list>
217
369
  </v-card>
370
+ -->
218
371
  </template>
219
372