You've already forked AstralRinth
forked from didirus/AstralRinth
Merge remote-tracking branch 'upstream/main' into beta
This commit is contained in:
@@ -3,8 +3,7 @@ root = true
|
|||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = "tab"
|
||||||
indent_size = 4
|
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
@@ -15,5 +14,5 @@ indent_size = 2
|
|||||||
max_line_length = off
|
max_line_length = off
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
[*.{json,yml,yaml,ts,vue,scss,css,html,js,cjs,mjs,gltf,prettierrc}]
|
[*.{json,yml,yaml}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|||||||
12
.vscode/settings.json
vendored
12
.vscode/settings.json
vendored
@@ -2,8 +2,14 @@
|
|||||||
"prettier.endOfLine": "lf",
|
"prettier.endOfLine": "lf",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
|
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
|
||||||
"editor.detectIndentation": true,
|
"editor.detectIndentation": false,
|
||||||
|
"editor.insertSpaces": false,
|
||||||
|
"files.eol": "\n",
|
||||||
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"files.insertFinalNewline": true,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit"
|
"source.fixAll.eslint": "explicit",
|
||||||
}
|
"source.organizeImports": "always"
|
||||||
|
},
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
All packages in this repository are licensed under their respective licenses. For more information, refer to the LICENSE file in each package.
|
All packages in this repository are licensed under their respective licenses. For more information, refer to the LICENSE file in each package.
|
||||||
|
|
||||||
For detailed information, consult each package's COPYING.md file, if available.
|
For detailed information, consult each package's COPYING.md, LICENSE.txt, or LICENSE file, if available.
|
||||||
|
|
||||||
## Modrinth Branding
|
## Modrinth Branding
|
||||||
|
|
||||||
|
|||||||
578
Cargo.lock
generated
578
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,3 @@
|
|||||||
**/dist
|
**/dist
|
||||||
*.gltf
|
*.gltf
|
||||||
|
src/locales/
|
||||||
|
|||||||
@@ -1,22 +1,2 @@
|
|||||||
import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
|
import config from '@modrinth/tooling-config/eslint/nuxt.mjs'
|
||||||
import { fixupPluginRules } from '@eslint/compat'
|
export default config
|
||||||
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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<script src="https://tally.so/widgets/embed.js" async></script>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"vue-virtual-scroller": "v2.0.0-beta.8"
|
"vue-virtual-scroller": "v2.0.0-beta.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@modrinth/tooling-config": "workspace:*",
|
||||||
"@eslint/compat": "^1.1.1",
|
"@eslint/compat": "^1.1.1",
|
||||||
"@formatjs/cli": "^6.2.12",
|
"@formatjs/cli": "^6.2.12",
|
||||||
"@nuxt/eslint-config": "^0.5.6",
|
"@nuxt/eslint-config": "^0.5.6",
|
||||||
@@ -48,13 +49,11 @@
|
|||||||
"@vitejs/plugin-vue": "^5.0.4",
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-config-custom": "workspace:*",
|
|
||||||
"eslint-plugin-turbo": "^2.5.4",
|
"eslint-plugin-turbo": "^2.5.4",
|
||||||
"postcss": "^8.4.39",
|
"postcss": "^8.4.39",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.74.1",
|
"sass": "^1.74.1",
|
||||||
"tailwindcss": "^3.4.4",
|
"tailwindcss": "^3.4.4",
|
||||||
"tsconfig": "workspace:*",
|
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"vite": "^5.4.6",
|
"vite": "^5.4.6",
|
||||||
"vue-tsc": "^2.1.6"
|
"vue-tsc": "^2.1.6"
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, onUnmounted, ref, watch, provide } from 'vue'
|
|
||||||
import { RouterView, useRoute, useRouter } from 'vue-router'
|
|
||||||
import {
|
import {
|
||||||
ArrowBigUpDashIcon,
|
ArrowBigUpDashIcon,
|
||||||
ChangeSkinIcon,
|
ChangeSkinIcon,
|
||||||
@@ -13,21 +11,23 @@ import {
|
|||||||
LogOutIcon,
|
LogOutIcon,
|
||||||
MaximizeIcon,
|
MaximizeIcon,
|
||||||
MinimizeIcon,
|
MinimizeIcon,
|
||||||
|
NewspaperIcon,
|
||||||
|
NotepadTextIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
RestoreIcon,
|
RestoreIcon,
|
||||||
RightArrowIcon,
|
RightArrowIcon,
|
||||||
SettingsIcon,
|
SettingsIcon,
|
||||||
WorldIcon,
|
WorldIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
NewspaperIcon,
|
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
Notifications,
|
|
||||||
OverflowMenu,
|
|
||||||
NewsArticleCard,
|
NewsArticleCard,
|
||||||
|
NotificationPanel,
|
||||||
|
OverflowMenu,
|
||||||
|
provideNotificationManager,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
import { useLoading, useTheming } from '@/store/state'
|
import { useLoading, useTheming } from '@/store/state'
|
||||||
// import ModrinthAppLogo from '@/assets/modrinth_app.svg?component'
|
// import ModrinthAppLogo from '@/assets/modrinth_app.svg?component'
|
||||||
@@ -39,46 +39,54 @@ import RunningAppBar from '@/components/ui/RunningAppBar.vue'
|
|||||||
import SplashScreen from '@/components/ui/SplashScreen.vue'
|
import SplashScreen from '@/components/ui/SplashScreen.vue'
|
||||||
import ErrorModal from '@/components/ui/ErrorModal.vue'
|
import ErrorModal from '@/components/ui/ErrorModal.vue'
|
||||||
import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue'
|
import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue'
|
||||||
import { handleError, useNotifications } from '@/store/notifications.js'
|
|
||||||
import { command_listener, warning_listener } from '@/helpers/events.js'
|
import { command_listener, warning_listener } from '@/helpers/events.js'
|
||||||
import { type } from '@tauri-apps/plugin-os'
|
import { type } from '@tauri-apps/plugin-os'
|
||||||
import { getOS, isDev } from '@/helpers/utils.js'
|
|
||||||
import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics'
|
import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics'
|
||||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||||
|
import { renderString } from '@modrinth/utils'
|
||||||
import { getVersion } from '@tauri-apps/api/app'
|
import { getVersion } from '@tauri-apps/api/app'
|
||||||
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import { create_profile_and_install_from_file } from './helpers/pack'
|
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||||
import { useError } from '@/store/error.js'
|
import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'
|
||||||
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
|
import { $fetch } from 'ofetch'
|
||||||
import ModInstallModal from '@/components/ui/install_flow/ModInstallModal.vue'
|
import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue'
|
||||||
|
import { RouterView, useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
import FriendsList from '@/components/ui/friends/FriendsList.vue'
|
||||||
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
|
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
|
||||||
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
|
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
|
||||||
import { useInstall } from '@/store/install.js'
|
import { useInstall } from '@/store/install.js'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
|
||||||
import { get_opening_command, initialize_state } from '@/helpers/state'
|
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 { useFetch } from '@/helpers/fetch.js'
|
||||||
// import { check } from '@tauri-apps/plugin-updater'
|
|
||||||
import NavButton from '@/components/ui/NavButton.vue'
|
import NavButton from '@/components/ui/NavButton.vue'
|
||||||
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.js'
|
import { cancelLogin, get as getCreds, login, logout } from '@/helpers/mr_auth.js'
|
||||||
import { get_user } from '@/helpers/cache.js'
|
import { get_user } from '@/helpers/cache.js'
|
||||||
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
|
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
|
||||||
import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue'
|
import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue'
|
||||||
// import PromotionWrapper from '@/components/ui/PromotionWrapper.vue'
|
import ModInstallModal from '@/components/ui/install_flow/ModInstallModal.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 QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue'
|
||||||
import { get_available_capes, get_available_skins } from './helpers/skins'
|
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
|
||||||
|
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
|
||||||
|
import { list } from '@/helpers/profile.js'
|
||||||
|
import { getOS, isDev } from '@/helpers/utils.js'
|
||||||
|
import { useError } from '@/store/error.js'
|
||||||
|
|
||||||
|
import { create_profile_and_install_from_file } from './helpers/pack'
|
||||||
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
|
import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer'
|
||||||
|
import { get_available_capes, get_available_skins } from './helpers/skins'
|
||||||
|
import { AppNotificationManager } from './providers/app-notifications'
|
||||||
|
|
||||||
// [AR] Feature
|
// [AR] Feature
|
||||||
import { getRemote, updateState } from '@/helpers/update.js'
|
import { getRemote, updateState } from '@/helpers/update.js'
|
||||||
|
|
||||||
const themeStore = useTheming()
|
const themeStore = useTheming()
|
||||||
|
|
||||||
|
const notificationManager = new AppNotificationManager()
|
||||||
|
provideNotificationManager(notificationManager)
|
||||||
|
const { handleError, addNotification } = notificationManager
|
||||||
|
|
||||||
const news = ref([])
|
const news = ref([])
|
||||||
|
const availableSurvey = ref(false)
|
||||||
|
|
||||||
const urlModal = ref(null)
|
const urlModal = ref(null)
|
||||||
|
|
||||||
@@ -115,15 +123,14 @@ onUnmounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function setupApp() {
|
async function setupApp() {
|
||||||
stateInitialized.value = true
|
|
||||||
|
|
||||||
const settings = await get()
|
const settings = await get()
|
||||||
|
|
||||||
// Patched
|
// [AR] Patched
|
||||||
settings.personalized_ads = false
|
settings.personalized_ads = false
|
||||||
settings.telemetry = false
|
settings.telemetry = false
|
||||||
await set(settings)
|
await set(settings)
|
||||||
|
|
||||||
|
stateInitialized.value = true
|
||||||
const {
|
const {
|
||||||
native_decorations,
|
native_decorations,
|
||||||
theme,
|
theme,
|
||||||
@@ -136,8 +143,7 @@ async function setupApp() {
|
|||||||
toggle_sidebar,
|
toggle_sidebar,
|
||||||
developer_mode,
|
developer_mode,
|
||||||
feature_flags,
|
feature_flags,
|
||||||
} = settings
|
} = await get()
|
||||||
|
|
||||||
|
|
||||||
if (default_page === 'Library') {
|
if (default_page === 'Library') {
|
||||||
await router.push('/library')
|
await router.push('/library')
|
||||||
@@ -164,7 +170,7 @@ async function setupApp() {
|
|||||||
isMaximized.value = await getCurrentWindow().isMaximized()
|
isMaximized.value = await getCurrentWindow().isMaximized()
|
||||||
})
|
})
|
||||||
|
|
||||||
initAnalytics()
|
// initAnalytics()
|
||||||
if (!telemetry) {
|
if (!telemetry) {
|
||||||
console.info("[AR] • Telemetry disabled by default (Hard patched).")
|
console.info("[AR] • Telemetry disabled by default (Hard patched).")
|
||||||
optOutAnalytics()
|
optOutAnalytics()
|
||||||
@@ -186,7 +192,7 @@ async function setupApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await warning_listener((e) =>
|
await warning_listener((e) =>
|
||||||
notificationsWrapper.value.addNotification({
|
addNotification({
|
||||||
title: 'Warning',
|
title: 'Warning',
|
||||||
text: e.message,
|
text: e.message,
|
||||||
type: 'warn',
|
type: 'warn',
|
||||||
@@ -240,6 +246,12 @@ async function setupApp() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to generate skin previews in app setup.', error)
|
console.warn('Failed to generate skin previews in app setup.', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (osType === 'windows') {
|
||||||
|
await processPendingSurveys()
|
||||||
|
} else {
|
||||||
|
console.info('Skipping user surveys on non-Windows platforms')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const stateFailed = ref(false)
|
const stateFailed = ref(false)
|
||||||
@@ -271,9 +283,6 @@ const route = useRoute()
|
|||||||
const loading = useLoading()
|
const loading = useLoading()
|
||||||
loading.setEnabled(false)
|
loading.setEnabled(false)
|
||||||
|
|
||||||
const notifications = useNotifications()
|
|
||||||
const notificationsWrapper = ref()
|
|
||||||
|
|
||||||
const error = useError()
|
const error = useError()
|
||||||
const errorModal = ref()
|
const errorModal = ref()
|
||||||
|
|
||||||
@@ -355,8 +364,6 @@ const sidebarVisible = computed(() => sidebarToggled.value || forceSidebar.value
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
invoke('show_window')
|
invoke('show_window')
|
||||||
|
|
||||||
notifications.setNotifs(notificationsWrapper.value)
|
|
||||||
|
|
||||||
error.setErrorModal(errorModal.value)
|
error.setErrorModal(errorModal.value)
|
||||||
|
|
||||||
install.setIncompatibilityWarningModal(incompatibilityWarningModal)
|
install.setIncompatibilityWarningModal(incompatibilityWarningModal)
|
||||||
@@ -432,6 +439,116 @@ function handleAuxClick(e) {
|
|||||||
e.target.dispatchEvent(event)
|
e.target.dispatchEvent(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cleanupOldSurveyDisplayData() {
|
||||||
|
const threeWeeksAgo = new Date()
|
||||||
|
threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21)
|
||||||
|
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const key = localStorage.key(i)
|
||||||
|
|
||||||
|
if (key.startsWith('survey-') && key.endsWith('-display')) {
|
||||||
|
const dateValue = new Date(localStorage.getItem(key))
|
||||||
|
if (dateValue < threeWeeksAgo) {
|
||||||
|
localStorage.removeItem(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openSurvey() {
|
||||||
|
if (!availableSurvey.value) {
|
||||||
|
console.error('No survey to open')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const creds = await getCreds().catch(handleError)
|
||||||
|
const userId = creds?.user_id
|
||||||
|
|
||||||
|
const formId = availableSurvey.value.tally_id
|
||||||
|
|
||||||
|
const popupOptions = {
|
||||||
|
layout: 'modal',
|
||||||
|
width: 700,
|
||||||
|
autoClose: 2000,
|
||||||
|
hideTitle: true,
|
||||||
|
hiddenFields: {
|
||||||
|
user_id: userId,
|
||||||
|
},
|
||||||
|
onOpen: () => console.info('Opened user survey'),
|
||||||
|
onClose: () => {
|
||||||
|
console.info('Closed user survey')
|
||||||
|
// show_ads_window()
|
||||||
|
},
|
||||||
|
onSubmit: () => console.info('Active user survey submitted'),
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// hide_ads_window()
|
||||||
|
if (window.Tally?.openPopup) {
|
||||||
|
console.info(`Opening Tally popup for user survey (form ID: ${formId})`)
|
||||||
|
dismissSurvey()
|
||||||
|
window.Tally.openPopup(formId, popupOptions)
|
||||||
|
} else {
|
||||||
|
console.warn('Tally script not yet loaded')
|
||||||
|
// show_ads_window()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error opening Tally popup:', e)
|
||||||
|
// show_ads_window()
|
||||||
|
}
|
||||||
|
|
||||||
|
console.info(`Found user survey to show with tally_id: ${formId}`)
|
||||||
|
window.Tally.openPopup(formId, popupOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissSurvey() {
|
||||||
|
localStorage.setItem(`survey-${availableSurvey.value.id}-display`, new Date())
|
||||||
|
availableSurvey.value = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processPendingSurveys() {
|
||||||
|
function isWithinLastTwoWeeks(date) {
|
||||||
|
const twoWeeksAgo = new Date()
|
||||||
|
twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14)
|
||||||
|
return date >= twoWeeksAgo
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanupOldSurveyDisplayData()
|
||||||
|
|
||||||
|
const creds = await getCreds().catch(handleError)
|
||||||
|
const userId = creds?.user_id
|
||||||
|
|
||||||
|
const instances = await list().catch(handleError)
|
||||||
|
const isActivePlayer =
|
||||||
|
instances.findIndex(
|
||||||
|
(instance) =>
|
||||||
|
isWithinLastTwoWeeks(instance.last_played) && !isWithinLastTwoWeeks(instance.created),
|
||||||
|
) >= 0
|
||||||
|
|
||||||
|
let surveys = []
|
||||||
|
try {
|
||||||
|
surveys = await $fetch('https://api.modrinth.com/v2/surveys')
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error fetching surveys:', e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const surveyToShow = surveys.find(
|
||||||
|
(survey) =>
|
||||||
|
!!(
|
||||||
|
localStorage.getItem(`survey-${survey.id}-display`) === null &&
|
||||||
|
survey.type === 'tally_app' &&
|
||||||
|
((survey.condition === 'active_player' && isActivePlayer) ||
|
||||||
|
(survey.assigned_users?.includes(userId) && !survey.dismissed_users?.includes(userId)))
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (surveyToShow) {
|
||||||
|
availableSurvey.value = surveyToShow
|
||||||
|
} else {
|
||||||
|
console.info('No user survey to show')
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -491,7 +608,6 @@ function handleAuxClick(e) {
|
|||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<div class="flex flex-grow"></div>
|
<div class="flex flex-grow"></div>
|
||||||
<!-- [AR] TODO -->
|
|
||||||
<!-- <NavButton v-if="updateAvailable" v-tooltip.right="'Install update'" :to="() => restartApp()">
|
<!-- <NavButton v-if="updateAvailable" v-tooltip.right="'Install update'" :to="() => restartApp()">
|
||||||
<DownloadIcon />
|
<DownloadIcon />
|
||||||
</NavButton> -->
|
</NavButton> -->
|
||||||
@@ -593,6 +709,28 @@ function handleAuxClick(e) {
|
|||||||
:class="{ 'sidebar-enabled': sidebarVisible }"
|
:class="{ 'sidebar-enabled': sidebarVisible }"
|
||||||
>
|
>
|
||||||
<div class="app-viewport flex-grow router-view">
|
<div class="app-viewport flex-grow router-view">
|
||||||
|
<transition name="popup-survey">
|
||||||
|
<div
|
||||||
|
v-if="availableSurvey"
|
||||||
|
class="w-[400px] z-20 fixed -bottom-12 pb-16 right-[--right-bar-width] mr-4 rounded-t-2xl card-shadow bg-bg-raised border-divider border-[1px] border-solid border-b-0 p-4"
|
||||||
|
>
|
||||||
|
<h2 class="text-lg font-extrabold mt-0 mb-2">Hey there Modrinth user!</h2>
|
||||||
|
<p class="m-0 leading-tight">
|
||||||
|
Would you mind answering a few questions about your experience with Modrinth App?
|
||||||
|
</p>
|
||||||
|
<p class="mt-3 mb-4 leading-tight">
|
||||||
|
This feedback will go directly to the Modrinth team and help guide future updates!
|
||||||
|
</p>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<ButtonStyled color="brand">
|
||||||
|
<button @click="openSurvey"><NotepadTextIcon /> Take survey</button>
|
||||||
|
</ButtonStyled>
|
||||||
|
<ButtonStyled>
|
||||||
|
<button @click="dismissSurvey"><XIcon /> No thanks</button>
|
||||||
|
</ButtonStyled>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
<div
|
<div
|
||||||
class="loading-indicator-container h-8 fixed z-50"
|
class="loading-indicator-container h-8 fixed z-50"
|
||||||
:style="{
|
:style="{
|
||||||
@@ -672,7 +810,7 @@ function handleAuxClick(e) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <template v-if="showAd">
|
<template v-if="showAd">
|
||||||
<a
|
<a
|
||||||
href="https://modrinth.plus?app"
|
href="https://modrinth.plus?app"
|
||||||
class="absolute bottom-[250px] w-full flex justify-center items-center gap-1 px-4 py-3 text-purple font-medium hover:underline z-10"
|
class="absolute bottom-[250px] w-full flex justify-center items-center gap-1 px-4 py-3 text-purple font-medium hover:underline z-10"
|
||||||
@@ -680,12 +818,12 @@ function handleAuxClick(e) {
|
|||||||
>
|
>
|
||||||
<ArrowBigUpDashIcon class="text-2xl" /> Upgrade to Modrinth+
|
<ArrowBigUpDashIcon class="text-2xl" /> Upgrade to Modrinth+
|
||||||
</a>
|
</a>
|
||||||
<PromotionWrapper />
|
<!-- <PromotionWrapper /> -->
|
||||||
</template> -->
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<URLConfirmModal ref="urlModal" />
|
<URLConfirmModal ref="urlModal" />
|
||||||
<Notifications ref="notificationsWrapper" sidebar />
|
<NotificationPanel has-sidebar />
|
||||||
<ErrorModal ref="errorModal" />
|
<ErrorModal ref="errorModal" />
|
||||||
<ModInstallModal ref="modInstallModal" />
|
<ModInstallModal ref="modInstallModal" />
|
||||||
<IncompatibilityWarningModal ref="incompatibilityWarningModal" />
|
<IncompatibilityWarningModal ref="incompatibilityWarningModal" />
|
||||||
@@ -893,6 +1031,26 @@ function handleAuxClick(e) {
|
|||||||
.sidebar-teleport-content:empty + .sidebar-default-content.sidebar-enabled {
|
.sidebar-teleport-content:empty + .sidebar-default-content.sidebar-enabled {
|
||||||
display: contents;
|
display: contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popup-survey-enter-active {
|
||||||
|
transition:
|
||||||
|
opacity 0.25s ease,
|
||||||
|
transform 0.25s cubic-bezier(0.51, 1.08, 0.35, 1.15);
|
||||||
|
transform-origin: top center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-survey-leave-active {
|
||||||
|
transition:
|
||||||
|
opacity 0.25s ease,
|
||||||
|
transform 0.25s cubic-bezier(0.68, -0.17, 0.23, 0.11);
|
||||||
|
transform-origin: top center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-survey-enter-from,
|
||||||
|
.popup-survey-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10rem) scale(0.8) scaleY(1.6);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<style>
|
<style>
|
||||||
.mac {
|
.mac {
|
||||||
|
|||||||
24
apps/app-frontend/src/assets/external/index.js
vendored
24
apps/app-frontend/src/assets/external/index.js
vendored
@@ -1,18 +1,18 @@
|
|||||||
|
export { default as ATLauncherIcon } from './atlauncher.svg'
|
||||||
export { default as BuyMeACoffeeIcon } from './bmac.svg'
|
export { default as BuyMeACoffeeIcon } from './bmac.svg'
|
||||||
export { default as DiscordIcon } from './discord.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 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 PatreonIcon } from './patreon.svg'
|
||||||
export { default as PaypalIcon } from './paypal.svg'
|
export { default as PaypalIcon } from './paypal.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'
|
export { default as PrismIcon } from './prism.svg'
|
||||||
|
export { default as RedditIcon } from './reddit.svg'
|
||||||
|
export { default as SteamIcon } from './steam.svg'
|
||||||
|
export { default as TwitterIcon } from './twitter.svg'
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
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 AddProjectImage } from './add-project.svg'
|
||||||
export { default as NewInstanceImage } from './new-instance.svg'
|
export { default as SwapIcon } from './arrow-left-right.svg'
|
||||||
export { default as MenuIcon } from './menu.svg'
|
export { default as MenuIcon } from './menu.svg'
|
||||||
export { default as ChatIcon } from './messages-square.svg'
|
export { default as ChatIcon } from './messages-square.svg'
|
||||||
export { default as Pirate } from './pirate.svg'
|
export { default as Pirate } from './pirate.svg'
|
||||||
export { default as Microsoft } from './microsoft.svg'
|
export { default as Microsoft } from './microsoft.svg'
|
||||||
export { default as PirateShip } from './pirate-ship.svg'
|
export { default as PirateShip } from './pirate-ship.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'
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import Instance from '@/components/ui/Instance.vue'
|
|
||||||
import { computed, ref } from 'vue'
|
|
||||||
import {
|
import {
|
||||||
ClipboardCopyIcon,
|
ClipboardCopyIcon,
|
||||||
|
EyeIcon,
|
||||||
FolderOpenIcon,
|
FolderOpenIcon,
|
||||||
PlayIcon,
|
PlayIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
TrashIcon,
|
|
||||||
StopCircleIcon,
|
|
||||||
EyeIcon,
|
|
||||||
SearchIcon,
|
SearchIcon,
|
||||||
|
StopCircleIcon,
|
||||||
|
TrashIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Button, DropdownSelect } from '@modrinth/ui'
|
import { Button, DropdownSelect, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { formatCategoryHeader } from '@modrinth/utils'
|
import { formatCategoryHeader } from '@modrinth/utils'
|
||||||
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { duplicate, remove } from '@/helpers/profile.js'
|
import { computed, ref } from 'vue'
|
||||||
import { handleError } from '@/store/notifications.js'
|
|
||||||
|
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
||||||
|
import Instance from '@/components/ui/Instance.vue'
|
||||||
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
||||||
|
import { duplicate, remove } from '@/helpers/profile.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
instances: {
|
instances: {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
||||||
|
|
||||||
import { useLoading } from '@/store/state.js'
|
import { useLoading } from '@/store/state.js'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@@ -1,31 +1,33 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
ClipboardCopyIcon,
|
ClipboardCopyIcon,
|
||||||
FolderOpenIcon,
|
|
||||||
PlayIcon,
|
|
||||||
PlusIcon,
|
|
||||||
TrashIcon,
|
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
GlobeIcon,
|
|
||||||
StopCircleIcon,
|
|
||||||
ExternalIcon,
|
ExternalIcon,
|
||||||
EyeIcon,
|
EyeIcon,
|
||||||
|
FolderOpenIcon,
|
||||||
|
GlobeIcon,
|
||||||
|
PlayIcon,
|
||||||
|
PlusIcon,
|
||||||
|
StopCircleIcon,
|
||||||
|
TrashIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
import { HeadingLink, injectNotificationManager } from '@modrinth/ui'
|
||||||
import Instance from '@/components/ui/Instance.vue'
|
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||||
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
|
||||||
import ProjectCard from '@/components/ui/ProjectCard.vue'
|
|
||||||
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 { useRouter } from 'vue-router'
|
||||||
import { showProfileInFolder } from '@/helpers/utils.js'
|
|
||||||
|
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
||||||
|
import Instance from '@/components/ui/Instance.vue'
|
||||||
|
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
||||||
|
import ProjectCard from '@/components/ui/ProjectCard.vue'
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
|
import { get_by_profile_path } from '@/helpers/process.js'
|
||||||
|
import { duplicate, kill, remove, run } from '@/helpers/profile.js'
|
||||||
|
import { showProfileInFolder } from '@/helpers/utils.js'
|
||||||
import { handleSevereError } from '@/store/error.js'
|
import { handleSevereError } from '@/store/error.js'
|
||||||
import { install as installVersion } from '@/store/install.js'
|
import { install as installVersion } from '@/store/install.js'
|
||||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
|
||||||
import { HeadingLink } from '@modrinth/ui'
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -163,7 +165,14 @@ const handleOptionsClick = async (args) => {
|
|||||||
await navigator.clipboard.writeText(args.item.path)
|
await navigator.clipboard.writeText(args.item.path)
|
||||||
break
|
break
|
||||||
case 'install': {
|
case 'install': {
|
||||||
await installVersion(args.item.project_id, null, null, 'ProjectCardContextMenu')
|
await installVersion(
|
||||||
|
args.item.project_id,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'ProjectCardContextMenu',
|
||||||
|
() => {},
|
||||||
|
() => {},
|
||||||
|
).catch(handleError)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
<Avatar size="xs" :src="avatarUrl" />
|
<Avatar size="xs" :src="avatarUrl" />
|
||||||
<div>
|
<div>
|
||||||
<h4>
|
<h4>
|
||||||
<component :is="getAccountType(selectedAccount)" class="vector-icon" /> {{ selectedAccount.profile.name }}
|
<component :is="getAccountType(selectedAccount)" class="vector-icon" /> {{
|
||||||
|
selectedAccount.profile.name }}
|
||||||
</h4>
|
</h4>
|
||||||
<p>Selected</p>
|
<p>Selected</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,9 +108,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
<ModalWrapper
|
<ModalWrapper ref="authenticationElybyErrorModal" class="modal"
|
||||||
ref="authenticationElybyErrorModal"
|
|
||||||
class="modal"
|
|
||||||
header="Error while proceeding authentication event with Ely.by">
|
header="Error while proceeding authentication event with Ely.by">
|
||||||
<div class="flex flex-col gap-4 px-6 py-5">
|
<div class="flex flex-col gap-4 px-6 py-5">
|
||||||
<label class="text-base font-medium text-red-700">
|
<label class="text-base font-medium text-red-700">
|
||||||
@@ -181,7 +180,7 @@ import {
|
|||||||
ElyByIcon,
|
ElyByIcon,
|
||||||
SpinnerIcon
|
SpinnerIcon
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Avatar, Button, Card } from '@modrinth/ui'
|
import { Avatar, Button, Card, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { ref, computed, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
|
import { ref, computed, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
|
||||||
import {
|
import {
|
||||||
elyby_auth_authenticate,
|
elyby_auth_authenticate,
|
||||||
@@ -193,13 +192,14 @@ import {
|
|||||||
login as login_flow,
|
login as login_flow,
|
||||||
get_default_user,
|
get_default_user,
|
||||||
} from '@/helpers/auth'
|
} from '@/helpers/auth'
|
||||||
import { handleError } from '@/store/state.js'
|
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
import { process_listener } from '@/helpers/events'
|
import { process_listener } from '@/helpers/events'
|
||||||
import { handleSevereError } from '@/store/error.js'
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
import { get_available_skins } from '@/helpers/skins'
|
|
||||||
import { getPlayerHeadUrl } from '@/helpers/rendering/batch-skin-renderer.ts'
|
import { getPlayerHeadUrl } from '@/helpers/rendering/batch-skin-renderer.ts'
|
||||||
|
import { get_available_skins } from '@/helpers/skins'
|
||||||
|
import { handleSevereError } from '@/store/error.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
mode: {
|
mode: {
|
||||||
@@ -417,7 +417,7 @@ function setLoginDisabled(value) {
|
|||||||
defineExpose({
|
defineExpose({
|
||||||
refreshValues,
|
refreshValues,
|
||||||
setLoginDisabled,
|
setLoginDisabled,
|
||||||
loginDisabled: microsoftLoginDisabled,
|
microsoftLoginDisabled,
|
||||||
})
|
})
|
||||||
await refreshValues()
|
await refreshValues()
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DropdownIcon, PlusIcon, FolderOpenIcon } from '@modrinth/assets'
|
import { DropdownIcon, FolderOpenIcon, PlusIcon } from '@modrinth/assets'
|
||||||
import { ButtonStyled, OverflowMenu } from '@modrinth/ui'
|
import { ButtonStyled, injectNotificationManager, OverflowMenu } from '@modrinth/ui'
|
||||||
import { open } from '@tauri-apps/plugin-dialog'
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { add_project_from_path } from '@/helpers/profile.js'
|
|
||||||
import { handleError } from '@/store/notifications.js'
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
import { add_project_from_path } from '@/helpers/profile.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
instance: {
|
instance: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|||||||
@@ -42,11 +42,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ChevronRightIcon, ChevronLeftIcon } from '@modrinth/assets'
|
import { ChevronLeftIcon, ChevronRightIcon } from '@modrinth/assets'
|
||||||
import { Button } from '@modrinth/ui'
|
import { Button } from '@modrinth/ui'
|
||||||
import { useBreadcrumbs } from '@/store/breadcrumbs'
|
|
||||||
import { useRoute } from 'vue-router'
|
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
import { useBreadcrumbs } from '@/store/breadcrumbs'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<div v-show="shown" ref="contextMenu" class="context-menu" :style="{
|
<div
|
||||||
|
v-show="shown"
|
||||||
|
ref="contextMenu"
|
||||||
|
class="context-menu"
|
||||||
|
:style="{
|
||||||
left: left,
|
left: left,
|
||||||
top: top,
|
top: top,
|
||||||
}">
|
}"
|
||||||
|
>
|
||||||
<div v-for="(option, index) in options" :key="index" @click.stop="optionClicked(option.name)">
|
<div v-for="(option, index) in options" :key="index" @click.stop="optionClicked(option.name)">
|
||||||
<hr v-if="option.type === 'divider'" class="divider" />
|
<hr v-if="option.type === 'divider'" class="divider" />
|
||||||
<div v-else-if="!(isLinkedData(item) && option.name === `add_content`)" class="item clickable"
|
<div
|
||||||
:class="[option.color ?? 'base']">
|
v-else-if="!(isLinkedData(item) && option.name === `add_content`)"
|
||||||
|
class="item clickable"
|
||||||
|
:class="[option.color ?? 'base']"
|
||||||
|
>
|
||||||
<slot :name="option.name" />
|
<slot :name="option.name" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,17 +5,9 @@
|
|||||||
<p class="input-label">Profile Code</p>
|
<p class="input-label">Profile Code</p>
|
||||||
<div class="iconified-input">
|
<div class="iconified-input">
|
||||||
<SearchIcon aria-hidden="true" class="text-lg" />
|
<SearchIcon aria-hidden="true" class="text-lg" />
|
||||||
<input
|
<input ref="codeInput" v-model="profileCode" autocomplete="off" class="h-12 card-shadow"
|
||||||
ref="codeInput"
|
spellcheck="false" type="text" placeholder="Enter CurseForge profile code" maxlength="20"
|
||||||
v-model="profileCode"
|
@keyup.enter="importProfile" />
|
||||||
autocomplete="off"
|
|
||||||
class="h-12 card-shadow"
|
|
||||||
spellcheck="false"
|
|
||||||
type="text"
|
|
||||||
placeholder="Enter CurseForge profile code"
|
|
||||||
maxlength="20"
|
|
||||||
@keyup.enter="importProfile"
|
|
||||||
/>
|
|
||||||
<Button v-if="profileCode" class="r-btn" @click="() => (profileCode = '')">
|
<Button v-if="profileCode" class="r-btn" @click="() => (profileCode = '')">
|
||||||
<XIcon />
|
<XIcon />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -37,10 +29,7 @@
|
|||||||
<span class="progress-percentage">{{ Math.floor(importProgress.percentage) }}%</span>
|
<span class="progress-percentage">{{ Math.floor(importProgress.percentage) }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-bar-container">
|
<div class="progress-bar-container">
|
||||||
<div
|
<div class="progress-bar" :style="{ width: `${importProgress.percentage}%` }"></div>
|
||||||
class="progress-bar"
|
|
||||||
:style="{ width: `${importProgress.percentage}%` }"
|
|
||||||
></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -49,21 +38,12 @@
|
|||||||
<XIcon />
|
<XIcon />
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button v-if="!metadata" @click="fetchMetadata" :disabled="!profileCode.trim() || fetching"
|
||||||
v-if="!metadata"
|
color="secondary">
|
||||||
@click="fetchMetadata"
|
|
||||||
:disabled="!profileCode.trim() || fetching"
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
<SearchIcon v-if="!fetching" />
|
<SearchIcon v-if="!fetching" />
|
||||||
{{ fetching ? 'Checking...' : 'Check Profile' }}
|
{{ fetching ? 'Checking...' : 'Check Profile' }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button v-if="metadata" @click="importProfile" :disabled="importing" color="primary">
|
||||||
v-if="metadata"
|
|
||||||
@click="importProfile"
|
|
||||||
:disabled="importing"
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<DownloadIcon v-if="!importing" />
|
<DownloadIcon v-if="!importing" />
|
||||||
{{ importing ? 'Importing...' : 'Import Profile' }}
|
{{ importing ? 'Importing...' : 'Import Profile' }}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -86,7 +66,6 @@ import {
|
|||||||
fetch_curseforge_profile_metadata,
|
fetch_curseforge_profile_metadata,
|
||||||
import_curseforge_profile
|
import_curseforge_profile
|
||||||
} from '@/helpers/import.js'
|
} from '@/helpers/import.js'
|
||||||
import { handleError } from '@/store/notifications.js'
|
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
import { loading_listener } from '@/helpers/events.js'
|
import { loading_listener } from '@/helpers/events.js'
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
|
CopyIcon,
|
||||||
DropdownIcon,
|
DropdownIcon,
|
||||||
XIcon,
|
|
||||||
HammerIcon,
|
HammerIcon,
|
||||||
LogInIcon,
|
LogInIcon,
|
||||||
UpdatedIcon,
|
UpdatedIcon,
|
||||||
CopyIcon,
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
|
import { ButtonStyled, Collapsible, injectNotificationManager } from '@modrinth/ui'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import { ChatIcon } from '@/assets/icons'
|
import { ChatIcon } from '@/assets/icons'
|
||||||
import { ButtonStyled, Collapsible } from '@modrinth/ui'
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import { login as login_flow, set_default_user } from '@/helpers/auth.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'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
|
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'
|
||||||
|
|
||||||
|
// [AR] Feature
|
||||||
import { applyMigrationFix } from '@/helpers/utils.js'
|
import { applyMigrationFix } from '@/helpers/utils.js'
|
||||||
import { restartApp } from '@/helpers/utils.js'
|
import { restartApp } from '@/helpers/utils.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const errorModal = ref()
|
const errorModal = ref()
|
||||||
const error = ref()
|
const error = ref()
|
||||||
const closable = ref(true)
|
const closable = ref(true)
|
||||||
@@ -327,20 +331,10 @@ async function onApplyMigrationFix(eol) {
|
|||||||
<template v-if="copied"> <CheckIcon class="text-green" /> Copied! </template>
|
<template v-if="copied"> <CheckIcon class="text-green" /> Copied! </template>
|
||||||
<template v-else> <CopyIcon /> Copy debug info </template>
|
<template v-else> <CopyIcon /> Copy debug info </template>
|
||||||
</button>
|
</button>
|
||||||
<ButtonStyled class="neon-button neon">
|
|
||||||
<a href="https://me.astralium.su/get/ar/help" target="_blank" rel="noopener noreferrer">
|
|
||||||
Get AstralRinth support
|
|
||||||
</a>
|
|
||||||
</ButtonStyled>
|
|
||||||
<ButtonStyled class="neon-button neon" >
|
|
||||||
<a href="https://me.astralium.su/get/ar" target="_blank" rel="noopener noreferrer">
|
|
||||||
Checkout latest releases
|
|
||||||
</a>
|
|
||||||
</ButtonStyled>
|
|
||||||
</ButtonStyled>
|
</ButtonStyled>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="hasDebugInfo">
|
<template v-if="hasDebugInfo">
|
||||||
<div class="bg-button-bg rounded-xl mt-2 overflow-hidden">
|
<div class="bg-button-bg rounded-xl mt-2 overflow-clip">
|
||||||
<button
|
<button
|
||||||
class="flex items-center justify-between w-full bg-transparent border-0 px-4 py-3 cursor-pointer"
|
class="flex items-center justify-between w-full bg-transparent border-0 px-4 py-3 cursor-pointer"
|
||||||
@click="errorCollapsed = !errorCollapsed"
|
@click="errorCollapsed = !errorCollapsed"
|
||||||
@@ -352,9 +346,7 @@ async function onApplyMigrationFix(eol) {
|
|||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<Collapsible :collapsed="errorCollapsed">
|
<Collapsible :collapsed="errorCollapsed">
|
||||||
<pre
|
<pre class="m-0 px-4 py-3 bg-bg rounded-none">{{ debugInfo }}</pre>
|
||||||
class="m-0 px-4 py-3 bg-bg rounded-none whitespace-pre-wrap break-words overflow-x-auto max-w-full"
|
|
||||||
>{{ debugInfo }}</pre>
|
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="errorType === 'state_init'">
|
<template v-if="errorType === 'state_init'">
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { XIcon, PlusIcon } from '@modrinth/assets'
|
import { PlusIcon, XIcon } from '@modrinth/assets'
|
||||||
import { Button, Checkbox } from '@modrinth/ui'
|
import { Button, Checkbox, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { PackageIcon, VersionIcon } from '@/assets/icons'
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { export_profile_mrpack, get_pack_export_candidates } from '@/helpers/profile.js'
|
|
||||||
import { open } from '@tauri-apps/plugin-dialog'
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { handleError } from '@/store/notifications.js'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
import { PackageIcon, VersionIcon } from '@/assets/icons'
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
import { export_profile_mrpack, get_pack_export_candidates } from '@/helpers/profile.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
instance: {
|
instance: {
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import {
|
import {
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
GameIcon,
|
GameIcon,
|
||||||
@@ -9,17 +7,20 @@ import {
|
|||||||
StopCircleIcon,
|
StopCircleIcon,
|
||||||
TimerIcon,
|
TimerIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Avatar, ButtonStyled, useRelativeTime } from '@modrinth/ui'
|
import { Avatar, ButtonStyled, injectNotificationManager, useRelativeTime } from '@modrinth/ui'
|
||||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
import { finish_install, kill, run } from '@/helpers/profile'
|
import dayjs from 'dayjs'
|
||||||
import { get_by_profile_path } from '@/helpers/process'
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
import { process_listener } from '@/helpers/events'
|
import { process_listener } from '@/helpers/events'
|
||||||
import { handleError } from '@/store/state.js'
|
import { get_by_profile_path } from '@/helpers/process'
|
||||||
|
import { finish_install, kill, run } from '@/helpers/profile'
|
||||||
import { showProfileInFolder } from '@/helpers/utils.js'
|
import { showProfileInFolder } from '@/helpers/utils.js'
|
||||||
import { handleSevereError } from '@/store/error.js'
|
import { handleSevereError } from '@/store/error.js'
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const formatRelativeTime = useRelativeTime()
|
const formatRelativeTime = useRelativeTime()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -93,7 +94,7 @@ const stop = async (e, context) => {
|
|||||||
const repair = async (e) => {
|
const repair = async (e) => {
|
||||||
e?.stopPropagation()
|
e?.stopPropagation()
|
||||||
|
|
||||||
await finish_install(props.instance)
|
await finish_install(props.instance).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const openFolder = async () => {
|
const openFolder = async () => {
|
||||||
|
|||||||
@@ -206,8 +206,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
|
||||||
import CurseForgeProfileImportModal from '@/components/ui/CurseForgeProfileImportModal.vue'
|
|
||||||
import {
|
import {
|
||||||
CodeIcon,
|
CodeIcon,
|
||||||
FolderOpenIcon,
|
FolderOpenIcon,
|
||||||
@@ -218,24 +216,29 @@ import {
|
|||||||
UploadIcon,
|
UploadIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Avatar, Button, Checkbox, Chips } from '@modrinth/ui'
|
import { Avatar, Button, Checkbox, Chips, injectNotificationManager } from '@modrinth/ui'
|
||||||
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 { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
import { get_game_versions, get_loader_versions } from '@/helpers/metadata'
|
import { getCurrentWebview } from '@tauri-apps/api/webview'
|
||||||
import { handleError } from '@/store/notifications.js'
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
|
import { computed, onUnmounted, ref, shallowRef } from 'vue'
|
||||||
import Multiselect from 'vue-multiselect'
|
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 { trackEvent } from '@/helpers/analytics'
|
||||||
import { create_profile_and_install_from_file } from '@/helpers/pack.js'
|
|
||||||
import {
|
import {
|
||||||
get_default_launcher_path,
|
get_default_launcher_path,
|
||||||
get_importable_instances,
|
get_importable_instances,
|
||||||
import_instance,
|
import_instance,
|
||||||
} from '@/helpers/import.js'
|
} from '@/helpers/import.js'
|
||||||
import ProgressBar from '@/components/ui/ProgressBar.vue'
|
import { get_game_versions, get_loader_versions } from '@/helpers/metadata'
|
||||||
import { getCurrentWebview } from '@tauri-apps/api/webview'
|
import { create_profile_and_install_from_file } from '@/helpers/pack.js'
|
||||||
|
import { create } from '@/helpers/profile'
|
||||||
|
import { get_loaders } from '@/helpers/tags'
|
||||||
|
|
||||||
|
import CurseForgeProfileImportModal from '@/components/ui/CurseForgeProfileImportModal.vue'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const profile_name = ref('')
|
const profile_name = ref('')
|
||||||
const game_version = ref('')
|
const game_version = ref('')
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
|
||||||
import { formatCategory } from '@modrinth/utils'
|
|
||||||
import { GameIcon, LeftArrowIcon } from '@modrinth/assets'
|
import { GameIcon, LeftArrowIcon } from '@modrinth/assets'
|
||||||
import { Avatar, ButtonStyled } from '@modrinth/ui'
|
import { Avatar, ButtonStyled } from '@modrinth/ui'
|
||||||
|
import { formatCategory } from '@modrinth/utils'
|
||||||
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
type Instance = {
|
type Instance = {
|
||||||
game_version: string
|
game_version: string
|
||||||
|
|||||||
@@ -35,13 +35,15 @@
|
|||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { PlusIcon, CheckIcon, XIcon } from '@modrinth/assets'
|
import { CheckIcon, PlusIcon, XIcon } from '@modrinth/assets'
|
||||||
import { Button } from '@modrinth/ui'
|
import { Button, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
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'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
|
import { find_filtered_jres } from '@/helpers/jre.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const chosenInstallOptions = ref([])
|
const chosenInstallOptions = ref([])
|
||||||
const detectJavaModal = ref(null)
|
const detectJavaModal = ref(null)
|
||||||
|
|||||||
@@ -53,20 +53,22 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
SearchIcon,
|
|
||||||
PlayIcon,
|
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
XIcon,
|
|
||||||
FolderSearchIcon,
|
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
|
FolderSearchIcon,
|
||||||
|
PlayIcon,
|
||||||
|
SearchIcon,
|
||||||
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Button } from '@modrinth/ui'
|
import { Button, injectNotificationManager } from '@modrinth/ui'
|
||||||
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 { open } from '@tauri-apps/plugin-dialog'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import JavaDetectionModal from '@/components/ui/JavaDetectionModal.vue'
|
import JavaDetectionModal from '@/components/ui/JavaDetectionModal.vue'
|
||||||
import { handleError } from '@/store/state.js'
|
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
|
import { auto_install_java, find_filtered_jres, get_jre, test_jre } from '@/helpers/jre.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
version: {
|
version: {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { CheckIcon } from '@modrinth/assets'
|
import { CheckIcon } from '@modrinth/assets'
|
||||||
import { Button, Badge } from '@modrinth/ui'
|
import { Badge, Button } from '@modrinth/ui'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { update_managed_modrinth_version } from '@/helpers/profile'
|
|
||||||
import { releaseColor } from '@/helpers/utils'
|
|
||||||
import { SwapIcon } from '@/assets/icons/index.js'
|
import { SwapIcon } from '@/assets/icons/index.js'
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
import { update_managed_modrinth_version } from '@/helpers/profile'
|
||||||
|
import { releaseColor } from '@/helpers/utils'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
versions: {
|
versions: {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import type { RouteLocationRaw } from 'vue-router'
|
import type { RouteLocationRaw } from 'vue-router'
|
||||||
import { useRoute, RouterLink } from 'vue-router'
|
import { RouterLink, useRoute } from 'vue-router'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { Avatar, TagItem } from '@modrinth/ui'
|
|
||||||
import { DownloadIcon, HeartIcon, TagIcon } from '@modrinth/assets'
|
import { DownloadIcon, HeartIcon, TagIcon } from '@modrinth/assets'
|
||||||
import { formatNumber, formatCategory } from '@modrinth/utils'
|
import { Avatar, TagItem } from '@modrinth/ui'
|
||||||
import { computed } from 'vue'
|
import { formatCategory, formatNumber } from '@modrinth/utils'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
|
import { computed } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { list } from '@/helpers/profile'
|
import { SpinnerIcon } from '@modrinth/assets'
|
||||||
import { handleError } from '@/store/notifications'
|
import { Avatar, injectNotificationManager } from '@modrinth/ui'
|
||||||
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { onUnmounted, ref } from 'vue'
|
import { onUnmounted, ref } from 'vue'
|
||||||
import { profile_listener } from '@/helpers/events.js'
|
|
||||||
import NavButton from '@/components/ui/NavButton.vue'
|
import NavButton from '@/components/ui/NavButton.vue'
|
||||||
import { Avatar } from '@modrinth/ui'
|
import { profile_listener } from '@/helpers/events.js'
|
||||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
import { list } from '@/helpers/profile'
|
||||||
import { SpinnerIcon } from '@modrinth/assets'
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const recentInstances = ref([])
|
const recentInstances = ref([])
|
||||||
const getInstances = async () => {
|
const getInstances = async () => {
|
||||||
|
|||||||
@@ -20,12 +20,21 @@
|
|||||||
>
|
>
|
||||||
{{ selectedProcess.profile.name }}
|
{{ selectedProcess.profile.name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
<div v-if="currentProcesses.length > 1" class="arrow button-base" :class="{ rotate: showProfiles }"
|
<div
|
||||||
@click="toggleProfiles()">
|
v-if="currentProcesses.length > 1"
|
||||||
|
class="arrow button-base"
|
||||||
|
:class="{ rotate: showProfiles }"
|
||||||
|
@click="toggleProfiles()"
|
||||||
|
>
|
||||||
<DropdownIcon />
|
<DropdownIcon />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button v-tooltip="'Stop instance'" icon-only class="icon-button stop" @click="stop(selectedProcess)">
|
<Button
|
||||||
|
v-tooltip="'Stop instance'"
|
||||||
|
icon-only
|
||||||
|
class="icon-button stop"
|
||||||
|
@click="stop(selectedProcess)"
|
||||||
|
>
|
||||||
<StopCircleIcon />
|
<StopCircleIcon />
|
||||||
</Button>
|
</Button>
|
||||||
<Button v-tooltip="'View logs'" icon-only class="icon-button" @click="goToTerminal()">
|
<Button v-tooltip="'View logs'" icon-only class="icon-button" @click="goToTerminal()">
|
||||||
@@ -45,20 +54,39 @@
|
|||||||
</h3>
|
</h3>
|
||||||
<ProgressBar :progress="Math.floor((100 * loadingBar.current) / loadingBar.total)" />
|
<ProgressBar :progress="Math.floor((100 * loadingBar.current) / loadingBar.total)" />
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{ Math.floor((100 * loadingBar.current) / loadingBar.total) }}% {{ loadingBar.message }}
|
{{ Math.floor((100 * loadingBar.current) / loadingBar.total) }}%
|
||||||
|
{{ loadingBar.message }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</transition>
|
</transition>
|
||||||
<transition name="download">
|
<transition name="download">
|
||||||
<Card v-if="showProfiles === true && currentProcesses.length > 0" ref="profiles" class="profile-card">
|
<Card
|
||||||
<Button v-for="process in currentProcesses" :key="process.uuid" class="profile-button"
|
v-if="showProfiles === true && currentProcesses.length > 0"
|
||||||
@click="selectProcess(process)">
|
ref="profiles"
|
||||||
|
class="profile-card"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
v-for="process in currentProcesses"
|
||||||
|
:key="process.uuid"
|
||||||
|
class="profile-button"
|
||||||
|
@click="selectProcess(process)"
|
||||||
|
>
|
||||||
<div class="text"><span class="circle running" /> {{ process.profile.name }}</div>
|
<div class="text"><span class="circle running" /> {{ process.profile.name }}</div>
|
||||||
<Button v-tooltip="'Stop instance'" icon-only class="icon-button stop" @click.stop="stop(process)">
|
<Button
|
||||||
|
v-tooltip="'Stop instance'"
|
||||||
|
icon-only
|
||||||
|
class="icon-button stop"
|
||||||
|
@click.stop="stop(process)"
|
||||||
|
>
|
||||||
<StopCircleIcon />
|
<StopCircleIcon />
|
||||||
</Button>
|
</Button>
|
||||||
<Button v-tooltip="'View logs'" icon-only class="icon-button" @click.stop="goToTerminal(process.profile.path)">
|
<Button
|
||||||
|
v-tooltip="'View logs'"
|
||||||
|
icon-only
|
||||||
|
class="icon-button"
|
||||||
|
@click.stop="goToTerminal(process.profile.path)"
|
||||||
|
>
|
||||||
<TerminalSquareIcon />
|
<TerminalSquareIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -69,21 +97,23 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
|
DropdownIcon,
|
||||||
StopCircleIcon,
|
StopCircleIcon,
|
||||||
TerminalSquareIcon,
|
TerminalSquareIcon,
|
||||||
DropdownIcon,
|
|
||||||
UnplugIcon,
|
UnplugIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Button, ButtonStyled, Card } from '@modrinth/ui'
|
import { Button, ButtonStyled, Card, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
import { get_all as getRunningProcesses, kill as killProcess } from '@/helpers/process'
|
|
||||||
import { loading_listener, process_listener } from '@/helpers/events'
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { progress_bars_list } from '@/helpers/state.js'
|
|
||||||
import ProgressBar from '@/components/ui/ProgressBar.vue'
|
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'
|
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 { progress_bars_list } from '@/helpers/state.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const card = ref(null)
|
const card = ref(null)
|
||||||
@@ -252,7 +282,6 @@ onBeforeUnmount(() => {
|
|||||||
transition: transform 0.2s ease-in-out;
|
transition: transform 0.2s ease-in-out;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
&.rotate {
|
&.rotate {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
@@ -274,10 +303,8 @@ onBeforeUnmount(() => {
|
|||||||
gap: var(--gap-xs);
|
gap: var(--gap-xs);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none; /* Safari */
|
||||||
/* Safari */
|
-ms-user-select: none; /* IE 10 and IE 11 */
|
||||||
-ms-user-select: none;
|
|
||||||
/* IE 10 and IE 11 */
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
&.clickable:hover {
|
&.clickable:hover {
|
||||||
|
|||||||
@@ -117,16 +117,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { TagsIcon, DownloadIcon, HeartIcon, PlusIcon, CheckIcon } from '@modrinth/assets'
|
import { CheckIcon, DownloadIcon, HeartIcon, PlusIcon, TagsIcon } from '@modrinth/assets'
|
||||||
import { ButtonStyled, Avatar } from '@modrinth/ui'
|
import { Avatar, ButtonStyled, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { formatNumber, formatCategory } from '@modrinth/utils'
|
import { formatCategory, formatNumber } from '@modrinth/utils'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
import { ref, computed } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { install as installVersion } from '@/store/install.js'
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
import { install as installVersion } from '@/store/install.js'
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -174,7 +177,7 @@ async function install() {
|
|||||||
(profile) => {
|
(profile) => {
|
||||||
router.push(`/instance/${profile}`)
|
router.push(`/instance/${profile}`)
|
||||||
},
|
},
|
||||||
)
|
).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const modpack = computed(() => props.project.project_type === 'modpack')
|
const modpack = computed(() => props.project.project_type === 'modpack')
|
||||||
|
|||||||
@@ -82,11 +82,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { MaximizeIcon, MinimizeIcon, XIcon } from '@modrinth/assets'
|
||||||
|
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
import ProgressBar from '@/components/ui/ProgressBar.vue'
|
import ProgressBar from '@/components/ui/ProgressBar.vue'
|
||||||
import { loading_listener } from '@/helpers/events.js'
|
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 { getOS } from '@/helpers/utils.js'
|
||||||
import { useLoading } from '@/store/loading.js'
|
import { useLoading } from '@/store/loading.js'
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { Button } from '@modrinth/ui'
|
import { Button, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import SearchCard from '@/components/ui/SearchCard.vue'
|
|
||||||
import { get_categories } from '@/helpers/tags.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'
|
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'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const confirmModal = ref(null)
|
const confirmModal = ref(null)
|
||||||
const project = ref(null)
|
const project = ref(null)
|
||||||
@@ -37,7 +39,14 @@ defineExpose({
|
|||||||
|
|
||||||
async function install() {
|
async function install() {
|
||||||
confirmModal.value.hide()
|
confirmModal.value.hide()
|
||||||
await installVersion(project.value.id, version.value.id, null, 'URLConfirmModal')
|
await installVersion(
|
||||||
|
project.value.id,
|
||||||
|
version.value.id,
|
||||||
|
null,
|
||||||
|
'URLConfirmModal',
|
||||||
|
() => {},
|
||||||
|
() => {},
|
||||||
|
).catch(handleError)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,30 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Avatar, ButtonStyled, OverflowMenu, useRelativeTime } from '@modrinth/ui'
|
|
||||||
import {
|
import {
|
||||||
UserPlusIcon,
|
|
||||||
MoreVerticalIcon,
|
|
||||||
MailIcon,
|
MailIcon,
|
||||||
|
MoreVerticalIcon,
|
||||||
SettingsIcon,
|
SettingsIcon,
|
||||||
TrashIcon,
|
TrashIcon,
|
||||||
|
UserPlusIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { ref, onUnmounted, watch, computed } from 'vue'
|
import {
|
||||||
import { friend_listener } from '@/helpers/events'
|
Avatar,
|
||||||
import { friends, friend_statuses, add_friend, remove_friend } from '@/helpers/friends'
|
ButtonStyled,
|
||||||
import { get_user_many } from '@/helpers/cache'
|
injectNotificationManager,
|
||||||
import { handleError } from '@/store/notifications.js'
|
OverflowMenu,
|
||||||
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
useRelativeTime,
|
||||||
|
} from '@modrinth/ui'
|
||||||
import type { Dayjs } from 'dayjs'
|
import type { Dayjs } from 'dayjs'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
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'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const formatRelativeTime = useRelativeTime()
|
const formatRelativeTime = useRelativeTime()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -56,16 +56,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import { DownloadIcon, XIcon } from '@modrinth/assets'
|
||||||
import { XIcon, DownloadIcon } from '@modrinth/assets'
|
import { Button, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { Button } from '@modrinth/ui'
|
|
||||||
import { formatCategory } from '@modrinth/utils'
|
import { formatCategory } from '@modrinth/utils'
|
||||||
import { add_project_from_version as installMod } from '@/helpers/profile'
|
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { handleError } from '@/store/state.js'
|
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
|
||||||
import Multiselect from 'vue-multiselect'
|
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'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const instance = ref(null)
|
const instance = ref(null)
|
||||||
const project = ref(null)
|
const project = ref(null)
|
||||||
const versions = ref(null)
|
const versions = ref(null)
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { DownloadIcon, XIcon } from '@modrinth/assets'
|
import { DownloadIcon, XIcon } from '@modrinth/assets'
|
||||||
import { Button } from '@modrinth/ui'
|
import { Button, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { create_profile_and_install as pack_install } from '@/helpers/pack'
|
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
|
||||||
import { handleError } from '@/store/state.js'
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.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'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const versionId = ref()
|
const versionId = ref()
|
||||||
const project = ref()
|
const project = ref()
|
||||||
|
|||||||
@@ -1,29 +1,30 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
|
CheckIcon,
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
|
RightArrowIcon,
|
||||||
UploadIcon,
|
UploadIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
RightArrowIcon,
|
|
||||||
CheckIcon,
|
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Avatar, Button, Card } from '@modrinth/ui'
|
import { Avatar, Button, Card, injectNotificationManager } from '@modrinth/ui'
|
||||||
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
import {
|
import {
|
||||||
add_project_from_version as installMod,
|
add_project_from_version as installMod,
|
||||||
check_installed,
|
check_installed,
|
||||||
|
create,
|
||||||
get,
|
get,
|
||||||
list,
|
list,
|
||||||
create,
|
|
||||||
} from '@/helpers/profile'
|
} from '@/helpers/profile'
|
||||||
import { open } from '@tauri-apps/plugin-dialog'
|
|
||||||
import { installVersionDependencies } from '@/store/install.js'
|
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 { handleError } = injectNotificationManager()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const versions = ref()
|
const versions = ref()
|
||||||
@@ -109,7 +110,7 @@ async function install(instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await installMod(instance.path, version.id).catch(handleError)
|
await installMod(instance.path, version.id).catch(handleError)
|
||||||
await installVersionDependencies(instance, version)
|
await installVersionDependencies(instance, version).catch(handleError)
|
||||||
|
|
||||||
instance.installedMod = true
|
instance.installedMod = true
|
||||||
instance.installing = false
|
instance.installing = false
|
||||||
@@ -184,7 +185,7 @@ const createInstance = async () => {
|
|||||||
await router.push(`/instance/${encodeURIComponent(id)}/`)
|
await router.push(`/instance/${encodeURIComponent(id)}/`)
|
||||||
|
|
||||||
const instance = await get(id, true)
|
const instance = await get(id, true)
|
||||||
await installVersionDependencies(instance, versions.value[0])
|
await installVersionDependencies(instance, versions.value[0]).catch(handleError)
|
||||||
|
|
||||||
trackEvent('InstanceCreate', {
|
trackEvent('InstanceCreate', {
|
||||||
profile_name: name.value,
|
profile_name: name.value,
|
||||||
|
|||||||
@@ -1,17 +1,25 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { CopyIcon, EditIcon, PlusIcon, SpinnerIcon, TrashIcon, UploadIcon } from '@modrinth/assets'
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
ButtonStyled,
|
||||||
|
Checkbox,
|
||||||
|
injectNotificationManager,
|
||||||
|
OverflowMenu,
|
||||||
|
} from '@modrinth/ui'
|
||||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
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 { trackEvent } from '@/helpers/analytics'
|
|
||||||
import { open } from '@tauri-apps/plugin-dialog'
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
|
import { computed, type Ref, ref, watch } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
|
||||||
import type { InstanceSettingsTabProps, GameInstance } from '../../../helpers/types'
|
|
||||||
|
|
||||||
|
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
||||||
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
|
import { duplicate, edit, edit_icon, list, remove } from '@/helpers/profile'
|
||||||
|
|
||||||
|
import type { GameInstance, InstanceSettingsTabProps } from '../../../helpers/types'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Checkbox } from '@modrinth/ui'
|
import { Checkbox, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { computed, ref, watch } from 'vue'
|
|
||||||
import { handleError } from '@/store/notifications'
|
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
import { get } from '@/helpers/settings.ts'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { edit } from '@/helpers/profile'
|
|
||||||
import type { InstanceSettingsTabProps, AppSettings, Hooks } from '../../../helpers/types'
|
|
||||||
|
|
||||||
|
import { edit } from '@/helpers/profile'
|
||||||
|
import { get } from '@/helpers/settings.ts'
|
||||||
|
|
||||||
|
import type { AppSettings, Hooks, InstanceSettingsTabProps } from '../../../helpers/types'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const props = defineProps<InstanceSettingsTabProps>()
|
const props = defineProps<InstanceSettingsTabProps>()
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
TransferIcon,
|
|
||||||
IssuesIcon,
|
|
||||||
HammerIcon,
|
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
WrenchIcon,
|
HammerIcon,
|
||||||
UndoIcon,
|
IssuesIcon,
|
||||||
SpinnerIcon,
|
SpinnerIcon,
|
||||||
UnplugIcon,
|
TransferIcon,
|
||||||
|
UndoIcon,
|
||||||
UnlinkIcon,
|
UnlinkIcon,
|
||||||
|
UnplugIcon,
|
||||||
|
WrenchIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Avatar, Checkbox, Chips, ButtonStyled, TeleportDropdownMenu } from '@modrinth/ui'
|
import {
|
||||||
import { computed, type ComputedRef, type Ref, ref, shallowRef, watch } from 'vue'
|
Avatar,
|
||||||
import { edit, install, update_repair_modrinth } from '@/helpers/profile'
|
ButtonStyled,
|
||||||
import { handleError } from '@/store/notifications'
|
Checkbox,
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
Chips,
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
injectNotificationManager,
|
||||||
import { get_loader_versions } from '@/helpers/metadata'
|
TeleportDropdownMenu,
|
||||||
import { get_game_versions, get_loaders } from '@/helpers/tags'
|
} from '@modrinth/ui'
|
||||||
import {
|
import {
|
||||||
formatCategory,
|
formatCategory,
|
||||||
type GameVersionTag,
|
type GameVersionTag,
|
||||||
@@ -25,15 +25,23 @@ import {
|
|||||||
type Project,
|
type Project,
|
||||||
type Version,
|
type Version,
|
||||||
} from '@modrinth/utils'
|
} from '@modrinth/utils'
|
||||||
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
import { get_project, get_version_many } from '@/helpers/cache'
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
import ModpackVersionModal from '@/components/ui/ModpackVersionModal.vue'
|
|
||||||
import dayjs from 'dayjs'
|
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 type {
|
import type {
|
||||||
InstanceSettingsTabProps,
|
InstanceSettingsTabProps,
|
||||||
ManifestLoaderVersion,
|
|
||||||
Manifest,
|
Manifest,
|
||||||
|
ManifestLoaderVersion,
|
||||||
} from '../../../helpers/types'
|
} from '../../../helpers/types'
|
||||||
|
|
||||||
import { initAuthlibPatching } from '@/helpers/utils.js'
|
import { initAuthlibPatching } from '@/helpers/utils.js'
|
||||||
@@ -41,6 +49,7 @@ const authLibPatchingModal = ref(null)
|
|||||||
const isAuthLibPatchedSuccess = ref(false)
|
const isAuthLibPatchedSuccess = ref(false)
|
||||||
const isAuthLibPatching = ref(false)
|
const isAuthLibPatching = ref(false)
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const repairConfirmModal = ref()
|
const repairConfirmModal = ref()
|
||||||
@@ -545,7 +554,8 @@ async function handleInitAuthLibPatching(ismojang: boolean) {
|
|||||||
</div>
|
</div>
|
||||||
<div v-else-if="!modpackProject && instance.linked_data && !fetching" class="mb-2">
|
<div v-else-if="!modpackProject && instance.linked_data && !fetching" class="mb-2">
|
||||||
<p class="text-brand-red font-medium mt-0">
|
<p class="text-brand-red font-medium mt-0">
|
||||||
<IssuesIcon class="top-[3px] relative" /> {{ formatMessage(messages.noModpackFound) }}
|
<IssuesIcon class="top-[3px] relative" />
|
||||||
|
{{ formatMessage(messages.noModpackFound) }}
|
||||||
</p>
|
</p>
|
||||||
<p>{{ formatMessage(messages.debugInformation) }}</p>
|
<p>{{ formatMessage(messages.debugInformation) }}</p>
|
||||||
<div class="bg-bg p-6 rounded-2xl mt-2 text-sm text-secondary">
|
<div class="bg-bg p-6 rounded-2xl mt-2 text-sm text-secondary">
|
||||||
@@ -572,7 +582,9 @@ async function handleInitAuthLibPatching(ismojang: boolean) {
|
|||||||
{{
|
{{
|
||||||
modpackProject
|
modpackProject
|
||||||
? modpackProject.title
|
? modpackProject.title
|
||||||
: formatMessage(messages.minecraftVersion, { version: instance.game_version })
|
: formatMessage(messages.minecraftVersion, {
|
||||||
|
version: instance.game_version,
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span class="text-sm text-secondary leading-none">
|
<span class="text-sm text-secondary leading-none">
|
||||||
@@ -702,7 +714,12 @@ async function handleInitAuthLibPatching(ismojang: boolean) {
|
|||||||
/>
|
/>
|
||||||
<div v-else class="mt-2 text-brand-red flex gap-2 items-center">
|
<div v-else class="mt-2 text-brand-red flex gap-2 items-center">
|
||||||
<IssuesIcon />
|
<IssuesIcon />
|
||||||
{{ formatMessage(messages.noLoaderVersions, { loader: loader, version: gameVersion }) }}
|
{{
|
||||||
|
formatMessage(messages.noLoaderVersions, {
|
||||||
|
loader: loader,
|
||||||
|
version: gameVersion,
|
||||||
|
})
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="mt-4 flex flex-wrap gap-2">
|
<div class="mt-4 flex flex-wrap gap-2">
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Checkbox, Slider } from '@modrinth/ui'
|
|
||||||
import { CheckCircleIcon, XCircleIcon } from '@modrinth/assets'
|
import { CheckCircleIcon, XCircleIcon } from '@modrinth/assets'
|
||||||
import { computed, readonly, ref, watch } from 'vue'
|
import { Checkbox, injectNotificationManager, Slider } from '@modrinth/ui'
|
||||||
import { edit, get_optimal_jre_key } from '@/helpers/profile'
|
|
||||||
import { handleError } from '@/store/notifications'
|
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
import JavaSelector from '@/components/ui/JavaSelector.vue'
|
import { computed, readonly, ref, watch } from 'vue'
|
||||||
import { get } from '@/helpers/settings.ts'
|
|
||||||
import type { InstanceSettingsTabProps, AppSettings, MemorySettings } from '../../../helpers/types'
|
|
||||||
import useMemorySlider from '@/composables/useMemorySlider'
|
|
||||||
|
|
||||||
|
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 type { AppSettings, InstanceSettingsTabProps, MemorySettings } from '../../../helpers/types'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const props = defineProps<InstanceSettingsTabProps>()
|
const props = defineProps<InstanceSettingsTabProps>()
|
||||||
|
|
||||||
const globalSettings = (await get().catch(handleError)) as AppSettings
|
const globalSettings = (await get().catch(handleError)) as unknown as AppSettings
|
||||||
|
|
||||||
const overrideJavaInstall = ref(!!props.instance.java_path)
|
const overrideJavaInstall = ref(!!props.instance.java_path)
|
||||||
const optimalJava = readonly(await get_optimal_jre_key(props.instance.path).catch(handleError))
|
const optimalJava = readonly(await get_optimal_jre_key(props.instance.path).catch(handleError))
|
||||||
@@ -34,7 +36,10 @@ const envVars = ref(
|
|||||||
|
|
||||||
const overrideMemorySettings = ref(!!props.instance.memory)
|
const overrideMemorySettings = ref(!!props.instance.memory)
|
||||||
const memory = ref(props.instance.memory ?? globalSettings.memory)
|
const memory = ref(props.instance.memory ?? globalSettings.memory)
|
||||||
const { maxMemory, snapPoints } = await useMemorySlider()
|
const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) as unknown as {
|
||||||
|
maxMemory: number
|
||||||
|
snapPoints: number[]
|
||||||
|
}
|
||||||
|
|
||||||
const editProfileObject = computed(() => {
|
const editProfileObject = computed(() => {
|
||||||
const editProfile: {
|
const editProfile: {
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Checkbox, Toggle } from '@modrinth/ui'
|
import { Checkbox, injectNotificationManager, Toggle } from '@modrinth/ui'
|
||||||
import { computed, ref, type Ref, watch } from 'vue'
|
|
||||||
import { handleError } from '@/store/notifications'
|
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
import { get } from '@/helpers/settings.ts'
|
import { computed, type Ref, ref, watch } from 'vue'
|
||||||
|
|
||||||
import { edit } from '@/helpers/profile'
|
import { edit } from '@/helpers/profile'
|
||||||
|
import { get } from '@/helpers/settings.ts'
|
||||||
|
|
||||||
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
|
import type { AppSettings, InstanceSettingsTabProps } from '../../../helpers/types'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const props = defineProps<InstanceSettingsTabProps>()
|
const props = defineProps<InstanceSettingsTabProps>()
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
ReportIcon,
|
|
||||||
AstralRinthLogo,
|
|
||||||
ShieldIcon,
|
|
||||||
SettingsIcon,
|
|
||||||
GaugeIcon,
|
|
||||||
PaintbrushIcon,
|
|
||||||
GameIcon,
|
|
||||||
CoffeeIcon,
|
CoffeeIcon,
|
||||||
|
GameIcon,
|
||||||
|
GaugeIcon,
|
||||||
|
AstralRinthLogo,
|
||||||
DownloadIcon,
|
DownloadIcon,
|
||||||
SpinnerIcon,
|
SpinnerIcon,
|
||||||
|
PaintbrushIcon,
|
||||||
|
ReportIcon,
|
||||||
|
SettingsIcon,
|
||||||
|
ShieldIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { TabbedModal } from '@modrinth/ui'
|
import { TabbedModal } from '@modrinth/ui'
|
||||||
import { computed, ref, watch } from 'vue'
|
|
||||||
import { useVIntl, defineMessage } from '@vintl/vintl'
|
|
||||||
import AppearanceSettings from '@/components/ui/settings/AppearanceSettings.vue'
|
|
||||||
import JavaSettings from '@/components/ui/settings/JavaSettings.vue'
|
|
||||||
import ResourceManagementSettings from '@/components/ui/settings/ResourceManagementSettings.vue'
|
|
||||||
import PrivacySettings from '@/components/ui/settings/PrivacySettings.vue'
|
|
||||||
import DefaultInstanceSettings from '@/components/ui/settings/DefaultInstanceSettings.vue'
|
|
||||||
import { getVersion } from '@tauri-apps/api/app'
|
import { getVersion } from '@tauri-apps/api/app'
|
||||||
import { version as getOsVersion, platform as getOsPlatform } from '@tauri-apps/plugin-os'
|
import { platform as getOsPlatform, version as getOsVersion } from '@tauri-apps/plugin-os'
|
||||||
import { useTheming } from '@/store/state'
|
import { defineMessage, useVIntl } from '@vintl/vintl'
|
||||||
import FeatureFlagSettings from '@/components/ui/settings/FeatureFlagSettings.vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
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 { get, set } from '@/helpers/settings.ts'
|
||||||
// [AR] Imports
|
// [AR] Imports
|
||||||
import { installState, getRemote, updateState } from '@/helpers/update.js'
|
import { installState, getRemote, updateState } from '@/helpers/update.js'
|
||||||
@@ -42,6 +42,7 @@ const initDownload = async () => {
|
|||||||
updateRequestFailView.value.show()
|
updateRequestFailView.value.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
import { useTheming } from '@/store/state'
|
||||||
|
|
||||||
const themeStore = useTheming()
|
const themeStore = useTheming()
|
||||||
|
|
||||||
@@ -159,12 +160,16 @@ function devModeCount() {
|
|||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<button
|
<button
|
||||||
class="p-0 m-0 bg-transparent border-none cursor-pointer button-animation"
|
class="p-0 m-0 bg-transparent border-none cursor-pointer button-animation"
|
||||||
:class="{ 'text-brand': themeStore.devMode, 'text-secondary': !themeStore.devMode }"
|
:class="{
|
||||||
@click="devModeCount">
|
'text-brand': themeStore.devMode,
|
||||||
|
'text-secondary': !themeStore.devMode,
|
||||||
|
}"
|
||||||
|
@click="devModeCount"
|
||||||
|
>
|
||||||
<AstralRinthLogo class="w-6 h-6" />
|
<AstralRinthLogo class="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
<div>
|
<div>
|
||||||
<p class="m-0">AstralRinth App {{ version }}</p>
|
<p class="m-0">Modrinth App {{ version }}</p>
|
||||||
<p class="m-0">
|
<p class="m-0">
|
||||||
<span v-if="osPlatform === 'macos'">MacOS</span>
|
<span v-if="osPlatform === 'macos'">MacOS</span>
|
||||||
<span v-else class="capitalize">{{ osPlatform }}</span>
|
<span v-else class="capitalize">{{ osPlatform }}</span>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { LogInIcon, SpinnerIcon } from '@modrinth/assets'
|
import { LogInIcon, SpinnerIcon } from '@modrinth/assets'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
|
||||||
import { ConfirmModal } from '@modrinth/ui'
|
import { ConfirmModal } from '@modrinth/ui'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import { useTheming } from '@/store/theme.js'
|
// import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
|
||||||
|
import { useTheming } from '@/store/theme.ts'
|
||||||
|
|
||||||
const themeStore = useTheming()
|
const themeStore = useTheming()
|
||||||
|
|
||||||
@@ -52,10 +53,11 @@ const modal = ref(null)
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
show: () => {
|
show: () => {
|
||||||
|
// hide_ads_window()
|
||||||
modal.value.show()
|
modal.value.show()
|
||||||
},
|
},
|
||||||
hide: () => {
|
hide: () => {
|
||||||
// onModalHide()
|
onModalHide()
|
||||||
modal.value.hide()
|
modal.value.hide()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { ChevronRightIcon } from '@modrinth/assets'
|
import { ChevronRightIcon } from '@modrinth/assets'
|
||||||
import { Avatar } from '@modrinth/ui'
|
import { Avatar } from '@modrinth/ui'
|
||||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
import type { GameInstance } from '@/helpers/types'
|
import type { GameInstance } from '@/helpers/types'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
|
CodeIcon,
|
||||||
CoffeeIcon,
|
CoffeeIcon,
|
||||||
InfoIcon,
|
InfoIcon,
|
||||||
WrenchIcon,
|
|
||||||
MonitorIcon,
|
MonitorIcon,
|
||||||
CodeIcon,
|
WrenchIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Avatar, TabbedModal, type TabbedModalTab } from '@modrinth/ui'
|
import { Avatar, TabbedModal, type TabbedModalTab } from '@modrinth/ui'
|
||||||
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 { convertFileSrc } from '@tauri-apps/api/core'
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
|
import { defineMessage, useVIntl } from '@vintl/vintl'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
import GeneralSettings from '@/components/ui/instance_settings/GeneralSettings.vue'
|
||||||
|
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
|
||||||
import InstallationSettings from '@/components/ui/instance_settings/InstallationSettings.vue'
|
import InstallationSettings from '@/components/ui/instance_settings/InstallationSettings.vue'
|
||||||
import JavaSettings from '@/components/ui/instance_settings/JavaSettings.vue'
|
import JavaSettings from '@/components/ui/instance_settings/JavaSettings.vue'
|
||||||
import WindowSettings from '@/components/ui/instance_settings/WindowSettings.vue'
|
import WindowSettings from '@/components/ui/instance_settings/WindowSettings.vue'
|
||||||
import HooksSettings from '@/components/ui/instance_settings/HooksSettings.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
|
||||||
import type { InstanceSettingsTabProps } from '../../../helpers/types'
|
import type { InstanceSettingsTabProps } from '../../../helpers/types'
|
||||||
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useTemplateRef } from 'vue'
|
|
||||||
import { NewModal as Modal } from '@modrinth/ui'
|
import { NewModal as Modal } from '@modrinth/ui'
|
||||||
// import { show_ads_window, hide_ads_window } from '@/helpers/ads.js'
|
import { useTemplateRef } from 'vue'
|
||||||
import { useTheming } from '@/store/theme.js'
|
|
||||||
|
// import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
|
||||||
|
import { useTheming } from '@/store/theme.ts'
|
||||||
|
|
||||||
const themeStore = useTheming()
|
const themeStore = useTheming()
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ const props = defineProps({
|
|||||||
onHide: {
|
onHide: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default() {
|
default() {
|
||||||
return () => { }
|
return () => {}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// showAdOnClose: {
|
// showAdOnClose: {
|
||||||
@@ -40,9 +41,9 @@ defineExpose({
|
|||||||
})
|
})
|
||||||
|
|
||||||
function onModalHide() {
|
function onModalHide() {
|
||||||
// if (props.showAdOnClose) {
|
// if (props.showAdOnClose) {
|
||||||
// show_ads_window()
|
// show_ads_window()
|
||||||
// }
|
// }
|
||||||
props.onHide?.()
|
props.onHide?.()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
|
||||||
import { ShareModal } from '@modrinth/ui'
|
import { ShareModal } from '@modrinth/ui'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import { useTheming } from '@/store/theme.js'
|
// import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
|
||||||
|
import { useTheming } from '@/store/theme.ts'
|
||||||
|
|
||||||
const themeStore = useTheming()
|
const themeStore = useTheming()
|
||||||
|
|
||||||
@@ -33,6 +34,7 @@ const modal = ref(null)
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
show: (passedContent) => {
|
show: (passedContent) => {
|
||||||
|
// hide_ads_window()
|
||||||
modal.value.show(passedContent)
|
modal.value.show(passedContent)
|
||||||
},
|
},
|
||||||
hide: () => {
|
hide: () => {
|
||||||
@@ -40,9 +42,21 @@ defineExpose({
|
|||||||
modal.value.hide()
|
modal.value.hide()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// function onModalHide() {
|
||||||
|
// show_ads_window()
|
||||||
|
// }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ShareModal ref="modal" :header="header" :share-title="shareTitle" :share-text="shareText" :link="link"
|
<ShareModal
|
||||||
:open-in-new-tab="openInNewTab" :on-hide="onModalHide" :noblur="!themeStore.advancedRendering" />
|
ref="modal"
|
||||||
|
:header="header"
|
||||||
|
:share-title="shareTitle"
|
||||||
|
:share-text="shareText"
|
||||||
|
:link="link"
|
||||||
|
:open-in-new-tab="openInNewTab"
|
||||||
|
:on-hide="onModalHide"
|
||||||
|
:noblur="!themeStore.advancedRendering"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { TeleportDropdownMenu, ThemeSelector, Toggle } from '@modrinth/ui'
|
import { TeleportDropdownMenu, ThemeSelector, Toggle } from '@modrinth/ui'
|
||||||
import { useTheming } from '@/store/state'
|
|
||||||
import { get, set } from '@/helpers/settings.ts'
|
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
|
import { get, set } from '@/helpers/settings.ts'
|
||||||
import { getOS } from '@/helpers/utils'
|
import { getOS } from '@/helpers/utils'
|
||||||
|
import { useTheming } from '@/store/state'
|
||||||
import type { ColorTheme } from '@/store/theme.ts'
|
import type { ColorTheme } from '@/store/theme.ts'
|
||||||
|
|
||||||
const themeStore = useTheming()
|
const themeStore = useTheming()
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { get, set } from '@/helpers/settings.ts'
|
import { injectNotificationManager, Slider, Toggle } from '@modrinth/ui'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { Slider, Toggle } from '@modrinth/ui'
|
|
||||||
import useMemorySlider from '@/composables/useMemorySlider'
|
import useMemorySlider from '@/composables/useMemorySlider'
|
||||||
|
import { get, set } from '@/helpers/settings.ts'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const fetchSettings = await get()
|
const fetchSettings = await get()
|
||||||
fetchSettings.launchArgs = fetchSettings.extra_launch_args.join(' ')
|
fetchSettings.launchArgs = fetchSettings.extra_launch_args.join(' ')
|
||||||
@@ -10,7 +13,10 @@ fetchSettings.envVars = fetchSettings.custom_env_vars.map((x) => x.join('=')).jo
|
|||||||
|
|
||||||
const settings = ref(fetchSettings)
|
const settings = ref(fetchSettings)
|
||||||
|
|
||||||
const { maxMemory, snapPoints } = await useMemorySlider()
|
const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) as unknown as {
|
||||||
|
maxMemory: number
|
||||||
|
snapPoints: number[]
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
settings,
|
settings,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Toggle } from '@modrinth/ui'
|
import { Toggle } from '@modrinth/ui'
|
||||||
import { useTheming } from '@/store/state'
|
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
|
import { get as getSettings, set as setSettings } from '@/helpers/settings.ts'
|
||||||
|
import { useTheming } from '@/store/state'
|
||||||
import { DEFAULT_FEATURE_FLAGS, type FeatureFlag } from '@/store/theme.ts'
|
import { DEFAULT_FEATURE_FLAGS, type FeatureFlag } from '@/store/theme.ts'
|
||||||
|
|
||||||
const themeStore = useTheming()
|
const themeStore = useTheming()
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { injectNotificationManager } from '@modrinth/ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { get_java_versions, set_java_version } from '@/helpers/jre'
|
|
||||||
import { handleError } from '@/store/notifications'
|
|
||||||
import JavaSelector from '@/components/ui/JavaSelector.vue'
|
import JavaSelector from '@/components/ui/JavaSelector.vue'
|
||||||
|
import { get_java_versions, set_java_version } from '@/helpers/jre'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const javaVersions = ref(await get_java_versions().catch(handleError))
|
const javaVersions = ref(await get_java_versions().catch(handleError))
|
||||||
async function updateJavaVersion(version) {
|
async function updateJavaVersion(version) {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue'
|
|
||||||
import { get, set } from '@/helpers/settings.ts'
|
|
||||||
import { Toggle } from '@modrinth/ui'
|
import { Toggle } from '@modrinth/ui'
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
import { optInAnalytics, optOutAnalytics } from '@/helpers/analytics'
|
import { optInAnalytics, optOutAnalytics } from '@/helpers/analytics'
|
||||||
|
import { get, set } from '@/helpers/settings.ts'
|
||||||
|
|
||||||
const settings = ref(await get())
|
const settings = ref(await get())
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ watch(
|
|||||||
<div>
|
<div>
|
||||||
<h2 class="m-0 text-lg font-extrabold text-contrast">Personalized ads</h2>
|
<h2 class="m-0 text-lg font-extrabold text-contrast">Personalized ads</h2>
|
||||||
<p class="m-0 text-sm">
|
<p class="m-0 text-sm">
|
||||||
(Hard disabled by AR) • Modrinth's ad provider, Aditude, shows ads based on your preferences. By disabling this
|
Modrinth's ad provider, Aditude, shows ads based on your preferences. By disabling this
|
||||||
option, you opt out and ads will no longer be shown based on your interests.
|
option, you opt out and ads will no longer be shown based on your interests.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,7 +39,7 @@ watch(
|
|||||||
<div>
|
<div>
|
||||||
<h2 class="m-0 text-lg font-extrabold text-contrast">Telemetry</h2>
|
<h2 class="m-0 text-lg font-extrabold text-contrast">Telemetry</h2>
|
||||||
<p class="m-0 text-sm">
|
<p class="m-0 text-sm">
|
||||||
(Hard disabled by AR) • Modrinth collects anonymized analytics and usage data to improve our user experience and
|
Modrinth collects anonymized analytics and usage data to improve our user experience and
|
||||||
customize your experience. By disabling this option, you opt out and your data will no
|
customize your experience. By disabling this option, you opt out and your data will no
|
||||||
longer be collected.
|
longer be collected.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { Button, Slider } from '@modrinth/ui'
|
|
||||||
import { ref, watch } from 'vue'
|
|
||||||
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 { BoxIcon, FolderSearchIcon, TrashIcon } from '@modrinth/assets'
|
||||||
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
import { Button, injectNotificationManager, Slider } from '@modrinth/ui'
|
||||||
import { open } from '@tauri-apps/plugin-dialog'
|
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'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const settings = ref(await get())
|
const settings = ref(await get())
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -100,37 +100,40 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch, useTemplateRef } from 'vue'
|
|
||||||
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
|
|
||||||
import {
|
import {
|
||||||
SkinPreviewRenderer,
|
CheckIcon,
|
||||||
|
ChevronRightIcon,
|
||||||
|
SaveIcon,
|
||||||
|
SpinnerIcon,
|
||||||
|
UploadIcon,
|
||||||
|
XIcon,
|
||||||
|
} from '@modrinth/assets'
|
||||||
|
import {
|
||||||
Button,
|
Button,
|
||||||
RadioButtons,
|
ButtonStyled,
|
||||||
CapeButton,
|
CapeButton,
|
||||||
CapeLikeTextButton,
|
CapeLikeTextButton,
|
||||||
ButtonStyled,
|
injectNotificationManager,
|
||||||
|
RadioButtons,
|
||||||
|
SkinPreviewRenderer,
|
||||||
} from '@modrinth/ui'
|
} 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 {
|
import {
|
||||||
add_and_equip_custom_skin,
|
add_and_equip_custom_skin,
|
||||||
remove_custom_skin,
|
|
||||||
unequip_skin,
|
|
||||||
type Skin,
|
|
||||||
type Cape,
|
type Cape,
|
||||||
type SkinModel,
|
|
||||||
get_normalized_skin_texture,
|
|
||||||
determineModelType,
|
determineModelType,
|
||||||
|
get_normalized_skin_texture,
|
||||||
|
remove_custom_skin,
|
||||||
|
type Skin,
|
||||||
|
type SkinModel,
|
||||||
|
unequip_skin,
|
||||||
} from '@/helpers/skins.ts'
|
} from '@/helpers/skins.ts'
|
||||||
import { handleError } from '@/store/notifications'
|
|
||||||
import {
|
const { handleError } = injectNotificationManager()
|
||||||
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 modal = useTemplateRef('modal')
|
||||||
const selectCapeModal = useTemplateRef('selectCapeModal')
|
const selectCapeModal = useTemplateRef('selectCapeModal')
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useTemplateRef, ref, computed } from 'vue'
|
import { CheckIcon, XIcon } from '@modrinth/assets'
|
||||||
import type { Cape, SkinModel } from '@/helpers/skins.ts'
|
|
||||||
import {
|
import {
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
ScrollablePanel,
|
|
||||||
CapeButton,
|
CapeButton,
|
||||||
CapeLikeTextButton,
|
CapeLikeTextButton,
|
||||||
|
ScrollablePanel,
|
||||||
SkinPreviewRenderer,
|
SkinPreviewRenderer,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
import { CheckIcon, XIcon } from '@modrinth/assets'
|
import { computed, ref, useTemplateRef } from 'vue'
|
||||||
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
|
import type { Cape, SkinModel } from '@/helpers/skins.ts'
|
||||||
|
|
||||||
const modal = useTemplateRef('modal')
|
const modal = useTemplateRef('modal')
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onBeforeUnmount, watch } from 'vue'
|
|
||||||
import { UploadIcon } from '@modrinth/assets'
|
import { UploadIcon } from '@modrinth/assets'
|
||||||
import { useNotifications } from '@/store/state'
|
import { injectNotificationManager } from '@modrinth/ui'
|
||||||
import { getCurrentWebview } from '@tauri-apps/api/webview'
|
import { getCurrentWebview } from '@tauri-apps/api/webview'
|
||||||
|
import { onBeforeUnmount, ref, watch } from 'vue'
|
||||||
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue'
|
||||||
import { get_dragged_skin_data } from '@/helpers/skins'
|
import { get_dragged_skin_data } from '@/helpers/skins'
|
||||||
|
|
||||||
const notifications = useNotifications()
|
const { addNotification } = injectNotificationManager()
|
||||||
|
|
||||||
const modal = ref()
|
const modal = ref()
|
||||||
const fileInput = ref<HTMLInputElement>()
|
const fileInput = ref<HTMLInputElement>()
|
||||||
@@ -99,7 +100,7 @@ async function setupDragDropListener() {
|
|||||||
const data = await get_dragged_skin_data(filePath)
|
const data = await get_dragged_skin_data(filePath)
|
||||||
await processData(data.buffer)
|
await processData(data.buffer)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.addNotification({
|
addNotification({
|
||||||
title: 'Error processing file',
|
title: 'Error processing file',
|
||||||
text: error instanceof Error ? error.message : 'Failed to read the dropped file.',
|
text: error instanceof Error ? error.message : 'Failed to read the dropped file.',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Dayjs } from 'dayjs'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import {
|
import {
|
||||||
EyeIcon,
|
EyeIcon,
|
||||||
FolderOpenIcon,
|
FolderOpenIcon,
|
||||||
@@ -13,25 +11,29 @@ import {
|
|||||||
Avatar,
|
Avatar,
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
commonMessages,
|
commonMessages,
|
||||||
|
injectNotificationManager,
|
||||||
OverflowMenu,
|
OverflowMenu,
|
||||||
SmartClickable,
|
SmartClickable,
|
||||||
useRelativeTime,
|
useRelativeTime,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
import { useVIntl } from '@vintl/vintl'
|
|
||||||
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 { capitalizeString } from '@modrinth/utils'
|
||||||
import { kill, run } from '@/helpers/profile'
|
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||||
import { handleSevereError } from '@/store/error'
|
import { useVIntl } from '@vintl/vintl'
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
import type { Dayjs } from 'dayjs'
|
||||||
import { get_by_profile_path } from '@/helpers/process'
|
import dayjs from 'dayjs'
|
||||||
import { handleError } from '@/store/notifications'
|
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { process_listener } from '@/helpers/events'
|
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 { showProfileInFolder } from '@/helpers/utils'
|
||||||
|
import { handleSevereError } from '@/store/error'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
const formatRelativeTime = useRelativeTime()
|
const formatRelativeTime = useRelativeTime()
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,32 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import { GAME_MODES, HeadingLink, injectNotificationManager } from '@modrinth/ui'
|
||||||
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 type { Dayjs } from 'dayjs'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useTheming } from '@/store/theme.ts'
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { kill, run } from '@/helpers/profile'
|
|
||||||
import { handleError } from '@/store/notifications'
|
import InstanceItem from '@/components/ui/world/InstanceItem.vue'
|
||||||
|
import WorldItem from '@/components/ui/world/WorldItem.vue'
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
import { process_listener, profile_listener } from '@/helpers/events'
|
import { process_listener, profile_listener } from '@/helpers/events'
|
||||||
import { get_all } from '@/helpers/process'
|
import { get_all } from '@/helpers/process'
|
||||||
|
import { kill, run } from '@/helpers/profile'
|
||||||
import type { GameInstance } from '@/helpers/types'
|
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 { handleSevereError } from '@/store/error'
|
||||||
|
import { useTheming } from '@/store/theme.ts'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
recentInstances: GameInstance[]
|
recentInstances: GameInstance[]
|
||||||
|
|||||||
@@ -1,28 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<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 {
|
import {
|
||||||
useRelativeTime,
|
|
||||||
Avatar,
|
|
||||||
ButtonStyled,
|
|
||||||
commonMessages,
|
|
||||||
OverflowMenu,
|
|
||||||
SmartClickable,
|
|
||||||
} from '@modrinth/ui'
|
|
||||||
import {
|
|
||||||
IssuesIcon,
|
|
||||||
EyeIcon,
|
|
||||||
ClipboardCopyIcon,
|
ClipboardCopyIcon,
|
||||||
EditIcon,
|
EditIcon,
|
||||||
|
EyeIcon,
|
||||||
FolderOpenIcon,
|
FolderOpenIcon,
|
||||||
|
IssuesIcon,
|
||||||
MoreVerticalIcon,
|
MoreVerticalIcon,
|
||||||
NoSignalIcon,
|
NoSignalIcon,
|
||||||
PlayIcon,
|
PlayIcon,
|
||||||
@@ -35,14 +17,33 @@ import {
|
|||||||
UserIcon,
|
UserIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} 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 type { MessageDescriptor } from '@vintl/vintl'
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import { Tooltip } from 'floating-vue'
|
||||||
import type { Component } from 'vue'
|
import type { Component } from 'vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { copyToClipboard } from '@/helpers/utils'
|
|
||||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { Tooltip } from 'floating-vue'
|
|
||||||
|
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'
|
||||||
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
const formatRelativeTime = useRelativeTime()
|
const formatRelativeTime = useRelativeTime()
|
||||||
@@ -235,7 +236,8 @@ const messages = defineMessages({
|
|||||||
/>
|
/>
|
||||||
<Tooltip :disabled="!hasPlayersTooltip">
|
<Tooltip :disabled="!hasPlayersTooltip">
|
||||||
<span :class="{ 'cursor-help': hasPlayersTooltip }">
|
<span :class="{ 'cursor-help': hasPlayersTooltip }">
|
||||||
{{ formatNumber(serverStatus.players?.online, false) }} online
|
{{ formatNumber(serverStatus.players?.online, false) }}
|
||||||
|
online
|
||||||
</span>
|
</span>
|
||||||
<template #popper>
|
<template #popper>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
@@ -248,7 +250,8 @@ const messages = defineMessages({
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<NoSignalIcon aria-hidden="true" stroke-width="3px" class="shrink-0" /> Offline
|
<NoSignalIcon aria-hidden="true" stroke-width="3px" class="shrink-0" />
|
||||||
|
Offline
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -258,7 +261,9 @@ const messages = defineMessages({
|
|||||||
world.last_played ? dayjs(world.last_played).format('MMMM D, YYYY [at] h:mm A') : null
|
world.last_played ? dayjs(world.last_played).format('MMMM D, YYYY [at] h:mm A') : null
|
||||||
"
|
"
|
||||||
class="w-fit shrink-0"
|
class="w-fit shrink-0"
|
||||||
:class="{ 'cursor-help smart-clickable:allow-pointer-events': world.last_played }"
|
:class="{
|
||||||
|
'cursor-help smart-clickable:allow-pointer-events': world.last_played,
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template v-if="world.last_played">
|
<template v-if="world.last_played">
|
||||||
{{
|
{{
|
||||||
@@ -435,17 +440,20 @@ const messages = defineMessages({
|
|||||||
{{ formatMessage(messages.viewInstance) }}
|
{{ formatMessage(messages.viewInstance) }}
|
||||||
</template>
|
</template>
|
||||||
<template #edit>
|
<template #edit>
|
||||||
<EditIcon aria-hidden="true" /> {{ formatMessage(commonMessages.editButton) }}
|
<EditIcon aria-hidden="true" />
|
||||||
|
{{ formatMessage(commonMessages.editButton) }}
|
||||||
</template>
|
</template>
|
||||||
<template #open-folder>
|
<template #open-folder>
|
||||||
<FolderOpenIcon aria-hidden="true" />
|
<FolderOpenIcon aria-hidden="true" />
|
||||||
{{ formatMessage(commonMessages.openFolderButton) }}
|
{{ formatMessage(commonMessages.openFolderButton) }}
|
||||||
</template>
|
</template>
|
||||||
<template #copy-address>
|
<template #copy-address>
|
||||||
<ClipboardCopyIcon aria-hidden="true" /> {{ formatMessage(messages.copyAddress) }}
|
<ClipboardCopyIcon aria-hidden="true" />
|
||||||
|
{{ formatMessage(messages.copyAddress) }}
|
||||||
</template>
|
</template>
|
||||||
<template #refresh>
|
<template #refresh>
|
||||||
<UpdatedIcon aria-hidden="true" /> {{ formatMessage(commonMessages.refreshButton) }}
|
<UpdatedIcon aria-hidden="true" />
|
||||||
|
{{ formatMessage(commonMessages.refreshButton) }}
|
||||||
</template>
|
</template>
|
||||||
<template #dont-show-on-home>
|
<template #dont-show-on-home>
|
||||||
<XIcon aria-hidden="true" />
|
<XIcon aria-hidden="true" />
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PlayIcon, PlusIcon, XIcon } from '@modrinth/assets'
|
import { PlayIcon, PlusIcon, XIcon } from '@modrinth/assets'
|
||||||
import { ButtonStyled, commonMessages } from '@modrinth/ui'
|
import { ButtonStyled, commonMessages, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { ref } from 'vue'
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.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 { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
import { handleError } from '@/store/notifications'
|
import { ref } from 'vue'
|
||||||
import ServerModalBody from '@/components/ui/world/modal/ServerModalBody.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 { add_server_to_profile, type ServerPackStatus, type ServerWorld } from '@/helpers/worlds.ts'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SaveIcon, XIcon } from '@modrinth/assets'
|
import { SaveIcon, XIcon } from '@modrinth/assets'
|
||||||
import { ButtonStyled, commonMessages } from '@modrinth/ui'
|
import { ButtonStyled, commonMessages, injectNotificationManager } from '@modrinth/ui'
|
||||||
|
import { defineMessage, useVIntl } from '@vintl/vintl'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.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 { GameInstance } from '@/helpers/types'
|
||||||
import {
|
import {
|
||||||
type ServerPackStatus,
|
type DisplayStatus,
|
||||||
edit_server_in_profile,
|
edit_server_in_profile,
|
||||||
|
type ServerPackStatus,
|
||||||
type ServerWorld,
|
type ServerWorld,
|
||||||
set_world_display_status,
|
set_world_display_status,
|
||||||
type DisplayStatus,
|
|
||||||
} from '@/helpers/worlds.ts'
|
} 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 { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ChevronRightIcon, SaveIcon, XIcon, UndoIcon } from '@modrinth/assets'
|
import { ChevronRightIcon, SaveIcon, UndoIcon, XIcon } from '@modrinth/assets'
|
||||||
import { Avatar, ButtonStyled, commonMessages } from '@modrinth/ui'
|
import { Avatar, ButtonStyled, commonMessages, injectNotificationManager } from '@modrinth/ui'
|
||||||
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import ModalWrapper from '@/components/ui/modal/ModalWrapper.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 { GameInstance } from '@/helpers/types'
|
||||||
import type { DisplayStatus, SingleplayerWorld } from '@/helpers/worlds.ts'
|
import type { DisplayStatus, SingleplayerWorld } from '@/helpers/worlds.ts'
|
||||||
import { set_world_display_status, rename_world, reset_world_icon } from '@/helpers/worlds.ts'
|
import { rename_world, reset_world_icon, set_world_display_status } 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 { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { Checkbox } from '@modrinth/ui'
|
||||||
import { defineMessage, useVIntl } from '@vintl/vintl'
|
import { defineMessage, useVIntl } from '@vintl/vintl'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { Checkbox } from '@modrinth/ui'
|
|
||||||
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
const value = defineModel<boolean>({ required: true })
|
const value = defineModel<boolean>({ required: true })
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { TeleportDropdownMenu } from '@modrinth/ui'
|
import { TeleportDropdownMenu } from '@modrinth/ui'
|
||||||
|
import { defineMessages, type MessageDescriptor, useVIntl } from '@vintl/vintl'
|
||||||
|
|
||||||
import type { ServerPackStatus } from '@/helpers/worlds.ts'
|
import type { ServerPackStatus } from '@/helpers/worlds.ts'
|
||||||
import { type MessageDescriptor, defineMessages, useVIntl } from '@vintl/vintl'
|
|
||||||
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
import cssContent from '@/assets/stylesheets/macFix.css?inline'
|
import cssContent from '@/assets/stylesheets/macFix.css?inline'
|
||||||
|
|
||||||
export async function useCheckDisableMouseover() {
|
export async function useCheckDisableMouseover() {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ref, computed } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import { get_max_memory } from '@/helpers/jre.js'
|
import { get_max_memory } from '@/helpers/jre.js'
|
||||||
import { handleError } from '@/store/notifications.js'
|
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
const maxMemory = ref(Math.floor((await get_max_memory().catch(handleError)) / 1024))
|
const maxMemory = ref(Math.floor((await get_max_memory()) / 1024))
|
||||||
|
|
||||||
const snapPoints = computed(() => {
|
const snapPoints = computed(() => {
|
||||||
let points = []
|
let points = []
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { fetch } from '@tauri-apps/plugin-http'
|
|
||||||
import { handleError } from '@/store/state.js'
|
|
||||||
import { getVersion } from '@tauri-apps/api/app'
|
import { getVersion } from '@tauri-apps/api/app'
|
||||||
|
import { fetch } from '@tauri-apps/plugin-http'
|
||||||
|
|
||||||
export const useFetch = async (url, item, isSilent) => {
|
export const useFetch = async (url, item, isSilent) => {
|
||||||
try {
|
try {
|
||||||
@@ -11,8 +10,9 @@ export const useFetch = async (url, item, isSilent) => {
|
|||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!isSilent) {
|
if (!isSilent) {
|
||||||
handleError({ message: `Error fetching ${item}` })
|
throw err
|
||||||
}
|
} else {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* and deserialized into a usable JS object.
|
* and deserialized into a usable JS object.
|
||||||
*/
|
*/
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
import { create } from './profile'
|
import { create } from './profile'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ export async function get_logs_by_filename(profilePath, logType, filename) {
|
|||||||
|
|
||||||
/// Get a profile's log text only by filename
|
/// Get a profile's log text only by filename
|
||||||
export async function get_output_by_filename(profilePath, logType, filename) {
|
export async function get_output_by_filename(profilePath, logType, filename) {
|
||||||
return await invoke('plugin:logs|logs_get_output_by_filename', { profilePath, logType, filename })
|
return await invoke('plugin:logs|logs_get_output_by_filename', {
|
||||||
|
profilePath,
|
||||||
|
logType,
|
||||||
|
filename,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a profile's log by filename
|
/// Delete a profile's log by filename
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* and deserialized into a usable JS object.
|
* and deserialized into a usable JS object.
|
||||||
*/
|
*/
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
import { create } from './profile'
|
import { create } from './profile'
|
||||||
|
|
||||||
// Installs pack from a version ID
|
// Installs pack from a version ID
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
* and deserialized into a usable JS object.
|
* and deserialized into a usable JS object.
|
||||||
*/
|
*/
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
import { install_to_existing_profile } from '@/helpers/pack.js'
|
import { install_to_existing_profile } from '@/helpers/pack.js'
|
||||||
import { handleError } from '@/store/notifications.js'
|
|
||||||
|
|
||||||
/// Add instance
|
/// Add instance
|
||||||
/*
|
/*
|
||||||
@@ -128,7 +128,10 @@ export async function remove_project(path, projectPath) {
|
|||||||
|
|
||||||
// Update a managed Modrinth profile to a specific version
|
// Update a managed Modrinth profile to a specific version
|
||||||
export async function update_managed_modrinth_version(path, versionId) {
|
export async function update_managed_modrinth_version(path, versionId) {
|
||||||
return await invoke('plugin:profile|profile_update_managed_modrinth_version', { path, versionId })
|
return await invoke('plugin:profile|profile_update_managed_modrinth_version', {
|
||||||
|
path,
|
||||||
|
versionId,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repair a managed Modrinth profile
|
// Repair a managed Modrinth profile
|
||||||
@@ -197,8 +200,8 @@ export async function finish_install(instance) {
|
|||||||
linkedData.version_id,
|
linkedData.version_id,
|
||||||
instance.name,
|
instance.name,
|
||||||
instance.path,
|
instance.path,
|
||||||
).catch(handleError)
|
)
|
||||||
} else {
|
} else {
|
||||||
await install(instance.path, false).catch(handleError)
|
await install(instance.path, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import * as THREE from 'three'
|
import { ClassicPlayerModel, SlimPlayerModel } from '@modrinth/assets'
|
||||||
import type { Skin, Cape } from '../skins'
|
|
||||||
import { get_normalized_skin_texture, determineModelType } from '../skins'
|
|
||||||
import { reactive } from 'vue'
|
|
||||||
import {
|
import {
|
||||||
setupSkinModel,
|
|
||||||
disposeCaches,
|
|
||||||
loadTexture,
|
|
||||||
applyCapeTexture,
|
applyCapeTexture,
|
||||||
createTransparentTexture,
|
createTransparentTexture,
|
||||||
|
disposeCaches,
|
||||||
|
loadTexture,
|
||||||
|
setupSkinModel,
|
||||||
} from '@modrinth/utils'
|
} from '@modrinth/utils'
|
||||||
import { skinPreviewStorage } from '../storage/skin-preview-storage'
|
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 { headStorage } from '../storage/head-storage'
|
||||||
import { ClassicPlayerModel, SlimPlayerModel } from '@modrinth/assets'
|
import { skinPreviewStorage } from '../storage/skin-preview-storage'
|
||||||
|
|
||||||
export interface RenderResult {
|
export interface RenderResult {
|
||||||
forwards: string
|
forwards: string
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
* and deserialized into a usable JS object.
|
* and deserialized into a usable JS object.
|
||||||
*/
|
*/
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
import type { ColorTheme, FeatureFlag } from '@/store/theme.ts'
|
|
||||||
import type { Hooks, MemorySettings, WindowSize } from '@/helpers/types'
|
import type { Hooks, MemorySettings, WindowSize } from '@/helpers/types'
|
||||||
|
import type { ColorTheme, FeatureFlag } from '@/store/theme.ts'
|
||||||
|
|
||||||
// Settings object
|
// Settings object
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { invoke } from '@tauri-apps/api/core'
|
|
||||||
import { handleError } from '@/store/notifications'
|
|
||||||
import { arrayBufferToBase64 } from '@modrinth/utils'
|
import { arrayBufferToBase64 } from '@modrinth/utils'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
export interface Cape {
|
export interface Cape {
|
||||||
id: string
|
id: string
|
||||||
@@ -39,7 +38,7 @@ export const DEFAULT_MODELS: Record<string, SkinModel> = {
|
|||||||
|
|
||||||
export function filterSavedSkins(list: Skin[]) {
|
export function filterSavedSkins(list: Skin[]) {
|
||||||
const customSkins = list.filter((s) => s.source !== 'default')
|
const customSkins = list.filter((s) => s.source !== 'default')
|
||||||
fixUnknownSkins(customSkins).catch(handleError)
|
fixUnknownSkins(customSkins)
|
||||||
return customSkins
|
return customSkins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { get_full_path, get_mod_full_path } from '@/helpers/profile'
|
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
|
import { get_full_path, get_mod_full_path } from '@/helpers/profile'
|
||||||
|
|
||||||
export async function isDev() {
|
export async function isDev() {
|
||||||
return await invoke('is_dev')
|
return await invoke('is_dev')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
import { autoToHTML } from '@geometrically/minecraft-motd-parser'
|
||||||
|
import type { GameVersion } from '@modrinth/ui'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
import { get_full_path } from '@/helpers/profile'
|
import { get_full_path } from '@/helpers/profile'
|
||||||
import { openPath } from '@/helpers/utils'
|
import { openPath } from '@/helpers/utils'
|
||||||
import { autoToHTML } from '@geometrically/minecraft-motd-parser'
|
|
||||||
import dayjs from 'dayjs'
|
|
||||||
import type { GameVersion } from '@modrinth/ui'
|
|
||||||
|
|
||||||
type BaseWorld = {
|
type BaseWorld = {
|
||||||
name: string
|
name: string
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
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 'floating-vue/dist/style.css'
|
||||||
import { createPlugin } from '@vintl/vintl/plugin'
|
|
||||||
import * as Sentry from '@sentry/vue'
|
import * as Sentry from '@sentry/vue'
|
||||||
import { VueScanPlugin } from '@taijased/vue-render-tracker'
|
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({
|
const VIntlPlugin = createPlugin({
|
||||||
controllerOpts: {
|
controllerOpts: {
|
||||||
|
|||||||
@@ -1,33 +1,35 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, nextTick, ref, shallowRef, watch } from 'vue'
|
import { ClipboardCopyIcon, ExternalIcon, GlobeIcon, SearchIcon, XIcon } from '@modrinth/assets'
|
||||||
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 type { Category, GameVersion, Platform, ProjectType, SortType, Tags } from '@modrinth/ui'
|
||||||
import {
|
import {
|
||||||
SearchFilterControl,
|
|
||||||
SearchSidebarFilter,
|
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
DropdownSelect,
|
DropdownSelect,
|
||||||
|
injectNotificationManager,
|
||||||
LoadingIndicator,
|
LoadingIndicator,
|
||||||
Pagination,
|
Pagination,
|
||||||
|
SearchFilterControl,
|
||||||
|
SearchSidebarFilter,
|
||||||
useSearch,
|
useSearch,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
import { handleError } from '@/store/state'
|
import { openUrl } from '@tauri-apps/plugin-opener'
|
||||||
import { useBreadcrumbs } from '@/store/breadcrumbs'
|
import { defineMessages, useVIntl } from '@vintl/vintl'
|
||||||
import { get_categories, get_game_versions, get_loaders } from '@/helpers/tags'
|
import type { Ref } from 'vue'
|
||||||
|
import { computed, nextTick, ref, shallowRef, watch } from 'vue'
|
||||||
import type { LocationQuery } from 'vue-router'
|
import type { LocationQuery } from 'vue-router'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import SearchCard from '@/components/ui/SearchCard.vue'
|
|
||||||
import { get as getInstance, get_projects as getInstanceProjects } from '@/helpers/profile.js'
|
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
||||||
import { get_search_results } from '@/helpers/cache.js'
|
|
||||||
import NavTabs from '@/components/ui/NavTabs.vue'
|
|
||||||
import type Instance from '@/components/ui/Instance.vue'
|
import type Instance from '@/components/ui/Instance.vue'
|
||||||
import InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
|
import InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
import NavTabs from '@/components/ui/NavTabs.vue'
|
||||||
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
import SearchCard from '@/components/ui/SearchCard.vue'
|
||||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
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'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -160,6 +162,8 @@ const {
|
|||||||
createPageParams,
|
createPageParams,
|
||||||
} = useSearch(projectTypes, tags, instanceFilters)
|
} = useSearch(projectTypes, tags, instanceFilters)
|
||||||
|
|
||||||
|
const previousFilterState = ref('')
|
||||||
|
|
||||||
const offline = ref(!navigator.onLine)
|
const offline = ref(!navigator.onLine)
|
||||||
window.addEventListener('offline', () => {
|
window.addEventListener('offline', () => {
|
||||||
offline.value = true
|
offline.value = true
|
||||||
@@ -220,7 +224,20 @@ async function refreshSearch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
results.value = rawResults.result
|
results.value = rawResults.result
|
||||||
|
|
||||||
|
const currentFilterState = JSON.stringify({
|
||||||
|
query: query.value,
|
||||||
|
filters: currentFilters.value,
|
||||||
|
sort: currentSortType.value,
|
||||||
|
maxResults: maxResults.value,
|
||||||
|
projectTypes: projectTypes.value,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (previousFilterState.value && previousFilterState.value !== currentFilterState) {
|
||||||
currentPage.value = 1
|
currentPage.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
previousFilterState.value = currentFilterState
|
||||||
|
|
||||||
const persistentParams: LocationQuery = {}
|
const persistentParams: LocationQuery = {}
|
||||||
|
|
||||||
@@ -380,6 +397,15 @@ const handleOptionsClick = (args) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await refreshSearch()
|
await refreshSearch()
|
||||||
|
|
||||||
|
// Initialize previousFilterState after first search
|
||||||
|
previousFilterState.value = JSON.stringify({
|
||||||
|
query: query.value,
|
||||||
|
filters: currentFilters.value,
|
||||||
|
sort: currentSortType.value,
|
||||||
|
maxResults: maxResults.value,
|
||||||
|
projectTypes: projectTypes.value,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onUnmounted, computed } from 'vue'
|
import { injectNotificationManager } from '@modrinth/ui'
|
||||||
import { useRoute } from 'vue-router'
|
|
||||||
import RowDisplay from '@/components/RowDisplay.vue'
|
|
||||||
import { list } from '@/helpers/profile.js'
|
|
||||||
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 type { SearchResult } from '@modrinth/utils'
|
||||||
import RecentWorldsList from '@/components/ui/world/RecentWorldsList.vue'
|
import dayjs from 'dayjs'
|
||||||
import type { GameInstance } from '@/helpers/types'
|
import { computed, onUnmounted, ref } 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 { useBreadcrumbs } from '@/store/breadcrumbs'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const breadcrumbs = useBreadcrumbs()
|
const breadcrumbs = useBreadcrumbs()
|
||||||
|
|
||||||
|
|||||||
@@ -12,42 +12,44 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
ConfirmModal,
|
ConfirmModal,
|
||||||
|
injectNotificationManager,
|
||||||
SkinButton,
|
SkinButton,
|
||||||
SkinLikeTextButton,
|
SkinLikeTextButton,
|
||||||
SkinPreviewRenderer,
|
SkinPreviewRenderer,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
|
import { arrayBufferToBase64 } from '@modrinth/utils'
|
||||||
import { computedAsync } from '@vueuse/core'
|
import { computedAsync } from '@vueuse/core'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { computed, inject, onMounted, onUnmounted, ref, useTemplateRef, watch } 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 EditSkinModal from '@/components/ui/skin/EditSkinModal.vue'
|
||||||
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
|
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
|
||||||
import UploadSkinModal from '@/components/ui/skin/UploadSkinModal.vue'
|
import UploadSkinModal from '@/components/ui/skin/UploadSkinModal.vue'
|
||||||
import { handleError, useNotifications } from '@/store/notifications'
|
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 type { Cape, Skin } from '@/helpers/skins.ts'
|
import type { Cape, Skin } from '@/helpers/skins.ts'
|
||||||
import {
|
import {
|
||||||
normalize_skin_texture,
|
|
||||||
equip_skin,
|
equip_skin,
|
||||||
filterDefaultSkins,
|
filterDefaultSkins,
|
||||||
filterSavedSkins,
|
filterSavedSkins,
|
||||||
get_available_capes,
|
get_available_capes,
|
||||||
get_available_skins,
|
get_available_skins,
|
||||||
get_normalized_skin_texture,
|
get_normalized_skin_texture,
|
||||||
|
normalize_skin_texture,
|
||||||
remove_custom_skin,
|
remove_custom_skin,
|
||||||
set_default_cape,
|
set_default_cape,
|
||||||
} from '@/helpers/skins.ts'
|
} 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 { handleSevereError } from '@/store/error'
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
|
||||||
import type AccountsCard from '@/components/ui/AccountsCard.vue'
|
|
||||||
import { arrayBufferToBase64 } from '@modrinth/utils'
|
|
||||||
const editSkinModal = useTemplateRef('editSkinModal')
|
const editSkinModal = useTemplateRef('editSkinModal')
|
||||||
const selectCapeModal = useTemplateRef('selectCapeModal')
|
const selectCapeModal = useTemplateRef('selectCapeModal')
|
||||||
const uploadSkinModal = useTemplateRef('uploadSkinModal')
|
const uploadSkinModal = useTemplateRef('uploadSkinModal')
|
||||||
|
|
||||||
const notifications = useNotifications()
|
const notifications = injectNotificationManager()
|
||||||
|
const { handleError } = notifications
|
||||||
|
|
||||||
const settings = ref(await getSettings())
|
const settings = ref(await getSettings())
|
||||||
const skins = ref<Skin[]>([])
|
const skins = ref<Skin[]>([])
|
||||||
@@ -64,7 +66,14 @@ const defaultCape = ref<Cape>()
|
|||||||
const originalSelectedSkin = ref<Skin | null>(null)
|
const originalSelectedSkin = ref<Skin | null>(null)
|
||||||
const originalDefaultCape = ref<Cape>()
|
const originalDefaultCape = ref<Cape>()
|
||||||
|
|
||||||
const savedSkins = computed(() => filterSavedSkins(skins.value))
|
const savedSkins = computed(() => {
|
||||||
|
try {
|
||||||
|
return filterSavedSkins(skins.value)
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error as Error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
})
|
||||||
const defaultSkins = computed(() => filterDefaultSkins(skins.value))
|
const defaultSkins = computed(() => filterDefaultSkins(skins.value))
|
||||||
|
|
||||||
const currentCape = computed(() => {
|
const currentCape = computed(() => {
|
||||||
@@ -113,7 +122,7 @@ async function loadCapes() {
|
|||||||
defaultCape.value = capes.value.find((c) => c.is_equipped)
|
defaultCape.value = capes.value.find((c) => c.is_equipped)
|
||||||
originalDefaultCape.value = defaultCape.value
|
originalDefaultCape.value = defaultCape.value
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (currentUser.value) {
|
if (currentUser.value && error instanceof Error) {
|
||||||
handleError(error)
|
handleError(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +135,7 @@ async function loadSkins() {
|
|||||||
selectedSkin.value = skins.value.find((s) => s.is_equipped) ?? null
|
selectedSkin.value = skins.value.find((s) => s.is_equipped) ?? null
|
||||||
originalSelectedSkin.value = selectedSkin.value
|
originalSelectedSkin.value = selectedSkin.value
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (currentUser.value) {
|
if (currentUser.value && error instanceof Error) {
|
||||||
handleError(error)
|
handleError(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +170,7 @@ async function changeSkin(newSkin: Skin) {
|
|||||||
text: "You're changing your skin too frequently. Mojang's servers have temporarily blocked further requests. Please wait a moment before trying again.",
|
text: "You're changing your skin too frequently. Mojang's servers have temporarily blocked further requests. Please wait a moment before trying again.",
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
handleError(error)
|
handleError(error as Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +199,7 @@ async function handleCapeSelected(cape: Cape | undefined) {
|
|||||||
text: "You're changing your cape too frequently. Mojang's servers have temporarily blocked further requests. Please wait a moment before trying again.",
|
text: "You're changing your cape too frequently. Mojang's servers have temporarily blocked further requests. Please wait a moment before trying again.",
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
handleError(error)
|
handleError(error as Error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +216,7 @@ async function loadCurrentUser() {
|
|||||||
const allAccounts = await users()
|
const allAccounts = await users()
|
||||||
currentUser.value = allAccounts.find((acc) => acc.profile.id === defaultId)
|
currentUser.value = allAccounts.find((acc) => acc.profile.id === defaultId)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
handleError(e)
|
handleError(e as Error)
|
||||||
currentUser.value = undefined
|
currentUser.value = undefined
|
||||||
currentUserId.value = undefined
|
currentUserId.value = undefined
|
||||||
}
|
}
|
||||||
@@ -276,7 +285,7 @@ async function checkUserChanges() {
|
|||||||
await loadSkins()
|
await loadSkins()
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (currentUser.value) {
|
if (currentUser.value && error instanceof Error) {
|
||||||
handleError(error)
|
handleError(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,7 +385,7 @@ await Promise.all([loadCapes(), loadSkins(), loadCurrentUser()])
|
|||||||
color="green"
|
color="green"
|
||||||
aria-label="Edit skin"
|
aria-label="Edit skin"
|
||||||
class="pointer-events-auto"
|
class="pointer-events-auto"
|
||||||
@click.stop="(e) => editSkinModal?.show(e, skin)"
|
@click.stop="(e: MouseEvent) => editSkinModal?.show(e, skin)"
|
||||||
>
|
>
|
||||||
<EditIcon /> Edit
|
<EditIcon /> Edit
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Index from './Index.vue'
|
|
||||||
import Browse from './Browse.vue'
|
import Browse from './Browse.vue'
|
||||||
import Worlds from './Worlds.vue'
|
import Index from './Index.vue'
|
||||||
import Skins from './Skins.vue'
|
import Skins from './Skins.vue'
|
||||||
|
import Worlds from './Worlds.vue'
|
||||||
|
|
||||||
export { Index, Browse, Worlds, Skins }
|
export { Browse, Index, Skins, Worlds }
|
||||||
|
|||||||
@@ -157,13 +157,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
ButtonStyled,
|
|
||||||
ContentPageHeader,
|
|
||||||
LoadingIndicator,
|
|
||||||
OverflowMenu,
|
|
||||||
} from '@modrinth/ui'
|
|
||||||
import {
|
import {
|
||||||
CheckCircleIcon,
|
CheckCircleIcon,
|
||||||
ClipboardCopyIcon,
|
ClipboardCopyIcon,
|
||||||
@@ -187,28 +180,38 @@ import {
|
|||||||
UserPlusIcon,
|
UserPlusIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { finish_install, get, get_full_path, kill, run } from '@/helpers/profile'
|
import {
|
||||||
import { get_by_profile_path } from '@/helpers/process'
|
Avatar,
|
||||||
import { process_listener, profile_listener } from '@/helpers/events'
|
ButtonStyled,
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
ContentPageHeader,
|
||||||
import { computed, onUnmounted, ref, watch } from 'vue'
|
injectNotificationManager,
|
||||||
import { handleError, useBreadcrumbs, useLoading } from '@/store/state'
|
LoadingIndicator,
|
||||||
import { showProfileInFolder } from '@/helpers/utils.js'
|
OverflowMenu,
|
||||||
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
} from '@modrinth/ui'
|
||||||
import NavTabs from '@/components/ui/NavTabs.vue'
|
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
|
||||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
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 dayjs from 'dayjs'
|
||||||
import duration from 'dayjs/plugin/duration'
|
import duration from 'dayjs/plugin/duration'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
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 ExportModal from '@/components/ui/ExportModal.vue'
|
||||||
import InstanceSettingsModal from '@/components/ui/modal/InstanceSettingsModal.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 { useBreadcrumbs, useLoading } from '@/store/state'
|
||||||
|
|
||||||
dayjs.extend(duration)
|
dayjs.extend(duration)
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -328,7 +331,7 @@ const stopInstance = async (context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const repairInstance = async () => {
|
const repairInstance = async () => {
|
||||||
await finish_install(instance.value)
|
await finish_install(instance.value).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleRightClick = (event) => {
|
const handleRightClick = (event) => {
|
||||||
|
|||||||
@@ -88,30 +88,32 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||||
|
|
||||||
import { CheckIcon, ClipboardCopyIcon, ShareIcon, TrashIcon } from '@modrinth/assets'
|
import { CheckIcon, ClipboardCopyIcon, ShareIcon, TrashIcon } from '@modrinth/assets'
|
||||||
import { Button, Card, Checkbox, DropdownSelect } from '@modrinth/ui'
|
import { Button, Card, Checkbox, DropdownSelect, injectNotificationManager } 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 dayjs from 'dayjs'
|
||||||
import isToday from 'dayjs/plugin/isToday'
|
import isToday from 'dayjs/plugin/isToday'
|
||||||
import isYesterday from 'dayjs/plugin/isYesterday'
|
import isYesterday from 'dayjs/plugin/isYesterday'
|
||||||
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 { 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 { RecycleScroller } from 'vue-virtual-scroller'
|
||||||
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
|
||||||
import ShareModalWrapper from '@/components/ui/modal/ShareModalWrapper.vue'
|
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'
|
||||||
|
|
||||||
dayjs.extend(isToday)
|
dayjs.extend(isToday)
|
||||||
dayjs.extend(isYesterday)
|
dayjs.extend(isYesterday)
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@@ -60,7 +60,10 @@
|
|||||||
if (x.id) {
|
if (x.id) {
|
||||||
item.project = {
|
item.project = {
|
||||||
id: x.id,
|
id: x.id,
|
||||||
link: { path: `/project/${x.id}`, query: { i: props.instance.path } },
|
link: {
|
||||||
|
path: `/project/${x.id}`,
|
||||||
|
query: { i: props.instance.path },
|
||||||
|
},
|
||||||
linkProps: {},
|
linkProps: {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,16 +274,35 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
ContentListPanel,
|
ContentListPanel,
|
||||||
|
injectNotificationManager,
|
||||||
OverflowMenu,
|
OverflowMenu,
|
||||||
Pagination,
|
Pagination,
|
||||||
RadialHeader,
|
RadialHeader,
|
||||||
Toggle,
|
Toggle,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
|
import type { ContentItem } from '@modrinth/ui/src/components/content/ContentListItem.vue'
|
||||||
import type { Organization, Project, TeamMember, Version } from '@modrinth/utils'
|
import type { Organization, Project, TeamMember, Version } from '@modrinth/utils'
|
||||||
import { formatProjectType } 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 type { ComputedRef } from 'vue'
|
||||||
import { computed, onUnmounted, ref, watch } from 'vue'
|
import { computed, onUnmounted, ref, watch } from 'vue'
|
||||||
import { defineMessages, useVIntl } from '@vintl/vintl'
|
|
||||||
|
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 {
|
import {
|
||||||
add_project_from_path,
|
add_project_from_path,
|
||||||
get_projects,
|
get_projects,
|
||||||
@@ -289,26 +311,10 @@ import {
|
|||||||
update_all,
|
update_all,
|
||||||
update_project,
|
update_project,
|
||||||
} from '@/helpers/profile.js'
|
} from '@/helpers/profile.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 { CacheBehaviour, ContentFile, GameInstance } from '@/helpers/types'
|
||||||
import type ContextMenu from '@/components/ui/ContextMenu.vue'
|
import { highlightModInProfile } from '@/helpers/utils.js'
|
||||||
import type { ContentItem } from '@modrinth/ui/src/components/content/ContentListItem.vue'
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
instance: GameInstance
|
instance: GameInstance
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<template>{{ instance.name }} overview</template>
|
<template>{{ instance.name }} overview</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { GameInstance } from '@/helpers/types'
|
|
||||||
import type ContextMenu from '@/components/ui/ContextMenu.vue'
|
|
||||||
import type { Version } from '@modrinth/utils'
|
import type { Version } from '@modrinth/utils'
|
||||||
|
|
||||||
|
import type ContextMenu from '@/components/ui/ContextMenu.vue'
|
||||||
|
import type { GameInstance } from '@/helpers/types'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
instance: GameInstance
|
instance: GameInstance
|
||||||
options: InstanceType<typeof ContextMenu>
|
options: InstanceType<typeof ContextMenu>
|
||||||
|
|||||||
@@ -121,55 +121,56 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onUnmounted, watch } from 'vue'
|
import { PlusIcon, SearchIcon, SpinnerIcon, UpdatedIcon, XIcon } from '@modrinth/assets'
|
||||||
import { useRoute } from 'vue-router'
|
|
||||||
import type { GameInstance } from '@/helpers/types'
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonStyled,
|
ButtonStyled,
|
||||||
RadialHeader,
|
|
||||||
FilterBar,
|
FilterBar,
|
||||||
type FilterBarOption,
|
type FilterBarOption,
|
||||||
type GameVersion,
|
|
||||||
GAME_MODES,
|
GAME_MODES,
|
||||||
|
type GameVersion,
|
||||||
|
injectNotificationManager,
|
||||||
|
RadialHeader,
|
||||||
} from '@modrinth/ui'
|
} from '@modrinth/ui'
|
||||||
import { PlusIcon, SpinnerIcon, UpdatedIcon, SearchIcon, XIcon } from '@modrinth/assets'
|
import type { Version } from '@modrinth/utils'
|
||||||
import {
|
import { defineMessages } from '@vintl/vintl'
|
||||||
type ProtocolVersion,
|
import { computed, onUnmounted, ref, watch } from 'vue'
|
||||||
type SingleplayerWorld,
|
import { useRoute } from 'vue-router'
|
||||||
type World,
|
|
||||||
type ServerWorld,
|
import type ContextMenu from '@/components/ui/ContextMenu.vue'
|
||||||
type ServerData,
|
import ConfirmModalWrapper from '@/components/ui/modal/ConfirmModalWrapper.vue'
|
||||||
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 AddServerModal from '@/components/ui/world/modal/AddServerModal.vue'
|
||||||
import EditServerModal from '@/components/ui/world/modal/EditServerModal.vue'
|
import EditServerModal from '@/components/ui/world/modal/EditServerModal.vue'
|
||||||
import EditWorldModal from '@/components/ui/world/modal/EditSingleplayerWorldModal.vue'
|
import EditWorldModal from '@/components/ui/world/modal/EditSingleplayerWorldModal.vue'
|
||||||
import WorldItem from '@/components/ui/world/WorldItem.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 { profile_listener } from '@/helpers/events'
|
||||||
import { get_game_versions } from '@/helpers/tags'
|
import { get_game_versions } from '@/helpers/tags'
|
||||||
import { defineMessages } from '@vintl/vintl'
|
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'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const addServerModal = ref<InstanceType<typeof AddServerModal>>()
|
const addServerModal = ref<InstanceType<typeof AddServerModal>>()
|
||||||
@@ -282,7 +283,7 @@ async function editServer(server: ServerWorld) {
|
|||||||
await refreshServer(server.address)
|
await refreshServer(server.address)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleError(`Error refreshing server, refreshing all worlds`)
|
handleError(new Error(`Error refreshing server, refreshing all worlds`))
|
||||||
await refreshAllWorlds()
|
await refreshAllWorlds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,7 +302,7 @@ async function editWorld(path: string, name: string, removeIcon: boolean) {
|
|||||||
}
|
}
|
||||||
sortWorlds(worlds.value)
|
sortWorlds(worlds.value)
|
||||||
} else {
|
} else {
|
||||||
handleError(`Error finding world in list, refreshing all worlds`)
|
handleError(new Error(`Error finding world in list, refreshing all worlds`))
|
||||||
await refreshAllWorlds()
|
await refreshAllWorlds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,7 +312,7 @@ async function deleteWorld(world: SingleplayerWorld) {
|
|||||||
worlds.value = worlds.value.filter((w) => w.type !== 'singleplayer' || w.path !== world.path)
|
worlds.value = worlds.value.filter((w) => w.type !== 'singleplayer' || w.path !== world.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleJoinError(err: unknown) {
|
function handleJoinError(err: Error) {
|
||||||
handleError(err)
|
handleError(err)
|
||||||
startingInstance.value = false
|
startingInstance.value = false
|
||||||
worldPlaying.value = undefined
|
worldPlaying.value = undefined
|
||||||
@@ -436,7 +437,7 @@ function promptToRemoveWorld(world: World): boolean {
|
|||||||
|
|
||||||
async function proceedRemoveServer() {
|
async function proceedRemoveServer() {
|
||||||
if (!serverToRemove.value) {
|
if (!serverToRemove.value) {
|
||||||
handleError(`Error removing server, no server marked for removal.`)
|
handleError(new Error(`Error removing server, no server marked for removal.`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await removeServer(serverToRemove.value)
|
await removeServer(serverToRemove.value)
|
||||||
@@ -445,7 +446,7 @@ async function proceedRemoveServer() {
|
|||||||
|
|
||||||
async function proceedDeleteWorld() {
|
async function proceedDeleteWorld() {
|
||||||
if (!worldToDelete.value) {
|
if (!worldToDelete.value) {
|
||||||
handleError(`Error deleting world, no world marked for removal.`)
|
handleError(new Error(`Error deleting world, no world marked for removal.`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await deleteWorld(worldToDelete.value)
|
await deleteWorld(worldToDelete.value)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Index from './Index.vue'
|
import Index from './Index.vue'
|
||||||
|
import Logs from './Logs.vue'
|
||||||
|
import Mods from './Mods.vue'
|
||||||
import Overview from './Overview.vue'
|
import Overview from './Overview.vue'
|
||||||
import Worlds from './Worlds.vue'
|
import Worlds from './Worlds.vue'
|
||||||
import Mods from './Mods.vue'
|
|
||||||
import Logs from './Logs.vue'
|
|
||||||
|
|
||||||
export { Index, Overview, Worlds, Mods, Logs }
|
export { Index, Logs, Mods, Overview, Worlds }
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onUnmounted, ref, shallowRef } from 'vue'
|
|
||||||
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 { PlusIcon } from '@modrinth/assets'
|
||||||
import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue'
|
import { Button, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { NewInstanceImage } from '@/assets/icons'
|
import { onUnmounted, ref, shallowRef } from 'vue'
|
||||||
import NavTabs from '@/components/ui/NavTabs.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 { useBreadcrumbs } from '@/store/breadcrumbs.js'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const breadcrumbs = useBreadcrumbs()
|
const breadcrumbs = useBreadcrumbs()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import Custom from './Custom.vue'
|
||||||
|
import Downloaded from './Downloaded.vue'
|
||||||
import Index from './Index.vue'
|
import Index from './Index.vue'
|
||||||
import Overview from './Overview.vue'
|
import Overview from './Overview.vue'
|
||||||
import Downloaded from './Downloaded.vue'
|
|
||||||
import Custom from './Custom.vue'
|
|
||||||
|
|
||||||
export { Index, Overview, Downloaded, Custom }
|
export { Custom, Downloaded, Index, Overview }
|
||||||
|
|||||||
@@ -83,16 +83,18 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
ExpandIcon,
|
|
||||||
RightArrowIcon,
|
|
||||||
LeftArrowIcon,
|
|
||||||
ExternalIcon,
|
|
||||||
ContractIcon,
|
|
||||||
XIcon,
|
|
||||||
CalendarIcon,
|
CalendarIcon,
|
||||||
|
ContractIcon,
|
||||||
|
ExpandIcon,
|
||||||
|
ExternalIcon,
|
||||||
|
LeftArrowIcon,
|
||||||
|
RightArrowIcon,
|
||||||
|
XIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import { Button, Card } from '@modrinth/ui'
|
import { Button, Card } from '@modrinth/ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
// import { hide_ads_window, show_ads_window } from '@/helpers/ads.js'
|
||||||
import { trackEvent } from '@/helpers/analytics'
|
import { trackEvent } from '@/helpers/analytics'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -108,6 +110,7 @@ const zoomedIn = ref(false)
|
|||||||
|
|
||||||
const hideImage = () => {
|
const hideImage = () => {
|
||||||
expandedGalleryItem.value = null
|
expandedGalleryItem.value = null
|
||||||
|
// show_ads_window()
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextImage = () => {
|
const nextImage = () => {
|
||||||
@@ -135,6 +138,7 @@ const previousImage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const expandImage = (item, index) => {
|
const expandImage = (item, index) => {
|
||||||
|
// hide_ads_window()
|
||||||
expandedGalleryItem.value = item
|
expandedGalleryItem.value = item
|
||||||
expandedGalleryIndex.value = index
|
expandedGalleryIndex.value = index
|
||||||
zoomedIn.value = false
|
zoomedIn.value = false
|
||||||
|
|||||||
@@ -131,44 +131,45 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
BookmarkIcon,
|
BookmarkIcon,
|
||||||
MoreVerticalIcon,
|
|
||||||
DownloadIcon,
|
|
||||||
ReportIcon,
|
|
||||||
HeartIcon,
|
|
||||||
ExternalIcon,
|
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
GlobeIcon,
|
|
||||||
ClipboardCopyIcon,
|
ClipboardCopyIcon,
|
||||||
|
DownloadIcon,
|
||||||
|
ExternalIcon,
|
||||||
|
GlobeIcon,
|
||||||
|
HeartIcon,
|
||||||
|
MoreVerticalIcon,
|
||||||
|
ReportIcon,
|
||||||
} from '@modrinth/assets'
|
} from '@modrinth/assets'
|
||||||
import {
|
import {
|
||||||
|
ButtonStyled,
|
||||||
|
injectNotificationManager,
|
||||||
|
OverflowMenu,
|
||||||
|
ProjectBackgroundGradient,
|
||||||
ProjectHeader,
|
ProjectHeader,
|
||||||
ProjectSidebarCompatibility,
|
ProjectSidebarCompatibility,
|
||||||
ButtonStyled,
|
|
||||||
OverflowMenu,
|
|
||||||
ProjectSidebarLinks,
|
|
||||||
ProjectSidebarCreators,
|
ProjectSidebarCreators,
|
||||||
ProjectSidebarDetails,
|
ProjectSidebarDetails,
|
||||||
ProjectBackgroundGradient,
|
ProjectSidebarLinks,
|
||||||
} from '@modrinth/ui'
|
} 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 dayjs from 'dayjs'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
|
||||||
import { ref, shallowRef, watch } from 'vue'
|
import { ref, shallowRef, watch } from 'vue'
|
||||||
import { useBreadcrumbs } from '@/store/breadcrumbs'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { handleError } from '@/store/notifications.js'
|
|
||||||
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
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 InstanceIndicator from '@/components/ui/InstanceIndicator.vue'
|
||||||
import { openUrl } from '@tauri-apps/plugin-opener'
|
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 { useBreadcrumbs } from '@/store/breadcrumbs'
|
||||||
|
import { install as installVersion } from '@/store/install.js'
|
||||||
|
import { useTheming } from '@/store/state.js'
|
||||||
|
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const breadcrumbs = useBreadcrumbs()
|
const breadcrumbs = useBreadcrumbs()
|
||||||
@@ -251,7 +252,7 @@ async function install(version) {
|
|||||||
(profile) => {
|
(profile) => {
|
||||||
router.push(`/instance/${profile}`)
|
router.push(`/instance/${profile}`)
|
||||||
},
|
},
|
||||||
)
|
).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = ref(null)
|
const options = ref(null)
|
||||||
|
|||||||
@@ -182,15 +182,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { DownloadIcon, FileIcon, ReportIcon, ExternalIcon, CheckIcon } from '@modrinth/assets'
|
import { CheckIcon, DownloadIcon, ExternalIcon, FileIcon, ReportIcon } from '@modrinth/assets'
|
||||||
|
import { Avatar, Badge, Breadcrumbs, Button, Card, CopyCode } from '@modrinth/ui'
|
||||||
import { formatBytes, renderString } from '@modrinth/utils'
|
import { formatBytes, renderString } from '@modrinth/utils'
|
||||||
import { Breadcrumbs, Badge, Avatar, Card, Button, CopyCode } from '@modrinth/ui'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { releaseColor } from '@/helpers/utils'
|
|
||||||
import { ref, watch, computed } from 'vue'
|
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useBreadcrumbs } from '@/store/breadcrumbs'
|
|
||||||
import { SwapIcon } from '@/assets/icons'
|
import { SwapIcon } from '@/assets/icons'
|
||||||
import { get_project_many, get_version_many } from '@/helpers/cache.js'
|
import { get_project_many, get_version_many } from '@/helpers/cache.js'
|
||||||
|
import { releaseColor } from '@/helpers/utils'
|
||||||
|
import { useBreadcrumbs } from '@/store/breadcrumbs'
|
||||||
|
|
||||||
const breadcrumbs = useBreadcrumbs()
|
const breadcrumbs = useBreadcrumbs()
|
||||||
|
|
||||||
|
|||||||
@@ -65,12 +65,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ProjectPageVersions, ButtonStyled, OverflowMenu } from '@modrinth/ui'
|
|
||||||
import { CheckIcon, DownloadIcon, ExternalIcon, MoreVerticalIcon } from '@modrinth/assets'
|
import { CheckIcon, DownloadIcon, ExternalIcon, MoreVerticalIcon } from '@modrinth/assets'
|
||||||
|
import {
|
||||||
|
ButtonStyled,
|
||||||
|
injectNotificationManager,
|
||||||
|
OverflowMenu,
|
||||||
|
ProjectPageVersions,
|
||||||
|
} from '@modrinth/ui'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import { SwapIcon } from '@/assets/icons/index.js'
|
import { SwapIcon } from '@/assets/icons/index.js'
|
||||||
import { get_game_versions, get_loaders } from '@/helpers/tags.js'
|
import { get_game_versions, get_loaders } from '@/helpers/tags.js'
|
||||||
import { handleError } from '@/store/notifications.js'
|
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
project: {
|
project: {
|
||||||
@@ -103,6 +108,8 @@ defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const [loaders, gameVersions] = await Promise.all([
|
const [loaders, gameVersions] = await Promise.all([
|
||||||
get_loaders().catch(handleError).then(ref),
|
get_loaders().catch(handleError).then(ref),
|
||||||
get_game_versions().catch(handleError).then(ref),
|
get_game_versions().catch(handleError).then(ref),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Index from './Index.vue'
|
|
||||||
import Description from './Description.vue'
|
import Description from './Description.vue'
|
||||||
import Versions from './Versions.vue'
|
|
||||||
import Gallery from './Gallery.vue'
|
import Gallery from './Gallery.vue'
|
||||||
|
import Index from './Index.vue'
|
||||||
import Version from './Version.vue'
|
import Version from './Version.vue'
|
||||||
|
import Versions from './Versions.vue'
|
||||||
|
|
||||||
export { Index, Description, Versions, Gallery, Version }
|
export { Description, Gallery, Index, Version, Versions }
|
||||||
|
|||||||
48
apps/app-frontend/src/providers/app-notifications.ts
Normal file
48
apps/app-frontend/src/providers/app-notifications.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import {
|
||||||
|
AbstractWebNotificationManager,
|
||||||
|
type NotificationPanelLocation,
|
||||||
|
type WebNotification,
|
||||||
|
} from '@modrinth/ui'
|
||||||
|
import { type Ref, ref } from 'vue'
|
||||||
|
|
||||||
|
export class AppNotificationManager extends AbstractWebNotificationManager {
|
||||||
|
private readonly state: Ref<WebNotification[]>
|
||||||
|
private readonly locationState: Ref<NotificationPanelLocation>
|
||||||
|
|
||||||
|
public constructor() {
|
||||||
|
super()
|
||||||
|
this.state = ref<WebNotification[]>([])
|
||||||
|
this.locationState = ref<NotificationPanelLocation>('right')
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNotificationLocation(): NotificationPanelLocation {
|
||||||
|
return this.locationState.value
|
||||||
|
}
|
||||||
|
|
||||||
|
public setNotificationLocation(location: NotificationPanelLocation): void {
|
||||||
|
this.locationState.value = location
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNotifications(): WebNotification[] {
|
||||||
|
return this.state.value
|
||||||
|
}
|
||||||
|
|
||||||
|
protected addNotificationToStorage(notification: WebNotification): void {
|
||||||
|
this.state.value.push(notification)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected removeNotificationFromStorage(id: string | number): void {
|
||||||
|
const index = this.state.value.findIndex((n) => n.id === id)
|
||||||
|
if (index > -1) {
|
||||||
|
this.state.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected removeNotificationFromStorageByIndex(index: number): void {
|
||||||
|
this.state.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected clearAllNotificationsFromStorage(): void {
|
||||||
|
this.state.value.splice(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
|
||||||
import * as Pages from '@/pages'
|
import * as Pages from '@/pages'
|
||||||
import * as Project from '@/pages/project'
|
|
||||||
import * as Instance from '@/pages/instance'
|
import * as Instance from '@/pages/instance'
|
||||||
import * as Library from '@/pages/library'
|
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.
|
* Configures application routing. Add page to pages/index and then add to route table here.
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
import dayjs from 'dayjs'
|
||||||
import { defineStore } from 'pinia'
|
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 {
|
import {
|
||||||
add_project_from_version,
|
add_project_from_version,
|
||||||
check_installed,
|
check_installed,
|
||||||
@@ -7,11 +12,6 @@ import {
|
|||||||
list,
|
list,
|
||||||
remove_project,
|
remove_project,
|
||||||
} from '@/helpers/profile.js'
|
} 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', {
|
export const useInstall = defineStore('installStore', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@@ -49,11 +49,11 @@ export const install = async (
|
|||||||
callback = () => {},
|
callback = () => {},
|
||||||
createInstanceCallback = () => {},
|
createInstanceCallback = () => {},
|
||||||
) => {
|
) => {
|
||||||
const project = await get_project(projectId, 'must_revalidate').catch(handleError)
|
const project = await get_project(projectId, 'must_revalidate')
|
||||||
|
|
||||||
if (project.project_type === 'modpack') {
|
if (project.project_type === 'modpack') {
|
||||||
const version = versionId ?? project.versions[project.versions.length - 1]
|
const version = versionId ?? project.versions[project.versions.length - 1]
|
||||||
const packs = await list().catch(handleError)
|
const packs = await list()
|
||||||
|
|
||||||
if (packs.length === 0 || !packs.find((pack) => pack.linked_data?.project_id === project.id)) {
|
if (packs.length === 0 || !packs.find((pack) => pack.linked_data?.project_id === project.id)) {
|
||||||
await packInstall(
|
await packInstall(
|
||||||
@@ -62,7 +62,7 @@ export const install = async (
|
|||||||
project.title,
|
project.title,
|
||||||
project.icon_url,
|
project.icon_url,
|
||||||
createInstanceCallback,
|
createInstanceCallback,
|
||||||
).catch(handleError)
|
)
|
||||||
|
|
||||||
trackEvent('PackInstall', {
|
trackEvent('PackInstall', {
|
||||||
id: project.id,
|
id: project.id,
|
||||||
@@ -79,8 +79,8 @@ export const install = async (
|
|||||||
} else {
|
} else {
|
||||||
if (instancePath) {
|
if (instancePath) {
|
||||||
const [instance, instanceProjects, versions] = await Promise.all([
|
const [instance, instanceProjects, versions] = await Promise.all([
|
||||||
await get(instancePath).catch(handleError),
|
await get(instancePath),
|
||||||
await get_projects(instancePath).catch(handleError),
|
await get_projects(instancePath),
|
||||||
await get_version_many(project.versions, 'must_revalidate'),
|
await get_version_many(project.versions, 'must_revalidate'),
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ export const install = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await add_project_from_version(instance.path, version.id).catch(handleError)
|
await add_project_from_version(instance.path, version.id)
|
||||||
await installVersionDependencies(instance, version)
|
await installVersionDependencies(instance, version)
|
||||||
|
|
||||||
trackEvent('ProjectInstall', {
|
trackEvent('ProjectInstall', {
|
||||||
@@ -142,7 +142,7 @@ export const install = async (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const versions = (await get_version_many(project.versions).catch(handleError)).sort(
|
const versions = (await get_version_many(project.versions)).sort(
|
||||||
(a, b) => dayjs(b.date_published) - dayjs(a.date_published),
|
(a, b) => dayjs(b.date_published) - dayjs(a.date_published),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -171,30 +171,22 @@ export const installVersionDependencies = async (profile, version) => {
|
|||||||
// disallow fabric api install on quilt
|
// disallow fabric api install on quilt
|
||||||
if (dep.project_id === 'P7dR8mSH' && profile.loader === 'quilt') continue
|
if (dep.project_id === 'P7dR8mSH' && profile.loader === 'quilt') continue
|
||||||
if (dep.version_id) {
|
if (dep.version_id) {
|
||||||
if (
|
if (dep.project_id && (await check_installed(profile.path, dep.project_id))) continue
|
||||||
dep.project_id &&
|
|
||||||
(await check_installed(profile.path, dep.project_id).catch(handleError))
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
await add_project_from_version(profile.path, dep.version_id)
|
await add_project_from_version(profile.path, dep.version_id)
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (dep.project_id && (await check_installed(profile.path, dep.project_id))) continue
|
||||||
dep.project_id &&
|
|
||||||
(await check_installed(profile.path, dep.project_id).catch(handleError))
|
const depProject = await get_project(dep.project_id, 'must_revalidate')
|
||||||
|
|
||||||
|
const depVersions = (await get_version_many(depProject.versions, 'must_revalidate')).sort(
|
||||||
|
(a, b) => dayjs(b.date_published) - dayjs(a.date_published),
|
||||||
)
|
)
|
||||||
continue
|
|
||||||
|
|
||||||
const depProject = await get_project(dep.project_id, 'must_revalidate').catch(handleError)
|
|
||||||
|
|
||||||
const depVersions = (
|
|
||||||
await get_version_many(depProject.versions, 'must_revalidate').catch(handleError)
|
|
||||||
).sort((a, b) => dayjs(b.date_published) - dayjs(a.date_published))
|
|
||||||
|
|
||||||
const latest = depVersions.find(
|
const latest = depVersions.find(
|
||||||
(v) => v.game_versions.includes(profile.game_version) && v.loaders.includes(profile.loader),
|
(v) => v.game_versions.includes(profile.game_version) && v.loaders.includes(profile.loader),
|
||||||
)
|
)
|
||||||
if (latest) {
|
if (latest) {
|
||||||
await add_project_from_version(profile.path, latest.id).catch(handleError)
|
await add_project_from_version(profile.path, latest.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user