download.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* global downloadMetadata */
  2. const html = require('choo/html');
  3. const archiveTile = require('./archiveTile');
  4. const modal = require('./modal');
  5. const notFound = require('./notFound');
  6. function password(state, emit) {
  7. const fileInfo = state.fileInfo;
  8. const invalid = fileInfo.password === null;
  9. const div = html`
  10. <div
  11. class="h-full w-full flex flex-col items-center justify-center bg-white py-8"
  12. >
  13. <h1 class="mb-4">${state.translate('downloadFileTitle')}</h1>
  14. <form
  15. class="flex flex-row flex-no-wrap w-full md:w-4/5"
  16. onsubmit="${checkPassword}"
  17. data-no-csrf
  18. >
  19. <input
  20. id="password-input"
  21. class="w-full border-l border-t border-b rounded-l-lg rounded-r-none ${invalid
  22. ? 'border-red'
  23. : 'border-grey'} leading-loose px-2 py-1"
  24. maxlength="32"
  25. autocomplete="off"
  26. placeholder="${state.translate('unlockInputPlaceholder')}"
  27. oninput="${inputChanged}"
  28. type="password"
  29. />
  30. <input
  31. type="submit"
  32. id="password-btn"
  33. class="btn rounded-r-lg rounded-l-none ${invalid
  34. ? 'bg-red hover:bg-red focus:bg-red'
  35. : ''}"
  36. value="${state.translate('unlockButtonLabel')}"
  37. title="${state.translate('unlockButtonLabel')}"
  38. />
  39. </form>
  40. <label
  41. id="password-error"
  42. class="${invalid ? '' : 'invisible'} text-red my-4"
  43. for="password-input"
  44. >
  45. ${state.translate('passwordTryAgain')}
  46. </label>
  47. </div>
  48. `;
  49. if (!(div instanceof String)) {
  50. setTimeout(() => document.getElementById('password-input').focus());
  51. }
  52. function inputChanged(event) {
  53. event.stopPropagation();
  54. event.preventDefault();
  55. const label = document.getElementById('password-error');
  56. const input = document.getElementById('password-input');
  57. const btn = document.getElementById('password-btn');
  58. label.classList.add('invisible');
  59. input.classList.remove('border-red');
  60. btn.classList.remove('bg-red', 'hover:bg-red', 'focus:bg-red');
  61. }
  62. function checkPassword(event) {
  63. event.stopPropagation();
  64. event.preventDefault();
  65. const el = document.getElementById('password-input');
  66. const password = el.value;
  67. if (password.length > 0) {
  68. document.getElementById('password-btn').disabled = true;
  69. state.fileInfo.url = window.location.href;
  70. state.fileInfo.password = password;
  71. emit('getMetadata');
  72. }
  73. return false;
  74. }
  75. return div;
  76. }
  77. function createFileInfo(state) {
  78. return {
  79. id: state.params.id,
  80. secretKey: state.params.key,
  81. nonce: downloadMetadata.nonce,
  82. requiresPassword: downloadMetadata.pwd
  83. };
  84. }
  85. module.exports = function(state, emit) {
  86. let content = '';
  87. if (!state.fileInfo) {
  88. state.fileInfo = createFileInfo(state);
  89. if (!state.fileInfo.nonce) {
  90. return notFound(state);
  91. }
  92. }
  93. if (!state.transfer && !state.fileInfo.requiresPassword) {
  94. emit('getMetadata');
  95. }
  96. if (state.transfer) {
  97. switch (state.transfer.state) {
  98. case 'downloading':
  99. case 'decrypting':
  100. content = html`
  101. <div class="flex flex-col w-full h-full items-center mt-8">
  102. <h1 class="mb-4">${state.translate('downloadingTitle')}</h1>
  103. ${archiveTile.downloading(state, emit)}
  104. </div>
  105. `;
  106. break;
  107. case 'complete':
  108. content = html`
  109. <div
  110. id="download-complete"
  111. class="flex flex-col items-center justify-center h-full w-full bg-white border border-grey-light p-2"
  112. >
  113. <h1 class="text-center font-bold my-4 text-2xl">
  114. ${state.translate('downloadFinish')}
  115. </h1>
  116. <p class="mb-4">
  117. <a
  118. href="/"
  119. class="text-blue hover:text-blue-dark focus:text-blue-darker font-medium"
  120. >${state.translate('sendYourFilesLink')}</a
  121. >
  122. </p>
  123. </div>
  124. `;
  125. break;
  126. default:
  127. content = html`
  128. <div class="flex flex-col w-full h-full items-center mt-8">
  129. <h1 class="mb-4">${state.translate('downloadFileTitle')}</h1>
  130. ${archiveTile.preview(state, emit)}
  131. </div>
  132. `;
  133. }
  134. } else if (state.fileInfo.requiresPassword && !state.fileInfo.password) {
  135. content = password(state, emit);
  136. }
  137. return html`
  138. <main class="main container">
  139. ${state.modal && modal(state, emit)}
  140. <section
  141. class="relative h-full w-full p-6 md:flex md:flex-row md:rounded-lg md:shadow-big"
  142. >
  143. ${content}
  144. </section>
  145. </main>
  146. `;
  147. };