notmuch-web-0.1.0: src/Handler/View.hs
{-
Copyright (C) 2013 John Lenz <lenz@math.uic.edu>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-}
{-# LANGUAGE RecordWildCards #-}
module Handler.View(
threadWidget
, threadHeader
, getThreadR
, getMessagePartR
) where
import Import
import Control.Monad (replicateM, unless)
import NotmuchCmd
import Settings
import StaticFiles
import Handler.Tags
import Network.Wai (Response(..))
import Network.HTTP.Types (status200)
import qualified Data.Conduit.List as CL
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Blaze.ByteString.Builder (fromByteString)
import qualified Data.Map as M
import qualified Data.Tree as TR
import qualified Data.CaseInsensitive as CI
messageContent :: MessageID -> MessagePart -> T.Text -> Widget
messageContent mid m "" = [whamlet|
<div .message-attachment>
<p>
<a href="@{MessagePartR mid (partID m)}">
$case partContentFilename m
$of Just f
#{f}
$of Nothing
<span>No filename
(#{partContentType m})
|]
messageContent _ _ txt = [whamlet|
<div .message-text>
<pre>
#{txt}
|]
messagePart :: MessageID -> MessagePart -> Widget
messagePart mid m = [whamlet|
<div .message-part>
$case partContent m
$of Left x
^{messageContent mid m x}
$of Right ms
$forall p <- ms
^{messagePart mid p}
|]
messageWidget :: Message -> Widget
messageWidget (Message {..}) = [whamlet|
<div .message data-notmuch-message-id="#{unMessageID messageId}">
<dl .dl-horizontal>
$forall (h,v) <- M.toList messageHeaders
<dt>#{CI.original h}
<dd>#{v}
$forall part <- messageBody
^{messagePart messageId part}
|]
messages :: TR.Forest Message -> Widget
messages [] = return ()
messages forest = do
ids <- replicateM (length forest) (lift newIdent)
let forestWithIds = zip forest ids
let isUnread m = "unread" `elem` messageTags m
$(widgetFile "thread")
threadWidget :: ThreadID -> Widget
threadWidget t = do
thread <- notmuchShow t
let msubject = case thread of
(Thread ((TR.Node m _):_)) -> Just $ messageSubject m
_ -> Nothing
case msubject of
Just s -> setTitle $ toHtml s
Nothing -> return ()
[whamlet|
$maybe s <- msubject
<div .page-header>
<h3>#{s}
<div #messageThread data-notmuch-threadid=#{t}>
^{messages (threadForest thread)}
|]
-- | The header code for displaying threads, should only be included once in the page
threadHeader :: Widget
threadHeader = do
tagHeader
toWidget [julius|
$(document).on("notmuch:retag", "span.tags", function(e, data) {
if ($.inArray("unread", data.remove) >= 0) {
$(this).parents("div.accordion-group").children("div.accordion-body").each(function(idx, b) {
$(b).collapse('hide');
});
}
});
|]
getThreadR :: ThreadID -> Handler RepHtml
getThreadR t = defaultLayout $ do
pjax <- lift isPjax
unless pjax threadHeader
threadWidget t
getMessagePartR :: MessageID -> Int -> Handler ()
getMessagePartR mid part = do
let (getMsg, rawMsg) = notmuchMessagePart mid part
msg <- getMsg
let contentdisp = case partContentFilename msg of
Just f -> [("Content-Disposition", "attachment;filename=\"" <> T.encodeUtf8 f <> "\"")]
Nothing -> []
let contenttype = [("Content-Type", T.encodeUtf8 $ partContentType msg)]
let source = rawMsg $= CL.map (Chunk . fromByteString)
sendWaiResponse $ ResponseSource status200 (contentdisp ++ contenttype) source