Compare commits

..

53 Commits

Author SHA1 Message Date
coolbot100s
4b73aee56a fix method typo 2025-08-05 12:59:06 -07:00
coolbot100s
b4339350e0 Merge branch 'main' into cal/dev-124-project-validation 2025-08-05 12:56:57 -07:00
coolbot100s
de11629402 lint fix 2025-08-05 12:48:52 -07:00
coolbot100s
29e4c6d18a correct vocabulary for resolutions tags warning and sort tags list in resolution tags nag 2025-08-05 12:46:42 -07:00
coolbot100s
474e482474 fix tags warning, and link shorteners and misused discord warnings to link settings page, reword some warnings. 2025-08-05 12:34:02 -07:00
Calum H.
ca48107e7e fix: formatjs 2025-08-05 11:24:14 +01:00
coolbot100s
1f4b43cf0d fix locale 2025-08-04 22:25:17 -07:00
coolbot100s
c850a3438c Merge branch 'cal/dev-124-project-validation' of https://github.com/modrinth/code into cal/dev-124-project-validation 2025-08-04 15:01:04 -07:00
coolbot100s
9c6c368408 updates to tags checking and rest of the nag titles 2025-08-04 15:00:58 -07:00
IMB11
87dcb04c43 Merge branch 'main' into cal/dev-124-project-validation 2025-08-04 21:56:12 +01:00
IMB11
8c0afd1183 feat: update readme 2025-08-04 18:41:14 +01:00
coolbot100s
9db2fd33c6 Merge branch 'cal/dev-124-project-validation' of https://github.com/modrinth/code into cal/dev-124-project-validation 2025-08-04 10:36:55 -07:00
coolbot100s
63787eebb7 Tweak core and description nag titles, change image accessability nag logic. 2025-08-04 10:36:51 -07:00
IMB11
02bbac00a8 feat: key + sort nags by type 2025-08-04 18:24:13 +01:00
coolbot100s
f15ceafd5f update links.ts 2025-08-02 18:03:47 -07:00
IMB11
56699fc9b5 fix: lint issues 2025-08-02 12:48:25 +01:00
IMB11
c470eea9ac Merge branch 'main' into cal/dev-124-project-validation 2025-08-02 12:41:49 +01:00
IMB11
88f653384e Merge branch 'main' into cal/dev-124-project-validation 2025-08-01 13:08:57 +01:00
IMB11
f606b20109 Merge branch 'main' into cal/dev-124-project-validation
Signed-off-by: IMB11 <hendersoncal117@gmail.com>
2025-07-31 13:45:17 +01:00
coolbot100s
26c81e3803 Correct plugin project type checking 2025-07-30 00:11:54 -07:00
coolbot100s
f720438bdb refactor link checking helper functions, prevent misuse of dsc links, prevent link shortener usage, check if source required licensed projects have additional files, bump this check back to required. 2025-07-29 17:00:26 -07:00
coolbot100s
2806d20e17 bump source publication nag to warn until additional files can be checked. 2025-07-29 14:26:48 -07:00
coolbot100s
b5f44ac5cd Merge branch 'cal/dev-124-project-validation' of https://github.com/modrinth/code into cal/dev-124-project-validation 2025-07-29 13:30:25 -07:00
IMB11
ad1fed91cf fix: description nag 2025-07-29 13:23:16 +01:00
coolbot100s
ba0b09d9e3 Tweak links nags adding project type checking for source publication check, make description nag tonally consistent. 2025-07-29 00:44:59 -07:00
coolbot100s
9dbc9607f7 Description nag rephrasing and tweaks 2025-07-29 00:09:00 -07:00
coolbot100s
f66bafc06b Remove redundant sentanceEnders check to reduce false positive. 2025-07-28 21:04:55 -07:00
coolbot100s
1d34a5989e Modify character limit numbers 2025-07-28 19:11:21 -07:00
coolbot100s
c594e32bc7 Rephrase a few core nags 2025-07-28 19:02:37 -07:00
IMB11
dc258de3c2 fix: issues 2025-07-28 17:06:57 +01:00
IMB11
54cfe29f7d fix: summary char min 2025-07-28 16:55:47 +01:00
IMB11
5c487795c4 refactor: inline i18n 2025-07-28 16:51:31 +01:00
IMB11
b87fb1de00 fix: locale issues 2025-07-28 16:41:30 +01:00
IMB11
fe3d360215 Merge branch 'main' into cal/dev-124-project-validation
Signed-off-by: IMB11 <hendersoncal117@gmail.com>
2025-07-28 16:33:03 +01:00
IMB11
89351b4be4 Merge branch 'main' into cal/dev-124-project-validation 2025-07-21 18:35:59 +01:00
Prospector
1261c7e7c9 Merge branch 'main' into cal/dev-124-project-validation 2025-07-16 15:22:38 -07:00
IMB11
252b7bf965 Merge branch 'main' into cal/dev-124-project-validation 2025-07-16 20:54:21 +01:00
IMB11
28c8b59820 fix: minecraft title clause update 2025-07-16 20:52:01 +01:00
Calum
2f1a31a9e4 feat: impl intl 2025-07-14 13:34:01 +01:00
Calum
35636f7c00 feat: start on i18nifying nags 2025-07-14 13:19:56 +01:00
Calum
bddf73119d fix: issues 2025-07-13 15:12:34 +01:00
Calum
24ca268aba Merge branch 'cal/dev-124-project-validation' of https://github.com/modrinth/code into cal/dev-124-project-validation 2025-07-13 15:10:07 +01:00
Calum
4934fb1e0d fix: lint 2025-07-13 15:09:56 +01:00
IMB11
4a7e8e98b0 Merge branch 'main' into cal/dev-124-project-validation 2025-07-13 15:08:15 +01:00
Calum
2f1627c000 fix: lint issues 2025-07-13 15:06:29 +01:00
Calum
debcb57f47 feat: tags validations 2025-07-13 15:01:43 +01:00
Calum
27caf336cc fix: links page + add more validations 2025-07-13 14:34:56 +01:00
Calum
729d584757 feat: start work implementing validation checks using new nag system 2025-07-12 22:02:48 +01:00
Calum
59ad8eb426 feat: re add submitting/re-submit nags 2025-07-11 21:12:56 +01:00
Calum
d33b06ea55 feat: continue work 2025-07-11 20:07:26 +01:00
Calum
b2978096fd fix: shouldShow issues 2025-07-11 17:21:45 +01:00
Calum
bcfceecf1b feat: start on frontend impl 2025-07-11 17:21:43 +01:00
Calum
b98c1fe7b8 feat: set up typed nag (validators) system 2025-07-11 17:21:37 +01:00
534 changed files with 20343 additions and 17718 deletions

View File

@@ -1,2 +1,22 @@
import config from '@modrinth/tooling-config/eslint/nuxt.mjs'
export default config
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
import { fixupPluginRules } from '@eslint/compat'
import turboPlugin from 'eslint-plugin-turbo'
export default createConfigForNuxt().append([
{
name: 'turbo',
plugins: {
turbo: fixupPluginRules(turboPlugin),
},
rules: {
'turbo/no-undeclared-env-vars': 'error',
},
},
{
name: 'modrinth',
rules: {
'vue/html-self-closing': 'off',
'vue/multi-word-component-names': 'off',
},
},
])

View File

