Bug fixes round 3 (#298)

* fixed bugs

* title case

* bugs; ioerror

* reset breadcrumbs

* more fixes

* more fixes

* scrolling bug

* more fixes

* more fixes

* clippy

* canonicalize fix

* fixed requested changes

* removed debouncer update
This commit is contained in:
Wyatt Verchere
2023-07-19 14:13:25 -07:00
committed by GitHub
parent 6650cc9ce4
commit 1f478ec9fc
34 changed files with 932 additions and 602 deletions

View File

@@ -1,6 +1,6 @@
<script setup>
import { ref, watch } from 'vue'
import { RouterView, RouterLink, useRouter } from 'vue-router'
import { computed, ref, watch } from 'vue'
import { RouterView, RouterLink, useRouter, useRoute } from 'vue-router'
import {
HomeIcon,
SearchIcon,
@@ -106,6 +106,8 @@ router.afterEach((to, from, failure) => {
mixpanel.track('PageView', { path: to.path, fromPath: from.path, failed: failure })
}
})
const route = useRoute()
const isOnBrowse = computed(() => route.path.startsWith('/browse'))
const loading = useLoading()
@@ -179,6 +181,7 @@ const accounts = ref(null)
'icon-only': themeStore.collapsedNavigation,
'collapsed-button': themeStore.collapsedNavigation,
'expanded-button': !themeStore.collapsedNavigation,
'router-link-active': isOnBrowse,
}"
>
<SearchIcon />
@@ -340,7 +343,7 @@ const accounts = ref(null)
display: flex;
align-items: center;
background: var(--color-raised-bg);
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
box-shadow: inset 0px -3px 0px black;
text-align: center;
padding: var(--gap-md);
height: 3.25rem;

View File

