Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
a946348
start implements MediaBrowser on UI side
lo92fr Apr 4, 2025
8d4faf6
add media browser support to standard ui
lo92fr Apr 8, 2025
cceea3c
first working version with playback to spotify !
lo92fr Apr 8, 2025
43d60aa
fix errors on date not already load
lo92fr Apr 9, 2025
52b02e4
Move MediaType to complexType so we can differentiate different type …
lo92fr Apr 12, 2025
cb096bd
remove media-browser as we finally don't use it
lo92fr Apr 12, 2025
3005993
progress on popup routing
lo92fr Jun 18, 2025
aa17dd7
little progress on media UI navigation
lo92fr Jun 18, 2025
5e79d6f
change browse icon
lo92fr Jun 18, 2025
22751e3
start review how to pass playing context to media-browser.vue
lo92fr Jun 18, 2025
d98dda1
readd details for albums, playlist, toptracks to enable individual tr…
lo92fr Jun 18, 2025
46ab260
start adding support in UI for a device selector
lo92fr Jun 18, 2025
e91a28d
progress on UI for media-device-selector
lo92fr Jun 18, 2025
adb1091
add support for device change
lo92fr Jun 19, 2025
7540779
few fixes on ui parts
lo92fr Jun 19, 2025
1593da9
introduce extended MediaType state on Player item to handle complex s…
lo92fr Jun 21, 2025
ed66bc7
fix Play, Enqueue command format
lo92fr Jun 21, 2025
8dc243e
review menu entry
lo92fr Jun 22, 2025
cf9f1e6
put back a navigation bar on top of media browser
lo92fr Jun 22, 2025
11fb2dc
fix device selector playback, lost code
lo92fr Jun 22, 2025
177798c
remove debug info
lo92fr Jun 25, 2025
2172f20
review navigation bar to display label and not id
lo92fr Jun 25, 2025
df9c307
implements infinite scrolling on media-browser.vue and review compone…
lo92fr Jun 26, 2025
2a6c275
add a search bar to the media-browser.vue
lo92fr Jun 27, 2025
e2037cb
fix handle of node presentation with paging
lo92fr Jun 27, 2025
4c73b86
first working version for searchbar (only working currently with spot…
lo92fr Jun 28, 2025
432b2bb
review pres of search result, first pass
lo92fr Jun 28, 2025
fe8f48c
fix playback from search results
lo92fr Jun 28, 2025
f8743b6
review presentation of Search Results, add a "Load More" link to see …
lo92fr Jun 28, 2025
f69194b
fix a few errors in last versions
lo92fr Jun 28, 2025
6b5f388
fix if-else bug
lo92fr Jun 28, 2025
17b29cd
first working version of global player widget
lo92fr Jul 2, 2025
8d6111b
fix handle of PLAY, ENQUEUE & DEVICE command
lo92fr Jul 2, 2025
baf3b68
add handling of volume change, track duration, and artUri
lo92fr Jul 2, 2025
6759f6c
little fix to target correct item on play/enqueu
lo92fr Jul 2, 2025
433455a
review search functionnalites (WIP)
lo92fr Jul 3, 2025
64a1136
disable debug info
lo92fr Jul 3, 2025
e36d5d5
review icons styling on global player
lo92fr Jul 3, 2025
ec5bd71
review MediaState handling to support extended json format correctly
lo92fr Oct 15, 2025
057422a
fix play/pause on global media player
lo92fr Oct 15, 2025
949777f
few fixes on global player selection and state change (WIP)
lo92fr Oct 15, 2025
9206930
progress on Ui fixes (WIP)
lo92fr Oct 15, 2025
063dda4
display mediaPlayer only in global mode
lo92fr Oct 15, 2025
186de05
code cleanup
lo92fr Oct 15, 2025
984dfc1
Globally review routing, media-browser, popup, and props passing to s…
lo92fr Oct 16, 2025
5f56267
more fixes on media-browser.vue, check we use the correct playerItem
lo92fr Oct 16, 2025
470ff75
refactore feature-media webui (WIP)
lo92fr Oct 17, 2025
557a237
fix tracking on global media player
lo92fr Oct 17, 2025
f9884cc
move currentPlayerItem from computed to var to prevent error on chang…
lo92fr Oct 17, 2025
df2ee01
remove debug info on device selector
lo92fr Oct 17, 2025
37ce04a
fix device selector icons position on oh-simple-player-controls.vue
lo92fr Oct 17, 2025
3c935c7
add primary support for Media Queue
lo92fr Oct 19, 2025
a7ea4e4
vue3 upgrade, first pass, nothing work but openhab interface is loading
lo92fr Nov 5, 2025
625f4bc
vue3 upgrade : start to upgrade mediaStore
lo92fr Nov 5, 2025
92c733e
put back the link to media browser in main menu
lo92fr Nov 6, 2025
e3b5fd0
convert media store to vue 3 / pinia store
lo92fr Nov 6, 2025
8c2bec6
convert media-browser.vue to vue3 and pinia store
lo92fr Nov 6, 2025
928717a
fix simple player control for vue3 and use new pinia store
lo92fr Nov 6, 2025
fcdbb51
fix sendCommand
lo92fr Nov 6, 2025
435bb8d
fix route-props missing mediaBrowseMode from menu !
lo92fr Nov 6, 2025
3bca615
fix media device selector
lo92fr Nov 6, 2025
fe99b32
fix a few old $store reference that was not converted !
lo92fr Nov 7, 2025
5044f97
fix a few old $store reference that was not converted !
lo92fr Nov 7, 2025
1a96914
fix media collection scrolling not working because of error on toast
lo92fr Nov 7, 2025
84fbffe
code cleanup
lo92fr Nov 7, 2025
59d5b78
fix watch not working anymore because of pinia store change
lo92fr Nov 7, 2025
58a7296
fix sendCommand called on wrong store
lo92fr Nov 7, 2025
cf6d2fd
fix routeur and route
lo92fr Nov 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions bundles/org.openhab.ui/web/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@
</template>
</f7-list-item>
</f7-list>

<f7-block-title>
{{ t('sidebar.media') }}
</f7-block-title>

<f7-list class="media-links">
<f7-list-item
link="/mediabrowser/"
:route-props="{ mediaBrowserMode: 'Global' }"
:title="t('sidebar.mediaBrowser')"
view=".view-main"
panel-close
:class="{ currentsection: currentPath.about }">
<template #media>
<f7-icon
ios="f7:question_circle_fill"
aurora="f7:question_circle_fill"
md="material:help"
color="gray" />
</template>
</f7-list-item>
</f7-list>

<f7-block-title
v-if="userStore.isAdmin()">
{{ t('sidebar.administration') }}
Expand Down
1 change: 1 addition & 0 deletions bundles/org.openhab.ui/web/src/assets/categories.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export const Categories = [
'parents_6_6',
'pie',
'piggybank',
'mediabrowser',
'player',
'poweroutlet_au',
'poweroutlet_eu',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ export const OhColorpickerCardDefinition = () => new WidgetDefinition('oh-colorp
.paramGroup(CardParameterGroup(), CardParameters())
.paramGroup(pg('colorpicker', 'Color picker'), ColorPickerParameters())


// OhMediaBrowserCard
import MediaBrowserParameters from '../system/mediabrowser.js'
export const OhMediaBrowserCardDefinition = () => new WidgetDefinition('oh-media-browser-card', 'Media Browser Card', 'Display media browser controls in a card')
.paramGroup(CardParameterGroup(), CardParameters())
.paramGroup(pg('media-browser', 'Media Browser Controls'), MediaBrowserParameters())
.paramGroup(pg('Current Track Info', 'Currently playing track information'), [
pi('artistItem', 'Artist Item', 'Item holding the artist name'),
pi('trackItem', 'Track Item', 'Item holding the track name')
])

// OhPlayerCard
import PlayerParameters from '../system/player.js'
export const OhPlayerCardDefinition = () => new WidgetDefinition('oh-player-card', 'Player Card', 'Display player controls in a card')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ export const OhColorpickerItemDefinition = () => new WidgetDefinition('oh-colorp
.paramGroup(ListItemParameterGroup(), ListItemParameters())
.paramGroup(pg('colorpicker', 'Color picker'), ColorPickerParameters())

// OhMediaBrowserItem
import MediaBrowserParameters from '../system/mediabrowser.js'
export const OhMediaBrowserItemDefinition = () => new WidgetDefinition('oh-media-browser-item', 'Media Browser List Item', 'Display media browser controls in a list')
.paramGroup(ListItemParameterGroup(), ListItemParameters())
.paramGroup(pg('media-browser', 'MediaBrowser Controls'), MediaBrowserParameters())
.paramGroup(pg('Current Track Info', 'Currently playing track information'), [
pi('artistItem', 'Artist Item', 'Item holding the artist name'),
pi('trackItem', 'Track Item', 'Item holding the track name')
])


// OhPlayerItem
import PlayerParameters from '../system/player.js'
export const OhPlayerItemDefinition = () => new WidgetDefinition('oh-player-item', 'Player List Item', 'Display player controls in a list')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ import ListParameters from './list.js'
export const OhListDefinition = () => new WidgetDefinition('oh-list', 'List', 'List control, hosts list items')
.params(ListParameters())

import MediaBrowserParameters from './mediabrowser.js'
export const OhMediaBrowserDefinition = () => new WidgetDefinition('oh-media-browser', 'Media browser', 'Media browser controls, with previous track/pause/play/next buttons/title selection')
.params(MediaBrowserParameters())

import PlayerParameters from './player.js'
export const OhPlayerDefinition = () => new WidgetDefinition('oh-player', 'Media player', 'Media player controls, with previous track/pause/play/next buttons')
.params(PlayerParameters())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { pi, pb } from '../helpers.js'

export default () => [
pi('item', 'Item', 'Media Browser item to control'),
pb('showRewindFFward', 'Rewind/Fast Forward', 'Show Rewind and Fast Forward buttons')
]
2 changes: 2 additions & 0 deletions bundles/org.openhab.ui/web/src/assets/i18n/common/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
"sidebar.addOnStore": "Add-on Store",
"sidebar.developerTools": "Developer Tools",
"sidebar.helpAbout": "Help & About",
"sidebar.media": "Media",
"sidebar.mediaBrowser": "Browser",
"sidebar.unlockAdmin": "Unlock Administration",
"sidebar.tip.signIn": "Sign in as an administrator to access settings",
"page.navbar.back": "Back",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@
"error.communicationFailure": "Erreur de communication",
"error.itemNotFound": "%s non trouvé",
"error.notReachable.title": "openHAB est hors ligne",
"error.notReachable.msg": "Le serveur openHAB ne peut pas être atteint pour le moment. Veuillez vérifier votre connexion réseau et votre serveur."
"error.notReachable.msg": "Le serveur openHAB ne peut pas être atteint pour le moment. Veuillez vérifier votre connexion réseau et votre serveur."
}
6 changes: 6 additions & 0 deletions bundles/org.openhab.ui/web/src/assets/i18n/media/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"media.title": "MediaBrowser",
"media.page.updated": "Media page updated",
"media.page.created": "Media page created",
"media.loading": "Loading..."
}
6 changes: 6 additions & 0 deletions bundles/org.openhab.ui/web/src/assets/i18n/media/fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"media.title": "MediaBrowser",
"media.page.updated": "Media page updated",
"media.page.created": "Media page created",
"media.loading": "Loading..."
}
16 changes: 15 additions & 1 deletion bundles/org.openhab.ui/web/src/assets/item-types.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const SharedTypes = ['Call', 'Color', 'Contact', 'DateTime', 'Dimmer', 'Image', 'Location', 'Number', 'Player', 'Rollershutter', 'String', 'Switch']
const SharedTypes = ['Call', 'Color', 'Contact', 'DateTime', 'Dimmer', 'Image', 'Location', 'MediaBrowser', 'Number', 'Player', 'Rollershutter', 'String', 'Switch']

export const ItemTypes = SharedTypes.concat(['Group'])
export const GroupTypes = ['None'].concat(SharedTypes)
Expand Down Expand Up @@ -80,6 +80,20 @@ export const LogicalOpenClosedFunctions = [{
value: 'One CLOSED then OPEN else CLOSED'
}]

export const LogicalMediaBrowserFunctions = [{
name: 'AND_PLAY_PAUSE',
value: 'All PLAY then PLAY else PAUSE'
}, {
name: 'AND_PAUSE_PLAY',
value: 'All PAUSE then PAUSE else PLAY'
}, {
name: 'OR_PLAY_PAUSE',
value: 'One PLAY then PLAY else PAUSE'
}, {
name: 'OR_PAUSE_PLAY',
value: 'One PAUSE then PAUSE else PLAY'
}]

export const LogicalPlayPauseFunctions = [{
name: 'AND_PLAY_PAUSE',
value: 'All PLAY then PLAY else PAUSE'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ export default {
return types.ArithmeticFunctions
case 'Contact':
return types.LogicalOpenClosedFunctions
case 'MediaBrowser':
return types.LogicalMediaBrowserFunctions
case 'Player':
return types.LogicalPlayPauseFunctions
case 'DateTime':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default function itemDefaultListComponent (item, footer) {
component: 'oh-player-item'
}
}

if (item.type === 'Image') {
component = {
component: 'oh-list-item',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<template>
<div>
<f7-segmented v-bind="config"
round
outline
Expand Down Expand Up @@ -38,7 +39,27 @@
icon-material="skip_next"
icon-size="24"
icon-color="gray" />


<f7-button color="blue"
large
icon-material="folder"
icon-size="24"
icon-color="gray"
@click="openBrowserPopup"/>
<f7-button color="blue"
large
icon-material="speaker"
icon-size="24"
icon-color="gray"
@click="openDeviceSelectorPopup"/>

<media-popup :opened="browserPopupOpened" :player-item="config.item" @update:opened="browserPopupOpened = $event"/>
<media-device-popup :opened="deviceSelectorPopupOpened" :player-item="config.item" @update:opened="deviceSelectorPopupOpened = $event"/>
</f7-segmented>
</div>


</template>

<style lang="stylus">
Expand All @@ -48,29 +69,76 @@
.segmented-highlight
display none
.aurora .player-controls
.button
.button
height 37px
</style>

<script>
import mixin from '../widget-mixin'
import { OhPlayerDefinition } from '@/assets/definitions/widgets/system'

import { useStatesStore } from '@/js/stores/useStatesStore'
import MediaPopup from '@/pages/media/media-browser-popup.vue'
import MediaDevicePopup from '@/pages/media/media-device-selector-popup.vue'

export default {
mixins: [mixin],
widget: OhPlayerDefinition,
mounted () {
delete this.config.value
},
components: { // ⚡ Ici on déclare le composant
MediaPopup,
MediaDevicePopup
},
data () {
return {
state: '',
device: '',
binding:'',
artistName: '',
trackName: '',
artUri: '',
trackPosition: 0,
trackDuration: 0,
volume: 0,
browserPopupOpened: false,
deviceSelectorPopupOpened: false
}
},
computed: {
isPlaying () {
const value = this.context.store[this.config.item].state
return value === 'PLAY'
this.decodeState()
return this.state === 'PLAY'
}
},
methods: {
openBrowserPopup() {
this.browserPopupOpened = true
},
openDeviceSelectorPopup() {
this.deviceSelectorPopupOpened = true
},
decodeState () {
const value = this.context.store[this.config.item].state
if (!(value === undefined || value === null || value === '' || value==='-')) {
if (value.indexOf('{') === 0) {
let json = JSON.parse(value);
this.state = json.state;
this.device = json.device.value;
this.binding = json.binding.value;
this.artistName = json.currentPlayingArtistName.value;
this.trackName = json.currentPlayingTrackName.value;
this.artUri = json.currentPlayingArtUri.value;
this.trackPosition = json.currentPlayingTrackPosition.value;
this.trackDuration = json.currentPlayingTrackDuration.value;
this.volume = json.currentPlayingVolume.value;
} else {
console.log("===========value:" + value)
let components = value.split(',')
this.state = components[0]
}
}
},
skipPrevious (value) {
useStatesStore().sendCommand(this.config.item, 'PREVIOUS')
},
Expand All @@ -85,6 +153,9 @@ export default {
},
skipNext (value) {
useStatesStore().sendCommand(this.config.item, 'NEXT')
},
mediaChange (value) {
//useStatesStore().sendCommand(this.config.item, 'spotify:playlist:5Z4AD0u9fwnvtsj7ce5ZLS')
}
}
}
Expand Down
Loading