update video player, and json generator
This commit is contained in:
parent
7eaeb022b0
commit
1fedcdf92b
|
@ -1,42 +1,50 @@
|
|||
[
|
||||
{
|
||||
"title": "",
|
||||
"title": "Late Junction",
|
||||
"details": "BBC, 2019",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-21 08_Late Junction_2019 - Meredith Monk v2 BBC.mp3"
|
||||
"media": "-21 08_Late Junction_2019 - Meredith Monk v2 BBC"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Speaking of Music",
|
||||
"details": "Meredith Monk, 1984 Part 1 of 2",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-22 02_Speaking of Music Meredith Monk 1984 Part 1 of 2.mp3"
|
||||
"media": "-22 02_Speaking of Music Meredith Monk 1984 Part 1 of 2"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Speaking of Music",
|
||||
"details": "Meredith Monk, 1984 Part 2 of 2",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-23 03_Speaking of Music_ Meredith Monk 1984 Part 2 of 2.mp3"
|
||||
"media": "-23 03_Speaking of Music_ Meredith Monk 1984 Part 2 of 2"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Interview with I Frechl-Bayn Rundfunk",
|
||||
"details": "1986",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-24 04 Meredith Monk Interview with I Ferchl_Bayn Rundfunk 1986.mp3"
|
||||
"media": "-24 04 Meredith Monk Interview with I Ferchl_Bayn Rundfunk 1986"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Terry Gross Interview",
|
||||
"details": "1987",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-25 05 Terry Gross interview_1987.mp3"
|
||||
"media": "-25 05 Terry Gross interview_1987"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Interview with David Garland",
|
||||
"details": "WNYC, Sacred Sundays, 2008",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-26 06 WNYC Interview w_ David Garland_SacredSundays_2008.mp3"
|
||||
"media": "-26 06 WNYC Interview w_ David Garland_SacredSundays_2008"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Frosty McNeil and Meredith Monk",
|
||||
"details": "Fireside Chat, Red Bull Radio",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-27 07_Red Bull Radio_Fireside Chat_M frosty McNeil and MM_41119.mp3"
|
||||
"media": "-27 07_Red Bull Radio_Fireside Chat_M frosty McNeil and MM_41119"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Late Junction",
|
||||
"details": "BBC, 2019",
|
||||
"parent_dir": "documentaries_interviews_audio",
|
||||
"media": "-28 08_Late Junction_2019 - Meredith Monk v2 BBC.mp3"
|
||||
"media": "-28 08_Late Junction_2019 - Meredith Monk v2 BBC"
|
||||
}
|
||||
]
|
|
@ -1,51 +1,61 @@
|
|||
[
|
||||
{
|
||||
"title": "",
|
||||
"title": "Michael Blackwood Making Dances",
|
||||
"details": "",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--2 MichaelBlackwoodMakingDances.m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "ECM 1981",
|
||||
"details": "2019",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--3 ECM1981 Video Meredith Monk V2_2019.m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Andere Avantgarde",
|
||||
"details": "TV Interview 1982",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--4 Meredith Monk_Andere Avantgarde_TV Interview_1982_.m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "New Sounds for a New World",
|
||||
"details": "1982",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--5 New Sounds for a New World_1982.m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Four American Composers",
|
||||
"details": "PeterGreenaway",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--6 Four American Composers_Peter Greenaway.m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "BBC Late Show",
|
||||
"details": "",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--7 bbc_late_show (Original).m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Documentary by Sidsel Mundal",
|
||||
"details": "Norwegian Television, 1994",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--8 1994 documentary by Sidsel Mundal_for Norwegian Telev.m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Television Documentary",
|
||||
"details": "Polish Television, 1995",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "--9 Meredith Monk - Polish Television Documentary (1995).m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Inner Voice",
|
||||
"details": "",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "-12 MeredithMonk_Inner Voice.m4v"
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Lecutre Performance",
|
||||
"details": "Bennington College, 11 March 2011",
|
||||
"parent_dir": "documentaries_interviews_video",
|
||||
"media": "-13 Bennington College lecture performance 3.11.11.m4v"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[
|
||||
{
|
||||
"title": "",
|
||||
"title": "Dolmen Music",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-43 Dolmen Music",
|
||||
"album": true,
|
||||
|
@ -13,7 +14,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Turtle Dreams",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-44 Turtle Dreams",
|
||||
"album": true,
|
||||
|
@ -26,7 +28,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Do You Be",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-45 Do You Be",
|
||||
"album": true,
|
||||
|
@ -46,7 +49,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Book of Days",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-46 Book of Days",
|
||||
"album": true,
|
||||
|
@ -68,7 +72,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Facing North",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-47 Facing North",
|
||||
"album": true,
|
||||
|
@ -90,7 +95,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Atlas",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-48 ATLAS an opera in three parts 2-CD album",
|
||||
"album": true,
|
||||
|
@ -123,7 +129,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Volcano Songs",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-49 Volcano Songs",
|
||||
"album": true,
|
||||
|
@ -145,7 +152,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Mercy",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-50 mercy",
|
||||
"album": true,
|
||||
|
@ -167,7 +175,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Impermenance",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-51 impermanance",
|
||||
"album": true,
|
||||
|
@ -191,7 +200,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Songs of Ascension",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-52 Songs of Ascension",
|
||||
"album": true,
|
||||
|
@ -220,7 +230,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "Piano Songs",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-53 Piano Songs",
|
||||
"album": true,
|
||||
|
@ -240,7 +251,8 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"title": "On Behalf of Nature",
|
||||
"details": "",
|
||||
"parent_dir": "music_sound_ecm",
|
||||
"media": "-54 On Behalf of Nature",
|
||||
"album": true,
|
||||
|
|
|
@ -1,4 +1,45 @@
|
|||
[
|
||||
{
|
||||
"title": "",
|
||||
"parent_dir": "music_sound_various",
|
||||
"media": "MONK MIX Remixes and Interpretations of Music by Meredith Monk CD1",
|
||||
"album": true,
|
||||
"tracks": [
|
||||
"01 Gotham Lullaby (Featuring Björk With The Brodsky Quartet).mp3",
|
||||
"02 Caldera Chimera (Featuring Gabriel Prokofiev Remix).mp3",
|
||||
"03 Click Song #1 (Featuring Don Byron).mp3",
|
||||
"04 Double Fiesta (Featuring Meredith Monk & Bang On A Can).mp3",
|
||||
"05 Astronaut Anthem (Featuring Sakamoto Remix).mp3",
|
||||
"06 Shaking (Featuring Lukas Ligeti) [Pyrolator Remix].mp3",
|
||||
"07 Last Song (Featuring Caetano Veloso).mp3",
|
||||
"08 Fat Stream (Featuring Nico_s Piano Homage).mp3",
|
||||
"09 Wheel (Featuring John Hollenbeck & Theo Bleckmann).mp3",
|
||||
"10 Scared Song (Featuring Pamela Z).mp3",
|
||||
"11 Boat Song (Featuring Rubin Kodheli).mp3",
|
||||
"12 Gathering (Featuring Lee Ranaldo Remix).mp3",
|
||||
"13 Evening (Featuring Henry Grimes Remix).mp3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"parent_dir": "music_sound_various",
|
||||
"media": "MONK MIX Remixes and Interpretations of Music by Meredith Monk CD2",
|
||||
"album": true,
|
||||
"tracks": [
|
||||
"01 Dawn (feat. Dj Spooky Remix).mp3",
|
||||
"02 Rain (feat. Vijay Iyer Revelation Mix Featuring Latasha N. Nevada Diggs).mp3",
|
||||
"03 Atlas Ascending (feat. Todd Reynolds Remix).mp3",
|
||||
"04 Epic (feat. Dj Rekha & Raj Star Remix).mp3",
|
||||
"05 Memory Song (feat. Miho Hatori Remix).mp3",
|
||||
"06 Travellers (feat. King Britt Idm Mix).mp3",
|
||||
"07 Night Vs. Lullaby (feat. Matt Marks Remix).mp3",
|
||||
"08 Double Fiesta (feat. Arto Lindsay Remix).mp3",
|
||||
"09 Long Shadows (feat. Scanner Entwine Mix).mp3",
|
||||
"10 Dolmen Music, Part 1 (feat. Shodekeh's Embody & Continuums Remix).mp3",
|
||||
"11 Braid (feat. High Priest _ Hprizm Ghostlover Remix).mp3",
|
||||
"12 Vocal_ Mill Feuille (feat. Sussan Deyhim Remix).mp3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"parent_dir": "music_sound_various",
|
||||
|
@ -79,16 +120,6 @@
|
|||
"_58_09 Double Fiesta.mp3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"parent_dir": "music_sound_various",
|
||||
"media": "_59 MONK MIX Remixes and Interpretations of Music by Meredith Monk 2-CD",
|
||||
"album": true,
|
||||
"tracks": [
|
||||
"MONK MIX CD1",
|
||||
"MONK MIX CD2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"parent_dir": "music_sound_various",
|
||||
|
|
|
@ -6,6 +6,8 @@ async function main() {
|
|||
let mediaDir = ''
|
||||
let outputDir = ''
|
||||
let recurse = false
|
||||
let imagesOnly = false
|
||||
let dryRun = false
|
||||
|
||||
// get command line arguments
|
||||
process.argv.forEach(function (val, index) {
|
||||
|
@ -15,6 +17,14 @@ async function main() {
|
|||
mediaDir = process.argv[index + 1] || ''
|
||||
}
|
||||
|
||||
if (val == '--dry-run') {
|
||||
dryRun = true
|
||||
}
|
||||
|
||||
if (val == '--images') {
|
||||
imagesOnly = true
|
||||
}
|
||||
|
||||
if (val == '-r' || val == '-R') {
|
||||
recurse = true
|
||||
}
|
||||
|
@ -30,8 +40,18 @@ async function main() {
|
|||
return 0
|
||||
}
|
||||
|
||||
// variable to hold media
|
||||
let media = []
|
||||
let images = []
|
||||
|
||||
// read directory
|
||||
const media = await fs.readdir(mediaDir)
|
||||
const dirList = await fs.readdir(mediaDir)
|
||||
|
||||
if (!recurse) {
|
||||
media = dirList.filter(i => i.match(/.(mp\d|m\d\w)$/i))
|
||||
images = dirList.filter(i => i.match(/.(jp\w*g|png)$/i))
|
||||
}
|
||||
|
||||
|
||||
// clean up directory for json
|
||||
let parent_dir = mediaDir
|
||||
|
@ -42,12 +62,14 @@ async function main() {
|
|||
outputDir = '.'
|
||||
}
|
||||
|
||||
const obj = await Promise.all(media.map(async m => {
|
||||
const obj = await Promise.all(media.map(async (m, i) => {
|
||||
|
||||
const _r = {
|
||||
title: '',
|
||||
details: '',
|
||||
parent_dir,
|
||||
media: m,
|
||||
image: images[i],
|
||||
}
|
||||
|
||||
if (recurse) {
|
||||
|
@ -63,7 +85,12 @@ async function main() {
|
|||
|
||||
const json = JSON.stringify(obj, null, 2)
|
||||
let output = `${parent_dir}.json`
|
||||
|
||||
if (dryRun) {
|
||||
console.log(json)
|
||||
} else {
|
||||
fs.writeFile(path.join(outputDir, output), json)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ export default new Router({
|
|||
plugins: [
|
||||
lazy(() => import('../views/videos.js'))
|
||||
],
|
||||
render: () => html`<mm-video></mm-video>`
|
||||
render: () => html`<mm-videos></mm-videos>`
|
||||
},
|
||||
{
|
||||
path: resolveRouterPath('images'),
|
||||
|
|
|
@ -6,26 +6,66 @@ import './SvgIcon.js'
|
|||
|
||||
class Footer extends LitElement {
|
||||
static properties = {
|
||||
path: { type: String }
|
||||
path: { type: String },
|
||||
navigation: { state: true }
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.path = ''
|
||||
this.navigation = []
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.renderRoutes()
|
||||
}
|
||||
|
||||
renderRoutes() {
|
||||
const grouped = {}
|
||||
const ungrouped = Router.routes.filter(r => !r.group && !r.hide)
|
||||
|
||||
Router.routes.forEach(r => {
|
||||
if (r.group) {
|
||||
if (!grouped[r.group]) {
|
||||
grouped[r.group] = []
|
||||
}
|
||||
grouped[r.group].push(r)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const sortedArray = ungrouped
|
||||
sortedArray.splice(1, 0, Object.values(grouped)[0])
|
||||
sortedArray.splice(2, 0, Object.values(grouped)[1])
|
||||
|
||||
this.navigation = sortedArray
|
||||
}
|
||||
|
||||
renderLink(r, first = false) {
|
||||
return html`
|
||||
${first ? html`<span class="break"></span>` : '' }
|
||||
<a href=${r.path} class="${r.path == this.path ? 'selected' : ''}">
|
||||
<mm-icon name=${r.icon}></mm-icon>
|
||||
<span>
|
||||
${r.short}
|
||||
</span>
|
||||
</a>
|
||||
`
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<footer>
|
||||
<nav>
|
||||
${Router.routes.map(r => !r.hide ? html`
|
||||
<a href=${r.path} class=${r.path == this.path ? 'selected' : ''}>
|
||||
<mm-icon name=${r.icon}></mm-icon>
|
||||
${r.short}
|
||||
</a>` : '') }
|
||||
${this.navigation?.map(r => {
|
||||
if (!r.hide) {
|
||||
if (Array.isArray(r)) {
|
||||
return r.map((r, i) => this.renderLink(r, i == 0))
|
||||
} else {
|
||||
return this.renderLink(r, r.path != '/')
|
||||
}
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
</footer>`
|
||||
}
|
||||
|
@ -34,15 +74,22 @@ class Footer extends LitElement {
|
|||
:host {
|
||||
background: var(--neutral-200, white);
|
||||
box-shadow: 0 0.5em 10px 10px #00000020;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
padding-block: 0.25em;
|
||||
gap: 0.25em;
|
||||
align-items: end;
|
||||
padding-inline: 0.5em;
|
||||
color: var(--green-400, blue);
|
||||
text-decoration: none;
|
||||
text-transform: capitalize;
|
||||
|
||||
& > span {
|
||||
line-height: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
a > svg {
|
||||
|
@ -55,10 +102,8 @@ class Footer extends LitElement {
|
|||
color: var(--neutral-900, black);
|
||||
}
|
||||
|
||||
.unicon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
outline: thin solid red;
|
||||
.break {
|
||||
border-inline-start: thin solid var(--green-400);
|
||||
}
|
||||
|
||||
footer {
|
||||
|
|
|
@ -19,9 +19,12 @@ class HorizontalScroller extends LitElement {
|
|||
:host {
|
||||
--col-width: 10em;
|
||||
--gap: 1em;
|
||||
display: flex;
|
||||
padding-block-end: 0.5em;
|
||||
}
|
||||
|
||||
.scroller {
|
||||
flex-grow: 1;
|
||||
display: grid;
|
||||
gap: var(--gap);
|
||||
grid-auto-flow: column;
|
||||
|
|
|
@ -2,16 +2,12 @@ import { LitElement, html, css,unsafeCSS } from 'lit'
|
|||
import { Task } from '@lit-labs/task'
|
||||
import { formatSeconds } from '../api/utils'
|
||||
|
||||
import VolumeController from '../controllers/volume.js'
|
||||
|
||||
import MainCSS from '../assets/styles/main.scss?inline'
|
||||
|
||||
import './RangeSlider.js'
|
||||
import './Loading.js'
|
||||
|
||||
class ModularPlayer extends LitElement {
|
||||
volCtrl = new VolumeController(this)
|
||||
|
||||
static properties = {
|
||||
// property
|
||||
details: { type: Object },
|
||||
|
@ -68,7 +64,6 @@ class ModularPlayer extends LitElement {
|
|||
|
||||
this.audio.addEventListener('loadstart', () => {
|
||||
this.loading = true
|
||||
this.audio.volume = this.volCtrl.volume
|
||||
})
|
||||
|
||||
this.audio.addEventListener('canplay', () => {
|
||||
|
@ -165,13 +160,6 @@ class ModularPlayer extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
_volHandler(evt) {
|
||||
if (evt.detail) {
|
||||
this.volCtrl.update(evt.detail.value)
|
||||
this.audio.volume = this.volCtrl.volume
|
||||
}
|
||||
}
|
||||
|
||||
_progressCalc() {
|
||||
let percentage = 0
|
||||
|
||||
|
@ -249,15 +237,6 @@ ${ this.details ?
|
|||
<mm-icon name="skip-f15" @click=${this._skipForward} ?disabled=${!this.duration || this.getAudio?.status == 1} class="skip15"></mm-icon>
|
||||
<mm-icon name="skip-next" @click=${this._nextTrack} ?disabled=${!this.duration || this.getAudio?.status == 1}></mm-icon>
|
||||
</div>
|
||||
|
||||
<div class="volume">
|
||||
<mm-icon name="volume"></mm-icon>
|
||||
<mm-range
|
||||
value=${this.volCtrl.volume}
|
||||
@input=${this._volHandler}
|
||||
?disabled=${!this.duration || this.getAudio?.status == 1}
|
||||
></mm-range>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}`
|
||||
|
@ -284,7 +263,7 @@ ${ this.details ?
|
|||
}
|
||||
|
||||
.player:has(.tracklist) {
|
||||
grid-template-rows: 0.7fr 0.5fr 0.3fr 1fr;
|
||||
grid-template-rows: 60% 0.5fr 0.3fr 1fr;
|
||||
padding-block-end: 2em;
|
||||
gap: 0;
|
||||
|
||||
|
@ -323,7 +302,7 @@ ${ this.details ?
|
|||
--tracklist-padding: calc(var(--padding) * 2);
|
||||
position: relative;
|
||||
background: var(--neutral-gradient-400);
|
||||
height: 20em;
|
||||
height: 100%;
|
||||
|
||||
> h2 {
|
||||
margin-inline: var(--tracklist-padding);
|
||||
|
|
|
@ -57,11 +57,11 @@ class NavCard extends LitElement {
|
|||
:host {
|
||||
--highlight-color: black;
|
||||
--shadow: 0 0 0px transparent;
|
||||
--inline-padding: 0.85em;
|
||||
--block-padding: 1em;
|
||||
height: 100%;
|
||||
background: linear-gradient(to bottom, rgb(255 255 255 / 0.9) 0%, rgb(159 159 159 / 0.6) 100%);
|
||||
border-radius: 0.75em;
|
||||
padding: 1em;
|
||||
padding-block-start: 1.25em;
|
||||
box-shadow: 0px 0px 10px #00000060;
|
||||
text-shadow: var(--shadow);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ class NavCard extends LitElement {
|
|||
display: grid;
|
||||
grid-auto-flow: rows;
|
||||
gap: 0.5em;
|
||||
padding: 0.25em;
|
||||
margin-inline: var(--inline-padding);
|
||||
cursor: pointer;
|
||||
font-size: 1.65em;
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ class NavCard extends LitElement {
|
|||
|
||||
.title {
|
||||
padding-bottom: 0.75em;
|
||||
margin-block-start: 1em;
|
||||
font-size: 0.75em;
|
||||
text-align: center;
|
||||
border-bottom: thin solid var(--highlight-color);
|
||||
|
|
|
@ -51,7 +51,7 @@ class VerticalCard extends LitElement {
|
|||
div {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: auto 0.2fr;
|
||||
grid-template-rows: 75% 25%;
|
||||
background: lightgrey;
|
||||
line-height: 1;
|
||||
overflow: hidden;
|
||||
|
@ -68,7 +68,7 @@ class VerticalCard extends LitElement {
|
|||
picture {
|
||||
display: block;
|
||||
background: var(--image-placeholder);
|
||||
aspect-ratio: 1 / 1;
|
||||
/* aspect-ratio: 1 / 1; */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,57 +1,23 @@
|
|||
import { LitElement, css, html } from 'lit'
|
||||
|
||||
import VolumeController from '../controllers/volume.js'
|
||||
|
||||
import './RangeSlider.js'
|
||||
import './SvgIcon.js'
|
||||
import { formatSeconds } from '../api/utils.js'
|
||||
|
||||
class VideoPlayer extends LitElement {
|
||||
volCtrl = new VolumeController(this)
|
||||
|
||||
static properties = {
|
||||
media: { type: String },
|
||||
autoplay: { type: Boolean },
|
||||
videoEl: { state: true },
|
||||
playing: { state: true },
|
||||
controls: { state: true },
|
||||
ctrlTimer: { state: true },
|
||||
position: { state: true },
|
||||
duration: { state: true },
|
||||
remain: { state: true },
|
||||
volumeOpen: { state: true },
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.media = ''
|
||||
this.hostHeight = 0
|
||||
this.hostWidth = 0
|
||||
this.playing = false
|
||||
this.controls = true
|
||||
this.ctrlTimer = {}
|
||||
this.position = 0
|
||||
this.duration = 0
|
||||
this.remain = true
|
||||
this.volumeOpen = false
|
||||
this.autoplay = false
|
||||
this.videoEl = document.createElement('video')
|
||||
this.videoEl.controls = true
|
||||
this.videoEl.playsInline = true
|
||||
this.videoEl.preload = 'metadata'
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.videoEl.addEventListener('loadeddata', () => {
|
||||
this.duration = this.videoEl.duration
|
||||
})
|
||||
|
||||
this.videoEl.addEventListener('timeupdate', () => {
|
||||
this.position = this.videoEl.currentTime
|
||||
})
|
||||
|
||||
this.videoEl.volume = this.volCtrl.volume
|
||||
}
|
||||
|
||||
willUpdate(att) {
|
||||
if (att.has('media')) {
|
||||
console.log(this.media)
|
||||
|
@ -60,123 +26,15 @@ class VideoPlayer extends LitElement {
|
|||
if (this.autoplay) {
|
||||
this.playing = true
|
||||
this.videoEl.play()
|
||||
this.interact()
|
||||
}
|
||||
}
|
||||
this.update()
|
||||
}
|
||||
|
||||
togglePlay() {
|
||||
if (this.playing) {
|
||||
this.videoEl.pause()
|
||||
} else {
|
||||
this.videoEl.play()
|
||||
}
|
||||
this.playing = !this.playing
|
||||
}
|
||||
|
||||
interact() {
|
||||
if (this.playing) {
|
||||
// show controls
|
||||
this.controls = true
|
||||
clearTimeout(this.ctrlTimer)
|
||||
|
||||
// timeout
|
||||
this.ctrlTimer = setTimeout(() => {
|
||||
if (this.playing) {
|
||||
this.volumeOpen = false
|
||||
this.controls = false
|
||||
}
|
||||
}, 2000)
|
||||
}
|
||||
}
|
||||
|
||||
toggleFullscreen() {
|
||||
const container = this.shadowRoot.querySelector('.videoContainer')
|
||||
|
||||
if (container.webkitSupportsFullscreen) {
|
||||
container.webkitEnterFullscreen()
|
||||
return
|
||||
}
|
||||
|
||||
if (document.fullscreenElement !== null) {
|
||||
document.exitFullscreen()
|
||||
container.setAttribute('data-fullscreen', false)
|
||||
} else {
|
||||
container.requestFullscreen()
|
||||
container.setAttribute('data-fullscreen', true)
|
||||
}
|
||||
}
|
||||
|
||||
toggleDuration() {
|
||||
console.log(this.remain)
|
||||
this.remain = !this.remain
|
||||
}
|
||||
|
||||
seek({ detail }) {
|
||||
if (detail) {
|
||||
this.interact()
|
||||
|
||||
this.videoEl.currentTime = detail.value
|
||||
this.position = detail.value
|
||||
}
|
||||
}
|
||||
|
||||
_toggleVolume() {
|
||||
this.interact()
|
||||
|
||||
this.volumeOpen = !this.volumeOpen
|
||||
}
|
||||
|
||||
_volHandler(evt) {
|
||||
this.interact()
|
||||
|
||||
if (evt.detail) {
|
||||
this.volCtrl.update(evt.detail.value)
|
||||
this.videoEl.volume = this.volCtrl.volume
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="videoContainer">
|
||||
${this.videoEl}
|
||||
|
||||
<div class="touchbox" @click=${this.interact}>
|
||||
<div class="playPause ${this.controls ? '' : 'invisible'}" @click=${this.togglePlay}>
|
||||
<mm-icon class="play ${this.playing ? '' : 'invisible'}" name="pause"></mm-icon>
|
||||
<mm-icon class="pause ${this.playing ? 'invisible' : ''}" name="play"></mm-icon>
|
||||
</div>
|
||||
|
||||
<div class="controls ${this.controls ? '' : 'invisible'}">
|
||||
|
||||
<div class="buttons">
|
||||
<div class="volume-container">
|
||||
<mm-icon name="volume" @click=${this._toggleVolume}></mm-icon>
|
||||
<div class="popout ${this.volumeOpen ? 'open' : ''}">
|
||||
<mm-range
|
||||
value=${this.volCtrl.volume}
|
||||
step="0.01"
|
||||
@input=${this._volHandler}
|
||||
></mm-range>
|
||||
</div>
|
||||
</div>
|
||||
<mm-icon @click=${this.toggleFullscreen} class="fullscreen" name="fullscreen"></mm-icon>
|
||||
</div>
|
||||
|
||||
<mm-range
|
||||
value="${this.position}"
|
||||
max="${this.duration}"
|
||||
step="0.1"
|
||||
@input=${this.seek}
|
||||
></mm-range>
|
||||
|
||||
<div class="time">
|
||||
<span class="pos">${formatSeconds(this.position)}</span>
|
||||
<span class="dur" @click=${this.toggleDuration}>${ this.remain ? `-${formatSeconds(this.duration - this.position)}` : formatSeconds(this.duration)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
@ -196,109 +54,6 @@ class VideoPlayer extends LitElement {
|
|||
height: 100%;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.controls {
|
||||
position: absolute;
|
||||
padding-inline: 0.75em;
|
||||
padding-block: 0.5em;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 5;
|
||||
transition: opacity 0.25s ease;
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
gap: 0.75em;
|
||||
padding-block-start: 0.5em;
|
||||
}
|
||||
|
||||
& mm-icon {
|
||||
font-size: 1.25em;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.volume-container {
|
||||
position: relative;
|
||||
margin-inline-start: auto;
|
||||
margin-block-end: 0.75em;
|
||||
|
||||
& .popout {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
width: 6em;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
transform: translateX(calc(calc(100% + 0.5em) * -1));
|
||||
overflow: hidden;
|
||||
|
||||
& mm-range {
|
||||
transform: translateX(calc(100% + 1em));
|
||||
transition: transform 0.125s ease-in-out;
|
||||
}
|
||||
|
||||
&.open mm-range {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
display: flex;
|
||||
color: white;
|
||||
font-size: 0.65em;
|
||||
padding-inline: 0.125em;
|
||||
padding-block: 1em 0.5em;
|
||||
}
|
||||
|
||||
.dur {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
mm-icon {
|
||||
display: block;
|
||||
color: white;
|
||||
}
|
||||
|
||||
mm-range {
|
||||
--track-height: 0.3em;
|
||||
--thumb-size: 0.8em;
|
||||
--track-color: #ffffff50;
|
||||
}
|
||||
|
||||
.touchbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 1;
|
||||
transition: opacity 0.25s ease;
|
||||
}
|
||||
|
||||
.playPause {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2.25em;
|
||||
transition: opacity 0.25 ease;
|
||||
}
|
||||
|
||||
.playPause > mm-icon {
|
||||
inset: 0;
|
||||
grid-column: 1 / span 1;
|
||||
grid-row: 1 / span 1;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
export default class VolumeController {
|
||||
volume = 0
|
||||
|
||||
constructor(host) {
|
||||
this.host = host
|
||||
this.host.addController(this)
|
||||
}
|
||||
|
||||
hostConnected() {
|
||||
if (!localStorage.getItem('deviceVolume')) {
|
||||
localStorage.setItem('deviceVolume', 0.6)
|
||||
}
|
||||
|
||||
this.volume = localStorage.getItem('deviceVolume')
|
||||
}
|
||||
|
||||
update(val) {
|
||||
console.log(val)
|
||||
this.volume = val
|
||||
localStorage.setItem('deviceVolume', val)
|
||||
}
|
||||
}
|
|
@ -17,8 +17,6 @@ class Home extends LitElement {
|
|||
|
||||
firstUpdated() {
|
||||
this.renderRoutes()
|
||||
|
||||
console.log(this.navigation)
|
||||
}
|
||||
|
||||
renderRoutes() {
|
||||
|
@ -48,7 +46,7 @@ class Home extends LitElement {
|
|||
</header>
|
||||
|
||||
<nav class="home-nav">
|
||||
${this.navigation?.map((r, i) => {
|
||||
${this.navigation?.map(r => {
|
||||
if (r.path !== '/' && !r.hide) {
|
||||
return html`<mm-ncard .route=${r}></mm-ncard>`
|
||||
}
|
||||
|
@ -57,7 +55,7 @@ class Home extends LitElement {
|
|||
|
||||
<footer>
|
||||
<div>
|
||||
<p>Rooms for Listening & Watching</p>
|
||||
<p>Rooms for Listening & Looking</p>
|
||||
</div>
|
||||
</footer>
|
||||
`
|
||||
|
@ -101,8 +99,8 @@ class Home extends LitElement {
|
|||
margin: 2em;
|
||||
flex-grow: 1;
|
||||
gap: 2em;
|
||||
grid-template-columns: repeat(auto-fill, minmax(25vw, 1fr));
|
||||
grid-auto-rows: 1fr;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
mm-ncard {
|
||||
|
|
|
@ -68,7 +68,7 @@ class VideoView extends LitElement {
|
|||
flex-grow: 1;
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr min-content;
|
||||
grid-template-rows: 70% 30%;
|
||||
gap: 0.25em;
|
||||
}
|
||||
|
||||
|
@ -86,10 +86,6 @@ class VideoView extends LitElement {
|
|||
gap: 0.5em;
|
||||
}
|
||||
|
||||
mm-hscroller {
|
||||
min-height: 15.625rem;
|
||||
}
|
||||
|
||||
aside {
|
||||
font-size: 1.5em;
|
||||
padding-inline-start: 0.5em;
|
||||
|
|
Loading…
Reference in New Issue