Skip to content

Commit

Permalink
Theseus Skin Manager (#1277)
Browse files Browse the repository at this point in the history
Initial skin manager
  • Loading branch information
Jakobabs authored Jan 16, 2025
1 parent 0409fce commit fc260b7
Show file tree
Hide file tree
Showing 60 changed files with 2,902 additions and 551 deletions.
19 changes: 10 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion apps/app-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"floating-vue": "^5.2.2",
"ofetch": "^1.3.4",
"pinia": "^2.1.7",
"skinview3d": "^3.0.1",
"posthog-js": "^1.158.2",
"vite-svg-loader": "^5.1.0",
"vue": "^3.5.13",
Expand Down Expand Up @@ -54,4 +55,4 @@
},
"packageManager": "[email protected]",
"web-types": "../../web-types.json"
}
}
119 changes: 88 additions & 31 deletions apps/app-frontend/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
<script setup>
import { computed, ref, onMounted, watch, onUnmounted } from 'vue'
import { RouterView, useRouter, useRoute } from 'vue-router'
<script async setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { RouterView, useRoute, useRouter } from 'vue-router'
import {
ArrowBigUpDashIcon,
LogInIcon,
CompassIcon,
DownloadIcon,
HomeIcon,
LeftArrowIcon,
LibraryIcon,
PlusIcon,
SettingsIcon,
XIcon,
DownloadIcon,
CompassIcon,
MinimizeIcon,
LogInIcon,
LogOutIcon,
MaximizeIcon,
MinimizeIcon,
PlusIcon,
RestoreIcon,
LogOutIcon,
RightArrowIcon,
LeftArrowIcon,
SettingsIcon,
XIcon,
SpinnerIcon,
} from '@modrinth/assets'
import { Avatar, Button, ButtonStyled, Notifications, OverflowMenu } from '@modrinth/ui'
import {
Avatar,
Button,
ButtonStyled,
commonMessages,
Notifications,
OverflowMenu
} from '@modrinth/ui'
import { useLoading, useTheming } from '@/store/state'
import ModrinthAppLogo from '@/assets/modrinth_app.svg?component'
import AccountsCard from '@/components/ui/AccountsCard.vue'
Expand All @@ -32,14 +40,16 @@ import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue'
import { handleError, useNotifications } from '@/store/notifications.js'
import { command_listener, warning_listener } from '@/helpers/events.js'
import { type } from '@tauri-apps/plugin-os'
import { isDev, getOS, restartApp } from '@/helpers/utils.js'
import { initAnalytics, debugAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics'
import { getOS, isDev, restartApp } from '@/helpers/utils.js'
import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { getVersion } from '@tauri-apps/api/app'
import URLConfirmModal from '@/components/ui/URLConfirmModal.vue'
import { install_from_file } from './helpers/pack'
import { create_profile_and_install_from_file } from './helpers/pack'
import { useError } from '@/store/error.js'
import { useCheckDisableMouseover } from '@/composables/macCssFix.js'
import { save_filters } from '@/helpers/skin_manager.js'
import { SkinManagerIcon } from '@/assets/icons/index.js'
import ModInstallModal from '@/components/ui/install_flow/ModInstallModal.vue'
import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue'
import InstallConfirmModal from '@/components/ui/install_flow/InstallConfirmModal.vue'
Expand All @@ -51,7 +61,7 @@ import { renderString } from '@modrinth/utils'
import { useFetch } from '@/helpers/fetch.js'
import { check } from '@tauri-apps/plugin-updater'
import NavButton from '@/components/ui/NavButton.vue'
import { get as getCreds, logout, login } from '@/helpers/mr_auth.js'
import { get as getCreds, login, logout } from '@/helpers/mr_auth.js'
import { get_user } from '@/helpers/cache.js'
import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue'
import dayjs from 'dayjs'
Expand All @@ -60,6 +70,9 @@ 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 { defineMessages, useVIntl } from '@vintl/vintl'
const { formatMessage } = useVIntl()
const themeStore = useTheming()
Expand Down Expand Up @@ -199,6 +212,7 @@ initialize_state()
})
const handleClose = async () => {
await save_filters()
await saveWindowState(StateFlags.ALL)
await getCurrentWindow().close()
}
Expand Down Expand Up @@ -296,7 +310,7 @@ async function handleCommand(e) {
if (e.event === 'RunMRPack') {
// RunMRPack should directly install a local mrpack given a path
if (e.path.endsWith('.mrpack')) {
await install_from_file(e.path).catch(handleError)
await create_profile_and_install_from_file(e.path).catch(handleError)
trackEvent('InstanceCreate', {
source: 'CreationModalFileDrop',
})
Expand Down Expand Up @@ -354,6 +368,45 @@ function handleAuxClick(e) {
e.target.dispatchEvent(event)
}
}
const messages = defineMessages({
playingAs: {
id: 'app.sidebar.accounts.title',
defaultMessage: 'Playing as',
},
loadingAccounts: {
id: 'app.sidebar.accounts.loading-accounts',
defaultMessage: 'Loading accounts...',
},
news: {
id: 'app.sidebar.news.title',
defaultMessage: 'News',
},
home: {
id: 'app.nav.home.title',
defaultMessage: 'Home',
},
discoverContent: {
id: 'app.nav.discover-content.title',
defaultMessage: 'Discover content',
},
library: {
id: 'app.nav.library.title',
defaultMessage: 'Library',
},
settings: {
id: 'app.nav.settings.title',
defaultMessage: 'Settings',
},
createInstance: {
id: 'app.nav.create-instance.title',
defaultMessage: 'Create new instance',
},
installUpdate: {
id: 'app.nav.install-update.title',
defaultMessage: 'Install update',
},
})
</script>

<template>
Expand All @@ -369,19 +422,19 @@ function handleAuxClick(e) {
<div
class="app-grid-navbar bg-bg-raised flex flex-col p-[0.5rem] pt-0 gap-[0.5rem] w-[--left-bar-width]"
>
<NavButton v-tooltip.right="'Home'" to="/">
<NavButton v-tooltip.right="formatMessage(messages.home)" to="/">
<HomeIcon />
</NavButton>
<NavButton
v-tooltip.right="'Discover content'"
v-tooltip.right="formatMessage(messages.discoverContent)"
to="/browse/modpack"
:is-primary="() => route.path.startsWith('/browse') && !route.query.i"
:is-subpage="(route) => route.path.startsWith('/project') && !route.query.i"
>
<CompassIcon />
</NavButton>
<NavButton
v-tooltip.right="'Library'"
v-tooltip.right="formatMessage(messages.library)"
to="/library"
:is-subpage="
() =>
Expand All @@ -397,17 +450,17 @@ function handleAuxClick(e) {
<QuickInstanceSwitcher />
</suspense>
<NavButton
v-tooltip.right="'Create new instance'"
v-tooltip.right="formatMessage(messages.createInstance)"
:to="() => $refs.installationModal.show()"
:disabled="offline"
>
<PlusIcon />
</NavButton>
<div class="flex flex-grow"></div>
<NavButton v-if="updateAvailable" v-tooltip.right="'Install update'" :to="() => restartApp()">
<NavButton v-if="updateAvailable" v-tooltip.right="formatMessage(messages.installUpdate)" :to="() => restartApp()">
<DownloadIcon />
</NavButton>
<NavButton v-tooltip.right="'Settings'" :to="() => $refs.settingsModal.show()">
<NavButton v-tooltip.right="formatMessage(messages.settings)" :to="() => $refs.settingsModal.show()">
<SettingsIcon />
</NavButton>
<ButtonStyled v-if="credentials" type="transparent" circular>
Expand All @@ -427,12 +480,11 @@ function handleAuxClick(e) {
size="32px"
circle
/>
<template #sign-out> <LogOutIcon /> Sign out </template>
<template #sign-out> <LogOutIcon /> {{ formatMessage(commonMessages.signOutButton) }} </template>
</OverflowMenu>
</ButtonStyled>
<NavButton v-else v-tooltip.right="'Sign in'" :to="() => signIn()">
<NavButton v-else v-tooltip.right="formatMessage(commonMessages.signInButton)" :to="() => signIn()">
<LogInIcon />
<template #label>Sign in</template>
</NavButton>
</div>
<div data-tauri-drag-region class="app-grid-statusbar bg-bg-raised h-[--top-bar-height] flex">
Expand Down Expand Up @@ -540,10 +592,15 @@ function handleAuxClick(e) {
<div id="sidebar-teleport-target" class="sidebar-teleport-content"></div>
<div class="sidebar-default-content" :class="{ 'sidebar-enabled': sidebarVisible }">
<div class="p-4 border-0 border-b-[1px] border-[--brand-gradient-border] border-solid">
<h3 class="text-lg m-0">Playing as</h3>
<suspense>
<AccountsCard ref="accounts" mode="small" />
</suspense>
<h3 class="text-lg m-0">{{ formatMessage(messages.playingAs) }}</h3>
<Suspense>
<AccountsCard ref="accounts" />
<template #fallback>
<div class="flex items-center gap-2 pt-4 pb-1">
<SpinnerIcon class="animate-spin" /> {{ formatMessage(messages.loadingAccounts) }}
</div>
</template>
</Suspense>
</div>
<div class="p-4 border-0 border-b-[1px] border-[--brand-gradient-border] border-solid">
<suspense>
Expand Down
1 change: 1 addition & 0 deletions apps/app-frontend/src/assets/icons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export { default as AddProjectImage } from './add-project.svg'
export { default as NewInstanceImage } from './new-instance.svg'
export { default as MenuIcon } from './menu.svg'
export { default as ChatIcon } from './messages-square.svg'
export { default as SkinManagerIcon } from './skin-editor.svg'
5 changes: 5 additions & 0 deletions apps/app-frontend/src/assets/icons/skin-editor.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit fc260b7

Please sign in to comment.