Sidebar.coffee 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. class Sidebar extends Class
  2. constructor: (@wrapper) ->
  3. @tag = null
  4. @container = null
  5. @opened = false
  6. @width = 410
  7. @console = new Console(@)
  8. @fixbutton = $(".fixbutton")
  9. @fixbutton_addx = 0
  10. @fixbutton_addy = 0
  11. @fixbutton_initx = 0
  12. @fixbutton_inity = 15
  13. @fixbutton_targetx = 0
  14. @move_lock = null
  15. @page_width = $(window).width()
  16. @page_height = $(window).height()
  17. @frame = $("#inner-iframe")
  18. @initFixbutton()
  19. @dragStarted = 0
  20. @globe = null
  21. @preload_html = null
  22. @original_set_site_info = @wrapper.setSiteInfo # We going to override this, save the original
  23. # Start in opened state for debugging
  24. if window.top.location.hash == "#ZeroNet:OpenSidebar"
  25. @startDrag()
  26. @moved("x")
  27. @fixbutton_targetx = @fixbutton_initx - @width
  28. @stopDrag()
  29. initFixbutton: ->
  30. # Detect dragging
  31. @fixbutton.on "mousedown touchstart", (e) =>
  32. if e.button > 0 # Right or middle click
  33. return
  34. e.preventDefault()
  35. # Disable previous listeners
  36. @fixbutton.off "click touchend touchcancel"
  37. # Make sure its not a click
  38. @dragStarted = (+ new Date)
  39. # Fullscreen drag bg to capture mouse events over iframe
  40. $(".drag-bg").remove()
  41. $("<div class='drag-bg'></div>").appendTo(document.body)
  42. $("body").one "mousemove touchmove", (e) =>
  43. mousex = e.pageX
  44. mousey = e.pageY
  45. if not mousex
  46. mousex = e.originalEvent.touches[0].pageX
  47. mousey = e.originalEvent.touches[0].pageY
  48. @fixbutton_addx = @fixbutton.offset().left - mousex
  49. @fixbutton_addy = @fixbutton.offset().top - mousey
  50. @startDrag()
  51. @fixbutton.parent().on "click touchend touchcancel", (e) =>
  52. if (+ new Date) - @dragStarted < 100
  53. window.top.location = @fixbutton.find(".fixbutton-bg").attr("href")
  54. @stopDrag()
  55. @resized()
  56. $(window).on "resize", @resized
  57. resized: =>
  58. @page_width = $(window).width()
  59. @page_height = $(window).height()
  60. @fixbutton_initx = @page_width - 75 # Initial x position
  61. if @opened
  62. @fixbutton.css
  63. left: @fixbutton_initx - @width
  64. else
  65. @fixbutton.css
  66. left: @fixbutton_initx
  67. # Start dragging the fixbutton
  68. startDrag: ->
  69. #@move_lock = "x" # Temporary until internals not finished
  70. @log "startDrag", @fixbutton_initx, @fixbutton_inity
  71. @fixbutton_targetx = @fixbutton_initx # Fallback x position
  72. @fixbutton_targety = @fixbutton_inity # Fallback y position
  73. @fixbutton.addClass("dragging")
  74. # IE position wrap fix
  75. if navigator.userAgent.indexOf('MSIE') != -1 or navigator.appVersion.indexOf('Trident/') > 0
  76. @fixbutton.css("pointer-events", "none")
  77. # Don't go to homepage
  78. @fixbutton.one "click", (e) =>
  79. @stopDrag()
  80. @fixbutton.removeClass("dragging")
  81. moved_x = Math.abs(@fixbutton.offset().left - @fixbutton_initx)
  82. moved_y = Math.abs(@fixbutton.offset().top - @fixbutton_inity)
  83. if moved_x > 5 or moved_y > 10
  84. # If moved more than some pixel the button then don't go to homepage
  85. e.preventDefault()
  86. # Animate drag
  87. @fixbutton.parents().on "mousemove touchmove", @animDrag
  88. @fixbutton.parents().on "mousemove touchmove" ,@waitMove
  89. # Stop dragging listener
  90. @fixbutton.parents().one "mouseup touchend touchcancel", (e) =>
  91. e.preventDefault()
  92. @stopDrag()
  93. # Wait for moving the fixbutton
  94. waitMove: (e) =>
  95. document.body.style.perspective = "1000px"
  96. document.body.style.height = "100%"
  97. document.body.style.willChange = "perspective"
  98. document.documentElement.style.height = "100%"
  99. #$(document.body).css("backface-visibility", "hidden").css("perspective", "1000px").css("height", "900px")
  100. # $("iframe").css("backface-visibility", "hidden")
  101. moved_x = Math.abs(parseInt(@fixbutton[0].style.left) - @fixbutton_targetx)
  102. moved_y = Math.abs(parseInt(@fixbutton[0].style.top) - @fixbutton_targety)
  103. if moved_x > 5 and (+ new Date) - @dragStarted + moved_x > 50
  104. @moved("x")
  105. @fixbutton.stop().animate {"top": @fixbutton_inity}, 1000
  106. @fixbutton.parents().off "mousemove touchmove" ,@waitMove
  107. else if moved_y > 5 and (+ new Date) - @dragStarted + moved_y > 50
  108. @moved("y")
  109. @fixbutton.parents().off "mousemove touchmove" ,@waitMove
  110. moved: (direction) ->
  111. @log "Moved", direction
  112. @move_lock = direction
  113. if direction == "y"
  114. $(document.body).addClass("body-console")
  115. return @console.createHtmltag()
  116. @createHtmltag()
  117. $(document.body).addClass("body-sidebar")
  118. @container.on "mousedown touchend touchcancel", (e) =>
  119. if e.target != e.currentTarget
  120. return true
  121. @log "closing"
  122. if $(document.body).hasClass("body-sidebar")
  123. @close()
  124. return true
  125. $(window).off "resize"
  126. $(window).on "resize", =>
  127. $(document.body).css "height", $(window).height()
  128. @scrollable()
  129. @resized()
  130. # Override setsiteinfo to catch changes
  131. @wrapper.setSiteInfo = (site_info) =>
  132. @setSiteInfo(site_info)
  133. @original_set_site_info.apply(@wrapper, arguments)
  134. # Preload world.jpg
  135. img = new Image();
  136. img.src = "/uimedia/globe/world.jpg";
  137. setSiteInfo: (site_info) ->
  138. RateLimit 1500, =>
  139. @updateHtmlTag()
  140. RateLimit 30000, =>
  141. @displayGlobe()
  142. # Create the sidebar html tag
  143. createHtmltag: ->
  144. @when_loaded = $.Deferred()
  145. if not @container
  146. @container = $("""
  147. <div class="sidebar-container"><div class="sidebar scrollable"><div class="content-wrapper"><div class="content">
  148. </div></div></div></div>
  149. """)
  150. @container.appendTo(document.body)
  151. @tag = @container.find(".sidebar")
  152. @updateHtmlTag()
  153. @scrollable = window.initScrollable()
  154. updateHtmlTag: ->
  155. if @preload_html
  156. @setHtmlTag(@preload_html)
  157. @preload_html = null
  158. else
  159. @wrapper.ws.cmd "sidebarGetHtmlTag", {}, @setHtmlTag
  160. setHtmlTag: (res) =>
  161. if @tag.find(".content").children().length == 0 # First update
  162. @log "Creating content"
  163. @container.addClass("loaded")
  164. morphdom(@tag.find(".content")[0], '<div class="content">'+res+'</div>')
  165. # @scrollable()
  166. @when_loaded.resolve()
  167. else # Not first update, patch the html to keep unchanged dom elements
  168. morphdom @tag.find(".content")[0], '<div class="content">'+res+'</div>', {
  169. onBeforeMorphEl: (from_el, to_el) -> # Ignore globe loaded state
  170. if from_el.className == "globe" or from_el.className.indexOf("noupdate") >= 0
  171. return false
  172. else
  173. return true
  174. }
  175. # Save and forget privatekey for site signing
  176. @tag.find("#privatekey-add").off("click, touchend").on "click touchend", (e) =>
  177. @wrapper.displayPrompt "Enter your private key:", "password", "Save", "", (privatekey) =>
  178. @wrapper.ws.cmd "userSetSitePrivatekey", [privatekey], (res) =>
  179. @wrapper.notifications.add "privatekey", "done", "Private key saved for site signing", 5000
  180. return false
  181. @tag.find("#privatekey-forget").off("click, touchend").on "click touchend", (e) =>
  182. @wrapper.displayConfirm "Remove saved private key for this site?", "Forget", (res) =>
  183. if not res
  184. return false
  185. @wrapper.ws.cmd "userSetSitePrivatekey", [""], (res) =>
  186. @wrapper.notifications.add "privatekey", "done", "Saved private key removed", 5000
  187. return false
  188. # Use requested address for browse files urls
  189. @tag.find("#browse-files").attr("href", document.location.pathname.replace(/(\/.*?(\/|$)).*$/, "/list$1"))
  190. animDrag: (e) =>
  191. mousex = e.pageX
  192. mousey = e.pageY
  193. if not mousex and e.originalEvent.touches
  194. mousex = e.originalEvent.touches[0].pageX
  195. mousey = e.originalEvent.touches[0].pageY
  196. overdrag = @fixbutton_initx - @width - mousex
  197. if overdrag > 0 # Overdragged
  198. overdrag_percent = 1 + overdrag/300
  199. mousex = (mousex + (@fixbutton_initx-@width)*overdrag_percent)/(1+overdrag_percent)
  200. targetx = @fixbutton_initx - mousex - @fixbutton_addx
  201. targety = @fixbutton_inity - mousey - @fixbutton_addy
  202. if @move_lock == "x"
  203. targety = @fixbutton_inity
  204. else if @move_lock == "y"
  205. targetx = @fixbutton_initx
  206. if not @move_lock or @move_lock == "x"
  207. @fixbutton[0].style.left = (mousex + @fixbutton_addx) + "px"
  208. if @tag
  209. @tag[0].style.transform = "translateX(#{0 - targetx}px)"
  210. if not @move_lock or @move_lock == "y"
  211. @fixbutton[0].style.top = (mousey + @fixbutton_addy) + "px"
  212. if @console.tag
  213. @console.tag[0].style.transform = "translateY(#{0 - targety}px)"
  214. #if @move_lock == "x"
  215. # @fixbutton[0].style.left = "#{@fixbutton_targetx} px"
  216. #@fixbutton[0].style.top = "#{@fixbutton_inity}px"
  217. #if @move_lock == "y"
  218. # @fixbutton[0].style.top = "#{@fixbutton_targety} px"
  219. # Check if opened
  220. if (not @opened and targetx > @width/3) or (@opened and targetx > @width*0.9)
  221. @fixbutton_targetx = @fixbutton_initx - @width # Make it opened
  222. else
  223. @fixbutton_targetx = @fixbutton_initx
  224. if (not @console.opened and 0 - targety > @page_height/10) or (@console.opened and 0 - targety > @page_height*0.8)
  225. @fixbutton_targety = @page_height - @fixbutton_inity - 50
  226. else
  227. @fixbutton_targety = @fixbutton_inity
  228. # Stop dragging the fixbutton
  229. stopDrag: ->
  230. @fixbutton.parents().off "mousemove touchmove"
  231. @fixbutton.off "mousemove touchmove"
  232. @fixbutton.css("pointer-events", "")
  233. $(".drag-bg").remove()
  234. if not @fixbutton.hasClass("dragging")
  235. return
  236. @fixbutton.removeClass("dragging")
  237. # Move back to initial position
  238. if @fixbutton_targetx != @fixbutton.offset().left or @fixbutton_targety != @fixbutton.offset().top
  239. # Animate fixbutton
  240. if @move_lock == "y"
  241. top = @fixbutton_targety
  242. left = @fixbutton_initx
  243. if @move_lock == "x"
  244. top = @fixbutton_inity
  245. left = @fixbutton_targetx
  246. @fixbutton.stop().animate {"left": left, "top": top}, 500, "easeOutBack", =>
  247. # Switch back to auto align
  248. if @fixbutton_targetx == @fixbutton_initx # Closed
  249. @fixbutton.css("left", "auto")
  250. else # Opened
  251. @fixbutton.css("left", left)
  252. $(".fixbutton-bg").trigger "mouseout" # Switch fixbutton back to normal status
  253. @stopDragX()
  254. @console.stopDragY()
  255. @move_lock = null
  256. stopDragX: ->
  257. # Animate sidebar and iframe
  258. if @fixbutton_targetx == @fixbutton_initx or @move_lock == "y"
  259. # Closed
  260. targetx = 0
  261. @opened = false
  262. else
  263. # Opened
  264. targetx = @width
  265. if @opened
  266. @onOpened()
  267. else
  268. @when_loaded.done =>
  269. @onOpened()
  270. @opened = true
  271. # Revent sidebar transitions
  272. if @tag
  273. @tag.css("transition", "0.4s ease-out")
  274. @tag.css("transform", "translateX(-#{targetx}px)").one transitionEnd, =>
  275. @tag.css("transition", "")
  276. if not @opened
  277. @container.remove()
  278. @container = null
  279. if @tag
  280. @tag.remove()
  281. @tag = null
  282. # Revert body transformations
  283. @log "stopdrag", "opened:", @opened
  284. if not @opened
  285. @onClosed()
  286. sign: (inner_path, privatekey) ->
  287. @wrapper.displayProgress("sign", "Signing: #{inner_path}...", 0)
  288. @wrapper.ws.cmd "siteSign", {privatekey: privatekey, inner_path: inner_path, update_changed_files: true}, (res) =>
  289. if res == "ok"
  290. @wrapper.displayProgress("sign", "#{inner_path} signed!", 100)
  291. else
  292. @wrapper.displayProgress("sign", "Error signing #{inner_path}", -1)
  293. publish: (inner_path, privatekey) ->
  294. @wrapper.ws.cmd "sitePublish", {privatekey: privatekey, inner_path: inner_path, sign: true, update_changed_files: true}, (res) =>
  295. if res == "ok"
  296. @wrapper.notifications.add "sign", "done", "#{inner_path} Signed and published!", 5000
  297. handleSiteDeleteClick: ->
  298. if @wrapper.site_info.privatekey
  299. question = "Are you sure?<br>This site has a saved private key"
  300. options = ["Forget private key and delete site"]
  301. else
  302. question = "Are you sure?"
  303. options = ["Delete this site", "Blacklist"]
  304. @wrapper.displayConfirm question, options, (confirmed) =>
  305. if confirmed == 1
  306. @tag.find("#button-delete").addClass("loading")
  307. @wrapper.ws.cmd "siteDelete", @wrapper.site_info.address, ->
  308. document.location = $(".fixbutton-bg").attr("href")
  309. else if confirmed == 2
  310. @wrapper.displayPrompt "Blacklist this site", "text", "Delete and Blacklist", "Reason", (reason) =>
  311. @tag.find("#button-delete").addClass("loading")
  312. @wrapper.ws.cmd "siteblockAdd", [@wrapper.site_info.address, reason]
  313. @wrapper.ws.cmd "siteDelete", @wrapper.site_info.address, ->
  314. document.location = $(".fixbutton-bg").attr("href")
  315. onOpened: ->
  316. @log "Opened"
  317. @scrollable()
  318. # Re-calculate height when site admin opened or closed
  319. @tag.find("#checkbox-owned, #checkbox-autodownloadoptional").off("click touchend").on "click touchend", =>
  320. setTimeout (=>
  321. @scrollable()
  322. ), 300
  323. # Site limit button
  324. @tag.find("#button-sitelimit").off("click touchend").on "click touchend", =>
  325. @wrapper.ws.cmd "siteSetLimit", $("#input-sitelimit").val(), (res) =>
  326. if res == "ok"
  327. @wrapper.notifications.add "done-sitelimit", "done", "Site storage limit modified!", 5000
  328. @updateHtmlTag()
  329. return false
  330. # Site autodownload limit button
  331. @tag.find("#button-autodownload_bigfile_size_limit").off("click touchend").on "click touchend", =>
  332. @wrapper.ws.cmd "siteSetAutodownloadBigfileLimit", $("#input-autodownload_bigfile_size_limit").val(), (res) =>
  333. if res == "ok"
  334. @wrapper.notifications.add "done-bigfilelimit", "done", "Site bigfile auto download limit modified!", 5000
  335. @updateHtmlTag()
  336. return false
  337. # Site start download optional files
  338. @tag.find("#button-autodownload_previous").off("click touchend").on "click touchend", =>
  339. @wrapper.ws.cmd "siteUpdate", {"address": @wrapper.site_info.address, "check_files": true}, =>
  340. @wrapper.notifications.add "done-download_optional", "done", "Optional files downloaded", 5000
  341. @wrapper.notifications.add "start-download_optional", "info", "Optional files download started", 5000
  342. return false
  343. # Database reload
  344. @tag.find("#button-dbreload").off("click touchend").on "click touchend", =>
  345. @wrapper.ws.cmd "dbReload", [], =>
  346. @wrapper.notifications.add "done-dbreload", "done", "Database schema reloaded!", 5000
  347. @updateHtmlTag()
  348. return false
  349. # Database rebuild
  350. @tag.find("#button-dbrebuild").off("click touchend").on "click touchend", =>
  351. @wrapper.notifications.add "done-dbrebuild", "info", "Database rebuilding...."
  352. @wrapper.ws.cmd "dbRebuild", [], =>
  353. @wrapper.notifications.add "done-dbrebuild", "done", "Database rebuilt!", 5000
  354. @updateHtmlTag()
  355. return false
  356. # Update site
  357. @tag.find("#button-update").off("click touchend").on "click touchend", =>
  358. @tag.find("#button-update").addClass("loading")
  359. @wrapper.ws.cmd "siteUpdate", @wrapper.site_info.address, =>
  360. @wrapper.notifications.add "done-updated", "done", "Site updated!", 5000
  361. @tag.find("#button-update").removeClass("loading")
  362. return false
  363. # Pause site
  364. @tag.find("#button-pause").off("click touchend").on "click touchend", =>
  365. @tag.find("#button-pause").addClass("hidden")
  366. @wrapper.ws.cmd "sitePause", @wrapper.site_info.address
  367. return false
  368. # Resume site
  369. @tag.find("#button-resume").off("click touchend").on "click touchend", =>
  370. @tag.find("#button-resume").addClass("hidden")
  371. @wrapper.ws.cmd "siteResume", @wrapper.site_info.address
  372. return false
  373. # Delete site
  374. @tag.find("#button-delete").off("click touchend").on "click touchend", =>
  375. @handleSiteDeleteClick()
  376. return false
  377. # Owned checkbox
  378. @tag.find("#checkbox-owned").off("click touchend").on "click touchend", =>
  379. owned = @tag.find("#checkbox-owned").is(":checked")
  380. @wrapper.ws.cmd "siteSetOwned", [owned], (res_set_owned) =>
  381. @log "Owned", owned
  382. if owned
  383. @wrapper.ws.cmd "siteRecoverPrivatekey", [], (res_recover) =>
  384. if res_recover == "ok"
  385. @wrapper.notifications.add("recover", "done", "Private key recovered from master seed", 5000)
  386. else
  387. @log "Unable to recover private key: #{res_recover.error}"
  388. # Owned auto download checkbox
  389. @tag.find("#checkbox-autodownloadoptional").off("click touchend").on "click touchend", =>
  390. @wrapper.ws.cmd "siteSetAutodownloadoptional", [@tag.find("#checkbox-autodownloadoptional").is(":checked")]
  391. # Change identity button
  392. @tag.find("#button-identity").off("click touchend").on "click touchend", =>
  393. @wrapper.ws.cmd "certSelect"
  394. return false
  395. # Save settings
  396. @tag.find("#button-settings").off("click touchend").on "click touchend", =>
  397. @wrapper.ws.cmd "fileGet", "content.json", (res) =>
  398. data = JSON.parse(res)
  399. data["title"] = $("#settings-title").val()
  400. data["description"] = $("#settings-description").val()
  401. json_raw = unescape(encodeURIComponent(JSON.stringify(data, undefined, '\t')))
  402. @wrapper.ws.cmd "fileWrite", ["content.json", btoa(json_raw), true], (res) =>
  403. if res != "ok" # fileWrite failed
  404. @wrapper.notifications.add "file-write", "error", "File write error: #{res}"
  405. else
  406. @wrapper.notifications.add "file-write", "done", "Site settings saved!", 5000
  407. if @wrapper.site_info.privatekey
  408. @wrapper.ws.cmd "siteSign", {privatekey: "stored", inner_path: "content.json", update_changed_files: true}
  409. @updateHtmlTag()
  410. return false
  411. # Open site directory
  412. @tag.find("#link-directory").off("click touchend").on "click touchend", =>
  413. @wrapper.ws.cmd "serverShowdirectory", ["site", @wrapper.site_info.address]
  414. return false
  415. # Copy site with peers
  416. @tag.find("#link-copypeers").off("click touchend").on "click touchend", (e) =>
  417. copy_text = e.currentTarget.href
  418. handler = (e) =>
  419. e.clipboardData.setData('text/plain', copy_text)
  420. e.preventDefault()
  421. @wrapper.notifications.add "copy", "done", "Site address with peers copied to your clipboard", 5000
  422. document.removeEventListener('copy', handler, true)
  423. document.addEventListener('copy', handler, true)
  424. document.execCommand('copy')
  425. return false
  426. # Sign and publish content.json
  427. $(document).on "click touchend", =>
  428. @tag?.find("#button-sign-publish-menu").removeClass("visible")
  429. @tag?.find(".contents + .flex").removeClass("sign-publish-flex")
  430. @tag.find(".contents-content").off("click touchend").on "click touchend", (e) =>
  431. $("#input-contents").val(e.currentTarget.innerText);
  432. return false;
  433. menu = new Menu(@tag.find("#menu-sign-publish"))
  434. menu.elem.css("margin-top", "-130px") # Open upwards
  435. menu.addItem "Sign", =>
  436. inner_path = @tag.find("#input-contents").val()
  437. @wrapper.ws.cmd "fileRules", {inner_path: inner_path}, (rules) =>
  438. if @wrapper.site_info.auth_address in rules.signers
  439. # ZeroID or other ID provider
  440. @sign(inner_path)
  441. else if @wrapper.site_info.privatekey
  442. # Privatekey stored in users.json
  443. @sign(inner_path, "stored")
  444. else
  445. # Ask the user for privatekey
  446. @wrapper.displayPrompt "Enter your private key:", "password", "Sign", "", (privatekey) => # Prompt the private key
  447. @sign(inner_path, privatekey)
  448. @tag.find(".contents + .flex").removeClass "active"
  449. menu.hide()
  450. menu.addItem "Publish", =>
  451. inner_path = @tag.find("#input-contents").val()
  452. @wrapper.ws.cmd "sitePublish", {"inner_path": inner_path, "sign": false}
  453. @tag.find(".contents + .flex").removeClass "active"
  454. menu.hide()
  455. @tag.find("#menu-sign-publish").off("click touchend").on "click touchend", =>
  456. if window.visible_menu == menu
  457. @tag.find(".contents + .flex").removeClass "active"
  458. menu.hide()
  459. else
  460. @tag.find(".contents + .flex").addClass "active"
  461. @tag.find(".content-wrapper").prop "scrollTop", 10000
  462. menu.show()
  463. return false
  464. $("body").on "click", =>
  465. if @tag
  466. @tag.find(".contents + .flex").removeClass "active"
  467. @tag.find("#button-sign-publish").off("click touchend").on "click touchend", =>
  468. inner_path = @tag.find("#input-contents").val()
  469. @wrapper.ws.cmd "fileRules", {inner_path: inner_path}, (rules) =>
  470. if @wrapper.site_info.auth_address in rules.signers
  471. # ZeroID or other ID provider
  472. @publish(inner_path, null)
  473. else if @wrapper.site_info.privatekey
  474. # Privatekey stored in users.json
  475. @publish(inner_path, "stored")
  476. else
  477. # Ask the user for privatekey
  478. @wrapper.displayPrompt "Enter your private key:", "password", "Sign", "", (privatekey) => # Prompt the private key
  479. @publish(inner_path, privatekey)
  480. return false
  481. # Close
  482. @tag.find(".close").off("click touchend").on "click touchend", (e) =>
  483. @close()
  484. return false
  485. @loadGlobe()
  486. close: ->
  487. @move_lock = "x"
  488. @startDrag()
  489. @stopDrag()
  490. onClosed: ->
  491. $(window).off "resize"
  492. $(window).on "resize", @resized
  493. $(document.body).css("transition", "0.6s ease-in-out").removeClass("body-sidebar").on transitionEnd, (e) =>
  494. if e.target == document.body and not $(document.body).hasClass("body-sidebar") and not $(document.body).hasClass("body-console")
  495. $(document.body).css("height", "auto").css("perspective", "").css("will-change", "").css("transition", "").off transitionEnd
  496. @unloadGlobe()
  497. # We dont need site info anymore
  498. @wrapper.setSiteInfo = @original_set_site_info
  499. loadGlobe: =>
  500. if @tag.find(".globe").hasClass("loading")
  501. setTimeout (=>
  502. if typeof(DAT) == "undefined" # Globe script not loaded, do it first
  503. script_tag = $("<script>")
  504. script_tag.attr("nonce", @wrapper.script_nonce)
  505. script_tag.attr("src", "/uimedia/globe/all.js")
  506. script_tag.on("load", @displayGlobe)
  507. document.head.appendChild(script_tag[0])
  508. else
  509. @displayGlobe()
  510. ), 600
  511. displayGlobe: =>
  512. img = new Image();
  513. img.src = "/uimedia/globe/world.jpg";
  514. img.onload = =>
  515. @wrapper.ws.cmd "sidebarGetPeers", [], (globe_data) =>
  516. if @globe
  517. @globe.scene.remove(@globe.points)
  518. @globe.addData( globe_data, {format: 'magnitude', name: "hello", animated: false} )
  519. @globe.createPoints()
  520. @tag?.find(".globe").removeClass("loading")
  521. else if typeof(DAT) != "undefined"
  522. try
  523. @globe = new DAT.Globe( @tag.find(".globe")[0], {"imgDir": "/uimedia/globe/"} )
  524. @globe.addData( globe_data, {format: 'magnitude', name: "hello"} )
  525. @globe.createPoints()
  526. @globe.animate()
  527. catch e
  528. console.log "WebGL error", e
  529. @tag?.find(".globe").addClass("error").text("WebGL not supported")
  530. @tag?.find(".globe").removeClass("loading")
  531. unloadGlobe: =>
  532. if not @globe
  533. return false
  534. @globe.unload()
  535. @globe = null
  536. wrapper = window.wrapper
  537. setTimeout ( ->
  538. window.sidebar = new Sidebar(wrapper)
  539. ), 500
  540. window.transitionEnd = 'transitionend webkitTransitionEnd oTransitionEnd otransitionend'