@@ -41,7 +41,6 @@
"vue-virtual-scroller": "v2.0.0-beta.8"
},
"devDependencies": {
"@modrinth/tooling-config": "workspace:*",
"@eslint/compat": "^1.1.1",
"@formatjs/cli": "^6.2.12",
"@nuxt/eslint-config": "^0.5.6",
@@ -49,11 +48,13 @@
"@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.4.19",
"eslint": "^9.9.1",
"eslint-config-custom": "workspace:*",
"eslint-plugin-turbo": "^2.5.4",
"postcss": "^8.4.39",
"prettier": "^3.2.5",
"sass": "^1.74.1",
"tailwindcss": "^3.4.4",
"tsconfig": "workspace:*",
"typescript": "^5.5.4",
"vite": "^5.4.6",
"vue-tsc": "^2.1.6"

View File

@@ -1,4 +1,6 @@
<script setup>
import { computed, onMounted, onUnmounted, ref, watch, provide } from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
import {
ArrowBigUpDashIcon,
ChangeSkinIcon,
@@ -11,69 +13,65 @@ import {
LogOutIcon,
MaximizeIcon,
MinimizeIcon,
NewspaperIcon,
PlusIcon,
RestoreIcon,
RightArrowIcon,
SettingsIcon,
WorldIcon,
XIcon,
NewspaperIcon,
} from '@modrinth/assets'
import {
Avatar,
Button,
ButtonStyled,
NewsArticleCard,
Notifications,
OverflowMenu,
NewsArticleCard,
} from '@modrinth/ui'
import { renderString } from '@modrinth/utils'
import { getVersion } from '@tauri-apps/api/app'
import { invoke } from '@tauri-apps/api/core'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { openUrl } from '@tauri-apps/plugin-opener'
import { type } from '@tauri-apps/plugin-os'
import { check } from '@tauri-apps/plugin-updater'
import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'
import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
import { useLoading, useTheming } from '@/store/state'
import ModrinthAppLogo from '@/assets/modrinth_app.svg?component'
import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue'
import AccountsCard from '@/components/ui/AccountsCard.vue'
import Breadcrumbs from '@/components/ui/Breadcrumbs.vue'
import ErrorModal from '@/components/ui/ErrorModal.vue'
import FriendsList from '@/components/ui/friends/FriendsList.vue'
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
import ModInstallModal from '@/components/ui/install_flow/ModInstallModal.vue'
import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue'
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue'
import NavButton from '@/components/ui/NavButton.vue'
import PromotionWrapper from '@/components/ui/PromotionWrapper.vue'
import QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue'
import { get } from '@/helpers/settings.ts'
import Breadcrumbs from '@/components/ui/Breadcrumbs.vue'
import RunningAppBar from '@/components/ui/RunningAppBar.vue'
import SplashScreen from '@/components/ui/SplashScreen.vue'
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
import { hide_ads_window, init_ads_window } from '@/helpers/ads.js'
import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics'
import { get_user } from '@/helpers/cache.js'
import { command_listener, warning_listener } from '@/helpers/events.js'
import { useFetch } from '@/helpers/fetch.js'
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.js'
import { get } from '@/helpers/settings.ts'
import { get_opening_command, initialize_state } from '@/helpers/state'
import { getOS, isDev, restartApp } from '@/helpers/utils.js'
import { useError } from '@/store/error.js'
import { useInstall } from '@/store/install.js'
import ErrorModal from '@/components/ui/ErrorModal.vue'
import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue'
import { handleError, useNotifications } from '@/store/notifications.js'
import { useLoading, useTheming } from '@/store/state'
import { command_listener, warning_listener } from '@/helpers/events.js'
import { type } from '@tauri-apps/plugin-os'
import { getOS, isDev, restartApp } from '@/helpers/utils.js'
import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { getVersion } from '@tauri-apps/api/app'
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import { create_profile_and_install_from_file } from './helpers/pack'
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
import { useError } from '@/store/error.js'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
import ModInstallModal from '@/components/ui/install_flow/ModInstallModal.vue'
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
import { useInstall } from '@/store/install.js'
import { invoke } from '@tauri-apps/api/core'
import { get_opening_command, initialize_state } from '@/helpers/state'
import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'
import { renderString } from '@modrinth/utils'
import { useFetch } from '@/helpers/fetch.js'
import { check } from '@tauri-apps/plugin-updater'
import NavButton from '@/components/ui/NavButton.vue'
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.js'
import { get_user } from '@/helpers/cache.js'
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue'
import PromotionWrapper from '@/components/ui/PromotionWrapper.vue'
import { hide_ads_window, init_ads_window } from '@/helpers/ads.js'
import FriendsList from '@/components/ui/friends/FriendsList.vue'
import { openUrl } from '@tauri-apps/plugin-opener'
import QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue'
import { get_available_capes, get_available_skins } from './helpers/skins'
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
const themeStore = useTheming()

View File

@@ -1,18 +1,18 @@
export { default as ATLauncherIcon } from './atlauncher.svg'
export { default as BuyMeACoffeeIcon } from './bmac.svg'
export { default as DiscordIcon } from './discord.svg'
export { default as GDLauncherIcon } from './gdlauncher.png'
export { default as GithubIcon } from './github.svg'
export { default as GitLabIcon } from './gitlab.svg'
export { default as GoogleIcon } from './google.svg'
export { default as KoFiIcon } from './kofi.svg'
export { default as MastodonIcon } from './mastodon.svg'
export { default as MicrosoftIcon } from './microsoft.svg'
export { default as MultiMCIcon } from './multimc.webp'
export { default as OpenCollectiveIcon } from './opencollective.svg'
export { default as PatreonIcon } from './patreon.svg'
export { default as PaypalIcon } from './paypal.svg'
export { default as PrismIcon } from './prism.svg'
export { default as RedditIcon } from './reddit.svg'
export { default as SteamIcon } from './steam.svg'
export { default as OpenCollectiveIcon } from './opencollective.svg'
export { default as TwitterIcon } from './twitter.svg'
export { default as GithubIcon } from './github.svg'
export { default as MastodonIcon } from './mastodon.svg'
export { default as RedditIcon } from './reddit.svg'
export { default as GoogleIcon } from './google.svg'
export { default as MicrosoftIcon } from './microsoft.svg'
export { default as SteamIcon } from './steam.svg'
export { default as GitLabIcon } from './gitlab.svg'
export { default as ATLauncherIcon } from './atlauncher.svg'
export { default as GDLauncherIcon } from './gdlauncher.png'
export { default as MultiMCIcon } from './multimc.webp'
export { default as PrismIcon } from './prism.svg'

View File

@@ -1,9 +1,9 @@
export { default as AddProjectImage } from './add-project.svg'
export { default as SwapIcon } from './arrow-left-right.svg'
export { default as ToggleIcon } from './toggle.svg'
export { default as PackageIcon } from './package.svg'
export { default as VersionIcon } from './milestone.svg'
export { default as TextInputIcon } from './text-cursor-input.svg'
export { default as AddProjectImage } from './add-project.svg'
export { default as NewInstanceImage } from './new-instance.svg'
export { default as MenuIcon } from './menu.svg'
export { default as ChatIcon } from './messages-square.svg'
export { default as VersionIcon } from './milestone.svg'
export { default as NewInstanceImage } from './new-instance.svg'
export { default as PackageIcon } from './package.svg'
export { default as TextInputIcon } from './text-cursor-input.svg'
export { default as ToggleIcon } from './toggle.svg'

View File

@@ -1,25 +1,24 @@
<script setup>
import Instance from '@/components/ui/Instance.vue'
import { computed, ref } from 'vue'
import {
ClipboardCopyIcon,
EyeIcon,
FolderOpenIcon,
PlayIcon,
PlusIcon,
SearchIcon,
StopCircleIcon,
TrashIcon,
StopCircleIcon,
EyeIcon,
SearchIcon,
XIcon,
} from '@modrinth/assets'
import { Button, DropdownSelect } from '@modrinth/ui'
import { formatCategoryHeader } from '@modrinth/utils'
import dayjs from 'dayjs'
import { computed, ref } from 'vue'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import Instance from '@/components/ui/Instance.vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import dayjs from 'dayjs'
import { duplicate, remove } from '@/helpers/profile.js'
import { handleError } from '@/store/notifications.js'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
const props = defineProps({
instances: {

View File

@@ -1,6 +1,5 @@
<script setup>
import { computed, onBeforeUnmount, ref, watch } from 'vue'
import { useLoading } from '@/store/state.js'
const props = defineProps({

View File

@@ -1,32 +1,31 @@
<script setup>
import {
ClipboardCopyIcon,
DownloadIcon,
ExternalIcon,
EyeIcon,
FolderOpenIcon,
GlobeIcon,
PlayIcon,
PlusIcon,
StopCircleIcon,
TrashIcon,
DownloadIcon,
GlobeIcon,
StopCircleIcon,
ExternalIcon,
EyeIcon,
} from '@modrinth/assets'
import { HeadingLink } from '@modrinth/ui'
import { openUrl } from '@tauri-apps/plugin-opener'
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import Instance from '@/components/ui/Instance.vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import Instance from '@/components/ui/Instance.vue'
import { computed, onMounted, onUnmounted, ref } from 'vue'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import ProjectCard from '@/components/ui/ProjectCard.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_by_profile_path } from '@/helpers/process.js'
import { handleError } from '@/store/notifications.js'
import { duplicate, kill, remove, run } from '@/helpers/profile.js'
import { useRouter } from 'vue-router'
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 { handleError } from '@/store/notifications.js'
import { openUrl } from '@tauri-apps/plugin-opener'
import { HeadingLink } from '@modrinth/ui'
const router = useRouter()

View File

@@ -73,23 +73,22 @@
</template>
<script setup>
import { DropdownIcon, LogInIcon, PlusIcon, SpinnerIcon, TrashIcon } from '@modrinth/assets'
import { DropdownIcon, PlusIcon, TrashIcon, LogInIcon, SpinnerIcon } from '@modrinth/assets'
import { Avatar, Button, Card } from '@modrinth/ui'
import { computed, onBeforeUnmount, onMounted, onUnmounted, ref } from 'vue'
import { trackEvent } from '@/helpers/analytics'
import { ref, computed, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
import {
get_default_user,
login as login_flow,
users,
remove_user,
set_default_user,
users,
login as login_flow,
get_default_user,
} from '@/helpers/auth'
import { process_listener } from '@/helpers/events'
import { getPlayerHeadUrl } from '@/helpers/rendering/batch-skin-renderer.ts'
import { get_available_skins } from '@/helpers/skins'
import { handleSevereError } from '@/store/error.js'
import { handleError } from '@/store/state.js'
import { trackEvent } from '@/helpers/analytics'
import { process_listener } from '@/helpers/events'
import { handleSevereError } from '@/store/error.js'
import { get_available_skins } from '@/helpers/skins'
import { getPlayerHeadUrl } from '@/helpers/rendering/batch-skin-renderer.ts'
defineProps({
mode: {

View File

@@ -1,11 +1,10 @@
<script setup lang="ts">
import { DropdownIcon, FolderOpenIcon, PlusIcon } from '@modrinth/assets'
import { DropdownIcon, PlusIcon, FolderOpenIcon } from '@modrinth/assets'
import { ButtonStyled, OverflowMenu } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { useRouter } from 'vue-router'
import { add_project_from_path } from '@/helpers/profile.js'
import { handleError } from '@/store/notifications.js'
import { useRouter } from 'vue-router'
const props = defineProps({
instance: {

View File

@@ -42,12 +42,11 @@
</template>
<script setup>
import { ChevronLeftIcon, ChevronRightIcon } from '@modrinth/assets'
import { ChevronRightIcon, ChevronLeftIcon } from '@modrinth/assets'
import { Button } from '@modrinth/ui'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useBreadcrumbs } from '@/store/breadcrumbs'
import { useRoute } from 'vue-router'
import { computed } from 'vue'
const route = useRoute()

View File

@@ -1,24 +1,23 @@
<script setup>
import {
CheckIcon,
CopyIcon,
DropdownIcon,
XIcon,
HammerIcon,
LogInIcon,
UpdatedIcon,
XIcon,
CopyIcon,
} from '@modrinth/assets'
import { ButtonStyled, Collapsible } from '@modrinth/ui'
import { computed, ref } from 'vue'
import { ChatIcon } from '@/assets/icons'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { ButtonStyled, Collapsible } from '@modrinth/ui'
import { ref, computed } from 'vue'
import { login as login_flow, set_default_user } from '@/helpers/auth.js'
import { install } from '@/helpers/profile.js'
import { cancel_directory_change } from '@/helpers/settings.ts'
import { handleSevereError } from '@/store/error.js'
import { handleError } from '@/store/notifications.js'
import { handleSevereError } from '@/store/error.js'
import { cancel_directory_change } from '@/helpers/settings.ts'
import { install } from '@/helpers/profile.js'
import { trackEvent } from '@/helpers/analytics'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
const errorModal = ref()
const error = ref()

View File

@@ -1,13 +1,12 @@
<script setup>
import { PlusIcon, XIcon } from '@modrinth/assets'
import { XIcon, PlusIcon } from '@modrinth/assets'
import { Button, Checkbox } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref } from 'vue'
import { PackageIcon, VersionIcon } from '@/assets/icons'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { ref } from 'vue'
import { export_profile_mrpack, get_pack_export_candidates } from '@/helpers/profile.js'
import { open } from '@tauri-apps/plugin-dialog'
import { handleError } from '@/store/notifications.js'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
const props = defineProps({
instance: {

View File

@@ -1,4 +1,6 @@
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import {
DownloadIcon,
GameIcon,
@@ -9,17 +11,14 @@ import {
} from '@modrinth/assets'
import { Avatar, ButtonStyled, useRelativeTime } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import dayjs from 'dayjs'
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { trackEvent } from '@/helpers/analytics'
import { process_listener } from '@/helpers/events'
import { get_by_profile_path } from '@/helpers/process'
import { finish_install, kill, run } from '@/helpers/profile'
import { get_by_profile_path } from '@/helpers/process'
import { process_listener } from '@/helpers/events'
import { handleError } from '@/store/state.js'
import { showProfileInFolder } from '@/helpers/utils.js'
import { handleSevereError } from '@/store/error.js'
import { handleError } from '@/store/state.js'
import { trackEvent } from '@/helpers/analytics'
import dayjs from 'dayjs'
const formatRelativeTime = useRelativeTime()

View File

@@ -197,6 +197,7 @@
</template>
<script setup>
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import {
CodeIcon,
FolderOpenIcon,
@@ -208,25 +209,23 @@ import {
XIcon,
} from '@modrinth/assets'
import { Avatar, Button, Checkbox, Chips } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import { open } from '@tauri-apps/plugin-dialog'
import { computed, onUnmounted, ref, shallowRef } from 'vue'
import { get_loaders } from '@/helpers/tags'
import { create } from '@/helpers/profile'
import { open } from '@tauri-apps/plugin-dialog'
import { convertFileSrc } from '@tauri-apps/api/core'
import { get_game_versions, get_loader_versions } from '@/helpers/metadata'
import { handleError } from '@/store/notifications.js'
import Multiselect from 'vue-multiselect'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import ProgressBar from '@/components/ui/ProgressBar.vue'
import { trackEvent } from '@/helpers/analytics'
import { create_profile_and_install_from_file } from '@/helpers/pack.js'
import {
get_default_launcher_path,
get_importable_instances,
import_instance,
} from '@/helpers/import.js'
import { get_game_versions, get_loader_versions } from '@/helpers/metadata'
import { create_profile_and_install_from_file } from '@/helpers/pack.js'
import { create } from '@/helpers/profile'
import { get_loaders } from '@/helpers/tags'
import { handleError } from '@/store/notifications.js'
import ProgressBar from '@/components/ui/ProgressBar.vue'
import { getCurrentWebview } from '@tauri-apps/api/webview'
const profile_name = ref('')
const game_version = ref('')

View File

@@ -1,8 +1,8 @@
<script setup lang="ts">
import { convertFileSrc } from '@tauri-apps/api/core'
import { formatCategory } from '@modrinth/utils'
import { GameIcon, LeftArrowIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled } from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { convertFileSrc } from '@tauri-apps/api/core'
type Instance = {
game_version: string

View File

@@ -35,14 +35,13 @@
</ModalWrapper>
</template>
<script setup>
import { CheckIcon, PlusIcon, XIcon } from '@modrinth/assets'
import { PlusIcon, CheckIcon, XIcon } from '@modrinth/assets'
import { Button } from '@modrinth/ui'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { find_filtered_jres } from '@/helpers/jre.js'
import { handleError } from '@/store/notifications.js'
import { trackEvent } from '@/helpers/analytics'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
const chosenInstallOptions = ref([])
const detectJavaModal = ref(null)

View File

@@ -53,21 +53,20 @@
<script setup>
import {
CheckIcon,
DownloadIcon,
FolderSearchIcon,
PlayIcon,
SearchIcon,
PlayIcon,
CheckIcon,
XIcon,
FolderSearchIcon,
DownloadIcon,
} from '@modrinth/assets'
import { Button } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref } from 'vue'
import JavaDetectionModal from '@/components/ui/JavaDetectionModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { auto_install_java, find_filtered_jres, get_jre, test_jre } from '@/helpers/jre.js'
import { ref } from 'vue'
import { open } from '@tauri-apps/plugin-dialog'
import JavaDetectionModal from '@/components/ui/JavaDetectionModal.vue'
import { handleError } from '@/store/state.js'
import { trackEvent } from '@/helpers/analytics'
const props = defineProps({
version: {

View File

@@ -1,12 +1,11 @@
<script setup>
import { CheckIcon } from '@modrinth/assets'
import { Badge, Button } from '@modrinth/ui'
import { Button, Badge } from '@modrinth/ui'
import { computed, ref } from 'vue'
import { SwapIcon } from '@/assets/icons/index.js'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { update_managed_modrinth_version } from '@/helpers/profile'
import { releaseColor } from '@/helpers/utils'
import { SwapIcon } from '@/assets/icons/index.js'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
const props = defineProps({
versions: {

View File

@@ -30,7 +30,7 @@
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import type { RouteLocationRaw } from 'vue-router'
import { RouterLink, useRoute } from 'vue-router'
import { useRoute, RouterLink } from 'vue-router'
const route = useRoute()

View File

@@ -1,10 +1,10 @@
<script setup>
import { DownloadIcon, HeartIcon, TagIcon } from '@modrinth/assets'
import { Avatar, TagItem } from '@modrinth/ui'
import { formatCategory, formatNumber } from '@modrinth/utils'
import { DownloadIcon, HeartIcon, TagIcon } from '@modrinth/assets'
import { formatNumber, formatCategory } from '@modrinth/utils'
import { computed } from 'vue'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { computed } from 'vue'
import { useRouter } from 'vue-router'
dayjs.extend(relativeTime)

View File

@@ -1,6 +1,5 @@
<script setup>
import { onMounted, ref } from 'vue'
import { ref, onMounted } from 'vue'
import { init_ads_window } from '@/helpers/ads.js'
const adsWrapper = ref(null)

View File

@@ -1,14 +1,13 @@
<script setup>
import { SpinnerIcon } from '@modrinth/assets'
import { Avatar } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import dayjs from 'dayjs'
import { onUnmounted, ref } from 'vue'
import NavButton from '@/components/ui/NavButton.vue'
import { profile_listener } from '@/helpers/events.js'
import { list } from '@/helpers/profile'
import { handleError } from '@/store/notifications'
import dayjs from 'dayjs'
import { onUnmounted, ref } from 'vue'
import { profile_listener } from '@/helpers/events.js'
import NavButton from '@/components/ui/NavButton.vue'
import { Avatar } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { SpinnerIcon } from '@modrinth/assets'
const recentInstances = ref([])
const getInstances = async () => {

View File

@@ -96,22 +96,21 @@
<script setup>
import {
DownloadIcon,
DropdownIcon,
StopCircleIcon,
TerminalSquareIcon,
DropdownIcon,
UnplugIcon,
} from '@modrinth/assets'
import { Button, ButtonStyled, Card } from '@modrinth/ui'
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import ProgressBar from '@/components/ui/ProgressBar.vue'
import { trackEvent } from '@/helpers/analytics'
import { loading_listener, process_listener } from '@/helpers/events'
import { get_all as getRunningProcesses, kill as killProcess } from '@/helpers/process'
import { get_many } from '@/helpers/profile.js'
import { loading_listener, process_listener } from '@/helpers/events'
import { useRouter } from 'vue-router'
import { progress_bars_list } from '@/helpers/state.js'
import ProgressBar from '@/components/ui/ProgressBar.vue'
import { handleError } from '@/store/notifications.js'
import { get_many } from '@/helpers/profile.js'
import { trackEvent } from '@/helpers/analytics'
const router = useRouter()
const card = ref(null)

View File

@@ -117,15 +117,14 @@
</template>
<script setup>
import { CheckIcon, DownloadIcon, HeartIcon, PlusIcon, TagsIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled } from '@modrinth/ui'
import { formatCategory, formatNumber } from '@modrinth/utils'
import { TagsIcon, DownloadIcon, HeartIcon, PlusIcon, CheckIcon } from '@modrinth/assets'
import { ButtonStyled, Avatar } from '@modrinth/ui'
import { formatNumber, formatCategory } from '@modrinth/utils'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ref, computed } from 'vue'
import { install as installVersion } from '@/store/install.js'
import { useRouter } from 'vue-router'
dayjs.extend(relativeTime)
const router = useRouter()

View File

@@ -82,12 +82,11 @@
</template>
<script setup>
import { MaximizeIcon, MinimizeIcon, XIcon } from '@modrinth/assets'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { ref, watch } from 'vue'
import ProgressBar from '@/components/ui/ProgressBar.vue'
import { loading_listener } from '@/helpers/events.js'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { XIcon, MaximizeIcon, MinimizeIcon } from '@modrinth/assets'
import { getOS } from '@/helpers/utils.js'
import { useLoading } from '@/store/loading.js'

View File

@@ -1,13 +1,12 @@
<script setup>
import { Button } from '@modrinth/ui'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import SearchCard from '@/components/ui/SearchCard.vue'
import { get_project, get_version } from '@/helpers/cache.js'
import { get_categories } from '@/helpers/tags.js'
import { install as installVersion } from '@/store/install.js'
import { handleError } from '@/store/notifications.js'
import { get_version, get_project } from '@/helpers/cache.js'
import { install as installVersion } from '@/store/install.js'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
const confirmModal = ref(null)
const project = ref(null)

View File

@@ -1,23 +1,22 @@
<script setup lang="ts">
import { Avatar, ButtonStyled, OverflowMenu, useRelativeTime } from '@modrinth/ui'
import {
MailIcon,
UserPlusIcon,
MoreVerticalIcon,
MailIcon,
SettingsIcon,
TrashIcon,
UserPlusIcon,
XIcon,
} from '@modrinth/assets'
import { Avatar, ButtonStyled, OverflowMenu, useRelativeTime } from '@modrinth/ui'
import { ref, onUnmounted, watch, computed } from 'vue'
import { friend_listener } from '@/helpers/events'
import { friends, friend_statuses, add_friend, remove_friend } from '@/helpers/friends'
import { get_user_many } from '@/helpers/cache'
import { handleError } from '@/store/notifications.js'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import { computed, onUnmounted, ref, watch } from 'vue'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { get_user_many } from '@/helpers/cache'
import { friend_listener } from '@/helpers/events'
import { add_friend, friend_statuses, friends, remove_friend } from '@/helpers/friends'
import { handleError } from '@/store/notifications.js'
const formatRelativeTime = useRelativeTime()

View File

@@ -56,16 +56,15 @@
</template>
<script setup>
import { DownloadIcon, XIcon } from '@modrinth/assets'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { XIcon, DownloadIcon } from '@modrinth/assets'
import { Button } from '@modrinth/ui'
import { formatCategory } from '@modrinth/utils'
import { ref } from 'vue'
import Multiselect from 'vue-multiselect'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { add_project_from_version as installMod } from '@/helpers/profile'
import { ref } from 'vue'
import { handleError } from '@/store/state.js'
import { trackEvent } from '@/helpers/analytics'
import Multiselect from 'vue-multiselect'
const instance = ref(null)
const project = ref(null)

View File

@@ -1,12 +1,11 @@
<script setup>
import { DownloadIcon, XIcon } from '@modrinth/assets'
import { Button } from '@modrinth/ui'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { create_profile_and_install as pack_install } from '@/helpers/pack'
import { ref } from 'vue'
import { trackEvent } from '@/helpers/analytics'
import { handleError } from '@/store/state.js'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
const versionId = ref()
const project = ref()

View File

@@ -1,29 +1,28 @@
<script setup>
import {
CheckIcon,
DownloadIcon,
PlusIcon,
RightArrowIcon,
UploadIcon,
XIcon,
RightArrowIcon,
CheckIcon,
} from '@modrinth/assets'
import { Avatar, Button, Card } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { open } from '@tauri-apps/plugin-dialog'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import {
add_project_from_version as installMod,
check_installed,
create,
get,
list,
create,
} from '@/helpers/profile'
import { open } from '@tauri-apps/plugin-dialog'
import { installVersionDependencies } from '@/store/install.js'
import { handleError } from '@/store/notifications.js'
import { useRouter } from 'vue-router'
import { convertFileSrc } from '@tauri-apps/api/core'
import { trackEvent } from '@/helpers/analytics'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
const router = useRouter()

View File

@@ -1,18 +1,16 @@
<script setup lang="ts">
import { CopyIcon, EditIcon, PlusIcon, SpinnerIcon, TrashIcon, UploadIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled, Checkbox, OverflowMenu } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { open } from '@tauri-apps/plugin-dialog'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed, type Ref, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import { trackEvent } from '@/helpers/analytics'
import { SpinnerIcon, TrashIcon, UploadIcon, PlusIcon, EditIcon, CopyIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled, OverflowMenu, Checkbox } from '@modrinth/ui'
import { computed, ref, type Ref, watch } from 'vue'
import { duplicate, edit, edit_icon, list, remove } from '@/helpers/profile'
import { handleError } from '@/store/notifications'
import type { GameInstance, InstanceSettingsTabProps } from '../../../helpers/types'
import { trackEvent } from '@/helpers/analytics'
import { open } from '@tauri-apps/plugin-dialog'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { useRouter } from 'vue-router'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import type { InstanceSettingsTabProps, GameInstance } from '../../../helpers/types'
const { formatMessage } = useVIntl()
const router = useRouter()

View File

@@ -1,13 +1,11 @@
<script setup lang="ts">
import { Checkbox } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { handleError } from '@/store/notifications'
import type { AppSettings, Hooks, InstanceSettingsTabProps } from '../../../helpers/types'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { get } from '@/helpers/settings.ts'
import { edit } from '@/helpers/profile'
import type { InstanceSettingsTabProps, AppSettings, Hooks } from '../../../helpers/types'
const { formatMessage } = useVIntl()

View File

@@ -1,16 +1,23 @@
<script setup lang="ts">
import {
DownloadIcon,
HammerIcon,
IssuesIcon,
SpinnerIcon,
TransferIcon,
UndoIcon,
UnlinkIcon,
UnplugIcon,
IssuesIcon,
HammerIcon,
DownloadIcon,
WrenchIcon,
UndoIcon,
SpinnerIcon,
UnplugIcon,
UnlinkIcon,
} from '@modrinth/assets'
import { Avatar, ButtonStyled, Checkbox, Chips, TeleportDropdownMenu } from '@modrinth/ui'
import { Avatar, Checkbox, Chips, ButtonStyled, TeleportDropdownMenu } from '@modrinth/ui'
import { computed, type ComputedRef, type Ref, ref, shallowRef, watch } from 'vue'
import { edit, install, update_repair_modrinth } from '@/helpers/profile'
import { handleError } from '@/store/notifications'
import { trackEvent } from '@/helpers/analytics'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { get_loader_versions } from '@/helpers/metadata'
import { get_game_versions, get_loaders } from '@/helpers/tags'
import {
formatCategory,
type GameVersionTag,
@@ -18,23 +25,14 @@ import {
type Project,
type Version,
} from '@modrinth/utils'
import { defineMessages, useVIntl } from '@vintl/vintl'
import dayjs from 'dayjs'
import { computed, type ComputedRef, type Ref, ref, shallowRef, watch } from 'vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_project, get_version_many } from '@/helpers/cache'
import { get_loader_versions } from '@/helpers/metadata'
import { edit, install, update_repair_modrinth } from '@/helpers/profile'
import { get_game_versions, get_loaders } from '@/helpers/tags'
import { handleError } from '@/store/notifications'
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
import dayjs from 'dayjs'
import type {
InstanceSettingsTabProps,
Manifest,
ManifestLoaderVersion,
Manifest,
} from '../../../helpers/types'
const { formatMessage } = useVIntl()

View File

@@ -1,16 +1,14 @@
<script setup lang="ts">
import { CheckCircleIcon, XCircleIcon } from '@modrinth/assets'
import { Checkbox, Slider } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { CheckCircleIcon, XCircleIcon } from '@modrinth/assets'
import { computed, readonly, ref, watch } from 'vue'
import JavaSelector from '@/components/ui/JavaSelector.vue'
import useMemorySlider from '@/composables/useMemorySlider'
import { edit, get_optimal_jre_key } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { handleError } from '@/store/notifications'
import type { AppSettings, InstanceSettingsTabProps, MemorySettings } from '../../../helpers/types'
import { defineMessages, useVIntl } from '@vintl/vintl'
import JavaSelector from '@/components/ui/JavaSelector.vue'
import { get } from '@/helpers/settings.ts'
import type { InstanceSettingsTabProps, AppSettings, MemorySettings } from '../../../helpers/types'
import useMemorySlider from '@/composables/useMemorySlider'
const { formatMessage } = useVIntl()

View File

@@ -1,12 +1,10 @@
<script setup lang="ts">
import { Checkbox, Toggle } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed, type Ref, ref, watch } from 'vue'
import { edit } from '@/helpers/profile'
import { get } from '@/helpers/settings.ts'
import { computed, ref, type Ref, watch } from 'vue'
import { handleError } from '@/store/notifications'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { get } from '@/helpers/settings.ts'
import { edit } from '@/helpers/profile'
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
const { formatMessage } = useVIntl()

View File

@@ -1,29 +1,28 @@
<script setup lang="ts">
import {
CoffeeIcon,
GameIcon,
GaugeIcon,
ModrinthIcon,
PaintbrushIcon,
ReportIcon,
SettingsIcon,
ModrinthIcon,
ShieldIcon,
SettingsIcon,
GaugeIcon,
PaintbrushIcon,
GameIcon,
CoffeeIcon,
} from '@modrinth/assets'
import { TabbedModal } from '@modrinth/ui'
import { getVersion } from '@tauri-apps/api/app'
import { platform as getOsPlatform, version as getOsVersion } from '@tauri-apps/plugin-os'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { computed, ref, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { useVIntl, defineMessage } from '@vintl/vintl'
import AppearanceSettings from '@/components/ui/settings/AppearanceSettings.vue'
import DefaultInstanceSettings from '@/components/ui/settings/DefaultInstanceSettings.vue'
import FeatureFlagSettings from '@/components/ui/settings/FeatureFlagSettings.vue'
import JavaSettings from '@/components/ui/settings/JavaSettings.vue'
import PrivacySettings from '@/components/ui/settings/PrivacySettings.vue'
import ResourceManagementSettings from '@/components/ui/settings/ResourceManagementSettings.vue'
import { get, set } from '@/helpers/settings.ts'
import PrivacySettings from '@/components/ui/settings/PrivacySettings.vue'
import DefaultInstanceSettings from '@/components/ui/settings/DefaultInstanceSettings.vue'
import { getVersion } from '@tauri-apps/api/app'
import { version as getOsVersion, platform as getOsPlatform } from '@tauri-apps/plugin-os'
import { useTheming } from '@/store/state'
import FeatureFlagSettings from '@/components/ui/settings/FeatureFlagSettings.vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { get, set } from '@/helpers/settings.ts'
const themeStore = useTheming()

View File

@@ -1,7 +1,6 @@
<script setup lang="ts">
import { LogInIcon, SpinnerIcon } from '@modrinth/assets'
import { ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
defineProps({

View File

@@ -1,8 +1,7 @@
<script setup lang="ts">
import { ConfirmModal } from '@modrinth/ui'
import { ref } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { ConfirmModal } from '@modrinth/ui'
import { show_ads_window, hide_ads_window } from '@/helpers/ads.js'
import { useTheming } from '@/store/theme.ts'
const themeStore = useTheming()

View File

@@ -2,7 +2,6 @@
import { ChevronRightIcon } from '@modrinth/assets'
import { Avatar } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import type { GameInstance } from '@/helpers/types'
defineProps<{

View File

@@ -1,24 +1,22 @@
<script setup lang="ts">
import {
ChevronRightIcon,
CodeIcon,
CoffeeIcon,
InfoIcon,
MonitorIcon,
WrenchIcon,
MonitorIcon,
CodeIcon,
} from '@modrinth/assets'
import { Avatar, TabbedModal, type TabbedModalTab } from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { ref } from 'vue'
import { defineMessage, useVIntl } from '@vintl/vintl'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import GeneralSettings from '@/components/ui/instance_settings/GeneralSettings.vue'
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
import { convertFileSrc } from '@tauri-apps/api/core'
import InstallationSettings from '@/components/ui/instance_settings/InstallationSettings.vue'
import JavaSettings from '@/components/ui/instance_settings/JavaSettings.vue'
import WindowSettings from '@/components/ui/instance_settings/WindowSettings.vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
import type { InstanceSettingsTabProps } from '../../../helpers/types'
const { formatMessage } = useVIntl()

View File

@@ -1,8 +1,7 @@
<script setup lang="ts">
import { NewModal as Modal } from '@modrinth/ui'
import { useTemplateRef } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { NewModal as Modal } from '@modrinth/ui'
import { show_ads_window, hide_ads_window } from '@/helpers/ads.js'
import { useTheming } from '@/store/theme.ts'
const themeStore = useTheming()

View File

@@ -1,8 +1,7 @@
<script setup lang="ts">
import { ShareModal } from '@modrinth/ui'
import { ref } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { ShareModal } from '@modrinth/ui'
import { show_ads_window, hide_ads_window } from '@/helpers/ads.js'
import { useTheming } from '@/store/theme.ts'
const themeStore = useTheming()

View File

@@ -1,10 +1,9 @@
<script setup lang="ts">
import { TeleportDropdownMenu, ThemeSelector, Toggle } from '@modrinth/ui'
import { ref, watch } from 'vue'
import { get, set } from '@/helpers/settings.ts'
import { getOS } from '@/helpers/utils'
import { useTheming } from '@/store/state'
import { get, set } from '@/helpers/settings.ts'
import { ref, watch } from 'vue'
import { getOS } from '@/helpers/utils'
import type { ColorTheme } from '@/store/theme.ts'
const themeStore = useTheming()

View File

@@ -1,9 +1,8 @@
<script setup lang="ts">
import { Slider, Toggle } from '@modrinth/ui'
import { ref, watch } from 'vue'
import useMemorySlider from '@/composables/useMemorySlider'
import { get, set } from '@/helpers/settings.ts'
import { ref, watch } from 'vue'
import { Slider, Toggle } from '@modrinth/ui'
import useMemorySlider from '@/composables/useMemorySlider'
const fetchSettings = await get()
fetchSettings.launchArgs = fetchSettings.extra_launch_args.join(' ')

View File

@@ -1,9 +1,8 @@
<script setup lang="ts">
import { Toggle } from '@modrinth/ui'
import { ref, watch } from 'vue'
import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
import { useTheming } from '@/store/state'
import { ref, watch } from 'vue'
import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
import { DEFAULT_FEATURE_FLAGS, type FeatureFlag } from '@/store/theme.ts'
const themeStore = useTheming()

View File

@@ -1,9 +1,8 @@
<script setup>
import { ref } from 'vue'
import JavaSelector from '@/components/ui/JavaSelector.vue'
import { get_java_versions, set_java_version } from '@/helpers/jre'
import { handleError } from '@/store/notifications'
import JavaSelector from '@/components/ui/JavaSelector.vue'
const javaVersions = ref(await get_java_versions().catch(handleError))
async function updateJavaVersion(version) {

View File

@@ -1,9 +1,8 @@
<script setup lang="ts">
import { Toggle } from '@modrinth/ui'
import { ref, watch } from 'vue'
import { optInAnalytics, optOutAnalytics } from '@/helpers/analytics'
import { get, set } from '@/helpers/settings.ts'
import { Toggle } from '@modrinth/ui'
import { optInAnalytics, optOutAnalytics } from '@/helpers/analytics'
const settings = ref(await get())

View File

@@ -1,13 +1,12 @@
<script setup>
import { BoxIcon, FolderSearchIcon, TrashIcon } from '@modrinth/assets'
import { Button, Slider } from '@modrinth/ui'
import { open } from '@tauri-apps/plugin-dialog'
import { ref, watch } from 'vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import { purge_cache_types } from '@/helpers/cache.js'
import { get, set } from '@/helpers/settings.ts'
import { purge_cache_types } from '@/helpers/cache.js'
import { handleError } from '@/store/notifications.js'
import { BoxIcon, FolderSearchIcon, TrashIcon } from '@modrinth/assets'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import { open } from '@tauri-apps/plugin-dialog'
const settings = ref(await get())

View File

@@ -100,38 +100,37 @@
</template>
<script setup lang="ts">
import { ref, computed, watch, useTemplateRef } from 'vue'
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
import {
CheckIcon,
ChevronRightIcon,
SaveIcon,
SpinnerIcon,
UploadIcon,
XIcon,
} from '@modrinth/assets'
import {
SkinPreviewRenderer,
Button,
ButtonStyled,
RadioButtons,
CapeButton,
CapeLikeTextButton,
RadioButtons,
SkinPreviewRenderer,
ButtonStyled,
} from '@modrinth/ui'
import { computed, ref, useTemplateRef, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
import UploadSkinModal from '@/components/ui/skin/UploadSkinModal.vue'
import {
add_and_equip_custom_skin,
type Cape,
determineModelType,
get_normalized_skin_texture,
remove_custom_skin,
type Skin,
type SkinModel,
unequip_skin,
type Skin,
type Cape,
type SkinModel,
get_normalized_skin_texture,
determineModelType,
} from '@/helpers/skins.ts'
import { handleError } from '@/store/notifications'
import {
UploadIcon,
CheckIcon,
SaveIcon,
XIcon,
ChevronRightIcon,
SpinnerIcon,
} from '@modrinth/assets'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import UploadSkinModal from '@/components/ui/skin/UploadSkinModal.vue'
const modal = useTemplateRef('modal')
const selectCapeModal = useTemplateRef('selectCapeModal')

View File

@@ -1,16 +1,15 @@
<script setup lang="ts">
import { CheckIcon, XIcon } from '@modrinth/assets'
import { useTemplateRef, ref, computed } from 'vue'
import type { Cape, SkinModel } from '@/helpers/skins.ts'
import {
ButtonStyled,
ScrollablePanel,
CapeButton,
CapeLikeTextButton,
ScrollablePanel,
SkinPreviewRenderer,
} from '@modrinth/ui'
import { computed, ref, useTemplateRef } from 'vue'
import { CheckIcon, XIcon } from '@modrinth/assets'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import type { Cape, SkinModel } from '@/helpers/skins.ts'
const modal = useTemplateRef('modal')

View File

@@ -27,13 +27,12 @@
</template>
<script setup lang="ts">
import { ref, onBeforeUnmount, watch } from 'vue'
import { UploadIcon } from '@modrinth/assets'
import { useNotifications } from '@/store/state'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import { onBeforeUnmount, ref, watch } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import { get_dragged_skin_data } from '@/helpers/skins'
import { useNotifications } from '@/store/state'
const notifications = useNotifications()

View File

@@ -1,4 +1,6 @@
<script setup lang="ts">
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import {
EyeIcon,
FolderOpenIcon,
@@ -15,23 +17,20 @@ import {
SmartClickable,
useRelativeTime,
} from '@modrinth/ui'
import { capitalizeString } from '@modrinth/utils'
import { convertFileSrc } from '@tauri-apps/api/core'
import { useVIntl } from '@vintl/vintl'
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { trackEvent } from '@/helpers/analytics'
import { get_project } from '@/helpers/cache'
import { process_listener } from '@/helpers/events'
import { get_by_profile_path } from '@/helpers/process'
import { kill, run } from '@/helpers/profile'
import type { GameInstance } from '@/helpers/types'
import { computed, nextTick, ref, onMounted, onUnmounted } from 'vue'
import { showProfileInFolder } from '@/helpers/utils'
import { convertFileSrc } from '@tauri-apps/api/core'
import { useRouter } from 'vue-router'
import type { GameInstance } from '@/helpers/types'
import { get_project } from '@/helpers/cache'
import { capitalizeString } from '@modrinth/utils'
import { kill, run } from '@/helpers/profile'
import { handleSevereError } from '@/store/error'
import { trackEvent } from '@/helpers/analytics'
import { get_by_profile_path } from '@/helpers/process'
import { handleError } from '@/store/notifications'
import { process_listener } from '@/helpers/events'
const { formatMessage } = useVIntl()
const formatRelativeTime = useRelativeTime()

View File

@@ -1,31 +1,30 @@
<script setup lang="ts">
import { GAME_MODES, HeadingLink } from '@modrinth/ui'
import {
type ProtocolVersion,
type ServerWorld,
type ServerData,
type WorldWithProfile,
get_recent_worlds,
getWorldIdentifier,
get_profile_protocol_version,
refreshServerData,
start_join_server,
start_join_singleplayer_world,
} from '@/helpers/worlds.ts'
import { HeadingLink, GAME_MODES } from '@modrinth/ui'
import WorldItem from '@/components/ui/world/WorldItem.vue'
import InstanceItem from '@/components/ui/world/InstanceItem.vue'
import { watch, onMounted, onUnmounted, ref, computed } from 'vue'
import type { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import InstanceItem from '@/components/ui/world/InstanceItem.vue'
import WorldItem from '@/components/ui/world/WorldItem.vue'
import { useTheming } from '@/store/theme.ts'
import { kill, run } from '@/helpers/profile'
import { handleError } from '@/store/notifications'
import { trackEvent } from '@/helpers/analytics'
import { process_listener, profile_listener } from '@/helpers/events'
import { get_all } from '@/helpers/process'
import { kill, run } from '@/helpers/profile'
import type { GameInstance } from '@/helpers/types'
import {
get_profile_protocol_version,
get_recent_worlds,
getWorldIdentifier,
type ProtocolVersion,
refreshServerData,
type ServerData,
type ServerWorld,
start_join_server,
start_join_singleplayer_world,
type WorldWithProfile,
} from '@/helpers/worlds.ts'
import { handleSevereError } from '@/store/error'
import { handleError } from '@/store/notifications'
import { useTheming } from '@/store/theme.ts'
const props = defineProps<{
recentInstances: GameInstance[]

View File

@@ -1,10 +1,28 @@
<script setup lang="ts">
import dayjs from 'dayjs'
import type {
ProtocolVersion,
ServerStatus,
ServerWorld,
SingleplayerWorld,
World,
} from '@/helpers/worlds.ts'
import { set_world_display_status, getWorldIdentifier } from '@/helpers/worlds.ts'
import { formatNumber, getPingLevel } from '@modrinth/utils'
import {
useRelativeTime,
Avatar,
ButtonStyled,
commonMessages,
OverflowMenu,
SmartClickable,
} from '@modrinth/ui'
import {
IssuesIcon,
EyeIcon,
ClipboardCopyIcon,
EditIcon,
EyeIcon,
FolderOpenIcon,
IssuesIcon,
MoreVerticalIcon,
NoSignalIcon,
PlayIcon,
@@ -17,33 +35,14 @@ import {
UserIcon,
XIcon,
} from '@modrinth/assets'
import {
Avatar,
ButtonStyled,
commonMessages,
OverflowMenu,
SmartClickable,
useRelativeTime,
} from '@modrinth/ui'
import { formatNumber, getPingLevel } from '@modrinth/utils'
import { convertFileSrc } from '@tauri-apps/api/core'
import type { MessageDescriptor } from '@vintl/vintl'
import { defineMessages, useVIntl } from '@vintl/vintl'
import dayjs from 'dayjs'
import { Tooltip } from 'floating-vue'
import type { Component } from 'vue'
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { copyToClipboard } from '@/helpers/utils'
import type {
ProtocolVersion,
ServerStatus,
ServerWorld,
SingleplayerWorld,
World,
} from '@/helpers/worlds.ts'
import { getWorldIdentifier, set_world_display_status } from '@/helpers/worlds.ts'
import { convertFileSrc } from '@tauri-apps/api/core'
import { useRouter } from 'vue-router'
import { Tooltip } from 'floating-vue'
const { formatMessage } = useVIntl()
const formatRelativeTime = useRelativeTime()

View File

@@ -1,15 +1,14 @@
<script setup lang="ts">
import { PlayIcon, PlusIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, commonMessages } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { ref } from 'vue'
import InstanceModalTitlePrefix from '@/components/ui/modal/InstanceModalTitlePrefix.vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import ServerModalBody from '@/components/ui/world/modal/ServerModalBody.vue'
import type { GameInstance } from '@/helpers/types'
import InstanceModalTitlePrefix from '@/components/ui/modal/InstanceModalTitlePrefix.vue'
import { add_server_to_profile, type ServerPackStatus, type ServerWorld } from '@/helpers/worlds.ts'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { handleError } from '@/store/notifications'
import ServerModalBody from '@/components/ui/world/modal/ServerModalBody.vue'
const { formatMessage } = useVIntl()

View File

@@ -1,21 +1,20 @@
<script setup lang="ts">
import { SaveIcon, XIcon } from '@modrinth/assets'
import { ButtonStyled, commonMessages } from '@modrinth/ui'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { computed, ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import HideFromHomeOption from '@/components/ui/world/modal/HideFromHomeOption.vue'
import ServerModalBody from '@/components/ui/world/modal/ServerModalBody.vue'
import type { GameInstance } from '@/helpers/types'
import {
type DisplayStatus,
edit_server_in_profile,
type ServerPackStatus,
edit_server_in_profile,
type ServerWorld,
set_world_display_status,
type DisplayStatus,
} from '@/helpers/worlds.ts'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { handleError } from '@/store/notifications'
import ServerModalBody from '@/components/ui/world/modal/ServerModalBody.vue'
import HideFromHomeOption from '@/components/ui/world/modal/HideFromHomeOption.vue'
const { formatMessage } = useVIntl()

View File

@@ -1,15 +1,14 @@
<script setup lang="ts">
import { ChevronRightIcon, SaveIcon, UndoIcon, XIcon } from '@modrinth/assets'
import { ChevronRightIcon, SaveIcon, XIcon, UndoIcon } from '@modrinth/assets'
import { Avatar, ButtonStyled, commonMessages } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed, ref } from 'vue'
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
import HideFromHomeOption from '@/components/ui/world/modal/HideFromHomeOption.vue'
import type { GameInstance } from '@/helpers/types'
import type { DisplayStatus, SingleplayerWorld } from '@/helpers/worlds.ts'
import { rename_world, reset_world_icon, set_world_display_status } from '@/helpers/worlds.ts'
import { set_world_display_status, rename_world, reset_world_icon } from '@/helpers/worlds.ts'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { handleError } from '@/store/notifications'
import HideFromHomeOption from '@/components/ui/world/modal/HideFromHomeOption.vue'
const { formatMessage } = useVIntl()

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { Checkbox } from '@modrinth/ui'
import { defineMessage, useVIntl } from '@vintl/vintl'
import { computed } from 'vue'
import { Checkbox } from '@modrinth/ui'
const { formatMessage } = useVIntl()
const value = defineModel<boolean>({ required: true })

View File

@@ -1,8 +1,7 @@
<script setup lang="ts">
import { TeleportDropdownMenu } from '@modrinth/ui'
import { defineMessages, type MessageDescriptor, useVIntl } from '@vintl/vintl'
import type { ServerPackStatus } from '@/helpers/worlds.ts'
import { type MessageDescriptor, defineMessages, useVIntl } from '@vintl/vintl'
const { formatMessage } = useVIntl()

View File

@@ -1,5 +1,4 @@
import { invoke } from '@tauri-apps/api/core'
import cssContent from '@/assets/stylesheets/macFix.css?inline'
export async function useCheckDisableMouseover() {

View File

@@ -1,5 +1,4 @@
import { computed, ref } from 'vue'
import { ref, computed } from 'vue'
import { get_max_memory } from '@/helpers/jre.js'
import { handleError } from '@/store/notifications.js'

View File

@@ -1,7 +1,6 @@
import { getVersion } from '@tauri-apps/api/app'
import { fetch } from '@tauri-apps/plugin-http'
import { handleError } from '@/store/state.js'
import { getVersion } from '@tauri-apps/api/app'
export const useFetch = async (url, item, isSilent) => {
try {

View File

@@ -4,7 +4,6 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
import { create } from './profile'
/*

View File

@@ -4,7 +4,6 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
import { create } from './profile'
// Installs pack from a version ID

View File

@@ -4,7 +4,6 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
import { install_to_existing_profile } from '@/helpers/pack.js'
import { handleError } from '@/store/notifications.js'

View File

@@ -1,18 +1,17 @@
import { ClassicPlayerModel, SlimPlayerModel } from '@modrinth/assets'
import * as THREE from 'three'
import type { Skin, Cape } from '../skins'
import { get_normalized_skin_texture, determineModelType } from '../skins'
import { reactive } from 'vue'
import {
applyCapeTexture,
createTransparentTexture,
setupSkinModel,
disposeCaches,
loadTexture,
setupSkinModel,
applyCapeTexture,
createTransparentTexture,
} from '@modrinth/utils'
import * as THREE from 'three'
import { reactive } from 'vue'
import type { Cape, Skin } from '../skins'
import { determineModelType, get_normalized_skin_texture } from '../skins'
import { headStorage } from '../storage/head-storage'
import { skinPreviewStorage } from '../storage/skin-preview-storage'
import { headStorage } from '../storage/head-storage'
import { ClassicPlayerModel, SlimPlayerModel } from '@modrinth/assets'
export interface RenderResult {
forwards: string

View File

@@ -4,9 +4,8 @@
* and deserialized into a usable JS object.
*/
import { invoke } from '@tauri-apps/api/core'
import type { Hooks, MemorySettings, WindowSize } from '@/helpers/types'
import type { ColorTheme, FeatureFlag } from '@/store/theme.ts'
import type { Hooks, MemorySettings, WindowSize } from '@/helpers/types'
// Settings object
/*

View File

@@ -1,7 +1,6 @@
import { arrayBufferToBase64 } from '@modrinth/utils'
import { invoke } from '@tauri-apps/api/core'
import { handleError } from '@/store/notifications'
import { arrayBufferToBase64 } from '@modrinth/utils'
export interface Cape {
id: string

View File

@@ -1,6 +1,5 @@
import { invoke } from '@tauri-apps/api/core'
import { get_full_path, get_mod_full_path } from '@/helpers/profile'
import { invoke } from '@tauri-apps/api/core'
export async function isDev() {
return await invoke('is_dev')

View File

@@ -1,10 +1,9 @@
import { autoToHTML } from '@geometrically/minecraft-motd-parser'
import type { GameVersion } from '@modrinth/ui'
import { invoke } from '@tauri-apps/api/core'
import dayjs from 'dayjs'
import { get_full_path } from '@/helpers/profile'
import { openPath } from '@/helpers/utils'
import { autoToHTML } from '@geometrically/minecraft-motd-parser'
import dayjs from 'dayjs'
import type { GameVersion } from '@modrinth/ui'
type BaseWorld = {
name: string

View File

@@ -1,14 +1,12 @@
import { createApp } from 'vue'
import router from '@/routes'
import App from '@/App.vue'
import { createPinia } from 'pinia'
import FloatingVue from 'floating-vue'
import 'floating-vue/dist/style.css'
import { createPlugin } from '@vintl/vintl/plugin'
import * as Sentry from '@sentry/vue'
import { VueScanPlugin } from '@taijased/vue-render-tracker'
import { createPlugin } from '@vintl/vintl/plugin'
import FloatingVue from 'floating-vue'
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from '@/App.vue'
import router from '@/routes'
const VIntlPlugin = createPlugin({
controllerOpts: {

View File

@@ -1,33 +1,32 @@
<script setup lang="ts">
import { ClipboardCopyIcon, ExternalIcon, GlobeIcon, SearchIcon, XIcon } from '@modrinth/assets'
import { computed, nextTick, ref, shallowRef, watch } from 'vue'
import type { Ref } from 'vue'
import { SearchIcon, XIcon, ClipboardCopyIcon, GlobeIcon, ExternalIcon } from '@modrinth/assets'
import type { Category, GameVersion, Platform, ProjectType, SortType, Tags } from '@modrinth/ui'
import {
SearchFilterControl,
SearchSidebarFilter,
Button,
Checkbox,
DropdownSelect,
LoadingIndicator,
Pagination,
SearchFilterControl,
SearchSidebarFilter,
useSearch,
} from '@modrinth/ui'
import { openUrl } from '@tauri-apps/plugin-opener'
import { defineMessages, useVIntl } from '@vintl/vintl'
import type { Ref } from 'vue'
import { computed, nextTick, ref, shallowRef, watch } from 'vue'
import { handleError } from '@/store/state'
import { useBreadcrumbs } from '@/store/breadcrumbs'
import { get_categories, get_game_versions, get_loaders } from '@/helpers/tags'
import type { LocationQuery } from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
import ContextMenu from '@/components/ui/ContextMenu.vue'
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 NavTabs from '@/components/ui/NavTabs.vue'
import type Instance from '@/components/ui/Instance.vue'
import InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
import NavTabs from '@/components/ui/NavTabs.vue'
import SearchCard from '@/components/ui/SearchCard.vue'
import { get_search_results } from '@/helpers/cache.js'
import { get as getInstance, get_projects as getInstanceProjects } from '@/helpers/profile.js'
import { get_categories, get_game_versions, get_loaders } from '@/helpers/tags'
import { useBreadcrumbs } from '@/store/breadcrumbs'
import { handleError } from '@/store/state'
import { defineMessages, useVIntl } from '@vintl/vintl'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import { openUrl } from '@tauri-apps/plugin-opener'
const { formatMessage } = useVIntl()

View File

@@ -1,17 +1,16 @@
<script setup lang="ts">
import type { SearchResult } from '@modrinth/utils'
import dayjs from 'dayjs'
import { computed, onUnmounted, ref } from 'vue'
import { ref, onUnmounted, computed } from 'vue'
import { useRoute } from 'vue-router'
import RowDisplay from '@/components/RowDisplay.vue'
import RecentWorldsList from '@/components/ui/world/RecentWorldsList.vue'
import { get_search_results } from '@/helpers/cache.js'
import { profile_listener } from '@/helpers/events'
import { list } from '@/helpers/profile.js'
import type { GameInstance } from '@/helpers/types'
import { profile_listener } from '@/helpers/events'
import { useBreadcrumbs } from '@/store/breadcrumbs'
import { handleError } from '@/store/notifications.js'
import dayjs from 'dayjs'
import { get_search_results } from '@/helpers/cache.js'
import type { SearchResult } from '@modrinth/utils'
import RecentWorldsList from '@/components/ui/world/RecentWorldsList.vue'
import type { GameInstance } from '@/helpers/types'
const route = useRoute()
const breadcrumbs = useBreadcrumbs()

View File

@@ -16,34 +16,33 @@ import {
SkinLikeTextButton,
SkinPreviewRenderer,
} from '@modrinth/ui'
import { arrayBufferToBase64 } from '@modrinth/utils'
import { computedAsync } from '@vueuse/core'
import type { Ref } from 'vue'
import { computed, inject, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue'
import type AccountsCard from '@/components/ui/AccountsCard.vue'
import EditSkinModal from '@/components/ui/skin/EditSkinModal.vue'
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
import UploadSkinModal from '@/components/ui/skin/UploadSkinModal.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_default_user, login as login_flow, users } from '@/helpers/auth'
import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts'
import { generateSkinPreviews, skinBlobUrlMap } from '@/helpers/rendering/batch-skin-renderer.ts'
import { get as getSettings } from '@/helpers/settings.ts'
import { handleError, useNotifications } from '@/store/notifications'
import type { Cape, Skin } from '@/helpers/skins.ts'
import {
normalize_skin_texture,
equip_skin,
filterDefaultSkins,
filterSavedSkins,
get_available_capes,
get_available_skins,
get_normalized_skin_texture,
normalize_skin_texture,
remove_custom_skin,
set_default_cape,
} from '@/helpers/skins.ts'
import { get as getSettings } from '@/helpers/settings.ts'
import { get_default_user, login as login_flow, users } from '@/helpers/auth'
import type { RenderResult } from '@/helpers/rendering/batch-skin-renderer.ts'
import { generateSkinPreviews, skinBlobUrlMap } from '@/helpers/rendering/batch-skin-renderer.ts'
import { handleSevereError } from '@/store/error'
import { handleError, useNotifications } from '@/store/notifications'
import { trackEvent } from '@/helpers/analytics'
import type AccountsCard from '@/components/ui/AccountsCard.vue'
import { arrayBufferToBase64 } from '@modrinth/utils'
const editSkinModal = useTemplateRef('editSkinModal')
const selectCapeModal = useTemplateRef('selectCapeModal')
const uploadSkinModal = useTemplateRef('uploadSkinModal')

View File

@@ -1,6 +1,6 @@
import Browse from './Browse.vue'
import Index from './Index.vue'
import Skins from './Skins.vue'
import Browse from './Browse.vue'
import Worlds from './Worlds.vue'
import Skins from './Skins.vue'
export { Browse, Index, Skins, Worlds }
export { Index, Browse, Worlds, Skins }

View File

@@ -157,6 +157,13 @@
</div>
</template>
<script setup>
import {
Avatar,
ButtonStyled,
ContentPageHeader,
LoadingIndicator,
OverflowMenu,
} from '@modrinth/ui'
import {
CheckCircleIcon,
ClipboardCopyIcon,
@@ -180,32 +187,24 @@ import {
UserPlusIcon,
XIcon,
} from '@modrinth/assets'
import {
Avatar,
ButtonStyled,
ContentPageHeader,
LoadingIndicator,
OverflowMenu,
} from '@modrinth/ui'
import { finish_install, 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'
import { computed, onUnmounted, ref, watch } from 'vue'
import { handleError, useBreadcrumbs, useLoading } from '@/store/state'
import { showProfileInFolder } from '@/helpers/utils.js'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import NavTabs from '@/components/ui/NavTabs.vue'
import { trackEvent } from '@/helpers/analytics'
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 { computed, onUnmounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import ExportModal from '@/components/ui/ExportModal.vue'
import InstanceSettingsModal from '@/components/ui/modal/InstanceSettingsModal.vue'
import NavTabs from '@/components/ui/NavTabs.vue'
import { trackEvent } from '@/helpers/analytics'
import { get_project, get_version_many } from '@/helpers/cache.js'
import { process_listener, profile_listener } from '@/helpers/events'
import { get_by_profile_path } from '@/helpers/process'
import { finish_install, get, get_full_path, kill, run } from '@/helpers/profile'
import { showProfileInFolder } from '@/helpers/utils.js'
import { handleSevereError } from '@/store/error.js'
import { handleError, useBreadcrumbs, useLoading } from '@/store/state'
dayjs.extend(duration)
dayjs.extend(relativeTime)

View File

@@ -88,28 +88,26 @@
</template>
<script setup>
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import { CheckIcon, ClipboardCopyIcon, ShareIcon, TrashIcon } from '@modrinth/assets'
import { Button, Card, Checkbox, DropdownSelect } from '@modrinth/ui'
import {
delete_logs_by_filename,
get_logs,
get_output_by_filename,
get_latest_log_cursor,
} from '@/helpers/logs.js'
import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue'
import dayjs from 'dayjs'
import isToday from 'dayjs/plugin/isToday'
import isYesterday from 'dayjs/plugin/isYesterday'
import { ofetch } from 'ofetch'
import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { RecycleScroller } from 'vue-virtual-scroller'
import ShareModalWrapper from '@/components/ui/modal/ShareModalWrapper.vue'
import { process_listener } from '@/helpers/events.js'
import {
delete_logs_by_filename,
get_latest_log_cursor,
get_logs,
get_output_by_filename,
} from '@/helpers/logs.js'
import { get_by_profile_path } from '@/helpers/process.js'
import { useRoute } from 'vue-router'
import { process_listener } from '@/helpers/events.js'
import { handleError } from '@/store/notifications.js'
import { ofetch } from 'ofetch'
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import ShareModalWrapper from '@/components/ui/modal/ShareModalWrapper.vue'
dayjs.extend(isToday)
dayjs.extend(isYesterday)

View File

@@ -276,29 +276,11 @@ import {
RadialHeader,
Toggle,
} from '@modrinth/ui'
import type { ContentItem } from '@modrinth/ui/src/components/content/ContentListItem.vue'
import type { Organization, Project, TeamMember, Version } from '@modrinth/utils'
import { formatProjectType } from '@modrinth/utils'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import { defineMessages, useVIntl } from '@vintl/vintl'
import dayjs from 'dayjs'
import type { ComputedRef } from 'vue'
import { computed, onUnmounted, ref, watch } from 'vue'
import { TextInputIcon } from '@/assets/icons'
import AddContentButton from '@/components/ui/AddContentButton.vue'
import type ContextMenu from '@/components/ui/ContextMenu.vue'
import ExportModal from '@/components/ui/ExportModal.vue'
import ShareModalWrapper from '@/components/ui/modal/ShareModalWrapper.vue'
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
import { trackEvent } from '@/helpers/analytics'
import {
get_organization_many,
get_project_many,
get_team_many,
get_version_many,
} from '@/helpers/cache.js'
import { profile_listener } from '@/helpers/events.js'
import { defineMessages, useVIntl } from '@vintl/vintl'
import {
add_project_from_path,
get_projects,
@@ -307,9 +289,26 @@ import {
update_all,
update_project,
} from '@/helpers/profile.js'
import type { CacheBehaviour, ContentFile, GameInstance } from '@/helpers/types'
import { highlightModInProfile } from '@/helpers/utils.js'
import { handleError } from '@/store/notifications.js'
import { trackEvent } from '@/helpers/analytics'
import { highlightModInProfile } from '@/helpers/utils.js'
import { TextInputIcon } from '@/assets/icons'
import ExportModal from '@/components/ui/ExportModal.vue'
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
import AddContentButton from '@/components/ui/AddContentButton.vue'
import {
get_organization_many,
get_project_many,
get_team_many,
get_version_many,
} from '@/helpers/cache.js'
import { profile_listener } from '@/helpers/events.js'
import ShareModalWrapper from '@/components/ui/modal/ShareModalWrapper.vue'
import { getCurrentWebview } from '@tauri-apps/api/webview'
import dayjs from 'dayjs'
import type { CacheBehaviour, ContentFile, GameInstance } from '@/helpers/types'
import type ContextMenu from '@/components/ui/ContextMenu.vue'
import type { ContentItem } from '@modrinth/ui/src/components/content/ContentListItem.vue'
const props = defineProps<{
instance: GameInstance

View File

@@ -1,9 +1,8 @@
<template>{{ instance.name }} overview</template>
<script setup lang="ts">
import type { Version } from '@modrinth/utils'
import type ContextMenu from '@/components/ui/ContextMenu.vue'
import type { GameInstance } from '@/helpers/types'
import type ContextMenu from '@/components/ui/ContextMenu.vue'
import type { Version } from '@modrinth/utils'
defineProps<{
instance: GameInstance

View File

@@ -121,54 +121,54 @@
</div>
</template>
<script setup lang="ts">
import { PlusIcon, SearchIcon, SpinnerIcon, UpdatedIcon, XIcon } from '@modrinth/assets'
import { ref, computed, onUnmounted, watch } from 'vue'
import { useRoute } from 'vue-router'
import type { GameInstance } from '@/helpers/types'
import {
Button,
ButtonStyled,
RadialHeader,
FilterBar,
type FilterBarOption,
GAME_MODES,
type GameVersion,
RadialHeader,
GAME_MODES,
} from '@modrinth/ui'
import type { Version } from '@modrinth/utils'
import { defineMessages } from '@vintl/vintl'
import { computed, onUnmounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import type ContextMenu from '@/components/ui/ContextMenu.vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import { PlusIcon, SpinnerIcon, UpdatedIcon, SearchIcon, XIcon } from '@modrinth/assets'
import {
type ProtocolVersion,
type SingleplayerWorld,
type World,
type ServerWorld,
type ServerData,
type ProfileEvent,
get_profile_protocol_version,
remove_server_from_profile,
delete_world,
start_join_server,
start_join_singleplayer_world,
getWorldIdentifier,
refreshServerData,
refreshWorld,
sortWorlds,
refreshServers,
hasWorldQuickPlaySupport,
refreshWorlds,
handleDefaultProfileUpdateEvent,
showWorldInFolder,
hasServerQuickPlaySupport,
} from '@/helpers/worlds.ts'
import AddServerModal from '@/components/ui/world/modal/AddServerModal.vue'
import EditServerModal from '@/components/ui/world/modal/EditServerModal.vue'
import EditWorldModal from '@/components/ui/world/modal/EditSingleplayerWorldModal.vue'
import WorldItem from '@/components/ui/world/WorldItem.vue'
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
import { handleError } from '@/store/notifications'
import type ContextMenu from '@/components/ui/ContextMenu.vue'
import type { Version } from '@modrinth/utils'
import { profile_listener } from '@/helpers/events'
import { get_game_versions } from '@/helpers/tags'
import type { GameInstance } from '@/helpers/types'
import {
delete_world,
get_profile_protocol_version,
getWorldIdentifier,
handleDefaultProfileUpdateEvent,
hasServerQuickPlaySupport,
hasWorldQuickPlaySupport,
type ProfileEvent,
type ProtocolVersion,
refreshServerData,
refreshServers,
refreshWorld,
refreshWorlds,
remove_server_from_profile,
type ServerData,
type ServerWorld,
showWorldInFolder,
type SingleplayerWorld,
sortWorlds,
start_join_server,
start_join_singleplayer_world,
type World,
} from '@/helpers/worlds.ts'
import { handleError } from '@/store/notifications'
import { defineMessages } from '@vintl/vintl'
const route = useRoute()

View File

@@ -1,7 +1,7 @@
import Index from './Index.vue'
import Logs from './Logs.vue'
import Mods from './Mods.vue'
import Overview from './Overview.vue'
import Worlds from './Worlds.vue'
import Mods from './Mods.vue'
import Logs from './Logs.vue'
export { Index, Logs, Mods, Overview, Worlds }
export { Index, Overview, Worlds, Mods, Logs }

View File

@@ -1,16 +1,15 @@
<script setup>
import { PlusIcon } from '@modrinth/assets'
import { Button } from '@modrinth/ui'
import { onUnmounted, ref, shallowRef } from 'vue'
import { useRoute } from 'vue-router'
import { NewInstanceImage } from '@/assets/icons'
import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue'
import NavTabs from '@/components/ui/NavTabs.vue'
import { profile_listener } from '@/helpers/events.js'
import { list } from '@/helpers/profile.js'
import { useRoute } from 'vue-router'
import { useBreadcrumbs } from '@/store/breadcrumbs.js'
import { profile_listener } from '@/helpers/events.js'
import { handleError } from '@/store/notifications.js'
import { Button } from '@modrinth/ui'
import { PlusIcon } from '@modrinth/assets'
import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue'
import { NewInstanceImage } from '@/assets/icons'
import NavTabs from '@/components/ui/NavTabs.vue'
const route = useRoute()
const breadcrumbs = useBreadcrumbs()

View File

@@ -1,6 +1,6 @@
import Custom from './Custom.vue'
import Downloaded from './Downloaded.vue'
import Index from './Index.vue'
import Overview from './Overview.vue'
import Downloaded from './Downloaded.vue'
import Custom from './Custom.vue'
export { Custom, Downloaded, Index, Overview }
export { Index, Overview, Downloaded, Custom }

View File

@@ -83,19 +83,18 @@
<script setup>
import {
CalendarIcon,
ContractIcon,
ExpandIcon,
ExternalIcon,
LeftArrowIcon,
RightArrowIcon,
LeftArrowIcon,
ExternalIcon,
ContractIcon,
XIcon,
CalendarIcon,
} from '@modrinth/assets'
import { Button, Card } from '@modrinth/ui'
import { ref } from 'vue'
import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
import { trackEvent } from '@/helpers/analytics'
import { show_ads_window, hide_ads_window } from '@/helpers/ads.js'
const props = defineProps({
project: {

View File

@@ -131,41 +131,41 @@
<script setup>
import {
BookmarkIcon,
CheckIcon,
ClipboardCopyIcon,
DownloadIcon,
ExternalIcon,
GlobeIcon,
HeartIcon,
MoreVerticalIcon,
DownloadIcon,
ReportIcon,
HeartIcon,
ExternalIcon,
CheckIcon,
GlobeIcon,
ClipboardCopyIcon,
} from '@modrinth/assets'
import {
ButtonStyled,
OverflowMenu,
ProjectBackgroundGradient,
ProjectHeader,
ProjectSidebarCompatibility,
ButtonStyled,
OverflowMenu,
ProjectSidebarLinks,
ProjectSidebarCreators,
ProjectSidebarDetails,
ProjectSidebarLinks,
ProjectBackgroundGradient,
} from '@modrinth/ui'
import { openUrl } from '@tauri-apps/plugin-opener'
import { get_categories, get_game_versions, get_loaders } from '@/helpers/tags'
import { get as getInstance, get_projects as getInstanceProjects } from '@/helpers/profile'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { ref, shallowRef, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
import NavTabs from '@/components/ui/NavTabs.vue'
import { get_project, get_team, get_version_many } from '@/helpers/cache.js'
import { get as getInstance, get_projects as getInstanceProjects } from '@/helpers/profile'
import { get_categories, get_game_versions, get_loaders } from '@/helpers/tags'
import { ref, shallowRef, watch } from 'vue'
import { useBreadcrumbs } from '@/store/breadcrumbs'
import { install as installVersion } from '@/store/install.js'
import { handleError } from '@/store/notifications.js'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import { install as installVersion } from '@/store/install.js'
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)

View File

@@ -182,16 +182,15 @@
</template>
<script setup>
import { CheckIcon, DownloadIcon, ExternalIcon, FileIcon, ReportIcon } from '@modrinth/assets'
import { Avatar, Badge, Breadcrumbs, Button, Card, CopyCode } from '@modrinth/ui'
import { DownloadIcon, FileIcon, ReportIcon, ExternalIcon, CheckIcon } from '@modrinth/assets'
import { formatBytes, renderString } from '@modrinth/utils'
import { computed, ref, watch } from 'vue'
import { Breadcrumbs, Badge, Avatar, Card, Button, CopyCode } from '@modrinth/ui'
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'
import { get_project_many, get_version_many } from '@/helpers/cache.js'
import { releaseColor } from '@/helpers/utils'
import { useBreadcrumbs } from '@/store/breadcrumbs'
const breadcrumbs = useBreadcrumbs()

View File

@@ -65,10 +65,9 @@
</template>
<script setup>
import { ProjectPageVersions, ButtonStyled, OverflowMenu } from '@modrinth/ui'
import { CheckIcon, DownloadIcon, ExternalIcon, MoreVerticalIcon } from '@modrinth/assets'
import { ButtonStyled, OverflowMenu, ProjectPageVersions } from '@modrinth/ui'
import { ref } from 'vue'
import { SwapIcon } from '@/assets/icons/index.js'
import { get_game_versions, get_loaders } from '@/helpers/tags.js'
import { handleError } from '@/store/notifications.js'

View File

@@ -1,7 +1,7 @@
import Description from './Description.vue'
import Gallery from './Gallery.vue'
import Index from './Index.vue'
import Version from './Version.vue'
import Description from './Description.vue'
import Versions from './Versions.vue'
import Gallery from './Gallery.vue'
import Version from './Version.vue'
export { Description, Gallery, Index, Version, Versions }
export { Index, Description, Versions, Gallery, Version }

View File

@@ -1,9 +1,8 @@
import { createRouter, createWebHistory } from 'vue-router'
import * as Pages from '@/pages'
import * as Project from '@/pages/project'
import * as Instance from '@/pages/instance'
import * as Library from '@/pages/library'
import * as Project from '@/pages/project'
/**
* Configures application routing. Add page to pages/index and then add to route table here.

View File

@@ -1,9 +1,4 @@
import dayjs from 'dayjs'
import { defineStore } from 'pinia'
import { trackEvent } from '@/helpers/analytics.js'
import { get_project, get_version_many } from '@/helpers/cache.js'
import { create_profile_and_install as packInstall } from '@/helpers/pack.js'
import {
add_project_from_version,
check_installed,
@@ -13,6 +8,10 @@ import {
remove_project,
} from '@/helpers/profile.js'
import { handleError } from '@/store/notifications.js'
import { get_project, get_version_many } from '@/helpers/cache.js'
import { create_profile_and_install as packInstall } from '@/helpers/pack.js'
import { trackEvent } from '@/helpers/analytics.js'
import dayjs from 'dayjs'
export const useInstall = defineStore('installStore', {
state: () => ({

View File

@@ -1,7 +1,7 @@
import { useBreadcrumbs } from './breadcrumbs'
import { useInstall } from './install'
import { useLoading } from './loading'
import { handleError, useNotifications } from './notifications'
import { useTheming } from './theme.ts'
import { useBreadcrumbs } from './breadcrumbs'
import { useLoading } from './loading'
import { useNotifications, handleError } from './notifications'
import { useInstall } from './install'
export { handleError, useBreadcrumbs, useInstall, useLoading, useNotifications, useTheming }
export { useTheming, useBreadcrumbs, useLoading, useNotifications, handleError, useInstall }

View File

@@ -1,8 +1,9 @@
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { defineConfig } from 'vite'
import svgLoader from 'vite-svg-loader'
import vue from '@vitejs/plugin-vue'
import tauriConf from '../app/tauri.conf.json'
const projectRootDir = resolve(__dirname)

View File

@@ -0,0 +1,7 @@
module.exports = {
root: true,
extends: ["../../packages/eslint-config-custom/nuxt.js"],
rules: {
"import/no-unresolved": "off",
},
};

View File

@@ -0,0 +1,4 @@
{
"endOfLine": "auto",
"plugins": ["prettier-plugin-tailwindcss"]
}

View File

@@ -1,6 +1,6 @@
project_id: 518556
preserve_hierarchy: true
commit_message: '[ci skip]'
commit_message: "[ci skip]"
files:
- source: /locales/en-US/*

View File

@@ -1,10 +0,0 @@
import config from '@modrinth/tooling-config/eslint/nuxt.mjs'
export default config.append([
{
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'import/no-unresolved': 'off',
'no-undef': 'off',
},
},
])

View File

@@ -1,28 +1,27 @@
import { pathToFileURL } from 'node:url'
import { promises as fs } from "fs";
import { pathToFileURL } from "node:url";
import svgLoader from "vite-svg-loader";
import { resolve, basename, relative } from "pathe";
import { defineNuxtConfig } from "nuxt/config";
import { $fetch } from "ofetch";
import { globIterate } from "glob";
import { match as matchLocale } from "@formatjs/intl-localematcher";
import { consola } from "consola";
import { match as matchLocale } from '@formatjs/intl-localematcher'
import { consola } from 'consola'
import { promises as fs } from 'fs'
import { globIterate } from 'glob'
import { defineNuxtConfig } from 'nuxt/config'
import { $fetch } from 'ofetch'
import { basename, relative, resolve } from 'pathe'
import svgLoader from 'vite-svg-loader'
const STAGING_API_URL = 'https://staging-api.modrinth.com/v2/'
const STAGING_API_URL = "https://staging-api.modrinth.com/v2/";
const preloadedFonts = [
'inter/Inter-Regular.woff2',
'inter/Inter-Medium.woff2',
'inter/Inter-SemiBold.woff2',
'inter/Inter-Bold.woff2',
]
"inter/Inter-Regular.woff2",
"inter/Inter-Medium.woff2",
"inter/Inter-SemiBold.woff2",
"inter/Inter-Bold.woff2",
];
const favicons = {
'(prefers-color-scheme:no-preference)': '/favicon-light.ico',
'(prefers-color-scheme:light)': '/favicon-light.ico',
'(prefers-color-scheme:dark)': '/favicon.ico',
}
"(prefers-color-scheme:no-preference)": "/favicon-light.ico",
"(prefers-color-scheme:light)": "/favicon-light.ico",
"(prefers-color-scheme:dark)": "/favicon.ico",
};
/**
* Tags of locales that are auto-discovered besides the default locale.
@@ -30,52 +29,52 @@ const favicons = {
* Preferably only the locales that reach a certain threshold of complete
* translations would be included in this array.
*/
const enabledLocales: string[] = []
const enabledLocales: string[] = [];
/**
* Overrides for the categories of the certain locales.
*/
const localesCategoriesOverrides: Partial<Record<string, 'fun' | 'experimental'>> = {
'en-x-pirate': 'fun',
'en-x-updown': 'fun',
'en-x-lolcat': 'fun',
'en-x-uwu': 'fun',
'ru-x-bandit': 'fun',
ar: 'experimental',
he: 'experimental',
pes: 'experimental',
}
const localesCategoriesOverrides: Partial<Record<string, "fun" | "experimental">> = {
"en-x-pirate": "fun",
"en-x-updown": "fun",
"en-x-lolcat": "fun",
"en-x-uwu": "fun",
"ru-x-bandit": "fun",
ar: "experimental",
he: "experimental",
pes: "experimental",
};
export default defineNuxtConfig({
srcDir: 'src/',
srcDir: "src/",
app: {
head: {
htmlAttrs: {
lang: 'en',
lang: "en",
},
title: 'Modrinth',
title: "Modrinth",
link: [
// The type is necessary because the linter can't always compare this very nested/complex type on itself
...preloadedFonts.map((font): object => {
return {
rel: 'preload',
rel: "preload",
href: `https://cdn-raw.modrinth.com/fonts/${font}?v=3.19`,
as: 'font',
type: 'font/woff2',
crossorigin: 'anonymous',
}
as: "font",
type: "font/woff2",
crossorigin: "anonymous",
};
}),
...Object.entries(favicons).map(([media, href]): object => {
return { rel: 'icon', type: 'image/x-icon', href, media }
return { rel: "icon", type: "image/x-icon", href, media };
}),
...Object.entries(favicons).map(([media, href]): object => {
return { rel: 'apple-touch-icon', type: 'image/x-icon', href, media, sizes: '64x64' }
return { rel: "apple-touch-icon", type: "image/x-icon", href, media, sizes: "64x64" };
}),
{
rel: 'search',
type: 'application/opensearchdescription+xml',
href: '/opensearch.xml',
title: 'Modrinth mods',
rel: "search",
type: "application/opensearchdescription+xml",
href: "/opensearch.xml",
title: "Modrinth mods",
},
],
},
@@ -86,19 +85,19 @@ export default defineNuxtConfig({
},
esbuild: {
define: {
global: 'globalThis',
global: "globalThis",
},
},
cacheDir: '../../node_modules/.vite/apps/knossos',
cacheDir: "../../node_modules/.vite/apps/knossos",
resolve: {
dedupe: ['vue'],
dedupe: ["vue"],
},
plugins: [
svgLoader({
svgoConfig: {
plugins: [
{
name: 'preset-default',
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
@@ -111,66 +110,60 @@ export default defineNuxtConfig({
],
},
hooks: {
async 'build:before'() {
async "build:before"() {
// 30 minutes
const TTL = 30 * 60 * 1000
const TTL = 30 * 60 * 1000;
let state: {
lastGenerated?: string
apiUrl?: string
categories?: any[]
loaders?: any[]
gameVersions?: any[]
donationPlatforms?: any[]
reportTypes?: any[]
homePageProjects?: any[]
homePageSearch?: any[]
homePageNotifs?: any[]
products?: any[]
errors?: number[]
} = {}
lastGenerated?: string;
apiUrl?: string;
categories?: any[];
loaders?: any[];
gameVersions?: any[];
donationPlatforms?: any[];
reportTypes?: any[];
homePageProjects?: any[];
homePageSearch?: any[];
homePageNotifs?: any[];
products?: any[];
errors?: number[];
} = {};
try {
state = JSON.parse(await fs.readFile('./src/generated/state.json', 'utf8'))
state = JSON.parse(await fs.readFile("./src/generated/state.json", "utf8"));
} catch {
// File doesn't exist, create folder
await fs.mkdir('./src/generated', { recursive: true })
await fs.mkdir("./src/generated", { recursive: true });
}
const API_URL = getApiUrl()
const API_URL = getApiUrl();
if (
// Skip regeneration if within TTL...
state.lastGenerated &&
new Date(state.lastGenerated).getTime() + TTL > new Date().getTime() &&
// ...but only if the API URL is the same
state.apiUrl === API_URL &&
// ...and if no errors were caught during the last generation
(state.errors ?? []).length === 0
state.apiUrl === API_URL
) {
console.log(
"Tags already recently generated. Delete apps/frontend/generated/state.json to force regeneration.",
);
return
return;
}
state.lastGenerated = new Date().toISOString()
state.lastGenerated = new Date().toISOString();
state.apiUrl = API_URL
state.apiUrl = API_URL;
const headers = {
headers: {
'user-agent': 'Knossos generator (support@modrinth.com)',
"user-agent": "Knossos generator (support@modrinth.com)",
},
}
};
const caughtErrorCodes = new Set<number>()
const caughtErrorCodes = new Set<number>();
function handleFetchError(err: any, defaultValue: any) {
console.error('Error generating state: ', err)
caughtErrorCodes.add(err.status)
return defaultValue
console.error("Error generating state: ", err);
caughtErrorCodes.add(err.status);
return defaultValue;
}
const [
@@ -200,152 +193,152 @@ export default defineNuxtConfig({
$fetch(`${API_URL}search?limit=3&query=&index=updated`, headers).catch((err) =>
handleFetchError(err, {}),
),
$fetch(`${API_URL.replace('/v2/', '/_internal/')}billing/products`, headers).catch((err) =>
$fetch(`${API_URL.replace("/v2/", "/_internal/")}billing/products`, headers).catch((err) =>
handleFetchError(err, []),
),
])
]);
state.categories = categories
state.loaders = loaders
state.gameVersions = gameVersions
state.donationPlatforms = donationPlatforms
state.reportTypes = reportTypes
state.homePageProjects = homePageProjects
state.homePageSearch = homePageSearch
state.homePageNotifs = homePageNotifs
state.products = products
state.errors = [...caughtErrorCodes]
state.categories = categories;
state.loaders = loaders;
state.gameVersions = gameVersions;
state.donationPlatforms = donationPlatforms;
state.reportTypes = reportTypes;
state.homePageProjects = homePageProjects;
state.homePageSearch = homePageSearch;
state.homePageNotifs = homePageNotifs;
state.products = products;
state.errors = [...caughtErrorCodes];
await fs.writeFile('./src/generated/state.json', JSON.stringify(state))
await fs.writeFile("./src/generated/state.json", JSON.stringify(state));
console.log('Tags generated!')
console.log("Tags generated!");
},
'pages:extend'(routes) {
"pages:extend"(routes) {
routes.splice(
routes.findIndex((x) => x.name === 'search-searchProjectType'),
routes.findIndex((x) => x.name === "search-searchProjectType"),
1,
)
);
const types = ['mods', 'modpacks', 'plugins', 'resourcepacks', 'shaders', 'datapacks']
const types = ["mods", "modpacks", "plugins", "resourcepacks", "shaders", "datapacks"];
types.forEach((type) =>
routes.push({
name: `search-${type}`,
path: `/${type}`,
file: resolve(__dirname, 'src/pages/search/[searchProjectType].vue'),
file: resolve(__dirname, "src/pages/search/[searchProjectType].vue"),
children: [],
}),
)
);
},
async 'vintl:extendOptions'(opts) {
opts.locales ??= []
async "vintl:extendOptions"(opts) {
opts.locales ??= [];
const isProduction = getDomain() === 'https://modrinth.com'
const isProduction = getDomain() === "https://modrinth.com";
const resolveCompactNumberDataImport = await (async () => {
const compactNumberLocales: string[] = []
const compactNumberLocales: string[] = [];
for await (const localeFile of globIterate(
'node_modules/@vintl/compact-number/dist/locale-data/*.mjs',
{ ignore: '**/*.data.mjs' },
"node_modules/@vintl/compact-number/dist/locale-data/*.mjs",
{ ignore: "**/*.data.mjs" },
)) {
const tag = basename(localeFile, '.mjs')
compactNumberLocales.push(tag)
const tag = basename(localeFile, ".mjs");
compactNumberLocales.push(tag);
}
function resolveImport(tag: string) {
const matchedTag = matchLocale([tag], compactNumberLocales, 'en-x-placeholder')
return matchedTag === 'en-x-placeholder'
const matchedTag = matchLocale([tag], compactNumberLocales, "en-x-placeholder");
return matchedTag === "en-x-placeholder"
? undefined
: `@vintl/compact-number/locale-data/${matchedTag}`
: `@vintl/compact-number/locale-data/${matchedTag}`;
}
return resolveImport
})()
return resolveImport;
})();
const resolveOmorphiaLocaleImport = await (async () => {
const omorphiaLocales: string[] = []
const omorphiaLocaleSets = new Map<string, { files: { from: string }[] }>()
const omorphiaLocales: string[] = [];
const omorphiaLocaleSets = new Map<string, { files: { from: string }[] }>();
for await (const localeDir of globIterate('node_modules/@modrinth/ui/src/locales/*', {
for await (const localeDir of globIterate("node_modules/@modrinth/ui/src/locales/*", {
posix: true,
})) {
const tag = basename(localeDir)
omorphiaLocales.push(tag)
const tag = basename(localeDir);
omorphiaLocales.push(tag);
const localeFiles: { from: string; format?: string }[] = []
const localeFiles: { from: string; format?: string }[] = [];
omorphiaLocaleSets.set(tag, { files: localeFiles })
omorphiaLocaleSets.set(tag, { files: localeFiles });
for await (const localeFile of globIterate(`${localeDir}/*`, { posix: true })) {
localeFiles.push({
from: pathToFileURL(localeFile).toString(),
format: 'default',
})
format: "default",
});
}
}
return function resolveLocaleImport(tag: string) {
return omorphiaLocaleSets.get(matchLocale([tag], omorphiaLocales, 'en-x-placeholder'))
}
})()
return omorphiaLocaleSets.get(matchLocale([tag], omorphiaLocales, "en-x-placeholder"));
};
})();
for await (const localeDir of globIterate('src/locales/*/', { posix: true })) {
const tag = basename(localeDir)
if (isProduction && !enabledLocales.includes(tag) && opts.defaultLocale !== tag) continue
for await (const localeDir of globIterate("src/locales/*/", { posix: true })) {
const tag = basename(localeDir);
if (isProduction && !enabledLocales.includes(tag) && opts.defaultLocale !== tag) continue;
const locale =
opts.locales.find((locale) => locale.tag === tag) ??
opts.locales[opts.locales.push({ tag }) - 1]!
opts.locales[opts.locales.push({ tag }) - 1]!;
const localeFiles = (locale.files ??= [])
const localeFiles = (locale.files ??= []);
for await (const localeFile of globIterate(`${localeDir}/*`, { posix: true })) {
const fileName = basename(localeFile)
if (fileName === 'index.json') {
const fileName = basename(localeFile);
if (fileName === "index.json") {
localeFiles.push({
from: `./${relative('./src', localeFile)}`,
format: 'crowdin',
})
} else if (fileName === 'meta.json') {
from: `./${relative("./src", localeFile)}`,
format: "crowdin",
});
} else if (fileName === "meta.json") {
const meta: Record<string, { message: string }> = await fs
.readFile(localeFile, 'utf8')
.then((date) => JSON.parse(date))
const localeMeta = (locale.meta ??= {})
.readFile(localeFile, "utf8")
.then((date) => JSON.parse(date));
const localeMeta = (locale.meta ??= {});
for (const key in meta) {
const value = meta[key]
if (value === undefined) continue
localeMeta[key] = value.message
const value = meta[key];
if (value === undefined) continue;
localeMeta[key] = value.message;
}
} else {
;(locale.resources ??= {})[fileName] = `./${relative('./src', localeFile)}`
(locale.resources ??= {})[fileName] = `./${relative("./src", localeFile)}`;
}
}
const categoryOverride = localesCategoriesOverrides[tag]
const categoryOverride = localesCategoriesOverrides[tag];
if (categoryOverride != null) {
;(locale.meta ??= {}).category = categoryOverride
(locale.meta ??= {}).category = categoryOverride;
}
const omorphiaLocaleData = resolveOmorphiaLocaleImport(tag)
const omorphiaLocaleData = resolveOmorphiaLocaleImport(tag);
if (omorphiaLocaleData != null) {
localeFiles.push(...omorphiaLocaleData.files)
localeFiles.push(...omorphiaLocaleData.files);
}
const cnDataImport = resolveCompactNumberDataImport(tag)
const cnDataImport = resolveCompactNumberDataImport(tag);
if (cnDataImport != null) {
;(locale.additionalImports ??= []).push({
(locale.additionalImports ??= []).push({
from: cnDataImport,
resolve: false,
})
});
}
}
},
},
runtimeConfig: {
// @ts-expect-error
// @ts-ignore
apiBaseUrl: process.env.BASE_URL ?? globalThis.BASE_URL ?? getApiUrl(),
// @ts-expect-error
// @ts-ignore
rateLimitKey: process.env.RATE_LIMIT_IGNORE_KEY ?? globalThis.RATE_LIMIT_IGNORE_KEY,
pyroBaseUrl: process.env.PYRO_BASE_URL,
public: {
@@ -355,26 +348,25 @@ export default defineNuxtConfig({
production: isProduction(),
featureFlagOverrides: getFeatureFlagOverrides(),
owner: process.env.VERCEL_GIT_REPO_OWNER || 'modrinth',
slug: process.env.VERCEL_GIT_REPO_SLUG || 'code',
owner: process.env.VERCEL_GIT_REPO_OWNER || "modrinth",
slug: process.env.VERCEL_GIT_REPO_SLUG || "code",
branch:
process.env.VERCEL_GIT_COMMIT_REF ||
process.env.CF_PAGES_BRANCH ||
// @ts-expect-error
// @ts-ignore
globalThis.CF_PAGES_BRANCH ||
'master',
"master",
hash:
process.env.VERCEL_GIT_COMMIT_SHA ||
process.env.CF_PAGES_COMMIT_SHA ||
// @ts-expect-error
// @ts-ignore
globalThis.CF_PAGES_COMMIT_SHA ||
'unknown',
"unknown",
stripePublishableKey:
process.env.STRIPE_PUBLISHABLE_KEY ||
// @ts-expect-error
globalThis.STRIPE_PUBLISHABLE_KEY ||
'pk_test_51JbFxJJygY5LJFfKV50mnXzz3YLvBVe2Gd1jn7ljWAkaBlRz3VQdxN9mXcPSrFbSqxwAb0svte9yhnsmm7qHfcWn00R611Ce7b',
"pk_test_51JbFxJJygY5LJFfKV50mnXzz3YLvBVe2Gd1jn7ljWAkaBlRz3VQdxN9mXcPSrFbSqxwAb0svte9yhnsmm7qHfcWn00R611Ce7b",
},
},
typescript: {
@@ -383,62 +375,62 @@ export default defineNuxtConfig({
typeCheck: false,
tsConfig: {
compilerOptions: {
moduleResolution: 'bundler',
moduleResolution: "bundler",
allowImportingTsExtensions: true,
},
},
},
modules: ['@vintl/nuxt', '@pinia/nuxt'],
modules: ["@vintl/nuxt", "@pinia/nuxt"],
vintl: {
defaultLocale: 'en-US',
defaultLocale: "en-US",
locales: [
{
tag: 'en-US',
tag: "en-US",
meta: {
static: {
iso: 'en',
iso: "en",
},
},
},
],
storage: 'cookie',
parserless: 'only-prod',
storage: "cookie",
parserless: "only-prod",
seo: {
defaultLocaleHasParameter: false,
},
onParseError({ error, message, messageId, moduleId, parseMessage, parserOptions }) {
const errorMessage = String(error)
const modulePath = relative(__dirname, moduleId)
const errorMessage = String(error);
const modulePath = relative(__dirname, moduleId);
try {
const fallback = parseMessage(message, { ...parserOptions, ignoreTag: true })
const fallback = parseMessage(message, { ...parserOptions, ignoreTag: true });
consola.warn(
`[i18n] ${messageId} in ${modulePath} cannot be parsed normally due to ${errorMessage}. The tags will will not be parsed.`,
)
);
return fallback
return fallback;
} catch (err) {
const secondaryErrorMessage = String(err)
const secondaryErrorMessage = String(err);
const reason =
errorMessage === secondaryErrorMessage
? errorMessage
: `${errorMessage} and ${secondaryErrorMessage}`
: `${errorMessage} and ${secondaryErrorMessage}`;
consola.warn(
`[i18n] ${messageId} in ${modulePath} cannot be parsed due to ${reason}. It will be skipped.`,
)
);
}
},
},
nitro: {
moduleSideEffects: ['@vintl/compact-number/locale-data'],
moduleSideEffects: ["@vintl/compact-number/locale-data"],
},
devtools: {
enabled: true,
},
css: ['~/assets/styles/tailwind.css'],
css: ["~/assets/styles/tailwind.css"],
postcss: {
plugins: {
tailwindcss: {},
@@ -446,50 +438,50 @@ export default defineNuxtConfig({
},
},
routeRules: {
'/**': {
"/**": {
headers: {
'Accept-CH': 'Sec-CH-Prefers-Color-Scheme',
'Critical-CH': 'Sec-CH-Prefers-Color-Scheme',
"Accept-CH": "Sec-CH-Prefers-Color-Scheme",
"Critical-CH": "Sec-CH-Prefers-Color-Scheme",
},
},
},
compatibilityDate: '2024-07-03',
compatibilityDate: "2024-07-03",
telemetry: false,
})
});
function getApiUrl() {
// @ts-expect-error
return process.env.BROWSER_BASE_URL ?? globalThis.BROWSER_BASE_URL ?? STAGING_API_URL
// @ts-ignore
return process.env.BROWSER_BASE_URL ?? globalThis.BROWSER_BASE_URL ?? STAGING_API_URL;
}
function isProduction() {
return process.env.NODE_ENV === 'production'
return process.env.NODE_ENV === "production";
}
function getFeatureFlagOverrides() {
return JSON.parse(process.env.FLAG_OVERRIDES ?? '{}')
return JSON.parse(process.env.FLAG_OVERRIDES ?? "{}");
}
function getDomain() {
if (process.env.NODE_ENV === 'production') {
if (process.env.NODE_ENV === "production") {
if (process.env.SITE_URL) {
return process.env.SITE_URL
return process.env.SITE_URL;
}
// @ts-expect-error
// @ts-ignore
else if (process.env.CF_PAGES_URL || globalThis.CF_PAGES_URL) {
// @ts-expect-error
return process.env.CF_PAGES_URL ?? globalThis.CF_PAGES_URL
// @ts-ignore
return process.env.CF_PAGES_URL ?? globalThis.CF_PAGES_URL;
} else if (process.env.HEROKU_APP_NAME) {
return `https://${process.env.HEROKU_APP_NAME}.herokuapp.com`
return `https://${process.env.HEROKU_APP_NAME}.herokuapp.com`;
} else if (process.env.VERCEL_URL) {
return `https://${process.env.VERCEL_URL}`
return `https://${process.env.VERCEL_URL}`;
} else if (getApiUrl() === STAGING_API_URL) {
return 'https://staging.modrinth.com'
return "https://staging.modrinth.com";
} else {
return 'https://modrinth.com'
return "https://modrinth.com";
}
} else {
const port = process.env.PORT || 3000
return `http://localhost:${port}`
const port = process.env.PORT || 3000;
return `http://localhost:${port}`;
}
}

View File

@@ -71,6 +71,5 @@
"vue3-apexcharts": "^1.5.2",
"xss": "^1.0.14"
},
"web-types": "../../web-types.json",
"prettier": "@modrinth/tooling-config/prettier.nuxt.config.js"
"web-types": "../../web-types.json"
}

View File

@@ -6,6 +6,6 @@
</NuxtLayout>
</template>
<script setup lang="ts">
import ModrinthLoadingIndicator from '~/components/ui/modrinth-loading-indicator.ts'
import Notifications from '~/components/ui/Notifications.vue'
import ModrinthLoadingIndicator from "~/components/ui/modrinth-loading-indicator.ts";
import Notifications from "~/components/ui/Notifications.vue";
</script>

Some files were not shown because too many files have changed in this diff Show More