* fix(content): changing mod versions works again * chore(assets): update pyro logo * fix(properties): deprecate fetchconfigfile * Revert "fix(content): changing mod versions works again" This reverts commit d7c0d1196f8c1850fd7ccbc1644941c6db4dc306. * feat(files): ability to sort via column click * chore(startup): update clunky wording * feat(serverListing): server icons SSR friendly * fix(servers): if archon fails, display err in listing * chore(serverlisting): use pyroserver hook to init icon * chore(servers): much more graceful reinstall * fix(servers): tw warn * fix(platform): correctly react when pack reinstalled * fix(serversroot): explicitly import navigateTo Signed-off-by: Evan Song <theevansong@gmail.com> * chore(serverlabels): show skeleton instead of hiding Signed-off-by: Evan Song <theevansong@gmail.com> * feat(platform): install-aware controls Signed-off-by: Evan Song <theevansong@gmail.com> * refactor!(platform): rewrite platform page * fix(platform): regression in autoselecting loader * chore(platform): prefer version over project modification date * fix(platform): permanent hang after initial mount * chore(platform): do not silently fail and hang if modpack fails loading * oops: remove hardcoded error causer * fix(platform): switch modpack btn while installing doesnt need class Signed-off-by: Evan Song <theevansong@gmail.com> * chore(platform): adjust styling in version modal Signed-off-by: Evan Song <theevansong@gmail.com> * chore(platform): prevent changing project card style Signed-off-by: Evan Song <theevansong@gmail.com> * refactor(pyrodropdown): rewrite Signed-off-by: Evan Song <theevansong@gmail.com> * fix(pyrodropdown): do nopt use deprecated substr Signed-off-by: Evan Song <theevansong@gmail.com> * chore: clean Signed-off-by: Evan Song <theevansong@gmail.com> * fix(network): sentence case Signed-off-by: Evan Song <theevansong@gmail.com> * refactor(terminal): initial batch Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): fulllog over fullscreen Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): fullscreen conflict with body scroll Signed-off-by: Evan Song <theevansong@gmail.com> * feat(terminal): init drag select * feat(terminal): shift click support Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): double lines limit Signed-off-by: Evan Song <theevansong@gmail.com> * feat(terminal): copy button Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): protip style Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): improve styles Signed-off-by: Evan Song <theevansong@gmail.com> * feat(terminal): regex search Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): move icons to icons dir Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): improve drag select autoscroll inertia Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): cancel selection on right click Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): progblur and stb btn disappearing Signed-off-by: Evan Song <theevansong@gmail.com> * refactor(serverstats): power efficiency * fix(subdomainlabel): correct tooltip terminology Signed-off-by: Evan Song <theevansong@gmail.com> * feat(preferences): users hide subdomain label Signed-off-by: Evan Song <theevansong@gmail.com> * chore(servers): clean Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): deselect lines on escape Signed-off-by: Evan Song <theevansong@gmail.com> * fix(serversidebar): type err Signed-off-by: Evan Song <theevansong@gmail.com> * fix(fileitem): vue server render type Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): disable pointer events on lines if scrolling Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): search result counts style Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): plural Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): clean Signed-off-by: Evan Song <theevansong@gmail.com> * feat(terminal): view selection Signed-off-by: Evan Song <theevansong@gmail.com> * feat(terminal): show actively selected lines in scrollbar Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminallog): btn color Signed-off-by: Evan Song <theevansong@gmail.com> * chore: clean Signed-off-by: Evan Song <theevansong@gmail.com> * fix(gamelabel): align to text Signed-off-by: Evan Song <theevansong@gmail.com> * fix(gamelabel): align to text Signed-off-by: Evan Song <theevansong@gmail.com> * fix(listing): remove deadcode Signed-off-by: Evan Song <theevansong@gmail.com> * fix(serverlisting): deprecated process.server Signed-off-by: Evan Song <theevansong@gmail.com> * fix(platform): correctly disable button Signed-off-by: Evan Song <theevansong@gmail.com> * fix(backups): do not allow backup creation during server installation Signed-off-by: Evan Song <theevansong@gmail.com> * fix(platform): flush stale currentversion data on successful install Signed-off-by: Evan Song <theevansong@gmail.com> * fix(gamelabel): fix gap Signed-off-by: Evan Song <theevansong@gmail.com> * chore(network): vaporize uppercase Signed-off-by: Evan Song <theevansong@gmail.com> * chore(info): vaporize uppercase Signed-off-by: Evan Song <theevansong@gmail.com> * chore(backups): style unification Signed-off-by: Evan Song <theevansong@gmail.com> * chore(backups): finalize style change Signed-off-by: Evan Song <theevansong@gmail.com> * fix(servers): catch pyro servers fetch errors during ssr Signed-off-by: Evan Song <theevansong@gmail.com> * fix(serverstats): ram as bytes graph now works Signed-off-by: Evan Song <theevansong@gmail.com> * fix(platform): unify attempts and refresh interval Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): input Signed-off-by: Evan Song <theevansong@gmail.com> * feat(servers): installing ticket + update available notice back in platform Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): dont add bg to scroll track Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): preserve whitespace Signed-off-by: Evan Song <theevansong@gmail.com> * chore(serversroot): unnest blurred icon query Signed-off-by: Evan Song <theevansong@gmail.com> * fix(serverstats): clamp memory usage to 100% no matter what Signed-off-by: Evan Song <theevansong@gmail.com> * feat(terminal): allow copy of single lines, show btn Signed-off-by: Evan Song <theevansong@gmail.com> * chore(terminal): animate copy>view transition Signed-off-by: Evan Song <theevansong@gmail.com> * init: search improvements Signed-off-by: Evan Song <theevansong@gmail.com> * fix: lint Signed-off-by: Evan Song <theevansong@gmail.com> * chore: change log modal title Signed-off-by: Evan Song <theevansong@gmail.com> * fix: hide fullscreen when selecting and cancel selection on clickout Signed-off-by: Evan Song <theevansong@gmail.com> * refactor(terminal): more reliable jumpToLine Signed-off-by: Evan Song <theevansong@gmail.com> * feat: search results separator Signed-off-by: Evan Song <theevansong@gmail.com> * chore: remove buggy isScrollable check Signed-off-by: Evan Song <theevansong@gmail.com> * fix: style Signed-off-by: Evan Song <theevansong@gmail.com> * refactor: correctly store pos to make jump reliable Signed-off-by: Evan Song <theevansong@gmail.com> * fix: disparity between search/log dragselect Signed-off-by: Evan Song <theevansong@gmail.com> * fix: prevent propagation of click events when clicking on jump btn Signed-off-by: Evan Song <theevansong@gmail.com> * fix: switch selection strategies depending on terminal mode Signed-off-by: Evan Song <theevansong@gmail.com> * chore: smarter esc handling Signed-off-by: Evan Song <theevansong@gmail.com> * finalize Signed-off-by: Evan Song <theevansong@gmail.com> * run fix * fix: ensure lines between cannot be selected Signed-off-by: Evan Song <theevansong@gmail.com> * fix: increase initial log batch to 256 Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): click on scroll track should take user to new scroll position Signed-off-by: Evan Song <theevansong@gmail.com> * fix(terminal): update aria label for view selected logs btn Signed-off-by: Evan Song <theevansong@gmail.com> * chore: clean Signed-off-by: Evan Song <theevansong@gmail.com> --------- Signed-off-by: Evan Song <theevansong@gmail.com>
230 lines
7.4 KiB
Vue
230 lines
7.4 KiB
Vue
<template>
|
|
<div ref="pyroFilesSentinel" class="sentinel" data-pyro-files-sentinel />
|
|
<header
|
|
:class="[
|
|
'duration-20 top-0 flex select-none flex-col justify-between gap-2 bg-table-alternateRow p-3 transition-[border-radius] sm:h-12 sm:flex-row',
|
|
!isStuck ? 'rounded-t-2xl' : 'sticky top-0 z-20',
|
|
]"
|
|
data-pyro-files-state="browsing"
|
|
aria-label="File navigation"
|
|
>
|
|
<nav
|
|
aria-label="Breadcrumb navigation"
|
|
class="m-0 flex min-w-0 flex-shrink items-center p-0 text-contrast"
|
|
>
|
|
<ol class="m-0 flex min-w-0 flex-shrink list-none items-center p-0">
|
|
<li class="-ml-1 flex-shrink-0">
|
|
<ButtonStyled type="transparent">
|
|
<button
|
|
v-tooltip="'Back to home'"
|
|
type="button"
|
|
class="mr-2 grid h-12 w-10 place-content-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
|
|
@click="$emit('navigate', -1)"
|
|
>
|
|
<span
|
|
class="grid size-8 place-content-center rounded-full bg-button-bg p-[6px] group-hover:bg-brand-highlight group-hover:text-brand"
|
|
>
|
|
<HomeIcon class="h-5 w-5" />
|
|
<span class="sr-only">Home</span>
|
|
</span>
|
|
</button>
|
|
</ButtonStyled>
|
|
</li>
|
|
<li class="m-0 -ml-2 min-w-0 flex-shrink p-0">
|
|
<ol class="m-0 flex min-w-0 flex-shrink items-center overflow-hidden p-0">
|
|
<TransitionGroup
|
|
name="breadcrumb"
|
|
tag="span"
|
|
class="relative flex min-w-0 flex-shrink items-center"
|
|
>
|
|
<li
|
|
v-for="(segment, index) in breadcrumbSegments"
|
|
:key="`${segment || index}-group`"
|
|
class="relative flex min-w-0 flex-shrink items-center text-sm"
|
|
>
|
|
<div class="flex min-w-0 flex-shrink items-center">
|
|
<ButtonStyled type="transparent">
|
|
<button
|
|
class="cursor-pointer truncate focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
|
|
:aria-current="
|
|
index === breadcrumbSegments.length - 1 ? 'location' : undefined
|
|
"
|
|
:class="{
|
|
'!text-contrast': index === breadcrumbSegments.length - 1,
|
|
}"
|
|
@click="$emit('navigate', index)"
|
|
>
|
|
{{ segment || "" }}
|
|
</button>
|
|
</ButtonStyled>
|
|
<ChevronRightIcon
|
|
v-if="index < breadcrumbSegments.length - 1"
|
|
class="size-4 flex-shrink-0 text-secondary"
|
|
aria-hidden="true"
|
|
/>
|
|
</div>
|
|
</li>
|
|
</TransitionGroup>
|
|
</ol>
|
|
</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<div class="flex flex-shrink-0 items-center gap-1">
|
|
<div class="flex w-full flex-row-reverse sm:flex-row">
|
|
<ButtonStyled type="transparent">
|
|
<UiServersTeleportOverflowMenu
|
|
position="bottom"
|
|
direction="left"
|
|
aria-label="Filter view"
|
|
:options="[
|
|
{ id: 'all', action: () => $emit('filter', 'all') },
|
|
{ id: 'filesOnly', action: () => $emit('filter', 'filesOnly') },
|
|
{ id: 'foldersOnly', action: () => $emit('filter', 'foldersOnly') },
|
|
]"
|
|
>
|
|
<div class="flex items-center gap-1">
|
|
<FilterIcon aria-hidden="true" class="h-5 w-5" />
|
|
<span class="hidden text-sm font-medium sm:block">
|
|
{{ filterLabel }}
|
|
</span>
|
|
</div>
|
|
<DropdownIcon aria-hidden="true" class="h-5 w-5 text-secondary" />
|
|
<template #all>Show all</template>
|
|
<template #filesOnly>Files only</template>
|
|
<template #foldersOnly>Folders only</template>
|
|
</UiServersTeleportOverflowMenu>
|
|
</ButtonStyled>
|
|
<div class="mx-1 w-full text-sm sm:w-48">
|
|
<label for="search-folder" class="sr-only">Search folder</label>
|
|
<div class="relative">
|
|
<SearchIcon
|
|
class="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2"
|
|
aria-hidden="true"
|
|
/>
|
|
<input
|
|
id="search-folder"
|
|
:value="searchQuery"
|
|
type="search"
|
|
name="search"
|
|
autocomplete="off"
|
|
class="h-8 min-h-[unset] w-full border-[1px] border-solid border-divider bg-transparent py-2 pl-9"
|
|
placeholder="Search..."
|
|
@input="$emit('update:searchQuery', ($event.target as HTMLInputElement).value)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<ButtonStyled type="transparent">
|
|
<UiServersTeleportOverflowMenu
|
|
position="bottom"
|
|
direction="left"
|
|
aria-label="Create new..."
|
|
:options="[
|
|
{ id: 'file', action: () => $emit('create', 'file') },
|
|
{ id: 'directory', action: () => $emit('create', 'directory') },
|
|
{ id: 'upload', action: () => $emit('upload') },
|
|
]"
|
|
>
|
|
<PlusIcon aria-hidden="true" />
|
|
<DropdownIcon aria-hidden="true" class="h-5 w-5 text-secondary" />
|
|
<template #file> <BoxIcon aria-hidden="true" /> New file </template>
|
|
<template #directory> <FolderOpenIcon aria-hidden="true" /> New folder </template>
|
|
<template #upload> <UploadIcon aria-hidden="true" /> Upload file </template>
|
|
</UiServersTeleportOverflowMenu>
|
|
</ButtonStyled>
|
|
</div>
|
|
</header>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {
|
|
BoxIcon,
|
|
PlusIcon,
|
|
UploadIcon,
|
|
DropdownIcon,
|
|
FolderOpenIcon,
|
|
SearchIcon,
|
|
HomeIcon,
|
|
ChevronRightIcon,
|
|
FilterIcon,
|
|
} from "@modrinth/assets";
|
|
import { ButtonStyled } from "@modrinth/ui";
|
|
import { ref, computed } from "vue";
|
|
import { useIntersectionObserver } from "@vueuse/core";
|
|
|
|
const props = defineProps<{
|
|
breadcrumbSegments: string[];
|
|
searchQuery: string;
|
|
currentFilter: string;
|
|
}>();
|
|
|
|
defineEmits<{
|
|
(e: "navigate", index: number): void;
|
|
(e: "create", type: "file" | "directory"): void;
|
|
(e: "upload"): void;
|
|
(e: "update:searchQuery", value: string): void;
|
|
(e: "filter", type: string): void;
|
|
}>();
|
|
|
|
const pyroFilesSentinel = ref<HTMLElement | null>(null);
|
|
const isStuck = ref(false);
|
|
|
|
useIntersectionObserver(
|
|
pyroFilesSentinel,
|
|
([{ isIntersecting }]) => {
|
|
isStuck.value = !isIntersecting;
|
|
},
|
|
{ threshold: [0, 1] },
|
|
);
|
|
|
|
const filterLabel = computed(() => {
|
|
switch (props.currentFilter) {
|
|
case "filesOnly":
|
|
return "Files only";
|
|
case "foldersOnly":
|
|
return "Folders only";
|
|
default:
|
|
return "Show all";
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.sentinel {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 1px;
|
|
visibility: hidden;
|
|
}
|
|
|
|
.breadcrumb-move,
|
|
.breadcrumb-enter-active,
|
|
.breadcrumb-leave-active {
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.breadcrumb-enter-from {
|
|
opacity: 0;
|
|
transform: translateX(-10px) scale(0.9);
|
|
}
|
|
|
|
.breadcrumb-leave-to {
|
|
opacity: 0;
|
|
transform: translateX(-10px) scale(0.8);
|
|
filter: blur(4px);
|
|
}
|
|
|
|
.breadcrumb-leave-active {
|
|
position: relative;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.breadcrumb-move {
|
|
z-index: 1;
|
|
}
|
|
</style>
|