App fixes 0.9.0 (#3034)
* push fixes to test on windows * Fix searching mods * Fix search not saving, fix scrolling issues, etc
This commit is contained in:
parent
7e8ceadfd4
commit
6ceed4b226
124
Cargo.lock
generated
124
Cargo.lock
generated
@ -8453,9 +8453,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tao"
|
||||
version = "0.30.8"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da"
|
||||
checksum = "cc6b53216f32e60efc27dfa111268481e4dfba53e553e4cdebcaed9db36c11bb"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cocoa 0.26.0",
|
||||
@ -8468,7 +8468,6 @@ dependencies = [
|
||||
"gdkwayland-sys",
|
||||
"gdkx11-sys",
|
||||
"gtk",
|
||||
"instant",
|
||||
"jni",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
@ -8527,8 +8526,7 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e545de0a2dfe296fa67db208266cd397c5a55ae782da77973ef4c4fac90e9f2c"
|
||||
source = "git+https://github.com/modrinth/tauri?rev=9c36dd3#9c36dd30ad6d19832a5dbd7ac9af0a152bb9323a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes 1.7.2",
|
||||
@ -8559,11 +8557,11 @@ dependencies = [
|
||||
"serde_repr",
|
||||
"serialize-to-javascript",
|
||||
"swift-rs",
|
||||
"tauri-build",
|
||||
"tauri-build 2.0.3 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
"tauri-macros",
|
||||
"tauri-runtime",
|
||||
"tauri-runtime-wry",
|
||||
"tauri-utils",
|
||||
"tauri-utils 2.1.0 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
"thiserror 2.0.7",
|
||||
"tokio 1.42.0",
|
||||
"tray-icon",
|
||||
@ -8592,8 +8590,29 @@ dependencies = [
|
||||
"semver 1.0.23",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri-codegen",
|
||||
"tauri-utils",
|
||||
"tauri-codegen 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tauri-utils 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tauri-winres",
|
||||
"toml 0.8.19",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-build"
|
||||
version = "2.0.3"
|
||||
source = "git+https://github.com/modrinth/tauri?rev=9c36dd3#9c36dd30ad6d19832a5dbd7ac9af0a152bb9323a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_toml",
|
||||
"dirs 5.0.1",
|
||||
"glob",
|
||||
"heck 0.5.0",
|
||||
"json-patch",
|
||||
"schemars",
|
||||
"semver 1.0.23",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri-utils 2.1.0 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
"tauri-winres",
|
||||
"toml 0.8.19",
|
||||
"walkdir",
|
||||
@ -8604,6 +8623,31 @@ name = "tauri-codegen"
|
||||
version = "2.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf79faeecf301d3e969b1fae977039edb77a4c1f25cc0a961be298b54bff97cf"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"ico",
|
||||
"json-patch",
|
||||
"plist",
|
||||
"png",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"semver 1.0.23",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"syn 2.0.90",
|
||||
"tauri-utils 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 2.0.7",
|
||||
"time",
|
||||
"url",
|
||||
"uuid 1.10.0",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-codegen"
|
||||
version = "2.0.3"
|
||||
source = "git+https://github.com/modrinth/tauri?rev=9c36dd3#9c36dd30ad6d19832a5dbd7ac9af0a152bb9323a"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"brotli 7.0.0",
|
||||
@ -8618,7 +8662,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
"syn 2.0.90",
|
||||
"tauri-utils",
|
||||
"tauri-utils 2.1.0 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
"thiserror 2.0.7",
|
||||
"time",
|
||||
"url",
|
||||
@ -8629,15 +8673,14 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-macros"
|
||||
version = "2.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c52027c8c5afb83166dacddc092ee8fff50772f9646d461d8c33ee887e447a03"
|
||||
source = "git+https://github.com/modrinth/tauri?rev=9c36dd3#9c36dd30ad6d19832a5dbd7ac9af0a152bb9323a"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.90",
|
||||
"tauri-codegen",
|
||||
"tauri-utils",
|
||||
"tauri-codegen 2.0.3 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
"tauri-utils 2.1.0 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -8652,7 +8695,7 @@ dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri-utils",
|
||||
"tauri-utils 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.8.19",
|
||||
"walkdir",
|
||||
]
|
||||
@ -8669,7 +8712,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"tauri-utils",
|
||||
"tauri-utils 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 2.0.7",
|
||||
"tracing",
|
||||
"url",
|
||||
@ -8711,7 +8754,7 @@ dependencies = [
|
||||
"serde_repr",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"tauri-utils",
|
||||
"tauri-utils 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 2.0.7",
|
||||
"toml 0.8.19",
|
||||
"url",
|
||||
@ -8821,8 +8864,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-runtime"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cce18d43f80d4aba3aa8a0c953bbe835f3d0f2370aca75e8dbb14bd4bab27958"
|
||||
source = "git+https://github.com/modrinth/tauri?rev=9c36dd3#9c36dd30ad6d19832a5dbd7ac9af0a152bb9323a"
|
||||
dependencies = [
|
||||
"dpi",
|
||||
"gtk",
|
||||
@ -8831,7 +8873,7 @@ dependencies = [
|
||||
"raw-window-handle 0.6.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri-utils",
|
||||
"tauri-utils 2.1.0 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
"thiserror 2.0.7",
|
||||
"url",
|
||||
"windows 0.58.0",
|
||||
@ -8840,8 +8882,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tauri-runtime-wry"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f442a38863e10129ffe2cec7bd09c2dcf8a098a3a27801a476a304d5bb991d2"
|
||||
source = "git+https://github.com/modrinth/tauri?rev=9c36dd3#9c36dd30ad6d19832a5dbd7ac9af0a152bb9323a"
|
||||
dependencies = [
|
||||
"gtk",
|
||||
"http 1.1.0",
|
||||
@ -8855,7 +8896,7 @@ dependencies = [
|
||||
"softbuffer",
|
||||
"tao",
|
||||
"tauri-runtime",
|
||||
"tauri-utils",
|
||||
"tauri-utils 2.1.0 (git+https://github.com/modrinth/tauri?rev=9c36dd3)",
|
||||
"url",
|
||||
"webkit2gtk",
|
||||
"webview2-com",
|
||||
@ -8868,6 +8909,41 @@ name = "tauri-utils"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9271a88f99b4adea0dc71d0baca4505475a0bbd139fb135f62958721aaa8fe54"
|
||||
dependencies = [
|
||||
"cargo_metadata",
|
||||
"ctor",
|
||||
"dunce",
|
||||
"glob",
|
||||
"html5ever",
|
||||
"http 1.1.0",
|
||||
"infer 0.16.0",
|
||||
"json-patch",
|
||||
"kuchikiki",
|
||||
"log",
|
||||
"memchr",
|
||||
"phf 0.11.2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"schemars",
|
||||
"semver 1.0.23",
|
||||
"serde",
|
||||
"serde-untagged",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"swift-rs",
|
||||
"thiserror 2.0.7",
|
||||
"toml 0.8.19",
|
||||
"url",
|
||||
"urlpattern",
|
||||
"uuid 1.10.0",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-utils"
|
||||
version = "2.1.0"
|
||||
source = "git+https://github.com/modrinth/tauri?rev=9c36dd3#9c36dd30ad6d19832a5dbd7ac9af0a152bb9323a"
|
||||
dependencies = [
|
||||
"brotli 7.0.0",
|
||||
"cargo_metadata",
|
||||
@ -9026,7 +9102,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-build 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tauri-plugin-deep-link",
|
||||
"tauri-plugin-dialog",
|
||||
"tauri-plugin-opener",
|
||||
|
||||
@ -19,3 +19,6 @@ strip = true # Remove debug symbols
|
||||
|
||||
[profile.dev.package.sqlx-macros]
|
||||
opt-level = 3
|
||||
|
||||
[patch.crates-io]
|
||||
tauri = { git = "https://github.com/modrinth/tauri", rev = "9c36dd3" }
|
||||
@ -127,7 +127,6 @@ const os = ref('')
|
||||
getOS().then((x) => (os.value = x))
|
||||
|
||||
loading_listener(async (e) => {
|
||||
console.log(e)
|
||||
if (e.event.type === 'directory_move') {
|
||||
loadingProgress.value = 100 * (e.fraction ?? 1)
|
||||
message.value = 'Updating app directory...'
|
||||
|
||||
@ -49,17 +49,3 @@ export const releaseColor = (releaseType) => {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
export function debounce(fn, wait) {
|
||||
let timer
|
||||
return function (...args) {
|
||||
if (timer) {
|
||||
clearTimeout(timer) // clear any pre-existing timer
|
||||
}
|
||||
|
||||
const context = this // get the current context
|
||||
timer = setTimeout(() => {
|
||||
fn.apply(context, args) // call the function if time expires
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,6 @@ import { useRoute, useRouter } from 'vue-router'
|
||||
import SearchCard from '@/components/ui/SearchCard.vue'
|
||||
import { get as getInstance, get_projects as getInstanceProjects } from '@/helpers/profile.js'
|
||||
import { get_search_results } from '@/helpers/cache.js'
|
||||
import { debounce } from '@/helpers/utils.js'
|
||||
import NavTabs from '@/components/ui/NavTabs.vue'
|
||||
import type Instance from '@/components/ui/Instance.vue'
|
||||
import InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
|
||||
@ -190,6 +189,7 @@ const pageCount = computed(() =>
|
||||
)
|
||||
|
||||
watch(requestParams, () => {
|
||||
if (!route.params.projectType) return
|
||||
refreshSearch()
|
||||
})
|
||||
|
||||
@ -214,19 +214,7 @@ async function refreshSearch() {
|
||||
}
|
||||
}
|
||||
results.value = rawResults.result
|
||||
}
|
||||
|
||||
function setPage(newPageNumber: number) {
|
||||
currentPage.value = newPageNumber
|
||||
|
||||
updateSearchResults()
|
||||
onSearchChangeToTop()
|
||||
}
|
||||
|
||||
async function updateSearchResults() {
|
||||
await refreshSearch()
|
||||
|
||||
if (import.meta.client) {
|
||||
const persistentParams: LocationQuery = {}
|
||||
|
||||
for (const [key, value] of Object.entries(route.query)) {
|
||||
@ -246,12 +234,19 @@ async function updateSearchResults() {
|
||||
...createPageParams(),
|
||||
}
|
||||
|
||||
breadcrumbs.setContext({
|
||||
name: 'Discover content',
|
||||
link: `/browse/${projectType.value}`,
|
||||
query: params,
|
||||
})
|
||||
await router.replace({ path: route.path, query: params })
|
||||
breadcrumbs.setContext({ name: 'Discover content', link: route.path, query: params })
|
||||
}
|
||||
}
|
||||
|
||||
const debouncedSearchChange = debounce(() => updateSearchResults(1), 200)
|
||||
async function setPage(newPageNumber: number) {
|
||||
currentPage.value = newPageNumber
|
||||
|
||||
await onSearchChangeToTop()
|
||||
}
|
||||
|
||||
const searchWrapper: Ref<HTMLElement | null> = ref(null)
|
||||
|
||||
@ -261,13 +256,10 @@ async function onSearchChangeToTop() {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
async function clearSearch() {
|
||||
function clearSearch() {
|
||||
query.value = ''
|
||||
await updateSearchResults()
|
||||
}
|
||||
|
||||
async function clearFilters() {}
|
||||
|
||||
watch(
|
||||
() => route.params.projectType,
|
||||
async (newType) => {
|
||||
@ -275,14 +267,9 @@ watch(
|
||||
if (!newType || newType === projectType.value) return
|
||||
|
||||
projectType.value = newType
|
||||
breadcrumbs.setContext({ name: 'Discover content', link: `/browse/${projectType.value}` })
|
||||
|
||||
currentSortType.value = { display: 'Relevance', name: 'relevance' }
|
||||
query.value = ''
|
||||
|
||||
loading.value = true
|
||||
await clearFilters()
|
||||
loading.value = false
|
||||
},
|
||||
)
|
||||
|
||||
@ -418,7 +405,6 @@ await refreshSearch()
|
||||
spellcheck="false"
|
||||
type="text"
|
||||
:placeholder="`Search ${projectType}s...`"
|
||||
@input="debouncedSearchChange()"
|
||||
/>
|
||||
<Button v-if="query" class="r-btn" @click="() => clearSearch()">
|
||||
<XIcon />
|
||||
@ -432,7 +418,6 @@ await refreshSearch()
|
||||
name="Sort by"
|
||||
:options="sortTypes as any"
|
||||
:display-name="(option: SortType | undefined) => option?.display"
|
||||
@change="updateSearchResults()"
|
||||
>
|
||||
<span class="font-semibold text-primary">Sort by: </span>
|
||||
<span class="font-semibold text-secondary">{{ selected }}</span>
|
||||
@ -443,7 +428,6 @@ await refreshSearch()
|
||||
name="Max results"
|
||||
:options="[5, 10, 15, 20, 50, 100]"
|
||||
class="max-w-[9rem]"
|
||||
@change="updateSearchResults()"
|
||||
>
|
||||
<span class="font-semibold text-primary">View: </span>
|
||||
<span class="font-semibold text-secondary">{{ selected }}</span>
|
||||
|
||||
@ -13,18 +13,26 @@
|
||||
</template>
|
||||
<template #summary> </template>
|
||||
<template #stats>
|
||||
<div class="flex items-center gap-2 font-semibold transform capitalize">
|
||||
<div
|
||||
class="flex items-center gap-2 font-semibold transform capitalize border-0 border-solid border-divider pr-4 md:border-r"
|
||||
>
|
||||
<GameIcon class="h-6 w-6 text-secondary" />
|
||||
{{ instance.loader }} {{ instance.game_version }}
|
||||
</div>
|
||||
<div class="flex items-center gap-2 font-semibold">
|
||||
<TimerIcon class="h-6 w-6 text-secondary" />
|
||||
<template v-if="timePlayed > 0">
|
||||
{{ timePlayedHumanized }}
|
||||
</template>
|
||||
<template v-else> Never played </template>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions>
|
||||
<div class="flex gap-2">
|
||||
<ButtonStyled v-if="instance.install_stage !== 'installed'" color="brand" size="large">
|
||||
<button disabled>Installing...</button>
|
||||
</ButtonStyled>
|
||||
<template v-else>
|
||||
<div class="flex gap-2">
|
||||
<ButtonStyled v-if="playing === true" color="red" size="large">
|
||||
<ButtonStyled v-else-if="playing === true" color="red" size="large">
|
||||
<button @click="stopInstance('InstancePage')">
|
||||
<StopCircleIcon />
|
||||
Stop
|
||||
@ -77,7 +85,6 @@
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</ContentPageHeader>
|
||||
</div>
|
||||
<div class="px-6">
|
||||
@ -106,15 +113,15 @@
|
||||
<ContextMenu ref="options" @option-clicked="handleOptionsClick">
|
||||
<template #play> <PlayIcon /> Play </template>
|
||||
<template #stop> <StopCircleIcon /> Stop </template>
|
||||
<template #add_content> <PlusIcon /> Add Content </template>
|
||||
<template #add_content> <PlusIcon /> Add content </template>
|
||||
<template #edit> <EditIcon /> Edit </template>
|
||||
<template #copy_path> <ClipboardCopyIcon /> Copy Path </template>
|
||||
<template #open_folder> <ClipboardCopyIcon /> Open Folder </template>
|
||||
<template #copy_link> <ClipboardCopyIcon /> Copy Link </template>
|
||||
<template #open_link> <ClipboardCopyIcon /> Open In Modrinth <ExternalIcon /> </template>
|
||||
<template #copy_path> <ClipboardCopyIcon /> Copy path </template>
|
||||
<template #open_folder> <ClipboardCopyIcon /> Open folder </template>
|
||||
<template #copy_link> <ClipboardCopyIcon /> Copy link </template>
|
||||
<template #open_link> <ClipboardCopyIcon /> Open in Modrinth <ExternalIcon /> </template>
|
||||
<template #copy_names><EditIcon />Copy names</template>
|
||||
<template #copy_slugs><HashIcon />Copy slugs</template>
|
||||
<template #copy_links><GlobeIcon />Copy Links</template>
|
||||
<template #copy_links><GlobeIcon />Copy links</template>
|
||||
<template #toggle><EditIcon />Toggle selected</template>
|
||||
<template #disable><XIcon />Disable selected</template>
|
||||
<template #enable><CheckCircleIcon />Enable selected</template>
|
||||
@ -153,8 +160,9 @@ import {
|
||||
UpdatedIcon,
|
||||
MoreVerticalIcon,
|
||||
GameIcon,
|
||||
TimerIcon,
|
||||
} from '@modrinth/assets'
|
||||
import { get, kill, run } from '@/helpers/profile'
|
||||
import { get, get_full_path, kill, run } from '@/helpers/profile'
|
||||
import { get_by_profile_path } from '@/helpers/process'
|
||||
import { process_listener, profile_listener } from '@/helpers/events'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
@ -168,8 +176,13 @@ import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import { handleSevereError } from '@/store/error.js'
|
||||
import { get_project, get_version_many } from '@/helpers/cache.js'
|
||||
import dayjs from 'dayjs'
|
||||
import duration from 'dayjs/plugin/duration'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import ExportModal from '@/components/ui/ExportModal.vue'
|
||||
|
||||
dayjs.extend(duration)
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const router = useRouter()
|
||||
@ -321,10 +334,12 @@ const handleOptionsClick = async (args) => {
|
||||
case 'open_folder':
|
||||
await showProfileInFolder(instance.value.path)
|
||||
break
|
||||
case 'copy_path':
|
||||
await navigator.clipboard.writeText(instance.value.path)
|
||||
case 'copy_path': {
|
||||
const fullPath = await get_full_path(instance.value.path)
|
||||
await navigator.clipboard.writeText(fullPath)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const unlistenProfiles = await profile_listener(async (event) => {
|
||||
@ -347,6 +362,26 @@ const icon = computed(() =>
|
||||
instance.value.icon_path ? convertFileSrc(instance.value.icon_path) : null,
|
||||
)
|
||||
|
||||
const timePlayed = computed(() => {
|
||||
return instance.value.recent_time_played + instance.value.submitted_time_played
|
||||
})
|
||||
|
||||
const timePlayedHumanized = computed(() => {
|
||||
const duration = dayjs.duration(timePlayed.value, 'seconds')
|
||||
const hours = Math.floor(duration.asHours())
|
||||
if (hours >= 1) {
|
||||
return hours + ' hour' + (hours > 1 ? 's' : '')
|
||||
}
|
||||
|
||||
const minutes = Math.floor(duration.asMinutes())
|
||||
if (minutes >= 1) {
|
||||
return minutes + ' minute' + (minutes > 1 ? 's' : '')
|
||||
}
|
||||
|
||||
const seconds = Math.floor(duration.asSeconds())
|
||||
return seconds + ' second' + (seconds > 1 ? 's' : '')
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
unlistenProcesses()
|
||||
unlistenProfiles()
|
||||
|
||||
@ -183,8 +183,8 @@
|
||||
},
|
||||
{
|
||||
id: 'copy-link',
|
||||
shown: item.project !== undefined,
|
||||
action: () => toggleDisableMod(item.data),
|
||||
shown: item.data !== undefined && item.data.slug !== undefined,
|
||||
action: () => copyModLink(item),
|
||||
},
|
||||
{
|
||||
divider: true,
|
||||
@ -674,6 +674,12 @@ const removeMod = async (mod) => {
|
||||
})
|
||||
}
|
||||
|
||||
const copyModLink = async (mod) => {
|
||||
await navigator.clipboard.writeText(
|
||||
`https://modrinth.com/${mod.data.project_type}/${mod.data.slug}`,
|
||||
)
|
||||
}
|
||||
|
||||
const deleteSelected = async () => {
|
||||
for (const project of functionValues.value) {
|
||||
await remove_project(props.instance.path, project.path).catch(handleError)
|
||||
|
||||
@ -149,9 +149,9 @@ export default new createRouter({
|
||||
linkExactActiveClass: 'router-link-exact-active',
|
||||
scrollBehavior() {
|
||||
// Sometimes Vue's scroll behavior is not working as expected, so we need to manually scroll to top (especially on Linux)
|
||||
document.querySelector('.router-view')?.scrollTo(0, 0)
|
||||
document.querySelector('.app-viewport')?.scrollTo(0, 0)
|
||||
return {
|
||||
el: '.router-view',
|
||||
el: '.app-viewport',
|
||||
top: 0,
|
||||
}
|
||||
},
|
||||
|
||||
@ -16,7 +16,7 @@ theseus = { path = "../../packages/app-lib", features = ["tauri"] }
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
tauri = { version = "2.1.1", features = ["devtools", "macos-private-api", "protocol-asset", "unstable"] }
|
||||
tauri = { git = "https://github.com/modrinth/tauri", rev = "9c36dd3", features = ["devtools", "macos-private-api", "protocol-asset", "unstable"] }
|
||||
tauri-plugin-window-state = "2.2.0"
|
||||
tauri-plugin-deep-link = "2.2.0"
|
||||
tauri-plugin-os = "2.2.0"
|
||||
|
||||
@ -103,7 +103,7 @@ pub async fn init_ads_window<R: Runtime>(
|
||||
AD_LINK.parse().unwrap(),
|
||||
),
|
||||
)
|
||||
.initialization_script(LINK_SCRIPT)
|
||||
.initialization_script_for_main_only(LINK_SCRIPT, false)
|
||||
.user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")
|
||||
.zoom_hotkeys_enabled(false)
|
||||
.transparent(true),
|
||||
|
||||
@ -42,9 +42,7 @@
|
||||
Install content to server
|
||||
</h1>
|
||||
</template>
|
||||
<ContentPageHeader v-else>
|
||||
<template #title> Discover content </template>
|
||||
</ContentPageHeader>
|
||||
<ContentPageHeader v-else></ContentPageHeader>
|
||||
<NavTabs v-if="!server" :links="selectableProjectTypes" class="hidden md:flex" />
|
||||
</section>
|
||||
<aside
|
||||
@ -342,7 +340,11 @@ const tags = useTags();
|
||||
const flags = useFeatureFlags();
|
||||
const auth = await useAuth();
|
||||
|
||||
const projectType = ref({ id: "mod", display: "mod", actual: "mod" });
|
||||
const projectType = computed(() =>
|
||||
tags.value.projectTypes.find(
|
||||
(x) => x.id === route.path.replaceAll(/^\/|s\/?$/g, ""), // Removes prefix `/` and suffixes `s` and `s/`
|
||||
),
|
||||
);
|
||||
const projectTypes = computed(() => [projectType.value.id]);
|
||||
|
||||
const server = ref();
|
||||
@ -506,10 +508,6 @@ async function serverInstall(project) {
|
||||
project.installing = false;
|
||||
}
|
||||
|
||||
projectType.value = tags.value.projectTypes.find(
|
||||
(x) => x.id === route.path.replaceAll(/^\/|s\/?$/g, ""), // Removes prefix `/` and suffixes `s` and `s/`
|
||||
);
|
||||
|
||||
const noLoad = ref(false);
|
||||
const {
|
||||
data: rawResults,
|
||||
|
||||
@ -118,7 +118,7 @@ pub async fn profile_create(
|
||||
&state.file_watcher,
|
||||
&state.directories,
|
||||
)
|
||||
.await?;
|
||||
.await;
|
||||
|
||||
profile.upsert(&state.pool).await?;
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ pub async fn init_watcher() -> crate::Result<FileWatcher> {
|
||||
pub(crate) async fn watch_profiles_init(
|
||||
watcher: &FileWatcher,
|
||||
dirs: &DirectoryInfo,
|
||||
) -> crate::Result<()> {
|
||||
) {
|
||||
if let Ok(profiles_dir) = std::fs::read_dir(dirs.profiles_dir()) {
|
||||
for profile_dir in profiles_dir {
|
||||
if let Ok(file_name) = profile_dir.map(|x| x.file_name()) {
|
||||
@ -96,20 +96,18 @@ pub(crate) async fn watch_profiles_init(
|
||||
continue;
|
||||
};
|
||||
|
||||
watch_profile(file_name, watcher, dirs).await?;
|
||||
watch_profile(file_name, watcher, dirs).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn watch_profile(
|
||||
profile_path: &str,
|
||||
watcher: &FileWatcher,
|
||||
dirs: &DirectoryInfo,
|
||||
) -> crate::Result<()> {
|
||||
) {
|
||||
let profile_path = dirs.profiles_dir().join(profile_path);
|
||||
|
||||
if profile_path.exists() && profile_path.is_dir() {
|
||||
@ -120,15 +118,25 @@ pub(crate) async fn watch_profile(
|
||||
let path = profile_path.join(folder);
|
||||
|
||||
if !path.exists() && !path.is_symlink() {
|
||||
crate::util::io::create_dir_all(&path).await?;
|
||||
if let Err(e) = crate::util::io::create_dir_all(&path).await {
|
||||
tracing::error!(
|
||||
"Failed to create directory for watcher {path:?}: {e}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut watcher = watcher.write().await;
|
||||
watcher.watcher().watch(&path, RecursiveMode::Recursive)?;
|
||||
if let Err(e) =
|
||||
watcher.watcher().watch(&path, RecursiveMode::Recursive)
|
||||
{
|
||||
tracing::error!(
|
||||
"Failed to watch directory for watcher {path:?}: {e}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn crash_task(path: String) {
|
||||
|
||||
@ -146,7 +146,7 @@ impl State {
|
||||
let discord_rpc = DiscordGuard::init()?;
|
||||
|
||||
let file_watcher = fs_watcher::init_watcher().await?;
|
||||
fs_watcher::watch_profiles_init(&file_watcher, &directories).await?;
|
||||
fs_watcher::watch_profiles_init(&file_watcher, &directories).await;
|
||||
|
||||
let process_manager = ProcessManager::new();
|
||||
|
||||
|
||||
1
packages/assets/icons/timer.svg
Normal file
1
packages/assets/icons/timer.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" x2="14" y1="2" y2="2"/><line x1="12" x2="15" y1="14" y2="11"/><circle cx="12" cy="14" r="8"/></svg>
|
||||
|
After Width: | Height: | Size: 295 B |
@ -180,6 +180,7 @@ import _CPUIcon from './icons/cpu.svg?component'
|
||||
import _DBIcon from './icons/db.svg?component'
|
||||
import _LoaderIcon from './icons/loader.svg?component'
|
||||
import _ImportIcon from './icons/import.svg?component'
|
||||
import _TimerIcon from './icons/timer.svg?component'
|
||||
|
||||
// Editor Icons
|
||||
import _BoldIcon from './icons/bold.svg?component'
|
||||
@ -381,3 +382,4 @@ export const DBIcon = _DBIcon
|
||||
export const LoaderIcon = _LoaderIcon
|
||||
export const ImportIcon = _ImportIcon
|
||||
export const CardIcon = _CardIcon
|
||||
export const TimerIcon = _TimerIcon
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
ref="dropdown"
|
||||
no-auto-focus
|
||||
:aria-id="dropdownId || null"
|
||||
@hide="focusTrigger"
|
||||
@apply-hide="focusTrigger"
|
||||
@apply-show="focusMenuChild"
|
||||
>
|
||||
<button ref="trigger" v-bind="$attrs" v-tooltip="tooltip">
|
||||
|
||||
@ -83,7 +83,7 @@ function setSelected(value: boolean) {
|
||||
<ContentListItem
|
||||
v-model="selectionStates[ref.filename]"
|
||||
:item="ref"
|
||||
:last="false"
|
||||
:last="ref === items.length - 1"
|
||||
class="mb-2"
|
||||
@update:model-value="updateSelection"
|
||||
>
|
||||
|
||||
@ -534,6 +534,10 @@ export function useSearch(
|
||||
currentPage.value = Number(page)
|
||||
readParams.add('page')
|
||||
})
|
||||
loadQueryParam(['q'], (queryVal) => {
|
||||
query.value = String(queryVal)
|
||||
readParams.add('q')
|
||||
})
|
||||
|
||||
for (const key of Object.keys(route.query).filter((key) => !readParams.has(key))) {
|
||||
const type = filters.value.find((type) => type.query_param === key)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user