@decentnetwork/beagle 0.1.92 → 0.1.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/desktop/app.js +1 -1
- package/dist/server.js +59 -9
- package/package.json +1 -1
package/dist/desktop/app.js
CHANGED
package/dist/server.js
CHANGED
|
@@ -75,6 +75,50 @@ async function ensFetchJson(path) {
|
|
|
75
75
|
clearTimeout(timer);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
/** requestedAt / acceptedAt per friend, read from the SDK's own friend store
|
|
79
|
+
* (`<keyFile>.friends.json`, next to the identity). The daemon's friends-list
|
|
80
|
+
* reports neither for a request we sent and only acceptedAt (as lastSeen)
|
|
81
|
+
* otherwise, so a friend just added had no stamp at all and sorted to the
|
|
82
|
+
* bottom — the third time this was reported. The store is the source of
|
|
83
|
+
* truth both backends write, and it is a file in our own config dir, so
|
|
84
|
+
* read it. Cached by mtime: the list is polled every 2.5s per tab. */
|
|
85
|
+
let friendStampsCache = null;
|
|
86
|
+
function friendStoreStamps(keyFile) {
|
|
87
|
+
const empty = new Map();
|
|
88
|
+
if (!keyFile)
|
|
89
|
+
return empty;
|
|
90
|
+
const path = `${keyFile}.friends.json`;
|
|
91
|
+
try {
|
|
92
|
+
const st = statSync(path);
|
|
93
|
+
if (friendStampsCache && friendStampsCache.mtimeMs === st.mtimeMs)
|
|
94
|
+
return friendStampsCache.map;
|
|
95
|
+
const raw = JSON.parse(readFileSync(path, "utf-8"));
|
|
96
|
+
const recs = Array.isArray(raw)
|
|
97
|
+
? raw
|
|
98
|
+
: raw && typeof raw === "object" && Array.isArray(raw.friends)
|
|
99
|
+
? raw.friends
|
|
100
|
+
: Object.values(raw ?? {});
|
|
101
|
+
const map = new Map();
|
|
102
|
+
for (const r of recs) {
|
|
103
|
+
if (!r || typeof r !== "object")
|
|
104
|
+
continue;
|
|
105
|
+
const id = r.userid || r.pubkey;
|
|
106
|
+
if (!id)
|
|
107
|
+
continue;
|
|
108
|
+
map.set(id, {
|
|
109
|
+
requestedAt: typeof r.requestedAt === "number" ? r.requestedAt : undefined,
|
|
110
|
+
acceptedAt: typeof r.acceptedAt === "number" ? r.acceptedAt : undefined,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
friendStampsCache = { mtimeMs: st.mtimeMs, map };
|
|
114
|
+
return map;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Unreadable or absent (a fresh install has no friends yet): whatever we
|
|
118
|
+
// last read, else nothing — the list still renders, just without stamps.
|
|
119
|
+
return friendStampsCache?.map ?? empty;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
78
122
|
/** The record beagle writes for its own name: what the profile page shows
|
|
79
123
|
* (displayName, description) on top of whatever the record already held —
|
|
80
124
|
* wallet binds, socials, avatar, referee — so a profile edit never strips a
|
|
@@ -1966,10 +2010,12 @@ export function startBeagleServer(opts) {
|
|
|
1966
2010
|
beagleVer: beagleVersion(),
|
|
1967
2011
|
};
|
|
1968
2012
|
const fl = (flist.ok ? (flist.data?.friends ?? []) : []);
|
|
2013
|
+
const stamps = friendStoreStamps(opts.callIce?.keyFile);
|
|
1969
2014
|
const peers = fl.map((f) => {
|
|
1970
2015
|
const uid = f.userid ?? "";
|
|
1971
2016
|
const sess = sessByUserid.get(uid);
|
|
1972
2017
|
const status = f.status;
|
|
2018
|
+
const stamp = stamps.get(uid);
|
|
1973
2019
|
const online = status === "connected" || status === "online";
|
|
1974
2020
|
const realName = typeof f.name === "string" && f.name !== uid ? f.name : undefined;
|
|
1975
2021
|
const lm = f.lastMessage;
|
|
@@ -1982,10 +2028,12 @@ export function startBeagleServer(opts) {
|
|
|
1982
2028
|
address: f.address || "",
|
|
1983
2029
|
online,
|
|
1984
2030
|
// Friendship not yet accepted by the other side. Only trusted when
|
|
1985
|
-
// the backend states it explicitly
|
|
1986
|
-
//
|
|
1987
|
-
//
|
|
1988
|
-
|
|
2031
|
+
// the backend states it explicitly: the embedded host's `accepted`,
|
|
2032
|
+
// or the SDK status "requested" that the daemon passes through
|
|
2033
|
+
// (the SDK demotes it the moment the other side proves itself).
|
|
2034
|
+
// Anything else defaults to established, so the banner can never
|
|
2035
|
+
// wrongly appear on an old backend.
|
|
2036
|
+
pending: f.accepted === false || status === "requested",
|
|
1989
2037
|
via: online ? viaFromTransport(sess?.transport) : null,
|
|
1990
2038
|
ping: null,
|
|
1991
2039
|
ip: ipByUserid.get(uid) ?? "",
|
|
@@ -2005,11 +2053,13 @@ export function startBeagleServer(opts) {
|
|
|
2005
2053
|
// The sidebar ranks a friend by the newest of these and the last
|
|
2006
2054
|
// message, so someone you just accepted — or just added — lands
|
|
2007
2055
|
// at the top like a fresh message would, not in a no-history
|
|
2008
|
-
// group at the bottom.
|
|
2009
|
-
//
|
|
2010
|
-
//
|
|
2011
|
-
|
|
2012
|
-
|
|
2056
|
+
// group at the bottom. The backend's own fields first; the SDK's
|
|
2057
|
+
// friend store on disk fills what the backend does not report — a
|
|
2058
|
+
// daemon backend gives only lastSeen (its acceptedAt) and nothing
|
|
2059
|
+
// for a request we sent, which left a just-added friend with no
|
|
2060
|
+
// stamp at all.
|
|
2061
|
+
acceptedAt: f.lastSeen ?? stamp?.acceptedAt ?? 0,
|
|
2062
|
+
requestedAt: f.requestedAt ?? stamp?.requestedAt ?? 0,
|
|
2013
2063
|
wire: "163",
|
|
2014
2064
|
avatarUrl: ensPub.get(uid)?.avatarUrl ?? null,
|
|
2015
2065
|
// What they advertised over Carrier wins over the directory: it is
|
package/package.json
CHANGED