Bugs again (#703)

* initial

* more fixes

* logs

* more fixes

* working rescuer

* minor log display fix

* mac fixes

* minor fix

* libsselinux1

* linux error

* actions test

* more bugs. Modpack page! BIG changes

* changed minimum 64 -> 8

* removed modpack page moved to modal

* removed unnecessary css

* mac compile

* many revs

* Merge colorful logs (#725)

* make implementation not dumb

* run prettier

* null -> true

* Add line numbers & make errors more robust.

* improvments

* changes; virtual scroll

---------

Co-authored-by: qtchaos <72168435+qtchaos@users.noreply.github.com>

* omorphia colors, comments fix

* fixes; _JAVA_OPTIONS

* revs

* mac specific

* more mac

* some fixes

* quick fix

* add java reinstall option

---------

Co-authored-by: qtchaos <72168435+qtchaos@users.noreply.github.com>
Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
Wyatt Verchere
2023-09-12 09:27:03 -07:00
committed by GitHub
parent bc02192d80
commit 1e8852b540
63 changed files with 2677 additions and 719 deletions

View File

@@ -20,7 +20,7 @@ import {
import ContextMenu from '@/components/ui/ContextMenu.vue'
import dayjs from 'dayjs'
import { useTheming } from '@/store/theme.js'
import { remove } from '@/helpers/profile.js'
import { duplicate, remove } from '@/helpers/profile.js'
import { handleError } from '@/store/notifications.js'
const props = defineProps({
@@ -51,11 +51,17 @@ async function deleteProfile() {
}
}
const handleRightClick = (event, item) => {
async function duplicateProfile(p) {
await duplicate(p).catch(handleError)
}
const handleRightClick = (event, profilePathId) => {
const item = instanceComponents.value.find((x) => x.instance.path === profilePathId)
const baseOptions = [
{ name: 'add_content' },
{ type: 'divider' },
{ name: 'edit' },
{ name: 'duplicate' },
{ name: 'open' },
{ name: 'copy' },
{ type: 'divider' },
@@ -100,6 +106,10 @@ const handleOptionsClick = async (args) => {
case 'edit':
await args.item.seeInstance()
break
case 'duplicate':
if (args.item.instance.install_stage == 'installed')
await duplicateProfile(args.item.instance.path)
break
case 'open':
await args.item.openFolder()
break
@@ -131,7 +141,7 @@ const filteredResults = computed(() => {
if (sortBy.value === 'Game version') {
instances.sort((a, b) => {
return a.metadata.name.localeCompare(b.metadata.game_version)
return a.metadata.game_version.localeCompare(b.metadata.game_version)
})
}
@@ -285,11 +295,11 @@ const filteredResults = computed(() => {
</div>
<section class="instances">
<Instance
v-for="(instance, index) in instanceSection.value"
v-for="instance in instanceSection.value"
ref="instanceComponents"
:key="instance.path"
:key="instance.path + instance.install_stage"
:instance="instance"
@contextmenu.prevent.stop="(event) => handleRightClick(event, instanceComponents[index])"
@contextmenu.prevent.stop="(event) => handleRightClick(event, instance.path)"
/>
</section>
</div>
@@ -298,6 +308,7 @@ const filteredResults = computed(() => {
<template #stop> <StopCircleIcon /> Stop </template>
<template #add_content> <PlusIcon /> Add content </template>
<template #edit> <EyeIcon /> View instance </template>
<template #duplicate> <ClipboardCopyIcon /> Duplicate instance</template>
<template #delete> <TrashIcon /> Delete </template>
<template #open> <FolderOpenIcon /> Open folder </template>
<template #copy> <ClipboardCopyIcon /> Copy path </template>

View File

@@ -25,7 +25,7 @@ import {
kill_by_uuid,
} from '@/helpers/process.js'
import { handleError } from '@/store/notifications.js'
import { remove, run } from '@/helpers/profile.js'
import { duplicate, remove, run } from '@/helpers/profile.js'
import { useRouter } from 'vue-router'
import { showProfileInFolder } from '@/helpers/utils.js'
import { useFetch } from '@/helpers/fetch.js'
@@ -70,11 +70,16 @@ async function deleteProfile() {
}
}
async function duplicateProfile(p) {
await duplicate(p).catch(handleError)
}
const handleInstanceRightClick = async (event, passedInstance) => {
const baseOptions = [
{ name: 'add_content' },
{ type: 'divider' },
{ name: 'edit' },
{ name: 'duplicate' },
{ name: 'open_folder' },
{ name: 'copy_path' },
{ type: 'divider' },
@@ -150,6 +155,9 @@ const handleOptionsClick = async (args) => {
path: `/instance/${encodeURIComponent(args.item.path)}/`,
})
break
case 'duplicate':
if (args.item.install_stage == 'installed') await duplicateProfile(args.item.path)
break
case 'delete':
currentDeleteInstance.value = args.item.path
deleteConfirmModal.value.show()
@@ -237,7 +245,7 @@ onUnmounted(() => {
<section v-if="row.instances[0].metadata" ref="modsRow" class="instances">
<Instance
v-for="instance in row.instances.slice(0, maxInstancesPerRow)"
:key="instance?.project_id || instance?.id"
:key="(instance?.project_id || instance?.id) + instance.install_stage"
:instance="instance"
@contextmenu.prevent.stop="(event) => handleInstanceRightClick(event, instance)"
/>
@@ -263,6 +271,7 @@ onUnmounted(() => {
<template #edit> <EyeIcon /> View instance </template>
<template #delete> <TrashIcon /> Delete </template>
<template #open_folder> <FolderOpenIcon /> Open folder </template>
<template #duplicate> <ClipboardCopyIcon /> Duplicate instance</template>
<template #copy_path> <ClipboardCopyIcon /> Copy path </template>
<template #install> <DownloadIcon /> Install </template>
<template #open_link> <GlobeIcon /> Open in Modrinth <ExternalIcon /> </template>

View File

@@ -105,7 +105,7 @@ import {
GlobeIcon,
ClipboardCopyIcon,
} from 'omorphia'
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import { ref, computed, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
import {
users,
remove_user,
@@ -116,6 +116,7 @@ import { get, set } from '@/helpers/settings'
import { handleError } from '@/store/state.js'
import { mixpanel_track } from '@/helpers/mixpanel'
import QrcodeVue from 'qrcode.vue'
import { process_listener } from '@/helpers/events'
defineProps({
mode: {
@@ -214,6 +215,12 @@ const handleClickOutside = (event) => {
}
}
const unlisten = await process_listener(async (e) => {
if (e.event === 'launched') {
await refreshValues()
}
})
onMounted(() => {
window.addEventListener('click', handleClickOutside)
})
@@ -221,6 +228,10 @@ onMounted(() => {
onBeforeUnmount(() => {
window.removeEventListener('click', handleClickOutside)
})
onUnmounted(() => {
unlisten()
})
</script>
<style scoped lang="scss">

View File

@@ -1,5 +1,5 @@
<script setup>
import { Button, Checkbox, Modal, SendIcon, XIcon } from 'omorphia'
import { Button, Checkbox, Modal, XIcon, PlusIcon } from 'omorphia'
import { PackageIcon, VersionIcon } from '@/assets/icons'
import { ref } from 'vue'
import { export_profile_mrpack, get_potential_override_folders } from '@/helpers/profile.js'
@@ -24,9 +24,11 @@ defineExpose({
const exportModal = ref(null)
const nameInput = ref(props.instance.metadata.name)
const exportDescription = ref('')
const versionInput = ref('1.0.0')
const files = ref([])
const folders = ref([])
const showingFiles = ref(false)
const themeStore = useTheming()
@@ -93,7 +95,9 @@ const exportPack = async () => {
props.instance.path,
outputPath + `/${nameInput.value} ${versionInput.value}.mrpack`,
filesToExport,
versionInput.value
versionInput.value,
exportDescription.value,
nameInput.value
).catch((err) => handleError(err))
exportModal.value.hide()
}
@@ -123,11 +127,31 @@ const exportPack = async () => {
</Button>
</div>
</div>
<div class="adjacent-input">
<div class="labeled_input">
<p>Description</p>
<div class="textarea-wrapper">
<textarea v-model="exportDescription" placeholder="Enter modpack description..." />
</div>
</div>
</div>
<div class="table">
<div class="table-head">
<div class="table-cell">Select files and folders to include in pack</div>
<div class="table-cell row-wise">
Select files and folders to include in pack
<Button
class="sleek-primary collapsed-button"
icon-only
@click="() => (showingFiles = !showingFiles)"
>
<PlusIcon v-if="!showingFiles" />
<XIcon v-else />
</Button>
</div>
</div>
<div class="table-content">
<div v-if="showingFiles" class="table-content">
<div v-for="[path, children] of folders" :key="path.name" class="table-row">
<div class="table-cell file-entry">
<div class="file-primary">
@@ -177,10 +201,6 @@ const exportPack = async () => {
<XIcon />
Cancel
</Button>
<Button disabled>
<SendIcon />
Share
</Button>
<Button color="primary" @click="exportPack">
<PackageIcon />
Export
@@ -261,4 +281,22 @@ const exportPack = async () => {
gap: var(--gap-sm);
align-items: center;
}
.row-wise {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.textarea-wrapper {
// margin-top: 1rem;
height: 12rem;
textarea {
max-height: 12rem;
}
.preview {
overflow-y: auto;
}
}
</style>

View File

@@ -18,6 +18,14 @@
"
/>
<span class="installation-buttons">
<Button
v-if="props.version"
:disabled="props.disabled || installingJava"
@click="reinstallJava"
>
<DownloadIcon />
{{ installingJava ? 'Installing...' : 'Install recommended' }}
</Button>
<Button :disabled="props.disabled" @click="autoDetect">
<SearchIcon />
Auto detect
@@ -44,8 +52,22 @@
</template>
<script setup>
import { Button, SearchIcon, PlayIcon, CheckIcon, XIcon, FolderSearchIcon } from 'omorphia'
import { find_jre_17_jres, get_jre } from '@/helpers/jre.js'
import {
Button,
SearchIcon,
PlayIcon,
CheckIcon,
XIcon,
FolderSearchIcon,
DownloadIcon,
} from 'omorphia'
import {
auto_install_java,
find_jre_17_jres,
find_jre_8_jres,
get_jre,
test_jre,
} from '@/helpers/jre.js'
import { ref } from 'vue'
import { open } from '@tauri-apps/api/dialog'
import JavaDetectionModal from '@/components/ui/JavaDetectionModal.vue'
@@ -82,15 +104,21 @@ const emit = defineEmits(['update:modelValue'])
const testingJava = ref(false)
const testingJavaSuccess = ref(null)
const installingJava = ref(false)
async function testJava() {
testingJava.value = true
let result = await get_jre(props.modelValue ? props.modelValue.path : '')
testingJavaSuccess.value = await test_jre(
props.modelValue ? props.modelValue.path : '',
1,
props.version
)
testingJava.value = false
testingJavaSuccess.value = !!result
mixpanel_track('JavaTest', {
path: props.modelValue ? props.modelValue.path : '',
success: !!result,
success: testingJavaSuccess.value,
})
setTimeout(() => {
@@ -109,13 +137,13 @@ async function handleJavaFileInput() {
version: props.version.toString(),
architecture: 'x86',
}
mixpanel_track('JavaManualSelect', {
path: filePath,
version: props.version,
})
}
mixpanel_track('JavaManualSelect', {
path: filePath,
version: props.version,
})
emit('update:modelValue', result)
}
}
@@ -125,12 +153,43 @@ async function autoDetect() {
if (!props.compact) {
detectJavaModal.value.show(props.version, props.modelValue)
} else {
let versions = await find_jre_17_jres().catch(handleError)
if (versions.length > 0) {
emit('update:modelValue', versions[0])
if (props.version == 8) {
let versions = await find_jre_8_jres().catch(handleError)
if (versions.length > 0) {
emit('update:modelValue', versions[0])
}
} else {
let versions = await find_jre_17_jres().catch(handleError)
if (versions.length > 0) {
emit('update:modelValue', versions[0])
}
}
}
}
async function reinstallJava() {
installingJava.value = true
const path = await auto_install_java(props.version).catch(handleError)
console.log('java path: ' + path)
let result = await get_jre(path)
console.log('java result ' + result)
if (!result) {
result = {
path: path,
version: props.version.toString(),
architecture: 'x86',
}
}
mixpanel_track('JavaReInstall', {
path: path,
version: props.version,
})
emit('update:modelValue', result)
installingJava.value = false
}
</script>
<style lang="scss" scoped>

View File

@@ -0,0 +1,187 @@
<script setup>
import { Button, Modal, CheckIcon, Badge } from 'omorphia'
import { computed, ref } from 'vue'
import { useTheming } from '@/store/theme'
import { update_managed_modrinth_version } from '@/helpers/profile'
import { releaseColor } from '@/helpers/utils'
import { SwapIcon } from '@/assets/icons/index.js'
const props = defineProps({
versions: {
type: Array,
required: true,
},
instance: {
type: Object,
default: null,
},
})
defineExpose({
show: () => {
modpackVersionModal.value.show()
},
})
const filteredVersions = computed(() => {
return props.versions
})
const modpackVersionModal = ref(null)
const installedVersion = computed(() => props.instance?.metadata?.linked_data?.version_id)
const installing = computed(() => props.instance.install_stage !== 'installed')
const inProgress = ref(false)
const themeStore = useTheming()
const switchVersion = async (versionId) => {
inProgress.value = true
await update_managed_modrinth_version(props.instance.path, versionId)
inProgress.value = false
}
</script>
<template>
<Modal
ref="modpackVersionModal"
class="modpack-version-modal"
header="Change modpack version"
:noblur="!themeStore.advancedRendering"
>
<div class="modal-body">
<Card v-if="instance.metadata.linked_data" class="mod-card">
<div class="table">
<div class="table-row with-columns table-head">
<div class="table-cell table-text download-cell" />
<div class="name-cell table-cell table-text">Name</div>
<div class="table-cell table-text">Supports</div>
</div>
<div class="scrollable">
<div
v-for="version in filteredVersions"
:key="version.id"
class="table-row with-columns selectable"
@click="$router.push(`/project/${$route.params.id}/version/${version.id}`)"
>
<div class="table-cell table-text">
<Button
:color="version.id === installedVersion ? '' : 'primary'"
icon-only
:disabled="inProgress || installing || version.id === installedVersion"
@click.stop="() => switchVersion(version.id)"
>
<SwapIcon v-if="version.id !== installedVersion" />
<CheckIcon v-else />
</Button>
</div>
<div class="name-cell table-cell table-text">
<div class="version-link">
{{ version.name.charAt(0).toUpperCase() + version.name.slice(1) }}
<div class="version-badge">
<div class="channel-indicator">
<Badge
:color="releaseColor(version.version_type)"
:type="
version.version_type.charAt(0).toUpperCase() +
version.version_type.slice(1)
"
/>
</div>
<div>
{{ version.version_number }}
</div>
</div>
</div>
</div>
<div class="table-cell table-text stacked-text">
<span>
{{
version.loaders
.map((str) => str.charAt(0).toUpperCase() + str.slice(1))
.join(', ')
}}
</span>
<span>
{{ version.game_versions.join(', ') }}
</span>
</div>
</div>
</div>
</div>
</Card>
</div>
</Modal>
</template>
<style scoped lang="scss">
.filter-header {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.with-columns {
grid-template-columns: min-content 1fr 1fr;
}
.scrollable {
overflow-y: auto;
max-height: 25rem;
}
.card-row {
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--color-raised-bg);
}
.mod-card {
display: flex;
flex-direction: column;
gap: 1rem;
overflow: hidden;
margin-top: 0.5rem;
}
.version-link {
display: flex;
flex-direction: column;
gap: 0.25rem;
.version-badge {
display: flex;
flex-wrap: wrap;
.channel-indicator {
margin-right: 0.5rem;
}
}
}
.stacked-text {
display: flex;
flex-direction: column;
gap: 0.25rem;
align-items: flex-start;
}
.download-cell {
width: 4rem;
padding: 1rem;
}
.modal-body {
padding: var(--gap-xl);
display: flex;
flex-direction: column;
gap: var(--gap-md);
}
.table {
border: 1px solid var(--color-bg);
}
</style>

View File

@@ -176,7 +176,7 @@ defineProps({
</Card>
</aside>
<div ref="searchWrapper" class="search">
<Promotion class="promotion" query-param="?r=launcher" />
<Promotion class="promotion" :external="false" query-param="?r=launcher" />
<Card class="project-type-container">
<NavRow :links="selectableProjectTypes" />
</Card>

View File

@@ -22,8 +22,9 @@ const pageOptions = ['Home', 'Library']
id="theme"
name="Theme dropdown"
:options="['Dark']"
:disabled="true"
:default-value="'dark'"
class="theme-dropdown"
class="theme-dropdown disable-children"
/>
</div>
<div class="adjacent-input">
@@ -33,7 +34,7 @@ const pageOptions = ['Home', 'Library']
>Change the style of the side navigation bar to a compact version.</span
>
</label>
<Toggle id="collapsed-nav" :checked="false" />
<Toggle id="collapsed-nav" :checked="false" :disabled="true" />
</div>
<div class="adjacent-input">
<label for="advanced-rendering">
@@ -43,7 +44,7 @@ const pageOptions = ['Home', 'Library']
without hardware-accelerated rendering.
</span>
</label>
<Toggle id="advanced-rendering" :checked="true" />
<Toggle id="advanced-rendering" :checked="true" :disabled="true" />
</div>
<div class="adjacent-input">
<label for="minimize-launcher">
@@ -52,7 +53,7 @@ const pageOptions = ['Home', 'Library']
>Minimize the launcher when a Minecraft process starts.</span
>
</label>
<Toggle id="minimize-launcher" :checked="false" />
<Toggle id="minimize-launcher" :checked="false" :disabled="true" />
</div>
<div class="opening-page">
<label for="opening-page">
@@ -65,6 +66,7 @@ const pageOptions = ['Home', 'Library']
:options="pageOptions"
default-value="Home"
class="opening-page"
:disabled="true"
/>
</div>
</Card>
@@ -82,7 +84,7 @@ const pageOptions = ['Home', 'Library']
lower value if you have a poor internet connection.</span
>
</label>
<Slider id="max-downloads" :min="1" :max="10" :step="1" />
<Slider id="max-downloads" :min="1" :max="10" :step="1" :disabled="true" />
</div>
<div class="adjacent-input">
@@ -93,7 +95,7 @@ const pageOptions = ['Home', 'Library']
lower value if you are frequently getting I/O errors.</span
>
</label>
<Slider id="max-writes" :min="1" :max="50" :step="1" />
<Slider id="max-writes" :min="1" :max="50" :step="1" :disabled="true" />
</div>
</Card>
<Card>
@@ -110,7 +112,7 @@ const pageOptions = ['Home', 'Library']
customize your experience. Opting out will disable this data collection.
</span>
</label>
<Toggle id="opt-out-analytics" />
<Toggle id="opt-out-analytics" :disabled="true" />
</div>
</Card>
<Card>
@@ -122,11 +124,11 @@ const pageOptions = ['Home', 'Library']
<label for="java-17">
<span class="label__title">Java 17 location</span>
</label>
<JavaSelector id="java-17" :version="17" model-value="" />
<JavaSelector id="java-17" :version="17" model-value="" :disabled="true" />
<label for="java-8">
<span class="label__title">Java 8 location</span>
</label>
<JavaSelector id="java-8" :version="8" model-value="" />
<JavaSelector id="java-8" :version="8" model-value="" :disabled="true" />
<hr class="card-divider" />
<label for="java-args">
<span class="label__title">Java arguments</span>
@@ -137,6 +139,7 @@ const pageOptions = ['Home', 'Library']
type="text"
class="installation-input"
placeholder="Enter java arguments..."
:disabled="true"
/>
<label for="env-vars">
<span class="label__title">Environmental variables</span>
@@ -147,6 +150,7 @@ const pageOptions = ['Home', 'Library']
type="text"
class="installation-input"
placeholder="Enter environmental variables..."
:disabled="true"
/>
<hr class="card-divider" />
<div class="adjacent-input">
@@ -156,7 +160,7 @@ const pageOptions = ['Home', 'Library']
The memory allocated to each instance when it is ran.
</span>
</label>
<Slider id="max-memory" :min="256" :max="10256" :step="1" unit="mb" />
<Slider id="max-memory" :min="256" :max="10256" :step="1" unit="mb" :disabled="true" />
</div>
</Card>
<Card>
@@ -175,6 +179,7 @@ const pageOptions = ['Home', 'Library']
autocomplete="off"
type="text"
placeholder="Enter pre-launch command..."
:disabled="true"
/>
</div>
<div class="adjacent-input">
@@ -182,7 +187,13 @@ const pageOptions = ['Home', 'Library']
<span class="label__title">Wrapper</span>
<span class="label__description"> Wrapper command for launching Minecraft. </span>
</label>
<input id="wrapper" autocomplete="off" type="text" placeholder="Enter wrapper command..." />
<input
id="wrapper"
autocomplete="off"
type="text"
placeholder="Enter wrapper command..."
:disabled="true"
/>
</div>
<div class="adjacent-input">
<label for="post-exit">
@@ -194,6 +205,7 @@ const pageOptions = ['Home', 'Library']
autocomplete="off"
type="text"
placeholder="Enter post-exit command..."
:disabled="true"
/>
</div>
</Card>
@@ -208,7 +220,13 @@ const pageOptions = ['Home', 'Library']
<span class="label__title">Width</span>
<span class="label__description"> The width of the game window when launched. </span>
</label>
<input id="width" autocomplete="off" type="number" placeholder="Enter width..." />
<input
id="width"
autocomplete="off"
type="number"
placeholder="Enter width..."
:disabled="true"
/>
</div>
<div class="adjacent-input">
<label for="height">
@@ -221,6 +239,7 @@ const pageOptions = ['Home', 'Library']
type="number"
class="input"
placeholder="Enter height..."
:disabled="true"
/>
</div>
</Card>
@@ -244,4 +263,8 @@ const pageOptions = ['Home', 'Library']
.card-divider {
margin: 1rem 0;
}
.disable-children * {
pointer-events: none;
}
</style>

View File

@@ -206,9 +206,7 @@ onMounted(() => {
<Button v-if="twoFactorCode" color="primary" large @click="signIn2fa"> Login </Button>
<Button v-else-if="loggingIn" color="primary" large @click="signIn"> Login </Button>
<Button v-else color="primary" large @click="createAccount"> Create account </Button>
<Button class="transparent" large @click="goToNextPage">
{{ modal ? 'Continue' : 'Next' }}
</Button>
<Button v-if="!modal" class="transparent" large @click="goToNextPage"> Next </Button>
</div>
</Card>
</template>

View File

@@ -295,7 +295,7 @@ onMounted(async () => {
:previous-function="prevPhase"
:progress="phase"
title="Settings"
description="You can view and change the settings for the Modrinth App here. You can change the appearance, set and download new Java versions, and more."
description="You will be able to view and change the settings for the Modrinth App here. You can change the appearance, set and download new Java versions, and more."
/>
<TutorialTip
v-if="phase === 9"