2019-07-07 00:14:19 -07:00
|
|
|
<li class="compose-media compose-media-realm-{realm}" aria-label={shortName}>
|
2019-06-23 09:41:31 -07:00
|
|
|
<img
|
2019-07-07 00:14:19 -07:00
|
|
|
alt=""
|
2019-06-23 09:41:31 -07:00
|
|
|
class="{type === 'audio' ? 'audio-preview' : ''}"
|
2019-07-07 00:14:19 -07:00
|
|
|
style="object-position: {objectPosition};"
|
2019-06-23 09:41:31 -07:00
|
|
|
src={previewSrc}
|
2019-07-07 00:14:19 -07:00
|
|
|
aria-hidden="true"
|
2019-06-23 09:41:31 -07:00
|
|
|
/>
|
2019-07-07 00:14:19 -07:00
|
|
|
<div class="compose-media-buttons">
|
2019-08-24 19:28:12 -07:00
|
|
|
<button class="compose-media-button compose-media-focal-button"
|
|
|
|
aria-label="Edit"
|
|
|
|
title="Edit"
|
|
|
|
on:click="onEdit()" >
|
|
|
|
<SvgIcon className="compose-media-button-svg" href="#fa-pencil" />
|
2019-07-07 00:14:19 -07:00
|
|
|
</button>
|
|
|
|
<button class="compose-media-button compose-media-delete-button"
|
|
|
|
aria-label="Delete"
|
|
|
|
title="Delete"
|
2018-04-09 18:30:15 -07:00
|
|
|
on:click="onDeleteMedia()" >
|
2019-07-07 00:14:19 -07:00
|
|
|
<SvgIcon className="compose-media-button-svg" href="#fa-times" />
|
2018-04-09 18:30:15 -07:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div class="compose-media-alt">
|
2019-05-27 12:31:49 -07:00
|
|
|
<textarea id="compose-media-input-{uuid}"
|
2018-08-17 22:44:53 -07:00
|
|
|
class="compose-media-alt-input"
|
2019-06-23 09:41:31 -07:00
|
|
|
placeholder="Description"
|
2019-05-27 12:31:49 -07:00
|
|
|
ref:textarea
|
2018-04-09 18:30:15 -07:00
|
|
|
bind:value=rawText
|
2019-05-27 12:31:49 -07:00
|
|
|
></textarea>
|
2019-07-07 00:14:19 -07:00
|
|
|
<label for="compose-media-input-{uuid}" class="sr-only">
|
|
|
|
Describe for the visually impaired (image, video) or auditorily impaired (audio, video)
|
|
|
|
</label>
|
2018-04-09 18:30:15 -07:00
|
|
|
</div>
|
2019-05-27 12:31:42 -07:00
|
|
|
</li>
|
2018-04-09 18:30:15 -07:00
|
|
|
<style>
|
|
|
|
.compose-media {
|
2019-05-27 12:31:42 -07:00
|
|
|
margin: 0;
|
|
|
|
padding: 0;
|
2018-04-09 18:30:15 -07:00
|
|
|
height: 200px;
|
|
|
|
overflow: hidden;
|
|
|
|
flex-direction: column;
|
|
|
|
position: relative;
|
|
|
|
display: flex;
|
|
|
|
background: var(--main-bg);
|
|
|
|
}
|
|
|
|
.compose-media img {
|
|
|
|
object-fit: contain;
|
|
|
|
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;
|
|
|
|
}
|
2018-08-17 22:44:53 -07:00
|
|
|
.compose-media-alt-input {
|
2018-04-09 18:30:15 -07:00
|
|
|
width: 100%;
|
|
|
|
font-size: 1.2em;
|
|
|
|
background: var(--alt-input-bg);
|
2018-08-17 22:44:53 -07:00
|
|
|
color: var(--body-text-color);
|
2019-05-27 12:31:49 -07:00
|
|
|
max-height: 100px;
|
|
|
|
border: 1px solid var(--input-border);
|
|
|
|
resize: none;
|
2018-04-09 18:30:15 -07:00
|
|
|
}
|
2018-08-17 22:44:53 -07:00
|
|
|
.compose-media-alt-input:focus {
|
2018-04-09 18:30:15 -07:00
|
|
|
background: var(--main-bg);
|
|
|
|
}
|
2019-07-07 00:14:19 -07:00
|
|
|
.compose-media-buttons {
|
2018-04-09 18:30:15 -07:00
|
|
|
position: absolute;
|
|
|
|
z-index: 10;
|
|
|
|
top: 0;
|
|
|
|
right: 0;
|
|
|
|
left: 0;
|
|
|
|
display: flex;
|
2019-07-07 00:14:19 -07:00
|
|
|
justify-content: space-between;
|
2018-04-09 18:30:15 -07:00
|
|
|
margin: 2px;
|
|
|
|
}
|
2019-07-07 00:14:19 -07:00
|
|
|
.compose-media-button {
|
2019-05-27 12:31:49 -07:00
|
|
|
padding: 7px 10px 5px;
|
|
|
|
background: var(--floating-button-bg);
|
|
|
|
border: 1px solid var(--button-border);
|
2018-04-09 18:30:15 -07:00
|
|
|
}
|
2019-07-07 00:14:19 -07:00
|
|
|
.compose-media-button:hover {
|
2019-05-27 12:31:49 -07:00
|
|
|
background: var(--floating-button-bg-hover);
|
|
|
|
}
|
2019-07-07 00:14:19 -07:00
|
|
|
.compose-media-button:active {
|
2019-05-27 12:31:49 -07:00
|
|
|
background: var(--floating-button-bg-active);
|
2018-04-09 18:30:15 -07:00
|
|
|
}
|
2019-07-07 00:14:19 -07:00
|
|
|
:global(.compose-media-button-svg) {
|
2018-04-09 18:30:15 -07:00
|
|
|
fill: var(--button-text);
|
|
|
|
width: 18px;
|
|
|
|
height: 18px;
|
|
|
|
}
|
2019-02-13 18:38:34 -08:00
|
|
|
|
2019-06-23 09:41:31 -07:00
|
|
|
.audio-preview {
|
|
|
|
background: var(--audio-bg);
|
|
|
|
}
|
|
|
|
|
2019-02-14 08:46:43 -08:00
|
|
|
.compose-media-realm-dialog {
|
2019-02-13 18:38:34 -08:00
|
|
|
max-height: 20vh;
|
|
|
|
}
|
|
|
|
|
|
|
|
@media (max-width: 767px) {
|
2019-02-14 08:46:43 -08:00
|
|
|
.compose-media-realm-dialog {
|
2019-02-13 18:38:34 -08:00
|
|
|
max-height: 15vh;
|
|
|
|
}
|
2019-05-27 12:31:49 -07:00
|
|
|
.compose-media-alt-input {
|
|
|
|
max-height: 7vh;
|
|
|
|
}
|
2019-02-13 18:38:34 -08:00
|
|
|
}
|
2018-04-09 18:30:15 -07:00
|
|
|
</style>
|
|
|
|
<script>
|
|
|
|
import { store } from '../../_store/store'
|
|
|
|
import { deleteMedia } from '../../_actions/media'
|
|
|
|
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
|
2018-04-30 08:29:04 -07:00
|
|
|
import { observe } from 'svelte-extras'
|
2019-03-02 19:02:06 -08:00
|
|
|
import SvgIcon from '../SvgIcon.html'
|
2019-05-27 12:31:49 -07:00
|
|
|
import { autosize } from '../../_thirdparty/autosize/autosize'
|
2019-06-23 09:41:31 -07:00
|
|
|
import { ONE_TRANSPARENT_PIXEL } from '../../_static/media'
|
2019-07-07 00:14:19 -07:00
|
|
|
import { get } from '../../_utils/lodash-lite'
|
|
|
|
import { coordsToPercent } from '../../_utils/coordsToPercent'
|
2019-08-24 19:28:12 -07:00
|
|
|
import { importShowMediaEditDialog } from '../dialog/asyncDialogs'
|
2019-08-20 08:08:15 -07:00
|
|
|
import { throttleTimer } from '../../_utils/throttleTimer'
|
|
|
|
|
|
|
|
const updateMediaInStore = throttleTimer(scheduleIdleTask)
|
2019-08-24 19:28:12 -07:00
|
|
|
const resizeTextarea = process.browser && throttleTimer(requestAnimationFrame)
|
2018-04-09 18:30:15 -07:00
|
|
|
|
|
|
|
export default {
|
2018-04-19 21:38:01 -07:00
|
|
|
oncreate () {
|
2018-04-09 18:30:15 -07:00
|
|
|
this.setupSyncFromStore()
|
|
|
|
this.setupSyncToStore()
|
2019-05-27 12:31:49 -07:00
|
|
|
this.setupAutosize()
|
|
|
|
},
|
|
|
|
ondestroy () {
|
|
|
|
this.teardownAutosize()
|
2018-04-09 18:30:15 -07:00
|
|
|
},
|
|
|
|
data: () => ({
|
2019-07-07 00:14:19 -07:00
|
|
|
rawText: '',
|
|
|
|
focusX: 0,
|
|
|
|
focusY: 0
|
2018-04-09 18:30:15 -07:00
|
|
|
}),
|
2018-12-03 23:23:29 -08:00
|
|
|
computed: {
|
2019-07-07 00:14:19 -07:00
|
|
|
type: ({ mediaItem }) => mediaItem.data.type,
|
|
|
|
shortName: ({ mediaItem }) => (
|
2018-12-03 23:23:29 -08:00
|
|
|
// sometimes we no longer have the file, e.g. in a delete and redraft situation,
|
|
|
|
// so fall back to the description if it was provided
|
2019-07-07 00:14:19 -07:00
|
|
|
get(mediaItem, ['file', 'name']) || get(mediaItem, ['description']) || 'media'
|
2018-12-03 23:23:29 -08:00
|
|
|
),
|
2019-06-23 09:41:31 -07:00
|
|
|
previewSrc: ({ mediaItem, type }) => (
|
|
|
|
type === 'audio' ? ONE_TRANSPARENT_PIXEL : mediaItem.data.preview_url
|
|
|
|
),
|
2019-07-07 00:14:19 -07:00
|
|
|
uuid: ({ realm, mediaItem }) => `${realm}-${mediaItem.data.id}`,
|
|
|
|
objectPosition: ({ focusX, focusY }) => {
|
|
|
|
if (!focusX && !focusY) {
|
|
|
|
return 'center center'
|
|
|
|
}
|
|
|
|
return `${coordsToPercent(focusX)}% ${100 - coordsToPercent(focusY)}%`
|
2019-08-24 19:28:12 -07:00
|
|
|
}
|
2018-12-03 23:23:29 -08:00
|
|
|
},
|
2018-04-09 18:30:15 -07:00
|
|
|
store: () => store,
|
|
|
|
methods: {
|
2018-04-30 08:29:04 -07:00
|
|
|
observe,
|
2018-04-19 21:38:01 -07:00
|
|
|
setupSyncFromStore () {
|
2018-08-26 18:54:59 -07:00
|
|
|
this.observe('media', media => {
|
|
|
|
media = media || []
|
2019-08-03 13:49:37 -07:00
|
|
|
const { index, rawText } = this.get()
|
|
|
|
const text = get(media, [index, 'description'], '')
|
2018-04-19 09:37:05 -07:00
|
|
|
if (rawText !== text) {
|
2018-08-29 21:42:57 -07:00
|
|
|
this.set({ rawText: text })
|
2019-08-24 19:28:12 -07:00
|
|
|
resizeTextarea(() => autosize.update(this.refs.textarea))
|
2018-04-09 18:30:15 -07:00
|
|
|
}
|
2019-08-03 13:49:37 -07:00
|
|
|
const focusX = get(media, [index, 'focusX'], 0)
|
|
|
|
const focusY = get(media, [index, 'focusY'], 0)
|
2019-07-07 00:14:19 -07:00
|
|
|
this.set({ focusX, focusY })
|
2018-04-09 18:30:15 -07:00
|
|
|
})
|
|
|
|
},
|
2018-04-19 21:38:01 -07:00
|
|
|
setupSyncToStore () {
|
2018-04-09 18:30:15 -07:00
|
|
|
this.observe('rawText', rawText => {
|
2019-08-20 08:08:15 -07:00
|
|
|
updateMediaInStore(() => {
|
|
|
|
const { realm, index, media } = this.get()
|
|
|
|
if (media[index].description !== rawText) {
|
|
|
|
media[index].description = rawText
|
|
|
|
this.store.setComposeData(realm, { media })
|
|
|
|
this.store.save()
|
|
|
|
}
|
|
|
|
})
|
2018-08-29 21:42:57 -07:00
|
|
|
}, { init: false })
|
2018-04-09 18:30:15 -07:00
|
|
|
},
|
2019-05-27 12:31:49 -07:00
|
|
|
setupAutosize () {
|
|
|
|
autosize(this.refs.textarea)
|
|
|
|
},
|
|
|
|
teardownAutosize () {
|
|
|
|
autosize.destroy(this.refs.textarea)
|
|
|
|
},
|
2018-04-19 21:38:01 -07:00
|
|
|
onDeleteMedia () {
|
2019-08-03 13:49:37 -07:00
|
|
|
const { realm, index } = this.get()
|
2018-04-19 09:37:05 -07:00
|
|
|
deleteMedia(realm, index)
|
2019-07-07 00:14:19 -07:00
|
|
|
},
|
2019-08-24 19:28:12 -07:00
|
|
|
async onEdit () {
|
|
|
|
const { realm, index, type } = this.get()
|
|
|
|
const showMediaEditDialog = await importShowMediaEditDialog()
|
|
|
|
showMediaEditDialog(realm, index, type)
|
2018-04-09 18:30:15 -07:00
|
|
|
}
|
2019-03-02 19:02:06 -08:00
|
|
|
},
|
|
|
|
components: {
|
|
|
|
SvgIcon
|
2018-04-09 18:30:15 -07:00
|
|
|
}
|
|
|
|
}
|
2018-12-03 23:23:29 -08:00
|
|
|
</script>
|