- The inventory's Recently Added puts T5 products added to the library in the last 30 days first. - The shop's T5 listing follows its sort menu: Best Match ranks by name, Newest by upload date (oldest first ascending); ratings and prices (T5 products have neither) sort by newest. - Outfit cards: outfit_products.php gets the outfit's community products added (not for sale), find_bundle.php is asked about IMVU's products only, and removing one in the card (remove_pids) keeps it from IMVU and forgets it in the outfit. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
af9158513b
commit
171e8173af
11 files changed
+463
-7
No files matched your search
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -37,6 +38,8 @@ func (p *Products) interceptShopSearch(x *proxy.Exchange) error {
|
||||
Page json.Number `json:"page"`
|
||||
Skip json.Number `json:"skip"`
|
||||
PerPage json.Number `json:"results_per_page"`
|
||||
Sort string `json:"sort_field"`
|
||||
Dir string `json:"sort_direction"`
|
||||
Limit json.Number `json:"solr_limit"`
|
||||
}
|
||||
if json.Unmarshal(x.Body, &req) != nil || req.Rating != ShopRating {
|
||||
@@ -67,6 +70,7 @@ func (p *Products) interceptShopSearch(x *proxy.Exchange) error {
|
||||
}
|
||||
p.mu.Unlock()
|
||||
list = inCategories(list, categoryIDs(req.Category))
|
||||
sortShop(list, query, req.Sort, req.Dir)
|
||||
p.fetchForShop(ctx, list)
|
||||
|
||||
var rows []shopRow
|
||||
@@ -244,6 +248,41 @@ func shopAnswer(rows []shopRow, page, skip, perPage, limit int) []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
// sortShop orders products for the shop's sort menu. T5 products have no ratings or prices, so those sorts are by
|
||||
// newest; Best Match (conversion_score_b, score) with a search puts the closest names first (the same name, then
|
||||
// names starting with it, then words starting with it, then the rest), newest first among equals; Newest
|
||||
// (id) is newest first, or oldest first ascending.
|
||||
func sortShop(list []hub.Product, query, field, direction string) {
|
||||
q := strings.ToLower(strings.TrimSpace(query))
|
||||
rank := func(hp hub.Product) int {
|
||||
if q == "" || (field != "conversion_score_b" && field != "score" && field != "") {
|
||||
return 0
|
||||
}
|
||||
name := strings.ToLower(hp.Name)
|
||||
switch {
|
||||
case name == q:
|
||||
return 0
|
||||
case strings.HasPrefix(name, q):
|
||||
return 1
|
||||
case strings.Contains(" "+name, " "+q):
|
||||
return 2
|
||||
case strings.Contains(name, q):
|
||||
return 3
|
||||
}
|
||||
return 4 // matched by creator
|
||||
}
|
||||
oldest := field == "id" && direction == "asc"
|
||||
sort.SliceStable(list, func(i, j int) bool {
|
||||
if ri, rj := rank(list[i]), rank(list[j]); ri != rj {
|
||||
return ri < rj
|
||||
}
|
||||
if oldest {
|
||||
return list[i].CreatedAt.Before(list[j].CreatedAt)
|
||||
}
|
||||
return list[i].CreatedAt.After(list[j].CreatedAt)
|
||||
})
|
||||
}
|
||||
|
||||
// categoryIDs reads the shop's category field: IDs separated by commas, as a string or number (empty: all).
|
||||
func categoryIDs(raw json.RawMessage) map[int64]bool {
|
||||
var s string
|
||||
|
||||
Reference in new issue
Block a user