From 5cd2de651874a86aaa9757f841fa318fdb9a2fb2 Mon Sep 17 00:00:00 2001 From: "ug.rp" Date: Thu, 16 May 2024 12:16:26 +0200 Subject: [PATCH] re-add and fix the r4-user-channels-select --- src/components/index.js | 2 + src/components/r4-app-menu.js | 35 +----- src/components/r4-app-user-menu.js | 64 ++++++++++ src/components/r4-app.js | 36 +++--- src/components/r4-user-channels-select.js | 141 +++++----------------- src/index.css | 11 ++ 6 files changed, 132 insertions(+), 157 deletions(-) create mode 100644 src/components/r4-app-user-menu.js diff --git a/src/components/index.js b/src/components/index.js index ba2e1e8c..b47a8352 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -6,6 +6,7 @@ import R4Actions from './r4-actions.js' import R4Admin from './r4-admin.js' import R4App from './r4-app.js' import R4AppMenu from './r4-app-menu.js' +import R4AppUserMenu from './r4-app-user-menu.js' import R4CommandMenu from './r4-command-menu.js' import R4Avatar from './r4-avatar.js' import R4AvatarUpdate from './r4-avatar-update.js' @@ -57,6 +58,7 @@ const componentDefinitions = { 'r4-app': R4App, 'r4-command-menu': R4CommandMenu, 'r4-app-menu': R4AppMenu, + 'r4-app-user-menu': R4AppUserMenu, 'r4-avatar': R4Avatar, 'r4-avatar-update': R4AvatarUpdate, 'r4-avatar-upload': R4AvatarUpload, diff --git a/src/components/r4-app-menu.js b/src/components/r4-app-menu.js index 0404bcce..7c23a7a7 100644 --- a/src/components/r4-app-menu.js +++ b/src/components/r4-app-menu.js @@ -4,15 +4,13 @@ import {LitElement, html, nothing} from 'lit' * The primary menu for */ export default class R4AppMenu extends LitElement { + createRenderRoot() { + return this + } static properties = { href: {type: String}, - slug: {type: String}, - /** If set to true, renders different menu items */ - auth: {type: Boolean}, - /** Used to set active link */ - path: {type: Boolean, state: true}, + path: {type: String, state: true}, } - constructor() { super() // Set "path" on every navigation. @@ -20,16 +18,9 @@ export default class R4AppMenu extends LitElement { this.path = e.destination.url.replace(this.href, '').split('?')[0] }) } - - get canAdd() { - /* could just be "slug", menu has slug if "user" has channel */ - return this.auth && this.slug - } - isCurrent(path) { return this.path === path ? 'page' : nothing } - render() { const {href, path} = this return html` @@ -37,28 +28,10 @@ export default class R4AppMenu extends LitElement {
  • -
  • ${this.auth ? this.renderAuth() : this.renderNoAuth()}
  • -
  • ${this.canAdd ? this.renderAdd() : null}
  • Explore
  • Map
  • Settings
  • ` } - renderNoAuth() {} - renderAuth() { - if (this.slug) { - return html` - @${this.slug} - ` - } else { - return html`New radio` - } - } - renderAdd() { - return html` + */ +export default class R4AppUserMenu extends LitElement { + createRenderRoot() { + return this + } + static properties = { + href: {type: String}, + channel: {type: Object || null}, + channels: {type: Array || null}, + } + constructor() { + super() + window?.navigation?.addEventListener('navigate', (e) => { + this.path = e.destination.url.replace(this.href, '').split('?')[0] + }) + } + + isCurrent(path) { + return this.path === path ? 'page' : nothing + } + onChannelSelect(event) { + event.stopPropagation() + event.preventDefault() + this.dispatchEvent( + new CustomEvent('select', { + bubbles: true, + detail: event.detail, + }), + ) + } + + render() { + console.log('channels', this.channels, this.channel) + const {href, path} = this + return html` + +
  • ${this.renderChannel()}
  • +
  • ${this.channel ? this.renderAdd() : null}
  • +
    + ` + } + renderChannel() { + if (this.channels) { + return html`` + } else if (this.channel) { + return html`
    @${this.channel.slug}` + } else { + return html`New radio` + } + } + renderAdd() { + return html` { - track.body = track.description - return track - }) + el.tracks = tracks + .slice() + .reverse() + .map((track) => { + track.body = track.description + return track + }) el.track = tracks.at(0) } @@ -302,7 +303,6 @@ export default class R4App extends LitElement { el.removeAttribute('image') } - // Update state about what's playing. this.isPlaying = true this.playingChannel = channel @@ -338,10 +338,10 @@ export default class R4App extends LitElement {
    ${this.renderRouter()}
    ${Object.entries(UI_STATES).map(this.renderPlayerUICtrl.bind(this))}
    @@ -369,7 +369,13 @@ export default class R4App extends LitElement { renderMenu() { return html`
    - + +
    ` } diff --git a/src/components/r4-user-channels-select.js b/src/components/r4-user-channels-select.js index 2cfd082d..d839d0e7 100644 --- a/src/components/r4-user-channels-select.js +++ b/src/components/r4-user-channels-select.js @@ -1,121 +1,40 @@ +import {LitElement, html} from 'lit' import {sdk} from '../libs/sdk.js' -export default class R4UserChannelsSelect extends HTMLElement { - static get observedAttributes() { - return ['channels', 'channel'] +export default class R4UserChannelsSelect extends LitElement { + createRenderRoot() { + return this } - - get channel() { - return this.getAttribute('channel') - } - set channel(str) { - this.setAttribute('channel', str) - } - - get channels() { - return JSON.parse(this.getAttribute('channels')) || [] - } - set channels(obj) { - if (obj) { - this.setAttribute('channels', JSON.stringify(obj)) - } else { - this.removeAttribute('channels') - } - } - - /* if any observed attribute changed, re-render */ - attributeChangedCallback(attrName, newVal) { - if (this.constructor.observedAttributes.indexOf(attrName) > -1) { - this.render() - if (attrName === 'channel') { - this.refreshOptions(newVal) - } - } + static properties = { + channel: {type: Object || null}, + channels: {type: Array || null}, } - - connectedCallback() { - sdk.supabase.auth.onAuthStateChange(this.onAuthStateChange.bind(this)) - - this.$select = document.createElement('select') - this.$select.addEventListener('input', this.onInput.bind(this)) - - this.$defaultOptroup = document.createElement('optgroup') - this.$defaultOptroup.label = 'Selected' - - this.$defaultOption = document.createElement('option') - this.$defaultOption.defaultValue = true - this.$defaultOption.value = '' - this.$defaultOption.innerText = this.channel ? this.channel : '…' - - this.$defaultOptroup.append(this.$defaultOption) - - this.$channelsOptgroup = document.createElement('optgroup') - this.$channelsOptgroup.label = 'All' - this.$select.append(this.$defaultOptroup) - this.$select.append(this.$channelsOptgroup) - - this.append(this.$select) - - if (this.channels && this.channels.length) { - this.refreshOptions(this.channels[0].slug) - } else { - this.refreshUserChannels() - } - } - onInput(event) { + onSelect(event) { event.stopPropagation() - /* event.preventDefault() */ - this.channel = event.target.value - const selectedChannel = this.channels.find((channel) => { - return channel.slug === this.channel - }) - const inputEvent = new CustomEvent('input', { - bubbles: true, - detail: { - channels: this.channels, - channel: selectedChannel, - } - }) - this.dispatchEvent(inputEvent) - this.refreshOptions(this.channel) - } - - onAuthStateChange() { - this.refreshUserChannels() - } - - async refreshUserChannels() { - const { data: user } = await sdk.users.readUser() - if (user) { - const { - error, - data, - } = await sdk.channels.readUserChannels() - - this.error = error - this.channels = data - if (this.channels && this.channels.length) { - if (this.channel) { - this.refreshOptions(this.channel) - } else { - this.refreshOptions(this.channels[0].slug) - } - } - } else { - this.channels = [] - } + event.preventDefault() + const {value: id} = event.target + this.dispatchEvent( + new CustomEvent('select', { + bubbles: true, + detail: this.channels.find((c) => c.id === id), + }), + ) } - render() { - this.$channelsOptgroup.innerHTML = '' - this.channels.map((channel) => { - const $option = document.createElement('option') - $option.value = channel.slug - $option.innerText = channel.slug - this.$channelsOptgroup.append($option) + return html` + + ` + } + _renderOptions() { + return this.channels?.map((channel) => { + return html` ` }) } - refreshOptions(channelSlug) { - this.$defaultOption.innerText = channelSlug - } } diff --git a/src/index.css b/src/index.css index ec1626c0..6e9e5e86 100644 --- a/src/index.css +++ b/src/index.css @@ -356,6 +356,10 @@ r4-layout [slot='player'] { flex: 1; } +r4-layout header[slot='menu'] { + display: flex; +} + r4-router { flex-grow: 1; display: flex; @@ -617,6 +621,13 @@ r4-actions details menu { r4-actions details menu li { margin: 0; } +r4-user-channels-select { + height: 100%; + display: flex; + & label { + display: flex; + } +} /* By default the dropdown is right-aligned, here it is left-aligned */ r4-app r4-actions[left] menu { right: auto;