From 284ba38cff0050f42de5d4661b03b859272af3f6 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Wed, 16 Jun 2021 10:29:06 -0500 Subject: [PATCH] Add movies to store to provide global realtime updates in the future --- .../mixins/MovieListComponentMixin.ts | 31 ++++++++++++++ services/webui/src/app/store/getters.ts | 12 +++++- services/webui/src/app/store/mutations.ts | 41 ++++++++++++++++++- services/webui/src/app/store/state.ts | 8 ++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 services/webui/src/app/components/mixins/MovieListComponentMixin.ts diff --git a/services/webui/src/app/components/mixins/MovieListComponentMixin.ts b/services/webui/src/app/components/mixins/MovieListComponentMixin.ts new file mode 100644 index 0000000..2bbf761 --- /dev/null +++ b/services/webui/src/app/components/mixins/MovieListComponentMixin.ts @@ -0,0 +1,31 @@ +import { IMovie } from "@autoplex-api/request"; +import { Mutation } from "../../store"; +import { defineComponent } from "vue"; + +export default defineComponent({ + computed: { + storedMovies(): IMovie[] { + return this.$store.getters.movies(this.movies); + } + }, + unmounted() { + if (this.movies.length > 0) { + this.$store.commit(Mutation.FreeMovies, this.movies); + } + }, + props: { + movies: { + default: [] + } + }, + watch: { + movies(newValue, oldValue) { + if (newValue.length > 0) { + this.$store.commit(Mutation.StoreMovies, newValue); + } + if (oldValue.length > 0) { + this.$store.commit(Mutation.FreeMovies, oldValue); + } + } + } +}) diff --git a/services/webui/src/app/store/getters.ts b/services/webui/src/app/store/getters.ts index c3f96c5..274fc8a 100644 --- a/services/webui/src/app/store/getters.ts +++ b/services/webui/src/app/store/getters.ts @@ -1,3 +1,4 @@ +import { IMovie } from "@autoplex-api/request"; import { GetterTree } from "vuex"; import { IState } from "./state"; @@ -6,7 +7,10 @@ export type GettersTypes = { isAuthenticated(state: IState): boolean, storedToken () : string | null, token (state: IState): string | null, - userName (state: IState): string | null + userName (state: IState): string | null, + + // Movie Store + movies(state: IState): (movies: IMovie[]) => IMovie[] } export const getters: GettersTypes & GetterTree = { @@ -50,5 +54,11 @@ export const getters: GettersTypes & GetterTree = { */ userName(state: IState) { return state.user?.name.split(" ")[0] ?? null; + }, + + // Movie Store --------------------------------------------------------------------------------- + + movies: (state: IState) => (movies: IMovie[]) => { + return movies.map(movie => state.movies[movie.tmdbId].movie); } }; diff --git a/services/webui/src/app/store/mutations.ts b/services/webui/src/app/store/mutations.ts index ed4a5cc..fc05df0 100644 --- a/services/webui/src/app/store/mutations.ts +++ b/services/webui/src/app/store/mutations.ts @@ -1,4 +1,4 @@ -import Modal from "@app/components/modals"; +import { IMovie } from "@autoplex-api/request/dist/typings"; import jwtDecode from "jwt-decode"; import { MutationTree } from "vuex"; import { IState } from "./state"; @@ -14,6 +14,8 @@ export enum Mutation { UserLoad = "USER_LOAD", UserStore = "USER_STORE", + FreeMovies = "FREE_MOVIES", + StoreMovies = "STORE_MOVIES", } /** @@ -24,6 +26,10 @@ export type MutationsTypes = { [Mutation.UserLoad] : (state: S, token: string) => boolean, [Mutation.UserStore] : (state: S, remember: boolean) => void, [Mutation.LockScroll]: (state: S, lock: boolean) => void, + + // Movie Store + [Mutation.FreeMovies]: (state: S, movies: IMovie[]) => void, + [Mutation.StoreMovies]: (state: S, movies: IMovie[]) => void } /** @@ -88,5 +94,38 @@ export const mutations: MutationsTypes & MutationTree = { } else { sessionStorage.setItem("jwt", state.user.token); } + }, + + // Movie Store --------------------------------------------------------------------------------- + + /** + * Free the cached movies from the store + */ + [Mutation.FreeMovies](state, movies: IMovie[]) { + for (let movie of movies) { + if (!(movie.tmdbId in state.movies)) { + console.warn("Attempted to free a movie not stored in the state!"); + continue; + } + state.movies[movie.tmdbId].refCount--; + if (state.movies[movie.tmdbId].refCount <= 0) { + delete state.movies[movie.tmdbId]; + } + } + }, + + /** + * Insert movie references in the store for updates + */ + [Mutation.StoreMovies](state, movies: IMovie[]) { + for (let movie of movies) { + if (!(movie.tmdbId in state.movies)) { + state.movies[movie.tmdbId] = { + refCount: 0, + movie + }; + } + state.movies[movie.tmdbId].refCount++; + } } } diff --git a/services/webui/src/app/store/state.ts b/services/webui/src/app/store/state.ts index 4a45d4c..11ea111 100644 --- a/services/webui/src/app/store/state.ts +++ b/services/webui/src/app/store/state.ts @@ -1,3 +1,4 @@ +import { IMovie } from "@autoplex-api/request"; import { IUser } from "./schema"; import type Modals from "../components/modals"; import Modal from "../components/modals"; @@ -6,6 +7,12 @@ import Modal from "../components/modals"; * The state definition */ export interface IState { + movies : { + [tmdbId: string]: { + refCount: number, + movie: IMovie + } + }, user : IUser | null, modalName : Modal | null, modalVisible: boolean @@ -15,6 +22,7 @@ export interface IState { * The state implementation */ export const state: IState = { + movies: {}, user: null, modalName: null, modalVisible: false,