@concord-consortium/cloud-file-manager 2.1.0-pre.9 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/dist/347 +276 -0
  2. package/dist/autolaunch/autolaunch.js +1 -1
  3. package/dist/autolaunch/autolaunch.js.map +1 -1
  4. package/dist/cjs/app-options.d.ts +2 -0
  5. package/dist/cjs/client.js +51 -79
  6. package/dist/cjs/client.js.map +1 -1
  7. package/dist/cjs/cloud-file-manager.js +2 -2
  8. package/dist/cjs/cloud-file-manager.js.map +1 -1
  9. package/dist/cjs/create-react-factory.d.ts +1 -0
  10. package/dist/cjs/create-react-factory.js.map +1 -1
  11. package/dist/cjs/providers/document-store-provider.js +7 -10
  12. package/dist/cjs/providers/document-store-provider.js.map +1 -1
  13. package/dist/cjs/providers/document-store-share-provider.js +4 -4
  14. package/dist/cjs/providers/document-store-share-provider.js.map +1 -1
  15. package/dist/cjs/providers/google-drive-provider.js +30 -34
  16. package/dist/cjs/providers/google-drive-provider.js.map +1 -1
  17. package/dist/cjs/providers/interactive-api-provider.d.ts +5 -2
  18. package/dist/cjs/providers/interactive-api-provider.js +27 -21
  19. package/dist/cjs/providers/interactive-api-provider.js.map +1 -1
  20. package/dist/cjs/providers/lara-provider.js +18 -26
  21. package/dist/cjs/providers/lara-provider.js.map +1 -1
  22. package/dist/cjs/providers/legacy-google-drive-provider.js +21 -27
  23. package/dist/cjs/providers/legacy-google-drive-provider.js.map +1 -1
  24. package/dist/cjs/providers/localstorage-provider.js +11 -13
  25. package/dist/cjs/providers/localstorage-provider.js.map +1 -1
  26. package/dist/cjs/providers/patchable-content.js +1 -1
  27. package/dist/cjs/providers/patchable-content.js.map +1 -1
  28. package/dist/cjs/providers/post-message-provider.js +1 -1
  29. package/dist/cjs/providers/post-message-provider.js.map +1 -1
  30. package/dist/cjs/providers/provider-interface.d.ts +1 -2
  31. package/dist/cjs/providers/provider-interface.js +11 -14
  32. package/dist/cjs/providers/provider-interface.js.map +1 -1
  33. package/dist/cjs/providers/readonly-provider.js +6 -6
  34. package/dist/cjs/providers/readonly-provider.js.map +1 -1
  35. package/dist/cjs/providers/s3-provider.js +1 -2
  36. package/dist/cjs/providers/s3-provider.js.map +1 -1
  37. package/dist/cjs/providers/s3-share-provider.js +1 -1
  38. package/dist/cjs/providers/s3-share-provider.js.map +1 -1
  39. package/dist/cjs/providers/test-provider.js +5 -5
  40. package/dist/cjs/providers/test-provider.js.map +1 -1
  41. package/dist/cjs/providers/url-provider.js +1 -1
  42. package/dist/cjs/providers/url-provider.js.map +1 -1
  43. package/dist/cjs/ui.js +2 -3
  44. package/dist/cjs/ui.js.map +1 -1
  45. package/dist/cjs/utils/focus-tracker.d.ts +3 -0
  46. package/dist/cjs/utils/focus-tracker.js +44 -0
  47. package/dist/cjs/utils/focus-tracker.js.map +1 -0
  48. package/dist/cjs/utils/ios-file-saver.d.ts +42 -0
  49. package/dist/cjs/utils/ios-file-saver.js +98 -0
  50. package/dist/cjs/utils/ios-file-saver.js.map +1 -0
  51. package/dist/cjs/utils/lang/en-US.json +9 -0
  52. package/dist/cjs/utils/s3-share-provider-token-service-helper.js +19 -13
  53. package/dist/cjs/utils/s3-share-provider-token-service-helper.js.map +1 -1
  54. package/dist/cjs/utils/url-params.js +1 -2
  55. package/dist/cjs/utils/url-params.js.map +1 -1
  56. package/dist/cjs/views/alert-dialog-view.d.ts +9 -3
  57. package/dist/cjs/views/alert-dialog-view.js +9 -24
  58. package/dist/cjs/views/alert-dialog-view.js.map +1 -1
  59. package/dist/cjs/views/app-view.d.ts +12 -5
  60. package/dist/cjs/views/app-view.js +167 -175
  61. package/dist/cjs/views/app-view.js.map +1 -1
  62. package/dist/cjs/views/blocking-modal-view.d.ts +9 -3
  63. package/dist/cjs/views/blocking-modal-view.js +8 -25
  64. package/dist/cjs/views/blocking-modal-view.js.map +1 -1
  65. package/dist/cjs/views/confirm-dialog-view.d.ts +14 -3
  66. package/dist/cjs/views/confirm-dialog-view.js +14 -31
  67. package/dist/cjs/views/confirm-dialog-view.js.map +1 -1
  68. package/dist/cjs/views/download-dialog-view.d.ts +12 -3
  69. package/dist/cjs/views/download-dialog-view.js +36 -63
  70. package/dist/cjs/views/download-dialog-view.js.map +1 -1
  71. package/dist/cjs/views/dropdown-anchors.d.ts +2 -2
  72. package/dist/cjs/views/dropdown-anchors.js +4 -10
  73. package/dist/cjs/views/dropdown-anchors.js.map +1 -1
  74. package/dist/cjs/views/dropdown-view.d.ts +20 -3
  75. package/dist/cjs/views/dropdown-view.js +40 -157
  76. package/dist/cjs/views/dropdown-view.js.map +1 -1
  77. package/dist/cjs/views/file-dialog-tab-view.d.ts +24 -2
  78. package/dist/cjs/views/file-dialog-tab-view.js +255 -315
  79. package/dist/cjs/views/file-dialog-tab-view.js.map +1 -1
  80. package/dist/cjs/views/icons/spin.d.ts +2 -2
  81. package/dist/cjs/views/icons/spin.js +2 -39
  82. package/dist/cjs/views/icons/spin.js.map +1 -1
  83. package/dist/cjs/views/import-tabbed-dialog-view.d.ts +12 -3
  84. package/dist/cjs/views/import-tabbed-dialog-view.js +33 -65
  85. package/dist/cjs/views/import-tabbed-dialog-view.js.map +1 -1
  86. package/dist/cjs/views/local-file-tab-list-view.d.ts +14 -3
  87. package/dist/cjs/views/local-file-tab-list-view.js +57 -66
  88. package/dist/cjs/views/local-file-tab-list-view.js.map +1 -1
  89. package/dist/cjs/views/local-file-tab-save-view.d.ts +32 -3
  90. package/dist/cjs/views/local-file-tab-save-view.js +125 -138
  91. package/dist/cjs/views/local-file-tab-save-view.js.map +1 -1
  92. package/dist/cjs/views/menu-bar-view.d.ts +58 -3
  93. package/dist/cjs/views/menu-bar-view.js +196 -183
  94. package/dist/cjs/views/menu-bar-view.js.map +1 -1
  95. package/dist/cjs/views/modal-dialog-view.js +7 -8
  96. package/dist/cjs/views/modal-dialog-view.js.map +1 -1
  97. package/dist/cjs/views/modal-tabbed-dialog-view.d.ts +15 -3
  98. package/dist/cjs/views/modal-tabbed-dialog-view.js +5 -17
  99. package/dist/cjs/views/modal-tabbed-dialog-view.js.map +1 -1
  100. package/dist/cjs/views/modal-view.d.ts +5 -32
  101. package/dist/cjs/views/modal-view.js +20 -64
  102. package/dist/cjs/views/modal-view.js.map +1 -1
  103. package/dist/cjs/views/provider-tabbed-dialog-view.d.ts +23 -3
  104. package/dist/cjs/views/provider-tabbed-dialog-view.js +43 -51
  105. package/dist/cjs/views/provider-tabbed-dialog-view.js.map +1 -1
  106. package/dist/cjs/views/rename-dialog-view.d.ts +8 -3
  107. package/dist/cjs/views/rename-dialog-view.js +25 -51
  108. package/dist/cjs/views/rename-dialog-view.js.map +1 -1
  109. package/dist/cjs/views/select-interactive-state-dialog-view.d.ts +1 -1
  110. package/dist/cjs/views/select-interactive-state-dialog-view.js +4 -30
  111. package/dist/cjs/views/select-interactive-state-dialog-view.js.map +1 -1
  112. package/dist/cjs/views/select-provider-dialog-tab-view.d.ts +6 -1
  113. package/dist/cjs/views/select-provider-dialog-tab-view.js +4 -12
  114. package/dist/cjs/views/select-provider-dialog-tab-view.js.map +1 -1
  115. package/dist/cjs/views/share-dialog-status-view.js +6 -13
  116. package/dist/cjs/views/share-dialog-status-view.js.map +1 -1
  117. package/dist/cjs/views/share-dialog-tabs-view.js +22 -61
  118. package/dist/cjs/views/share-dialog-tabs-view.js.map +1 -1
  119. package/dist/cjs/views/share-dialog-view.d.ts +1 -1
  120. package/dist/cjs/views/share-dialog-view.js +15 -21
  121. package/dist/cjs/views/share-dialog-view.js.map +1 -1
  122. package/dist/cjs/views/share-loading-view.d.ts +2 -2
  123. package/dist/cjs/views/share-loading-view.js +2 -4
  124. package/dist/cjs/views/share-loading-view.js.map +1 -1
  125. package/dist/cjs/views/tabbed-panel-view.d.ts +16 -3
  126. package/dist/cjs/views/tabbed-panel-view.js +25 -75
  127. package/dist/cjs/views/tabbed-panel-view.js.map +1 -1
  128. package/dist/cjs/views/url-tab-view.d.ts +12 -3
  129. package/dist/cjs/views/url-tab-view.js +31 -46
  130. package/dist/cjs/views/url-tab-view.js.map +1 -1
  131. package/dist/css/app.css +1 -1
  132. package/dist/css/app.css.map +1 -1
  133. package/dist/esm/app-options.d.ts +2 -0
  134. package/dist/esm/client.js +51 -79
  135. package/dist/esm/client.js.map +1 -1
  136. package/dist/esm/cloud-file-manager.js +2 -2
  137. package/dist/esm/cloud-file-manager.js.map +1 -1
  138. package/dist/esm/create-react-factory.d.ts +1 -0
  139. package/dist/esm/create-react-factory.js.map +1 -1
  140. package/dist/esm/providers/document-store-provider.js +7 -10
  141. package/dist/esm/providers/document-store-provider.js.map +1 -1
  142. package/dist/esm/providers/document-store-share-provider.js +4 -4
  143. package/dist/esm/providers/document-store-share-provider.js.map +1 -1
  144. package/dist/esm/providers/google-drive-provider.js +30 -34
  145. package/dist/esm/providers/google-drive-provider.js.map +1 -1
  146. package/dist/esm/providers/interactive-api-provider.d.ts +5 -2
  147. package/dist/esm/providers/interactive-api-provider.js +25 -20
  148. package/dist/esm/providers/interactive-api-provider.js.map +1 -1
  149. package/dist/esm/providers/lara-provider.js +18 -26
  150. package/dist/esm/providers/lara-provider.js.map +1 -1
  151. package/dist/esm/providers/legacy-google-drive-provider.js +21 -27
  152. package/dist/esm/providers/legacy-google-drive-provider.js.map +1 -1
  153. package/dist/esm/providers/localstorage-provider.js +11 -13
  154. package/dist/esm/providers/localstorage-provider.js.map +1 -1
  155. package/dist/esm/providers/patchable-content.js +1 -1
  156. package/dist/esm/providers/patchable-content.js.map +1 -1
  157. package/dist/esm/providers/post-message-provider.js +1 -1
  158. package/dist/esm/providers/post-message-provider.js.map +1 -1
  159. package/dist/esm/providers/provider-interface.d.ts +1 -2
  160. package/dist/esm/providers/provider-interface.js +11 -14
  161. package/dist/esm/providers/provider-interface.js.map +1 -1
  162. package/dist/esm/providers/readonly-provider.js +6 -6
  163. package/dist/esm/providers/readonly-provider.js.map +1 -1
  164. package/dist/esm/providers/s3-provider.js +1 -2
  165. package/dist/esm/providers/s3-provider.js.map +1 -1
  166. package/dist/esm/providers/s3-share-provider.js +1 -1
  167. package/dist/esm/providers/s3-share-provider.js.map +1 -1
  168. package/dist/esm/providers/test-provider.js +5 -5
  169. package/dist/esm/providers/test-provider.js.map +1 -1
  170. package/dist/esm/providers/url-provider.js +1 -1
  171. package/dist/esm/providers/url-provider.js.map +1 -1
  172. package/dist/esm/ui.js +2 -3
  173. package/dist/esm/ui.js.map +1 -1
  174. package/dist/esm/utils/focus-tracker.d.ts +3 -0
  175. package/dist/esm/utils/focus-tracker.js +38 -0
  176. package/dist/esm/utils/focus-tracker.js.map +1 -0
  177. package/dist/esm/utils/ios-file-saver.d.ts +42 -0
  178. package/dist/esm/utils/ios-file-saver.js +91 -0
  179. package/dist/esm/utils/ios-file-saver.js.map +1 -0
  180. package/dist/esm/utils/lang/en-US.json +9 -0
  181. package/dist/esm/utils/s3-share-provider-token-service-helper.js +19 -10
  182. package/dist/esm/utils/s3-share-provider-token-service-helper.js.map +1 -1
  183. package/dist/esm/utils/url-params.js +1 -2
  184. package/dist/esm/utils/url-params.js.map +1 -1
  185. package/dist/esm/views/alert-dialog-view.d.ts +9 -3
  186. package/dist/esm/views/alert-dialog-view.js +10 -25
  187. package/dist/esm/views/alert-dialog-view.js.map +1 -1
  188. package/dist/esm/views/app-view.d.ts +12 -5
  189. package/dist/esm/views/app-view.js +176 -184
  190. package/dist/esm/views/app-view.js.map +1 -1
  191. package/dist/esm/views/blocking-modal-view.d.ts +9 -3
  192. package/dist/esm/views/blocking-modal-view.js +9 -26
  193. package/dist/esm/views/blocking-modal-view.js.map +1 -1
  194. package/dist/esm/views/confirm-dialog-view.d.ts +14 -3
  195. package/dist/esm/views/confirm-dialog-view.js +15 -32
  196. package/dist/esm/views/confirm-dialog-view.js.map +1 -1
  197. package/dist/esm/views/download-dialog-view.d.ts +12 -3
  198. package/dist/esm/views/download-dialog-view.js +36 -63
  199. package/dist/esm/views/download-dialog-view.js.map +1 -1
  200. package/dist/esm/views/dropdown-anchors.d.ts +2 -2
  201. package/dist/esm/views/dropdown-anchors.js +4 -7
  202. package/dist/esm/views/dropdown-anchors.js.map +1 -1
  203. package/dist/esm/views/dropdown-view.d.ts +20 -3
  204. package/dist/esm/views/dropdown-view.js +40 -154
  205. package/dist/esm/views/dropdown-view.js.map +1 -1
  206. package/dist/esm/views/file-dialog-tab-view.d.ts +24 -2
  207. package/dist/esm/views/file-dialog-tab-view.js +256 -316
  208. package/dist/esm/views/file-dialog-tab-view.js.map +1 -1
  209. package/dist/esm/views/icons/spin.d.ts +2 -2
  210. package/dist/esm/views/icons/spin.js +2 -36
  211. package/dist/esm/views/icons/spin.js.map +1 -1
  212. package/dist/esm/views/import-tabbed-dialog-view.d.ts +12 -3
  213. package/dist/esm/views/import-tabbed-dialog-view.js +36 -68
  214. package/dist/esm/views/import-tabbed-dialog-view.js.map +1 -1
  215. package/dist/esm/views/local-file-tab-list-view.d.ts +14 -3
  216. package/dist/esm/views/local-file-tab-list-view.js +57 -66
  217. package/dist/esm/views/local-file-tab-list-view.js.map +1 -1
  218. package/dist/esm/views/local-file-tab-save-view.d.ts +32 -3
  219. package/dist/esm/views/local-file-tab-save-view.js +125 -138
  220. package/dist/esm/views/local-file-tab-save-view.js.map +1 -1
  221. package/dist/esm/views/menu-bar-view.d.ts +58 -3
  222. package/dist/esm/views/menu-bar-view.js +198 -185
  223. package/dist/esm/views/menu-bar-view.js.map +1 -1
  224. package/dist/esm/views/modal-dialog-view.js +7 -8
  225. package/dist/esm/views/modal-dialog-view.js.map +1 -1
  226. package/dist/esm/views/modal-tabbed-dialog-view.d.ts +15 -3
  227. package/dist/esm/views/modal-tabbed-dialog-view.js +7 -19
  228. package/dist/esm/views/modal-tabbed-dialog-view.js.map +1 -1
  229. package/dist/esm/views/modal-view.d.ts +5 -32
  230. package/dist/esm/views/modal-view.js +21 -61
  231. package/dist/esm/views/modal-view.js.map +1 -1
  232. package/dist/esm/views/provider-tabbed-dialog-view.d.ts +23 -3
  233. package/dist/esm/views/provider-tabbed-dialog-view.js +46 -54
  234. package/dist/esm/views/provider-tabbed-dialog-view.js.map +1 -1
  235. package/dist/esm/views/rename-dialog-view.d.ts +8 -3
  236. package/dist/esm/views/rename-dialog-view.js +25 -51
  237. package/dist/esm/views/rename-dialog-view.js.map +1 -1
  238. package/dist/esm/views/select-interactive-state-dialog-view.d.ts +1 -1
  239. package/dist/esm/views/select-interactive-state-dialog-view.js +4 -30
  240. package/dist/esm/views/select-interactive-state-dialog-view.js.map +1 -1
  241. package/dist/esm/views/select-provider-dialog-tab-view.d.ts +6 -1
  242. package/dist/esm/views/select-provider-dialog-tab-view.js +4 -9
  243. package/dist/esm/views/select-provider-dialog-tab-view.js.map +1 -1
  244. package/dist/esm/views/share-dialog-status-view.js +6 -13
  245. package/dist/esm/views/share-dialog-status-view.js.map +1 -1
  246. package/dist/esm/views/share-dialog-tabs-view.js +22 -61
  247. package/dist/esm/views/share-dialog-tabs-view.js.map +1 -1
  248. package/dist/esm/views/share-dialog-view.d.ts +1 -1
  249. package/dist/esm/views/share-dialog-view.js +15 -21
  250. package/dist/esm/views/share-dialog-view.js.map +1 -1
  251. package/dist/esm/views/share-loading-view.d.ts +2 -2
  252. package/dist/esm/views/share-loading-view.js +2 -4
  253. package/dist/esm/views/share-loading-view.js.map +1 -1
  254. package/dist/esm/views/tabbed-panel-view.d.ts +16 -3
  255. package/dist/esm/views/tabbed-panel-view.js +25 -72
  256. package/dist/esm/views/tabbed-panel-view.js.map +1 -1
  257. package/dist/esm/views/url-tab-view.d.ts +12 -3
  258. package/dist/esm/views/url-tab-view.js +31 -46
  259. package/dist/esm/views/url-tab-view.js.map +1 -1
  260. package/dist/examples/codap3-local-file.html +42 -0
  261. package/dist/examples/index.html +2 -0
  262. package/dist/examples/local-json-save.html +36 -0
  263. package/dist/index.html +1 -1
  264. package/dist/js/app.js +1 -1
  265. package/dist/js/app.js.LICENSE.txt +41 -11
  266. package/dist/js/app.js.map +1 -1
  267. package/dist/js/globals.js +1 -1
  268. package/dist/js/globals.js.map +1 -1
  269. package/package.json +40 -36
  270. package/readme.md +4 -0
  271. package/dist/cjs/lib/file-saver.d.ts +0 -2
  272. package/dist/cjs/lib/file-saver.js +0 -164
  273. package/dist/cjs/lib/file-saver.js.map +0 -1
  274. package/dist/esm/lib/file-saver.d.ts +0 -2
  275. package/dist/esm/lib/file-saver.js +0 -164
  276. package/dist/esm/lib/file-saver.js.map +0 -1
