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' : ''}}" | ||||
|      style="grid-template-columns: repeat(auto-fit, minmax({{maxMediaWidth}}px, 1fr));" > | ||||
|   {{#each mediaAttachments as media}} | ||||
|     {{#if media.type === 'video'}} | ||||
|       <button type="button" | ||||
|               class="play-video-button" | ||||
|               aria-label="Play video: {{media.description || ''}}" | ||||
|               on:click="onClickPlayVideoButton(media, getOriginalWidth(media), getOriginalHeight(media))"> | ||||
|         <div class="svg-wrapper"> | ||||
|           <svg> | ||||
|             <use xlink:href="#fa-play-circle" /> | ||||
|           </svg> | ||||
|         </div> | ||||
|         <img alt="{{media.description || ''}}" | ||||
|              src="{{media.preview_url}}" | ||||
|              width="{{getSmallWidth(media)}}" | ||||
|              height="{{getSmallHeight(media)}}" | ||||
|              class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}" | ||||
|         /> | ||||
|       </button> | ||||
|     {{else}} | ||||
|       <button type="button" | ||||
|             class="show-image-button" | ||||
|             aria-label="Show image: {{media.description || ''}}" | ||||
|             on:click="onClickShowImageButton(media, getOriginalWidth(media), getOriginalHeight(media))" | ||||
|             on:mouseover="set({mouseover: event})" | ||||
|       > | ||||
|       {{#if media.type === 'gifv' && $autoplayGifs}} | ||||
|         <video | ||||
|           class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}" | ||||
|           aria-label="Animated GIF: {{media.description || ''}}" | ||||
|           poster="{{media.preview_url}}" | ||||
|           src="{{media.url}}" | ||||
|           width="{{getSmallWidth(media)}}" | ||||
|           height="{{getSmallHeight(media)}}" | ||||
|           autoplay | ||||
|           muted | ||||
|           loop | ||||
|           playsinline | ||||
|         /> | ||||
|       {{elseif media.type === 'gifv' && !$autoplayGifs}} | ||||
|         <NonAutoplayGifv | ||||
|           class="{{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}" | ||||
|           label="Animated GIF: {{media.description || ''}}" | ||||
|           poster="{{media.preview_url}}" | ||||
|           src="{{media.url}}" | ||||
|           staticSrc="{{media.preview_url}}" | ||||
|           width="{{getSmallWidth(media)}}" | ||||
|           height="{{getSmallHeight(media)}}" | ||||
|           playing="{{mouseover}}" | ||||
|         /> | ||||
|       {{else}} | ||||
|         <img class="{{!imageLoaded ? 'image-loading' : ''}} {{imageError ? 'image-error' : ''}} {{hasNoNativeWidthHeight(media) ? 'no-native-width-height' : ''}}" | ||||
|              on:imgLoad="set({imageLoaded: true})" | ||||
|              on:imgLoadError="set({imageError: true})" | ||||
|              alt="{{media.description || ''}}" | ||||
|              src="{{media.preview_url}}" | ||||
|              width="{{getSmallWidth(media)}}" | ||||
|              height="{{getSmallHeight(media)}}"/> | ||||
|       {{/if}} | ||||
|     </button> | ||||
|     {{/if}} | ||||
|   {{/each}} | ||||
| </div> | ||||
| {{#if media.type === 'video'}} | ||||
|   <button type="button" | ||||
|           class="play-video-button" | ||||
|           aria-label="Play video: {{media.description || ''}}" | ||||
|           on:click="onClickPlayVideoButton()"> | ||||
|     <div class="svg-wrapper"> | ||||
|       <svg> | ||||
|         <use xlink:href="#fa-play-circle" /> | ||||
|       </svg> | ||||
|     </div> | ||||
|     <img alt="{{media.description || ''}}" | ||||
|          src="{{media.preview_url}}" | ||||
|          width="{{inlineWidth}}" | ||||
|          height="{{inlineHeight}}" | ||||
|          class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}" | ||||
|     /> | ||||
|   </button> | ||||
| {{else}} | ||||
|   <button type="button" | ||||
|           class="show-image-button" | ||||
|           aria-label="Show image: {{media.description || ''}}" | ||||
|           on:click="onClickShowImageButton()" | ||||
|           on:mouseover="set({mouseover: event})" | ||||
|   > | ||||
|   {{#if media.type === 'gifv' && $autoplayGifs}} | ||||
|     <video | ||||
|       class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}" | ||||
|       aria-label="Animated GIF: {{media.description || ''}}" | ||||
|       poster="{{media.preview_url}}" | ||||
|       src="{{media.url}}" | ||||
|       width="{{inlineWidth}}" | ||||
|       height="{{inlineHeight}}" | ||||
|       autoplay | ||||
|       muted | ||||
|       loop | ||||
|       playsinline | ||||
|     /> | ||||
|   {{elseif media.type === 'gifv' && !$autoplayGifs}} | ||||
|     <NonAutoplayGifv | ||||
|       class="{{noNativeWidthHeight ? 'no-native-width-height' : ''}}" | ||||
|       label="Animated GIF: {{media.description || ''}}" | ||||
|       poster="{{media.preview_url}}" | ||||
|       src="{{media.url}}" | ||||
|       staticSrc="{{media.preview_url}}" | ||||
|       width="{{inlineWidth}}" | ||||
|       height="{{inlineHeight}}" | ||||
|       playing="{{mouseover}}" | ||||
|     /> | ||||
|   {{else}} | ||||
|     <img class="{{!imageLoaded ? 'image-loading' : ''}} {{imageError ? 'image-error' : ''}} {{noNativeWidthHeight ? 'no-native-width-height' : ''}}" | ||||
|          on:imgLoad="set({imageLoaded: true})" | ||||
|          on:imgLoadError="set({imageError: true})" | ||||
|          alt="{{media.description || ''}}" | ||||
|          src="{{media.preview_url}}" | ||||
|          width="{{inlineWidth}}" | ||||
|          height="{{inlineHeight}}" | ||||
|     /> | ||||
|   {{/if}} | ||||
| </button> | ||||
| {{/if}} | ||||
| <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; | ||||
|   :global(.status-media img.image-loading, .status-media img.image-error) { | ||||
|     background: var(--loading-bg); | ||||
|   } | ||||
|   .status-media.status-media-is-sensitive { | ||||
|     margin: 0; | ||||
|   :global(.status-media video, .status-media img) { | ||||
|     object-fit: cover; | ||||
|   } | ||||
|   .no-native-width-height { | ||||
|     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 { | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
|  | @ -126,16 +103,18 @@ | |||
|     background: none; | ||||
|     cursor: zoom-in; | ||||
|   } | ||||
| 
 | ||||
|   :global(.status-media video, .status-media img) { | ||||
|     max-width: calc(100vw - 40px); | ||||
|   } | ||||
|   @media (max-width: 767px) { | ||||
|     .status-media, .status-media video, .status-media img { | ||||
|     :global(.status-media video, .status-media img) { | ||||
|       max-width: calc(100vw - 20px); | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| <script> | ||||
|   const DEFAULT_MEDIA_WIDTH = 300 | ||||
|   const DEFAULT_MEDIA_HEIGHT = 200 | ||||
| 
 | ||||
|   import { DEFAULT_MEDIA_WIDTH, DEFAULT_MEDIA_HEIGHT } from '../../_static/media' | ||||
|   import { imgLoad, imgLoadError } from '../../_utils/events' | ||||
|   import { showVideoDialog } from '../../_utils/showVideoDialog' | ||||
|   import { showImageDialog } from '../../_utils/showImageDialog' | ||||
|  | @ -143,21 +122,33 @@ | |||
|   import NonAutoplayGifv from '../NonAutoplayGifv.html' | ||||
| 
 | ||||
|   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: { | ||||
|       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: { | ||||
|       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) | ||||
|       }, | ||||
|       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) | ||||
|       } | ||||
|     }, | ||||
|  |  | |||
							
								
								
									
										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> | ||||
|     </div> | ||||
|   </button> | ||||
|   <Media mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/> | ||||
|   <MediaAttachments mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/> | ||||
|   {{else}} | ||||
|     <button type="button" | ||||
|             class="status-sensitive-media-button" | ||||
|  | @ -31,7 +31,7 @@ | |||
|   {{/if}} | ||||
| </div> | ||||
| {{else}} | ||||
| <Media mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/> | ||||
|   <MediaAttachments mediaAttachments="{{mediaAttachments}}" sensitive="{{status.sensitive}}"/> | ||||
| {{/if}} | ||||
| <style> | ||||
|   .status-sensitive-media-container { | ||||
|  | @ -124,12 +124,12 @@ | |||
|   } | ||||
| </style> | ||||
| <script> | ||||
|   import Media from './Media.html' | ||||
|   import MediaAttachments from './MediaAttachments.html' | ||||
|   import { store } from '../../_store/store' | ||||
| 
 | ||||
|   export default { | ||||
|     components: { | ||||
|       Media | ||||
|       MediaAttachments | ||||
|     }, | ||||
|     store: () => store, | ||||
|     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