-
Notifications
You must be signed in to change notification settings - Fork 63
Conversation
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 opened a PR with some suggested additional simplifications to the media service alongside the ones you've already made: #1173
This also removes the redundant MediaDetail
type (it duplicates the Media
type and does so at the cost of type resolution performance as well).
src/stores/media.ts
Outdated
defineStore('media', () => { | ||
/* State */ | ||
|
||
const state: MediaState = reactive({ |
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.
Can we put the MediaState
type in this file instead of delocalizing it? Kind of the same issue we have with moving props into separate files.
src/stores/media.ts
Outdated
audio: null, | ||
image: null, |
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.
Stuffing all our media results into a single store seems like it's going to introduce some complications for types and also long term maintainability... it increases the complexity a lot. This store is responsible for managing the results for each individual media type as well as managing the results for the aggregating the results for the all view. I wonder if we can split these responsibilities, remove the state nesting, and fix some of the type errors along the way.
This is probably for a separate PR/issue, not this one!
If we changed the media store to be generic, something like this:
const createResultsStore = <T extends SupportedMediaType>(mediaType: T) => createStore(`${mediaType}-results`, () => {
const state: ResultState<DetailFromMediaType<T>> = reactive({
results: // unnested,
fetchState: // unnested,
// no need for audio or image key at the root
})
const getItemById = (id: string) => {
return state.results.items[id]
}
const resultList = computed(() => Object.values(state.results.items))
const resultCount = computed(() => state.results.count)
// etc...
})
Then useImageStore
and useAudioStore
are separate entities. A third useAllResultsStore
would aggregate the two (and any future stores) in a generic fashion.
This would remove all the [mediaType]
keying we have to do now as well as the conditionals around ALL_MEDIA
that we have to do now.
The search page itself would decide which store to use based on the search type, rather than having the media store opaquely decide which results to return.
Does this seem possible to you based on your understanding of the current stores?
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.
This looks like a great idea, @sarayourfriend ! I will have to think more about it.
I was planning to extract something like singleMediaStore
for the detail pages, and the relatedMediaStore
(converted from composable), after Pinia conversion is done.
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 opened a new issue for splitting the store based on @sarayourfriend 's comment, #1192 .
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.
Looking great!
src/models/media.ts
Outdated
thumbnail?: string | ||
audio_set?: string | ||
genres?: string[] | ||
duration?: number | ||
bit_rate?: number | ||
sample_rate?: number | ||
alt_files?: { provider: string; filetype: string }[] | ||
filetype?: string | ||
peaks?: number[] |
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 some of these are inaccurate, either they're not optional properties (but actually required and nullable instead) or they're always present but sometimes just empty (like peaks
is a required property but is sometimes an empty array).
It's not a big deal though, in particular with the nullability, it'll just make writing code using these types more annoying because we'll have to add null checks in places that we don't need them (like on the array types).
thumbnail
can be moved up to Media
too as it's on both Audio and Images.
Use filter button text as a proxy for how many filters are applied instead of checking that the 'Tall' checkbox doesn't exist (with `toHaveCount(0)`
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.
This is a huge refactor! Thanks for adding/updating tests for the additional confidence that things are running as they should.
@@ -24,7 +24,6 @@ const statuses = Object.freeze({ | |||
FETCHING: 'fetching', | |||
SUCCESS: 'success', | |||
ERROR: 'error', | |||
FINISHED: 'finished', |
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.
Can we remove the comment above describing the finished
state, if it no longer exists?
* - `finished`: for multi-page requests, this is true when no more pages are left.
src/data/media-service.ts
Outdated
* Decodes the text data to avoid encoding problems. | ||
* Also, converts the results from an array of media objects into an object with | ||
* media id as keys. |
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.
* Decodes the text data to avoid encoding problems. | |
* Also, converts the results from an array of media objects into an object with | |
* media id as keys. | |
* Decodes the text data to avoid encoding problems. | |
* Also, converts the results from an array of media | |
* objects into an object with media id as keys. |
minor, minor nit to clean up the line breaks here
src/data/media-service.ts
Outdated
} | ||
|
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.
} | |
} |
Remove whitespace for consistency with the method above it
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 am sure a lot of the complexity came much earlier in the process, but I actually found this quite easy to review! It's great to see such a significant piece of code moved over to Pinia.
Fixes
Fixes #1042 by @obulat
Fixes #1028 by @obulat
Description
This PR converts the Media store from Vuex to Pinia, and typescriptifies it.
It replaces the types that were previously set to be used from JS with TS generics. There are still a couple of places where I couldn't fix types, and added
ts-ignore
to be able to commit and push the changes.Testing Instructions
Run the app. Searching all media types, filtering and loading more and viewing the detail pages should all work.
Checklist
Update index.md
).main
) or a parent feature branch.Developer Certificate of Origin
Developer Certificate of Origin