Skip to content

Commit

Permalink
feat: enable category-based narrowing and reset to default on search …
Browse files Browse the repository at this point in the history
…clear
  • Loading branch information
shinshin86 committed Dec 27, 2024
1 parent 9acb5ab commit 4d5d7b6
Showing 1 changed file with 89 additions and 15 deletions.
104 changes: 89 additions & 15 deletions src/components/dialog/content/SettingDialogContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
/>
<Listbox
v-model="activeCategory"
:options="categories"
:options="displayedCategories"
optionLabel="translatedLabel"
scrollHeight="100%"
:disabled="inSearch"
:optionDisabled="(option) => option.disabled"
class="border-none w-full"
/>
</ScrollPanel>
Expand All @@ -21,7 +21,7 @@
<Tabs :value="tabValue" :lazy="true" class="settings-content h-full w-full">
<TabPanels class="settings-tab-panels h-full w-full pr-0">
<PanelTemplate value="Search Results">
<SettingsPanel :settingGroups="searchResults" />
<SettingsPanel :settingGroups="filteredSearchResults" />
</PanelTemplate>

<PanelTemplate
Expand Down Expand Up @@ -154,9 +154,10 @@ const categories = computed<SettingTreeNode[]>(() =>
const activeCategory = ref<SettingTreeNode | null>(null)
const searchResults = ref<ISettingGroup[]>([])
const displayedCategories = ref<SettingTreeNode[]>([])
watch(activeCategory, (newCategory, oldCategory) => {
if (newCategory === null) {
if (!inSearch.value && newCategory === null) {
activeCategory.value = oldCategory
}
})
Expand All @@ -166,6 +167,8 @@ onMounted(() => {
? categories.value.find((x) => x.key === props.defaultPanel) ??
categories.value[0]
: categories.value[0]
displayedCategories.value = categories.value
})
const sortedGroups = (category: SettingTreeNode): ISettingGroup[] => {
Expand All @@ -179,15 +182,36 @@ const sortedGroups = (category: SettingTreeNode): ISettingGroup[] => {
const searchQuery = ref<string>('')
const searchInProgress = ref<boolean>(false)
watch(searchQuery, () => (searchInProgress.value = true))
const inSearch = computed(
() => searchQuery.value.length > 0 && !searchInProgress.value
)
const clearSearchResults = () => {
searchResults.value = []
displayedCategories.value = categories.value
displayedCategories.value.forEach((cat) => {
cat.disabled = false
})
}
const restoreDefaultCategory = () => {
const fallback = props.defaultPanel
? categories.value.find((x) => x.key === props.defaultPanel)
: categories.value[0]
activeCategory.value = fallback
}
const handleSearch = (query: string) => {
if (!query) {
searchResults.value = []
clearSearchResults()
restoreDefaultCategory()
return
}
activeCategory.value = null
const queryLower = query.toLocaleLowerCase()
searchInProgress.value = true
const allSettings = flattenTree<SettingParams>(settingRoot.value)
const filteredSettings = allSettings.filter((setting) => {
const idLower = setting.id.toLowerCase()
Expand All @@ -203,27 +227,77 @@ const handleSearch = (query: string) => {
)
})
const groupedSettings: { [key: string]: SettingParams[] } = {}
const groupedSettingsByCategory: Record<string, SettingParams[]> = {}
filteredSettings.forEach((setting) => {
const groupLabel = setting.id.split('.')[1]
if (!groupedSettings[groupLabel]) {
groupedSettings[groupLabel] = []
const secondLevel = setting.category?.[1] || setting.id.split('.')[1] // e.g. "Comfy", "Appearance", ...
if (!groupedSettingsByCategory[secondLevel]) {
groupedSettingsByCategory[secondLevel] = []
}
groupedSettings[groupLabel].push(setting)
groupedSettingsByCategory[secondLevel].push(setting)
})
searchResults.value = Object.entries(groupedSettings).map(
searchResults.value = Object.entries(groupedSettingsByCategory).map(
([label, settings]) => ({
label,
settings
})
)
const matchedTopCategories = new Set<string>(
filteredSettings.map((s) => {
const topCat = s.category?.[0] || s.id.split('.')[0] || ''
return topCat.toLowerCase()
})
)
displayedCategories.value = categories.value.map((cat) => {
const splitted = cat.key.split('/')
const lastPart = splitted[splitted.length - 1] // "Comfy", "Appearance", ...
const isMatched = matchedTopCategories.has(lastPart.toLowerCase())
return {
...cat,
disabled: !isMatched
}
})
searchInProgress.value = false
}
const inSearch = computed(
() => searchQuery.value.length > 0 && !searchInProgress.value
)
watch(searchQuery, () => {
searchInProgress.value = true
})
/**
* Further filter the search results by the currently active category.
* → For example, if the user clicks on "Comfy" in the sidebar,
* show only the search results for "Comfy"
*/
const filteredSearchResults = computed<ISettingGroup[]>(() => {
if (!inSearch.value) {
return searchResults.value
}
if (!activeCategory.value) {
return searchResults.value
}
// e.g. "root/Comfy" -> "Comfy" (strip the prefix)
const splitted = activeCategory.value.key.split('/')
const lastPart = splitted[splitted.length - 1] // e.g. "Comfy"
const activeCatName = lastPart.toLowerCase()
return searchResults.value
.map((group) => {
const filtered = group.settings.filter((setting) => {
const topCat = setting.category?.[0] || setting.id.split('.')[0] || ''
return topCat.toLowerCase() === activeCatName
})
return { label: group.label, settings: filtered }
})
.filter((g) => g.settings.length > 0)
})
const tabValue = computed(() =>
inSearch.value ? 'Search Results' : activeCategory.value?.label
)
Expand Down

0 comments on commit 4d5d7b6

Please sign in to comment.