mirror of
https://github.com/modrinth/code.git
synced 2026-08-27 18:14:49 +00:00
feat: instance sharing thru shared-instances service (#6569)
* feat: implement instance share page + search_users backend call * feat: invite players modal * feat: use tanstack queries for friends sync across app pages * feat: base shared instances implementation * fix: admon style * feat: impl instance admonitions like server panel * fix: impl get + del usage * feat: support modpack links * feat: invite notif accepting * fix: lint + fmt * feat: impl install to play * feat: impl usage of UpdateToPlayModal * feat: warnings on deleting/disabling shared-instance version content * fix: send instance name * feat: align with backend * feat: shared instances qa * feat: wrong account protection * feat: qa * fix: smartly apply updates * fix: install bug * fix: 401/404 differentiation * fix: fmt+prepr * feat: qa * feat: qa * fix: signing out messes up revoke/deleted checks * feat: qa * fix: fmt + lint * feat: lock content if part of shared instance * fix: lint * [do not merge] feat: rough invite links impl temp (#6666) * fix: wrong cmd * feat: invite page * fix: server-manager DTO mismatch * fix: drop anonymous invite link acceptance * refactor: structured shared-instance unavailable errors * refactor: centralise error presentations * refactor: dedupe shared instance diff detection * fix: logging in reqwests * refactor: move app.vue shared instances into handler * refactor: break up Share.vue * refactor: split up shared instances state outside of instance index * refactor: dedicated shared instances install/update modals + split up page * refactor: centralized managed content * refactor: split up install shared to own runner + shared.rs split up * refactor: dedupe sql for instance metadata enrichmnt * refactor: friends composable + dedupe friends logic across usages * chore: reduced unused code * fix: align with backend * fix: lint * fix: file sha changes * fix: invite links not working due to icon signed * feat: qa * feat: reporting frontend dummy * fix: try use header * remove: file hash field * fix: pin box * feat: malware warning for shared instances * fix: cache rule * feat: config files syncing * feat: disable config sharing * fix: header * fix: use mark ready * fix: dont cause push update for configs * fix: lint * feat: sharing page in settings * feat: move config + change flow * fix: qa * fix: lint prepr * feat: proxy file upload thru shared instances backend * fix: use collapisible * fix: push config * fix: config * feat: swap out sign in modal for new one * fix: report flow * fix: exclude configs.zip from external warnings * fix: nuxi init * fix: config bundle downloading * fix: error notif * fix: polling * fix: qa * fix: lint + prepr * feat: shared instances moderation frontend + hook up report flow * fix: report copy * fix: lint * fix: lint * fix: modrinth ids being undefined * feat: instance quarantining * fix: prepr + fmt * fix: quarantined -> locked terminology * fix: missing endpoint impls + fmt * fix: missing api in build.rs * fix: share tab jittery * fix: fmt *PT bug * fix: invites count as users even if pending * fix: prepr * fix: invite page owner in users list * fix: lint * fix: qa * fix: lint * fix: members stale not clearing * fix: invite use joined_at field * fix: lint * fix: qa --------- Co-authored-by: sychic <47618543+Sychic@users.noreply.github.com>
This commit is contained in:
@@ -9,25 +9,47 @@
|
||||
<slot name="icon" :icon-class="['h-6 w-6 flex-none', iconClasses[type]]">
|
||||
<component :is="getSeverityIcon(type)" :class="['h-6 w-6 flex-none', iconClasses[type]]" />
|
||||
</slot>
|
||||
<div class="col-start-2 flex min-w-0 flex-1 flex-col gap-2">
|
||||
<div
|
||||
class="col-start-2 min-w-0"
|
||||
:class="
|
||||
inlineActions && !showActionsUnderneath && $slots.actions
|
||||
? 'flex flex-wrap items-start gap-x-4 gap-y-3'
|
||||
: 'flex flex-1 flex-col gap-2'
|
||||
"
|
||||
>
|
||||
<div
|
||||
v-if="header || $slots.header || normalizedTimestamp"
|
||||
class="flex flex-wrap items-center gap-2 text-lg font-semibold leading-6"
|
||||
class="flex min-w-0 flex-1 flex-col gap-2"
|
||||
:class="
|
||||
inlineActions && !showActionsUnderneath && $slots.actions
|
||||
? 'admonition-inline-content'
|
||||
: ''
|
||||
"
|
||||
>
|
||||
<slot name="header">{{ header }}</slot>
|
||||
<span
|
||||
v-if="normalizedTimestamp"
|
||||
v-tooltip="timestampTooltip"
|
||||
class="flex items-center gap-1.5 text-base font-medium leading-normal text-secondary"
|
||||
<div
|
||||
v-if="header || $slots.header || normalizedTimestamp"
|
||||
class="flex flex-wrap items-center gap-2 text-lg font-semibold leading-6"
|
||||
>
|
||||
<ClockIcon class="size-4" />
|
||||
{{ relativeTimeLabel }}
|
||||
</span>
|
||||
<slot name="header">{{ header }}</slot>
|
||||
<span
|
||||
v-if="normalizedTimestamp"
|
||||
v-tooltip="timestampTooltip"
|
||||
class="flex items-center gap-1.5 text-base font-medium leading-normal text-secondary"
|
||||
>
|
||||
<ClockIcon class="size-4" />
|
||||
{{ relativeTimeLabel }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="font-normal text-contrast/85 leading-tight">
|
||||
<slot>{{ body }}</slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-normal text-contrast/85 leading-tight">
|
||||
<slot>{{ body }}</slot>
|
||||
<div
|
||||
v-if="inlineActions && !showActionsUnderneath && $slots.actions"
|
||||
class="ml-auto flex shrink-0 items-center justify-end self-center"
|
||||
>
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
<div v-if="showActionsUnderneath || $slots.actions" class="mt-2">
|
||||
<div v-else-if="showActionsUnderneath || $slots.actions" class="mt-2">
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,9 +102,10 @@ import ButtonStyled from './ButtonStyled.vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
type?: 'info' | 'warning' | 'critical' | 'success' | 'moderation' | 'circle-warning'
|
||||
type?: 'info' | 'warning' | 'critical' | 'success' | 'moderation' | 'circle-warning' | 'neutral'
|
||||
header?: string
|
||||
body?: string
|
||||
inlineActions?: boolean
|
||||
showActionsUnderneath?: boolean
|
||||
dismissible?: boolean
|
||||
progress?: number
|
||||
@@ -95,6 +118,7 @@ const props = withDefaults(
|
||||
type: 'info',
|
||||
header: '',
|
||||
body: '',
|
||||
inlineActions: false,
|
||||
showActionsUnderneath: false,
|
||||
dismissible: false,
|
||||
progress: undefined,
|
||||
@@ -143,6 +167,7 @@ const typeClasses = {
|
||||
critical: 'border-brand-red bg-bg-red',
|
||||
success: 'border-brand-green bg-bg-green',
|
||||
moderation: 'border-brand-orange bg-bg-orange',
|
||||
neutral: 'border-surface-4 bg-surface-3',
|
||||
}
|
||||
|
||||
const iconClasses = {
|
||||
@@ -152,6 +177,7 @@ const iconClasses = {
|
||||
critical: 'text-brand-red',
|
||||
success: 'text-brand-green',
|
||||
moderation: 'text-brand-orange',
|
||||
neutral: 'text-secondary',
|
||||
}
|
||||
|
||||
const buttonColors = {
|
||||
@@ -161,6 +187,7 @@ const buttonColors = {
|
||||
critical: 'red',
|
||||
success: 'green',
|
||||
moderation: 'orange',
|
||||
neutral: 'standard',
|
||||
} as const
|
||||
|
||||
const progressTrackClasses = {
|
||||
@@ -170,6 +197,7 @@ const progressTrackClasses = {
|
||||
critical: 'bg-brand-red/20',
|
||||
success: 'bg-brand-green/20',
|
||||
moderation: 'bg-brand-orange/20',
|
||||
neutral: 'bg-surface-4',
|
||||
}
|
||||
|
||||
const progressFillClasses = {
|
||||
@@ -181,10 +209,15 @@ const progressFillClasses = {
|
||||
blue: 'bg-brand-blue',
|
||||
green: 'bg-brand-green',
|
||||
red: 'bg-brand-red',
|
||||
neutral: 'bg-surface-5',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admonition-inline-content {
|
||||
min-width: min(100%, 16rem);
|
||||
}
|
||||
|
||||
.admonition-progress--waiting {
|
||||
animation: admonition-progress-waiting 1s linear infinite;
|
||||
position: relative;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
</div>
|
||||
<div class="ml-2 flex shrink-0 items-center gap-4">
|
||||
<button
|
||||
v-if="showSize"
|
||||
type="button"
|
||||
class="hidden w-[92px] appearance-none items-center gap-1 border-0 bg-transparent p-0 text-left font-semibold hover:text-primary sm:flex"
|
||||
:class="sortField === 'size' ? 'text-contrast' : 'text-secondary'"
|
||||
@@ -52,6 +53,7 @@
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
v-if="showModified"
|
||||
type="button"
|
||||
class="hidden w-[132px] appearance-none items-center gap-1 border-0 bg-transparent p-0 text-left font-semibold hover:text-primary sm:flex"
|
||||
:class="sortField === 'modified' ? 'text-contrast' : 'text-secondary'"
|
||||
@@ -90,8 +92,11 @@
|
||||
{{ formatMessage(messages.parentFolder) }}
|
||||
</span>
|
||||
<div class="ml-2 flex shrink-0 items-center gap-4">
|
||||
<span class="hidden w-[92px] text-left text-sm text-secondary sm:block" />
|
||||
<span class="hidden w-[132px] text-left text-sm text-secondary sm:block" />
|
||||
<span v-if="showSize" class="hidden w-[92px] text-left text-sm text-secondary sm:block" />
|
||||
<span
|
||||
v-if="showModified"
|
||||
class="hidden w-[132px] text-left text-sm text-secondary sm:block"
|
||||
/>
|
||||
<span class="size-4 shrink-0" aria-hidden="true" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,10 +145,16 @@
|
||||
{{ entry.name }}
|
||||
</span>
|
||||
<div class="ml-2 flex shrink-0 items-center gap-4">
|
||||
<span class="hidden w-[92px] truncate text-left text-sm text-secondary sm:block">
|
||||
<span
|
||||
v-if="showSize"
|
||||
class="hidden w-[92px] truncate text-left text-sm text-secondary sm:block"
|
||||
>
|
||||
{{ formatSize(entry) }}
|
||||
</span>
|
||||
<span class="hidden w-[132px] truncate text-left text-sm text-secondary sm:block">
|
||||
<span
|
||||
v-if="showModified"
|
||||
class="hidden w-[132px] truncate text-left text-sm text-secondary sm:block"
|
||||
>
|
||||
{{ formatModified(entry) }}
|
||||
</span>
|
||||
<ChevronRightIcon
|
||||
@@ -164,8 +175,8 @@
|
||||
<span class="size-4 shrink-0" />
|
||||
<span class="min-w-0 flex-1 truncate text-sm font-medium opacity-0">.</span>
|
||||
<div class="ml-2 flex shrink-0 items-center gap-4">
|
||||
<span class="hidden w-[92px] text-left text-sm sm:block" />
|
||||
<span class="hidden w-[132px] text-left text-sm sm:block" />
|
||||
<span v-if="showSize" class="hidden w-[92px] text-left text-sm sm:block" />
|
||||
<span v-if="showModified" class="hidden w-[132px] text-left text-sm sm:block" />
|
||||
<span class="size-4 shrink-0" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -262,10 +273,14 @@ const props = withDefaults(
|
||||
defineProps<{
|
||||
items: FileTreeSelectItem[]
|
||||
modelValue: string[]
|
||||
showSize?: boolean
|
||||
showModified?: boolean
|
||||
}>(),
|
||||
{
|
||||
items: () => [],
|
||||
modelValue: () => [],
|
||||
showSize: true,
|
||||
showModified: true,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
ref="metadata"
|
||||
class="page-header-metadata flex min-w-0 flex-wrap items-center gap-x-2 gap-y-2"
|
||||
class="page-header-metadata flex min-w-0 flex-wrap items-center gap-x-[1.625rem] gap-y-2"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div :class="rootClass" data-page-header-metadata-item v-bind="$attrs">
|
||||
<BulletDivider class="page-header-metadata-item-divider shrink-0" />
|
||||
<span
|
||||
class="page-header-metadata-item-divider absolute right-full flex h-full w-[1.625rem] items-center justify-center"
|
||||
>
|
||||
<BulletDivider class="shrink-0" />
|
||||
</span>
|
||||
<AutoLink
|
||||
v-if="to && !disabled"
|
||||
v-tooltip="tooltip"
|
||||
@@ -72,7 +76,7 @@ const props = withDefaults(defineProps<PageHeaderMetadataItemProps>(), {
|
||||
|
||||
const defaultIconClass = 'block size-5 shrink-0 text-current'
|
||||
const baseClass =
|
||||
'flex min-w-0 items-center gap-2 font-medium leading-none text-secondary text-nowrap'
|
||||
'relative flex min-w-0 items-center font-medium leading-none text-secondary text-nowrap'
|
||||
const contentBaseClass = 'inline-flex min-w-0 items-center gap-2 text-inherit'
|
||||
const interactiveClass = 'm-0 cursor-pointer border-0 bg-transparent p-0 hover:underline'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user