130 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <div class="compose-box {{overLimit ? 'over-char-limit' : ''}}">
 | |
|   <ComposeAuthor />
 | |
|   {{#if contentWarningShown}}
 | |
|     <div class="compose-content-warning-wrapper"
 | |
|          transition:slide="{duration: 333}">
 | |
|       <ComposeContentWarning :realm :contentWarning />
 | |
|     </div>
 | |
|   {{/if}}
 | |
|   <ComposeInput :realm :text :autoFocus />
 | |
|   <ComposeLengthGauge :length :overLimit />
 | |
|   <ComposeToolbar :realm :postPrivacy :media :contentWarningShown />
 | |
|   <ComposeLengthIndicator :length :overLimit />
 | |
|   <ComposeMedia :realm :media />
 | |
|   <ComposeButton :length :overLimit on:click="onClickPostButton()" />
 | |
| </div>
 | |
| <style>
 | |
|   .compose-box {
 | |
|     border-radius: 4px;
 | |
|     padding: 20px;
 | |
|     display: grid;
 | |
|     align-items: flex-start;
 | |
|     grid-template-areas:
 | |
|       "avatar name       handle    handle"
 | |
|       "avatar cw         cw        cw"
 | |
|       "avatar input      input     input"
 | |
|       "avatar gauge      gauge     gauge"
 | |
|       "avatar toolbar    toolbar   length"
 | |
|       "avatar media      media     media"
 | |
|       "avatar button     button    button";
 | |
|     grid-template-columns: min-content minmax(0, max-content) 1fr 1fr;
 | |
|     border-bottom: 1px solid var(--main-border);
 | |
|     width: 560px;
 | |
|     max-width: calc(100vw - 40px);
 | |
|   }
 | |
| 
 | |
|   .compose-content-warning-wrapper {
 | |
|     grid-area: cw;
 | |
|   }
 | |
| 
 | |
|   @media (max-width: 767px) {
 | |
|     .compose-box {
 | |
|       padding: 10px 10px;
 | |
|       max-width: calc(100vw - 20px);
 | |
|       width: 580px;
 | |
|     }
 | |
|   }
 | |
| </style>
 | |
| <script>
 | |
|   import ComposeToolbar from './ComposeToolbar.html'
 | |
|   import ComposeLengthGauge from './ComposeLengthGauge.html'
 | |
|   import ComposeLengthIndicator from './ComposeLengthIndicator.html'
 | |
|   import ComposeAuthor from './ComposeAuthor.html'
 | |
|   import ComposeInput from './ComposeInput.html'
 | |
|   import ComposeButton from './ComposeButton.html'
 | |
|   import ComposeMedia from './ComposeMedia.html'
 | |
|   import ComposeContentWarning from './ComposeContentWarning.html'
 | |
|   import { measureText } from '../../_utils/measureText'
 | |
|   import { CHAR_LIMIT, POST_PRIVACY_OPTIONS } from '../../_static/statuses'
 | |
|   import { store } from '../../_store/store'
 | |
|   import { slide } from 'svelte-transitions'
 | |
|   import { postStatus, insertHandleForReply } from '../../_actions/compose'
 | |
| 
 | |
|   export default {
 | |
|     oncreate() {
 | |
|       let realm = this.get('realm')
 | |
|       if (realm !== 'home') {
 | |
|         // if this is a reply, populate the handle immediately
 | |
|         insertHandleForReply(realm)
 | |
| 
 | |
|         // if this is a reply, go back immediately after it's posted
 | |
|         this.observe('postedStatusForRealm', postedStatusForRealm => {
 | |
|           if (postedStatusForRealm === realm) {
 | |
|             window.history.back()
 | |
|           }
 | |
|         }, {init: false})
 | |
|       }
 | |
|     },
 | |
|     components: {
 | |
|       ComposeAuthor,
 | |
|       ComposeToolbar,
 | |
|       ComposeLengthGauge,
 | |
|       ComposeLengthIndicator,
 | |
|       ComposeInput,
 | |
|       ComposeButton,
 | |
|       ComposeMedia,
 | |
|       ComposeContentWarning
 | |
|     },
 | |
|     store: () => store,
 | |
|     computed: {
 | |
|       composeData: ($currentComposeData, realm) => $currentComposeData[realm] || {},
 | |
|       text: (composeData) => composeData.text || '',
 | |
|       media: (composeData) => composeData.media || [],
 | |
|       postPrivacy: (postPrivacyKey) => POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey),
 | |
|       defaultPostPrivacyKey: ($currentVerifyCredentials) => $currentVerifyCredentials.source.privacy,
 | |
|       postPrivacyKey: (composeData, defaultPostPrivacyKey) => composeData.postPrivacy || defaultPostPrivacyKey,
 | |
|       textLength: (text) => measureText(text),
 | |
|       contentWarningLength: (contentWarning) => measureText(contentWarning),
 | |
|       length: (textLength, contentWarningLength, contentWarningShown) => {
 | |
|         return textLength + (contentWarningShown ? contentWarningLength : 0)
 | |
|       },
 | |
|       overLimit: (length) => length > CHAR_LIMIT,
 | |
|       contentWarningShown: (composeData) => composeData.contentWarningShown,
 | |
|       contentWarning: (composeData) => composeData.contentWarning || '',
 | |
|       postedStatusForRealm: ($postedStatusForRealm) => $postedStatusForRealm
 | |
|     },
 | |
|     transitions: {
 | |
|       slide
 | |
|     },
 | |
|     methods: {
 | |
|       onClickPostButton() {
 | |
|         let text = this.get('text')
 | |
|         let media = this.get('media')
 | |
|         let postPrivacyKey = this.get('postPrivacyKey')
 | |
|         let contentWarning = this.get('contentWarning')
 | |
|         let sensitive = media.length && !!contentWarning
 | |
|         let realm = this.get('realm')
 | |
|         let mediaIds = media.map(_ => _.data.id)
 | |
|         let inReplyTo = realm === 'home' ? null : realm
 | |
|         let overLimit = this.get('overLimit')
 | |
| 
 | |
|         if (!text || overLimit) {
 | |
|           return // do nothing if invalid
 | |
|         }
 | |
| 
 | |
|         /* no await */ postStatus(realm, text, inReplyTo, mediaIds,
 | |
|           sensitive, contentWarning, postPrivacyKey)
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| </script>
 |