Mayx's Home Page
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
4.5 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
  1. /*
  2. * Mayx的博客 · /offline.html 控制页控制器(classic script,PJAX 兼容)
  3. *
  4. * 本体是 IIFE,不含模块语法:PJAX 换页时 jQuery 会重新执行本文件,
  5. * 每次执行都重新查询元素、重新绑定事件,天然幂等。真正的解包逻辑在
  6. * ES module /assets/js/offline-unpack.js 中,通过动态 import() 加载
  7. * (浏览器模块缓存保证 PJAX 反复进入本页也不会重复加载)。
  8. * 注意:本文件经 Liquid 原样输出,不能使用模板语法字符。
  9. */
  10. (function () {
  11. var MODULE_URL = '/assets/js/offline-unpack.js';
  12. // 压缩包大致量级(当前约 27MB),仅用于进度条比例,不影响正确性
  13. var EXPECTED_BYTES = 27 * 1024 * 1024;
  14. var busy = false;
  15. function el(id) { return document.getElementById(id); }
  16. function fmtMB(bytes) { return (bytes / 1048576).toFixed(1) + ' MB'; }
  17. function setMessage(text) {
  18. el('offline-message').textContent = text || '';
  19. }
  20. function showProgress(show) {
  21. el('offline-progress-box').hidden = !show;
  22. }
  23. function render(meta) {
  24. var online = !meta;
  25. el('offline-state').textContent = online
  26. ? '在线模式(离线未启用)'
  27. : '离线模式(优先从本地缓存加载)';
  28. el('offline-version').textContent = online ? '-' : fmtMB(meta.payloadSize) + '(压缩包大小即版本号)';
  29. el('offline-files').textContent = online ? '-' : meta.files + ' 个文件 / ' + fmtMB(meta.bytes);
  30. el('offline-time').textContent = online ? '-' : new Date(meta.unpackedAt).toLocaleString();
  31. el('offline-persist').textContent = online ? '-' : (meta.persisted ? '已授权(缓存不会被自动回收)' : '未授权(浏览器空间紧张时可能回收缓存)');
  32. el('offline-enable').disabled = busy || !online;
  33. el('offline-disable').disabled = busy || online;
  34. }
  35. function onProgress(info) {
  36. if (info.done) return;
  37. el('offline-progress').value = Math.min(100, (info.bytes / EXPECTED_BYTES) * 100);
  38. el('offline-progress-text').textContent =
  39. '已解包 ' + info.files + ' 个文件(' + fmtMB(info.bytes) + ')…';
  40. }
  41. function withModule(fn) {
  42. return import(MODULE_URL).then(fn);
  43. }
  44. function refresh() {
  45. if (!('serviceWorker' in navigator) || !('caches' in window)) {
  46. el('offline-state').textContent = '当前浏览器不支持离线模式(需要 Service Worker)';
  47. el('offline-enable').disabled = true;
  48. el('offline-disable').disabled = true;
  49. return;
  50. }
  51. withModule(function (mod) { return mod.ensureFresh(); }).then(function (fresh) {
  52. render(fresh.ready ? fresh.meta : null);
  53. if (fresh.stale) {
  54. setMessage('检测到站点压缩包已更新,离线缓存已自动失效,当前处于在线模式。可重新启用离线模式。');
  55. }
  56. }).catch(function (e) {
  57. setMessage('状态检测失败:' + (e && e.message ? e.message : e));
  58. });
  59. }
  60. function onEnable() {
  61. busy = true;
  62. render(null);
  63. showProgress(true);
  64. setMessage('正在下载并解包站点压缩包,请保持网络连接…');
  65. withModule(function (mod) { return mod.activateOffline({ onProgress: onProgress }); })
  66. .then(function (meta) {
  67. el('offline-progress').value = 100;
  68. el('offline-progress-text').textContent = '解包完成';
  69. setMessage('离线模式已启用。之后访问本博客将优先使用本地缓存,断网也能阅读。');
  70. busy = false;
  71. showProgress(false);
  72. render(meta); // 立即展示离线状态,不必等后台刷新
  73. })
  74. .catch(function (e) {
  75. setMessage('启用失败:' + (e && e.message ? e.message : e));
  76. busy = false;
  77. showProgress(false);
  78. refresh();
  79. });
  80. }
  81. function onDisable() {
  82. busy = true;
  83. setMessage('');
  84. withModule(function (mod) { return mod.deactivateOffline(); })
  85. .then(function () {
  86. setMessage('已切回在线模式,之后页面将通过网络加载。');
  87. busy = false;
  88. render(null);
  89. if (navigator.onLine) {
  90. setTimeout(function () { location.reload(); }, 800);
  91. }
  92. })
  93. .catch(function (e) {
  94. setMessage('操作失败:' + (e && e.message ? e.message : e));
  95. busy = false;
  96. refresh();
  97. });
  98. }
  99. function bind() {
  100. var enable = el('offline-enable');
  101. if (!enable) return; // 不在控制页(PJAX 容错)
  102. enable.addEventListener('click', onEnable);
  103. el('offline-disable').addEventListener('click', onDisable);
  104. refresh();
  105. }
  106. bind();
  107. })();