big refactor of media attachments
This commit is contained in:
		
							parent
							
								
									074ef0a760
								
							
						
					
					
						commit
						3db6579300
					
				
					 4 changed files with 147 additions and 105 deletions
				
			
		| 
						 | 
					@ -1,96 +1,73 @@
 | 
				
			||||||
<div class="status-media {{sensitive ? 'status-media-is-sensitive' : ''}}"
 | 
					{{#if media.type === 'video'}}
 | 
				
			||||||
     style="grid-template-columns: repeat(auto-fit, minmax({{maxMediaWidth}}px, 1fr));" >
 | 
					  <button type="button"
 | 
				
			||||||
  {{#each mediaAttachments as media}}
 | 
					          class="play-video-button"
 | 
				
			||||||
    {{#if media.type === 'video'}}
 | 
					          aria-label="Play video: {{media.description || ''}}"
 | 
				
			||||||
      <button type="button"
 | 
					          on:click="onClickPlayVideoButton()">
 | 
				
			||||||
              class="play-video-button"
 | 
					    <div class="svg-wrapper">
 | 
				
			||||||
              aria-label="Play video: {{media.description || ''}}"
 | 
					      <svg>
 | 
				
			||||||
              on:click="onClickPlayVideoButton(media, getOriginalWidth(media), getOriginalHeight(media))">
 | 
					        <use xlink:href="#fa-play-circle" />
 | 
				
			||||||
        <div class="svg-wrapper">
 | 
					      </svg>
 | 
				
			||||||
          <svg>
 | 
					    </div>
 | 
				
			||||||
            <use xlink:href="#fa-play-circle" />
 | 
					    <img alt="{{media.description || ''}}"
 | 
				
			||||||
          </svg>
 | 
					         src="{{media.preview_url}}"
 | 
				
			||||||
        </div>
 | 
					         width="{{inlineWidth}}"
 | 
				
			||||||
        <img alt="{{media.description || ''}}"
 | 
					         height="{{inlineHeight}}"
 | 
				
			||||||
             src="{{media.preview_url}}"
 | 
					         class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}"
 | 
				
			||||||
             width="{{getSmallWidth(media)}}"
 | 
					    />
 | 
				
			||||||
             height="{{getSmallHeight(media)}}"
 | 
					  </button>
 | 
				
			||||||
             class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
 | 
					{{else}}
 | 
				
			||||||
        />
 | 
					  <button type="button"
 | 
				
			||||||
      </button>
 | 
					          class="show-image-button"
 | 
				
			||||||
    {{else}}
 | 
					          aria-label="Show image: {{media.description || ''}}"
 | 
				
			||||||
      <button type="button"
 | 
					          on:click="onClickShowImageButton()"
 | 
				
			||||||
            class="show-image-button"
 | 
					          on:mouseover="set({mouseover: event})"
 | 
				
			||||||
            aria-label="Show image: {{media.description || ''}}"
 | 
					  >
 | 
				
			||||||
            on:click="onClickShowImageButton(media, getOriginalWidth(media), getOriginalHeight(media))"
 | 
					  {{#if media.type === 'gifv' && $autoplayGifs}}
 | 
				
			||||||
            on:mouseover="set({mouseover: event})"
 | 
					    <video
 | 
				
			||||||
      >
 | 
					      class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}"
 | 
				
			||||||
      {{#if media.type === 'gifv' && $autoplayGifs}}
 | 
					      aria-label="Animated GIF: {{media.description || ''}}"
 | 
				
			||||||
        <video
 | 
					      poster="{{media.preview_url}}"
 | 
				
			||||||
          class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
 | 
					      src="{{media.url}}"
 | 
				
			||||||
          aria-label="Animated GIF: {{media.description || ''}}"
 | 
					      width="{{inlineWidth}}"
 | 
				
			||||||
          poster="{{media.preview_url}}"
 | 
					      height="{{inlineHeight}}"
 | 
				
			||||||
          src="{{media.url}}"
 | 
					      autoplay
 | 
				
			||||||
          width="{{getSmallWidth(media)}}"
 | 
					      muted
 | 
				
			||||||
          height="{{getSmallHeight(media)}}"
 | 
					      loop
 | 
				
			||||||
          autoplay
 | 
					      playsinline
 | 
				
			||||||
          muted
 | 
					    />
 | 
				
			||||||
          loop
 | 
					  {{elseif media.type === 'gifv' && !$autoplayGifs}}
 | 
				
			||||||
          playsinline
 | 
					    <NonAutoplayGifv
 | 
				
			||||||
        />
 | 
					      class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}"
 | 
				
			||||||
      {{elseif media.type === 'gifv' && !$autoplayGifs}}
 | 
					      label="Animated GIF: {{media.description || ''}}"
 | 
				
			||||||
        <NonAutoplayGifv
 | 
					      poster="{{media.preview_url}}"
 | 
				
			||||||
          class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
 | 
					      src="{{media.url}}"
 | 
				
			||||||
          label="Animated GIF: {{media.description || ''}}"
 | 
					      staticSrc="{{media.preview_url}}"
 | 
				
			||||||
          poster="{{media.preview_url}}"
 | 
					      width="{{inlineWidth}}"
 | 
				
			||||||
          src="{{media.url}}"
 | 
					      height="{{inlineHeight}}"
 | 
				
			||||||
          staticSrc="{{media.preview_url}}"
 | 
					      playing="{{mouseover}}"
 | 
				
			||||||
          width="{{getSmallWidth(media)}}"
 | 
					    />
 | 
				
			||||||
          height="{{getSmallHeight(media)}}"
 | 
					  {{else}}
 | 
				
			||||||
          playing="{{mouseover}}"
 | 
					    <img class="{{!imageLoaded ? 'image-loading' : ''}} {{imageError ? 'image-error' : ''}} {{noNativeWidthHeight ? 'no-native-width-height' : ''}}"
 | 
				
			||||||
        />
 | 
					         on:imgLoad="set({imageLoaded: true})"
 | 
				
			||||||
      {{else}}
 | 
					         on:imgLoadError="set({imageError: true})"
 | 
				
			||||||
        <img class="{{!imageLoaded ? 'image-loading' : ''}} {{imageError ? 'image-error' : ''}} {{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}"
 | 
					         alt="{{media.description || ''}}"
 | 
				
			||||||
             on:imgLoad="set({imageLoaded: true})"
 | 
					         src="{{media.preview_url}}"
 | 
				
			||||||
             on:imgLoadError="set({imageError: true})"
 | 
					         width="{{inlineWidth}}"
 | 
				
			||||||
             alt="{{media.description || ''}}"
 | 
					         height="{{inlineHeight}}"
 | 
				
			||||||
             src="{{media.preview_url}}"
 | 
					    />
 | 
				
			||||||
             width="{{getSmallWidth(media)}}"
 | 
					  {{/if}}
 | 
				
			||||||
             height="{{getSmallHeight(media)}}"/>
 | 
					</button>
 | 
				
			||||||
      {{/if}}
 | 
					{{/if}}
 | 
				
			||||||
    </button>
 | 
					 | 
				
			||||||
    {{/if}}
 | 
					 | 
				
			||||||
  {{/each}}
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
  .status-media {
 | 
					  :global(.status-media img.image-loading, .status-media img.image-error) {
 | 
				
			||||||
    grid-area: status-media;
 | 
					    background: var(--loading-bg);
 | 
				
			||||||
    display: grid;
 | 
					 | 
				
			||||||
    align-items: center;
 | 
					 | 
				
			||||||
    justify-content: center;
 | 
					 | 
				
			||||||
    justify-items: center;
 | 
					 | 
				
			||||||
    grid-column-gap: 10px;
 | 
					 | 
				
			||||||
    grid-row-gap: 10px;
 | 
					 | 
				
			||||||
    margin: 10px 0;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .status-media.status-media-is-sensitive {
 | 
					  :global(.status-media video, .status-media img) {
 | 
				
			||||||
    margin: 0;
 | 
					    object-fit: cover;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .no-native-width-height {
 | 
					  .no-native-width-height {
 | 
				
			||||||
    background-color: var(--mask-bg);
 | 
					    background-color: var(--mask-bg);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  .status-media img.image-loading, .status-media img.image-error {
 | 
					 | 
				
			||||||
    background: var(--loading-bg);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .status-media {
 | 
					 | 
				
			||||||
    overflow: hidden;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .status-media video, .status-media img {
 | 
					 | 
				
			||||||
    object-fit: cover;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .status-media, .status-media video, .status-media img {
 | 
					 | 
				
			||||||
    max-width: calc(100vw - 40px);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .play-video-button {
 | 
					  .play-video-button {
 | 
				
			||||||
    margin: 0;
 | 
					    margin: 0;
 | 
				
			||||||
    padding: 0;
 | 
					    padding: 0;
 | 
				
			||||||
| 
						 | 
					@ -126,16 +103,18 @@
 | 
				
			||||||
    background: none;
 | 
					    background: none;
 | 
				
			||||||
    cursor: zoom-in;
 | 
					    cursor: zoom-in;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  :global(.status-media video, .status-media img) {
 | 
				
			||||||
 | 
					    max-width: calc(100vw - 40px);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  @media (max-width: 767px) {
 | 
					  @media (max-width: 767px) {
 | 
				
			||||||
    .status-media, .status-media video, .status-media img {
 | 
					    :global(.status-media video, .status-media img) {
 | 
				
			||||||
      max-width: calc(100vw - 20px);
 | 
					      max-width: calc(100vw - 20px);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
  const DEFAULT_MEDIA_WIDTH = 300
 | 
					  import { DEFAULT_MEDIA_WIDTH, DEFAULT_MEDIA_HEIGHT } from '../../_static/media'
 | 
				
			||||||
  const DEFAULT_MEDIA_HEIGHT = 200
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  import { imgLoad, imgLoadError } from '../../_utils/events'
 | 
					  import { imgLoad, imgLoadError } from '../../_utils/events'
 | 
				
			||||||
  import { showVideoDialog } from '../../_utils/showVideoDialog'
 | 
					  import { showVideoDialog } from '../../_utils/showVideoDialog'
 | 
				
			||||||
  import { showImageDialog } from '../../_utils/showImageDialog'
 | 
					  import { showImageDialog } from '../../_utils/showImageDialog'
 | 
				
			||||||
| 
						 | 
					@ -143,21 +122,33 @@
 | 
				
			||||||
  import NonAutoplayGifv from '../NonAutoplayGifv.html'
 | 
					  import NonAutoplayGifv from '../NonAutoplayGifv.html'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export default {
 | 
					  export default {
 | 
				
			||||||
    helpers: {
 | 
					 | 
				
			||||||
      getSmallWidth: media => media.meta && media.meta.small && typeof media.meta.small.width === 'number' ?  media.meta.small.width : DEFAULT_MEDIA_WIDTH,
 | 
					 | 
				
			||||||
      getSmallHeight: media => media.meta && media.meta.small && typeof media.meta.small.height === 'number' ?  media.meta.small.height : DEFAULT_MEDIA_HEIGHT,
 | 
					 | 
				
			||||||
      getOriginalWidth: media => media.meta && media.meta.original && typeof media.meta.original.width === 'number' ?  media.meta.original.width : DEFAULT_MEDIA_WIDTH,
 | 
					 | 
				
			||||||
      getOriginalHeight: media => media.meta && media.meta.original && typeof media.meta.original.height === 'number' ?  media.meta.original.height : DEFAULT_MEDIA_HEIGHT,
 | 
					 | 
				
			||||||
      hasNoNativeWidthHeight: media => !(media && media.meta && media.meta.small && typeof media.meta.small.width === 'number' && typeof media.meta.small.height === 'number'),
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    computed: {
 | 
					    computed: {
 | 
				
			||||||
      maxMediaWidth: (mediaAttachments) => Math.max.apply(Math, mediaAttachments.map(media => media.meta && media.meta.small && typeof media.meta.small.width === 'number' ?  media.meta.small.width : DEFAULT_MEDIA_WIDTH))
 | 
					      // width/height to show inline
 | 
				
			||||||
 | 
					      inlineWidth: smallWidth => smallWidth || DEFAULT_MEDIA_WIDTH,
 | 
				
			||||||
 | 
					      inlineHeight: smallHeight => smallHeight || DEFAULT_MEDIA_HEIGHT,
 | 
				
			||||||
 | 
					      // width/height to show in a modal
 | 
				
			||||||
 | 
					      modalWidth: (originalWidth, inlineWidth) => originalWidth || inlineWidth,
 | 
				
			||||||
 | 
					      modalHeight: (originalHeight, inlineHeight) => originalHeight || inlineHeight,
 | 
				
			||||||
 | 
					      meta: media => media.meta,
 | 
				
			||||||
 | 
					      small: meta => meta && meta.small,
 | 
				
			||||||
 | 
					      original: meta => meta && meta.original,
 | 
				
			||||||
 | 
					      smallWidth: small => small && small.width,
 | 
				
			||||||
 | 
					      smallHeight: small => small && small.height,
 | 
				
			||||||
 | 
					      originalWidth: original => original && original.width,
 | 
				
			||||||
 | 
					      originalHeight: original => original && original.height,
 | 
				
			||||||
 | 
					      noNativeWidthHeight: (smallWidth, smallHeight) => typeof smallWidth !== 'number' || typeof smallHeight !== 'number'
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    methods: {
 | 
					    methods: {
 | 
				
			||||||
      onClickPlayVideoButton(media, width, height) {
 | 
					      onClickPlayVideoButton() {
 | 
				
			||||||
 | 
					        let media = this.get('media')
 | 
				
			||||||
 | 
					        let width = this.get('modalWidth')
 | 
				
			||||||
 | 
					        let height = this.get('modalHeight')
 | 
				
			||||||
        showVideoDialog(media.preview_url, media.url, width, height, media.description)
 | 
					        showVideoDialog(media.preview_url, media.url, width, height, media.description)
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      onClickShowImageButton(media, width, height) {
 | 
					      onClickShowImageButton() {
 | 
				
			||||||
 | 
					        let media = this.get('media')
 | 
				
			||||||
 | 
					        let width = this.get('modalWidth')
 | 
				
			||||||
 | 
					        let height = this.get('modalHeight')
 | 
				
			||||||
        showImageDialog(media.preview_url, media.url, media.type, width, height, media.description)
 | 
					        showImageDialog(media.preview_url, media.url, media.type, width, height, media.description)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								routes/_components/status/MediaAttachments.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								routes/_components/status/MediaAttachments.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					<div class="status-media {{sensitive ? 'status-media-is-sensitive' : ''}}"
 | 
				
			||||||
 | 
					     style="grid-template-columns: repeat(auto-fit, minmax({{maxMediaWidth}}px, 1fr));" >
 | 
				
			||||||
 | 
					  {{#each mediaAttachments as media}}
 | 
				
			||||||
 | 
					    <Media :media />
 | 
				
			||||||
 | 
					  {{/each}}
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
					  .status-media {
 | 
				
			||||||
 | 
					    grid-area: status-media;
 | 
				
			||||||
 | 
					    display: grid;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					    justify-items: center;
 | 
				
			||||||
 | 
					    grid-column-gap: 10px;
 | 
				
			||||||
 | 
					    grid-row-gap: 10px;
 | 
				
			||||||
 | 
					    margin: 10px 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .status-media.status-media-is-sensitive {
 | 
				
			||||||
 | 
					    margin: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .status-media {
 | 
				
			||||||
 | 
					    overflow: hidden;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .status-media {
 | 
				
			||||||
 | 
					    max-width: calc(100vw - 40px);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  @media (max-width: 767px) {
 | 
				
			||||||
 | 
					    .status-media {
 | 
				
			||||||
 | 
					      max-width: calc(100vw - 20px);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  import Media from './Media.html'
 | 
				
			||||||
 | 
					  import { DEFAULT_MEDIA_WIDTH } from '../../_static/media'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export default {
 | 
				
			||||||
 | 
					    computed: {
 | 
				
			||||||
 | 
					      maxMediaWidth: (mediaAttachments) => {
 | 
				
			||||||
 | 
					        return Math.max.apply(Math, mediaAttachments.map(media => {
 | 
				
			||||||
 | 
					          return media.meta && media.meta.small && typeof media.meta.small.width === 'number' ?  media.meta.small.width : DEFAULT_MEDIA_WIDTH
 | 
				
			||||||
 | 
					        }))
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    components: {
 | 
				
			||||||
 | 
					      Media
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
      </svg>
 | 
					      </svg>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </button>
 | 
					  </button>
 | 
				
			||||||
  <Media mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/>
 | 
					  <MediaAttachments mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/>
 | 
				
			||||||
  {{else}}
 | 
					  {{else}}
 | 
				
			||||||
    <button type="button"
 | 
					    <button type="button"
 | 
				
			||||||
            class="status-sensitive-media-button"
 | 
					            class="status-sensitive-media-button"
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@
 | 
				
			||||||
  {{/if}}
 | 
					  {{/if}}
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
{{else}}
 | 
					{{else}}
 | 
				
			||||||
<Media mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/>
 | 
					  <MediaAttachments mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/>
 | 
				
			||||||
{{/if}}
 | 
					{{/if}}
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
  .status-sensitive-media-container {
 | 
					  .status-sensitive-media-container {
 | 
				
			||||||
| 
						 | 
					@ -124,12 +124,12 @@
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
  import Media from './Media.html'
 | 
					  import MediaAttachments from './MediaAttachments.html'
 | 
				
			||||||
  import { store } from '../../_store/store'
 | 
					  import { store } from '../../_store/store'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export default {
 | 
					  export default {
 | 
				
			||||||
    components: {
 | 
					    components: {
 | 
				
			||||||
      Media
 | 
					      MediaAttachments
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    store: () => store,
 | 
					    store: () => store,
 | 
				
			||||||
    computed: {
 | 
					    computed: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								routes/_static/media.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								routes/_static/media.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					export const DEFAULT_MEDIA_WIDTH = 300
 | 
				
			||||||
 | 
					export const DEFAULT_MEDIA_HEIGHT = 200
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue