{"version":3,"file":"XFile.min.mjs","sources":["../../../../src/shapes/canvasx/XFile.ts"],"sourcesContent":["import { TClassProperties } from '../../typedefs';\nimport { classRegistry } from '../../ClassRegistry';\nimport { createFileDefaultControls } from '../../controls/commonControls';\nimport { Shadow } from '../../Shadow';\nimport { Rect } from '../../shapes/Rect';\nimport { FabricImage } from '../Image';\n\nimport type { FabricObjectProps, SerializedObjectProps } from '../Object/types';\n\nimport { TOptions } from '../../typedefs';\nimport { loadImage } from '../../util';\n\nexport type WBFileSource =\n  | string\n  | HTMLImageElement\n  | HTMLVideoElement\n  | HTMLCanvasElement;\n\ninterface UniqueWBFileProps {\n  srcFromAttribute: boolean;\n  minimumScaleTrigger: number;\n  cropX: number;\n  cropY: number;\n  imageSmoothing: boolean;\n  crossOrigin: string | null;\n}\n\nexport const WBFileDefaultValues: Partial<TClassProperties<XFile>> = {\n  minWidth: 20,\n  dynamicMinWidth: 2,\n  lockScalingFlip: true,\n  noScaleCache: false,\n\n  splitByGrapheme: true,\n  objType: 'WBFile',\n  height: 200,\n  maxHeight: 200,\n};\n\nexport interface SerializedWBFileProps extends SerializedObjectProps {\n  src: string;\n  crossOrigin: string | null;\n  filters: any[];\n  resizeFilter?: any;\n  cropX: number;\n  cropY: number;\n}\nexport interface WBFileProps extends FabricObjectProps, UniqueWBFileProps {}\n\nexport class XFile<\n  Props extends TOptions<WBFileProps> = Partial<WBFileProps>\n> extends FabricImage {\n  declare minWidth: number;\n\n  /* boardx cusotm function */\n  declare id: string;\n  declare maxHeight: number;\n\n  declare objType: string;\n\n  declare locked: boolean;\n\n  declare whiteboardId: string;\n\n  declare userId: string;\n\n  declare timestamp: Date;\n\n  declare verticalAlign: string;\n\n  declare zIndex: number;\n\n  declare lines: object[];\n\n  declare url: string;\n  declare fileSrc: string;\n\n  declare relationship: object[];\n  declare name: string;\n  declare isUploading: boolean;\n\n  public extendPropeties = [\n    'objType',\n    'whiteboardId',\n    'userId',\n    'timestamp',\n    'zIndex',\n    'locked',\n    'verticalAlign',\n    'lines',\n    'id',\n    'zIndex',\n    'relationship',\n    'url',\n  ];\n\n  declare dynamicMinWidth: number;\n\n  /**\n   * Use this boolean property in order to split strings that have no white space concept.\n   * this is a cheap way to help with chinese/japanese\n   * @type Boolean\n   * @since 2.6.0\n   */\n  declare splitByGrapheme: boolean;\n\n  static ownDefaults: Record<string, any> = WBFileDefaultValues;\n\n  static getDefaults() {\n    return {\n      ...super.getDefaults(),\n      controls: createFileDefaultControls(),\n      ...XFile.ownDefaults,\n    };\n  }\n\n  //@ts-ignore\n  constructor(element: WBFileSource, options: Props) {\n    super(element.toString(), options);\n    this.filters = [];\n    // this.resizeFilters = [];\n    this.name = options.name;\n    this.shadow = new Shadow({\n      color: 'rgba(217, 161, 177, 0.54)',\n      offsetX: 1,\n      offsetY: 2,\n      blur: 4,\n      id: 310,\n    });\n    (this.clipPath = new Rect({\n      left: 0,\n      top: 0,\n      rx: 8,\n      ry: 8,\n      width: 230,\n      height: 248,\n      fill: '#000000',\n    })),\n      // // double click\n      // this.on('mousedblclick', () => {\n      //   if (this.src || !this.isUploading) {\n      //     //@ts-ignore\n      //     if (Boardx.Util.isMobile()) {\n      //       getWindow().parent.location.href = this.fileSrc\n      //         ? this.fileSrc\n      //         : this.src;\n      //     } else if (this.isFileVideo(this.name)) {\n      //       store.dispatch(handleSetVideoUrl(this.src));\n      //     } else {\n      //       getWindow()\n      //         .open(this.fileSrc ? this.fileSrc : this.src, '_blank')\n      //         .focus();\n      //     }\n      //   }\n      // });\n      // this.initDoubleClickSimulation();\n      (this.width = 230);\n    this.height = 248;\n  }\n  // setElement(element: WBFileSource, size: Partial<TSize> = {}) {\n  //   this.removeTexture(this.cacheKey);\n  //   this.removeTexture(`${this.cacheKey}_filtered`);\n  //   this._element = element;\n  //   this._originalElement = element;\n  //   this._setWidthHeight(size);\n  //   element.classList.add(WBFile.CSS_CANVAS);\n  //   if (this.filters.length !== 0) {\n  //     this.applyFilters();\n  //   }\n  //   // resizeFilters work on the already filtered copy.\n  //   // we need to apply resizeFilters AFTER normal filters.\n  //   // applyResizeFilters is run more often than normal filters\n  //   // and is triggered by user interactions rather than dev code\n  //   if (this.resizeFilter) {\n  //     this.applyResizeFilters();\n  //   }\n  // }\n\n  // toObject(propertiesToInclude: Array<any>): object {\n  //   return super.toObject(\n  //     [...this.extendPropeties, 'minWidth', 'splitByGrapheme'].concat(\n  //       propertiesToInclude\n  //     )\n  //   );\n  // }\n  getWidgetMenuList() {\n    const menuList = [];\n    if (this.locked) {\n      menuList.push('objectLock');\n    } else {\n      menuList.push('more');\n      menuList.push('objectLock');\n      menuList.push('delete');\n      menuList.push('fileName');\n      menuList.push('borderLineIcon');\n      menuList.push('fileDownload');\n      const fileType = this.name.split('.').pop() || '';\n      if (\n        fileType.toLocaleLowerCase() == 'mp3' ||\n        fileType.toLocaleLowerCase() === 'm4a' ||\n        fileType.toLocaleLowerCase() === 'wav' ||\n        fileType.toLocaleLowerCase() === 'aac' ||\n        fileType.toLocaleLowerCase() === 'flac' ||\n        fileType.toLocaleLowerCase() === 'ogg' ||\n        fileType.toLocaleLowerCase() === 'aiff' ||\n        fileType.toLocaleLowerCase() === 'wma' ||\n        fileType.toLocaleLowerCase() === 'ape'\n      ) {\n        menuList.push('audioToText');\n      }\n    }\n    return menuList;\n  }\n  getWidgetMenuLength() {\n    if (this.locked) return 50;\n    return 60;\n  }\n  getContextMenuList() {\n    let menuList;\n    if (this.locked) {\n      menuList = [\n        'Bring forward',\n        'Bring to front',\n        'Send backward',\n        'Send to back',\n      ];\n    } else {\n      menuList = [\n        'Bring forward',\n        'Bring to front',\n        'Send backward',\n        'Send to back',\n        'Duplicate',\n        'Copy',\n        'Paste',\n        'Cut',\n        'Delete',\n      ];\n    }\n    if (this.locked) {\n      menuList.push('Unlock');\n    } else {\n      menuList.push('Lock');\n    }\n\n    return menuList;\n  }\n\n  InitializeEvent = () => {\n    const zoom = this.canvas?.getZoom() || 1;\n    // this.on('mousedblclick', (memo) => {\n    //   const offsetX = memo.e.offsetX - (this.left - this.width / 2);\n    //   const offsetY = memo.e.offsetY - (this.top - this.height / 2);\n\n    //   if (\n    //     offsetX < 20 ||\n    //     offsetX > 480 ||\n    //     offsetY < 20 ||\n    //     offsetY > 480 ||\n    //     (offsetY > 64 && offsetY < 446)\n    //   ) {\n    //     getWindow().open(this.url, '_blank').focus();\n    //   } else {\n    //     let text = this.title;\n    //     const textarea = $('#urlTextarea');\n    //     const cvsPosition = $('#canvasContainer').offset();\n    //     let fontSize = 20 * this.scaleX * zoom;\n    //     const left = `${\n    //       cvsPosition.left +\n    //       (this.left - (this.width / 2 - 22) * this.scaleX) * zoom\n    //     }px`;\n    //     let top = `${\n    //       cvsPosition.top +\n    //       (this.top - (this.height / 2 - 22) * this.scaleY) * zoom\n    //     }px`;\n    //     const newWidth = (this.width - 44) * this.scaleX * zoom;\n    //     const width = `${newWidth}px`;\n    //     let height = `${40 * this.scaleY * zoom}px`;\n    //     const paddingLeft = `${10 * this.scaleY * zoom}px`;\n    //     let lineHeight = '40px';\n    //     textarea.data('type', 'title');\n    //     if (offsetY >= 446) {\n    //       text = this.description;\n    //       fontSize = 15 * this.scaleX * zoom;\n    //       top = `${\n    //         cvsPosition.top +\n    //         (this.top + (this.height / 2 - 52) * this.scaleY) * zoom\n    //       }px`;\n    //       height = `${30 * this.scaleY * zoom}px`;\n    //       lineHeight = '30px';\n    //       textarea.data('type', 'description');\n    //     }\n    //     textarea\n    //       .data('widget', this)\n    //       .css('left', left)\n    //       .css('top', top)\n    //       .css('padding-left', paddingLeft)\n    //       .css('width', width)\n    //       .css('height', height)\n    //       .css('background-color', 'white')\n    //       .css('font-size', `${fontSize}px`)\n    //       .css('font-family', 'Arial')\n    //       .css('line-height', lineHeight)\n    //       .val(text)\n    //       .show()\n    //       .focus();\n    //   }\n    // });\n    // this.on('removed', this.removedListener);\n  };\n  // removedListener() {\n  //   if (this.loading) {\n  //     this.loading.remove();\n  //     this.loading = null;\n  //   }\n  // }\n  // initDoubleClickSimulation() {\n  //   this.__lastClickTime = +new Date();\n  //   this.on('touchstart', this.onMouseDown.bind(this));\n  //   this.on('mousedown', this.onMouseDown.bind(this));\n  // }\n\n  // onMouseUp(options) {\n  //   this.__newClickTime = +new Date();\n  //   if (this.__newClickTime - this.__lastClickTime < 500) {\n  //     this.fire('dblclick', options);\n  //     this._stopEvent(options.e);\n  //   }\n  //   this.__lastClickTime = this.__newClickTime;\n  // }\n\n  // _stopEvent(e) {\n  //   e.preventDefault();\n  //   e.stopPropagation();\n  // }\n  //@ts-ignore\n  drawObject(ctx: CanvasRenderingContext2D) {\n    let elementToDraw = null;\n    // draw border\n    ctx.beginPath();\n    ctx.fillStyle = 'rgba(255,255,255,0)';\n    ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height);\n    ctx.lineWidth = 0;\n    ctx.strokeStyle = '#ffffff';\n    ctx.moveTo(-this.width / 2, -this.height / 2);\n    ctx.stroke();\n\n    if (\n      this.isMoving === false &&\n      // this.resizeFilters.length &&\n      this._needsResize()\n    ) {\n      this._lastScaleX = this.scaleX;\n      this._lastScaleY = this.scaleY;\n      // elementToDraw = this.applyFilters(\n      //   null,\n      //   this.resizeFilters,\n      //   this._filteredEl || this._originalElement,\n      //   true\n      // );\n    } else {\n      elementToDraw = this._element;\n    }\n\n    const imgWidth =\n      this.name.substring(this.name.lastIndexOf('.') + 1) === 'pdf' ? 320 : 230;\n    const imgHeight =\n      this.name.substring(this.name.lastIndexOf('.') + 1) === 'pdf' ? 453 : 160;\n\n    if (elementToDraw) {\n      ctx.drawImage(\n        elementToDraw,\n        -this.width / 2,\n        -this.height / 2,\n        imgWidth,\n        imgHeight\n      );\n    }\n\n    if (this.name.substring(this.name.lastIndexOf('.') + 1) !== 'pdf') {\n      this.renderTitle(ctx, this.name);\n    }\n    this._renderStroke(ctx);\n  }\n\n  getFileType(name = '') {\n    let fileType = '';\n    switch (name.substring(name.lastIndexOf('.') + 1)) {\n      case 'doc':\n      case 'docx':\n        fileType = 'Word Document';\n        break;\n      case 'xls':\n      case 'xlsx':\n        fileType = 'Excel Document';\n        break;\n      case 'ppt':\n      case 'pptx':\n        fileType = 'PPT Document';\n        break;\n      case 'pdf':\n        fileType = 'PDF Document';\n        break;\n      case 'zip':\n        fileType = 'ZIP File';\n        break;\n      case 'mp4':\n        fileType = 'Video Document';\n        break;\n      case 'webm':\n        fileType = 'Video Document';\n        break;\n      default:\n        fileType = 'Other Document';\n        break;\n    }\n    return fileType;\n  }\n\n  isFileVideo(name: string) {\n    if (!name) return false;\n    const FileType = this.name.split('.').pop() || '';\n    switch (name.substr(name.lastIndexOf('.') + 1).toUpperCase()) {\n      case 'MP4':\n        return true;\n      case 'WEBM':\n        return true;\n      default:\n        return false;\n    }\n  }\n\n  renderTitle(ctx: any, title: string) {\n    const maxWidth = this.width;\n    const x = -this.width / 2;\n    const y = this.height / 2 - 60;\n\n    ctx.font = '16px Arial';\n    ctx.fillStyle = 'rgba(255, 255, 255, 1)';\n\n    // white board behind the title\n    ctx.fillRect(x, y - 29, maxWidth, 90);\n    ctx.fillStyle = '#190FA1';\n\n    // helper function to convert string\n    const GB2312UnicodeConverter = {\n      ToUnicode(str: string) {\n        return escape(str).toLocaleLowerCase().replace(/%u/gi, '\\\\u');\n      },\n      ToGB2312(str: string) {\n        return unescape(str.replace(/\\\\u/gi, '%u'));\n      },\n    };\n    // Handle non-unicode or non-utf8 coding string\n    const unicodeTitle = GB2312UnicodeConverter.ToUnicode(title);\n\n    // handle the situation that the website's title is null\n    if (title === null || unicodeTitle.indexOf('\\\\ufffd') !== -1 || !title) {\n      const firstChar = this.url.indexOf('.');\n      const lastChar = this.url.indexOf('.', firstChar + 1);\n      this.name = this.url.substring(firstChar + 1, lastChar);\n    }\n\n    // title setting\n    this.wrapText(ctx, title, x + 15, y - 5, maxWidth - 20, 23);\n\n    // url setting\n    const newurl = this.url\n      ? `${this.url.split('/')[0]}/${this.url.split('/')[1]}/${\n          this.url.split('/')[2]\n        }`\n      : '';\n    ctx.font = '12px Arial';\n    ctx.fillStyle = 'rgba(35, 41, 48, 0.65)';\n    // gray square in front of website\n    this.wrapText(ctx, newurl, x + 15, y + 45, maxWidth - 20, 25);\n  }\n\n  changeFileImgUrl(targetSrc: string) {\n    this.setSrc(targetSrc);\n  }\n\n  wrapText(\n    context: any,\n    text: any,\n    x: number,\n    y: number,\n    maxWidth: number,\n    lineHeight: number\n  ) {\n    let words = '';\n    if (text) words = text.split(' ');\n\n    let line = '';\n    let lineCount = 1;\n    let tempLine = '';\n    let _y = y;\n\n    // handle non-English char\n    if (escape(text).indexOf('%u') < 0) {\n      // only the English char\n      for (let n = 0; n < words.length; n++) {\n        if (lineCount === 3) return;\n        if (n !== 0) tempLine = `${line.slice(0, -3)}...`;\n        const testLine = `${line + words[n]} `;\n        const metrics = context.measureText(testLine);\n        const testWidth = metrics.width;\n        if (testWidth > maxWidth && n > 0) {\n          if (lineCount === 2) {\n            line = tempLine;\n          }\n          context.fillText(line, x, _y);\n          line = `${words[n]} `;\n          _y += lineHeight;\n          lineCount++;\n        } else {\n          line = testLine;\n        }\n      }\n    } else {\n      for (let n = 0; n < text.length; n++) {\n        if (lineCount === 3) return;\n        if (n !== 0) tempLine = `${line.slice(0, -2)}...`;\n        const testLine = `${line + text[n]}`;\n        const metrics = context.measureText(testLine);\n        const testWidth = metrics.width;\n        if (testWidth > maxWidth && n > 0) {\n          if (lineCount === 2) {\n            line = tempLine;\n          }\n          context.fillText(line, x, _y);\n          line = `${text[n]}`;\n          _y += lineHeight;\n          lineCount++;\n        } else {\n          line = testLine;\n        }\n      }\n    }\n    if (lineCount < 3) context.fillText(line, x, _y);\n  }\n  getFileIconURL(name: string) {\n    let fileIconURL = '';\n    switch (name.substring(name.lastIndexOf('.') + 1)) {\n      case 'doc':\n      case 'docx':\n        fileIconURL = '/fileIcons/word.png';\n        break;\n      case 'xls':\n      case 'xlsx':\n        fileIconURL = '/fileIcons/excel.png';\n        break;\n      case 'ppt':\n      case 'pptx':\n        fileIconURL = '/fileIcons/ppt.png';\n        break;\n      case 'pdf':\n        fileIconURL = '/fileIcons/pdf.svg';\n        break;\n      case 'zip':\n        fileIconURL = '/fileIcons/zip.png';\n        break;\n      case 'mp4':\n        fileIconURL = '/fileIcons/mp4.png';\n        break;\n\n      case 'webm':\n        fileIconURL = '/fileIcons/mp4.png';\n        break;\n      default:\n        fileIconURL = '/fileIcons/file.png';\n        break;\n    }\n    return fileIconURL;\n  }\n  fromURL<T extends TOptions<SerializedWBFileProps>>(\n    fileOptions: any\n  ): Promise<XFile> {\n    return new Promise(async (resolve, reject) => {\n      const url = fileOptions.previewImage\n        ? fileOptions.previewImage\n        : this.getFileIconURL(fileOptions.name);\n      try {\n        const loadedImg = await loadImage(url, {\n          ...fileOptions,\n          crossOrigin: 'anonymous',\n        });\n        resolve(new XFile(loadedImg, fileOptions));\n      } catch (error) {\n        reject(error);\n      }\n    });\n  }\n}\nclassRegistry.setClass(XFile);\n"],"names":["WBFileDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","splitByGrapheme","objType","height","maxHeight","XFile","FabricImage","getDefaults","_objectSpread","super","controls","createFileDefaultControls","ownDefaults","constructor","element","options","toString","_defineProperty","this","_this$canvas","canvas","getZoom","filters","name","shadow","Shadow","color","offsetX","offsetY","blur","id","clipPath","Rect","left","top","rx","ry","width","fill","getWidgetMenuList","menuList","locked","push","fileType","split","pop","toLocaleLowerCase","getWidgetMenuLength","getContextMenuList","drawObject","ctx","elementToDraw","beginPath","fillStyle","fillRect","lineWidth","strokeStyle","moveTo","stroke","isMoving","_needsResize","_lastScaleX","scaleX","_lastScaleY","scaleY","_element","imgWidth","substring","lastIndexOf","imgHeight","drawImage","renderTitle","_renderStroke","getFileType","arguments","length","undefined","isFileVideo","substr","toUpperCase","title","maxWidth","x","y","font","unicodeTitle","ToUnicode","str","escape","replace","ToGB2312","unescape","indexOf","firstChar","url","lastChar","wrapText","newurl","concat","changeFileImgUrl","targetSrc","setSrc","context","text","lineHeight","words","line","lineCount","tempLine","_y","n","slice","testLine","measureText","fillText","getFileIconURL","fileIconURL","fromURL","fileOptions","Promise","async","resolve","reject","previewImage","loadedImg","loadImage","crossOrigin","error","classRegistry","setClass"],"mappings":"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"}