     undefined
   , [message._id]
 
+  ## Fold naturally folded (minimized and deleted) messages by default on
+  ## initial load.  But only if not previously manually overridden.
+  useEffect ->
+    oldDefault = defaultFolded.get message._id
+    oldFolded = messageFolded.get message._id
+    defaultFolded.set message._id, naturallyFolded message
+    ## Initially switch messageFolded to defaultFolded if:
+    ## * default has changed
+    ## * default has initialized but messageFolded not already set
+    ##   (e.g. because we just clicked the message)
+    setTimeout ->
+      if oldFolded? and (not oldDefault? or oldDefault == defaultFolded.get message._id)
+        unless oldFolded == messageFolded.get message._id
+          messageFolded.set message._id, oldFolded
+      else
+        messageFolded.set message._id, defaultFolded.get message._id
+    , 0
+  , [message._id]
+
+  ## Fold referenced attached files by default on initial load.
+  messageBodyRef = useRef()
+  useEffect ->
+    initImage message._id
+    ## initImage calls updateFileQuery which will do this:
+    #images[message._id].file = message.file
+    #initImageInternal message.file if message.file?
+    ## If message is naturally folded, don't count images it references.
+    images[message._id].naturallyFolded = naturallyFolded message
+    images[message._id].children = message.children?.length
+    return if images[message._id].naturallyFolded
+    messageImages = {}
+    messageImagesInternal = {}
+    return unless messageBodyRef.current?
+    for elt in messageBodyRef.current.querySelectorAll """
+      img[src^="#{fileUrlPrefix}"],
+      img[src^="#{fileAbsoluteUrlPrefix}"],
+      img[src^="#{internalFileUrlPrefix}"],
+      img[src^="#{internalFileAbsoluteUrlPrefix}"],
+      video source[src^="#{fileUrlPrefix}"],
+      video source[src^="#{fileAbsoluteUrlPrefix}"],
+      video source[src^="#{internalFileUrlPrefix}"],
+      video source[src^="#{internalFileAbsoluteUrlPrefix}"]
+    """
+      src = elt.getAttribute 'src'
+      if 0 <= src.indexOf 'gridfs'
+        messageImagesInternal[url2internalFile src] = true
+      else
+        messageImages[url2file src] = true
+    for id of messageImages
+      #console.log 'source', id
+      initImage id
+      images[id].count += 1
+      checkImage id
+    for id of messageImagesInternal
+      #console.log 'source', id
+      initImageInternal id
+      imagesInternal[id].count += 1
+      checkImageInternal id
+    ->
+      for id of messageImages
+        images[id].count -= 1
+        checkImage id
+      for id of messageImagesInternal
+        imagesInternal[id].count -= 1
+        checkImageInternal id
+  # too many dependencies to list
+
   ## Transform images
-  messageBodyRef = useRef()
   ## Retransform when window width changes
   [windowWidth, setWindowWidth] = useState window.innerWidth
   useEventListener 'resize', (e) -> setWindowWidth window.innerWidth
   useEffect ->
+    return unless messageBodyRef.current?
     ## Transform any images embedded within message body
     trackers =
       for img in messageBodyRef.current.querySelectorAll """

## A message is "naturally" folded if it is flagged as minimized or deleted.
## It still will be default-folded if it's an image referenced in another
## message that is not naturally folded.
export naturallyFolded = (data) -> data.minimized or data.deleted

## Cache EXIF orientations, as files should be static
image2orientation = {}

      messageFolded.set ancestor._id, false
  ## Also unfold message itself, because you probably want to see it.
  messageFolded.set id, false

historify = (x, post) -> () ->
  history = messageHistory.get @_id
