You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
With the rewrite/port to Vue 3 (See #1228 for more information), it is a good time to perform some deep architectural changes, in order to improve maintainability of the code and fix some issues we encountered in the past.
As a result, I spent the past few days going over the entire project to define some pain points and figuring out some paths for improvements, in order to help people willing to help with the transition.
Adopting Domain-Driven Design
While our current organization is easy to approach for most developers used to the Vue.js ecosystem, I feel it can still be improved, mostly around how components are structured and how different parts of the app interoperate. I also feel it is important to prepare for future growth, as the final client would be a lot larger than the current codebase. This design also makes it a lot easier to test every part of the client in isolation, which has been a pain point of the current design.
To provide a better (and more modular) organization of code, the plan is adopt some form of domain-driven design. This aims to ensure that the different parts of the application are split into more maintainable and self-contained modules.
Of course, this design would be adapted a bit to how Vue.js works, in order to stay familiar for existing Jellyfin developers and new Vue client contributors.
The following layers would be implemented:
Presentation
Application
Domain
Infrastructure
Presentation layer
This layer contains all the user interface part of the application. This is where all the Vue components live, where the pages and layouts are defined.
It's only goal is to communicate with the application layer, and build the user interface from the information it gets/sends back.
Application layer
This layer contains all the Vue composables, defines routes and only knows about the domain and infrastructure layers.
Domain layer
This layer contains mainly services meant to interact with the repository layer.
It transforms data, validates it or otherwise manipulates it for the layers above.
One simple example would be a service to increment/decrement a counter, which would call the repository to perform said operations, or checking that a password has the required length and complexity before passing it down to the infrastructure layer.
Infrastructure layer
This layer contains our Vuex stores and API layer.
It exposes a repository, which talks to both the API and the store in order to perform various operations.
Modules
We currently have around 13 Vuex stores total, for example, which is a lot. We are expected to have even more as the application grows. Components and pages suffer a similar issue.
In order to deal with this, it becomes quite obvious that there needs to be some more organization in the code. While the layers proposed above help a little the architecture of the client as a whole (Ensuring various parts are well defined and we avoid some of the mistakes of the Vue 2 branch), it doesn't help us with making each part of the client more approachable and maintainable.
To solution that, I propose dividing the client into logical modules, each composed of the layers defined above, and comprised of a set of loosely related features and screens.
Some of the modules, for the current scope of the Vue client on the master branch at time of writing could be:
Authentication
Items
Playback
Settings
Home
Onboarding
Refactoring plans
Along with architectural changes, we should take the time to fix some pain points with the current design of some parts of the app.
This is a non-exhaustive list of the refactoring jobs that could take place during this migration.
Home header
Status: Done
The component is overly complex for what it needs to do. Some parts should be rewritten and others should be removed.
The welcome message is unnecessary and arbitrarily slows down the display of information. It should be removed.
The way the progress indicator/page selector and autoplay work currently is needlessly complicated and buggy. Use the build-in pagination and autoplay components.
Since we can remove the progress bar component and the welcome message, the component can be simplified a lot.
Home sections
Status: Not started
The current design of the home sections is pretty bad and very limiting.
We should simply store a list of sections, with their content and other relevant information, in an array of HomeSection objects (Which would be extended with relevant properties depending on the type of section).
The home header would be one of these sections, stored alongside all the others. It is probably safe to assume that it will always be the first section in the data we get from the server, if enabled.
The home page would then be a simple generic <component /> loop. Each kind of section will have bespoke components to render them.
Current planned home sections (some still needing server-side support, planned for Jellyfin 11) include:
Next up
Continue watching/listening
Latest in library
Latest in media type
Suggestions by actor/collection/recently played item/etc
Item pages
Status: Not started
It might be interesting to look at simplifying the item pages.
Some early ideas:
Merge all the routes into one component
We could still keep /musicalbum/:id, /movie/:id and others, but assign them to an ItemPage component, since we now have more control over routing.
This component could then use multiple <component /> and assign them a different Vue component depending on the type of item that is being viewed.
Factorize parts of the page to avoid repetition and make the main component simpler.
Some early ideas would be the info block (Poster, title, media info, buttons) and some common tabs.
Library
Status: Not started
This page needs to be essentially entirely rewritten, along with the filter buttons.
No real thought has been given yet as to how a proper design for it might look, however.
Players
Status: Not started
The <player-manager /> component should be using a simple <component /> and load the proper player dynamically when needed.
We can use Teleport in order to properly handle the various modals, if needed.
Queue button
Status: Not started
For proper responsiveness and to make it more usable, the queue button should route to a dedicated queue edition page.
It should also use virtual scrolling in order to improve the performance when rendering the queue.
Feedback and getting involved
If you are a Vue developer and want to give your opinion about this transition or the proposals in this post, or want to get involved, feedback is welcome in this post or through the #jellyfin-vue Matrix channel
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
With the rewrite/port to Vue 3 (See #1228 for more information), it is a good time to perform some deep architectural changes, in order to improve maintainability of the code and fix some issues we encountered in the past.
As a result, I spent the past few days going over the entire project to define some pain points and figuring out some paths for improvements, in order to help people willing to help with the transition.
Adopting Domain-Driven Design
While our current organization is easy to approach for most developers used to the Vue.js ecosystem, I feel it can still be improved, mostly around how components are structured and how different parts of the app interoperate. I also feel it is important to prepare for future growth, as the final client would be a lot larger than the current codebase. This design also makes it a lot easier to test every part of the client in isolation, which has been a pain point of the current design.
To provide a better (and more modular) organization of code, the plan is adopt some form of domain-driven design. This aims to ensure that the different parts of the application are split into more maintainable and self-contained modules.
Of course, this design would be adapted a bit to how Vue.js works, in order to stay familiar for existing Jellyfin developers and new Vue client contributors.
The following layers would be implemented:
Presentation layer
This layer contains all the user interface part of the application. This is where all the Vue components live, where the pages and layouts are defined.
It's only goal is to communicate with the application layer, and build the user interface from the information it gets/sends back.
Application layer
This layer contains all the Vue composables, defines routes and only knows about the domain and infrastructure layers.
Domain layer
This layer contains mainly services meant to interact with the repository layer.
It transforms data, validates it or otherwise manipulates it for the layers above.
One simple example would be a service to increment/decrement a counter, which would call the repository to perform said operations, or checking that a password has the required length and complexity before passing it down to the infrastructure layer.
Infrastructure layer
This layer contains our Vuex stores and API layer.
It exposes a repository, which talks to both the API and the store in order to perform various operations.
Modules
We currently have around 13 Vuex stores total, for example, which is a lot. We are expected to have even more as the application grows. Components and pages suffer a similar issue.
In order to deal with this, it becomes quite obvious that there needs to be some more organization in the code. While the layers proposed above help a little the architecture of the client as a whole (Ensuring various parts are well defined and we avoid some of the mistakes of the Vue 2 branch), it doesn't help us with making each part of the client more approachable and maintainable.
To solution that, I propose dividing the client into logical modules, each composed of the layers defined above, and comprised of a set of loosely related features and screens.
Some of the modules, for the current scope of the Vue client on the
master
branch at time of writing could be:Refactoring plans
Along with architectural changes, we should take the time to fix some pain points with the current design of some parts of the app.
This is a non-exhaustive list of the refactoring jobs that could take place during this migration.
Home header
Status: Done
The component is overly complex for what it needs to do. Some parts should be rewritten and others should be removed.
Home sections
Status: Not started
The current design of the home sections is pretty bad and very limiting.
We should simply store a list of sections, with their content and other relevant information, in an array of
HomeSection
objects (Which would be extended with relevant properties depending on the type of section).The home header would be one of these sections, stored alongside all the others. It is probably safe to assume that it will always be the first section in the data we get from the server, if enabled.
The home page would then be a simple generic
<component />
loop. Each kind of section will have bespoke components to render them.Current planned home sections (some still needing server-side support, planned for Jellyfin 11) include:
Item pages
Status: Not started
It might be interesting to look at simplifying the item pages.
Some early ideas:
We could still keep
/musicalbum/:id
,/movie/:id
and others, but assign them to anItemPage
component, since we now have more control over routing.This component could then use multiple
<component />
and assign them a different Vue component depending on the type of item that is being viewed.Some early ideas would be the info block (Poster, title, media info, buttons) and some common tabs.
Library
Status: Not started
This page needs to be essentially entirely rewritten, along with the filter buttons.
No real thought has been given yet as to how a proper design for it might look, however.
Players
Status: Not started
The
<player-manager />
component should be using a simple<component />
and load the proper player dynamically when needed.We can use Teleport in order to properly handle the various modals, if needed.
Queue button
Status: Not started
For proper responsiveness and to make it more usable, the queue button should route to a dedicated queue edition page.
It should also use virtual scrolling in order to improve the performance when rendering the queue.
Feedback and getting involved
If you are a Vue developer and want to give your opinion about this transition or the proposals in this post, or want to get involved, feedback is welcome in this post or through the #jellyfin-vue Matrix channel
Beta Was this translation helpful? Give feedback.
All reactions