mirror of
https://github.com/h3poteto/whalebird-desktop
synced 2025-02-01 09:56:46 +01:00
Rewrite Modals/NewToot with composition API
This commit is contained in:
parent
ebc09cdf55
commit
ee9300054c
@ -119,7 +119,6 @@ export default {
|
||||
return false
|
||||
}
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/openModal')
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/incrementMediaCount')
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Modals/NewToot/uploadImage', file)
|
||||
.then(() => {
|
||||
|
@ -7,18 +7,18 @@
|
||||
:before-close="closeConfirm"
|
||||
width="600px"
|
||||
custom-class="new-toot-modal"
|
||||
ref="dialog"
|
||||
ref="dialogRef"
|
||||
>
|
||||
<el-form v-on:submit.prevent="toot" role="form">
|
||||
<Quote :message="quoteToMessage" :displayNameStyle="displayNameStyle" v-if="quoteToMessage !== null" ref="quote"></Quote>
|
||||
<div class="spoiler" v-if="showContentWarning" ref="spoiler">
|
||||
<Quote :message="quoteToMessage" :displayNameStyle="displayNameStyle" v-if="quoteToMessage !== null" ref="quoteRef"></Quote>
|
||||
<div class="spoiler" v-if="showContentWarning" ref="spoilerRef">
|
||||
<div class="el-input">
|
||||
<input type="text" class="el-input__inner" :placeholder="$t('modals.new_toot.cw')" v-model="spoiler" />
|
||||
<input type="text" class="el-input__inner" :placeholder="$t('modals.new_toot.cw')" v-model="spoilerText" />
|
||||
</div>
|
||||
</div>
|
||||
<Status
|
||||
:modelValue="status"
|
||||
@update:modelValue="status = $event"
|
||||
:modelValue="statusText"
|
||||
@update:modelValue="statusText = $event"
|
||||
:opened="newTootModal"
|
||||
:fixCursorPos="hashtagInserting"
|
||||
:height="statusHeight"
|
||||
@ -26,8 +26,15 @@
|
||||
@toot="toot"
|
||||
/>
|
||||
</el-form>
|
||||
<Poll v-if="openPoll" v-model:polls="polls" v-model:expire="pollExpire" @addPoll="addPoll" @removePoll="removePoll" ref="poll"></Poll>
|
||||
<div class="preview" ref="preview">
|
||||
<Poll
|
||||
v-if="openPoll"
|
||||
v-model:polls="polls"
|
||||
v-model:expire="pollExpire"
|
||||
@addPoll="addPoll"
|
||||
@removePoll="removePoll"
|
||||
ref="pollRef"
|
||||
></Poll>
|
||||
<div class="preview" ref="previewRef">
|
||||
<div class="image-wrapper" v-for="media in attachedMedias" v-bind:key="media.id">
|
||||
<img :src="media.preview_url" class="preview-image" />
|
||||
<el-button type="text" @click="removeAttachment(media)" class="remove-image"><font-awesome-icon icon="circle-xmark" /></el-button>
|
||||
@ -50,7 +57,7 @@
|
||||
<el-button size="default" type="text" @click="selectImage" :title="$t('modals.new_toot.footer.add_image')">
|
||||
<font-awesome-icon icon="camera" />
|
||||
</el-button>
|
||||
<input name="image" type="file" class="image-input" ref="image" @change="onChangeImage" :key="attachedMediaId" />
|
||||
<input name="image" type="file" class="image-input" ref="imageRef" @change="onChangeImage" />
|
||||
</div>
|
||||
<div class="poll">
|
||||
<el-button size="default" type="text" @click="togglePollForm" :title="$t('modals.new_toot.footer.poll')">
|
||||
@ -122,7 +129,7 @@
|
||||
</div>
|
||||
<div class="info">
|
||||
<img src="../../../assets/images/loading-spinner-wide.svg" v-show="loading" class="loading" />
|
||||
<span class="text-count">{{ tootMax - status.length }}</span>
|
||||
<span class="text-count">{{ tootMax - statusText.length }}</span>
|
||||
|
||||
<el-button class="toot-action" @click="closeConfirm(close)">{{ $t('modals.new_toot.cancel') }}</el-button>
|
||||
<el-button class="toot-action" type="primary" @click="toot" :loading="blockSubmit">{{ $t('modals.new_toot.toot') }}</el-button>
|
||||
@ -135,332 +142,366 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, reactive, computed, onMounted, ComponentPublicInstance, nextTick } from 'vue'
|
||||
import { useI18next } from 'vue3-i18next'
|
||||
import { ElMessage, ElMessageBox, ElDialog } from 'element-plus'
|
||||
import { Entity } from 'megalodon'
|
||||
import { useStore } from '@/store'
|
||||
import Visibility from '~/src/constants/visibility'
|
||||
import Status from './NewToot/Status'
|
||||
import Poll from './NewToot/Poll'
|
||||
import Quote from './NewToot/Quote'
|
||||
import Status from './NewToot/Status.vue'
|
||||
import Poll from './NewToot/Poll.vue'
|
||||
import Quote from './NewToot/Quote.vue'
|
||||
import { NewTootTootLength, NewTootAttachLength, NewTootModalOpen, NewTootBlockSubmit, NewTootPollInvalid } from '@/errors/validations'
|
||||
import { EventEmitter } from '~/src/renderer/components/event'
|
||||
import { EventEmitter } from '@/components/event'
|
||||
import { ACTION_TYPES, MUTATION_TYPES } from '@/store/TimelineSpace/Modals/NewToot'
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'new-toot',
|
||||
components: {
|
||||
Status,
|
||||
Poll,
|
||||
Quote
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
status: '',
|
||||
spoiler: '',
|
||||
showContentWarning: false,
|
||||
visibilityList: Visibility,
|
||||
openPoll: false,
|
||||
polls: [],
|
||||
pollExpire: {
|
||||
label: this.$t('modals.new_toot.poll.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
},
|
||||
statusHeight: 240
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('TimelineSpace/Modals/NewToot', {
|
||||
replyToId: state => {
|
||||
if (state.replyToMessage !== null) {
|
||||
return state.replyToMessage.id
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
quoteToMessage: state => state.quoteToMessage,
|
||||
attachedMedias: state => state.attachedMedias,
|
||||
attachedMediaId: state => state.attachedMediaId,
|
||||
mediaDescriptions: state => state.mediaDescriptions,
|
||||
blockSubmit: state => state.blockSubmit,
|
||||
visibility: state => state.visibility,
|
||||
sensitive: state => state.sensitive,
|
||||
initialStatus: state => state.initialStatus,
|
||||
initialSpoiler: state => state.initialSpoiler,
|
||||
visibilityIcon: state => {
|
||||
switch (state.visibility) {
|
||||
case Visibility.Public.value:
|
||||
return 'globe'
|
||||
case Visibility.Unlisted.value:
|
||||
return 'unlock'
|
||||
case Visibility.Private.value:
|
||||
return 'lock'
|
||||
case Visibility.Direct.value:
|
||||
return 'envelope'
|
||||
default:
|
||||
return 'globe'
|
||||
}
|
||||
},
|
||||
loading: state => state.loading
|
||||
}),
|
||||
...mapState('TimelineSpace', {
|
||||
tootMax: state => state.tootMax
|
||||
}),
|
||||
...mapState('App', {
|
||||
displayNameStyle: state => state.displayNameStyle
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals/NewToot', ['hashtagInserting']),
|
||||
newTootModal: {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.NewToot.modalOpen
|
||||
},
|
||||
set(value) {
|
||||
if (value) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/openModal')
|
||||
} else {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/closeModal')
|
||||
}
|
||||
}
|
||||
},
|
||||
pinedHashtag: {
|
||||
get() {
|
||||
return this.$store.state.TimelineSpace.Modals.NewToot.pinedHashtag
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/changePinedHashtag', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/setupLoading')
|
||||
},
|
||||
mounted() {
|
||||
EventEmitter.on('image-uploaded', () => {
|
||||
if (this.$refs.preview) {
|
||||
this.statusHeight = this.statusHeight - this.$refs.preview.offsetHeight
|
||||
setup() {
|
||||
const space = 'TimelineSpace/Modals/NewToot'
|
||||
const store = useStore()
|
||||
const i18n = useI18next()
|
||||
const visibilityList = Visibility
|
||||
|
||||
const enableResizing = ref<boolean>(true)
|
||||
const statusText = ref<string>('')
|
||||
const spoilerText = ref<string>('')
|
||||
const showContentWarning = ref<boolean>(false)
|
||||
const openPoll = ref<boolean>(false)
|
||||
const polls = ref<Array<string>>([])
|
||||
const pollExpire = reactive({
|
||||
label: i18n.t('modals.new_toot.poll.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
})
|
||||
const statusHeight = ref<number>(240)
|
||||
const previewRef = ref<HTMLElement>()
|
||||
const imageRef = ref<HTMLInputElement>()
|
||||
const pollRef = ref<ComponentPublicInstance>()
|
||||
const spoilerRef = ref<HTMLElement>()
|
||||
const dialogRef = ref<InstanceType<typeof ElDialog>>()
|
||||
const quoteRef = ref<ComponentPublicInstance>()
|
||||
|
||||
const quoteToMessage = computed(() => store.state.TimelineSpace.Modals.NewToot.quoteToMessage)
|
||||
const attachedMedias = computed(() => store.state.TimelineSpace.Modals.NewToot.attachedMedias)
|
||||
const mediaDescriptions = computed(() => store.state.TimelineSpace.Modals.NewToot.mediaDescriptions)
|
||||
const blockSubmit = computed(() => store.state.TimelineSpace.Modals.NewToot.blockSubmit)
|
||||
const sensitive = computed(() => store.state.TimelineSpace.Modals.NewToot.sensitive)
|
||||
const initialStatus = computed(() => store.state.TimelineSpace.Modals.NewToot.initialStatus)
|
||||
const initialSpoiler = computed(() => store.state.TimelineSpace.Modals.NewToot.initialSpoiler)
|
||||
const visibilityIcon = computed(() => {
|
||||
switch (store.state.TimelineSpace.Modals.NewToot.visibility) {
|
||||
case Visibility.Public.value:
|
||||
return 'globe'
|
||||
case Visibility.Unlisted.value:
|
||||
return 'unlock'
|
||||
case Visibility.Private.value:
|
||||
return 'lock'
|
||||
case Visibility.Direct.value:
|
||||
return 'envelope'
|
||||
default:
|
||||
return 'globe'
|
||||
}
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
newTootModal: function (newState, oldState) {
|
||||
if (!oldState && newState) {
|
||||
this.showContentWarning = this.initialSpoiler
|
||||
this.status = this.initialStatus
|
||||
this.spoiler = this.initialSpoiler
|
||||
const loading = computed(() => store.state.TimelineSpace.Modals.NewToot.loading)
|
||||
const tootMax = computed(() => store.state.TimelineSpace.tootMax)
|
||||
const displayNameStyle = computed(() => store.state.App.displayNameStyle)
|
||||
const hashtagInserting = computed(() => store.getters[`${space}/hashtagInserting`])
|
||||
const newTootModal = computed({
|
||||
get: () => store.state.TimelineSpace.Modals.NewToot.modalOpen,
|
||||
set: (value: boolean) => {
|
||||
if (value) {
|
||||
store.dispatch(`${space}/${ACTION_TYPES.OPEN_MODAL}`)
|
||||
} else {
|
||||
store.dispatch(`${space}/${ACTION_TYPES.CLOSE_MODAL}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
const pinedHashtag = computed({
|
||||
get: () => store.state.TimelineSpace.Modals.NewToot.pinedHashtag,
|
||||
set: (value: boolean) => store.commit(`${space}/${MUTATION_TYPES.CHANGE_PINED_HASHTAG}`, value)
|
||||
})
|
||||
|
||||
store.dispatch(`${space}/${ACTION_TYPES.SETUP_LOADING}`)
|
||||
|
||||
onMounted(() => {
|
||||
EventEmitter.on('image-uploaded', () => {
|
||||
if (previewRef.value) {
|
||||
statusHeight.value = statusHeight.value - previewRef.value.offsetHeight
|
||||
}
|
||||
})
|
||||
|
||||
showContentWarning.value = initialSpoiler.value.length > 0
|
||||
statusText.value = initialStatus.value
|
||||
spoilerText.value = initialSpoiler.value
|
||||
})
|
||||
|
||||
const close = () => {
|
||||
store.dispatch(`${space}/${ACTION_TYPES.RESET_MEDIA_COUNT}`)
|
||||
store.dispatch(`${space}/${ACTION_TYPES.CLOSE_MODAL}`)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.filteredAccount = []
|
||||
const spoilerHeight = this.$refs.spoiler ? this.$refs.spoiler.offsetHeight : 0
|
||||
this.showContentWarning = false
|
||||
this.spoiler = ''
|
||||
this.statusHeight = this.statusHeight + spoilerHeight
|
||||
const pollHeight = this.$refs.poll ? this.$refs.poll.$el.offsetHeight : 0
|
||||
this.openPoll = false
|
||||
this.polls = []
|
||||
this.pollExpire = {
|
||||
label: this.$t('modals.new_toot.poll.expires.1_day'),
|
||||
value: 3600 * 24
|
||||
}
|
||||
this.statusHeight = this.statusHeight + pollHeight
|
||||
const quoteHeight = this.$refs.quote ? this.$refs.quote.$el.offsetHeight : 0
|
||||
this.statusHeight = this.statusHeight + quoteHeight
|
||||
const attachmentHeight = this.$refs.preview ? this.$refs.preview.offsetHeight : 0
|
||||
this.statusHeight = this.statusHeight + attachmentHeight
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/resetMediaCount')
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/closeModal')
|
||||
},
|
||||
async toot() {
|
||||
const toot = async () => {
|
||||
const form = {
|
||||
status: this.status,
|
||||
spoiler: this.spoiler,
|
||||
polls: this.polls,
|
||||
pollExpireSeconds: this.pollExpire.value
|
||||
status: statusText.value,
|
||||
spoiler: spoilerText.value,
|
||||
polls: polls.value,
|
||||
pollExpireSeconds: pollExpire.value
|
||||
}
|
||||
|
||||
try {
|
||||
const status = await this.$store.dispatch('TimelineSpace/Modals/NewToot/postToot', form)
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/updateHashtags', status.tags)
|
||||
this.close()
|
||||
const status = await store.dispatch(`${space}/${ACTION_TYPES.POST_TOOT}`, form)
|
||||
store.dispatch(`${space}/${ACTION_TYPES.UPDATE_HASHTAGS}`, status.tags)
|
||||
close()
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
if (err instanceof NewTootTootLength) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.toot_length', {
|
||||
ElMessage({
|
||||
message: i18n.t('validation.new_toot.toot_length', {
|
||||
min: 1,
|
||||
max: this.tootMax
|
||||
max: tootMax.value
|
||||
}),
|
||||
type: 'error'
|
||||
})
|
||||
} else if (err instanceof NewTootAttachLength) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_length', { max: 4 }),
|
||||
ElMessage({
|
||||
message: i18n.t('validation.new_toot.attach_length', { max: 4 }),
|
||||
type: 'error'
|
||||
})
|
||||
} else if (err instanceof NewTootPollInvalid) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.poll_invalid'),
|
||||
ElMessage({
|
||||
message: i18n.t('validation.new_toot.poll_invalid'),
|
||||
type: 'error'
|
||||
})
|
||||
} else if (err instanceof NewTootModalOpen || err instanceof NewTootBlockSubmit) {
|
||||
// Nothing
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.$t('message.toot_error'),
|
||||
ElMessage({
|
||||
message: i18n.t('message.toot_error'),
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
selectImage() {
|
||||
this.$refs.image.click()
|
||||
},
|
||||
onChangeImage(e) {
|
||||
if (e.target.files.item(0) === null || e.target.files.item(0) === undefined) {
|
||||
}
|
||||
const selectImage = () => {
|
||||
imageRef!.value!.click()
|
||||
}
|
||||
const updateImage = (file: File) => {
|
||||
store
|
||||
.dispatch(`${space}/${ACTION_TYPES.UPLOAD_IMAGE}`, file)
|
||||
.then(() => {
|
||||
enableResizing.value = false
|
||||
nextTick(() => {
|
||||
if (attachedMedias.value.length === 1 && previewRef.value) {
|
||||
statusHeight.value = statusHeight.value - previewRef.value.offsetHeight
|
||||
}
|
||||
enableResizing.value = true
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
if (err instanceof NewTootAttachLength) {
|
||||
ElMessage({
|
||||
message: i18n.t('validation.new_toot.attach_length', { max: 4 }),
|
||||
type: 'error'
|
||||
})
|
||||
} else {
|
||||
ElMessage({
|
||||
message: i18n.t('message.attach_error'),
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const onChangeImage = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement
|
||||
const file = target.files?.item(0)
|
||||
if (file === null || file === undefined) {
|
||||
return
|
||||
}
|
||||
const file = e.target.files.item(0)
|
||||
if (!file.type.includes('image') && !file.type.includes('video')) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_image'),
|
||||
ElMessage({
|
||||
message: i18n.t('validation.new_toot.attach_image'),
|
||||
type: 'error'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.updateImage(file)
|
||||
},
|
||||
onPaste(e) {
|
||||
const mimeTypes = window.clipboard.availableFormats().filter(type => type.startsWith('image'))
|
||||
updateImage(file)
|
||||
}
|
||||
const onPaste = (e: Event) => {
|
||||
const mimeTypes = (window as any).clipboard.availableFormats().filter(t => t.startsWith('image'))
|
||||
if (mimeTypes.length === 0) {
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
const image = window.clipboard.readImage()
|
||||
let data
|
||||
const image = (window as any).clipboard.readImage()
|
||||
let data: any
|
||||
if (/^image\/jpe?g$/.test(mimeTypes[0])) {
|
||||
data = image.toJPEG(100)
|
||||
} else {
|
||||
data = image.toPNG()
|
||||
}
|
||||
const file = new File([data], 'clipboard.picture', { type: mimeTypes[0] })
|
||||
this.updateImage(file)
|
||||
},
|
||||
updateImage(file) {
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/incrementMediaCount')
|
||||
this.$store
|
||||
.dispatch('TimelineSpace/Modals/NewToot/uploadImage', file)
|
||||
.then(() => {
|
||||
this.statusHeight = this.statusHeight - this.$refs.preview.offsetHeight
|
||||
})
|
||||
.catch(err => {
|
||||
if (err instanceof NewTootAttachLength) {
|
||||
this.$message({
|
||||
message: this.$t('validation.new_toot.attach_length', { max: 4 }),
|
||||
type: 'error'
|
||||
})
|
||||
} else {
|
||||
this.$message({
|
||||
message: this.$t('message.attach_error'),
|
||||
type: 'error'
|
||||
})
|
||||
updateImage(file)
|
||||
}
|
||||
const removeAttachment = (media: Entity.Attachment) => {
|
||||
const previousHeight = previewRef!.value!.offsetHeight
|
||||
store.dispatch(`${space}/${ACTION_TYPES.REMOVE_MEDIA}`, media).then(() => {
|
||||
enableResizing.value = false
|
||||
nextTick(() => {
|
||||
if (attachedMedias.value.length === 0) {
|
||||
statusHeight.value = statusHeight.value + previousHeight
|
||||
}
|
||||
enableResizing.value = true
|
||||
})
|
||||
},
|
||||
removeAttachment(media) {
|
||||
const previousHeight = this.$refs.preview.offsetHeight
|
||||
this.$store.dispatch('TimelineSpace/Modals/NewToot/removeMedia', media).then(() => {
|
||||
this.statusHeight = this.statusHeight + previousHeight
|
||||
})
|
||||
},
|
||||
changeVisibility(level) {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/changeVisibilityValue', level)
|
||||
},
|
||||
changeSensitive() {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/changeSensitive', !this.sensitive)
|
||||
},
|
||||
closeConfirm(done) {
|
||||
if (this.status.length === 0) {
|
||||
}
|
||||
const changeVisibility = (level: number) => {
|
||||
store.commit(`${space}/${MUTATION_TYPES.CHANGE_VISIBILITY_VALUE}`, level)
|
||||
}
|
||||
const changeSensitive = () => {
|
||||
store.commit(`${space}/${MUTATION_TYPES.CHANGE_SENSITIVE}`, !sensitive.value)
|
||||
}
|
||||
const closeConfirm = (done: Function) => {
|
||||
if (statusText.value.length === 0) {
|
||||
done()
|
||||
} else {
|
||||
this.$confirm(this.$t('modals.new_toot.close_confirm'), {
|
||||
confirmButtonText: this.$t('modals.new_toot.close_confirm_ok'),
|
||||
cancelButtonText: this.$t('modals.new_toot.close_confirm_cancel')
|
||||
ElMessageBox.confirm(i18n.t('modals.new_toot.close_confirm'), {
|
||||
confirmButtonText: i18n.t('modals.new_toot.close_confirm_ok'),
|
||||
cancelButtonText: i18n.t('modals.new_toot.close_confirm_cancel')
|
||||
})
|
||||
.then(_ => {
|
||||
done()
|
||||
})
|
||||
.catch(_ => {})
|
||||
}
|
||||
},
|
||||
updateDescription(id, value) {
|
||||
this.$store.commit('TimelineSpace/Modals/NewToot/updateMediaDescription', { id: id, description: value })
|
||||
},
|
||||
async togglePollForm() {
|
||||
const previousHeight = this.$refs.poll ? this.$refs.poll.$el.offsetHeight : 0
|
||||
}
|
||||
const updateDescription = (id: number, value: string) => {
|
||||
store.commit(`${space}/${MUTATION_TYPES.UPDATE_MEDIA_DESCRIPTION}`, { id: id, description: value })
|
||||
}
|
||||
const togglePollForm = () => {
|
||||
const previousHeight = pollRef.value ? pollRef.value.$el.offsetHeight : 0
|
||||
const toggle = () => {
|
||||
this.openPoll = !this.openPoll
|
||||
if (this.openPoll) {
|
||||
this.polls = ['', '']
|
||||
openPoll.value = !openPoll.value
|
||||
if (openPoll.value) {
|
||||
polls.value = ['', '']
|
||||
} else {
|
||||
this.polls = []
|
||||
polls.value = []
|
||||
}
|
||||
}
|
||||
await toggle()
|
||||
if (this.openPoll) {
|
||||
this.statusHeight = this.statusHeight - this.$refs.poll.$el.offsetHeight
|
||||
} else {
|
||||
this.statusHeight = this.statusHeight + previousHeight
|
||||
}
|
||||
},
|
||||
async addPoll() {
|
||||
const previousPollHeight = this.$refs.poll.$el.offsetHeight
|
||||
await this.polls.push('')
|
||||
const diff = this.$refs.poll.$el.offsetHeight - previousPollHeight
|
||||
this.statusHeight = this.statusHeight - diff
|
||||
},
|
||||
async removePoll(id) {
|
||||
const previousPollHeight = this.$refs.poll.$el.offsetHeight
|
||||
await this.polls.splice(id, 1)
|
||||
const diff = previousPollHeight - this.$refs.poll.$el.offsetHeight
|
||||
this.statusHeight = this.statusHeight + diff
|
||||
},
|
||||
async toggleContentWarning() {
|
||||
const previousHeight = this.$refs.spoiler ? this.$refs.spoiler.offsetHeight : 0
|
||||
await (this.showContentWarning = !this.showContentWarning)
|
||||
if (this.showContentWarning) {
|
||||
this.statusHeight = this.statusHeight - this.$refs.spoiler.offsetHeight
|
||||
} else {
|
||||
this.statusHeight = this.statusHeight + previousHeight
|
||||
}
|
||||
},
|
||||
handleResize(event) {
|
||||
enableResizing.value = false
|
||||
toggle()
|
||||
nextTick(() => {
|
||||
if (openPoll.value) {
|
||||
const currentHeight = pollRef.value ? pollRef.value.$el.offsetHeight : 0
|
||||
statusHeight.value = statusHeight.value - currentHeight
|
||||
} else {
|
||||
statusHeight.value = statusHeight.value + previousHeight
|
||||
}
|
||||
enableResizing.value = true
|
||||
})
|
||||
}
|
||||
const addPoll = () => {
|
||||
enableResizing.value = false
|
||||
polls.value.push('')
|
||||
nextTick(() => {
|
||||
enableResizing.value = true
|
||||
})
|
||||
}
|
||||
const removePoll = (id: number) => {
|
||||
enableResizing.value = false
|
||||
polls.value.splice(id, 1)
|
||||
nextTick(() => {
|
||||
enableResizing.value = true
|
||||
})
|
||||
}
|
||||
const toggleContentWarning = () => {
|
||||
const previousHeight = spoilerRef.value ? spoilerRef.value.offsetHeight : 0
|
||||
enableResizing.value = false
|
||||
showContentWarning.value = !showContentWarning.value
|
||||
nextTick(() => {
|
||||
if (showContentWarning.value) {
|
||||
if (spoilerRef.value) {
|
||||
statusHeight.value = statusHeight.value - spoilerRef.value.offsetHeight
|
||||
}
|
||||
} else {
|
||||
statusHeight.value = statusHeight.value + previousHeight
|
||||
}
|
||||
enableResizing.value = true
|
||||
})
|
||||
}
|
||||
const handleResize = (event: { width: number; height: number }) => {
|
||||
if (!enableResizing.value) return
|
||||
const dialog = document.getElementsByClassName('new-toot-modal').item(0) as HTMLElement
|
||||
if (!dialog) return
|
||||
const dialogStyle = window.getComputedStyle(dialog, null)
|
||||
// Ignore when the modal height already reach window height.
|
||||
const vHeight = this.$refs.dialog.$el.firstChild.style.marginTop
|
||||
const marginTop = (document.documentElement.clientHeight / 100) * parseInt(vHeight)
|
||||
const limitHeight = document.documentElement.clientHeight - marginTop - 80
|
||||
if (this.$refs.dialog.$el.firstChild.offsetHeight >= limitHeight) {
|
||||
const marginTop = dialogStyle.marginTop
|
||||
const limitHeight = document.documentElement.clientHeight - parseInt(marginTop) - 80
|
||||
if (dialog.offsetHeight >= limitHeight) {
|
||||
return
|
||||
}
|
||||
// When emoji picker is opened, resize event has to be stopped.
|
||||
const style = this.$refs.dialog.$el.firstChild.style
|
||||
if (style.overflow === '' || style.overflow === 'hidden') {
|
||||
const pollHeight = this.$refs.poll ? this.$refs.poll.$el.offsetHeight : 0
|
||||
const spoilerHeight = this.$refs.spoiler ? this.$refs.spoiler.offsetHeight : 0
|
||||
const quoteHeight = this.$refs.quote ? this.$refs.quote.$el.offsetHeight : 0
|
||||
const headerHeight = 54
|
||||
const footerHeight = 63
|
||||
this.statusHeight =
|
||||
event.height - footerHeight - headerHeight - this.$refs.preview.offsetHeight - pollHeight - spoilerHeight - quoteHeight
|
||||
}
|
||||
},
|
||||
innerElementOpened() {
|
||||
// if (open) {
|
||||
// this.$refs.dialog.$el.firstChild.style.overflow = 'visible'
|
||||
// } else {
|
||||
// this.$refs.dialog.$el.firstChild.style.overflow = 'hidden'
|
||||
// }
|
||||
const pollHeight = pollRef.value ? pollRef.value.$el.offsetHeight : 0
|
||||
const spoilerHeight = spoilerRef.value ? spoilerRef.value.offsetHeight : 0
|
||||
const quoteHeight = quoteRef.value ? quoteRef.value.$el.offsetHeight : 0
|
||||
const previewHeight = previewRef.value ? previewRef.value.offsetHeight : 0
|
||||
const headerHeight = 54
|
||||
const footerHeight = 66
|
||||
statusHeight.value = event.height - footerHeight - headerHeight - previewHeight - pollHeight - spoilerHeight - quoteHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
visibilityList,
|
||||
statusText,
|
||||
spoilerText,
|
||||
showContentWarning,
|
||||
openPoll,
|
||||
polls,
|
||||
pollExpire,
|
||||
statusHeight,
|
||||
// DOM refs
|
||||
previewRef,
|
||||
imageRef,
|
||||
pollRef,
|
||||
spoilerRef,
|
||||
dialogRef,
|
||||
quoteRef,
|
||||
// computed
|
||||
quoteToMessage,
|
||||
attachedMedias,
|
||||
mediaDescriptions,
|
||||
blockSubmit,
|
||||
sensitive,
|
||||
visibilityIcon,
|
||||
loading,
|
||||
tootMax,
|
||||
displayNameStyle,
|
||||
hashtagInserting,
|
||||
newTootModal,
|
||||
pinedHashtag,
|
||||
// methods
|
||||
close,
|
||||
toot,
|
||||
selectImage,
|
||||
onChangeImage,
|
||||
onPaste,
|
||||
removeAttachment,
|
||||
changeVisibility,
|
||||
changeSensitive,
|
||||
closeConfirm,
|
||||
updateDescription,
|
||||
togglePollForm,
|
||||
addPoll,
|
||||
removePoll,
|
||||
toggleContentWarning,
|
||||
handleResize
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
} from '@/errors/validations'
|
||||
import { MyWindow } from '~/src/types/global'
|
||||
|
||||
const win = (window as any) as MyWindow
|
||||
const win = window as any as MyWindow
|
||||
|
||||
type MediaDescription = {
|
||||
id: string
|
||||
@ -156,8 +156,27 @@ const mutations: MutationTree<NewTootState> = {
|
||||
}
|
||||
}
|
||||
|
||||
export const ACTION_TYPES = {
|
||||
SETUP_LOADING: 'setupLoading',
|
||||
START_LOADING: 'startLoading',
|
||||
STOP_LOADING: 'stopLoading',
|
||||
UPDATE_MEDIA: 'updateMedia',
|
||||
POST_TOOT: 'postToot',
|
||||
OPEN_REPLY: 'openReply',
|
||||
OPEN_QUOTE: 'openQuote',
|
||||
OPEN_MODAL: 'openModal',
|
||||
CLOSE_MODAL: 'closeModal',
|
||||
UPLOAD_IMAGE: 'uploadImage',
|
||||
INCREMENT_MEDIA_COUNT: 'incrementMediaCount',
|
||||
DECREMENT_MEDIA_COUNT: 'decrementMediaCount',
|
||||
RESET_MEDIA_COUNT: 'resetMediaCount',
|
||||
REMOVE_MEDIA: 'removeMedia',
|
||||
UPDATE_HASHTAGS: 'updateHashtags',
|
||||
FETCH_VISIBILITY: 'fetchVisibility'
|
||||
}
|
||||
|
||||
const actions: ActionTree<NewTootState, RootState> = {
|
||||
setupLoading: ({ dispatch }) => {
|
||||
[ACTION_TYPES.SETUP_LOADING]: ({ dispatch }) => {
|
||||
const axiosLoading = new AxiosLoading()
|
||||
axiosLoading.on('start', (_: number) => {
|
||||
dispatch('startLoading')
|
||||
@ -166,17 +185,17 @@ const actions: ActionTree<NewTootState, RootState> = {
|
||||
dispatch('stopLoading')
|
||||
})
|
||||
},
|
||||
startLoading: ({ commit, state }) => {
|
||||
[ACTION_TYPES.START_LOADING]: ({ commit, state }) => {
|
||||
if (state.modalOpen && !state.loading) {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
}
|
||||
},
|
||||
stopLoading: ({ commit, state }) => {
|
||||
[ACTION_TYPES.STOP_LOADING]: ({ commit, state }) => {
|
||||
if (state.modalOpen && state.loading) {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
}
|
||||
},
|
||||
updateMedia: async ({ rootState }, mediaDescription: MediaDescription) => {
|
||||
[ACTION_TYPES.UPDATE_MEDIA]: async ({ rootState }, mediaDescription: MediaDescription) => {
|
||||
if (rootState.TimelineSpace.account.accessToken === undefined || rootState.TimelineSpace.account.accessToken === null) {
|
||||
throw new AuthenticationError()
|
||||
}
|
||||
@ -198,7 +217,7 @@ const actions: ActionTree<NewTootState, RootState> = {
|
||||
throw err
|
||||
})
|
||||
},
|
||||
postToot: async ({ state, commit, rootState, dispatch }, params: TootForm): Promise<Entity.Status> => {
|
||||
[ACTION_TYPES.POST_TOOT]: async ({ state, commit, rootState, dispatch }, params: TootForm): Promise<Entity.Status> => {
|
||||
if (!state.modalOpen) {
|
||||
throw new NewTootModalOpen()
|
||||
}
|
||||
@ -287,7 +306,7 @@ const actions: ActionTree<NewTootState, RootState> = {
|
||||
commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, false)
|
||||
})
|
||||
},
|
||||
openReply: ({ commit, rootState }, message: Entity.Status) => {
|
||||
[ACTION_TYPES.OPEN_REPLY]: ({ commit, rootState }, message: Entity.Status) => {
|
||||
commit(MUTATION_TYPES.SET_REPLY_TO, message)
|
||||
const mentionAccounts = [message.account.acct]
|
||||
.concat(message.mentions.map(a => a.acct))
|
||||
@ -305,18 +324,18 @@ const actions: ActionTree<NewTootState, RootState> = {
|
||||
})
|
||||
commit(MUTATION_TYPES.CHANGE_VISIBILITY_VALUE, value)
|
||||
},
|
||||
openQuote: ({ commit }, message: Entity.Status) => {
|
||||
[ACTION_TYPES.OPEN_QUOTE]: ({ commit }, message: Entity.Status) => {
|
||||
commit(MUTATION_TYPES.SET_QUOTE_TO, message)
|
||||
commit(MUTATION_TYPES.CHANGE_MODAL, true)
|
||||
},
|
||||
openModal: ({ dispatch, commit, state }) => {
|
||||
[ACTION_TYPES.OPEN_MODAL]: ({ dispatch, commit, state }) => {
|
||||
if (!state.replyToMessage && state.pinedHashtag) {
|
||||
commit(MUTATION_TYPES.UPDATE_INITIAL_STATUS, state.hashtags.map(t => `#${t.name}`).join(' '))
|
||||
}
|
||||
commit(MUTATION_TYPES.CHANGE_MODAL, true)
|
||||
dispatch('fetchVisibility')
|
||||
},
|
||||
closeModal: ({ commit }) => {
|
||||
[ACTION_TYPES.CLOSE_MODAL]: ({ commit }) => {
|
||||
commit(MUTATION_TYPES.CHANGE_MODAL, false)
|
||||
commit(MUTATION_TYPES.UPDATE_INITIAL_STATUS, '')
|
||||
commit(MUTATION_TYPES.UPDATE_INITIAL_SPOILER, '')
|
||||
@ -328,7 +347,7 @@ const actions: ActionTree<NewTootState, RootState> = {
|
||||
commit(MUTATION_TYPES.CHANGE_SENSITIVE, false)
|
||||
commit(MUTATION_TYPES.CHANGE_VISIBILITY_VALUE, Visibility.Public.value)
|
||||
},
|
||||
uploadImage: async ({ commit, state, rootState }, image: any) => {
|
||||
[ACTION_TYPES.UPLOAD_IMAGE]: async ({ commit, state, dispatch, rootState }, image: any) => {
|
||||
if (state.attachedMedias.length > 3) {
|
||||
throw new NewTootAttachLength()
|
||||
}
|
||||
@ -348,6 +367,7 @@ const actions: ActionTree<NewTootState, RootState> = {
|
||||
commit(MUTATION_TYPES.CHANGE_BLOCK_SUBMIT, false)
|
||||
if (res.data.type === 'unknown') throw new NewTootUnknownType()
|
||||
commit(MUTATION_TYPES.APPEND_ATTACHED_MEDIAS, res.data)
|
||||
dispatch(ACTION_TYPES.INCREMENT_MEDIA_COUNT)
|
||||
return res.data
|
||||
})
|
||||
.catch(err => {
|
||||
@ -356,26 +376,26 @@ const actions: ActionTree<NewTootState, RootState> = {
|
||||
throw err
|
||||
})
|
||||
},
|
||||
incrementMediaCount: ({ commit, state }) => {
|
||||
[ACTION_TYPES.INCREMENT_MEDIA_COUNT]: ({ commit, state }) => {
|
||||
commit(MUTATION_TYPES.UPDATE_MEDIA_COUNT, state.attachedMediaCount + 1)
|
||||
},
|
||||
decrementMediaCount: ({ commit, state }) => {
|
||||
[ACTION_TYPES.DECREMENT_MEDIA_COUNT]: ({ commit, state }) => {
|
||||
commit(MUTATION_TYPES.UPDATE_MEDIA_COUNT, state.attachedMediaCount - 1)
|
||||
},
|
||||
resetMediaCount: ({ commit }) => {
|
||||
[ACTION_TYPES.RESET_MEDIA_COUNT]: ({ commit }) => {
|
||||
commit(MUTATION_TYPES.UPDATE_MEDIA_COUNT, 0)
|
||||
},
|
||||
removeMedia: ({ commit, dispatch }, media: Entity.Attachment) => {
|
||||
[ACTION_TYPES.REMOVE_MEDIA]: ({ commit, dispatch }, media: Entity.Attachment) => {
|
||||
commit(MUTATION_TYPES.REMOVE_MEDIA, media)
|
||||
commit(MUTATION_TYPES.REMOVE_MEDIA_DESCRIPTION, media.id)
|
||||
dispatch('decrementMediaCount')
|
||||
dispatch(ACTION_TYPES.DECREMENT_MEDIA_COUNT)
|
||||
},
|
||||
updateHashtags: ({ commit, state }, tags: Array<Entity.Tag>) => {
|
||||
[ACTION_TYPES.UPDATE_HASHTAGS]: ({ commit, state }, tags: Array<Entity.Tag>) => {
|
||||
if (state.pinedHashtag && tags.length > 0) {
|
||||
commit(MUTATION_TYPES.UPDATE_HASHTAGS, tags)
|
||||
}
|
||||
},
|
||||
fetchVisibility: async ({ commit, rootState }) => {
|
||||
[ACTION_TYPES.FETCH_VISIBILITY]: async ({ commit, rootState }) => {
|
||||
const client = generator(
|
||||
rootState.TimelineSpace.sns,
|
||||
rootState.TimelineSpace.account.baseURL,
|
||||
|
Loading…
x
Reference in New Issue
Block a user