mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 21:26:40 +00:00
fix authorized apps settings, redesign, fix retro theme vars (#6900)
* fix authorized apps settings, redesign, fix retro theme vars * merge * fix: retro in app --------- Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { Combobox, defineMessages, ThemeSelector, Toggle, useVIntl } from '@modrinth/ui'
|
||||
import { ref, watch } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
|
||||
import { get, set } from '@/helpers/settings.ts'
|
||||
import { getOS } from '@/helpers/utils'
|
||||
@@ -123,6 +123,11 @@ const messages = defineMessages({
|
||||
|
||||
const os = ref(await getOS())
|
||||
const settings = ref(await get())
|
||||
const themeOptions = computed(() =>
|
||||
themeStore
|
||||
.getThemeOptions()
|
||||
.filter((theme) => theme !== 'retro' || themeStore.devMode || settings.value.theme === 'retro'),
|
||||
)
|
||||
|
||||
watch(
|
||||
settings,
|
||||
@@ -146,7 +151,7 @@ watch(
|
||||
}
|
||||
"
|
||||
:current-theme="settings.theme"
|
||||
:theme-options="themeStore.getThemeOptions()"
|
||||
:theme-options="themeOptions"
|
||||
system-theme-color="system"
|
||||
/>
|
||||
|
||||
|
||||
+1
-1
@@ -189,7 +189,7 @@ type AppSettings = {
|
||||
max_concurrent_downloads: number
|
||||
max_concurrent_writes: number
|
||||
|
||||
theme: 'dark' | 'light' | 'oled'
|
||||
theme: 'dark' | 'light' | 'oled' | 'retro' | 'system'
|
||||
default_page: 'Home' | 'Library'
|
||||
collapsed_navigation: boolean
|
||||
advanced_rendering: boolean
|
||||
|
||||
@@ -20,7 +20,7 @@ export const DEFAULT_FEATURE_FLAGS = {
|
||||
always_show_copy_details: false,
|
||||
}
|
||||
|
||||
export const THEME_OPTIONS = ['dark', 'light', 'oled', 'system'] as const
|
||||
export const THEME_OPTIONS = ['dark', 'light', 'oled', 'retro', 'system'] as const
|
||||
|
||||
export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS
|
||||
export type FeatureFlags = Record<FeatureFlag, boolean>
|
||||
|
||||
@@ -280,15 +280,19 @@ html {
|
||||
}
|
||||
|
||||
.retro-mode {
|
||||
--color-bg: #191917;
|
||||
--color-raised-bg: #1d1e1b;
|
||||
--surface-1: #191917;
|
||||
--surface-2: rgb(22, 22, 21);
|
||||
--surface-3: #232421;
|
||||
--surface-4: #3a3b38;
|
||||
--surface-5: #5a5c58;
|
||||
--color-button-bg: #3a3b38;
|
||||
--color-base: #c3c4b3;
|
||||
--color-secondary: #777a74;
|
||||
--color-secondary: #9b9e98;
|
||||
--color-contrast: #e6e2d1;
|
||||
|
||||
--color-brand: #4d9227;
|
||||
--color-brand-highlight: #25421e;
|
||||
--color-accent-contrast: #ffffff;
|
||||
--color-ad: var(--color-brand-highlight);
|
||||
--color-ad-raised: var(--color-brand);
|
||||
--color-ad-contrast: black;
|
||||
|
||||
@@ -590,6 +590,7 @@ onBeforeUnmount(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
<template><div></div></template>
|
||||
<style>
|
||||
html.modrinth-cmp-summary-hidden .qc-cmp2-container,
|
||||
html.modrinth-cmp-summary-hidden #qc-cmp2-container,
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<div class="rounded-2xl border border-solid border-surface-4 bg-surface-3">
|
||||
<div class="flex flex-col gap-2 border-0 border-b border-solid border-surface-4 p-4">
|
||||
<div class="flex flex-wrap justify-between gap-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<Avatar :src="authorization.app.icon_url" size="48px" />
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<h2 class="m-0 flex items-center gap-1 text-base font-semibold">
|
||||
{{ authorization.app.name }}
|
||||
|
||||
<BadgeCheckIcon
|
||||
v-if="isOfficial"
|
||||
v-tooltip="formatMessage(messages.officialTooltip)"
|
||||
class="size-5 text-green"
|
||||
fill="currentColor"
|
||||
fill-opacity="0.125"
|
||||
/>
|
||||
</h2>
|
||||
<PageHeaderMetadata>
|
||||
<PageHeaderMetadataItem>
|
||||
<IntlFormatted :message-id="messages.byLabel">
|
||||
<template #~user>
|
||||
<nuxt-link
|
||||
:to="'/user/' + authorization.owner.id"
|
||||
class="flex items-center gap-1 hover:underline"
|
||||
target="_blank"
|
||||
>
|
||||
<Avatar :src="authorization.owner.avatar_url" size="24px" circle />
|
||||
{{ authorization.owner.username }}
|
||||
</nuxt-link>
|
||||
</template>
|
||||
</IntlFormatted>
|
||||
</PageHeaderMetadataItem>
|
||||
<PageHeaderMetadataItem v-if="authorization.app.url">
|
||||
<a class="text-link" :to="authorization.app.url" target="_blank">
|
||||
{{ authorization.app.url }}
|
||||
</a>
|
||||
</PageHeaderMetadataItem>
|
||||
</PageHeaderMetadata>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ButtonStyled color="red">
|
||||
<button @click="emit('revoke', authorization.app_id)">
|
||||
<XCircleIcon />
|
||||
{{ formatMessage(messages.revokeAction) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showUnofficialDisclosure" class="flex items-center gap-1 text-orange">
|
||||
<IssuesIcon />
|
||||
{{ formatMessage(messages.unofficialDisclosure) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-b-2xl bg-surface-2 p-4">
|
||||
<template v-if="authorization.app.description">
|
||||
<label :for="descriptionId" class="mb-1 flex font-semibold text-contrast">
|
||||
{{ formatMessage(messages.aboutThisAppLabel) }}
|
||||
</label>
|
||||
<div :id="descriptionId" class="mb-4">{{ authorization.app.description }}</div>
|
||||
</template>
|
||||
|
||||
<label :for="scopeListId" class="mb-1 flex font-semibold text-contrast">
|
||||
{{ formatMessage(commonMessages.permissionsLabel) }}
|
||||
</label>
|
||||
<div :id="scopeListId" class="grid gap-1 sm:grid-cols-2">
|
||||
<div
|
||||
v-for="scope in scopesToDefinitions(BigInt(authorization.scopes || 0))"
|
||||
:key="scope"
|
||||
class="flex items-center gap-1"
|
||||
>
|
||||
<CheckIcon class="size-5 shrink-0 text-green" />
|
||||
{{ scope }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import { BadgeCheckIcon, CheckIcon, IssuesIcon, XCircleIcon } from '@modrinth/assets'
|
||||
import {
|
||||
Avatar,
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
defineMessages,
|
||||
IntlFormatted,
|
||||
PageHeaderMetadata,
|
||||
PageHeaderMetadataItem,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { isOfficialAccount } from '@modrinth/utils'
|
||||
|
||||
import { useScopes } from '~/composables/auth/scopes.ts'
|
||||
|
||||
export type AuthorizationCardData = Labrinth.OAuth.Internal.OAuthClientAuthorization & {
|
||||
app: Labrinth.OAuth.Internal.OAuthClient
|
||||
owner: Labrinth.Users.v2.User
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
authorization: AuthorizationCardData
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
revoke: [appId: string]
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const { scopesToDefinitions } = useScopes()
|
||||
|
||||
const descriptionId = computed(() => `app-description-${props.authorization.id}`)
|
||||
const scopeListId = computed(() => `app-scope-list-${props.authorization.id}`)
|
||||
|
||||
const unofficialTriggerWords = [
|
||||
'modrinth',
|
||||
'mod rinth',
|
||||
'rnodrinth',
|
||||
'rinth',
|
||||
'modrith',
|
||||
'official',
|
||||
'verified',
|
||||
'verification',
|
||||
]
|
||||
|
||||
const showUnofficialDisclosure = computed(() => {
|
||||
return (
|
||||
(unofficialTriggerWords.some((word) =>
|
||||
props.authorization.app.name.toLowerCase().includes(word),
|
||||
) ||
|
||||
unofficialTriggerWords.some((word) =>
|
||||
props.authorization.owner.username?.toLowerCase().includes(word),
|
||||
)) &&
|
||||
!isOfficial.value
|
||||
)
|
||||
})
|
||||
|
||||
const isOfficial = computed(() => {
|
||||
return isOfficialAccount(props.authorization.owner.id)
|
||||
})
|
||||
|
||||
const messages = defineMessages({
|
||||
revokeAction: {
|
||||
id: 'settings.authorizations.revoke.action',
|
||||
defaultMessage: 'Revoke',
|
||||
},
|
||||
byLabel: {
|
||||
id: 'settings.authorizations.created-by',
|
||||
defaultMessage: 'Created by {user}',
|
||||
},
|
||||
aboutThisAppLabel: {
|
||||
id: 'settings.authorizations.about-this-app',
|
||||
defaultMessage: 'About this app',
|
||||
},
|
||||
unofficialDisclosure: {
|
||||
id: 'settings.authorizations.unofficial-disclosure',
|
||||
defaultMessage: 'This app is not affiliated with Modrinth in any way, despite its name.',
|
||||
},
|
||||
officialTooltip: {
|
||||
id: 'settings.authorizations.official-tooltip',
|
||||
defaultMessage: 'This app is created by an official Modrinth account.',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
@@ -2831,9 +2831,6 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "O této aplikaci"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "od"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorizace"
|
||||
},
|
||||
|
||||
@@ -2999,9 +2999,6 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Omkring denne app"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "af"
|
||||
},
|
||||
"settings.billing.charges.product.midas": {
|
||||
"message": "Modrinth Plus"
|
||||
},
|
||||
|
||||
@@ -4772,15 +4772,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Über diese Anwendung"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "von"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Wenn du eine Anwendung mit deinem Modrinth-Konto autorisierst, gewährst du dieser Zugriff auf dein Konto. Du kannst den Zugriff auf dein Konto hier jederzeit verwalten und überprüfen."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Wir konnen aktuell deine autorisierten Anwendungen nicht anzeigen und arbeiten an einer lösung dafür. Bitte besuche diese Seite zu einem späteren Zeitpunkt erneut!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorisierungen"
|
||||
},
|
||||
|
||||
@@ -4772,15 +4772,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Über diese Anwendung"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "von"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Wenn du eine Anwendung mit deinem Modrinth-Konto autorisierst, gewährst du dieser Zugriff auf dein Konto. Du kannst den Zugriff auf dein Konto hier jederzeit verwalten und überprüfen."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Wir können deine autorisierten Apps derzeit nicht anzeigen, wir arbeiten daran, das zu beheben. Bitte besuche diese Seite zu einem späteren Zeitpunkt erneut!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorisierungen"
|
||||
},
|
||||
|
||||
@@ -4802,18 +4802,24 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "About this app"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "by"
|
||||
"settings.authorizations.created-by": {
|
||||
"message": "Created by {user}"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "When you authorize an application with your Modrinth account, you grant it access to your account. You can manage and review access to your account here at any time."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "We currently can't display your authorized apps, we're working to fix this. Please visit this page at a later date!"
|
||||
"settings.authorizations.empty-state.description": {
|
||||
"message": "Applications you authorize will appear here."
|
||||
},
|
||||
"settings.authorizations.empty-state.heading": {
|
||||
"message": "No authorized apps"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Authorizations"
|
||||
},
|
||||
"settings.authorizations.official-tooltip": {
|
||||
"message": "This app is created by an official Modrinth account."
|
||||
},
|
||||
"settings.authorizations.revoke.action": {
|
||||
"message": "Revoke"
|
||||
},
|
||||
@@ -4823,6 +4829,9 @@
|
||||
"settings.authorizations.revoke.confirm.title": {
|
||||
"message": "Are you sure you want to revoke this application?"
|
||||
},
|
||||
"settings.authorizations.unofficial-disclosure": {
|
||||
"message": "This app is not affiliated with Modrinth in any way, despite its name."
|
||||
},
|
||||
"settings.billing.charges.description": {
|
||||
"message": "All of your past charges to your Modrinth account will be listed here:"
|
||||
},
|
||||
|
||||
@@ -4280,15 +4280,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Acerca de esta aplicación"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "por"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Cuando autorizas una aplicación con tu cuenta de Modrinth, le concedes acceso a tu cuenta. Puedes gestionar y revisar los accesos a tu cuenta aquí en cualquier momento."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Actualmente no podemos mostrar tus aplicaciones autorizadas. Estamos trabajando para solucionar esto. ¡Por favor, visita esta página más tarde!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorizaciones"
|
||||
},
|
||||
|
||||
@@ -3953,15 +3953,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Acerca de esta aplicación"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "por"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Cuando autorizas una aplicación con tu cuenta de Modrinth, le concedes acceso a tu cuenta. Puedes gestionar y revisar el acceso a tu cuenta aquí en cualquier momento."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Por el momento no podemos mostrar tus aplicaciones autorizadas, pero estamos trabajando para solucionar el problema. ¡Vuelve a visitar esta página más adelante!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorizaciones"
|
||||
},
|
||||
|
||||
@@ -2933,12 +2933,6 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Tungkol sa app"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "ni/ng"
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Kasalukuyang hindi namin mapapakita ang mga pinahintulutang app, kinukumpuni pa namin ito. Mangyaring bisitahin ang pahinang ito sa ibang pagkataon!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Mga pagpapahintulot"
|
||||
},
|
||||
|
||||
@@ -4760,15 +4760,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "À propos de cette application"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "par"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Lorsque vous autorisez une application avec votre compte Modrinth, vous lui accordez l’accès à votre compte. Vous pouvez gérer et consulter les accès à votre compte ici à tout moment."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Nous ne pouvons pas afficher vos applications autorisées pour le moment, nous travaillons à résoudre ce problème. Veuillez revenir sur cette page ultérieurement !"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorisations"
|
||||
},
|
||||
|
||||
@@ -4223,15 +4223,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Az alkalmazásról"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "által"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Amikor engedélyezel egy alkalmazást a Modrinth fiókoddal, hozzáférést biztosítasz számára a fiókodhoz. A fiókodhoz való hozzáférést bármikor kezelheted és ellenőrizheted itt."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Jelenleg nem tudjuk megjeleníteni az azonosított alkalmazásokat, dolgozunk a probléma megoldásán. Kérlek látogasd meg ezt az oldalt később!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Engedélyek"
|
||||
},
|
||||
|
||||
@@ -4760,15 +4760,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Info sull'app"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "da"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Quando autorizzi un'applicazione, le concedi l'accesso al tuo account Modrinth. Qui puoi gestirne e controllarne l'accesso in qualsiasi momento."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Al momento non riusciamo a mostrare le tue app autorizzate, stiamo lavorando per risolvere il problema. Ritorna più tardi!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorizzazioni"
|
||||
},
|
||||
|
||||
@@ -3713,15 +3713,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "このアプリについて"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "作成者"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Modrinthアカウントでアプリケーションを承認することにより、アプリケーションがあなたのアカウントにアクセスできるようになります。 アクセス権はいつでも確認でき、変更可能です。"
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "現在承認済みアプリを表示することができません。現在修正中のため、また後ほど確認ください!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "承認"
|
||||
},
|
||||
|
||||
@@ -4724,15 +4724,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "이 앱에 대해"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "제작자"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Modrinth 계정으로 애플리케이션에 권한을 부여하면, 해당 앱이 귀하의 계정에 접근할 수 있게 됩니다. 여기에서 언제든지 계정 접근 권한을 관리하고 확인할 수 있습니다."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "현재 승인한 애플리케이션을 표시할 수 없습니다. 이 문제를 해결하기 위해 노력 중입니다. 나중에 다시 확인해 주세요!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "승인"
|
||||
},
|
||||
|
||||
@@ -3746,15 +3746,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Mengenai aplikasi ini"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "oleh"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Apabila anda membenarkan aplikasi ini dengan akaun Modrinth anda, anda memberikannya akses kepada akaun anda. Anda boleh mengurus dan menyemak akses kepada akaun anda di sini pada bila-bila masa."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Kami tidak dapat memaparkan aplikasi yang dibenarkan oleh anda pada masa ini, kami sedang berusaha untuk memperbaikinya. Sila kunjungi laman ini pada tarikh yang akan datang!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Kebenaran"
|
||||
},
|
||||
|
||||
@@ -4799,15 +4799,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Over deze app"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "door"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Wanneer je een app via je Modrinth-account autoriseert, verleen je die app toegang tot je account. Je kunt de toegang tot je account hier op elk moment beheren en bekijken."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "We kunnen je geautoriseerde apps momenteel niet weergeven, maar we werken eraan om dit te verhelpen. Kom later nog eens terug op deze pagina!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Toestemmingen"
|
||||
},
|
||||
|
||||
@@ -3632,15 +3632,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Om denne appen"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "fra"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Når du autoriserer en applikasjon med Modrinth-kontoen din, så gir du tilgang til kontoen din. Du kan handere og gå gjennom tilgang til kontoen din her når som helst."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Vi kan ikke vise de autoriserte appene dine akkurat nå, vi jobber med å fikse det. Vær så snill å besøk denne sida seinere!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autoriseringer"
|
||||
},
|
||||
|
||||
@@ -4715,15 +4715,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "O aplikacji"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "od"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Kiedy autoryzujesz aplikacje ze swoim kontem Modrinth, dajesz jej dostęp do swojego konta. Możesz tutaj zawsze zarządzać oraz przeglądać stan aplikacji z dostępem do Twojego konta."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Nie udało się nam wyświetlić twoich zautoryzowanych aplikacji, pracujemy nad tym, aby to naprawić. Odwiedź tę stronę później!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autoryzacje"
|
||||
},
|
||||
|
||||
@@ -4802,15 +4802,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Sobre este aplicativo"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "por"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Ao autorizar um aplicativo com sua conta do Modrinth, você concede acesso à sua conta. Você pode gerenciar e revisar o acesso à sua conta aqui a qualquer momento."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "No momento, não podemos exibir seus aplicativos autorizados. Estamos trabalhando para corrigir isso. Visite esta página novamente mais tarde!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorizações"
|
||||
},
|
||||
|
||||
@@ -3443,15 +3443,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Sobre esta aplicação"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "por"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Quando autorizas uma aplicação com a tua conta Modrinth, dás-lhe acesso à tua conta. Podes gerir e rever acesso à tua conta aqui quando quiseres."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Neste momento, não conseguimos mostrar as tuas aplicações autorizadas, estamos a tentar corrigir isto. Por favor tenta novamente mais tarde!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autorizações"
|
||||
},
|
||||
|
||||
@@ -4748,15 +4748,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "О приложении"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "от"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Авторизованные приложения получают доступ к аккаунту Modrinth. Здесь можно просматривать и отзывать этот доступ."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Список приложений временно недоступен. Мы работаем над исправлением — загляните сюда позже."
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Авторизации"
|
||||
},
|
||||
|
||||
@@ -1679,9 +1679,6 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "O ovoj aplikaciji"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "od"
|
||||
},
|
||||
"settings.authorizations.revoke.action": {
|
||||
"message": "Oduzmi"
|
||||
},
|
||||
|
||||
@@ -3791,9 +3791,6 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Om appen"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "av"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Autentiseringar"
|
||||
},
|
||||
|
||||
@@ -4211,15 +4211,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Bu uygulama hakkında"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "tarafından"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Modrinth hesabınızla bir uygulamayı yetkilendirdiğinizde, ona hesabınıza erişim izni vermiş olursunuz. Hesabınıza verilen erişimi dilediğiniz zaman burada yönetebilir ve gözden geçirebilirsiniz."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Yetkilendirdiğiniz uygulamalar şu anda görüntülenemiyor, bunu düzeltmek için çalışıyoruz. Lütfen bu sayfayı daha sonra tekrar ziyaret edin."
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Yetkiler"
|
||||
},
|
||||
|
||||
@@ -4724,15 +4724,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Про застосунок"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "від"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Коли ви авторизуєтеся у застосунку за допомогою Modrinth, ви надаєте йому доступ до вашого облікового запису. Ви завжди можете переглядати й керувати доступом до свого облікового запису тут."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Наразі ми не можемо показати ваші авторизовані застосунки, але ми працюємо, щоб виправити це. Будь ласка, завітайте на цю сторінку пізніше!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Авторизації"
|
||||
},
|
||||
|
||||
@@ -3911,15 +3911,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "Về ứng dụng này"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "bởi"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "Khi bạn ủy quyền cho một ứng dụng bằng tài khoản Modrinth của mình, bạn đã cấp cho ứng dụng đó quyền truy cập vào tài khoản của bạn. Bạn có thể quản lý và xem lại quyền truy cập vào tài khoản của mình tại đây bất cứ lúc nào."
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "Hiện tại chúng tôi không thể hiển thị các ứng dụng đã ủy quyền của bạn, chúng tôi đang nỗ lực khắc phục sự cố này. Vui lòng quay lại trang này sau!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "Quyền hạn"
|
||||
},
|
||||
|
||||
@@ -4802,15 +4802,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "关于此应用"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "by"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "当您使用 Modrinth 账户授权某个应用程序时,即表示您授予其访问您账户的权限。您可以随时在此处管理和审查对您账户的访问权限。"
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "我们目前无法显示您授权的应用程序,我们正在努力解决这个问题。请稍后再访问此页面!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "授权"
|
||||
},
|
||||
|
||||
@@ -4802,15 +4802,9 @@
|
||||
"settings.authorizations.about-this-app": {
|
||||
"message": "關於這個應用程式"
|
||||
},
|
||||
"settings.authorizations.by": {
|
||||
"message": "作者"
|
||||
},
|
||||
"settings.authorizations.description": {
|
||||
"message": "當你使用 Modrinth 帳號授權應用程式時,即代表你授予該應用程式存取你帳戶的權限。你可以隨時在這裡管理並審查帳號的存取權。"
|
||||
},
|
||||
"settings.authorizations.empty-state": {
|
||||
"message": "目前無法顯示你已授權的應用程式,我們正在努力修正這個問題。請稍後再回來查看!"
|
||||
},
|
||||
"settings.authorizations.head-title": {
|
||||
"message": "授權"
|
||||
},
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="normal-page no-sidebar">
|
||||
<h1>{{ formatMessage(commonMessages.settingsLabel) }}</h1>
|
||||
</div>
|
||||
<div class="normal-page">
|
||||
<div class="normal-page__sidebar">
|
||||
<NormalPage sidebar="left">
|
||||
<template #header>
|
||||
<h1 class="m-0 text-3xl font-semibold">
|
||||
{{ formatMessage(commonMessages.settingsLabel) }}
|
||||
</h1>
|
||||
</template>
|
||||
<template #sidebar>
|
||||
<NavStack
|
||||
:items="
|
||||
[
|
||||
@@ -18,7 +20,6 @@
|
||||
link: '/settings/language',
|
||||
label: formatMessage(commonSettingsMessages.language),
|
||||
icon: LanguagesIcon,
|
||||
badge: `${formatMessage(commonMessages.beta)}`,
|
||||
},
|
||||
flags.developerMode
|
||||
? {
|
||||
@@ -81,11 +82,9 @@
|
||||
].filter(Boolean)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="normal-page__content mt-3 lg:mt-0">
|
||||
</template>
|
||||
<NuxtPage :route="route" />
|
||||
</div>
|
||||
</div>
|
||||
</NormalPage>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
@@ -101,7 +100,13 @@ import {
|
||||
ToggleRightIcon,
|
||||
UserIcon,
|
||||
} from '@modrinth/assets'
|
||||
import { commonMessages, commonSettingsMessages, defineMessages, useVIntl } from '@modrinth/ui'
|
||||
import {
|
||||
commonMessages,
|
||||
commonSettingsMessages,
|
||||
defineMessages,
|
||||
NormalPage,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
|
||||
import NavStack from '~/components/ui/NavStack.vue'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="universal-card">
|
||||
<div class="flex flex-col">
|
||||
<ConfirmModal
|
||||
ref="modal_confirm"
|
||||
:title="formatMessage(messages.revokeConfirmTitle)"
|
||||
@@ -7,101 +7,70 @@
|
||||
:proceed-label="formatMessage(messages.revokeAction)"
|
||||
@proceed="revokeApp(revokingId)"
|
||||
/>
|
||||
<h2 class="text-2xl">{{ formatMessage(commonSettingsMessages.authorizedApps) }}</h2>
|
||||
<p>
|
||||
<h2 class="m-0 text-2xl font-semibold">
|
||||
{{ formatMessage(commonSettingsMessages.authorizedApps) }}
|
||||
</h2>
|
||||
<p class="mb-4 mt-2">
|
||||
{{ formatMessage(messages.description) }}
|
||||
</p>
|
||||
<div v-if="appInfoLookup.length === 0" class="universal-card recessed">
|
||||
{{ formatMessage(messages.emptyState) }}
|
||||
</div>
|
||||
<template v-if="isLoading">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div
|
||||
v-for="i in 2"
|
||||
:key="`authorization-skeleton-${i}`"
|
||||
class="overflow-hidden rounded-2xl border border-solid border-surface-4 bg-surface-3"
|
||||
>
|
||||
<div class="flex items-center gap-3 border-0 border-b border-solid border-surface-4 p-4">
|
||||
<div class="size-12 shrink-0 animate-pulse rounded-xl bg-surface-4" />
|
||||
<div class="flex flex-1 flex-col gap-2">
|
||||
<div class="h-4 w-36 animate-pulse rounded-lg bg-surface-4" />
|
||||
<div class="h-3 w-48 animate-pulse rounded-lg bg-surface-4" />
|
||||
</div>
|
||||
<div class="h-9 w-24 animate-pulse rounded-xl bg-surface-4" />
|
||||
</div>
|
||||
<div class="bg-surface-2 p-4">
|
||||
<div class="mb-3 h-3 w-28 animate-pulse rounded-lg bg-surface-3" />
|
||||
<div class="grid gap-2 sm:grid-cols-2">
|
||||
<div
|
||||
v-for="j in 4"
|
||||
:key="`authorization-skeleton-${i}-scope-${j}`"
|
||||
class="h-4 w-full animate-pulse rounded-lg bg-surface-3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<EmptyState
|
||||
v-else-if="showEmptyState"
|
||||
type="done"
|
||||
:heading="formatMessage(messages.emptyStateHeading)"
|
||||
:description="formatMessage(messages.emptyStateDescription)"
|
||||
/>
|
||||
<div v-else class="flex flex-col gap-4">
|
||||
<AuthorizationCard
|
||||
v-for="authorization in appInfoLookup"
|
||||
:key="authorization.id"
|
||||
class="universal-card recessed token mt-4"
|
||||
>
|
||||
<div class="token-content">
|
||||
<div>
|
||||
<div class="icon-name">
|
||||
<Avatar :src="authorization.app.icon_url" />
|
||||
<div>
|
||||
<h2 class="token-title">
|
||||
{{ authorization.app.name }}
|
||||
</h2>
|
||||
<div>
|
||||
{{ formatMessage(messages.byLabel) }}
|
||||
<nuxt-link class="text-link" :to="'/user/' + authorization.owner.id">{{
|
||||
authorization.owner.username
|
||||
}}</nuxt-link>
|
||||
<template v-if="authorization.app.url">
|
||||
<span> ⋅ </span>
|
||||
<nuxt-link class="text-link" :to="authorization.app.url">
|
||||
{{ authorization.app.url }}
|
||||
</nuxt-link>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<template v-if="authorization.app.description">
|
||||
<label for="app-description">
|
||||
<span class="label__title">{{ formatMessage(messages.aboutThisAppLabel) }}</span>
|
||||
</label>
|
||||
<div id="app-description">{{ authorization.app.description }}</div>
|
||||
</template>
|
||||
|
||||
<label for="app-scope-list">
|
||||
<span class="label__title">{{ formatMessage(commonMessages.scopesLabel) }}</span>
|
||||
</label>
|
||||
<div class="scope-list">
|
||||
<div
|
||||
v-for="scope in scopesToDefinitions(authorization.scopes)"
|
||||
:key="scope"
|
||||
class="scope-list-item"
|
||||
>
|
||||
<div class="scope-list-item-icon">
|
||||
<CheckIcon />
|
||||
</div>
|
||||
{{ scope }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<ButtonStyled color="red">
|
||||
<button
|
||||
@click="
|
||||
() => {
|
||||
revokingId = authorization.app_id
|
||||
$refs.modal_confirm.show()
|
||||
}
|
||||
"
|
||||
>
|
||||
<TrashIcon />
|
||||
{{ formatMessage(messages.revokeAction) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
:authorization="authorization"
|
||||
@revoke="onRevoke"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { CheckIcon, TrashIcon } from '@modrinth/assets'
|
||||
import {
|
||||
Avatar,
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
commonSettingsMessages,
|
||||
ConfirmModal,
|
||||
defineMessages,
|
||||
EmptyState,
|
||||
injectModrinthClient,
|
||||
injectNotificationManager,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
import { useScopes } from '~/composables/auth/scopes.ts'
|
||||
import AuthorizationCard from '~/components/ui/AuthorizationCard.vue'
|
||||
|
||||
const client = injectModrinthClient()
|
||||
const { addNotification } = injectNotificationManager()
|
||||
@@ -117,10 +86,13 @@ const messages = defineMessages({
|
||||
defaultMessage:
|
||||
'When you authorize an application with your Modrinth account, you grant it access to your account. You can manage and review access to your account here at any time.',
|
||||
},
|
||||
emptyState: {
|
||||
id: 'settings.authorizations.empty-state',
|
||||
defaultMessage:
|
||||
"We currently can't display your authorized apps, we're working to fix this. Please visit this page at a later date!",
|
||||
emptyStateHeading: {
|
||||
id: 'settings.authorizations.empty-state.heading',
|
||||
defaultMessage: 'No authorized apps',
|
||||
},
|
||||
emptyStateDescription: {
|
||||
id: 'settings.authorizations.empty-state.description',
|
||||
defaultMessage: 'Applications you authorize will appear here.',
|
||||
},
|
||||
revokeConfirmTitle: {
|
||||
id: 'settings.authorizations.revoke.confirm.title',
|
||||
@@ -135,19 +107,10 @@ const messages = defineMessages({
|
||||
id: 'settings.authorizations.revoke.action',
|
||||
defaultMessage: 'Revoke',
|
||||
},
|
||||
byLabel: {
|
||||
id: 'settings.authorizations.by',
|
||||
defaultMessage: 'by',
|
||||
},
|
||||
aboutThisAppLabel: {
|
||||
id: 'settings.authorizations.about-this-app',
|
||||
defaultMessage: 'About this app',
|
||||
},
|
||||
})
|
||||
|
||||
const { scopesToDefinitions } = useScopes()
|
||||
|
||||
const revokingId = ref(null)
|
||||
const modal_confirm = ref()
|
||||
|
||||
definePageMeta({
|
||||
middleware: 'auth',
|
||||
@@ -176,20 +139,58 @@ const { data: appCreatorsInformation } = useQuery({
|
||||
})
|
||||
|
||||
const appInfoLookup = computed(() => {
|
||||
if (!usersApps.value || !appInformation.value || !appCreatorsInformation.value) {
|
||||
if (!usersApps.value || !appInformation.value) {
|
||||
return []
|
||||
}
|
||||
return usersApps.value.map((app) => {
|
||||
if (appInformation.value.length === 0) {
|
||||
return []
|
||||
}
|
||||
if (!appCreatorsInformation.value) {
|
||||
return []
|
||||
}
|
||||
|
||||
return usersApps.value
|
||||
.map((app) => {
|
||||
const info = appInformation.value.find((c) => c.id === app.app_id)
|
||||
const owner = appCreatorsInformation.value.find((c) => c.id === info?.created_by)
|
||||
if (!info || !owner) {
|
||||
return null
|
||||
}
|
||||
return {
|
||||
...app,
|
||||
app: info || null,
|
||||
owner: owner || null,
|
||||
app: info,
|
||||
owner,
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
})
|
||||
|
||||
const showEmptyState = computed(() => {
|
||||
if (!usersApps.value) {
|
||||
return false
|
||||
}
|
||||
if (usersApps.value.length === 0) {
|
||||
return true
|
||||
}
|
||||
if (!appInformation.value) {
|
||||
return false
|
||||
}
|
||||
if (appInformation.value.length === 0) {
|
||||
return true
|
||||
}
|
||||
if (!appCreatorsInformation.value) {
|
||||
return false
|
||||
}
|
||||
return appInfoLookup.value.length === 0
|
||||
})
|
||||
|
||||
const isLoading = computed(() => !showEmptyState.value && appInfoLookup.value.length === 0)
|
||||
|
||||
function onRevoke(appId) {
|
||||
revokingId.value = appId
|
||||
modal_confirm.value.show()
|
||||
}
|
||||
|
||||
async function revokeApp(id) {
|
||||
try {
|
||||
await client.labrinth.oauth_internal.revokeAuthorization(id)
|
||||
@@ -204,73 +205,3 @@ async function revokeApp(id) {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.input-group {
|
||||
// Overrides for omorphia compat
|
||||
> * {
|
||||
padding: var(--gap-sm) var(--gap-lg) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.scope-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
|
||||
gap: var(--gap-sm);
|
||||
|
||||
.scope-list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
background-color: var(--color-gray-200);
|
||||
color: var(--color-gray-700);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.25rem;
|
||||
|
||||
// avoid breaking text or overflowing
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scope-list-item-icon {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
flex: 0 0 auto;
|
||||
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--color-green);
|
||||
color: var(--color-raised-bg);
|
||||
}
|
||||
}
|
||||
|
||||
.icon-name {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--gap-lg);
|
||||
padding-bottom: var(--gap-sm);
|
||||
}
|
||||
|
||||
.token-content {
|
||||
width: 100%;
|
||||
|
||||
.token-title {
|
||||
margin-bottom: var(--spacing-card-xs);
|
||||
}
|
||||
}
|
||||
|
||||
.token {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
|
||||
@media screen and (min-width: 800px) {
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -45,14 +45,15 @@ export class LabrinthOAuthInternalModule extends AbstractModule {
|
||||
* @returns Promise resolving to an array of OAuth clients
|
||||
*/
|
||||
public async getApps(ids: string[]): Promise<Labrinth.OAuth.Internal.OAuthClient[]> {
|
||||
return this.client.request<Labrinth.OAuth.Internal.OAuthClient[]>(
|
||||
`/oauth/apps?ids=${encodeURIComponent(JSON.stringify(ids))}`,
|
||||
{
|
||||
api: 'labrinth',
|
||||
version: 'internal',
|
||||
method: 'GET',
|
||||
},
|
||||
)
|
||||
if (ids.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
// bulk `/oauth/apps` is broken on backend, fetch by id instead
|
||||
// TODO: Remove this once the backend is fixed
|
||||
const results = await Promise.all(ids.map((id) => this.getApp(id).catch(() => null)))
|
||||
|
||||
return results.filter((app): app is Labrinth.OAuth.Internal.OAuthClient => app !== null)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -329,6 +329,7 @@ pub enum Theme {
|
||||
Dark,
|
||||
Light,
|
||||
Oled,
|
||||
Retro,
|
||||
System,
|
||||
}
|
||||
|
||||
@@ -338,6 +339,7 @@ impl Theme {
|
||||
Theme::Dark => "dark",
|
||||
Theme::Light => "light",
|
||||
Theme::Oled => "oled",
|
||||
Theme::Retro => "retro",
|
||||
Theme::System => "system",
|
||||
}
|
||||
}
|
||||
@@ -347,6 +349,7 @@ impl Theme {
|
||||
"dark" => Theme::Dark,
|
||||
"light" => Theme::Light,
|
||||
"oled" => Theme::Oled,
|
||||
"retro" => Theme::Retro,
|
||||
"system" => Theme::System,
|
||||
_ => Theme::Dark,
|
||||
}
|
||||
|
||||
@@ -422,6 +422,39 @@ html {
|
||||
}
|
||||
|
||||
.retro-mode {
|
||||
@extend .dark-mode;
|
||||
--surface-1: #191917;
|
||||
--surface-2: rgb(22, 22, 21);
|
||||
--surface-2-5: #3a3c3e;
|
||||
--surface-3: #232421;
|
||||
--surface-4: #3a3b38;
|
||||
--surface-5: #5a5c58;
|
||||
--color-button-bg: #3a3b38;
|
||||
--color-base: #c3c4b3;
|
||||
--color-secondary: #9b9e98;
|
||||
--color-contrast: #e6e2d1;
|
||||
|
||||
--color-brand: #4d9227;
|
||||
--color-brand-highlight: #25421e;
|
||||
--color-accent-contrast: #ffffff;
|
||||
--color-ad: var(--color-brand-highlight);
|
||||
--color-ad-raised: var(--color-brand);
|
||||
--color-ad-contrast: black;
|
||||
--color-ad-highlight: var(--color-brand);
|
||||
|
||||
--color-red: rgb(232, 32, 13);
|
||||
--color-orange: rgb(232, 141, 13);
|
||||
--color-green: rgb(60, 219, 54);
|
||||
--color-blue: rgb(9, 159, 239);
|
||||
--color-purple: rgb(139, 129, 230);
|
||||
--color-gray: #718096;
|
||||
|
||||
--color-red-highlight: rgba(232, 32, 13, 0.25);
|
||||
--color-orange-highlight: rgba(232, 141, 13, 0.25);
|
||||
--color-green-highlight: rgba(60, 219, 54, 0.25);
|
||||
--color-blue-highlight: rgba(9, 159, 239, 0.25);
|
||||
--color-purple-highlight: rgba(139, 129, 230, 0.25);
|
||||
--color-gray-highlight: rgba(113, 128, 150, 0.25);
|
||||
|
||||
--brand-gradient-strong-bg: #3a3b38;
|
||||
}
|
||||
|
||||
@@ -402,7 +402,11 @@ import {
|
||||
SpinnerIcon,
|
||||
XIcon,
|
||||
} from '@modrinth/assets'
|
||||
import { UserBadge } from '@modrinth/utils'
|
||||
import {
|
||||
isModrinthUser as checkIsModrinthUser,
|
||||
isOfficialAccount as checkIsOfficialAccount,
|
||||
UserBadge,
|
||||
} from '@modrinth/utils'
|
||||
import { useQuery, useQueryClient } from '@tanstack/vue-query'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
@@ -716,8 +720,8 @@ const earliestProjectByType = computed(() => {
|
||||
return earliest
|
||||
})
|
||||
|
||||
const isModrinthUser = computed(() => user.value?.id === '2REoufqX')
|
||||
const isOfficialAccount = computed(() => isModrinthUser.value || user.value?.id === 'GVFjtWTf')
|
||||
const isModrinthUser = computed(() => checkIsModrinthUser(user.value?.id))
|
||||
const isOfficialAccount = computed(() => checkIsOfficialAccount(user.value?.id))
|
||||
const isSelf = computed(() => auth.user.value?.id === user.value?.id)
|
||||
const isAdminViewing = computed(() => auth.user.value?.role === 'admin')
|
||||
const isStaffViewing = computed(
|
||||
|
||||
@@ -2318,6 +2318,9 @@
|
||||
"label.password": {
|
||||
"defaultMessage": "Password"
|
||||
},
|
||||
"label.permissions": {
|
||||
"defaultMessage": "Permissions"
|
||||
},
|
||||
"label.plan-custom": {
|
||||
"defaultMessage": "Custom"
|
||||
},
|
||||
|
||||
@@ -287,6 +287,10 @@ export const commonMessages = defineMessages({
|
||||
id: 'label.scopes',
|
||||
defaultMessage: 'Scopes',
|
||||
},
|
||||
permissionsLabel: {
|
||||
id: 'label.permissions',
|
||||
defaultMessage: 'Permissions',
|
||||
},
|
||||
searchLabel: {
|
||||
id: 'label.search',
|
||||
defaultMessage: 'Search',
|
||||
|
||||
@@ -13,3 +13,17 @@ export const isAdmin = (user) => {
|
||||
}
|
||||
|
||||
export const STAFF_ROLES = ['moderator', 'admin']
|
||||
|
||||
export const MODRINTH_USER_ID = '2REoufqX'
|
||||
export const AUTOMOD_USER_ID = ''
|
||||
export const MODRINTH_ARCHIVES_USER_ID = 'GVFjtWTf'
|
||||
|
||||
export const OFFICIAL_ACCOUNT_IDS = [MODRINTH_USER_ID, AUTOMOD_USER_ID, MODRINTH_ARCHIVES_USER_ID]
|
||||
|
||||
export const isModrinthUser = (userId) => {
|
||||
return userId === MODRINTH_USER_ID
|
||||
}
|
||||
|
||||
export const isOfficialAccount = (userId) => {
|
||||
return OFFICIAL_ACCOUNT_IDS.includes(userId)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user