0.9.0 release (app) (#3056)

* Debug app

* Bump version, final fixes
This commit is contained in:
Geometrically 2024-12-23 13:38:52 -07:00 committed by GitHub
parent cae6f12ea0
commit 9952c3a0c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 111 additions and 70 deletions

4
Cargo.lock generated
View File

@ -8956,7 +8956,7 @@ dependencies = [
[[package]]
name = "theseus"
version = "0.9.0-2"
version = "0.9.0"
dependencies = [
"async-recursion",
"async-tungstenite",
@ -9007,7 +9007,7 @@ dependencies = [
[[package]]
name = "theseus_gui"
version = "0.9.0-2"
version = "0.9.0"
dependencies = [
"chrono",
"cocoa 0.25.0",

View File

@ -1,7 +1,7 @@
{
"name": "@modrinth/app-frontend",
"private": true,
"version": "0.9.0-2",
"version": "0.9.0",
"type": "module",
"scripts": {
"dev": "vite",

View File

@ -264,13 +264,15 @@ router.afterEach((to) => {
forceSidebar.value = to.path.startsWith('/browse') || to.path.startsWith('/project')
})
const currentTimeout = ref(null)
watch(
showAd,
() => {
if (!showAd.value) {
if (currentTimeout.value) clearTimeout(currentTimeout.value)
hide_ads_window(true)
} else {
setTimeout(() => {
currentTimeout.value = setTimeout(() => {
init_ads_window(true)
}, 400)
}
@ -441,7 +443,7 @@ function handleAuxClick(e) {
<div data-tauri-drag-region class="app-grid-statusbar bg-bg-raised h-[--top-bar-height] flex">
<div data-tauri-drag-region class="flex p-3">
<ModrinthAppLogo class="h-full w-auto text-contrast pointer-events-none" />
<Breadcrumbs />
<Breadcrumbs class="pt-[2px]" />
</div>
<section class="flex ml-auto items-center">
<ButtonStyled

View File

@ -25,6 +25,7 @@ import { showProfileInFolder } from '@/helpers/utils.js'
import { trackEvent } from '@/helpers/analytics'
import { handleSevereError } from '@/store/error.js'
import { install as installVersion } from '@/store/install.js'
import { openUrl } from '@tauri-apps/plugin-opener'
const router = useRouter()
@ -165,13 +166,7 @@ const handleOptionsClick = async (args) => {
break
}
case 'open_link':
window.__TAURI_INVOKE__('tauri', {
__tauriModule: 'Shell',
message: {
cmd: 'open',
path: `https://modrinth.com/${args.item.project_type}/${args.item.slug}`,
},
})
openUrl(`https://modrinth.com/${args.item.project_type}/${args.item.slug}`)
break
case 'copy_link':
await navigator.clipboard.writeText(

View File

@ -189,11 +189,12 @@ onUnmounted(() => unlisten())
v-else-if="modLoading || installing"
v-tooltip="modLoading ? 'Instance is loading...' : 'Installing...'"
class="animate-spin w-8 h-8"
tabindex="-1"
/>
<ButtonStyled v-else size="large" color="brand" circular>
<button
v-tooltip="'Play'"
class="transition-all scale-75 group-hover:scale-100 origin-bottom opacity-0 group-hover:opacity-100 card-shadow"
class="transition-all scale-75 group-hover:scale-100 group-focus-within:scale-100 origin-bottom opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 card-shadow"
@click="(e) => play(e, 'InstanceCard')"
@mousehover="checkProcess"
>

View File

@ -16,10 +16,10 @@ const getInstances = async () => {
recentInstances.value = profiles
.sort((a, b) => {
const dateACreated = dayjs(a.created)
const dateAPlayed = dayjs(a.last_played)
const dateAPlayed = a.last_played ? dayjs(a.last_played) : dayjs(0)
const dateBCreated = dayjs(b.created)
const dateBPlayed = dayjs(b.last_played)
const dateBPlayed = b.last_played ? dayjs(b.last_played) : dayjs(0)
const dateA = dateACreated.isAfter(dateAPlayed) ? dateACreated : dateAPlayed
const dateB = dateBCreated.isAfter(dateBPlayed) ? dateBCreated : dateBPlayed
@ -35,8 +35,10 @@ const getInstances = async () => {
await getInstances()
const unlistenProfile = await profile_listener(async () => {
await getInstances()
const unlistenProfile = await profile_listener(async (event) => {
if (event.event !== 'synced') {
await getInstances()
}
})
onUnmounted(() => {
@ -50,6 +52,7 @@ onUnmounted(() => {
:key="instance.id"
v-tooltip.right="instance.name"
:to="`/instance/${encodeURIComponent(instance.path)}`"
class="relative"
>
<Avatar
:src="instance.icon_path ? convertFileSrc(instance.icon_path) : null"
@ -59,7 +62,7 @@ onUnmounted(() => {
/>
<div
v-if="instance.install_stage !== 'installed'"
class="absolute inset-0 flex items-center justify-center"
class="absolute inset-0 flex items-center justify-center z-10"
>
<SpinnerIcon class="animate-spin w-4 h-4" />
</div>

View File

@ -1,14 +1,10 @@
<template>
<div class="action-groups">
<Button
v-if="currentLoadingBars.length > 0"
ref="infoButton"
icon-only
class="icon-button show-card-icon"
@click="toggleCard()"
>
<DownloadIcon />
</Button>
<ButtonStyled v-if="currentLoadingBars.length > 0" color="brand" type="transparent" circular>
<button ref="infoButton" @click="toggleCard()">
<DownloadIcon />
</button>
</ButtonStyled>
<div v-if="offline" class="status">
<UnplugIcon />
<div class="running-text">
@ -41,15 +37,6 @@
<Button v-tooltip="'View logs'" icon-only class="icon-button" @click="goToTerminal()">
<TerminalSquareIcon />
</Button>
<Button
v-if="currentLoadingBars.length > 0"
ref="infoButton"
icon-only
class="icon-button show-card-icon"
@click="toggleCard()"
>
<DownloadIcon />
</Button>
</div>
<div v-else class="status">
<span class="circle stopped" />
@ -111,7 +98,7 @@ import {
DropdownIcon,
UnplugIcon,
} from '@modrinth/assets'
import { Button, Card } from '@modrinth/ui'
import { Button, ButtonStyled, Card } from '@modrinth/ui'
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { get_all as getRunningProcesses, kill as killProcess } from '@/helpers/process'
import { loading_listener, process_listener } from '@/helpers/events'
@ -409,10 +396,6 @@ onBeforeUnmount(() => {
}
}
.show-card-icon {
color: var(--color-brand);
}
.download-enter-active,
.download-leave-active {
transition: opacity 0.3s ease;

View File

@ -157,13 +157,13 @@ const installing = ref(false)
async function install() {
installing.value = true
await installVersion(
props.project.project_id,
props.project.project_id ?? props.project.id,
null,
props.instance ? props.instance.path : null,
'SearchCard',
() => {
installing.value = false
emit('install', props.project.project_id)
emit('install', props.project.project_id ?? props.project.id)
},
)
}

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, nextTick, ref, shallowRef, watch } from 'vue'
import type { Ref } from 'vue'
import { SearchIcon, XIcon } from '@modrinth/assets'
import { SearchIcon, XIcon, ClipboardCopyIcon, GlobeIcon, ExternalIcon } from '@modrinth/assets'
import type { Category, GameVersion, Platform, ProjectType, SortType, Tags } from '@modrinth/ui'
import {
SearchFilterControl,
@ -25,6 +25,8 @@ import NavTabs from '@/components/ui/NavTabs.vue'
import type Instance from '@/components/ui/Instance.vue'
import InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
import { defineMessages, useVIntl } from '@vintl/vintl'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import { openUrl } from '@tauri-apps/plugin-opener'
const { formatMessage } = useVIntl()
@ -351,6 +353,36 @@ const messages = defineMessages({
},
})
const options = ref(null)
const handleRightClick = (event, result) => {
options.value.showMenu(event, result, [
{
name: 'install',
},
{
type: 'divider',
},
{
name: 'open_link',
},
{
name: 'copy_link',
},
])
}
const handleOptionsClick = (args) => {
switch (args.option) {
case 'open_link':
openUrl(`https://modrinth.com/${args.item.project_type}/${args.item.slug}`)
break
case 'copy_link':
navigator.clipboard.writeText(
`https://modrinth.com/${args.item.project_type}/${args.item.slug}`,
)
break
}
}
await refreshSearch()
</script>
@ -477,7 +509,12 @@ await refreshSearch()
newlyInstalled.push(id)
}
"
@contextmenu.prevent.stop="(event) => handleRightClick(event, result)"
/>
<ContextMenu ref="options" @option-clicked="handleOptionsClick">
<template #open_link> <GlobeIcon /> Open in Modrinth <ExternalIcon /> </template>
<template #copy_link> <ClipboardCopyIcon /> Copy link </template>
</ContextMenu>
</section>
<div class="flex justify-end">
<pagination

View File

@ -218,6 +218,15 @@
</ButtonStyled>
</template>
</ContentListPanel>
<div class="flex justify-end mt-4">
<Pagination
v-if="search.length > 0"
:page="currentPage"
:count="Math.ceil(search.length / 20)"
:link-function="(page) => `?page=${page}`"
@switch-page="(page) => (currentPage = page)"
/>
</div>
</template>
<div v-else class="w-full flex flex-col items-center justify-center mt-6 max-w-[48rem] mx-auto">
<div class="top-box w-full">
@ -416,6 +425,7 @@ const initProjects = async (cacheBehaviour?) => {
icon: null,
disabled: file.file_name.endsWith('.disabled'),
outdated: false,
updated: dayjs(0),
project_type: file.project_type === 'shaderpack' ? 'shader' : file.project_type,
})
}
@ -541,20 +551,19 @@ const search = computed(() => {
switch (sortColumn.value) {
case 'Updated':
return filtered.slice().sort((a, b) => {
if (a.updated < b.updated) {
return ascending.value ? 1 : -1
}
if (a.updated > b.updated) {
return ascending.value ? -1 : 1
}
return 0
const updated = a.updated.isAfter(b.updated) ? 1 : -1
return ascending.value ? -updated : updated
})
default:
return filtered.slice().sort((a, b) => a.name.localeCompare(b.name))
return filtered
.slice()
.sort((a, b) =>
ascending.value ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name),
)
}
})
watch(search, () => (currentPage.value = 1))
watch([sortColumn, ascending, selectedFilters.value, searchFilter], () => (currentPage.value = 1))
const sortProjects = (filter) => {
if (sortColumn.value === filter) {

View File

@ -31,7 +31,7 @@
>
<ProjectBackgroundGradient :project="data" />
</Teleport>
<ProjectHeader :project="data">
<ProjectHeader :project="data" @contextmenu.prevent.stop="handleRightClick">
<template #actions>
<ButtonStyled size="large" color="brand">
<button
@ -118,7 +118,7 @@
:installed-version="installedVersion"
/>
</template>
<template v-else> Project data coult not be loaded. </template>
<template v-else> Project data couldn't not be loaded. </template>
</div>
<ContextMenu ref="options" @option-clicked="handleOptionsClick">
<template #install> <DownloadIcon /> Install </template>
@ -165,6 +165,7 @@ import { get_project, get_team, get_version_many } from '@/helpers/cache.js'
import NavTabs from '@/components/ui/NavTabs.vue'
import { useTheming } from '@/store/state.js'
import InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
import { openUrl } from '@tauri-apps/plugin-opener'
dayjs.extend(relativeTime)
@ -172,7 +173,6 @@ const route = useRoute()
const breadcrumbs = useBreadcrumbs()
const themeStore = useTheming()
const options = ref(null)
const installing = ref(false)
const data = shallowRef(null)
const versions = shallowRef([])
@ -245,19 +245,30 @@ async function install(version) {
)
}
const options = ref(null)
const handleRightClick = (event) => {
options.value.showMenu(event, data.value, [
{
name: 'install',
},
{
type: 'divider',
},
{
name: 'open_link',
},
{
name: 'copy_link',
},
])
}
const handleOptionsClick = (args) => {
switch (args.option) {
case 'install':
install(null)
break
case 'open_link':
window.__TAURI_INVOKE__('tauri', {
__tauriModule: 'Shell',
message: {
cmd: 'open',
path: `https://modrinth.com/${args.item.project_type}/${args.item.slug}`,
},
})
openUrl(`https://modrinth.com/${args.item.project_type}/${args.item.slug}`)
break
case 'copy_link':
navigator.clipboard.writeText(

View File

@ -1,6 +1,6 @@
[package]
name = "theseus_gui"
version = "0.9.0-2"
version = "0.9.0"
description = "The Modrinth App is a desktop application for managing your Minecraft mods"
license = "GPL-3.0-only"
repository = "https://github.com/modrinth/code/apps/app/"

View File

@ -61,7 +61,7 @@ fn get_webview_position<R: Runtime>(
let width = 300.0 * dpr;
let height = 250.0 * dpr;
let main_window_size = main_window.inner_size()?;
let main_window_size = main_window.outer_size()?;
let x = (main_window_size.width as f32) - width;
let y = (main_window_size.height as f32) - height;

View File

@ -237,7 +237,7 @@ fn main() {
if let Some(window) = app.get_window("main") {
// Hide window to prevent white flash on startup
let _ = window.hide();
// let _ = window.hide();
#[cfg(not(target_os = "linux"))]
{

View File

@ -44,7 +44,7 @@
]
},
"productName": "Modrinth App",
"version": "0.9.0-2",
"version": "0.9.0",
"mainBinaryName": "Modrinth App",
"identifier": "ModrinthApp",
"plugins": {
@ -69,7 +69,7 @@
"width": 1280,
"minHeight": 700,
"minWidth": 1100,
"visible": false,
"visible": true,
"zoomHotkeysEnabled": false,
"decorations": false
}

View File

@ -1,6 +1,6 @@
[package]
name = "theseus"
version = "0.9.0-2"
version = "0.9.0"
authors = ["Jai A <jaiagr+gpg@pm.me>"]
edition = "2021"

View File

@ -41,7 +41,7 @@ defineExpose({ selectedTab, setTab })
<slot name="footer" />
</div>
<div class="w-[600px] h-[500px] overflow-y-auto pl-4">
<div class="w-[600px] h-[500px] overflow-y-auto px-4">
<component :is="tabs[selectedTab].content" v-bind="tabs[selectedTab].props ?? {}" />
</div>
</div>