improved tags when replying. reduced sorting burden by not sorting child threads ( by time). top thread still sorted.

This commit is contained in:
vishalxl
2022-08-27 00:25:22 +05:30
parent bb16c30f63
commit 29a925512a

View File

@ -2,12 +2,10 @@ import 'dart:io';
import 'dart:convert'; import 'dart:convert';
import 'package:nostr_console/event_ds.dart'; import 'package:nostr_console/event_ds.dart';
import 'package:nostr_console/settings.dart'; import 'package:nostr_console/settings.dart';
import 'package:bip340/bip340.dart';
typedef fTreeSelector = bool Function(Tree a); typedef fTreeSelector = bool Function(Tree a);
bool selectAll(Tree t) { bool selectAll(Tree t) {
//print("In select all");
return true; return true;
} }
@ -77,37 +75,25 @@ class Tree {
//print("Processing type 40"); //print("Processing type 40");
String chatRoomId = eId; String chatRoomId = eId;
try { try {
//print("Processing type 40 json");
dynamic json = jsonDecode(value.e.eventData.content); dynamic json = jsonDecode(value.e.eventData.content);
//print("Processed type 40 json");
if( rooms.containsKey(chatRoomId)) { if( rooms.containsKey(chatRoomId)) {
//print("in if chatRoomId key in rooms");
if( rooms[chatRoomId]?.name == "") { if( rooms[chatRoomId]?.name == "") {
if( gDebug > 0) print('Added room name = ${json['name']} for $chatRoomId' ); if( gDebug > 0) print('Added room name = ${json['name']} for $chatRoomId' );
rooms[chatRoomId]?.name = json['name']; rooms[chatRoomId]?.name = json['name'];
} }
} else { } else {
List<String> temp = []; List<String> temp = [];
//temp.add(eId);
//print("in else");
//print("json = $json");
String roomName = "", roomAbout = ""; String roomName = "", roomAbout = "";
if( json.containsKey('name') ) { if( json.containsKey('name') ) {
roomName = json['name']; roomName = json['name'];
} }
if( json.containsKey('about')) { if( json.containsKey('about')) {
roomAbout = json['about']; roomAbout = json['about'];
} }
ChatRoom room = ChatRoom(chatRoomId, roomName, roomAbout, "", []); ChatRoom room = ChatRoom(chatRoomId, roomName, roomAbout, "", []);
rooms[chatRoomId] = room; rooms[chatRoomId] = room;
if( gDebug > 0) print("Added new chat room $chatRoomId with name ${json['name']} ."); if( gDebug > 0) print("Added new chat room $chatRoomId with name ${json['name']} .");
} }
} on Exception catch(e) { } on Exception catch(e) {
if( gDebug > 0) print("In From Event. Event type 40. Json Decode error for event id ${value.e.eventData.id}"); if( gDebug > 0) print("In From Event. Event type 40. Json Decode error for event id ${value.e.eventData.id}");
} }
@ -139,6 +125,14 @@ class Tree {
tempChildEventsMap[parentId]?.addChildNode(value); // in this if condition this will get called tempChildEventsMap[parentId]?.addChildNode(value); // in this if condition this will get called
} else { } else {
if( gDebug > 0 && key == "e9c0c91d52a2cf000bb2460406139a99dd5b7823165be435e96433a600be8e41" || parentId == "f377a303a852c8821069714f43b4eef5e341c03892eacf49abb594660b2fbb00") {
print (value.e.eventData.tags);
print("In from json: newId = $key parentid = $parentId for event id = ${value.e.eventData.id}");
print(tempChildEventsMap.containsKey(parentId));
print("----------------------------------------------/constructor from json");
}
// in case where the parent of the new event is not in the pool of all events, // in case where the parent of the new event is not in the pool of all events,
// then we create a dummy event and put it at top ( or make this a top event?) TODO handle so that this can be replied to, and is fetched // then we create a dummy event and put it at top ( or make this a top event?) TODO handle so that this can be replied to, and is fetched
Tree dummyTopNode = Tree(Event("","", Tree dummyTopNode = Tree(Event("","",
@ -230,6 +224,12 @@ class Tree {
} else { } else {
// if it has a parent , then add the newTree as the parent's child // if it has a parent , then add the newTree as the parent's child
String parentId = newTree.e.eventData.getParent(); String parentId = newTree.e.eventData.getParent();
if( gDebug > 0 && newId == "e9c0c91d52a2cf000bb2460406139a99dd5b7823165be435e96433a600be8e41" || parentId == "f377a303a852c8821069714f43b4eef5e341c03892eacf49abb594660b2fbb00") {
print (newTree.e.eventData.tags);
print("In from json: newId = $newId parentid = $parentId for event id = ${newTree.e.eventData.id}");
print(allChildEventsMap.containsKey(parentId));
print("----------------------------------------------/insert events");
}
if( allChildEventsMap.containsKey(parentId)) { if( allChildEventsMap.containsKey(parentId)) {
allChildEventsMap[parentId]?.addChildNode(newTree); allChildEventsMap[parentId]?.addChildNode(newTree);
} else { } else {
@ -366,13 +366,14 @@ class Tree {
int printTree(int depth, var newerThan, fTreeSelector treeSelector) { int printTree(int depth, var newerThan, fTreeSelector treeSelector) {
int numPrinted = 0; int numPrinted = 0;
children.sort(sortTreeNewestReply);
if( !whetherTopMost) { if( !whetherTopMost) {
e.printEvent(depth); e.printEvent(depth);
numPrinted++; numPrinted++;
} else { } else {
depth = depth - 1; depth = depth - 1;
children.sort(sortTreeNewestReply); // sorting done only for top most threads. Lower threads aren't sorted so save cpu etc TODO improve top sorting
} }
bool leftShifted = false; bool leftShifted = false;
@ -388,8 +389,8 @@ class Tree {
continue; continue;
} }
Tree newestChild = children[i].getMostRecent(0); int newestChildTime = children[i].getMostRecentTime(0);
DateTime dTime = DateTime.fromMillisecondsSinceEpoch(newestChild.e.eventData.createdAt *1000); DateTime dTime = DateTime.fromMillisecondsSinceEpoch(newestChildTime *1000);
//print("comparing $newerThan with $dTime"); //print("comparing $newerThan with $dTime");
if( dTime.compareTo(newerThan) < 0) { if( dTime.compareTo(newerThan) < 0) {
continue; continue;
@ -411,8 +412,10 @@ class Tree {
} }
numPrinted += children[i].printTree(depth+1, newerThan, treeSelector); numPrinted += children[i].printTree(depth+1, newerThan, treeSelector);
if( whetherTopMost && gDebug != 0) { if( whetherTopMost && gDebug > 0) {
print(children[i].getMostRecent(0).e.eventData.createdAt); print("");
print(children[i].getMostRecentTime(0));
print("-----");
} }
//if( gDebug > 0) print("at end for loop iteraion: numPrinted = $numPrinted"); //if( gDebug > 0) print("at end for loop iteraion: numPrinted = $numPrinted");
} }
@ -426,18 +429,12 @@ class Tree {
if( whetherTopMost) { if( whetherTopMost) {
print("\n\nTotal posts/replies printed: $numPrinted for last $gNumLastDays days"); print("\n\nTotal posts/replies printed: $numPrinted for last $gNumLastDays days");
} }
return numPrinted; return numPrinted;
} }
void printAllChannelsInfo() { void printAllChannelsInfo() {
print("\n\nChannels/Rooms:"); print("\n\nChannels/Rooms:");
printUnderlined(" Channel/Room Name Num of Messages Latest Message "); printUnderlined(" Channel/Room Name Num of Messages Latest Message ");
//print("");
chatRooms.forEach((key, value) { chatRooms.forEach((key, value) {
String name = ""; String name = "";
if( value.name == "") { if( value.name == "") {
@ -447,9 +444,7 @@ class Tree {
} }
int numMessages = value.messageIds.length; int numMessages = value.messageIds.length;
stdout.write("${name} ${getNumSpaces(32-name.length)} $numMessages${getNumSpaces(12- numMessages.toString().length)}"); stdout.write("${name} ${getNumSpaces(32-name.length)} $numMessages${getNumSpaces(12- numMessages.toString().length)}");
List<String> messageIds = value.messageIds; List<String> messageIds = value.messageIds;
for( int i = messageIds.length - 1; i >= 0; i++) { for( int i = messageIds.length - 1; i >= 0; i++) {
if( allChildEventsMap.containsKey(messageIds[i])) { if( allChildEventsMap.containsKey(messageIds[i])) {
@ -460,9 +455,7 @@ class Tree {
break; // print only one event, the latest one break; // print only one event, the latest one
} }
} }
} }
print(""); print("");
}); });
} }
@ -555,7 +548,6 @@ class Tree {
nLinesStr = ""; nLinesStr = "";
} }
//int len = await file.length();
print("\n\nWrote total $eventCounter events to file \"$gEventsFilename\" of which ${countPosts + 1} are posts.") ; // TODO remove extra 1 print("\n\nWrote total $eventCounter events to file \"$gEventsFilename\" of which ${countPosts + 1} are posts.") ; // TODO remove extra 1
} on Exception catch (err) { } on Exception catch (err) {
print("Could not open file $filename."); print("Could not open file $filename.");
@ -602,10 +594,8 @@ class Tree {
if( pTagPubkey != null) { if( pTagPubkey != null) {
strTags += ',["p","$pTagPubkey"]'; strTags += ',["p","$pTagPubkey"]';
} }
String relay = getRelayOfUser(userPublicKey, pTagPubkey??""); String relay = getRelayOfUser(userPublicKey, pTagPubkey??"");
relay = (relay == "")? defaultServerUrl: relay; relay = (relay == "")? defaultServerUrl: relay;
String rootEventId = ""; String rootEventId = "";
// nip 10: first e tag should be the id of the top/parent event. 2nd ( or last) e tag should be id of the event being replied to. // nip 10: first e tag should be the id of the top/parent event. 2nd ( or last) e tag should be id of the event being replied to.
@ -613,12 +603,13 @@ class Tree {
if( t != null) { if( t != null) {
Tree topTree = getTopTree(t); Tree topTree = getTopTree(t);
rootEventId = topTree.e.eventData.id; rootEventId = topTree.e.eventData.id;
if( rootEventId != latestEventId) { // if the reply is to a top/parent event, then only one e tag is sufficient
strTags += ',["e","$rootEventId"]'; strTags += ',["e","$rootEventId"]';
} }
}
strTags += ',["e","$latestEventId","$relay"]'; strTags += ',["e","$latestEventId","$relay"]';
} }
return strTags; return strTags;
} }
@ -628,7 +619,6 @@ class Tree {
if(e.eventData.pubkey != gDummyAccountPubkey) { if(e.eventData.pubkey != gDummyAccountPubkey) {
totalCount = 1; totalCount = 1;
} }
for(int i = 0; i < children.length; i++) { for(int i = 0; i < children.length; i++) {
totalCount += children[i].count(); // then add all the children totalCount += children[i].count(); // then add all the children
} }
@ -659,33 +649,46 @@ class Tree {
} }
// returns the time of the most recent comment // returns the time of the most recent comment
Tree getMostRecent(int mostRecentTime) { int getMostRecentTime(int mostRecentTime) {
int initial = mostRecentTime;
if( children.isEmpty) { if( children.isEmpty) {
return this; return e.eventData.createdAt;
} }
if( e.eventData.createdAt > mostRecentTime) { if( e.eventData.createdAt > mostRecentTime) {
mostRecentTime = e.eventData.createdAt; mostRecentTime = e.eventData.createdAt;
} }
int mostRecentIndex = -1; int mostRecentIndex = -1;
for( int i = 0; i < children.length; i++) { for( int i = 0; i < children.length; i++) {
int mostRecentChild = children[i].getMostRecent(mostRecentTime).e.eventData.createdAt; int mostRecentChild = children[i].getMostRecentTime(mostRecentTime);
if( mostRecentTime <= mostRecentChild) { if( mostRecentTime <= mostRecentChild) {
if( gDebug > 0 && children[i].e.eventData.id == "970bbd22e63000dc1313867c61a50e0face728139afe6775fa9fe4bc61bdf664") {
print("plantimals 970bbd22e63000dc1313867c61a50e0face728139afe6775fa9fe4bc61bdf664");
print( "children[i].e.eventData. = ${children[i].e.eventData.createdAt} mostRecentChild = $mostRecentChild i = $i mostRecentIndex = $mostRecentIndex mostRecentTime = $mostRecentTime\n");
printTree(0, 0, (a) => true);
print("--------------");
}
mostRecentTime = mostRecentChild; mostRecentTime = mostRecentChild;
mostRecentIndex = i; mostRecentIndex = i;
} }
} }
if( mostRecentIndex == -1) { if( mostRecentIndex == -1) {
Tree top = getTopTree(this);
if( gDebug > 0 ) {
print('\nerror: returning newer child id = ${e.eventData.id}. e.eventData.createdAt = ${e.eventData.createdAt} num child = ${children.length} 1st child time = ${children[0].e.eventData.createdAt} mostRecentTime = $mostRecentTime initial time = $initial ');
print("its top event time and id = time ${top.e.eventData.createdAt} id ${top.e.eventData.id} num tags = ${top.e.eventData.tags} num e tags = ${top.e.eventData.eTagsRest}\n");
top.printTree(0,0, (a) => true);
print("\n-----------------------------------------------------------------------\n");
}
// typically this should not happen. child nodes/events can't be older than parents // typically this should not happen. child nodes/events can't be older than parents
return this; return e.eventData.createdAt;
} else { } else {
return children[mostRecentIndex]; return mostRecentTime;
} }
} }
// returns true if the treee or its children has a post by user // returns true if the treee or its children has a post or like by user; and notification flags are set for such events
bool hasUserPostAndLike(String pubkey) { bool hasUserPostAndLike(String pubkey) {
bool hasReacted = false; bool hasReacted = false;
@ -708,17 +711,13 @@ class Tree {
childMatches = true; childMatches = true;
} }
} }
if( e.eventData.pubkey == pubkey) { if( e.eventData.pubkey == pubkey) {
e.eventData.isNotification = true; e.eventData.isNotification = true;
return true; return true;
} }
if( hasReacted || childMatches) { if( hasReacted || childMatches) {
return true; return true;
} }
return false; return false;
} }
@ -728,8 +727,6 @@ class Tree {
if( e.eventData.content.length > 1000) { if( e.eventData.content.length > 1000) {
return false; return false;
} }
bool childMatches = false; bool childMatches = false;
for( int i = 0; i < children.length; i++ ) { for( int i = 0; i < children.length; i++ ) {
// ignore too large comments // ignore too large comments
@ -746,11 +743,9 @@ class Tree {
e.eventData.isNotification = true; e.eventData.isNotification = true;
return true; return true;
} }
if( childMatches) { if( childMatches) {
return true; return true;
} }
return false; return false;
} }
@ -764,7 +759,6 @@ class Tree {
if( tags[i].length < 2) { if( tags[i].length < 2) {
continue; continue;
} }
if( tags[i][0] == "client" && tags[i][1].contains(clientName)) { if( tags[i][0] == "client" && tags[i][1].contains(clientName)) {
e.eventData.isNotification = true; e.eventData.isNotification = true;
byClient = true; byClient = true;
@ -778,17 +772,13 @@ class Tree {
childMatch = true; childMatch = true;
} }
} }
if( byClient || childMatch) { if( byClient || childMatch) {
return true; return true;
} }
return false; return false;
} }
Event? getContactEvent(String pkey) { Event? getContactEvent(String pkey) {
// get the latest kind 3 event for the user, which lists his 'follows' list // get the latest kind 3 event for the user, which lists his 'follows' list
int latestContactsTime = 0; int latestContactsTime = 0;
String latestContactEvent = ""; String latestContactEvent = "";
@ -812,8 +802,7 @@ class Tree {
return null; return null;
} }
//void create // TODO inefficient; fix
List<String> getFollowers(String pubkey) { List<String> getFollowers(String pubkey) {
if( gDebug > 0) print("Finding followrs for $pubkey"); if( gDebug > 0) print("Finding followrs for $pubkey");
List<String> followers = []; List<String> followers = [];
@ -876,18 +865,14 @@ class Tree {
if( isFollow) { if( isFollow) {
print("* You follow $otherName "); print("* You follow $otherName ");
} }
print("* Of the $numContacts people you follow, $numSecond follow $otherName"); print("* Of the $numContacts people you follow, $numSecond follow $otherName");
} // end if contact event was found } // end if contact event was found
} }
} // end Tree } // end Tree
void addMessageToChannel(String channelId, String messageId, var tempChildEventsMap, var chatRooms) { void addMessageToChannel(String channelId, String messageId, var tempChildEventsMap, var chatRooms) {
//chatRooms[channelId]?.messageIds.add(newTree.e.eventData.id); //chatRooms[channelId]?.messageIds.add(newTree.e.eventData.id);
int newEventTime = (tempChildEventsMap[messageId]?.e.eventData.createdAt??0); int newEventTime = (tempChildEventsMap[messageId]?.e.eventData.createdAt??0);
if( chatRooms.containsKey(channelId)) { if( chatRooms.containsKey(channelId)) {
@ -898,7 +883,6 @@ class Tree {
room.messageIds.add(messageId); room.messageIds.add(messageId);
return; return;
} }
if(gDebug> 0) print("room has ${room.messageIds.length} messages already. adding new one to it. "); if(gDebug> 0) print("room has ${room.messageIds.length} messages already. adding new one to it. ");
for(int i = 0; i < room.messageIds.length; i++) { for(int i = 0; i < room.messageIds.length; i++) {
@ -909,23 +893,18 @@ class Tree {
return; return;
} }
} }
// insert at end // insert at end
room.messageIds.add(messageId); room.messageIds.add(messageId);
return; return;
} else { } else {
print("In addMessageToChannel: could not find room"); print("In addMessageToChannel: could not find room");
} }
} else { } else {
print("In addMessageToChannel: could not find channel id"); print("In addMessageToChannel: could not find channel id");
} }
print("In addMessageToChannel: returning without inserting message"); print("In addMessageToChannel: returning without inserting message");
} }
int ascendingTimeTree(Tree a, Tree b) { int ascendingTimeTree(Tree a, Tree b) {
if(a.e.eventData.createdAt < b.e.eventData.createdAt) { if(a.e.eventData.createdAt < b.e.eventData.createdAt) {
return -1; return -1;
@ -939,18 +918,19 @@ int ascendingTimeTree(Tree a, Tree b) {
// sorter function that looks at the latest event in the whole tree including the/its children // sorter function that looks at the latest event in the whole tree including the/its children
int sortTreeNewestReply(Tree a, Tree b) { int sortTreeNewestReply(Tree a, Tree b) {
int aMostRecent = a.getMostRecent(0).e.eventData.createdAt; int aMostRecent = a.getMostRecentTime(0);
int bMostRecent = b.getMostRecent(0).e.eventData.createdAt; int bMostRecent = b.getMostRecentTime(0);
if(aMostRecent < bMostRecent) { if(aMostRecent < bMostRecent) {
return -1; return -1;
} else { } else {
if( aMostRecent == bMostRecent) { if( aMostRecent == bMostRecent) {
return 0; return 0;
} } else {
}
return 1; return 1;
} }
}
}
// for the given reaction event of kind 7, will update the global gReactions appropriately, returns // for the given reaction event of kind 7, will update the global gReactions appropriately, returns
// the reactedTo event's id, blank if invalid reaction etc // the reactedTo event's id, blank if invalid reaction etc
@ -983,7 +963,6 @@ void processReactions(List<Event> events) {
return; return;
} }
/* /*
* @function getTree Creates a Tree out of these received List of events. * @function getTree Creates a Tree out of these received List of events.
*/ */
@ -1018,4 +997,3 @@ Future<Tree> getTree(List<Event> events) async {
if(gDebug != 0) print("total number of events in main tree = ${node.count()}"); if(gDebug != 0) print("total number of events in main tree = ${node.count()}");
return node; return node;
} }