126 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
		
		
			
		
	
	
			126 lines
		
	
	
	
		
			3.2 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'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  export default {
							 | 
						||
| 
								 | 
							
								    oncreate() {
							 | 
						||
| 
								 | 
							
								      this.setupSyncFromStore()
							 | 
						||
| 
								 | 
							
								      this.setupSyncToStore()
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    data: () => ({
							 | 
						||
| 
								 | 
							
								      rawText: ''
							 | 
						||
| 
								 | 
							
								    }),
							 | 
						||
| 
								 | 
							
								    store: () => store,
							 | 
						||
| 
								 | 
							
								    methods: {
							 | 
						||
| 
								 | 
							
								      setupSyncFromStore() {
							 | 
						||
| 
								 | 
							
								        this.observe('mediaDescriptions', mediaDescriptions => {
							 | 
						||
| 
								 | 
							
								          mediaDescriptions = mediaDescriptions || []
							 | 
						||
| 
								 | 
							
								          let index = this.get('index')
							 | 
						||
| 
								 | 
							
								          let text = mediaDescriptions[index] || ''
							 | 
						||
| 
								 | 
							
								          if (this.get('rawText') !== text) {
							 | 
						||
| 
								 | 
							
								            this.set({rawText: text})
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      setupSyncToStore() {
							 | 
						||
| 
								 | 
							
								        const saveStore = debounce(() => scheduleIdleTask(() => this.store.save()), 1000)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        this.observe('rawText', rawText => {
							 | 
						||
| 
								 | 
							
								          let realm = this.get('realm')
							 | 
						||
| 
								 | 
							
								          let index = this.get('index')
							 | 
						||
| 
								 | 
							
								          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() {
							 | 
						||
| 
								 | 
							
								        deleteMedia(this.get('realm'), this.get('index'))
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								</script>
							 |