feat: expand ring to all positions so fresh mode has full inventory

The related content list only showed 42 forward items. When fresh mode
hid watched items, most were filtered out leaving a sparse list with
huge gaps. Now all ring positions are included so fresh mode always
has plenty of unwatched items to display.

- Pass forward=len(ring) to get_ring_related_products in all callers
- Cap forward in the function to prevent backward/forward overlap
- Add loading="lazy" to thumbnails beyond offset 7 (template + JS)
- Override mobile overflow hiding in fresh mode so unwatched overflow
  items remain visible
This commit is contained in:
russell@unturf.com 2026-02-23 12:50:33 -05:00
parent 4311a9b2b6
commit f4fc645586
7 changed files with 15 additions and 5 deletions

View file

@ -734,6 +734,10 @@ def get_ring_related_products(product, ring, forward=42, backward=3):
idx = ring.index(product_id_str)
ring_len = len(ring)
# Cap forward to avoid overlap with backward items in circular ring
max_forward = max(ring_len - 1 - backward, 0)
forward = min(forward, max_forward)
# Collect IDs with their offsets: negative=previous, positive=next
items = []
for i in range(backward, 0, -1):

View file

@ -1451,6 +1451,11 @@ textarea.markup-editor-textarea {
display: none;
}
/* Fresh mode: show overflow items that aren't watched */
.related-content.fresh-mode .related-content-row.related-content-overflow:not(.related-content-row-watched) {
display: block;
}
/* Show the comments anchor link on mobile */
.related-content-comments-link,
.product-comments-link {

View file

@ -921,7 +921,8 @@
html += '<span class="related-content-index">' + offset + '</span>';
html += '<a href="' + item.url + '" class="related-content-item" data-watch-id="' + item.id + '">';
if (item.thumbnail_url) {
html += '<img src="' + item.thumbnail_url + '" />';
var lazyAttr = offset > 7 ? ' loading="lazy"' : '';
html += '<img' + lazyAttr + ' src="' + item.thumbnail_url + '" />';
} else {
html += '<span class="related-content-no-thumb"></span>';
}

View file

@ -73,7 +73,7 @@
<span class="related-content-index">{{ offset }}</span>
<a href="{{ related.absolute_url(request) }}" class="related-content-item" data-watch-id="{{ related.id }}">
{% if "thumbnail1" in related.extensions %}
<img src="{{ request.app["bucket.secure_uploads.get_endpoint"] }}/{{ related.s3_path }}/thumbnail1?ts={{ related.updated_timestamp }}" />
<img {% if offset > 7 %}loading="lazy" {% endif %}src="{{ request.app["bucket.secure_uploads.get_endpoint"] }}/{{ related.s3_path }}/thumbnail1?ts={{ related.updated_timestamp }}" />
{% else %}
<span class="related-content-no-thumb"></span>
{% endif %}

View file

@ -78,7 +78,7 @@ def content(request):
from ..models.product import get_ring_related_products, get_related_products
ring = product.shop.discovery_ring
if ring:
related_products = get_ring_related_products(product, ring)
related_products = get_ring_related_products(product, ring, forward=len(ring))
else:
related_products = get_related_products(product)

View file

@ -98,7 +98,7 @@ def product(request):
from ..models.product import get_ring_related_products, get_related_products
ring = product.shop.discovery_ring
if ring:
related_products = get_ring_related_products(product, ring)
related_products = get_ring_related_products(product, ring, forward=len(ring))
else:
related_products = get_related_products(product)

View file

@ -106,7 +106,7 @@ def watch_json(request):
# Use existing discovery ring — never recompute during a request
ring = request.shop.discovery_ring
if ring:
related = get_ring_related_products(product, ring)
related = get_ring_related_products(product, ring, forward=len(ring))
else:
related = get_related_products(product)