From 011ea19a774cf5d1d6dba4649bafd5ae16930b82 Mon Sep 17 00:00:00 2001
From: Prospector <6166773+Prospector@users.noreply.github.com>
Date: Mon, 27 Jul 2026 11:08:41 -0700
Subject: [PATCH 1/3] fix authorized apps settings, redesign, fix retro theme
vars
---
apps/frontend/src/assets/styles/global.scss | 10 +-
.../components/ui/AdsConsentNotification.vue | 1 +
.../src/components/ui/AuthorizationCard.vue | 165 +++++++++++
apps/frontend/src/locales/cs-CZ/index.json | 3 -
apps/frontend/src/locales/da-DK/index.json | 3 -
apps/frontend/src/locales/de-CH/index.json | 6 -
apps/frontend/src/locales/de-DE/index.json | 6 -
apps/frontend/src/locales/en-US/index.json | 17 +-
apps/frontend/src/locales/es-419/index.json | 6 -
apps/frontend/src/locales/es-ES/index.json | 6 -
apps/frontend/src/locales/fil-PH/index.json | 6 -
apps/frontend/src/locales/fr-FR/index.json | 6 -
apps/frontend/src/locales/hu-HU/index.json | 6 -
apps/frontend/src/locales/it-IT/index.json | 6 -
apps/frontend/src/locales/ja-JP/index.json | 6 -
apps/frontend/src/locales/ko-KR/index.json | 6 -
apps/frontend/src/locales/ms-MY/index.json | 6 -
apps/frontend/src/locales/nl-NL/index.json | 6 -
apps/frontend/src/locales/no-NO/index.json | 6 -
apps/frontend/src/locales/pl-PL/index.json | 6 -
apps/frontend/src/locales/pt-BR/index.json | 6 -
apps/frontend/src/locales/pt-PT/index.json | 6 -
apps/frontend/src/locales/ru-RU/index.json | 6 -
apps/frontend/src/locales/sr-CS/index.json | 3 -
apps/frontend/src/locales/sv-SE/index.json | 3 -
apps/frontend/src/locales/tr-TR/index.json | 6 -
apps/frontend/src/locales/uk-UA/index.json | 6 -
apps/frontend/src/locales/vi-VN/index.json | 6 -
apps/frontend/src/locales/zh-CN/index.json | 6 -
apps/frontend/src/locales/zh-TW/index.json | 6 -
apps/frontend/src/pages/settings.vue | 29 +-
.../src/pages/settings/authorizations.vue | 265 +++++++-----------
apps/frontend/src/pages/user/[user].vue | 15 +-
.../src/modules/labrinth/oauth/internal.ts | 17 +-
packages/assets/styles/variables.scss | 1 +
packages/ui/src/locales/en-US/index.json | 3 +
packages/ui/src/utils/common-messages.ts | 4 +
packages/utils/users.ts | 14 +
38 files changed, 341 insertions(+), 344 deletions(-)
create mode 100644 apps/frontend/src/components/ui/AuthorizationCard.vue
diff --git a/apps/frontend/src/assets/styles/global.scss b/apps/frontend/src/assets/styles/global.scss
index 56214eba8c..8ad63c2da1 100644
--- a/apps/frontend/src/assets/styles/global.scss
+++ b/apps/frontend/src/assets/styles/global.scss
@@ -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;
diff --git a/apps/frontend/src/components/ui/AdsConsentNotification.vue b/apps/frontend/src/components/ui/AdsConsentNotification.vue
index 4734b96260..e3fff38da6 100644
--- a/apps/frontend/src/components/ui/AdsConsentNotification.vue
+++ b/apps/frontend/src/components/ui/AdsConsentNotification.vue
@@ -590,6 +590,7 @@ onBeforeUnmount(() => {
})
+
diff --git a/apps/frontend/src/pages/user/[user].vue b/apps/frontend/src/pages/user/[user].vue
index 4ebf1e763d..e96009ba35 100644
--- a/apps/frontend/src/pages/user/[user].vue
+++ b/apps/frontend/src/pages/user/[user].vue
@@ -382,7 +382,13 @@ import {
UserBadges,
useVIntl,
} from '@modrinth/ui'
-import { isAdmin, isStaff, UserBadge } from '@modrinth/utils'
+import {
+ isAdmin,
+ isModrinthUser as checkIsModrinthUser,
+ isOfficialAccount as checkIsOfficialAccount,
+ isStaff,
+ UserBadge,
+} from '@modrinth/utils'
import { useQuery, useQueryClient } from '@tanstack/vue-query'
import { onServerPrefetch } from 'vue'
@@ -582,11 +588,8 @@ const sortedOrgs = computed(() =>
organizations.value ? [...organizations.value].sort((a, b) => a.name.localeCompare(b.name)) : [],
)
-const isModrinthUser = computed(() => user.value?.id === '2REoufqX')
-const isAutoMod = computed(() => user.value?.id === '')
-const isOfficialAccount = computed(
- () => isModrinthUser.value || isAutoMod.value || user.value?.id === 'GVFjtWTf',
-)
+const isModrinthUser = computed(() => checkIsModrinthUser(user.value?.id))
+const isOfficialAccount = computed(() => checkIsOfficialAccount(user.value?.id))
const sortedCollections = computed(() => {
const list = collections.value
diff --git a/packages/api-client/src/modules/labrinth/oauth/internal.ts b/packages/api-client/src/modules/labrinth/oauth/internal.ts
index 0b44186320..680009e05e 100644
--- a/packages/api-client/src/modules/labrinth/oauth/internal.ts
+++ b/packages/api-client/src/modules/labrinth/oauth/internal.ts
@@ -45,14 +45,15 @@ export class LabrinthOAuthInternalModule extends AbstractModule {
* @returns Promise resolving to an array of OAuth clients
*/
public async getApps(ids: string[]): Promise {
- return this.client.request(
- `/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)
}
/**
diff --git a/packages/assets/styles/variables.scss b/packages/assets/styles/variables.scss
index fdcb7bbabd..37b0b7935a 100644
--- a/packages/assets/styles/variables.scss
+++ b/packages/assets/styles/variables.scss
@@ -422,6 +422,7 @@ html {
}
.retro-mode {
+ @extend .dark-mode;
--surface-2-5: #3a3c3e;
--brand-gradient-strong-bg: #3a3b38;
}
diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json
index e4534c0512..8cbd5f694f 100644
--- a/packages/ui/src/locales/en-US/index.json
+++ b/packages/ui/src/locales/en-US/index.json
@@ -2318,6 +2318,9 @@
"label.password": {
"defaultMessage": "Password"
},
+ "label.permissions": {
+ "defaultMessage": "Permissions"
+ },
"label.plan-custom": {
"defaultMessage": "Custom"
},
diff --git a/packages/ui/src/utils/common-messages.ts b/packages/ui/src/utils/common-messages.ts
index f9d65d0747..26eefd90ad 100644
--- a/packages/ui/src/utils/common-messages.ts
+++ b/packages/ui/src/utils/common-messages.ts
@@ -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',
diff --git a/packages/utils/users.ts b/packages/utils/users.ts
index f13f438d81..192955dd9d 100644
--- a/packages/utils/users.ts
+++ b/packages/utils/users.ts
@@ -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)
+}
From d026afbe43cae68dc7940634e4ef1a780197527c Mon Sep 17 00:00:00 2001
From: Prospector <6166773+Prospector@users.noreply.github.com>
Date: Mon, 27 Jul 2026 13:20:44 -0700
Subject: [PATCH 2/3] merge
---
packages/ui/src/layouts/shared/user-profile/layout.vue | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/packages/ui/src/layouts/shared/user-profile/layout.vue b/packages/ui/src/layouts/shared/user-profile/layout.vue
index 28dcdf0f8d..6ba0cdf85d 100644
--- a/packages/ui/src/layouts/shared/user-profile/layout.vue
+++ b/packages/ui/src/layouts/shared/user-profile/layout.vue
@@ -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(
From ae67af0314f6d794bf45abbbe5c5538dc960267c Mon Sep 17 00:00:00 2001
From: "Calum H. (IMB11)"
Date: Tue, 28 Jul 2026 13:09:08 +0100
Subject: [PATCH 3/3] fix: retro in app
---
.../ui/settings/AppearanceSettings.vue | 9 ++++--
apps/app-frontend/src/helpers/types.d.ts | 2 +-
apps/app-frontend/src/store/theme.ts | 2 +-
packages/app-lib/src/state/settings.rs | 3 ++
packages/assets/styles/variables.scss | 32 +++++++++++++++++++
5 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue b/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
index b986d25bc9..8100571a9a 100644
--- a/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
+++ b/apps/app-frontend/src/components/ui/settings/AppearanceSettings.vue
@@ -1,6 +1,6 @@