sidebarpreviewmanager.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /**
  2. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  3. * SPDX-License-Identifier: AGPL-3.0-or-later
  4. */
  5. (function () {
  6. var SidebarPreviewManager = function (fileList) {
  7. this._fileList = fileList;
  8. this._previewHandlers = {};
  9. OC.Plugins.attach('OCA.Files.SidebarPreviewManager', this);
  10. };
  11. SidebarPreviewManager.prototype = {
  12. addPreviewHandler: function (mime, handler) {
  13. this._previewHandlers[mime] = handler;
  14. },
  15. getMimeTypePreviewHandler: function(mime) {
  16. var mimePart = mime.split('/').shift();
  17. if (this._previewHandlers[mime]) {
  18. return this._previewHandlers[mime];
  19. } else if (this._previewHandlers[mimePart]) {
  20. return this._previewHandlers[mimePart];
  21. } else {
  22. return null;
  23. }
  24. },
  25. getPreviewHandler: function (mime) {
  26. var mimetypeHandler = this.getMimeTypePreviewHandler(mime);
  27. if (mimetypeHandler) {
  28. return mimetypeHandler;
  29. } else {
  30. return this.fallbackPreview.bind(this);
  31. }
  32. },
  33. loadPreview: function (model, $thumbnailDiv, $thumbnailContainer) {
  34. if (model.get('hasPreview') === false && this.getMimeTypePreviewHandler(model.get('mimetype')) === null) {
  35. var mimeIcon = OC.MimeType.getIconUrl(model.get('mimetype'));
  36. $thumbnailDiv.removeClass('icon-loading icon-32');
  37. $thumbnailContainer.removeClass('image'); //fall back to regular view
  38. $thumbnailDiv.css({
  39. 'background-image': 'url("' + mimeIcon + '")'
  40. });
  41. } else {
  42. var handler = this.getPreviewHandler(model.get('mimetype'));
  43. var fallback = this.fallbackPreview.bind(this, model, $thumbnailDiv, $thumbnailContainer);
  44. handler(model, $thumbnailDiv, $thumbnailContainer, fallback);
  45. }
  46. },
  47. // previews for images and mimetype icons
  48. fallbackPreview: function (model, $thumbnailDiv, $thumbnailContainer) {
  49. var isImage = model.isImage();
  50. var maxImageWidth = $thumbnailContainer.parent().width() + 50; // 50px for negative margins
  51. var maxImageHeight = maxImageWidth / (16 / 9);
  52. var isLandscape = function (img) {
  53. return img.width > (img.height * 1.2);
  54. };
  55. var isSmall = function (img) {
  56. return (img.width * 1.1) < (maxImageWidth * window.devicePixelRatio);
  57. };
  58. var getTargetHeight = function (img) {
  59. var targetHeight = img.height / window.devicePixelRatio;
  60. if (targetHeight <= maxImageHeight) {
  61. targetHeight = maxImageHeight;
  62. }
  63. return targetHeight;
  64. };
  65. var getTargetRatio = function (img) {
  66. var ratio = img.width / img.height;
  67. if (ratio > 16 / 9) {
  68. return ratio;
  69. } else {
  70. return 16 / 9;
  71. }
  72. };
  73. this._fileList.lazyLoadPreview({
  74. fileId: model.get('id'),
  75. path: model.getFullPath(),
  76. mime: model.get('mimetype'),
  77. etag: model.get('etag'),
  78. y: maxImageHeight,
  79. x: maxImageWidth,
  80. a: 1,
  81. mode: 'cover',
  82. callback: function (previewUrl, img) {
  83. $thumbnailDiv.previewImg = previewUrl;
  84. // as long as we only have the mimetype icon, we only save it in case there is no preview
  85. if (!img) {
  86. return;
  87. }
  88. $thumbnailDiv.removeClass('icon-loading icon-32');
  89. var targetHeight = getTargetHeight(img);
  90. $thumbnailContainer.addClass((isLandscape(img) && !isSmall(img)) ? 'landscape' : 'portrait');
  91. $thumbnailContainer.addClass('large');
  92. // only set background when we have an actual preview
  93. // when we don't have a preview we show the mime icon in the error handler
  94. $thumbnailDiv.css({
  95. 'background-image': 'url("' + previewUrl + '")',
  96. height: (targetHeight > maxImageHeight) ? 'auto' : targetHeight,
  97. 'max-height': isSmall(img) ? targetHeight : null
  98. });
  99. var targetRatio = getTargetRatio(img);
  100. $thumbnailDiv.find('.stretcher').css({
  101. 'padding-bottom': (100 / targetRatio) + '%'
  102. });
  103. },
  104. error: function () {
  105. $thumbnailDiv.removeClass('icon-loading icon-32');
  106. $thumbnailContainer.removeClass('image'); //fall back to regular view
  107. $thumbnailDiv.css({
  108. 'background-image': 'url("' + $thumbnailDiv.previewImg + '")'
  109. });
  110. }
  111. });
  112. }
  113. };
  114. OCA.Files.SidebarPreviewManager = SidebarPreviewManager;
  115. })();