* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import type { IUploadListRenderlessParams, IFileUploadFile, IUploadListVideoParam } from '@/types'
import { xss } from '@opentiny/utils'
import { addResizeListener, removeResizeListener } from '@opentiny/utils'
export const parsePercentage =
() =>
(val: string): number =>
parseInt(val, 10)
export const handleClick =
({ props, api, parent }: Pick<IUploadListRenderlessParams, 'props' | 'api' | 'parent'>) =>
(e: Event, file: IFileUploadFile): Function => {
e.preventDefault()
if (parent.state.isEdm) {
const { downloadFile } = api.getApi()
props.openDownloadFile && downloadFile && downloadFile(file)
} else {
props.openDownloadFile && api.downloadFile(file)
}
return props.handlePreview && props.handlePreview(file)
}
export const downloadFile = (service: IUploadListRenderlessParams['service']) => (file: IFileUploadFile) => {
const data = file && file.response && file.response.data
let responseFile
if (Array.isArray(data)) {
responseFile = data[0]
} else if (data && typeof data === 'object') {
for (let key in data) {
responseFile = data[key]
break
}
}
if (responseFile) {
service.getFileDownloadUrl().then((url) => {
window.open(xss.filterUrl(url + '&id=' + responseFile.attachmentId + '&type=AttachmentDemo')).opener = null
})
} else if (file.url) {
window.open(xss.filterUrl(file.url)).opener = null
} else {
throw new Error('[TINY Error][FileUpload]file.url must not be empty')
}
}
export const picturefilePreview = (state: IUploadListRenderlessParams['state']) => (index: number) => {
state.startPostion = index
state.shows = true
}
export const getDeleteData = (emit: IUploadListRenderlessParams['emit']) => (data: string[]) => {
emit('remove', data)
}
export const showOperatePanel =
({ state }: Pick<IUploadListRenderlessParams, 'state'>) =>
({ file }: { file: IFileUploadFile }) => {
state.currentFile = file
state.showPanel = true
}
export const reUpload =
({ emit, props, parent }: Pick<IUploadListRenderlessParams, 'emit' | 'props' | 'parent'>) =>
(file: IFileUploadFile) => {
parent.state.isEdm
? emit('start', [file && file.raw], '', true)
: props.handleReUpload && props.handleReUpload(file)
}
const addPlayEventListener = ({ type, el }: IUploadListVideoParam, fn: Function) => el && el.addEventListener(type, fn)
const removePlayEventListener = ({ type, el }: IUploadListVideoParam, fn: Function) =>
el && el.removeEventListener(type, fn)
export const play =
({ vm, api, props }: Pick<IUploadListRenderlessParams, 'vm' | 'api' | 'props'>) =>
({ file, index, type }: { file: IFileUploadFile; index: number; type: string }) => {
if (props.isHwh5) {
return props.triggerPlay(file, type, 'play')
}
const videoOrAudioEle = vm.$refs[type + (file.uid || index)] && vm.$refs[type + (file.uid || index)][0]
if (file.isPlay) return api.pause({ file, index, type })
if (videoOrAudioEle && videoOrAudioEle.play) {
file.playEvent = () => {
if (file) {
file.isPlay = false
removePlayEventListener({ type: 'ended', el: videoOrAudioEle }, file.playEvent)
}
}
file.el = videoOrAudioEle
removePlayEventListener({ type: 'ended', el: videoOrAudioEle }, file.playEvent)
addPlayEventListener({ type: 'ended', el: videoOrAudioEle }, file.playEvent)
vm.$set(file, 'isPlay', true)
videoOrAudioEle.play()
}
}
export const pause =
({ vm, props }: Pick<IUploadListRenderlessParams, 'vm' | 'props'>) =>
({ file, index, type }: { file: IFileUploadFile; index: number; type: string }) => {
if (props.isHwh5) {
return props.triggerPlay(file, type, 'pause')
}
const videoOrAudioEle = vm.$refs[type + (file.uid || index)] && vm.$refs[type + (file.uid || index)][0]
if (videoOrAudioEle && videoOrAudioEle.pause) {
removePlayEventListener({ type: 'ended', el: videoOrAudioEle }, file.playEvent)
file.isPlay = false
videoOrAudioEle.pause()
}
}
export const handleLoadedmetadata =
({ vm }: Pick<IUploadListRenderlessParams, 'vm'>) =>
({ e, file }: { e: Event; file: IFileUploadFile }) => {
vm.$set(file, 'totalSecond', parseInt(e.target?.duration))
vm.$set(file, 'currentSecond', parseInt(e.target?.currentTime))
}
export const handleTimeupdate =
() =>
({ e, file }: { e: Event; file: IFileUploadFile }) => {
file.currentSecond = parseInt(e.target?.currentTime)
}
export const getFileType =
() =>
({ file }: { file: IFileUploadFile }): string =>
file.name && file.name.split('.')[file.name.split('.').length - 1].toLowerCase()
export const getFileIcon =
({ constants }: Pick<IUploadListRenderlessParams, 'constants'>) =>
({ type }: { type: string }): { name: string; color: string } => {
const { EXCEL, FILE, PDF, PICTURE, PPT, TEXT, WORD, ZIP, VIDEO, AUDIO } = constants.FILE_TYPE
let iconTypes = {
[EXCEL]: {
name: 'icon-excel-type',
color: '#09AA71'
},
[FILE]: {
name: 'icon-file-type',
color: '#09AA71'
},
[PDF]: {
name: 'icon-pdf-type',
color: '#E02128'
},
[PICTURE]: {
name: 'icon-picture-type',
color: '#5531EB'
},
[PPT]: {
name: 'icon-ppt-type',
color: '#E02128'
},
[TEXT]: {
name: 'icon-text-type',
color: '#2CB8C9'
},
[WORD]: {
name: 'icon-word-type',
color: '#0067D1'
},
[ZIP]: {
name: 'icon-zip-type',
color: '#2CB8C9'
},
[VIDEO]: {
name: 'icon-video-type',
color: '#0067D1'
},
[AUDIO]: {
name: 'icon-audio',
color: '#5531EB'
},
default: {
name: 'icon-other-type',
color: '#9185F0'
}
}
for (const typeName in iconTypes) {
if (Object.hasOwnProperty.call(iconTypes, typeName)) {
const typeValue = iconTypes[typeName]
delete iconTypes[typeName]
typeName.split('/').forEach((type) => (iconTypes[type] = typeValue))
}
}
return iconTypes[type] || iconTypes.default
}
export const remove =
({ emit }: Pick<IUploadListRenderlessParams, 'emit'>) =>
({ file }: { file: IFileUploadFile }) =>
emit('remove', file)
export const calcUploadListLiWidth =
({ vm, nextTick, props, constants }: Pick<IUploadListRenderlessParams, 'vm' | 'nextTick' | 'props' | 'constants'>) =>
() => {
const { listType } = props
const { LIST_TYPE } = constants
nextTick(() => {
const uploadListEle = vm.$refs.uploadList
const uploadListLiEle = uploadListEle && uploadListEle.querySelectorAll('[data-tag="tiny-upload-list-item"]')
if (!uploadListEle || !(uploadListLiEle && uploadListLiEle[0])) return
if (listType === LIST_TYPE.TEXT || listType === LIST_TYPE.SAAS) {
const { minWidth } = window.getComputedStyle(uploadListLiEle && uploadListLiEle[0])
const marginRight = 8
const num = Math.floor(uploadListEle.offsetWidth / (parseFloat(minWidth) + marginRight))
Array.from(uploadListLiEle).forEach((li, index) => {
if (!((index + 1) % num) || num === 1) {
li.style.marginRight = 0
li.style.width = `${100 / num}%`
} else {
li.style.marginRight = `${marginRight}px`
li.style.width = `calc(${100 / num}% - ${marginRight}px)`
}
})
}
})
}
export const calcVisible =
({ props, constants, emit }: Pick<IUploadListRenderlessParams, 'props' | 'constants' | 'emit'>) =>
() => {
const { SUCESS } = constants.FILE_STATUS
const isAllSuccess = props.files.every(({ status }) => status === SUCESS || !status)
emit('update:visible', !isAllSuccess)
}
export const getNotSuccessFiles =
({ props, constants }: Pick<IUploadListRenderlessParams, 'props' | 'constants'>) =>
(): object[] => {
const { SUCESS } = constants.FILE_STATUS
let files = props.files
if (props.mode === constants.MODE.BUBBLE && props.listType === constants.LIST_TYPE.TEXT) {
files = props.files.filter(({ status }) => status !== SUCESS)
}
return files
}
export const chooseFile =
({ state, constants }: Pick<IUploadListRenderlessParams, 'state' | 'constants'>) =>
(type: string) => {
const { SOURCE_AUDIO } = constants.SOURCE_TYPE
if (type === SOURCE_AUDIO) {
state.showAudioPanel = true
} else {
state.showTriggerPanel = true
}
state.triggerClickType = type
}
export const handleTriggerClick =
({ state, props }: Pick<IUploadListRenderlessParams, 'state' | 'props'>) =>
($event: Event, type: string) => {
return new Promise((resolve) => {
let res = props.triggerClick($event, state.triggerClickType, type)
if (res && res.then) {
res
.then(() => {
state.showTriggerPanel = false
resolve()
})
.catch(() => {
state.showTriggerPanel = false
state.showAudioPanel = false
})
} else {
state.showTriggerPanel = false
resolve()
}
})
}
export const mounted =
({ api, vm }: Pick<IUploadListRenderlessParams, 'api' | 'vm'>) =>
() => {
const el = vm.$refs.uploadList
if (el) {
addResizeListener(el, api.calcUploadListLiWidth)
vm._removeResizeListener = () => removeResizeListener(el, api.calcUploadListLiWidth)
}
}
export const destroyed =
({ props, vm }: Pick<IUploadListRenderlessParams, 'props' | 'vm'>) =>
() => {
if (vm._removeResizeListener) {
vm._removeResizeListener()
vm._removeResizeListener = null
}
props.files.forEach((file) => {
removePlayEventListener({ type: 'ended', el: file.el }, file.playEvent)
delete file.playEvent
delete file.isPlay
delete file.el
})
}