Add input module

This commit is contained in:
Dakedres 2024-11-29 13:09:49 -07:00
parent 814d6741a2
commit b9af38f49d
11 changed files with 274 additions and 126 deletions

View File

@ -107,18 +107,9 @@
</svg>
<nav>
<button class="left player">Previous</button>
<button class="center player playing">Paused</button>
<button class="center player paused">Play</button>
<button class="right player">Next</button>
<button class="left queue">Up</button>
<button class="center queue">Jump</button>
<button class="right queue">Down</button>
<button class="left browser">Queue All</button>
<button class="center browser">Queue</button>
<button class="right browser">Play Track</button>
<button id="left">Previous</button>
<button id="center">Paused</button>
<button id="right">Next</button>
</nav>

View File

@ -7,7 +7,6 @@ import List from "./list.js"
import * as entry from "./entry.js"
import * as mode from "./mode.js"
import * as device from "device"
import { OnEntryListKeydown } from "./util.js"
const app = window.app ??= {}
const view = window.view ??= {}
@ -26,10 +25,9 @@ export const Init = async () => {
}
export const View = async () => {
list = new List(
view.browser = {},
document.getElementById('browser')
)
list = new List(view.browser = {
element: document.getElementById('browser')
})
Render()
}
@ -63,44 +61,7 @@ export const Open = () => {
mode.Display('browser')
}
export const OnKeydown = (event) => {
let e = Focused()
switch(event.key) {
case 'SoftLeft':
// PlayTrack()
break
case 'Escape':
case 'Backspace':
back()
break
case ' ':
case 'Enter':
if(e.entries) {
Cd(e)
break
}
case 'q':
if(e.entries == null) {
queue.Add(e)
}
list.Scroll(1)
break;
case 'r':
case '7':
app.browser.recursiveView = !app.browser.recursiveView
Render()
break
default:
return OnEntryListKeydown(list, event, e)
}
}
export const back = () => {
export const Back = () => {
let e = app.browser.current
if(e.root) {
return
@ -112,7 +73,7 @@ export const back = () => {
}
}
export const Cd = (entry = app.browser.root) => {
export const Cd = (entry = Focused() || app.browser.root) => {
if(entry.entries) {
app.browser.current = entry
Render()
@ -123,6 +84,28 @@ export const Cd = (entry = app.browser.root) => {
}
}
export const Queue = (entry = Focused()) => {
queue.Add(entry)
list.Scroll(1)
}
export const QueueAllBelow = () => {
let e = app.browser.current.entries
for(let i = app.cursor; i < e.length; i++) {
queue.Add(e)
}
}
export const GoToDirectory = (entry = Focused()) => {
Cd(entry.parent) &&
list.Focus(app.browser.view.indexOf(entry))
}
export const ToggleRecursiveView = () => {
app.browser.recursiveView = !app.browser.recursiveView
Render()
}
export const Focused = () => {
return app.browser.view[view.browser.cursor]

1
src/in Normal file
View File

@ -0,0 +1 @@
1

View File

@ -4,6 +4,7 @@ import * as queue from './queue.js'
import * as entry from './entry.js'
import * as mode from './mode.js'
import * as player from './player.js'
import * as input from './input.js'
import * as device from 'device'
window.device = device
@ -12,6 +13,7 @@ window.queue = queue
window.entry = entry
window.mode = mode
window.player = player
window.input = input
window.main = main
document.addEventListener('load', main.Start())

210
src/input.js Normal file
View File

@ -0,0 +1,210 @@
const app = window.app ??= {}
const view = window.view ??= {}
const holdIntervals = 3
const holdIntervalLength = 200
import * as browser from './browser.js'
import * as player from './player.js'
import * as queue from './queue.js'
export function Init() {
}
export function View() {
view.c
window.addEventListener('keydown', OnKeydown)
window.addEventListener('keyup', OnKeyup)
Render()
}
export function Render() {
Actions()
}
export function Actions() {
let a = view.actions = {}
a['ArrowRight'] = {
name: 'Next Panel',
up() {
mode.Scroll(1)
}
}
a['ArrowLeft'] = {
name: 'Prev Panel',
up() {
mode.Scroll(-1)
}
}
a['0'] = {
}
a['c'] = a.pausePlay = {
hint: 'Pause/Play',
up: player.TogglePausePlay
}
a['s'] = a.skip = {
hint: 'Next',
up: player.Next
}
a['+'] = a.volumeUp = {
hint: 'Volume Up',
down() {
navigator.volumeUp()
}
}
a['-'] = a.volumeDown = {
hint: 'Volume Down',
down() {
navigator.volumeDown()
}
}
switch(app.mode) {
case mode.states.PLAYER:
a[' '] = a['Enter'] = player.State() == player.states.PLAYING ?
{
hint: 'Play',
up: player.Play
} :
{
hint: 'Pause',
up: player.Pause
}
a['ArrowUp'] = a.volumeUp
a['ArrowDown'] = a.volumeDown
a['SoftRight'] = a.skip
break
case mode.states.BROWSER:
a['q'] = {
down: browser.Queue
}
a[' '] = a['Enter'] = {
hint: 'Queue',
press() {
browser.Cd() && browser.Queue()
},
holdHint: 'Queue All',
hold: browser.QueueAllBelow
}
a['4'] = a['g'] = {
up: browser.GoToDirectory
}
a['Backspace'] = a['Escape'] = {
up: browser.Back
}
listActions(browser.list)
break
case mode.states.QUEUE:
listActions(queue.list)
a[' '] = a['Enter'] = {
hint: 'Remove',
press: queue.Remove,
holdHint: 'Remove All',
hold: queue.RemoveAllBelow
}
a['SoftLeft'] = a['['] = a['ArrowUp'].shift = {
down() {
queue.Move(-1)
}
}
a['SoftRight'] = a[']'] = a['ArrowDown'].shift = {
down() {
queue.Move(1)
}
}
a['4'] = a['g'] = {
up() {
browser.GoToDirectory(queue.Focused())
mode.Set(mode.states.BROWSER)
}
}
break
}
}
function listActions(list) {
let a = view.actions
a['ArrowUp'] = {
down() {
list.Scroll(-1)
}
}
a['ArrowDown'] = {
down() {
list.Scroll(1)
}
}
}
export function OnKeydown(event) {
let a = view.actions[event.key]
if(a == null) return
ActionDown(a.shift && event.shiftKey ? a.shift : a)
&& event.preventDefault()
}
export function ActionDown(action) {
if(action.holdTimeout != null) {
return true
}
if(action.down) {
return action.down()
}
if(action.hold) {
Hold(action)
} else if(action.press) {
return action.press()
}
}
export function OnKeyup(event) {
let a = view.actions[event.key]
if(a == null) return
ActionUp(a.shift && event.shiftKey ? a.shift : a)
&& event.preventDefault()
}
export function ActionUp(action) {
if(action.holdTimeout != null) {
clearTimeout(action.holdTimeout)
action.holdTimeout = null
}
if(action.up) {
return action.up()
}
if(action.heldCount > 0) {
return action.press()
}
}
export function Hold(aAction) {
aAction.heldCount = holdIntervals
createHoldTimeout(aAction)
}
export function createHoldTimeout(aAction) {
aAction.holdTimeout = setTimeout(() => {
aAction.heldCount--
if(aAction.heldCount == 0) {
aAction.hold()
} else {
createHoldTimeout(aAction)
}
}, holdIntervalLength)
}

View File

@ -1,6 +1,5 @@
export default function List(view, element) {
export default function List(view) {
view.element = element
view.cursor = 0
const Render = this.Render = (entries, iResetCursorTo = view.cursor) => {
@ -89,20 +88,5 @@ export default function List(view, element) {
}
}
const OnKeydown = this.OnKeydown = (event) => {
switch(event.key) {
case 'ArrowDown':
Scroll(1)
break
case 'ArrowUp':
Scroll(-1)
break
default:
return true
}
}
return this
}

View File

@ -6,6 +6,7 @@ import * as device from 'device'
import * as browser from './browser.js'
import * as entry from './entry.js'
import * as mode from './mode.js'
import * as input from './input.js'
export let store
export let saveTimeout
@ -47,9 +48,8 @@ export const View = async () => {
await queue.View()
await player.View()
mode.View()
input.View()
window.addEventListener('keydown', OnKeydown)
// player.Render({ name: 'Timeland, Smoke & Mirrors, The Land Before Timeland, & Hypertension', artist: 'King Gizzard & The Lizard Wizard' })
}

View File

@ -4,6 +4,7 @@ const view = window.view ??= {}
import * as browser from './browser.js'
import * as player from './player.js'
import * as queue from './queue.js'
import * as input from './input.js'
export let modules
export const states = {
@ -27,6 +28,7 @@ export const View = () => {
modules[app.mode].Open()
Render()
input.Actions()
}
export const Display = (name) => {

View File

@ -61,7 +61,14 @@ export const textContainer = (eElement, sText) => {
export const Open = () => {
mode.Display('player')
document.body.classList.add('paused')
}
export const TogglePausePlay = () => {
if(State() === states.PLAYING) {
Pause()
} else {
Play()
}
}
export const OnKeydown = (event) => {

View File

@ -2,22 +2,19 @@ import List from "./list.js"
import * as mode from "./mode.js"
import * as player from "./player.js"
import { OnEntryListKeydown } from "./util.js"
const app = window.app ??= {}
const view = window.view ??= {}
export let list
export let list = new List(view.queue = {
element: document.getElementById('queue'),
})
export const Init = async () => {
app.queue = []
}
export const View = async () => {
list = new List(
view.queue = {},
document.getElementById('queue')
)
Render()
}
@ -25,36 +22,7 @@ export const Render = async () => {
list.Render(app.queue)
}
export const OnKeydown = (event) => {
let e = Focused()
switch(event.key) {
// case 'ArrowLeft':
// back()
// break
// case 'ArrowRight':
// cd(e)
// break
case '[':
case 'SoftLeft':
// Move track up
Move(e, -1)
break
case ']':
case 'SoftRight':
// Move track down
Move(e, 1)
break;
default:
return OnEntryListKeydown(list, event, e)
}
}
export const Move = (eTrack, offset) => {
export const Move = (offset, eTrack = Focused()) => {
let i = view.queue.cursor + offset
if(i == app.queue.length || i < 0) {
return
@ -70,17 +38,30 @@ export const Open = () => {
mode.Display('queue')
}
export const Focused = () => {
return app.queue[view.queue.cursor]
}
export const Add = (eTrack) => {
// TODO: solid way to determine if something is playable
if(eTrack.entries) {
return false
}
app.queue.push(eTrack)
if(app.queue.length == 1 && player.State() === player.states.EMPTY) {
player.Next()
}
return true
}
export const Remove = () => {
app.queue.splice(view.queue.cursor, 1)
Render()
}
export const RemoveAllBelow = () => {
app.queue = app.queue.slice(0, view.queue.cursor)
Render()
}
export const Shift = () => {

View File

@ -1,13 +0,0 @@
export const OnEntryListKeydown = (list, event, e) => {
switch(event.key) {
case '4':
case 'g':
browser.Open()
browser.Cd(e.parent) &&
list.Focus(app.browser.view.indexOf(e))
break
default:
return list.OnKeydown(event)
}
}