@@ -122,9 +122,9 @@
</div>
<Chips
v-model="javaSelectionType"
:items="['automatically install', 'use existing installation']"
:items="['Automatically install', 'Use existing installation']"
/>
<div v-if="javaSelectionType === 'use existing installation'" class="settings-group">
<div v-if="javaSelectionType === 'Use existing installation'" class="settings-group">
<h3>Java location</h3>
<JavaSelector v-model="settings.java_globals.JAVA_17" compact />
</div>
@@ -230,7 +230,7 @@ async function pageTurn() {
}
}
const javaSelectionType = ref('automatically install')
const javaSelectionType = ref('Automatically install')
async function autoInstallJava() {
const path = await auto_install_java(17).catch(handleError)
@@ -239,6 +239,7 @@ async function autoInstallJava() {
// weird vue bug, ignore
settings.value.java_globals.JAVA_17 = version
settings.value.java_globals.JAVA_17 = version
set(settings.value)
mixpanel.track('OnboardingAutoInstallJava')
}
@@ -258,6 +259,10 @@ onBeforeUnmount(() => {
</script>
<style scoped lang="scss">
:deep(.chips .btn) {
text-transform: none !important;
}
.modal-body {
display: flex;
flex-direction: column;

View File

@@ -1,5 +1,6 @@
<template>
<div class="breadcrumbs">
{{ breadcrumbData.resetToNames(breadcrumbs) }}
<div v-for="breadcrumb in breadcrumbs" :key="breadcrumb.name" class="breadcrumbs__item">
<router-link
v-if="breadcrumb.link"

View File

@@ -40,7 +40,7 @@
</div>
<div v-else class="status">
<span class="circle stopped" />
<span class="running-text"> No running instances </span>
<span class="running-text"> No instances running </span>
</div>
</div>
<transition name="download">

View File

@@ -14,6 +14,7 @@ defineProps({
<style scoped lang="scss">
.page-loading {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;

View File

@@ -272,6 +272,11 @@ async function onSearchChangeToTop(newPageNumber) {
searchWrapper.value.scrollTo({ top: 0, behavior: 'smooth' })
}
async function clearSearch() {
query.value = ''
await onSearchChange(1)
}
function getSearchUrl(offset, useObj) {
const queryItems = []
const obj = {}
@@ -355,6 +360,33 @@ const sortedCategories = computed(() => {
return values
})
// Sorts alphabetically, but correctly identifies 8x, 128x, 256x, etc
// identifier[0], then if it ties, identifier[1], etc
async function sortByNameOrNumber(sortable, identifiers) {
console.log(sortable)
sortable.sort((a, b) => {
for (let identifier of identifiers) {
let aNum = parseFloat(a[identifier])
let bNum = parseFloat(b[identifier])
if (isNaN(aNum) && isNaN(bNum)) {
// Both are strings, sort alphabetically
let stringComp = a[identifier].localeCompare(b[identifier])
if (stringComp != 0) return stringComp
} else if (!isNaN(aNum) && !isNaN(bNum)) {
// Both are numbers, sort numerically
let numComp = aNum - bNum
if (numComp != 0) return numComp
} else {
// One is a number and one is a string, numbers go first
let numStringComp = isNaN(aNum) ? 1 : -1
if (numStringComp != 0) return numStringComp
}
}
return 0
})
return sortable
}
async function clearFilters() {
for (const facet of [...facets.value]) {
await toggleFacet(facet, true)
@@ -426,7 +458,10 @@ watch(
)
const [categories, loaders, availableGameVersions] = await Promise.all([
get_categories().catch(handleError).then(ref),
get_categories()
.catch(handleError)
.then((s) => sortByNameOrNumber(s, ['header', 'name']))
.then(ref),
get_loaders().catch(handleError).then(ref),
get_game_versions().catch(handleError).then(ref),
refreshSearch(),
@@ -473,7 +508,7 @@ const showLoaders = computed(
</script>
<template>
<div class="search-container">
<div ref="searchWrapper" class="search-container">
<aside class="filter-panel">
<Card v-if="instanceContext" class="small-instance">
<router-link :to="`/instance/${encodeURIComponent(instanceContext.path)}`" class="instance">
@@ -525,7 +560,7 @@ const showLoaders = computed(
"
@click="clearFilters"
>
<ClearIcon /> Clear Filters
<ClearIcon /> Clear filters
</Button>
<div v-if="showLoaders" class="loaders">
<h2>Loaders</h2>
@@ -618,7 +653,7 @@ const showLoaders = computed(
</div>
</Card>
</aside>
<div ref="searchWrapper" class="search">
<div class="search">
<Promotion class="promotion" />
<Card class="project-type-container">
<NavRow :links="selectableProjectTypes" />
@@ -633,7 +668,7 @@ const showLoaders = computed(
:placeholder="`Search ${projectType}s...`"
@input="onSearchChange(1)"
/>
<Button @click="() => (searchStore.searchInput = '')">
<Button @click="() => clearSearch()">
<XIcon />
</Button>
</div>
@@ -698,6 +733,7 @@ const showLoaders = computed(
class="pagination-after"
@switch-page="onSearchChangeToTop"
/>
<br />
</div>
</div>
<InstallConfirmModal ref="confirmModal" />
@@ -818,6 +854,9 @@ const showLoaders = computed(
.search-container {
display: flex;
height: 100%; /* takes up only the necessary height */
overflow-y: auto;
scroll-behavior: smooth;
.filter-panel {
position: fixed;
@@ -846,7 +885,6 @@ const showLoaders = computed(
}
.search {
scroll-behavior: smooth;
margin: 0 1rem 0.5rem 20.5rem;
width: calc(100% - 20.5rem);

View File

@@ -65,7 +65,7 @@
</template>
<template #filter_update>
<UpdatedIcon />
Select Updatable
Select updatable
</template>
</DropdownButton>
<Button v-if="selected.length > 0" class="no-wrap" @click="deleteWarning.show()">
@@ -155,21 +155,16 @@
<TrashIcon />
</Button>
<AnimatedLogo v-if="mod.updating" class="btn icon-only updating-indicator"></AnimatedLogo>
<Button
v-else
v-tooltip="'Update project'"
:disabled="!mod.outdated"
icon-only
@click="updateProject(mod)"
>
<UpdatedIcon v-if="mod.outdated" />
<CheckIcon v-else />
<Button v-else :disabled="!mod.outdated" icon-only @click="updateProject(mod)">
<UpdatedIcon v-if="mod.outdated" v-tooltip="'Update project'" />
<CheckIcon v-else v-tooltip="'Updated'" />
</Button>
<input
id="switch-1"
autocomplete="off"
type="checkbox"
class="switch stylized-toggle"
:disabled="mod.toggleInProgress"
:checked="!mod.disabled"
@change="toggleDisableMod(mod)"
/>
@@ -454,7 +449,6 @@ async function updateProject(mod) {
async function toggleDisableMod(mod) {
mod.path = await toggle_disable_project(props.instance.path, mod.path).catch(handleError)
mod.disabled = !mod.disabled
mixpanel.track('InstanceProjectDisable', {
loader: props.instance.metadata.loader,
game_version: props.instance.metadata.game_version,

View File

@@ -610,6 +610,10 @@ async function saveGvLoaderEdits() {
padding: 1rem;
gap: 1rem;
:deep(.animated-dropdown .options) {
max-height: 13.375rem;
}
.input-label {
font-size: 1rem;
font-weight: bolder;

View File

@@ -207,6 +207,7 @@
:dependencies="dependencies"
:install="install"
:installed="installed"
:installing="installing"
:installed-version="installedVersion"
/>
</div>
@@ -310,7 +311,7 @@ async function fetchProjectData() {
useFetch(`https://api.modrinth.com/v2/project/${route.params.id}/members`, 'project'),
useFetch(`https://api.modrinth.com/v2/project/${route.params.id}/dependencies`, 'project'),
get_categories().catch(handleError),
route.query.i ? getInstance(route.query.i, true).catch(handleError) : Promise.resolve(),
route.query.i ? getInstance(route.query.i, false).catch(handleError) : Promise.resolve(),
])
installed.value =
@@ -344,6 +345,7 @@ const markInstalled = () => {
async function install(version) {
installing.value = true
let queuedVersionData
instance.value = await getInstance(instance.value.path, false).catch(handleError)
if (installed.value) {
await remove_project(

View File

@@ -14,10 +14,21 @@
<h2>{{ version.name }}</h2>
</div>
<div class="button-group">
<Button color="primary" :action="() => install(version.id)" :disabled="installed">
<Button
color="primary"
:action="() => install(version.id)"
:disabled="installing || (installed && installedVersion === version.id)"
>
<DownloadIcon v-if="!installed" />
<SwapIcon v-else-if="installedVersion !== version.id" />
<CheckIcon v-else />
{{ installed ? 'Installed' : 'Install' }}
{{
installing
? 'Installing...'
: installed && installedVersion === version.id
? 'Installed'
: 'Install'
}}
</Button>
<Button>
<ReportIcon />
@@ -29,7 +40,7 @@
class="btn"
>
<ExternalIcon />
Modrinth Website
Modrinth website
</a>
</div>
</Card>
@@ -195,6 +206,7 @@ import { releaseColor } from '@/helpers/utils'
import { ref, watch, computed } from 'vue'
import { useRoute } from 'vue-router'
import { useBreadcrumbs } from '@/store/breadcrumbs'
import { SwapIcon } from '@/assets/icons'
const breadcrumbs = useBreadcrumbs()
@@ -225,6 +237,14 @@ const props = defineProps({
type: Boolean,
required: true,
},
installing: {
type: Boolean,
required: true,
},
installedVersion: {
type: String,
required: true,
},
})
const version = ref(props.versions.find((version) => version.id === route.params.version))

View File

@@ -89,7 +89,7 @@
<Button
:color="installed && version.id === installedVersion ? '' : 'primary'"
icon-only
:disabled="installed && version.id === installedVersion"
:disabled="installing || (installed && version.id === installedVersion)"
@click.stop="() => install(version.id)"
>
<DownloadIcon v-if="!installed" />
@@ -191,6 +191,10 @@ const props = defineProps({
type: Boolean,
default: null,
},
installing: {
type: Boolean,
default: false,
},
instance: {
type: Object,
default: null,

View File

@@ -8,11 +8,24 @@ export const useBreadcrumbs = defineStore('breadcrumbsStore', {
}),
actions: {
getName(route) {
return this.names.get(route) ?? route
return this.names.get(route) ?? ''
},
setName(route, title) {
this.names.set(route, title)
},
// resets breadcrumbs to only included ones as to not have stale breadcrumbs
resetToNames(breadcrumbs) {
// names is an array of every breadcrumb.name that starts with a ?
const names = breadcrumbs
.filter((breadcrumb) => breadcrumb.name.charAt(0) === '?')
.map((breadcrumb) => breadcrumb.name.slice(1))
// remove all names that are not in the names array
for (const [route] of this.names) {
if (!names.includes(route)) {
this.names.delete(route)
}
}
},
setContext(context) {
this.context = context
},