offline_page.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. app.views.OfflinePage = class OfflinePage extends app.View {
  2. static className = "_static";
  3. static events = {
  4. click: "onClick",
  5. change: "onChange",
  6. };
  7. deactivate() {
  8. if (super.deactivate(...arguments)) {
  9. this.empty();
  10. }
  11. }
  12. render() {
  13. if (app.cookieBlocked) {
  14. this.html(this.tmpl("offlineError", "cookie_blocked"));
  15. return;
  16. }
  17. app.docs.getInstallStatuses((statuses) => {
  18. if (!this.activated) {
  19. return;
  20. }
  21. if (statuses === false) {
  22. this.html(this.tmpl("offlineError", app.db.reason, app.db.error));
  23. } else {
  24. let html = "";
  25. for (var doc of app.docs.all()) {
  26. html += this.renderDoc(doc, statuses[doc.slug]);
  27. }
  28. this.html(this.tmpl("offlinePage", html));
  29. this.refreshLinks();
  30. }
  31. });
  32. }
  33. renderDoc(doc, status) {
  34. return app.templates.render("offlineDoc", doc, status);
  35. }
  36. getTitle() {
  37. return "Offline";
  38. }
  39. refreshLinks() {
  40. for (var action of ["install", "update", "uninstall"]) {
  41. this.find(`[data-action-all='${action}']`).classList[
  42. this.find(`[data-action='${action}']`) ? "add" : "remove"
  43. ]("_show");
  44. }
  45. }
  46. docByEl(el) {
  47. let slug;
  48. while (!(slug = el.getAttribute("data-slug"))) {
  49. el = el.parentNode;
  50. }
  51. return app.docs.findBy("slug", slug);
  52. }
  53. docEl(doc) {
  54. return this.find(`[data-slug='${doc.slug}']`);
  55. }
  56. onRoute(context) {
  57. this.render();
  58. }
  59. onClick(event) {
  60. let action;
  61. let el = $.eventTarget(event);
  62. if ((action = el.getAttribute("data-action"))) {
  63. const doc = this.docByEl(el);
  64. if (action === "update") {
  65. action = "install";
  66. }
  67. doc[action](
  68. this.onInstallSuccess.bind(this, doc),
  69. this.onInstallError.bind(this, doc),
  70. this.onInstallProgress.bind(this, doc),
  71. );
  72. el.parentNode.innerHTML = `${el.textContent.replace(/e$/, "")}ing…`;
  73. } else if (
  74. (action =
  75. el.getAttribute("data-action-all") ||
  76. el.parentElement.getAttribute("data-action-all"))
  77. ) {
  78. if (action === "uninstall" && !window.confirm("Uninstall all docs?")) {
  79. return;
  80. }
  81. app.db.migrate();
  82. for (el of Array.from(this.findAll(`[data-action='${action}']`))) {
  83. $.click(el);
  84. }
  85. }
  86. }
  87. onInstallSuccess(doc) {
  88. if (!this.activated) {
  89. return;
  90. }
  91. doc.getInstallStatus((status) => {
  92. let el;
  93. if (!this.activated) {
  94. return;
  95. }
  96. if ((el = this.docEl(doc))) {
  97. el.outerHTML = this.renderDoc(doc, status);
  98. $.highlight(el, { className: "_highlight" });
  99. this.refreshLinks();
  100. }
  101. });
  102. }
  103. onInstallError(doc) {
  104. let el;
  105. if (!this.activated) {
  106. return;
  107. }
  108. if ((el = this.docEl(doc))) {
  109. el.lastElementChild.textContent = "Error";
  110. }
  111. }
  112. onInstallProgress(doc, event) {
  113. let el;
  114. if (!this.activated || !event.lengthComputable) {
  115. return;
  116. }
  117. if ((el = this.docEl(doc))) {
  118. const percentage = Math.round((event.loaded * 100) / event.total);
  119. el.lastElementChild.textContent = el.lastElementChild.textContent.replace(
  120. /(\s.+)?$/,
  121. ` (${percentage}%)`,
  122. );
  123. }
  124. }
  125. onChange(event) {
  126. if (event.target.name === "autoUpdate") {
  127. app.settings.set("manualUpdate", !event.target.checked);
  128. }
  129. }
  130. };