Skip to content

Commit

Permalink
Add standalone CategoryFilterModal
Browse files Browse the repository at this point in the history
Continue making Manager page less of a god-class component.

This also partially fixes the problem where "allow NSFW" checkbox
didn't react correctly to dark/light theme. The value is now read from
correct place, so the checkbox is themed based on the theme that was
active when user entered Manager page. However, if user changes the
theme while on manager page, the checkbox theme is not updated yet. I
wasn't sure how this should be solved, and it falls outside the scope
of the ticket, so I just marked the issue with TODO comment.

Refs TS-1309
  • Loading branch information
anttimaki authored and MythicManiac committed Nov 25, 2022
1 parent fcfc571 commit eb22e8c
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 89 deletions.
155 changes: 155 additions & 0 deletions src/components/modals/CategoryFilterModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<template>
<modal v-show="isOpen" :open="isOpen" :show-close="false">
<template v-slot:title>
<p class="card-header-title">Filter mod categories</p>
</template>
<template v-slot:body>
<div class="input-group">
<label>Categories</label>
<select class="select select--content-spacing" @change="selectCategory($event)">
<option selected disabled>
Select a category
</option>
<option v-for="(key, index) in unselectedCategories" :key="`category--${key}-${index}`">
{{ key }}
</option>
</select>
</div>
<br/>
<div class="input-group">
<label>Selected categories:</label>
<div class="field has-addons" v-if="selectedCategories.length > 0">
<div class="control" v-for="(key, index) in selectedCategories" :key="`${key}-${index}`">
<span class="block margin-right">
<a href="#" @click="unselectCategory(key)">
<span class="tags has-addons">
<span class="tag">{{ key }}</span>
<span class="tag is-danger">
<i class="fas fa-times"></i>
</span>
</span>
</a>
</span>
</div>
</div>
<div class="field has-addons" v-else>
<span class="tags">
<span class="tag">No categories selected</span>
</span>
</div>
</div>
<hr/>
<div>
<input
v-model="allowNsfw"
id="nsfwCheckbox"
class="is-checkradio has-background-color"
type="checkbox"
:class="[{'is-dark': !isDarkTheme, 'is-white': isDarkTheme}]"
>
<label for="nsfwCheckbox">Allow NSFW (potentially explicit) mods</label>
</div>
<br/>
<div>
<div v-for="(key, index) in categoryFilterValues" :key="`cat-filter-${key}-${index}`">
<input
name="categoryFilterCondition"
type="radio"
:id="`cat-filter-${key}-${index}`"
:value=key
:checked="index === 0 ? true : undefined" v-model="categoryFilterMode"
/>
<label :for="`cat-filter-${key}-${index}`">
<span class="margin-right margin-right--half-width" />
{{ key }}
</label>
</div>
</div>
</template>
<template v-slot:footer>
<button class="button is-info" @click="close">
Apply filters
</button>
</template>
</modal>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { Modal } from '../../components/all';
import CategoryFilterMode from "../../model/enums/CategoryFilterMode";
import GameManager from "../../model/game/GameManager";
import ManagerSettings from "../../r2mm/manager/ManagerSettings";
@Component({
components: { Modal }
})
export default class CategoryFilterModal extends Vue {
activeGame = GameManager.activeGame;
settings: ManagerSettings = new ManagerSettings();
@Prop({default: () => null})
private onClose!: () => Promise<void>;
get allowNsfw(): boolean {
return this.$store.state.modFilters.allowNsfw;
}
set allowNsfw(value: boolean) {
this.$store.commit("modFilters/setAllowNsfw", value);
}
get categoryFilterMode(): CategoryFilterMode {
return this.$store.state.modFilters.categoryFilterMode;
}
set categoryFilterMode(value: CategoryFilterMode) {
this.$store.commit("modFilters/setCategoryFilterMode", value);
}
get categoryFilterValues() {
return Object.values(CategoryFilterMode);
}
close() {
this.onClose();
this.$store.commit("closeCategoryFilterModal");
}
async created() {
this.settings = await ManagerSettings.getSingleton(this.activeGame);
}
// TODO: The value doesn't get updated if the theme is toggled while
// the modal in mounted.
get isDarkTheme(): boolean {
return this.settings.getContext().global.darkTheme;
}
get isOpen(): boolean {
return this.$store.state.modals.isCategoryFilterModalOpen;
}
selectCategory(event: Event) {
if (!(event.target instanceof HTMLSelectElement)) {
return;
}
this.$store.commit("modFilters/selectCategory", event.target.value);
event.target.selectedIndex = 0;
}
get selectedCategories(): string[] {
return this.$store.state.modFilters.selectedCategories;
}
unselectCategory(category: string) {
this.$store.commit("modFilters/unselectCategory", category);
}
get unselectedCategories(): string[] {
return this.$store.getters["modFilters/unselectedCategories"];
}
}
</script>
93 changes: 4 additions & 89 deletions src/pages/Manager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -127,66 +127,7 @@
</template>
</modal>

<modal v-show="showCategoryFilterModal" :open="showCategoryFilterModal" :show-close="false">
<template v-slot:title>
<p class='card-header-title'>Filter mod categories</p>
</template>
<template v-slot:body>

