michielbdejong/solid-ui

View on GitHub
src/chat/message.js

Summary

Maintainability
C
1 day
Test Coverage
/* global $rdf */

import { messageToolbar, sentimentStripLinked } from './messageTools'
const UI = {
  authn: require('../authn/authn'),
  icons: require('../iconBase'),
  log: require('../log'),
  ns: require('../ns'),
  media: require('../media-capture'),
  pad: require('../pad'),
  rdf: require('rdflib'),
  store: require('../store'),
  style: require('../style'),
  utils: require('../utils'),
  widgets: require('../widgets')
}
const dom = UI.dom || window.document
// const kb = UI.store

// module.exports = { renderMessage, creatorAndDate, creatorAndDateHorizontal }

const messageBodyStyle = UI.style.messageBodyStyle

// const { messageToolbar, sentimentStripLinked } = require('./messageTools')
const label = UI.utils.label

export function elementForImageURI (imageUri, options) {
  const img = dom.createElement('img')
  let height = '10'
  if (options.inlineImageHeightEms) {
    height = ('' + options.inlineImageHeightEms).trim()
  }
  img.setAttribute(
    'style',
    'max-height: ' + height + 'em; border-radius: 1em; margin: 0.7em;'
  )
  // UI.widgets.makeDropTarget(img, handleURIsDroppedOnMugshot, droppedFileHandler)
  if (imageUri) img.setAttribute('src', imageUri)
  const anchor = dom.createElement('a')
  anchor.setAttribute('href', imageUri)
  anchor.setAttribute('target', 'images')
  anchor.appendChild(img)
  UI.widgets.makeDraggable(img, $rdf.sym(imageUri))
  return anchor
}

var anchor = function (text, term) {
  // If there is no link return an element anyway
  var a = dom.createElement('a')
  if (term && term.uri) {
    a.setAttribute('href', term.uri)
    a.addEventListener('click', UI.widgets.openHrefInOutlineMode, true)
    a.setAttribute('style', 'color: #3B5998; text-decoration: none; ') // font-weight: bold
  }
  a.textContent = text
  return a
}

function nick (person) {
  var s = UI.store.any(person, UI.ns.foaf('nick'))
  if (s) return '' + s.value
  return '' + label(person)
}

export function creatorAndDate (td1, creator, date, message) {
  var nickAnchor = td1.appendChild(anchor(nick(creator), creator))
  if (creator.uri) {
    UI.store.fetcher.nowOrWhenFetched(creator.doc(), undefined, function (
      _ok,
      _body
    ) {
      nickAnchor.textContent = nick(creator)
    })
  }
  td1.appendChild(dom.createElement('br'))
  td1.appendChild(anchor(date, message))
}

export function creatorAndDateHorizontal (td1, creator, date, message) {
  var nickAnchor = td1.appendChild(anchor(label(creator), creator))
  if (creator.uri) {
    UI.store.fetcher.nowOrWhenFetched(creator.doc(), undefined, function (
      _ok,
      _body
    ) {
      nickAnchor.textContent = nick(creator)
    })
  }
  const dateBit = td1.appendChild(anchor(date, message))
  dateBit.style.fontSize = '80%'
  dateBit.style.marginLeft = '1em'
  td1.appendChild(dom.createElement('br'))
}

// BODY of renderMessage

