integrar la 1.3.5 del dev y perfiles Minimo, Acampada y Activista

Lo del dev, tal cual desde el nodejs-project de su APK oficial 1.3.5, mezclado
a tres bandas con la 1.3.3 como base. Lo que no habiamos tocado se coge entero.

Conflictos:
- backend.js: su middleware nuevo de media va delante de nuestro router.
- main_views.js y bookmark_view.js: lo suyo. Su menu de tarjeta (⋯) ya aparta
  borrar del pulgar, que era lo que hacia nuestro cambio.
- settings_view.js y tribes_view.js: lo suyo mas nuestra linea de enganche.

La 1.3.5 trae una cabecera de modulo para el movil (apkModbar) que se lleva la
primera caja de fichas, el buscador y los contadores. Con el skin Activista su
CSS (OasisMobile.css) no se carga: se le da estilo en mobile_ux.css, los avisos
suben encima con order y se ajusta la cabecera nueva de las tarjetas. Filtrar
va ahora dentro de la caja de fichas (casilla + etiqueta) para viajar con ella.

Perfiles: Minimo (6 modulos, de serie), Acampada (16), Activista (24, con
tribus, votaciones, campañas, encuestas y tareas) y despues los del dev por
numero de modulos.
This commit is contained in:
hacklab 2026-10-22 12:12:20 +02:00
parent ff91ef938c
commit 83f26ba19e
157 changed files with 6633 additions and 4710 deletions

View file

@ -57,7 +57,7 @@ const hasBidder = (poll, userId) => {
return false
}
module.exports = ({ cooler, tribeCrypto }) => {
module.exports = ({ cooler, cryptoModel }) => {
let ssb
const openSsb = async () => {
if (!ssb) ssb = await cooler.open()
@ -196,9 +196,9 @@ module.exports = ({ cooler, tribeCrypto }) => {
return new Promise((resolve, reject) => {
ssbClient.publish(itemContent, (err, res) => {
if (err) return reject(err)
if (res && res.key && tribeCrypto) {
const key = tribeCrypto.generateTribeKey()
tribeCrypto.setKey(res.key, key, 1)
if (res && res.key && cryptoModel) {
const key = cryptoModel.generateKey()
cryptoModel.setKey(res.key, key, 1)
}
resolve(res)
})
@ -353,7 +353,7 @@ module.exports = ({ cooler, tribeCrypto }) => {
includesShipping: !!c.includesShipping,
stock,
deadline: c.deadline || null,
auctions_poll: (tribeCrypto && tribeCrypto.getKey(rootId)) ? poll : [],
auctions_poll: (cryptoModel && cryptoModel.getKey(rootId)) ? poll : [],
mapUrl: c.mapUrl || "",
shopProductId: c.shopProductId || "",
shopId: c.shopId || "",
@ -458,7 +458,7 @@ module.exports = ({ cooler, tribeCrypto }) => {
includesShipping: !!c.includesShipping,
stock,
deadline: c.deadline,
auctions_poll: (tribeCrypto && tribeCrypto.getKey(rootId)) ? poll : [],
auctions_poll: (cryptoModel && cryptoModel.getKey(rootId)) ? poll : [],
mapUrl: c.mapUrl || "",
shopProductId: c.shopProductId || "",
shopId: c.shopId || "",
@ -505,6 +505,42 @@ module.exports = ({ cooler, tribeCrypto }) => {
return changed
},
async createOrder(itemId, details = {}) {
const ssbClient = await openSsb()
const me = ssbClient.id
const item = await this.getItemById(itemId)
if (!item) throw new Error("Item not found")
if (item.seller === me) throw new Error("You cannot buy your own item")
const content = {
type: "marketOrder",
itemId: item.rootId || item.id,
seller: item.seller,
title: String(item.title || ""),
price: String(item.price || ""),
deliveryAddress: String(details.deliveryAddress || ""),
contact: String(details.contact || ""),
notes: String(details.notes || ""),
createdAt: new Date().toISOString()
}
return new Promise((res, rej) => ssbClient.private.publish(content, [me, item.seller], (e, m) => e ? rej(e) : res(m)))
},
async listOrders(itemId) {
const ssbClient = await openSsb()
const me = ssbClient.id
const item = await this.getItemById(itemId)
if (!item) return []
const rootId = item.rootId || item.id
const msgs = await readTyped(ssbClient, ["marketOrder"], { limit: logLimit, withPrivate: true })
return msgs
.filter(m => {
const c = m && m.value && m.value.content
return m.value.private === true && c && c.type === "marketOrder" && c.itemId === rootId && c.seller === item.seller && (item.seller === me || m.value.author === me)
})
.map(m => ({ id: m.key, buyer: m.value.author, ts: m.value.timestamp || 0, deliveryAddress: m.value.content.deliveryAddress || "", contact: m.value.content.contact || "", notes: m.value.content.notes || "" }))
.sort((a, b) => b.ts - a.ts)
},
async getItemByShopProductId(shopProductId) {
if (!shopProductId) return null
const items = await this.listAllItems("all")