···66- Load 100 videos at a time instead of 50
77- Allow selecting bottom row diagonally with the down arrow key
88- Fix channel tags sometimes not saving
99+- Add ability to edit tags by double-clicking
9101011## 1.5.0 - 2023 Nov 19
1112- Add support for all channel URLs. URLs like `/lacunarecs`, `/@lacunarecs`, `/c/lacunarecs`, `/user/lacunarecs` and even `/lacunarecs/playlists` etc work now.
+73-55
src/lib/Tags.svelte
···11<script lang="ts">
22+ import { tick } from 'svelte'
23 import { checkShortcut } from './general'
3445 export let value: string[]
56 export let onUpdate: () => void
67 let inputEl: HTMLInputElement
88+ let text = ''
99+ let editingIndex: number | null = null
71088- let editing = false
99- function startEditing() {
1010- editing = true
1111- text = value[value.length - 1]
1212- }
1313- function startAdding() {
1414- editing = false
1111+ async function startAdding() {
1212+ editingIndex = null
1313+ await tick()
1414+ inputEl.focus()
1515 text = ''
1616 }
1717+ async function startEditing(index: number) {
1818+ editingIndex = index
1919+ await tick()
2020+ inputEl.focus()
2121+ text = value[index]
2222+ }
2323+2424+ function add(text: string) {
2525+ value.push(text)
2626+ update(value)
2727+ }
1728 function applyEditing() {
1818- if (editing) {
2929+ if (editingIndex !== null) {
1930 if (text === '') {
2020- value.pop()
3131+ value.splice(editingIndex, 1)
2132 update(value)
2222- } else if (text !== value[value.length - 1]) {
2323- value[value.length - 1] = text
3333+ } else if (text !== value[editingIndex]) {
3434+ value[editingIndex] = text
2435 update(value)
2536 }
2637 text = ''
2727- editing = false
3838+ editingIndex = null
2839 }
2940 }
3030-3131- let text = ''
4141+ function remove(i: number) {
4242+ value.splice(i, 1)
4343+ update(value)
4444+ }
32453346 function update(newValue: string[]) {
3447 value = newValue
···3952 text = ''
4053 }
4154 function onBlur() {
4242- if (editing) {
5555+ if (editingIndex !== null) {
4356 applyEditing()
4457 } else if (text !== '') {
4545- value.push(text)
4646- update(value)
5858+ add(text)
4759 }
4860 text = ''
4961 }
5062 let tagXEls: HTMLButtonElement[] = []
5151- async function editingKeydown(e: KeyboardEvent) {
5252- if (checkShortcut(e, 'Enter')) {
5353- applyEditing()
5454- } else if (checkShortcut(e, 'Backspace')) {
5555- if (text === '' && value.length >= 2) {
5656- e.preventDefault()
5757- value.pop()
5858- update(value)
5959- startEditing()
6060- }
6161- } else if (checkShortcut(e, 'Escape')) {
6262- startAdding()
6363- e.preventDefault()
6464- }
6565- }
6663 async function keydown(e: KeyboardEvent) {
6767- if (editing) {
6464+ if (editingIndex !== null) {
6865 editingKeydown(e)
6966 return
7067 }
7168 if (checkShortcut(e, 'Enter')) {
7269 if (text !== '') {
7373- value.push(text)
7474- update(value)
7070+ add(text)
7571 startAdding()
7672 }
7773 } else if (checkShortcut(e, 'Backspace')) {
7874 if (text === '' && value.length >= 1) {
7975 e.preventDefault()
8080- startEditing()
7676+ startEditing(value.length - 1)
8177 }
8282- } else if (checkShortcut(e, 'Escape')) {
8383- e.preventDefault()
8478 }
8579 }
8686- function remove(i: number) {
8787- value.splice(i, 1)
8888- update(value)
8080+ async function editingKeydown(e: KeyboardEvent) {
8181+ if (checkShortcut(e, 'Enter')) {
8282+ applyEditing()
8383+ startAdding()
8484+ } else if (checkShortcut(e, 'Backspace') && editingIndex !== null) {
8585+ if (text === '' && value.length >= 2) {
8686+ e.preventDefault()
8787+ remove(editingIndex)
8888+ startEditing(editingIndex - 1)
8989+ }
9090+ } else if (checkShortcut(e, 'Escape')) {
9191+ startAdding()
9292+ }
8993 }
9094 function tagKeydown(e: KeyboardEvent, i: number) {
9195 if (checkShortcut(e, 'Backspace')) {
9292- value.splice(i, 1)
9393- update(value)
9696+ remove(i)
9497 if (i >= 1) {
9598 tagXEls[i - 1].focus()
9699 } else {
···103106<div class="tags">
104107 <div class="label">Tags</div>
105108 {#each value as tag, i}
106106- {#if i === value.length - 1 && editing}
107107- <!-- hide last element when editing -->
109109+ {#if i === editingIndex}
110110+ <input
111111+ bind:this={inputEl}
112112+ type="text"
113113+ placeholder="Add tags..."
114114+ on:focus={onFocus}
115115+ on:blur={onBlur}
116116+ on:keydown={keydown}
117117+ bind:value={text}
118118+ />
108119 {:else}
109120 <div class="tag">
110110- {tag}<button
121121+ <span
122122+ role="none"
123123+ on:dblclick={() => {
124124+ startEditing(i)
125125+ }}>{tag}</span
126126+ ><button
111127 bind:this={tagXEls[i]}
112128 on:keydown={(e) => tagKeydown(e, i)}
113129 on:click={() => remove(i)}
···116132 </div>
117133 {/if}
118134 {/each}
119119- <input
120120- bind:this={inputEl}
121121- type="text"
122122- placeholder="Add tags..."
123123- on:focus={onFocus}
124124- on:blur={onBlur}
125125- on:keydown={keydown}
126126- bind:value={text}
127127- />
135135+ {#if editingIndex === null}
136136+ <input
137137+ bind:this={inputEl}
138138+ type="text"
139139+ placeholder="Add tags..."
140140+ on:focus={onFocus}
141141+ on:blur={onBlur}
142142+ on:keydown={keydown}
143143+ bind:value={text}
144144+ />
145145+ {/if}
128146</div>
129147130148<style lang="sass">