mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 21:26:40 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a1ac11a79 | ||
|
|
4e8f349b75 |
@@ -1468,6 +1468,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
|
||||
|
||||
.app-grid-statusbar {
|
||||
grid-area: status;
|
||||
padding-right: var(--window-controls-width, 0px);
|
||||
}
|
||||
|
||||
[data-tauri-drag-region-exclude] {
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<section
|
||||
v-if="!nativeDecorations && os !== 'MacOS'"
|
||||
class="window-controls"
|
||||
data-tauri-drag-region-exclude
|
||||
>
|
||||
<section v-if="showControls" class="window-controls" data-tauri-drag-region-exclude>
|
||||
<ButtonStyled type="transparent" circular>
|
||||
<button class="titlebar-button" @click="() => getCurrentWindow().minimize()">
|
||||
<MinimizeIcon />
|
||||
@@ -28,18 +24,35 @@ import { MaximizeIcon, MinimizeIcon, RestoreIcon, XIcon } from '@modrinth/assets
|
||||
import { ButtonStyled } from '@modrinth/ui'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
|
||||
import { get as getSettings } from '@/helpers/settings.ts'
|
||||
import { getOS } from '@/helpers/utils.js'
|
||||
|
||||
const WINDOW_CONTROLS_WIDTH = '8rem'
|
||||
|
||||
const nativeDecorations = ref(true)
|
||||
const isMaximized = ref(false)
|
||||
const os = ref('')
|
||||
|
||||
const showControls = computed(() => !nativeDecorations.value && os.value !== 'MacOS')
|
||||
watch(
|
||||
showControls,
|
||||
(visible) => {
|
||||
if (typeof document === 'undefined') return
|
||||
if (visible) {
|
||||
document.documentElement.style.setProperty('--window-controls-width', WINDOW_CONTROLS_WIDTH)
|
||||
} else {
|
||||
document.documentElement.style.removeProperty('--window-controls-width')
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
os.value = await getOS()
|
||||
|
||||
const settings = await import('@/helpers/settings.ts').then((m) => m.get())
|
||||
const settings = await getSettings()
|
||||
nativeDecorations.value = settings.native_decorations
|
||||
|
||||
if (os.value !== 'MacOS') {
|
||||
@@ -54,6 +67,7 @@ onMounted(async () => {
|
||||
|
||||
onUnmounted(() => {
|
||||
unlisten()
|
||||
document.documentElement.style.removeProperty('--window-controls-width')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ export class LauncherMetaManifestV0Module extends AbstractModule {
|
||||
/**
|
||||
* Get the loader manifest for a given loader platform.
|
||||
*
|
||||
* launcher-meta refuses CORS preflights that ask for the `Content-Type`
|
||||
* header (returns 403), so we strip the default `Content-Type: application/json`
|
||||
* the abstract client sets — these are body-less GETs and don't need it.
|
||||
* Without this the browser preflight is rejected and the GET never fires.
|
||||
*
|
||||
* @param loader - Loader platform (fabric, forge, quilt, neo)
|
||||
*/
|
||||
public async getManifest(loader: string): Promise<LauncherMeta.Manifest.v0.Manifest> {
|
||||
@@ -21,6 +26,7 @@ export class LauncherMetaManifestV0Module extends AbstractModule {
|
||||
version: `${loader}/v0`,
|
||||
method: 'GET',
|
||||
skipAuth: true,
|
||||
headers: { 'Content-Type': '' },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { onUnmounted, ref, watch } from 'vue'
|
||||
import { computed, onUnmounted, ref, watch } from 'vue'
|
||||
|
||||
import { useModalStack } from '../../composables/modal-stack'
|
||||
|
||||
const props = defineProps<{
|
||||
shown: boolean
|
||||
@@ -9,6 +11,9 @@ const props = defineProps<{
|
||||
const toolbarEl = ref<HTMLElement | null>(null)
|
||||
const compact = ref(false)
|
||||
|
||||
const { stackCount } = useModalStack()
|
||||
const zIndex = computed(() => 100 + stackCount.value * 10 + 31)
|
||||
|
||||
function checkCompact() {
|
||||
const el = toolbarEl.value
|
||||
if (!el) return
|
||||
@@ -58,23 +63,26 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Transition name="floating-action-bar" appear>
|
||||
<div
|
||||
v-if="shown"
|
||||
class="floating-action-bar drop-shadow-2xl fixed z-[21] p-4 bottom-0"
|
||||
aria-live="polite"
|
||||
>
|
||||
<Teleport to="body">
|
||||
<Transition name="floating-action-bar" appear>
|
||||
<div
|
||||
ref="toolbarEl"
|
||||
role="toolbar"
|
||||
:aria-label="ariaLabel"
|
||||
class="relative overflow-clip flex items-center gap-2 rounded-[20px] bg-surface-3 border border-surface-5 border-solid mx-auto max-w-[60vw] px-4 py-3 shadow-[0px_1px_3px_0px_rgba(0,0,0,0.3),0px_6px_10px_0px_rgba(0,0,0,0.15)]"
|
||||
:class="{ 'bar-compact': compact }"
|
||||
v-if="shown"
|
||||
class="floating-action-bar drop-shadow-2xl fixed p-4 bottom-0"
|
||||
:style="{ zIndex }"
|
||||
aria-live="polite"
|
||||
>
|
||||
<slot />
|
||||
<div
|
||||
ref="toolbarEl"
|
||||
role="toolbar"
|
||||
:aria-label="ariaLabel"
|
||||
class="relative overflow-clip flex items-center gap-2 rounded-[20px] bg-surface-3 border border-surface-5 border-solid mx-auto max-w-[60vw] px-4 py-3 shadow-[0px_1px_3px_0px_rgba(0,0,0,0.3),0px_6px_10px_0px_rgba(0,0,0,0.15)]"
|
||||
:class="{ 'bar-compact': compact }"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
<!-- eslint-disable no-console -->
|
||||
<script setup>
|
||||
import dayjs from 'dayjs'
|
||||
import { defineAsyncComponent, ref } from 'vue'
|
||||
import { defineAsyncComponent, onMounted, ref } from 'vue'
|
||||
|
||||
import { useFormatNumber } from '../../composables/index.ts'
|
||||
import Button from '../base/Button.vue'
|
||||
import Checkbox from '../base/Checkbox.vue'
|
||||
|
||||
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
||||
|
||||
// apexcharts touches `window` at module load time, so we must not let SSR
|
||||
// resolve the async component. Render only after mount on the client.
|
||||
const isClient = ref(false)
|
||||
onMounted(() => {
|
||||
isClient.value = true
|
||||
})
|
||||
|
||||
const formatNumber = useFormatNumber()
|
||||
|
||||
const props = defineProps({
|
||||
@@ -232,7 +240,14 @@ defineExpose({
|
||||
<slot name="toolbar" />
|
||||
</div>
|
||||
</div>
|
||||
<VueApexCharts ref="chart" :type="type" :options="chartOptions" :series="data" class="chart" />
|
||||
<VueApexCharts
|
||||
v-if="isClient"
|
||||
ref="chart"
|
||||
:type="type"
|
||||
:options="chartOptions"
|
||||
:series="data"
|
||||
class="chart"
|
||||
/>
|
||||
<div v-if="!hideLegend" class="legend">
|
||||
<Checkbox
|
||||
v-for="legend in legendValues"
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
<!-- eslint-disable eslint-comments/require-description -->
|
||||
<script setup>
|
||||
import dayjs from 'dayjs'
|
||||
import { defineAsyncComponent, ref } from 'vue'
|
||||
import { defineAsyncComponent, onMounted, ref } from 'vue'
|
||||
|
||||
import { useFormatNumber } from '../../composables/index.ts'
|
||||
import Card from '../base/Card.vue'
|
||||
|
||||
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
||||
|
||||
// apexcharts touches `window` at module load time, so we must not let SSR
|
||||
// resolve the async component. Render only after mount on the client.
|
||||
const isClient = ref(false)
|
||||
onMounted(() => {
|
||||
isClient.value = true
|
||||
})
|
||||
|
||||
const formatNumber = useFormatNumber()
|
||||
|
||||
const props = defineProps({
|
||||
@@ -148,6 +155,7 @@ const chartOptions = ref({
|
||||
{{ title }}
|
||||
</div>
|
||||
<VueApexCharts
|
||||
v-if="isClient"
|
||||
ref="chart"
|
||||
type="area"
|
||||
height="120"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, type Ref, ref } from 'vue'
|
||||
|
||||
const isClient = typeof window !== 'undefined'
|
||||
const stack: symbol[] = []
|
||||
@@ -33,6 +33,7 @@ export function useModalStack() {
|
||||
}
|
||||
|
||||
const hasModal = computed(() => stackSizeRef.value > 0)
|
||||
const stackCount: Readonly<Ref<number>> = stackSizeRef
|
||||
|
||||
return { push, pop, isTopmost, stackSize, hasModal }
|
||||
return { push, pop, isTopmost, stackSize, hasModal, stackCount }
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<div v-if="metric.showGraph" class="chart-space absolute bottom-0 left-0 right-0">
|
||||
<VueApexCharts
|
||||
v-if="!loading && metric.chartOptions"
|
||||
v-if="isClient && !loading && metric.chartOptions"
|
||||
type="area"
|
||||
height="142"
|
||||
:options="metric.chartOptions"
|
||||
@@ -62,13 +62,20 @@
|
||||
import { CpuIcon, DatabaseIcon, FolderOpenIcon } from '@modrinth/assets'
|
||||
import type { Stats } from '@modrinth/utils'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { computed, defineAsyncComponent, ref, shallowRef, watch } from 'vue'
|
||||
import { computed, defineAsyncComponent, onMounted, ref, shallowRef, watch } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
|
||||
import { injectModrinthServerContext, injectPageContext } from '#ui/providers'
|
||||
|
||||
const VueApexCharts = defineAsyncComponent(() => import('vue3-apexcharts'))
|
||||
|
||||
// apexcharts touches `window` at module load time, so we must not let SSR
|
||||
// resolve the async component. Render only after mount on the client.
|
||||
const isClient = ref(false)
|
||||
onMounted(() => {
|
||||
isClient.value = true
|
||||
})
|
||||
|
||||
const { serverId } = injectModrinthServerContext()
|
||||
const { featureFlags } = injectPageContext()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user