Post.coffee 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. class Post extends Class
  2. constructor: (row, @item_list) ->
  3. @liked = false
  4. @commenting = false
  5. @submitting_like = false
  6. @owned = false
  7. @editable_comments = {}
  8. @field_comment = new Autosize({placeholder: "Add your comment", onsubmit: @handleCommentSubmit, title_submit: "Send"})
  9. @comment_limit = 3
  10. @menu = null
  11. @meta = null
  12. @css_style = ""
  13. @setRow(row)
  14. setRow: (row) ->
  15. @row = row
  16. if @row.meta
  17. @meta = new PostMeta(@, JSON.parse(@row.meta))
  18. if Page.user
  19. @liked = Page.user.likes[@row.key]
  20. @user = new User({hub: row.site, auth_address: row.directory.replace("data/users/", "")})
  21. @user.row = row
  22. @owned = @user.auth_address == Page.user?.auth_address
  23. if @owned
  24. @editable_body = new Editable("div.body", @handlePostSave, @handlePostDelete)
  25. @editable_body.render_function = Text.renderMarked
  26. @editable_body.empty_text = " "
  27. getLink: ->
  28. "?Post/#{@user.hub}/#{@user.auth_address}/#{@row.post_id}"
  29. handlePostSave: (body, cb) =>
  30. Page.user.getData Page.user.hub, (data) =>
  31. post_index = i for post, i in data.post when post.post_id == @row.post_id
  32. data.post[post_index].body = body
  33. Page.user.save data, Page.user.hub, (res) =>
  34. cb(res)
  35. handlePostDelete: (cb) =>
  36. Page.user.getData Page.user.hub, (data) =>
  37. post_index = i for post, i in data.post when post.post_id == @row.post_id
  38. data.post.splice(post_index, 1)
  39. if @meta?.meta?.img
  40. Page.cmd "fileDelete", "#{@user.getPath()}/#{@row.post_id}.jpg", =>
  41. Page.user.save data, Page.user.hub, (res) =>
  42. cb(res)
  43. else
  44. Page.user.save data, Page.user.hub, (res) =>
  45. cb(res)
  46. handleLikeClick: (e) =>
  47. @submitting_like = true
  48. [site, post_uri] = @row.key.split("-")
  49. if Page.user.likes[post_uri]
  50. Animation.flashOut(e.currentTarget.firstChild)
  51. Page.user.dislike site, post_uri, =>
  52. @submitting_like = false
  53. @unfollow()
  54. else
  55. Animation.flashIn(e.currentTarget.firstChild)
  56. Page.user.like site, post_uri, =>
  57. @submitting_like = false
  58. @follow()
  59. return false
  60. handleCommentClick: =>
  61. if @field_comment.node
  62. @field_comment.node.focus()
  63. else
  64. @commenting = true
  65. setTimeout ( =>
  66. @field_comment.node.focus()
  67. ), 600
  68. return false
  69. handleCommentSubmit: =>
  70. if not @field_comment.attrs.value then return
  71. timer_loading = setTimeout ( => @field_comment.loading = true ), 100 # Only add loading message if takes more than 100ms
  72. [site, post_uri] = @row.key.split("-")
  73. Page.user.comment site, post_uri, @field_comment.attrs.value, (res) =>
  74. clearInterval(timer_loading)
  75. @field_comment.loading = false
  76. if res
  77. @field_comment.setValue("")
  78. @follow()
  79. handleCommentSave: (comment_id, body, cb) =>
  80. Page.user.getData @row.site, (data) =>
  81. comment_index = i for comment, i in data.comment when comment.comment_id == comment_id
  82. data.comment[comment_index].body = body
  83. Page.user.save data, @row.site, (res) =>
  84. cb(res)
  85. handleCommentDelete: (comment_id, cb) =>
  86. Page.user.getData @row.site, (data) =>
  87. comment_index = i for comment, i in data.comment when comment.comment_id == comment_id
  88. data.comment.splice(comment_index, 1)
  89. Page.user.save data, @row.site, (res) =>
  90. cb(res)
  91. @unfollow()
  92. handleMoreCommentsClick: =>
  93. @comment_limit += 10
  94. return false
  95. handleReplyClick: (e) =>
  96. user_name = e.currentTarget.attributes.user_name.value
  97. if @field_comment.attrs.value
  98. @field_comment.setValue("#{@field_comment.attrs.value}\n@#{user_name}: ")
  99. else
  100. @field_comment.setValue("@#{user_name}: ")
  101. @handleCommentClick(e)
  102. return false
  103. getEditableComment: (comment_uri) ->
  104. if not @editable_comments[comment_uri]
  105. [user_address, comment_id] = comment_uri.split("_")
  106. handleCommentSave = (body, cb) =>
  107. @handleCommentSave(parseInt(comment_id), body, cb)
  108. handleCommentDelete = (cb) =>
  109. @handleCommentDelete(parseInt(comment_id), cb)
  110. @editable_comments[comment_uri] = new Editable("div.body", handleCommentSave, handleCommentDelete)
  111. @editable_comments[comment_uri].render_function = Text.renderMarked
  112. return @editable_comments[comment_uri]
  113. getPostUri: =>
  114. return "#{@user.auth_address}_#{@row.post_id}"
  115. handleSettingsClick: =>
  116. @css_style = "z-index: #{@row.date_added}; position: relative"
  117. Page.cmd "feedListFollow", [], (follows) =>
  118. if not @menu
  119. @menu = new Menu()
  120. followed = follows["Post follow"] and @getPostUri() in follows["Post follow"][1]
  121. @menu.items = []
  122. @menu.items.push ["Follow in newsfeed", ( => if followed then @unfollow() else @follow() ), followed]
  123. @menu.items.push ["Mute user", @user.handleMuteClick]
  124. @menu.items.push ["Permalink", @getLink()]
  125. if @owned
  126. @menu.items.push ["Edit", ( (e) => @editable_body.handleEditClick(e) )]
  127. @menu.toggle()
  128. return false
  129. unfollow: =>
  130. Page.cmd "feedListFollow", [], (follows) =>
  131. if not follows["Post follow"]
  132. return
  133. followed_uris = follows["Post follow"][1]
  134. index = followed_uris.indexOf @getPostUri()
  135. if index == -1
  136. return
  137. followed_uris.splice(index, 1)
  138. if followed_uris.length == 0
  139. delete follows["Post follow"]
  140. @log "Unfollow", follows
  141. Page.cmd "feedFollow", [follows]
  142. follow: =>
  143. Page.cmd "feedListFollow", [], (follows) =>
  144. if not follows["Post follow"]
  145. follows["Post follow"] = ["""
  146. SELECT
  147. "comment" AS type,
  148. comment.date_added AS date_added,
  149. "a followed post" AS title,
  150. '@' || user_name || ': ' || comment.body AS body,
  151. '?Post/' || json.site || '/' || REPLACE(post_uri, '_', '/') AS url
  152. FROM comment
  153. LEFT JOIN json USING (json_id)
  154. WHERE post_uri IN (:params)
  155. """, []]
  156. followed_uris = follows["Post follow"][1]
  157. followed_uris.push @getPostUri()
  158. Page.cmd "feedFollow", [follows]
  159. renderComments: =>
  160. if not @row.comments and not @commenting
  161. return []
  162. if @row.selected
  163. comment_limit = @comment_limit + 50
  164. else
  165. comment_limit = @comment_limit
  166. h("div.comment-list", {enterAnimation: Animation.slideDown, exitAnimation: Animation.slideUp, animate_scrollfix: true, animate_noscale: true}, [
  167. if @commenting then h("div.comment-create", {enterAnimation: Animation.slideDown},
  168. @field_comment.render()
  169. ),
  170. @row.comments?[0..comment_limit-1].map (comment) =>
  171. user_address = comment.directory.replace("data/users/", "")
  172. comment_uri = user_address+"_"+comment.comment_id
  173. owned = user_address == Page.user?.auth_address
  174. user_link = "?Profile/"+comment.hub+"/"+user_address+"/"+comment.cert_user_id
  175. h("div.comment", {id: comment_uri, key: comment_uri, animate_scrollfix: true, enterAnimation: Animation.slideDown, exitAnimation: Animation.slideUp}, [
  176. h("div.user", [
  177. h("a.name.link", {href: user_link, style: "color: #{Text.toColor(user_address)}", onclick: Page.handleLinkClick}, comment.user_name),
  178. h("span.sep", " \u00B7 "),
  179. h("span.address", {title: user_address}, comment.cert_user_id),
  180. h("span.sep", " \u2015 "),
  181. h("a.added.link", {href: "#", title: Time.date(comment.date_added, "long")}, Time.since(comment.date_added)),
  182. h("a.icon.icon-reply", {href: "#Reply", onclick: @handleReplyClick, user_name: comment.user_name}, "Reply")
  183. ])
  184. if owned
  185. @getEditableComment(comment_uri).render(comment.body)
  186. else if comment.body?.length > 5000
  187. h("div.body.maxheight", {innerHTML: Text.renderMarked(comment.body), afterCreate: Maxheight.apply})
  188. else
  189. h("div.body", {innerHTML: Text.renderMarked(comment.body) })
  190. ])
  191. if @row.comments?.length > comment_limit
  192. h("a.more", {href: "#More", onclick: @handleMoreCommentsClick, enterAnimation: Animation.slideDown, exitAnimation: Animation.slideUp}, "Show more comments...")
  193. ])
  194. render: =>
  195. [site, post_uri] = @row.key.split("-")
  196. h("div.post", {key: @row.key, enterAnimation: Animation.slideDown, exitAnimation: Animation.slideUp, animate_scrollfix: true, classes: {selected: @row.selected}, style: @css_style}, [
  197. h("div.user", [
  198. @user.renderAvatar({href: @user.getLink(), onclick: Page.handleLinkClick}),
  199. h("a.name.link", {href: @user.getLink(), onclick: Page.handleLinkClick, style: "color: #{Text.toColor(@user.auth_address)}"},
  200. @row.user_name
  201. ),
  202. h("span.sep", " \u00B7 "),
  203. h("span.address", {title: @user.auth_address}, @row.cert_user_id),
  204. h("span.sep", " \u2015 "),
  205. h("a.added.link", {href: @getLink(), title: Time.date(@row.date_added, "long"), onclick: Page.handleLinkClick}, Time.since(@row.date_added)),
  206. if @menu then @menu.render(".menu-right"),
  207. h("a.settings", {href: "#Settings", onclick: Page.returnFalse, onmousedown: @handleSettingsClick}, "\u22EE")
  208. ])
  209. if @owned
  210. @editable_body.render(@row.body)
  211. else
  212. h("div.body", {classes: {maxheight: not @row.selected and @row.body?.length > 3000}, innerHTML: Text.renderMarked(@row.body), afterCreate: Maxheight.apply, afterUpdate: Maxheight.apply})
  213. if @meta
  214. @meta.render()
  215. h("div.actions", [
  216. h("a.icon.icon-comment.link", {href: "#Comment", onclick: @handleCommentClick}, "Comment"),
  217. h("a.like.link", {classes: {active: Page.user?.likes[post_uri], loading: @submitting_like, "like-zero": @row.likes == 0}, href: "#Like", onclick: @handleLikeClick},
  218. h("div.icon.icon-heart", {classes: {active: Page.user?.likes[post_uri]}}),
  219. if @row.likes then @row.likes
  220. )
  221. # h("a.icon.icon-share.link", {href: "#Share"}, "Share"),
  222. ]),
  223. @renderComments()
  224. ])
  225. window.Post = Post