cluster: new albums layout

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/767/head
Varun Patil 2023-08-04 18:49:28 -07:00
parent eba28c3976
commit 3fec0a94bd
3 changed files with 114 additions and 44 deletions

View File

@ -8,7 +8,8 @@
:items="clusters" :items="clusters"
:skipHover="true" :skipHover="true"
:buffer="400" :buffer="400"
:itemSize="itemSize" :itemSize="height"
:itemSecondarySize="width"
:gridItems="gridItems" :gridItems="gridItems"
@resize="resize" @resize="resize"
> >
@ -18,7 +19,7 @@
<template v-slot="{ item }"> <template v-slot="{ item }">
<div class="grid-item fill-block"> <div class="grid-item fill-block">
<Cluster :data="item" @click="click(item)" :link="link" /> <Cluster :data="item" :link="link" :class="clusterClasses" :counters="counters" @click="click(item)" />
</div> </div>
</template> </template>
</RecycleScroller> </RecycleScroller>
@ -60,8 +61,7 @@ export default defineComponent({
}, },
data: () => ({ data: () => ({
itemSize: 200, recyclerWidth: 300,
gridItems: 5,
}), }),
mounted() { mounted() {
@ -69,6 +69,40 @@ export default defineComponent({
}, },
computed: { computed: {
/** Height of the cluster */
height() {
if (this.routeIsAlbums) {
// album view: add gap for text below album
return this.width + 42;
}
return this.width;
},
/** Width of the cluster */
width() {
// Restrict the number of columns between minCols and the size cap
return Math.floor(this.recyclerWidth / this.gridItems);
},
/** Number of items horizontally */
gridItems() {
return Math.max(Math.floor(this.recyclerWidth / this.maxSize), this.minCols);
},
/** Classes list on cluster object */
clusterClasses() {
return {
'cluster--album': this.routeIsAlbums,
};
},
/** Whether the clusters should show counters */
counters() {
return !this.routeIsAlbums;
},
/** List of clusters to display */
clusters() { clusters() {
const items = [...this.items]; const items = [...this.items];
@ -98,10 +132,7 @@ export default defineComponent({
}, },
resize() { resize() {
// Restrict the number of columns between minCols and the size cap this.recyclerWidth = (<any>this.$refs.recycler).$el.clientWidth;
const w = (<any>this.$refs.recycler).$el.clientWidth;
this.gridItems = Math.max(Math.floor(w / this.maxSize), this.minCols);
this.itemSize = Math.floor(w / this.gridItems);
}, },
}, },
}); });

View File

@ -6,7 +6,7 @@
<EmptyContent v-if="!items.length && !loading" /> <EmptyContent v-if="!items.length && !loading" />
<ClusterGrid :items="items" :minCols="minCols"> <ClusterGrid :items="items" :minCols="minCols" :maxSize="maxSize">
<template #before> <template #before>
<DynamicTopMatter class="cv-dtm" ref="dtm" /> <DynamicTopMatter class="cv-dtm" ref="dtm" />
</template> </template>
@ -56,7 +56,11 @@ export default defineComponent({
}, },
minCols() { minCols() {
return this.$route.name === 'albums' ? 2 : 3; return this.routeIsAlbums ? 2 : 3;
},
maxSize() {
return this.routeIsAlbums ? 250 : 180;
}, },
}, },

View File

@ -4,8 +4,8 @@
<NcCounterBubble> {{ data.count }} </NcCounterBubble> <NcCounterBubble> {{ data.count }} </NcCounterBubble>
</div> </div>
<div class="name"> <div class="name">
{{ title }} <div class="title">{{ title }}</div>
<span class="subtitle" v-if="subtitle"> {{ subtitle }} </span> <div class="subtitle" v-if="subtitle">{{ subtitle }}</div>
</div> </div>
<div class="previews fill-block" ref="previews"> <div class="previews fill-block" ref="previews">
@ -87,8 +87,23 @@ export default defineComponent({
}, },
subtitle() { subtitle() {
if (this.album && this.album.user !== getCurrentUser()?.uid) { if (this.album) {
return `(${this.album.user_display || this.album.user})`; let text: string;
if (this.album.count === 0) {
text = this.t('memories', 'No items');
} else {
text = this.n('memories', '{n} item', '{n} items', this.album.count, { n: this.album.count });
}
if (this.album.user !== getCurrentUser()?.uid) {
text +=
' / ' +
this.t('memories', 'Shared by {user}', {
user: this.album.user_display || this.album.user,
});
}
return text;
} }
return ''; return '';
@ -165,14 +180,6 @@ img {
} }
.cluster { .cluster {
// to use this option, the height must be set to a bit more
// than the width for the text; the image will then be forced
// to be square and the label will be outside.
&--circle {
height: unset; // from .fill-block
aspect-ratio: 1;
}
// Get rid of color of the bubble // Get rid of color of the bubble
.count-bubble :deep .counter-bubble__counter { .count-bubble :deep .counter-bubble__counter {
color: unset !important; color: unset !important;
@ -187,9 +194,6 @@ $namemargin: 7px;
width: calc(100% - 2 * #{$namemargin}); width: calc(100% - 2 * #{$namemargin});
margin: $namemargin; margin: $namemargin;
// 2px padding prevents the bottom of the text from being cut off
padding-bottom: 2px;
color: white; color: white;
word-wrap: break-word; word-wrap: break-word;
white-space: normal; white-space: normal;
@ -198,31 +202,55 @@ $namemargin: 7px;
line-height: 1.1em; line-height: 1.1em;
// multiline ellipsis // multiline ellipsis
display: -webkit-box; > .title {
-webkit-line-clamp: 5; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-line-clamp: 5;
overflow: hidden; -webkit-box-orient: vertical;
overflow: hidden;
// 2px padding prevents the bottom of the text from being cut off
padding-bottom: 2px;
}
// name is below the image
.cluster--circle & { .cluster--circle & {
-webkit-line-clamp: 2;
margin: 0 $namemargin; margin: 0 $namemargin;
min-height: 26px; // alignment min-height: 26px; // alignment
}
> .subtitle {
font-size: 0.7em;
margin-top: 2px;
display: block;
}
.cluster.error > &,
.cluster--circle & {
color: unset; color: unset;
} }
.cluster--circle &,
.cluster--album &,
.cluster.error & {
color: unset;
> .title {
-webkit-line-clamp: 2;
}
}
.cluster--album & {
text-align: start;
margin: 0;
padding: 0 12px;
min-height: 50px;
> .subtitle {
color: var(--color-text-lighter);
font-size: 0.87em;
}
}
@media (max-width: 768px) { @media (max-width: 768px) {
font-size: 0.9em; font-size: 0.9em;
} }
> .subtitle {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
} }
.count-bubble { .count-bubble {
@ -239,6 +267,10 @@ $namemargin: 7px;
padding: 2px; padding: 2px;
box-sizing: border-box; box-sizing: border-box;
.cluster--album & {
padding: 12px;
}
> .img-outer { > .img-outer {
position: relative; position: relative;
background-color: var(--color-background-dark); background-color: var(--color-background-dark);
@ -250,14 +282,17 @@ $namemargin: 7px;
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
.cluster--rounded & { .cluster--rounded &,
.cluster--album & {
border-radius: 12px; // rounded corners border-radius: 12px; // rounded corners
} }
.cluster--album &,
.cluster--circle & { .cluster--circle & {
// circle image
border-radius: 50%;
height: unset; height: unset;
aspect-ratio: 1; aspect-ratio: 1; // force square
}
.cluster--circle & {
border-radius: 50%; // circle image
} }
&.plus { &.plus {