export function renderMessage (
  messageTable,
  bindings,
  fresh,
  options,
  userContext
) {
  var colorizeByAuthor =
    options.colorizeByAuthor === '1' || options.colorizeByAuthor === true

  var creator = bindings['?creator']
  var message = bindings['?msg']
  var date = bindings['?date']
  var content = bindings['?content']

  var dateString = date.value
  var messageRow = dom.createElement('tr')
  messageRow.AJAR_date = dateString
  messageRow.AJAR_subject = message

  if (options.selectedMessage && options.selectedMessage.sameTerm(message)) {
    messageRow.style.backgroundColor = 'yellow'
    options.selectedElement = messageRow
    messageTable.selectedElement = messageRow
  }

  var done = false
  for (var ele = messageTable.firstChild; ; ele = ele.nextSibling) {
    if (!ele) {
      // empty
      break
    }
    var newestFirst = options.newestfirst === true
    if (
      (dateString > ele.AJAR_date && newestFirst) ||
      (dateString < ele.AJAR_date && !newestFirst)
    ) {
      messageTable.insertBefore(messageRow, ele)
      done = true
      break
    }
  }
  if (!done) {
    messageTable.appendChild(messageRow)
  }

  var td1 = dom.createElement('td')
  messageRow.appendChild(td1)
  if (options.authorAboveContent) {
    const img = dom.createElement('img')
    img.setAttribute(
      'style',
      'max-height: 2.5em; max-width: 2.5em; border-radius: 0.5em; margin: auto;'
    )
    UI.widgets.setImage(img, creator)
    td1.appendChild(img)
  } else {
    creatorAndDate(td1, creator, UI.widgets.shortDate(dateString), message)
  }

  // Render the content ot the message itself
  var td2 = messageRow.appendChild(dom.createElement('td'))

  if (options.authorAboveContent) {
    creatorAndDateHorizontal(
      td2,
      creator,
      UI.widgets.shortDate(dateString),
      message
    )
  }
  const text = content.value.trim()
  const isURI = /^https?:\/[^ <>]*$/i.test(text)
  let para = null
  if (isURI) {
    var isImage = /\.(gif|jpg|jpeg|tiff|png|svg)$/i.test(text) // @@ Should use content-type not URI
    if (isImage && options.expandImagesInline) {
      const img = elementForImageURI(text, options)
      td2.appendChild(img)
    } else {
      // Link but not Image
      const anc = td2.appendChild(dom.createElement('a'))
      para = anc.appendChild(dom.createElement('p'))
      anc.href = text
      para.textContent = text
      td2.appendChild(anc)
    }
  } else {
    // text
    para = dom.createElement('p')
    td2.appendChild(para)
    para.textContent = text
  }
  if (para) {
    var bgcolor = colorizeByAuthor
      ? UI.pad.lightColorHash(creator)
      : getBgColor(fresh)
    para.setAttribute(
      'style',
      messageBodyStyle + 'background-color: ' + bgcolor + ';'
    )
  }

  function getBgColor (fresh) {
    return fresh ? '#e8ffe8' : 'white'
  }

  // Sentiment strip
  const strip = sentimentStripLinked(message, message.doc())
  if (strip.children.length) {
    td2.appendChild(dom.createElement('br'))
    td2.appendChild(strip)
  }

  // Message tool bar button
  var td3 = dom.createElement('td')
  messageRow.appendChild(td3)
  var toolsButton = UI.widgets.button(
    dom,
    UI.icons.iconBase + 'noun_243787.svg',
    '...'
  )
  td3.appendChild(toolsButton)
  toolsButton.addEventListener('click', function (_event) {
    if (messageRow.toolTR) {
      // already got a toolbar? Toogle
      messageRow.parentNode.removeChild(messageRow.toolTR)
      delete messageRow.toolTR
      return
    }
    const toolsTR = dom.createElement('tr')
    const tools = messageToolbar(message, messageRow, userContext)
    tools.style =
      'border: 0.05em solid #888; border-radius: 0 0 0.7em 0.7em;  border-top: 0; height:3.5em; background-color: #fff;' // @@ fix
    if (messageRow.nextSibling) {
      messageRow.parentElement.insertBefore(toolsTR, messageRow.nextSibling)
    } else {
      messageRow.parentElement.appendChild(toolsTR)
    }
    messageRow.toolTR = toolsTR
    toolsTR.appendChild(dom.createElement('td')) // left
    const toolsTD = toolsTR.appendChild(dom.createElement('td'))
    toolsTR.appendChild(dom.createElement('td')) // right
    toolsTD.appendChild(tools)
  })
  return messageRow
}