@@ -1,238 +1,121 @@
1
1
  "use strict";
2
- // TODO: This file was created by bulk-decaffeinate.
3
- // Sanity-check the conversion and remove this comment.
4
- /*
5
- * decaffeinate suggestions:
6
- * DS101: Remove unnecessary use of Array.from
7
- * DS102: Remove unnecessary code created because of implicit returns
8
- * DS205: Consider reworking code to avoid use of IIFEs
9
- * DS207: Consider shorter variations of null checks
10
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
11
- */
12
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
13
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
14
4
  };
15
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
16
8
  const jquery_1 = __importDefault(require("jquery"));
17
9
  const lodash_1 = __importDefault(require("lodash"));
18
- const create_react_class_1 = __importDefault(require("create-react-class"));
19
- const react_dom_factories_1 = __importDefault(require("react-dom-factories"));
20
- const create_react_factory_1 = require("../create-react-factory");
21
10
  const provider_interface_1 = require("../providers/provider-interface");
22
11
  const translate_1 = __importDefault(require("../utils/translate"));
23
- const { div, i, input, button } = react_dom_factories_1.default;
24
- const italic = i;
25
- const FileListFile = (0, create_react_factory_1.createReactClassFactory)({
26
- displayName: 'FileListFile',
27
- componentDidMount() {
28
- return this.lastClick = 0;
29
- },
30
- fileSelected(e) {
12
+ const FileListFile = ({ metadata, selected, isSubFolder, fileSelected, fileConfirmed }) => {
13
+ const lastClickRef = (0, react_1.useRef)(0);
14
+ const isSelectable = metadata.type !== provider_interface_1.CloudMetadata.Label;
15
+ const handleFileSelected = (e) => {
31
16
  e.preventDefault();
32
17
  e.stopPropagation();
33
- const now = (new Date()).getTime();
34
- this.props.fileSelected(this.props.metadata);
35
- if ((now - this.lastClick) <= 250) {
36
- this.props.fileConfirmed();
18
+ const now = new Date().getTime();
19
+ fileSelected(metadata);
20
+ if (now - lastClickRef.current <= 250) {
21
+ fileConfirmed();
37
22
  }
38
- return this.lastClick = now;
39
- },
40
- render() {
41
- const selectableClass = this.props.metadata.type !== provider_interface_1.CloudMetadata.Label ? 'selectable' : '';
42
- const selectedClass = this.props.selected ? 'selected' : '';
43
- const subFolderClass = this.props.isSubFolder ? 'subfolder' : '';
44
- return (div({ className: `${selectableClass} ${selectedClass} ${subFolderClass}`,
45
- title: this.props.metadata.description || undefined,
46
- onClick: this.props.metadata.type !== provider_interface_1.CloudMetadata.Label ? this.fileSelected : undefined }, (italic({ className: (() => {
47
- if (this.props.metadata.type === provider_interface_1.CloudMetadata.Folder) {
48
- return 'icon-inspectorArrow-collapse';
49
- }
50
- else if (this.props.metadata.type === provider_interface_1.CloudMetadata.File) {
51
- return 'icon-noteTool';
52
- }
53
- })() })), this.props.metadata.name));
54
- }
55
- });
56
- const FileList = (0, create_react_factory_1.createReactClassFactory)({
57
- displayName: 'FileList',
58
- getInitialState() {
59
- return { loading: true };
60
- },
61
- componentDidMount() {
62
- this._isMounted = true;
63
- return this.load(this.props.folder);
64
- },
65
- UNSAFE_componentWillReceiveProps(nextProps) {
66
- if (nextProps.folder !== this.props.folder) {
67
- return this.load(nextProps.folder);
68
- }
69
- },
70
- componentWillUnmount() {
71
- return this._isMounted = false;
72
- },
73
- load(folder) {
74
- this.setState({ loading: true });
75
- return this.props.provider.list(folder, (err, list) => {
76
- // asynchronous callback may be called after dialog has been dismissed
77
- if (this._isMounted) {
78
- this.setState({ loading: false });
79
- }
80
- if (err) {
81
- return this.props.client.alert(err);
23
+ lastClickRef.current = now;
24
+ };
25
+ const handleKeyDown = (e) => {
26
+ if (e.key === 'Enter') {
27
+ fileSelected(metadata);
28
+ if (metadata.type === provider_interface_1.CloudMetadata.File) {
29
+ fileConfirmed();
82
30
  }
83
- return this.props.listLoaded(list);
84
- }, this.props.listOptions);
85
- },
86
- parentSelected(e) {
87
- var _a;
88
- return this.props.fileSelected((_a = this.props.folder) === null || _a === void 0 ? void 0 : _a.parent);
89
- },
90
- fileSelected(metadata) {
91
- if (!this.state.loading) {
92
- this.props.fileSelected(metadata);
93
31
  }
94
- },
95
- fileConfirmed() {
96
- if (!this.state.loading) {
97
- this.props.fileConfirmed();
32
+ else if (e.key === ' ') {
33
+ e.preventDefault();
34
+ fileSelected(metadata);
98
35
  }
99
- },
100
- render() {
101
- const list = [];
102
- const isSubFolder = (this.props.folder != null);
103
- if (!this.state.loading) {
104
- if (isSubFolder) {
105
- list.push((div({ key: 'parent', className: 'selectable', onClick: this.parentSelected }, (italic({ className: 'icon-paletteArrow-collapse' })), this.props.folder.name)));
106
- }
107
- for (let i = 0; i < this.props.list.length; i++) {
108
- const metadata = this.props.list[i];
109
- list.push((FileListFile({ key: i, metadata, selected: this.props.selectedFile === metadata, fileSelected: this.fileSelected, fileConfirmed: this.fileConfirmed, isSubFolder })));
110
- }
111
- }
112
- return (div({ className: 'filelist' }, this.state.loading
113
- ? div({ key: 'loading' }, (0, translate_1.default)("~FILE_DIALOG.LOADING"))
114
- : (this.props.overrideMessage || list)));
115
- }
116
- });
117
- const FileDialogTab = (0, create_react_class_1.default)({
118
- displayName: 'FileDialogTab',
119
- getInitialState() {
120
- var _a, _b, _c;
121
- this._isMounted = true;
122
- const initialState = this.getStateForFolder((_a = this.props.client.state.metadata) === null || _a === void 0 ? void 0 : _a.parent, true) || null;
123
- initialState.filename = ((_b = initialState.metadata) === null || _b === void 0 ? void 0 : _b.name) || '';
124
- // on saves default the search to the filename - on saves the search is the final filename
125
- if (!this.isOpen()) {
126
- initialState.search = initialState.filename || (0, translate_1.default)("~MENUBAR.UNTITLED_DOCUMENT");
127
- // add the file extension on export
128
- if (this.isExport() && ((_c = this.props.dialog.data) === null || _c === void 0 ? void 0 : _c.extension)) {
129
- initialState.search = provider_interface_1.CloudMetadata.newExtension(initialState.search, this.props.dialog.data.extension);
36
+ };
37
+ const getIconClass = () => {
38
+ if (metadata.type === provider_interface_1.CloudMetadata.Folder)
39
+ return 'icon-inspectorArrow-collapse';
40
+ if (metadata.type === provider_interface_1.CloudMetadata.File)
41
+ return 'icon-noteTool';
42
+ return '';
43
+ };
44
+ const selectableClass = isSelectable ? 'selectable' : '';
45
+ const selectedClass = selected ? 'selected' : '';
46
+ const subFolderClass = isSubFolder ? 'subfolder' : '';
47
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `${selectableClass} ${selectedClass} ${subFolderClass}`, title: metadata.description || undefined, role: isSelectable ? 'option' : undefined, "aria-selected": isSelectable ? selected : undefined, tabIndex: isSelectable ? 0 : undefined, onClick: isSelectable ? handleFileSelected : undefined, onKeyDown: isSelectable ? handleKeyDown : undefined, children: [(0, jsx_runtime_1.jsx)("i", { className: getIconClass() }), metadata.name] }));
48
+ };
49
+ const FileList = ({ provider, folder, selectedFile, list, listLoaded, fileSelected, fileConfirmed, client, overrideMessage, listOptions }) => {
50
+ const [loading, setLoading] = (0, react_1.useState)(true);
51
+ const isMountedRef = (0, react_1.useRef)(true);
52
+ const prevFolderRef = (0, react_1.useRef)(folder);
53
+ const load = (targetFolder) => {
54
+ setLoading(true);
55
+ provider.list(targetFolder, (err, loadedList) => {
56
+ // asynchronous callback may be called after dialog has been dismissed
57
+ if (isMountedRef.current) {
58
+ setLoading(false);
130
59
  }
131
- }
132
- // NP 2020-04-23 Copied from authorize-mixin.js
133
- this._isAuthorized = false;
134
- initialState.authorized = false;
135
- return initialState;
136
- },
137
- // The constraints here are somewhat subtle. We want to try to
138
- // determine whether the user is authorized before the first render,
139
- // because authorization status can affect rendering. Thus, we want
140
- // to perform the check in componentWillMount(). Some providers
141
- // can/will respond immediately, either because they don't require
142
- // authorization or because they are already authorized. Unfortunately,
143
- // setState() can't be called in componentWillMount(), so if we get
144
- // an immediate response, we need to store it in an instance variable.
145
- // Then in componentDidMount(), we can propagate the instance variable
146
- // to the state via a call to setState(). Some providers will need to
147
- // make an asynchronous call to determine authorization status. This
148
- // call may complete before or after the first render, i.e. before or
149
- // after the componentDidMount() method. Once the component is mounted,
150
- // the call to setState() is required to set the state and trigger a
151
- // re-render. In the end we need to maintain both the instance variable
152
- // and the state to track the authorization status, render the appropriate
153
- // authorization status, and re-render when authorization status changes.
154
- UNSAFE_componentWillMount() {
155
- var _a, _b;
156
- const setAuthorization = (authorized) => {
157
- // always set the instance variable
158
- this._isAuthorized = authorized;
159
- // set the state if we can
160
- if (this._isMounted) {
161
- return this.setState({ authorized });
60
+ if (err) {
61
+ client.alert(err);
62
+ return;
162
63
  }
64
+ listLoaded(loadedList ?? []);
65
+ }, listOptions);
66
+ };
67
+ (0, react_1.useEffect)(() => {
68
+ isMountedRef.current = true;
69
+ load(folder);
70
+ return () => {
71
+ isMountedRef.current = false;
163
72
  };
164
- // listen for logouts (Google Drive provider)
165
- (_b = (_a = this.props.provider).onAuthorizationChange) === null || _b === void 0 ? void 0 : _b.call(_a, (authorized) => {
166
- // reset rendering when de-authorized
167
- if (this._isAuthorized && !authorized) {
168
- this.setState(this.getInitialState());
169
- }
170
- setAuthorization(authorized);
171
- });
172
- // Check for authorization before the first render. Providers that
173
- // don't require authorization or are already authorized will respond
174
- // immediately, but since the component isn't mounted yet we can't
175
- // call setState, so we set an instance variable and update state
176
- // in componentDidMount(). Providers that require asynchronous checks
177
- // for authorization may return before or after the first render, so
178
- // code should be prepared for either eventuality.
179
- return this.props.provider.authorized(setAuthorization);
180
- },
181
- // NP 2020-04-23 Copied from authorize-mixin.js
182
- componentDidMount() {
183
- this._isMounted = true;
184
- // synchronize state if necessary
185
- if (this.state.authorized !== this._isAuthorized) {
186
- return this.setState({ authorized: this._isAuthorized });
73
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
74
+ (0, react_1.useEffect)(() => {
75
+ if (folder !== prevFolderRef.current) {
76
+ load(folder);
77
+ prevFolderRef.current = folder;
187
78
  }
188
- },
189
- // NP 2020-04-23 Copied from authorize-mixin.js
190
- componentWillUnmount() {
191
- var _a, _b;
192
- (_b = (_a = this.props.provider).onAuthorizationChange) === null || _b === void 0 ? void 0 : _b.call(_a, null);
193
- return this._isMounted = false;
194
- },
195
- // NP 2020-04-23 Copied from authorize-mixin.js
196
- render() {
197
- if (!this.props.provider.isAuthorizationRequired() || this.props.provider.authorized()) {
198
- // the google drive provider renders its own dialog tab views that need to load after authorization
199
- if (this.props.provider.renderFileDialogTabView) {
200
- return this.props.provider.renderFileDialogTabView({ ...this.props, onConfirm: this.confirmed, onCancel: this.cancel });
201
- }
202
- return this.renderWhenAuthorized();
79
+ }, [folder]); // eslint-disable-line react-hooks/exhaustive-deps
80
+ const handleParentSelected = () => {
81
+ fileSelected(folder?.parent ?? null);
82
+ };
83
+ const handleFileSelected = (metadata) => {
84
+ if (!loading) {
85
+ fileSelected(metadata);
203
86
  }
204
- else {
205
- return this.props.provider.renderAuthorizationDialog();
87
+ };
88
+ const handleFileConfirmed = () => {
89
+ if (!loading) {
90
+ fileConfirmed();
206
91
  }
207
- },
208
- isOpen() {
209
- return this.props.dialog.action === 'openFile';
210
- },
211
- isExport() {
212
- return this.props.dialog.action === 'saveSecondaryFileAs';
213
- },
214
- searchChanged(e) {
215
- const search = e.target.value;
216
- return this.setState({
217
- search,
218
- filename: '',
219
- metadata: null
220
- });
221
- },
222
- listLoaded(list) {
223
- // asynchronous callback may be called after dialog has been dismissed
224
- if (this._isMounted) {
225
- return this.setState({ list });
92
+ };
93
+ const isSubFolder = folder != null;
94
+ let listContent = [];
95
+ if (!loading) {
96
+ if (isSubFolder && folder) {
97
+ listContent.push((0, jsx_runtime_1.jsxs)("div", { className: "selectable", role: "option", "aria-selected": false, tabIndex: 0, onClick: handleParentSelected, onKeyDown: (e) => {
98
+ if (e.key === 'Enter' || e.key === ' ') {
99
+ e.preventDefault();
100
+ handleParentSelected();
101
+ }
102
+ }, children: [(0, jsx_runtime_1.jsx)("i", { className: "icon-paletteArrow-collapse" }), folder.name] }, "parent"));
226
103
  }
227
- },
228
- getSaveMetadata() {
229
- // The save metadata for a file that may have been opened from another
230
- // provider must be cloned, but without cloning the provider field.
231
- // Furthermore, if the provider has changed, the provider and providerData
232
- // fields should be cleared.
233
- const saveMetadata = this.props.client.state.metadata ? lodash_1.default.clone(this.props.client.state.metadata) : null;
104
+ const fileItems = list.map((metadata, i) => ((0, jsx_runtime_1.jsx)(FileListFile, { metadata: metadata, selected: selectedFile === metadata, fileSelected: handleFileSelected, fileConfirmed: handleFileConfirmed, isSubFolder: isSubFolder }, i)));
105
+ listContent = listContent.concat(fileItems);
106
+ }
107
+ return ((0, jsx_runtime_1.jsx)("div", { className: "filelist", role: "listbox", "aria-label": (0, translate_1.default)("~FILE_DIALOG.FILENAME"), children: loading ? ((0, jsx_runtime_1.jsx)("div", { children: (0, translate_1.default)("~FILE_DIALOG.LOADING") }, "loading")) : (overrideMessage || listContent) }));
108
+ };
109
+ const FileDialogTab = ({ dialog, close, client, provider }) => {
110
+ const isMountedRef = (0, react_1.useRef)(true);
111
+ const isAuthorizedRef = (0, react_1.useRef)(false);
112
+ const inputRef = (0, react_1.useRef)(null);
113
+ const isOpen = () => dialog.action === 'openFile';
114
+ const isExport = () => dialog.action === 'saveSecondaryFileAs';
115
+ const getSaveMetadata = () => {
116
+ const saveMetadata = client.state.metadata ? lodash_1.default.clone(client.state.metadata) : null;
234
117
  if (saveMetadata) {
235
- if (this.props.provider === saveMetadata.provider) {
118
+ if (provider === saveMetadata.provider) {
236
119
  saveMetadata.providerData = lodash_1.default.cloneDeep(saveMetadata.providerData);
237
120
  }
238
121
  else {
@@ -242,17 +125,54 @@ const FileDialogTab = (0, create_react_class_1.default)({
242
125
  }
243
126
  }
244
127
  return saveMetadata;
245
- },
246
- getStateForFolder(folder, initialFolder) {
247
- var _a;
248
- const metadata = this.isOpen() ? ((_a = this.state) === null || _a === void 0 ? void 0 : _a.metadata) || null : this.getSaveMetadata();
249
- if (initialFolder) {
250
- folder = null;
128
+ };
129
+ const getInitialState = () => {
130
+ const metadata = isOpen() ? null : getSaveMetadata();
131
+ const filename = metadata?.name || '';
132
+ let search = '';
133
+ if (!isOpen()) {
134
+ search = filename || (0, translate_1.default)("~MENUBAR.UNTITLED_DOCUMENT");
135
+ if (isExport() && dialog.data?.extension) {
136
+ search = provider_interface_1.CloudMetadata.newExtension(search, dialog.data.extension);
137
+ }
251
138
  }
252
- else {
253
- if (metadata != null) {
254
- metadata.parent = folder;
139
+ return {
140
+ folder: null, // Start with null folder for initial load
141
+ metadata,
142
+ filename,
143
+ list: [],
144
+ search,
145
+ authorized: false
146
+ };
147
+ };
148
+ const [state, setState] = (0, react_1.useState)(getInitialState);
149
+ (0, react_1.useEffect)(() => {
150
+ isMountedRef.current = true;
151
+ const setAuthorization = (authorized) => {
152
+ isAuthorizedRef.current = authorized;
153
+ if (isMountedRef.current) {
154
+ setState(prev => ({ ...prev, authorized }));
255
155
  }
156
+ };
157
+ // listen for logouts (Google Drive provider)
158
+ // Note: onAuthorizationChange is only available on some providers
159
+ const providerAny = provider;
160
+ providerAny.onAuthorizationChange?.((authorized) => {
161
+ if (isAuthorizedRef.current && !authorized) {
162
+ setState(getInitialState());
163
+ }
164
+ setAuthorization(authorized);
165
+ });
166
+ provider.authorized(setAuthorization);
167
+ return () => {
168
+ providerAny.onAuthorizationChange?.(null);
169
+ isMountedRef.current = false;
170
+ };
171
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
172
+ const getStateForFolder = (folder) => {
173
+ const metadata = isOpen() ? state.metadata : getSaveMetadata();
174
+ if (metadata != null) {
175
+ metadata.parent = folder ?? undefined;
256
176
  }
257
177
  const newState = {
258
178
  folder,
@@ -260,146 +180,166 @@ const FileDialogTab = (0, create_react_class_1.default)({
260
180
  filename: "",
261
181
  list: []
262
182
  };
263
- if (this.isOpen()) {
183
+ if (isOpen()) {
264
184
  newState.search = "";
265
185
  }
266
186
  return newState;
267
- },
268
- fileSelected(metadata) {
269
- if ((metadata === null || metadata === void 0 ? void 0 : metadata.type) === provider_interface_1.CloudMetadata.Folder) {
270
- return this.setState(this.getStateForFolder(metadata));
187
+ };
188
+ const searchChanged = (e) => {
189
+ const search = e.target.value;
190
+ setState(prev => ({
191
+ ...prev,
192
+ search,
193
+ filename: '',
194
+ metadata: null
195
+ }));
196
+ };
197
+ const listLoaded = (list) => {
198
+ if (isMountedRef.current) {
199
+ setState(prev => ({ ...prev, list }));
200
+ }
201
+ };
202
+ const fileSelected = (metadata) => {
203
+ if (metadata?.type === provider_interface_1.CloudMetadata.Folder) {
204
+ setState(prev => ({ ...prev, ...getStateForFolder(metadata) }));
271
205
  }
272
- else if ((metadata === null || metadata === void 0 ? void 0 : metadata.type) === provider_interface_1.CloudMetadata.File) {
206
+ else if (metadata?.type === provider_interface_1.CloudMetadata.File) {
273
207
  const newState = { filename: metadata.name, metadata };
274
- if (!this.isOpen()) {
275
- newState.search = newState.filename;
208
+ if (!isOpen()) {
209
+ newState.search = metadata.name;
276
210
  }
277
- return this.setState(newState);
211
+ setState(prev => ({ ...prev, ...newState }));
278
212
  }
279
213
  else {
280
- return this.setState(this.getStateForFolder(null));
214
+ setState(prev => ({ ...prev, ...getStateForFolder(null) }));
281
215
  }
282
- },
283
- confirmed(_metadata) {
284
- const metadata = _metadata;
216
+ };
217
+ const confirmed = (metadata) => {
285
218
  // ensure the metadata provider is the currently-showing tab
286
- if (metadata.provider !== this.props.provider) {
287
- metadata.provider = this.props.provider;
288
- // if switching provider, then clear providerData
219
+ if (metadata.provider !== provider) {
220
+ metadata.provider = provider;
289
221
  metadata.providerData = {};
290
222
  }
291
- if (typeof this.props.dialog.callback === 'function') {
292
- this.props.dialog.callback(metadata);
223
+ dialog.callback?.(metadata);
224
+ setState(prev => ({ ...prev, metadata }));
225
+ close();
226
+ };
227
+ const findMetadata = (filename, list, extension) => {
228
+ const checkExtension = extension !== undefined;
229
+ const filenameWithExtension = checkExtension && provider_interface_1.CloudMetadata.newExtension(filename, extension);
230
+ for (const metadata of list) {
231
+ const found = checkExtension
232
+ ? metadata.filename === filenameWithExtension
233
+ : metadata.name === filename;
234
+ if (found) {
235
+ return metadata;
236
+ }
293
237
  }
294
- this.setState({ metadata: metadata });
295
- return this.props.close();
296
- },
297
- confirm() {
298
- var _a;
299
- const filename = jquery_1.default.trim(this.finalConfirmedFilename());
300
- const existingMetadata = this.findMetadata(filename, this.state.list, (_a = this.props.dialog.data) === null || _a === void 0 ? void 0 : _a.extension);
301
- const metadata = this.state.metadata || existingMetadata;
238
+ return null;
239
+ };
240
+ const finalConfirmedFilename = () => {
241
+ return isOpen() ? state.filename : (state.filename || state.search || "");
242
+ };
243
+ const confirmDisabled = () => {
244
+ return provider.fileDialogDisabled(state.folder) || (finalConfirmedFilename().length === 0) || (isOpen() && !state.metadata);
245
+ };
246
+ const confirm = () => {
247
+ const filename = jquery_1.default.trim(finalConfirmedFilename());
248
+ const existingMetadata = findMetadata(filename, state.list, dialog.data?.extension);
249
+ let metadata = state.metadata || existingMetadata;
302
250
  // a bit of a hack - on export clear the provider data if there is no matching file found so we don't
303
251
  // accidentally override the original saved file
304
- if (this.isExport() && metadata && !existingMetadata) {
252
+ if (isExport() && metadata && !existingMetadata) {
305
253
  metadata.providerData = {};
306
254
  }
307
255
  if (metadata) {
308
- if (this.isOpen()) {
309
- return this.confirmed(metadata);
256
+ if (isOpen()) {
257
+ confirmed(metadata);
310
258
  }
311
259
  else if (existingMetadata) {
312
- return this.props.client.confirm(`Are you sure you want to overwrite ${existingMetadata.name}?`, () => this.confirmed(existingMetadata));
260
+ client.confirm((0, translate_1.default)("~FILE_DIALOG.OVERWRITE_CONFIRM", { filename: existingMetadata.name }), () => confirmed(existingMetadata));
313
261
  }
314
262
  else {
315
- return this.confirmed(metadata);
263
+ confirmed(metadata);
316
264
  }
317
265
  }
318
- else if (this.isOpen()) {
319
- return this.props.client.alert(`${filename} not found`);
266
+ else if (isOpen()) {
267
+ client.alert((0, translate_1.default)("~FILE_DIALOG.FILE_NOT_FOUND", { filename }));
320
268
  }
321
269
  else {
322
- return this.confirmed(new provider_interface_1.CloudMetadata({
270
+ confirmed(new provider_interface_1.CloudMetadata({
323
271
  name: filename,
324
272
  type: provider_interface_1.CloudMetadata.File,
325
- parent: this.state.folder || null,
326
- provider: this.props.provider
273
+ parent: state.folder ?? undefined,
274
+ provider
327
275
  }));
328
276
  }
329
- },
330
- remove() {
331
- if (this.state.metadata && (this.state.metadata.type !== provider_interface_1.CloudMetadata.Folder)) {
332
- return this.props.client.confirm((0, translate_1.default)("~FILE_DIALOG.REMOVE_CONFIRM", { filename: this.state.metadata.name }), () => {
333
- return this.props.provider.remove(this.state.metadata, (err) => {
277
+ };
278
+ const remove = () => {
279
+ if (state.metadata && state.metadata.type !== provider_interface_1.CloudMetadata.Folder) {
280
+ const filename = state.metadata.name ?? '';
281
+ client.confirm((0, translate_1.default)("~FILE_DIALOG.REMOVE_CONFIRM", { filename }), () => {
282
+ provider.remove(state.metadata, (err) => {
334
283
  if (!err) {
335
- this.props.client.alert((0, translate_1.default)("~FILE_DIALOG.REMOVED_MESSAGE", { filename: this.state.metadata.name }), (0, translate_1.default)("~FILE_DIALOG.REMOVED_TITLE"));
336
- const list = this.state.list.slice(0);
337
- const index = list.indexOf(this.state.metadata);
284
+ client.alert((0, translate_1.default)("~FILE_DIALOG.REMOVED_MESSAGE", { filename }), (0, translate_1.default)("~FILE_DIALOG.REMOVED_TITLE"));
285
+ const list = state.list.slice(0);
286
+ const index = list.indexOf(state.metadata);
338
287
  list.splice(index, 1);
339
- return this.setState({
288
+ setState(prev => ({
289
+ ...prev,
340
290
  list,
341
291
  metadata: null,
342
292
  filename: '',
343
293
  search: ''
344
- });
294
+ }));
345
295
  }
346
296
  });
347
297
  });
348
298
  }
349
- },
350
- cancel() {
351
- return this.props.close();
352
- },
353
- findMetadata(filename, list, extension) {
354
- const checkExtension = extension !== undefined;
355
- const filenameWithExtension = checkExtension && provider_interface_1.CloudMetadata.newExtension(filename, extension);
356
- for (let metadata of Array.from(list)) {
357
- const found = checkExtension
358
- ? metadata.filename === filenameWithExtension
359
- : metadata.name === filename;
360
- if (found) {
361
- return metadata;
362
- }
363
- }
364
- return null;
365
- },
366
- watchForEnter(e) {
367
- if ((e.keyCode === 13) && !this.confirmDisabled()) {
368
- return this.confirm();
299
+ };
300
+ const cancel = () => {
301
+ close();
302
+ };
303
+ const watchForEnter = (e) => {
304
+ if (e.key === 'Enter' && !confirmDisabled()) {
305
+ confirm();
369
306
  }
370
- },
371
- finalConfirmedFilename() {
372
- // use filename for open and filename or search for saves
373
- return this.isOpen() ? this.state.filename : (this.state.filename || this.state.search || "");
374
- },
375
- confirmDisabled() {
376
- return this.props.provider.fileDialogDisabled(this.state.folder) || (this.finalConfirmedFilename().length === 0) || (this.isOpen() && !this.state.metadata);
377
- },
378
- clearListFilter() {
379
- var _a;
380
- this.setState({ search: "" });
381
- (_a = this.inputRef) === null || _a === void 0 ? void 0 : _a.focus();
382
- },
383
- renderWhenAuthorized() {
384
- var _a;
385
- const confirmDisabled = this.confirmDisabled();
386
- const removeDisabled = (this.state.metadata === null) || (this.state.metadata.type === provider_interface_1.CloudMetadata.Folder);
387
- const isOpen = this.isOpen();
388
- const search = this.state.search || "";
307
+ };
308
+ const clearListFilter = () => {
309
+ setState(prev => ({ ...prev, search: "" }));
310
+ inputRef.current?.focus();
311
+ };
312
+ const renderWhenAuthorized = () => {
313
+ const disabled = confirmDisabled();
314
+ const removeDisabled = state.metadata === null || state.metadata.type === provider_interface_1.CloudMetadata.Folder;
315
+ const isOpenAction = isOpen();
316
+ const search = state.search || "";
389
317
  const lowerSearch = search.toLowerCase();
390
- const filtering = isOpen && search.length > 0;
318
+ const filtering = isOpenAction && search.length > 0;
391
319
  const list = filtering
392
- ? this.state.list.filter((item) => item.name.toLowerCase().indexOf(lowerSearch) !== -1)
393
- : this.state.list;
394
- const listFiltered = list.length !== this.state.list.length;
320
+ ? state.list.filter((item) => item.name?.toLowerCase().indexOf(lowerSearch) !== -1)
321
+ : state.list;
322
+ const listFiltered = list.length !== state.list.length;
395
323
  const overrideMessage = filtering && listFiltered && list.length === 0
396
- ? div({}, `No files found matching "${search}"`)
324
+ ? (0, jsx_runtime_1.jsxs)("div", { children: ["No files found matching \u201C", search, "\u201D"] })
397
325
  : null;
398
326
  // when exporting only show folders as we can't filter based on mimetypes like text/csv or image/png to show only those files
399
- const listOptions = this.isExport() && ((_a = this.props.dialog.data) === null || _a === void 0 ? void 0 : _a.extension) ? { extension: this.props.dialog.data.extension } : undefined;
400
- return (div({ className: 'dialogTab' }, (input({ type: 'text', value: search, placeholder: ((0, translate_1.default)(isOpen ? "~FILE_DIALOG.FILTER" : "~FILE_DIALOG.FILENAME")), autoFocus: true, onChange: this.searchChanged, onKeyDown: this.watchForEnter, ref: (elt) => { return this.inputRef = elt; } })), (listFiltered && div({ className: 'dialogClearFilter', onClick: this.clearListFilter }, "X")), (FileList({ provider: this.props.provider, folder: this.state.folder, selectedFile: this.state.metadata, fileSelected: this.fileSelected, fileConfirmed: this.confirm, list, listLoaded: this.listLoaded, client: this.props.client, overrideMessage, listOptions })), (div({ className: 'buttons' }, (button({ onClick: this.confirm, disabled: confirmDisabled, className: confirmDisabled ? 'disabled' : '' }, this.isOpen() ? ((0, translate_1.default)("~FILE_DIALOG.OPEN")) : ((0, translate_1.default)("~FILE_DIALOG.SAVE")))), this.props.provider.can('remove') ?
401
- (button({ onClick: this.remove, disabled: removeDisabled, className: removeDisabled ? 'disabled' : '' }, ((0, translate_1.default)("~FILE_DIALOG.REMOVE")))) : undefined, (button({ onClick: this.cancel }, ((0, translate_1.default)("~FILE_DIALOG.CANCEL"))))))));
327
+ const listOptions = isExport() && dialog.data?.extension ? { extension: dialog.data.extension } : undefined;
328
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "dialogTab", children: [(0, jsx_runtime_1.jsx)("input", { type: "text", value: search, "aria-label": (0, translate_1.default)(isOpenAction ? "~FILE_DIALOG.FILTER" : "~FILE_DIALOG.FILENAME"), placeholder: (0, translate_1.default)(isOpenAction ? "~FILE_DIALOG.FILTER" : "~FILE_DIALOG.FILENAME"), autoFocus: true, onChange: searchChanged, onKeyDown: watchForEnter, ref: inputRef }), listFiltered && ((0, jsx_runtime_1.jsx)("button", { className: "dialogClearFilter", title: (0, translate_1.default)("~FILE_DIALOG.CLEAR_FILTER"), "aria-label": (0, translate_1.default)("~FILE_DIALOG.CLEAR_FILTER"), onClick: clearListFilter, children: "\u00D7" })), (0, jsx_runtime_1.jsx)(FileList, { provider: provider, folder: state.folder, selectedFile: state.metadata, fileSelected: fileSelected, fileConfirmed: confirm, list: list, listLoaded: listLoaded, client: client, overrideMessage: overrideMessage, listOptions: listOptions }), (0, jsx_runtime_1.jsxs)("div", { className: "buttons", children: [(0, jsx_runtime_1.jsx)("button", { onClick: confirm, disabled: disabled, className: disabled ? 'disabled' : 'default', children: isOpenAction ? (0, translate_1.default)("~FILE_DIALOG.OPEN") : (0, translate_1.default)("~FILE_DIALOG.SAVE") }), provider.can(provider_interface_1.ECapabilities.remove) && ((0, jsx_runtime_1.jsx)("button", { onClick: remove, disabled: removeDisabled, className: removeDisabled ? 'disabled' : '', children: (0, translate_1.default)("~FILE_DIALOG.REMOVE") })), (0, jsx_runtime_1.jsx)("button", { onClick: cancel, children: (0, translate_1.default)("~FILE_DIALOG.CANCEL") })] })] }));
329
+ };
330
+ // Main render
331
+ // Note: authorized() is typed as void but actually returns a boolean when called without a callback
332
+ const providerAny = provider;
333
+ if (!provider.isAuthorizationRequired() || providerAny.authorized()) {
334
+ // the google drive provider renders its own dialog tab views that need to load after authorization
335
+ if (providerAny.renderFileDialogTabView) {
336
+ return providerAny.renderFileDialogTabView({ ...{ dialog, close, client, provider }, onConfirm: confirmed, onCancel: cancel });
337
+ }
338
+ return renderWhenAuthorized();
402
339
  }
403
- });
340
+ else {
341
+ return provider.renderAuthorizationDialog();
342
+ }
343
+ };
404
344
  exports.default = FileDialogTab;
405
345
  //# sourceMappingURL=file-dialog-tab-view.js.map