Added stash sorting to stash tooltip menu and profile page.

This commit is contained in:
2026-07-26 00:26:49 +02:00
parent d3f549c92f
commit 07d9dfaaaa
8 changed files with 281 additions and 16 deletions

View File

@@ -261,6 +261,7 @@ async function reloadStashes(newStash) {
<StashMenu
:stashes="stashes"
:item-stashes="itemStashes"
:domain="domain"
@stash="(stash) => stashItem(stash)"
@unstash="(stash) => unstashItem(stash)"
@create="showStashDialog = true"
@@ -318,6 +319,7 @@ async function reloadStashes(newStash) {
<StashMenu
:stashes="stashes"
:item-stashes="itemStashes"
:domain="domain"
@stash="(stash) => stashItem(stash)"
@unstash="(stash) => unstashItem(stash)"
@create="showStashDialog = true"

View File

@@ -1,7 +1,9 @@
<script setup>
import { computed, ref } from 'vue';
import Checkbox from '#/components/form/checkbox.vue';
defineProps({
const props = defineProps({
stashes: {
type: Array,
default: () => [],
@@ -10,16 +12,63 @@ defineProps({
type: Array,
default: () => [],
},
domain: {
type: String,
default: 'scenes',
},
});
const emit = defineEmits(['stash', 'unstash', 'create']);
const sortings = ['used', 'name', 'size', 'created'];
const sorting = ref(localStorage.getItem('stashMenuSorting') || 'used');
const domainKey = {
actors: 'stashedActors',
scenes: 'stashedScenes',
movies: 'stashedMovies',
}[props.domain];
const sortedStashes = computed(() => props.stashes
.toSorted((stashA, stashB) => {
return stashA.createdAt - stashB.createdAt;
})
.toSorted((stashA, stashB) => {
if (sorting.value === 'used') {
return stashB.lastStashAt - stashA.lastStashAt;
}
if (sorting.value === 'name') {
return stashA.name.localeCompare(stashB.name);
}
if (sorting.value === 'size') {
return stashB[domainKey] - stashA[domainKey];
}
if (sorting.value === 'created') {
return stashA.createdAt - stashB.createdAt;
}
return 0;
}));
/*
.toSorted((stashA, stashB) => {
return stashB.isPrimary - stashA.isPrimary;
}));
*/
function toggleSorting() {
sorting.value = sortings[(sortings.indexOf(sorting.value) + 1) % sortings.length];
localStorage.setItem('stashMenuSorting', sorting.value);
}
</script>
<template>
<div class="stash-menu noselect">
<ul class="stash-list nolist noselect">
<li
v-for="userStash in stashes"
v-for="userStash in sortedStashes"
:key="`stash-${userStash.id}`"
class="menu-item"
>
@@ -32,13 +81,47 @@ const emit = defineEmits(['stash', 'unstash', 'create']);
</li>
</ul>
<div
v-close-popper
class="menu-item menu-stash create"
@click="emit('create')"
>
<Icon icon="plus3" />
New
<div class="menu-actions">
<div
v-close-popper
class="menu-item menu-stash menu-create"
@click="emit('create')"
>
<Icon icon="plus3" />
New
</div>
<Icon
v-if="sorting === 'used'"
v-tooltip="'By last stash'"
icon="sort-heart"
class="menu-sort"
@click="toggleSorting"
/>
<Icon
v-if="sorting === 'name'"
v-tooltip="'By name'"
icon="sort-alpha-asc"
class="menu-sort"
@click="toggleSorting"
/>
<Icon
v-if="sorting === 'size'"
v-tooltip="`By total stashed ${domain}`"
icon="sort-amount-desc"
class="menu-sort"
@click="toggleSorting"
/>
<Icon
v-if="sorting === 'created'"
v-tooltip="'By stash age'"
icon="sort-time-asc"
class="menu-sort"
@click="toggleSorting"
/>
</div>
</div>
</template>
@@ -85,10 +168,22 @@ const emit = defineEmits(['stash', 'unstash', 'create']);
.check-container {
margin-right: .5rem;
}
}
&.create {
flex-shrink: 0;
border-top: 1px solid var(--glass-weak-40);
.menu-actions {
flex-shrink: 0;
display: flex;
border-top: solid 1px var(--glass-weak-40);
}
.menu-sort {
padding: .75rem 1rem;
fill: var(--glass);
border-left: solid 1px var(--glass-weak-40);
&:hover {
fill: var(--primary);
cursor: pointer;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<script setup>
import { inject, ref } from 'vue';
import { computed, inject, ref } from 'vue';
import StashDialog from '#/components/stashes/create.vue';
import StashTile from '#/components/stashes/tile.vue';
@@ -13,16 +13,51 @@ const stashes = ref(pageContext.pageProps.stashes);
const profile = ref(pageContext.pageProps.profile);
const showStashDialog = ref(false);
const sortings = ['used', 'name', 'size', 'created'];
const sorting = ref('size');
async function reloadStashes() {
// profile.value = await get(`/users/${profile.value.id}`);
stashes.value = await get(`/users/${profile.value.id}/stashes`);
}
const sortedStashes = computed(() => stashes.value
.toSorted((stashA, stashB) => {
return stashA.createdAt - stashB.createdAt;
})
.toSorted((stashA, stashB) => {
if (sorting.value === 'used') {
return stashB.lastStashAt - stashA.lastStashAt;
}
if (sorting.value === 'name') {
return stashA.name.localeCompare(stashB.name);
}
if (sorting.value === 'size') {
return (stashB.stashedScenes + stashB.stashedMovies + stashB.stashedActors)
- (stashA.stashedScenes + stashA.stashedMovies + stashA.stashedActors);
}
if (sorting.value === 'created') {
return stashA.createdAt - stashB.createdAt;
}
return 0;
})
.toSorted((stashA, stashB) => {
// always put favorites first
return stashB.isPrimary - stashA.isPrimary;
}));
function toggleSorting() {
sorting.value = sortings[(sortings.indexOf(sorting.value) + 1) % sortings.length];
}
</script>
<template>
<section class="profile-section">
<div class="section-header">
<div class="section-header noselect">
<button
v-if="profile.id === user?.id"
class="button"
@@ -31,6 +66,38 @@ async function reloadStashes() {
<Icon icon="folder-plus2" />
<span class="button-label">New stash</span>
</button>
<Icon
v-if="sorting === 'used'"
v-tooltip="'By last stash'"
icon="sort-heart"
class="sort"
@click="toggleSorting"
/>
<Icon
v-if="sorting === 'name'"
v-tooltip="'By name'"
icon="sort-alpha-asc"
class="sort"
@click="toggleSorting"
/>
<Icon
v-if="sorting === 'size'"
v-tooltip="'By total stashed'"
icon="sort-amount-desc"
class="sort"
@click="toggleSorting"
/>
<Icon
v-if="sorting === 'created'"
v-tooltip="'By stash age'"
icon="sort-time-asc"
class="sort"
@click="toggleSorting"
/>
</div>
<StashDialog
@@ -41,7 +108,7 @@ async function reloadStashes() {
<ul class="stashes nolist">
<li
v-for="stash in stashes"
v-for="stash in sortedStashes"
:key="`stash-${stash.id}`"
>
<StashTile
@@ -59,6 +126,7 @@ async function reloadStashes() {
display: flex;
justify-content: center;
margin-bottom: .5rem;
gap: 1rem;
}
.stashes {
@@ -68,6 +136,16 @@ async function reloadStashes() {
padding: 0 0 1rem 0;
}
.sort {
padding: .5rem 1rem;
fill: var(--glass);
&:hover {
fill: var(--primary);
cursor: pointer;
}
}
@media(--compact) {
.stashes {
padding: 0 1rem 1rem 1rem;