<div class="input-group">
<label>Categories</label>
<select class="select select--content-spacing" @change="addFilterCategory($event.target)">
<option selected disabled>
Select a category
</option>
<option v-for="(key, index) in $store.getters['modFilters/unselectedCategories']" :key="`category--${key}-${index}`">
{{ key }}
</option>
</select>
</div>
<br/>
<div class="input-group">
<label>Selected categories:</label>
<div class="field has-addons" v-if="$store.state.modFilters.selectedCategories.length > 0">
<div class="control" v-for="(key, index) in $store.state.modFilters.selectedCategories" :key="`${key}-${index}`">
<span class="block margin-right">
<a href="#" @click="$store.commit('modFilters/unselectCategory', key)">
<span class="tags has-addons">
<span class="tag">{{ key }}</span>
<span class="tag is-danger">
<i class="fas fa-times"></i>
</span>
</span>
</a>
</span>
</div>
</div>
<div class="field has-addons" v-else>
<span class="tags">
<span class="tag">No categories selected</span>
</span>
</div>
</div>
<hr/>
<div>
<input class="is-checkradio has-background-color" id="nsfwCheckbox" type="checkbox" :class="[{'is-dark':!settings.darkTheme}, {'is-white':settings.darkTheme}]" v-model="allowNsfw">
<label for="nsfwCheckbox">Allow NSFW (potentially explicit) mods</label>
</div>
<br/>
<div>
<div v-for="(key, index) in categoryFilterValues" :key="`cat-filter-${key}-${index}`">
<input type="radio" :id="`cat-filter-${key}-${index}`" name="categoryFilterCondition" :value=key :checked="index === 0 ? true : undefined" v-model="categoryFilterMode">
<label :for="`cat-filter-${key}-${index}`"><span class="margin-right margin-right--half-width"/>{{ key }}</label>
</div>
</div>
</template>
<template v-slot:footer>
<button class="button is-info" @click="showCategoryFilterModal = false;">
Apply filters
</button>
</template>
</modal>

<CategoryFilterModal :onClose="sortThunderstoreModList" />
<LocalFileImportModal :visible="importingLocalMod" @close-modal="importingLocalMod = false" @error="showError($event)"/>

<DownloadModModal
Expand Down Expand Up @@ -233,7 +174,7 @@
<div class="input-group">
<div class="input-group input-group--flex">
<label for="thunderstore-category-filter">Additional filters</label>
<button id="thunderstore-category-filter" class="button" @click="showCategoryFilterModal = true;">Filter categories</button>
<button id="thunderstore-category-filter" class="button" @click="$store.commit('openCategoryFilterModal')">Filter categories</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -358,6 +299,7 @@ import GameRunnerProvider from '../providers/generic/game/GameRunnerProvider';
import LocalFileImportModal from '../components/importing/LocalFileImportModal.vue';
import { PackageLoader } from '../model/installing/PackageLoader';
import GameInstructions from '../r2mm/launching/instructions/GameInstructions';
import CategoryFilterModal from '../components/modals/CategoryFilterModal.vue';
import GameRunningModal from '../components/modals/GameRunningModal.vue';
@Component({
Expand All @@ -367,6 +309,7 @@ import GameRunningModal from '../components/modals/GameRunningModal.vue';
LocalModList: LocalModListProvider.provider,
NavigationMenu: NavigationMenuProvider.provider,
SettingsView,
CategoryFilterModal,
DownloadModModal,
GameRunningModal,
'hero': Hero,
Expand Down Expand Up @@ -412,8 +355,6 @@ import GameRunningModal from '../components/modals/GameRunningModal.vue';
showUpdateAllModal: boolean = false;
showDependencyStrings: boolean = false;
showCategoryFilterModal: boolean = false;
importingLocalMod: boolean = false;
doorstopTarget: string = "";
Expand All @@ -435,22 +376,6 @@ import GameRunningModal from '../components/modals/GameRunningModal.vue';
this.filterThunderstoreModList();
}
get allowNsfw(): boolean {
return this.$store.state.modFilters.allowNsfw;
}
set allowNsfw(value: boolean) {
this.$store.commit("modFilters/setAllowNsfw", value);
}
get categoryFilterMode(): CategoryFilterMode {
return this.$store.state.modFilters.categoryFilterMode;
}
set categoryFilterMode(value: CategoryFilterMode) {
this.$store.commit("modFilters/setCategoryFilterMode", value);
}
get thunderstoreModList(): ThunderstoreMod[] {
return this.$store.state.thunderstoreModList || [];
}
Expand All @@ -475,7 +400,6 @@ import GameRunningModal from '../components/modals/GameRunningModal.vue';
}
@Watch("thunderstoreModList")
@Watch("showCategoryFilterModal")
thunderstoreModListUpdate() {
this.sortThunderstoreModList();
}
Expand Down Expand Up @@ -955,15 +879,6 @@ import GameRunningModal from '../components/modals/GameRunningModal.vue';
});
}
addFilterCategory(target: HTMLSelectElement) {
this.$store.commit("modFilters/selectCategory", target.value);
target.selectedIndex = 0;
}
get categoryFilterValues() {
return Object.values(CategoryFilterMode);
}
handleSettingsCallbacks(invokedSetting: any) {
switch(invokedSetting) {
case "BrowseDataFolder":
Expand Down
10 changes: 10 additions & 0 deletions src/store/modules/ModalsModule.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
interface State {
isCategoryFilterModalOpen: boolean;
isGameRunningModalOpen: boolean;
}

export default {
state: (): State => ({
isCategoryFilterModalOpen: false,
isGameRunningModalOpen: false,
}),

mutations: {
closeCategoryFilterModal: function(state: State): void {
state.isCategoryFilterModalOpen = false;
},

closeGameRunningModal: function(state: State): void {
state.isGameRunningModalOpen = false;
},

openCategoryFilterModal: function(state: State): void {
state.isCategoryFilterModalOpen = true;
},

openGameRunningModal: function(state: State): void {
state.isGameRunningModalOpen = true;
}
Expand Down

0 comments on commit eb22e8c

Please sign in to comment.