Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 43 additions & 24 deletions apps/app-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,20 @@ async function setupApp() {
show_worlds_tab_in_instances,
show_screenshots_tab_in_instances,
show_skin_selector_in_sidebar,
refocus_on_game_close,
compact_instance_cards,
show_play_time,
warn_on_unknown_modpacks,
skip_non_essential_warnings,
show_jump_in,
always_show_copy_details,
hide_installed_modpacks,
advanced_filters_collapsed,
dismissed_photosensitivity_filter_warning,
friends_active_collapsed,
friends_online_collapsed,
friends_offline_collapsed,
friends_pending_collapsed,
developer_mode,
feature_flags,
pending_update_toast_for_version,
Expand Down Expand Up @@ -819,6 +833,20 @@ async function setupApp() {
appSettings.showWorldsTabInInstances = show_worlds_tab_in_instances
appSettings.showScreenshotsTabInInstances = show_screenshots_tab_in_instances
appSettings.showSkinSelectorInSidebar = show_skin_selector_in_sidebar
appSettings.refocusOnGameClose = refocus_on_game_close
appSettings.compactInstanceCards = compact_instance_cards
appSettings.showPlayTime = show_play_time
appSettings.warnOnUnknownModpacks = warn_on_unknown_modpacks
appSettings.skipNonEssentialWarnings = skip_non_essential_warnings
appSettings.showJumpIn = show_jump_in
appSettings.alwaysShowCopyDetails = always_show_copy_details
appSettings.hideInstalledModpacks = hide_installed_modpacks
appSettings.advancedFiltersCollapsed = advanced_filters_collapsed
appSettings.dismissedPhotosensitivityFilterWarning = dismissed_photosensitivity_filter_warning
appSettings.friendsActiveCollapsed = friends_active_collapsed
appSettings.friendsOnlineCollapsed = friends_online_collapsed
appSettings.friendsOfflineCollapsed = friends_offline_collapsed
appSettings.friendsPendingCollapsed = friends_pending_collapsed
appSettings.devMode = developer_mode
stateInitialized.value = true
debugStartup('App state initialized')
Expand Down Expand Up @@ -1241,16 +1269,24 @@ watch(
}

if (behavior && appSettings.syncBehaviorAcrossDevices) {
const behaviorFeatureFlags = {
compact_instance_cards: behavior.compact_instance_cards,
show_instance_play_time: behavior.show_play_time,
skip_unknown_pack_warning: !behavior.warn_on_unknown_modpacks,
skip_non_essential_warnings: behavior.skip_non_essential_warnings,
const behaviorSettings = {
refocus_on_game_close: 'refocusOnGameClose',
compact_instance_cards: 'compactInstanceCards',
show_play_time: 'showPlayTime',
warn_on_unknown_modpacks: 'warnOnUnknownModpacks',
skip_non_essential_warnings: 'skipNonEssentialWarnings',
}
for (const [key, stateKey] of Object.entries(behaviorSettings)) {
const value = behavior[key] ?? settings[key]
appSettings[stateKey] = value
if (settings[key] !== value) {
settings[key] = value
settingsChanged = true
}
}

appSettings.toggleSidebar = behavior.hide_right_sidebar
appSettings.hideNametagSkinsPage = behavior.hide_nametag
Object.assign(appSettings.featureFlags, behaviorFeatureFlags)

if (settings.hide_on_process_start !== behavior.minimize_app) {
settings.hide_on_process_start = behavior.minimize_app
Expand All @@ -1264,20 +1300,11 @@ watch(
settings.hide_nametag_skins_page = behavior.hide_nametag
settingsChanged = true
}

for (const [flag, value] of Object.entries(behaviorFeatureFlags)) {
if (settings.feature_flags[flag] !== value) {
settings.feature_flags[flag] = value
settingsChanged = true
}
}
}

if (behavior && appSettings.syncFeaturesAcrossDevices) {
const featureFlags = {
worlds_in_home: behavior.show_jump_in,
}
const featureSettings = {
show_jump_in: 'showJumpIn',
show_files_tab_in_instances: 'showFilesTabInInstances',
show_worlds_tab_in_instances: 'showWorldsTabInInstances',
show_screenshots_tab_in_instances: 'showScreenshotsTabInInstances',
Expand All @@ -1291,7 +1318,6 @@ watch(
settingsChanged = true
}
}
Object.assign(appSettings.featureFlags, featureFlags)
if (typeof behavior.quick_instance_count === 'number') {
quickInstances.setLimit(behavior.quick_instance_count)
}
Expand All @@ -1310,13 +1336,6 @@ watch(
await queryClient.invalidateQueries({ queryKey: screenshotKeys.all })
}
}

for (const [flag, value] of Object.entries(featureFlags)) {
if (settings.feature_flags[flag] !== value) {
settings.feature_flags[flag] = value
settingsChanged = true
}
}
}

if (settingsChanged) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export function useDownloadManager() {
canCopyDetails:
job.status === 'failed' ||
job.status === 'interrupted' ||
appSettings.getFeatureFlag('always_show_copy_details'),
appSettings.alwaysShowCopyDetails,
copied: copiedJobs.value.has(job.job_id),
busy: busyJobs.value.has(job.job_id),
}
Expand Down
19 changes: 13 additions & 6 deletions apps/app-frontend/src/components/ui/friends/FriendsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,28 @@ const props = defineProps<{
signIn: () => void
}>()

type FriendsSectionCollapsedFlag =
type FriendsSectionCollapsedSetting =
| 'friends_active_collapsed'
| 'friends_online_collapsed'
| 'friends_offline_collapsed'
| 'friends_pending_collapsed'

function isFriendsSectionCollapsed(flag: FriendsSectionCollapsedFlag) {
return appSettings.getFeatureFlag(flag)
const friendsSectionSettings = {
friends_active_collapsed: 'friendsActiveCollapsed',
friends_online_collapsed: 'friendsOnlineCollapsed',
friends_offline_collapsed: 'friendsOfflineCollapsed',
friends_pending_collapsed: 'friendsPendingCollapsed',
} as const

function isFriendsSectionCollapsed(setting: FriendsSectionCollapsedSetting) {
return appSettings[friendsSectionSettings[setting]]
}

function setFriendsSectionCollapsed(flag: FriendsSectionCollapsedFlag, collapsed: boolean) {
appSettings.featureFlags[flag] = collapsed
function setFriendsSectionCollapsed(setting: FriendsSectionCollapsedSetting, collapsed: boolean) {
appSettings[friendsSectionSettings[setting]] = collapsed
getSettings()
.then((settings) => {
settings.feature_flags[flag] = collapsed
settings[setting] = collapsed
return setSettings(settings)
})
.catch(handleError)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@
import { UnknownFileWarningModal } from '@modrinth/ui'
import { ref, useTemplateRef } from 'vue'

import { type FeatureFlag, useAppSettings } from '@/composables/use-app-settings.ts'
import { useAppSettings } from '@/composables/use-app-settings.ts'
import { get as getSettings, set as setSettings } from '@/helpers/settings'

const appSettings = useAppSettings()
const skipUnknownPackWarningFeatureFlag = 'skip_unknown_pack_warning' as FeatureFlag

const modal = useTemplateRef('modal')
const onProceed = ref<() => Promise<void>>()
Expand All @@ -33,7 +32,7 @@ function show(
fileName.value = selectedFileName
externalFilesInModpack.value = selectedExternalFiles

if (appSettings.getFeatureFlag(skipUnknownPackWarningFeatureFlag)) {
if (!appSettings.warnOnUnknownModpacks) {
void createInstance()
return
}
Expand All @@ -49,9 +48,9 @@ function reset() {

async function proceed(dontShowAgain: boolean) {
if (dontShowAgain) {
appSettings.featureFlags[skipUnknownPackWarningFeatureFlag] = true
appSettings.warnOnUnknownModpacks = false
const settings = await getSettings()
settings.feature_flags[skipUnknownPackWarningFeatureFlag] = true
settings.warn_on_unknown_modpacks = false
await setSettings(settings)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const props = withDefaults(

const { formatMessage } = useVIntl()
const appSettings = useAppSettings()
const compactMode = computed(() => appSettings.getFeatureFlag('compact_instance_cards'))
const compactMode = computed(() => appSettings.compactInstanceCards)
const { addNotification } = injectNotificationManager()
const {
isSectionCollapsed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const localIcon = computed(() => {
return path && !/^https?:/.test(path) && !path.toLowerCase().endsWith('.svg') ? path : undefined
})
const appSettings = useAppSettings()
const compactMode = computed(() => appSettings.getFeatureFlag('compact_instance_cards'))
const compactMode = computed(() => appSettings.compactInstanceCards)
const thumbnail = useImageThumbnail(
localIcon,
() => (compactMode.value ? 96 : 384),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ import {
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
import { inject, onBeforeUnmount, onMounted } from 'vue'

import {
DEFAULT_FEATURE_FLAGS,
type FeatureFlag,
useAppSettings,
} from '@/composables/use-app-settings.ts'
import { useAppSettings } from '@/composables/use-app-settings.ts'
import {
type AppSettings,
appSettingsKeys,
Expand All @@ -33,11 +29,6 @@ const { updatePreferences } = injectUserPreferences()
const settingsModal = inject(appSettingsModalContextKey, null)
const queryClient = useQueryClient()

const compactInstanceCardsFlag: FeatureFlag = 'compact_instance_cards'
const skipNonEssentialWarningsFlag: FeatureFlag = 'skip_non_essential_warnings'
const skipUnknownPackWarningFlag: FeatureFlag = 'skip_unknown_pack_warning'
const showPlayTimeFlag: FeatureFlag = 'show_instance_play_time'

const messages = defineMessages({
syncAcrossDevicesTitle: {
id: 'app.behavior-settings.sync-across-devices.title',
Expand Down Expand Up @@ -72,6 +63,14 @@ const messages = defineMessages({
id: 'app.appearance-settings.minimize-launcher.description',
defaultMessage: 'Minimize Modrinth App when Minecraft starts.',
},
refocusOnGameCloseTitle: {
id: 'app.behavior-settings.refocus-on-game-close.title',
defaultMessage: 'Refocus app when Minecraft closes',
},
refocusOnGameCloseDescription: {
id: 'app.behavior-settings.refocus-on-game-close.description',
defaultMessage: 'Bring Modrinth App to the foreground when Minecraft exits.',
},
defaultLandingPageHome: {
id: 'app.appearance-settings.default-landing-page.home',
defaultMessage: 'Home',
Expand Down Expand Up @@ -135,6 +134,7 @@ const messages = defineMessages({
type BehaviorSettingsState = {
syncBehaviorAcrossDevices: boolean
minimizeApp: boolean
refocusOnGameClose: boolean
hideRightSidebar: boolean
compactInstanceCards: boolean
showPlayTime: boolean
Expand All @@ -150,20 +150,13 @@ function getBehaviorSettingsState(settings: AppSettings): BehaviorSettingsState
return {
syncBehaviorAcrossDevices: settings.sync_behavior_across_devices,
minimizeApp: settings.hide_on_process_start,
refocusOnGameClose: settings.refocus_on_game_close,
compactInstanceCards: settings.compact_instance_cards,
showPlayTime: settings.show_play_time,
warnOnUnknownModpacks: settings.warn_on_unknown_modpacks,
skipNonEssentialWarnings: settings.skip_non_essential_warnings,
hideRightSidebar: settings.toggle_sidebar,
compactInstanceCards:
settings.feature_flags[compactInstanceCardsFlag] ??
DEFAULT_FEATURE_FLAGS[compactInstanceCardsFlag],
showPlayTime:
settings.feature_flags[showPlayTimeFlag] ?? DEFAULT_FEATURE_FLAGS[showPlayTimeFlag],
hideNametag: settings.hide_nametag_skins_page,
warnOnUnknownModpacks: !(
settings.feature_flags[skipUnknownPackWarningFlag] ??
DEFAULT_FEATURE_FLAGS[skipUnknownPackWarningFlag]
),
skipNonEssentialWarnings:
settings.feature_flags[skipNonEssentialWarningsFlag] ??
DEFAULT_FEATURE_FLAGS[skipNonEssentialWarningsFlag],
}
}

Expand All @@ -175,6 +168,7 @@ const settingsMutation = useMutation({
await updatePreferences({
behavior: {
minimize_app: value.minimizeApp,
refocus_on_game_close: value.refocusOnGameClose,
hide_right_sidebar: value.hideRightSidebar,
compact_instance_cards: value.compactInstanceCards,
show_play_time: value.showPlayTime,
Expand All @@ -192,24 +186,23 @@ const settingsMutation = useMutation({
hide_on_process_start: value.minimizeApp,
toggle_sidebar: value.hideRightSidebar,
hide_nametag_skins_page: value.hideNametag,
feature_flags: {
...latestSettings.feature_flags,
[compactInstanceCardsFlag]: value.compactInstanceCards,
[showPlayTimeFlag]: value.showPlayTime,
[skipUnknownPackWarningFlag]: !value.warnOnUnknownModpacks,
[skipNonEssentialWarningsFlag]: value.skipNonEssentialWarnings,
},
refocus_on_game_close: value.refocusOnGameClose,
compact_instance_cards: value.compactInstanceCards,
show_play_time: value.showPlayTime,
warn_on_unknown_modpacks: value.warnOnUnknownModpacks,
skip_non_essential_warnings: value.skipNonEssentialWarnings,
}

await set(nextSettings)
queryClient.setQueryData(appSettingsKeys.all, nextSettings)
appSettings.setBehaviorSyncAcrossDevices(value.syncBehaviorAcrossDevices)
appSettings.refocusOnGameClose = value.refocusOnGameClose
appSettings.compactInstanceCards = value.compactInstanceCards
appSettings.showPlayTime = value.showPlayTime
appSettings.warnOnUnknownModpacks = value.warnOnUnknownModpacks
appSettings.skipNonEssentialWarnings = value.skipNonEssentialWarnings
appSettings.toggleSidebar = value.hideRightSidebar
appSettings.hideNametagSkinsPage = value.hideNametag
appSettings.featureFlags[compactInstanceCardsFlag] = value.compactInstanceCards
appSettings.featureFlags[showPlayTimeFlag] = value.showPlayTime
appSettings.featureFlags[skipUnknownPackWarningFlag] = !value.warnOnUnknownModpacks
appSettings.featureFlags[skipNonEssentialWarningsFlag] = value.skipNonEssentialWarnings
},
onMutate: () => queryClient.cancelQueries({ queryKey: appSettingsKeys.all }),
onError: handleError,
Expand Down Expand Up @@ -289,6 +282,23 @@ onBeforeUnmount(() => {
<Toggle id="minimize-launcher" v-model="current.minimizeApp" />
</div>

<div class="flex items-center justify-between gap-4">
<div>
<h3 id="refocus-on-game-close-label" class="m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.refocusOnGameCloseTitle) }}
</h3>
<p id="refocus-on-game-close-description" class="m-0 mt-1">
{{ formatMessage(messages.refocusOnGameCloseDescription) }}
</p>
</div>
<Toggle
id="refocus-on-game-close"
v-model="current.refocusOnGameClose"
aria-labelledby="refocus-on-game-close-label"
aria-describedby="refocus-on-game-close-description"
/>
</div>

<div class="flex items-center justify-between gap-4">
<div>
<h3 class="m-0 text-lg font-semibold text-contrast">
Expand Down
Loading
Loading