diff --git a/README.md b/README.md index c53e986..323b183 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ usage: dart run bin/nostr_console.dart [OPTIONS] UI Options -a, --align When "left" is given as option to this argument, then the text is aligned to left. By default the posts or text is aligned to the center of the terminal. - -w, --width This specifies how wide you want the text to be, in number of columns. Default is 120. + -w, --width This specifies how wide you want the text to be, in number of columns. Default is 100. Cant be less than 60. -m, --maxdepth The maximum depth to which the threads can be displayed. Minimum is 2 and maximum allowed is 12. diff --git a/lib/console_ui.dart b/lib/console_ui.dart index 470fd3a..ed756b8 100644 --- a/lib/console_ui.dart +++ b/lib/console_ui.dart @@ -195,7 +195,7 @@ void readjustAlignment() { void printProfile(Store node, String profilePubkey) { - bool onlyUserPostAndLike (Tree t) => t.hasUserPostAndLike(profilePubkey); + bool onlyUserPostAndLike (Tree t) => t.treeSelectorUserPostAndLike(profilePubkey); node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), onlyUserPostAndLike); // get the latest kind 3 event for the user, which lists his 'follows' list @@ -325,7 +325,7 @@ Future otherMenuUi(Store node) async { String? $tempWords = stdin.readLineSync(); String clientName = $tempWords??""; if( clientName != "") { - bool fromClient (Tree t) => t.fromClientSelector(clientName); + bool fromClient (Tree t) => t.treeSelectorClientName(clientName); node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), fromClient); // search for last gNumLastDays only } break; @@ -335,7 +335,7 @@ Future otherMenuUi(Store node) async { String? $tempWords = stdin.readLineSync(); String words = $tempWords??""; if( words != "") { - bool onlyWords (Tree t) => t.hasWords(words.toLowerCase()); + bool onlyWords (Tree t) => t.treeSelectorHasWords(words.toLowerCase()); node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), onlyWords); // search for last gNumLastDays only } else print("Blank word entered. Try again."); break; @@ -673,9 +673,9 @@ Future mainMenuUi(Store node) async { //Show only notifications - //bool hasRepliesAndLikes (Tree t) => t.hasRepliesAndLikes(userPublicKey); - //node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), hasRepliesAndLikes); - //print("\n"); + bool hasNotifications (Tree t) => t.treeSelectorNotifications(); + node.printTree(0, DateTime.now().subtract(Duration(days:gNumLastDays)), hasNotifications); + print("\n"); bool showNotifications (ScrollableMessages room) => room.selectorNotifications(); int numDirectRoomsPrinted = node.printDirectRoomInfo(showNotifications); diff --git a/lib/event_ds.dart b/lib/event_ds.dart index 203482d..5fd8ce0 100644 --- a/lib/event_ds.dart +++ b/lib/event_ds.dart @@ -57,7 +57,7 @@ class EventData { List> tags; bool isNotification; // whether its to be highlighted using highlight color String evaluatedContent; // content which has mentions expanded, and which has been translated - Set newLikes; // user for notifications, are colored as notifications and then reset + Set newLikes; // used for notifications, are colored as notifications and then reset List contactList = []; // used for kind:3 events, which is contact list event diff --git a/lib/settings.dart b/lib/settings.dart index d788b1d..e6821f7 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -88,7 +88,7 @@ const String gDummyAccountPubkey = "Non"; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// UI and Color related settings const int gMinValidTextWidth = 60; // minimum text width acceptable -const int gDefaultTextWidth = 120; // default text width +const int gDefaultTextWidth = 100; // default text width int gTextWidth = gDefaultTextWidth; // is changed by --width option const int gSpacesPerDepth = 4; // constant int gNumLeftMarginSpaces = 0;// this number is modified in main diff --git a/lib/tree_ds.dart b/lib/tree_ds.dart index 2ac9a25..28730de 100644 --- a/lib/tree_ds.dart +++ b/lib/tree_ds.dart @@ -251,18 +251,12 @@ class Tree { int printTree(int depth, DateTime newerThan, bool topPost) { int numPrinted = 0; - //if( event.eventData.pubkey != gDummyAccountPubkey) { // don't print dummy events - event.printEvent(depth, topPost); - numPrinted++; - //} + event.printEvent(depth, topPost); + numPrinted++; bool leftShifted = false; for( int i = 0; i < children.length; i++) { - //stdout.write("\n"); - //printDepth(depth+1); - //stdout.write("│"); - // if the thread becomes too 'deep' then reset its depth, so that its // children will not be displayed too much on the right, but are shifted // left by about places @@ -312,8 +306,7 @@ class Tree { } // returns true if the treee or its children has a reply or like for the user with public key pk; and notification flags are set for such events - bool hasRepliesAndLikes(String pk) { - //print("----- pk = $pk"); + bool treeSelectorRepliesAndLikes(String pk) { bool hasReaction = false; bool childMatches = false; @@ -321,7 +314,7 @@ class Tree { List>? reactions = gReactions[event.eventData.id]; if( reactions != null) { if( reactions.length > 0) { - //print("has reactions"); + // has reactions reactions.forEach((reaction) { // dont add notificatoin for self reaction Event? reactorEvent = store?.allChildEventsMap[reaction[0]]?.event; @@ -346,13 +339,12 @@ class Tree { } for( int i = 0; i < children.length; i++ ) { - if( children[i].hasRepliesAndLikes(pk)) { + if( children[i].treeSelectorRepliesAndLikes(pk)) { childMatches = true; } } if( hasReaction || childMatches) { - //print("returning true"); return true; } return false; @@ -360,7 +352,7 @@ class Tree { // 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 treeSelectorUserPostAndLike(String pubkey) { bool hasReacted = false; if( gReactions.containsKey(event.eventData.id)) { @@ -378,7 +370,7 @@ class Tree { bool childMatches = false; for( int i = 0; i < children.length; i++ ) { - if( children[i].hasUserPostAndLike(pubkey)) { + if( children[i].treeSelectorUserPostAndLike(pubkey)) { childMatches = true; } } @@ -393,7 +385,7 @@ class Tree { } // returns true if the given words exists in it or its children - bool hasWords(String word) { + bool treeSelectorHasWords(String word) { if( event.eventData.content.length > 2000) { // ignore if content is too large, takes lot of time return false; } @@ -405,7 +397,7 @@ class Tree { continue; } - if( children[i].hasWords(word)) { + if( children[i].treeSelectorHasWords(word)) { childMatches = true; } } @@ -421,8 +413,7 @@ class Tree { } // returns true if the event or any of its children were made from the given client, and they are marked for notification - bool fromClientSelector(String clientName) { - //if(gDebug > 0) print("In tree selector hasWords: this id = ${e.eventData.id} word = $word"); + bool treeSelectorClientName(String clientName) { bool byClient = false; List> tags = event.eventData.tags; @@ -439,15 +430,35 @@ class Tree { bool childMatch = false; for( int i = 0; i < children.length; i++ ) { - if( children[i].fromClientSelector(clientName)) { + if( children[i].treeSelectorClientName(clientName)) { childMatch = true; } } if( byClient || childMatch) { - //print("SOME matched $clientName "); return true; } - //print("none matched $clientName "); + + return false; + } + + // returns true if the event or any of its children were made from the given client, and they are marked for notification + bool treeSelectorNotifications() { + + bool hasNotifications = false; + if( event.eventData.isNotification || event.eventData.newLikes.length > 0) { + hasNotifications = true; + } + + bool childMatch = false; + for( int i = 0; i < children.length; i++ ) { + if( children[i].treeSelectorNotifications()) { + childMatch = true; + break; + } + } + if( hasNotifications || childMatch) { + return true; + } return false; } @@ -963,7 +974,8 @@ class Store { numPrinted += topPosts[i].printTree(depth+1, newerThan, true); } - print("\n\nTotal posts/replies printed: $numPrinted for last $gNumLastDays days"); + if( numPrinted > 0) + print("\n\nTotal posts/replies printed: $numPrinted for last $gNumLastDays days"); return numPrinted; } @@ -1513,6 +1525,11 @@ class Store { } List temp = [reactorPubkey, comment]; gReactions[reactedTo]?.add(temp); + if( event.eventData.isNotification) { + // if the reaction is new ( a notification) then the comment it is reacting to also becomes a notification in form of newLikes + tempChildEventsMap[reactedTo]?.event.eventData.newLikes.add(reactorPubkey); + //tempChildEventsMap[reactedTo]?.event.eventData.isNotification = true; + } } else { // first reaction to this event, create the entry in global map List> newReactorList = [];