-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Create a plugin component to override file previews #2519
Conversation
Thanks @hanzei but I'll defer review to @levb in this case since he's given more thoughts on the direction of this issue. (updated) |
My idea was to split the reviews among teams. But 1/5. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the surface, looks good to me other than a couple naming suggestions.
I lack React expertise to assert the correctness, will leave it to @crspeller
@levb @crspeller There is another change in this PR. I have exposed PDFJS to the window so that we can use it from plugins as Webpack externals. https://github.com/mattermost/mattermost-webapp/pull/2519/files#diff-b6fe17723dee9e7445e3645b93f535caR15 Also, I think this is good for re-review. |
Given Lev is out, have requested Joram's help with review. |
@@ -262,6 +269,18 @@ export default class ViewImageModal extends React.PureComponent { | |||
); | |||
} | |||
|
|||
for (const preview of this.props.pluginFilePreviewComponents) { | |||
if (preview.override(fileInfo, this.props.post)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if I have multiple plugins trying to override file previews and two of the plugins want to override the same preview? The only other case we have overrides like this is for post components based on the post's type which we provide the best practice of only overriding types specific to your plugin to prevent your plugin negatively affecting other plugins. Is there a best practice we can offer here to avoid two different plugins colliding here (e.g one getting clobbered by the other)? If not, we should try to come up with a way to do this that will allow multiple plugins using this feature to work well together
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
So, the idea here is that preview component of the first plugin that can override a preview for the given
fileInfo
andpost
objects will be used. -
This is in a sense similar to the custom post type component, where if multiple plugins try to register the same post-type, the first plugin component in sorted order of plugin-ids is used.
-
Although this may change depending on plugin requirements, one best practice we could suggest plugin authors is to override file previews for specific file types. An example would be that one plugin would override previews for pdf files and another for office files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure there is a lot that can be done here. I hesitate to make this more complicated than it needs to be just to allow multiple plugins to coexist. The best practice suggested that plugins limit themselves to one or a reasonably small set of related extensions seems reasonable.
The only case I worry about here is some kind of "better previews for MM" plugin clashing with "super png previews for MM" plugin. Where I want the second to override the first. The only way I see resolving that is somehow allowing the user to specify which one gets priority. A workaround could be to rename the second asuperpngpreivews
because then it gets sorted first.
Anyway I think that this might be out of scope for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that there probably isn't a great solution to this. I'm fine with it as is then but we should clearly document the dangers of overriding all file previews. A comment on the register API saying something like:
// Only one plugin can override a file preview at a time. If two plugins try to override the same file preview, the first plugin will perform the override and the second will not. Plugin precedence is ordered alphabetically by plugin ID.
@@ -18,7 +18,7 @@ const PREVIEW_IMAGE_MIN_DIMENSION = 50; | |||
|
|||
export default class SingleImageView extends React.PureComponent { | |||
static propTypes = { | |||
postId: PropTypes.string.isRequired, | |||
post: PropTypes.object.isRequired, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of updating this to receive the post object as a prop, can you instead continue passing the post ID and then just pull the correct post using a redux selector in the view_image/index.js
? It's generally better to avoid passing objects down multiple layers as props where avoidable and to pass primitives instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Updated.
@@ -262,6 +269,18 @@ export default class ViewImageModal extends React.PureComponent { | |||
); | |||
} | |||
|
|||
for (const preview of this.props.pluginFilePreviewComponents) { | |||
if (preview.override(fileInfo, this.props.post)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure there is a lot that can be done here. I hesitate to make this more complicated than it needs to be just to allow multiple plugins to coexist. The best practice suggested that plugins limit themselves to one or a reasonably small set of related extensions seems reasonable.
The only case I worry about here is some kind of "better previews for MM" plugin clashing with "super png previews for MM" plugin. Where I want the second to override the first. The only way I see resolving that is somehow allowing the user to specify which one gets priority. A workaround could be to rename the second asuperpngpreivews
because then it gets sorted first.
Anyway I think that this might be out of scope for this PR.
window.PropTypes = require('prop-types'); | ||
window.PDFJS = require('pdfjs-dist'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is only required for certain libraries because they need to be consistent with the webapp or there can only be one loaded on the window at a time. I don't think pdfjs falls into this category.
What's your reasoning for exporting this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- If
pdfjs-dist
is installed via npm and imported in a plugin component, the following warning is shown while building the plugin:
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
main.js (437 KiB)
1.main.js (698 KiB)
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
main (437 KiB)
main.js
By exposing PDFJS
using Webpack externals, we can avoid the above warning.
- I was running into several issues with using PDFJS in a plugin without the above change.
By exposing thePDFJS
object to the window, it would be easier for plugin developers to render PDFs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Yes, I guess it's a bit large, maybe worth it to export.
- What where those issues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2.> Uncaught TypeError: r(...) is not a function
would be logged to the console.
You can go to the current master branch and see this if you run npm i -S pdfjs-dist
and add import PDFJS from 'pdfjs-dist';
in any plugin.
I have tried with different versions of PDFJS. Couldn't find much help from the internet about this issue as well.
But this does get resolved by eporting PDFJS to the window from mattermost-webapp to be used in plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright I think this is fine then.
@crspeller Can you help review this PR today? This will need to make it for today's Feature Complete. |
@chetanyakan Just need to accept the documentation suggested change, then I think this PR is good to go. |
Co-Authored-By: chetanyakan <[email protected]>
@crspeller Done. |
* Create a plugin component to override file previews * Add test cases * Code refactoring * Expost pdfjs to window to use in webpack externals in plugins * - Pass postId to ViewImageModal and use getPost to fetch post object. - Update test cases * Update plugins/registry.js Co-Authored-By: chetanyakan <[email protected]>
* Create a plugin component to override file previews * Add test cases * Code refactoring * Expost pdfjs to window to use in webpack externals in plugins * - Pass postId to ViewImageModal and use getPost to fetch post object. - Update test cases * Update plugins/registry.js Co-Authored-By: chetanyakan <[email protected]>
Summary
Ticket Link
mattermost/mattermost#4300
Checklist
make check-style
to check for style errors (required for all pull requests)make test
to ensure unit and component tests passed