Pinafore-Web-Client-Frontend/routes/_components/compose/ComposeMediaItem.html

132 lines
3.3 KiB
HTML

<div class="compose-media">
<img src={{mediaItem.data.preview_url}} alt={{mediaItem.file.name}}/>
<div class="compose-media-delete">
<button class="compose-media-delete-button"
aria-label="Delete {{mediaItem.file.name}}"
on:click="onDeleteMedia()" >
<svg class="compose-media-delete-button-svg">
<use xlink:href="#fa-times" />
</svg>
</button>
</div>
<div class="compose-media-alt">
<input type="text"
placeholder="Description"
aria-label="Describe {{mediaItem.file.name}} for the visually impaired"
bind:value=rawText
>
</div>
</div>
<style>
.compose-media {
height: 200px;
overflow: hidden;
flex-direction: column;
position: relative;
display: flex;
background: var(--main-bg);
}
.compose-media img {
object-fit: contain;
object-position: center center;
flex: 1;
height: 100%;
width: 100%;
}
.compose-media-alt {
z-index: 10;
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
}
.compose-media-alt input {
width: 100%;
font-size: 1.2em;
background: var(--alt-input-bg);
}
.compose-media-alt input:focus {
background: var(--main-bg);
}
.compose-media-delete {
position: absolute;
z-index: 10;
top: 0;
right: 0;
left: 0;
display: flex;
justify-content: flex-end;
margin: 2px;
}
.compose-media-delete-button {
padding: 10px;
background: none;
border: none;
}
.compose-media-delete-button:hover {
background: var(--toast-border);
}
.compose-media-delete-button-svg {
fill: var(--button-text);
width: 18px;
height: 18px;
}
</style>
<script>
import { store } from '../../_store/store'
import { deleteMedia } from '../../_actions/media'
import debounce from 'lodash-es/debounce'
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
import { observe } from 'svelte-extras'
export default {
oncreate () {
this.setupSyncFromStore()
this.setupSyncToStore()
},
data: () => ({
rawText: ''
}),
store: () => store,
methods: {
observe,
setupSyncFromStore () {
this.observe('mediaDescriptions', mediaDescriptions => {
mediaDescriptions = mediaDescriptions || []
let { index, rawText } = this.get()
let text = mediaDescriptions[index] || ''
if (rawText !== text) {
this.set({rawText: text})
}
})
},
setupSyncToStore () {
const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000)
this.observe('rawText', rawText => {
let { realm } = this.get()
let { index } = this.get()
let mediaDescriptions = store.getComposeData(realm, 'mediaDescriptions') || []
if (mediaDescriptions[index] === rawText) {
return
}
while (mediaDescriptions.length <= index) {
mediaDescriptions.push(null)
}
mediaDescriptions[index] = rawText
store.setComposeData(realm, {mediaDescriptions})
saveStore()
}, {init: false})
},
onDeleteMedia () {
let {
realm,
index
} = this.get()
deleteMedia(realm, index)
}
}
}
</script>