sorted channels by latest event

made them into a list like directRooms in Store
This commit is contained in:
Vishal
2022-09-08 18:50:30 +05:30
parent 855b2fe8fe
commit cb8c74bef3
3 changed files with 129 additions and 75 deletions

View File

@ -480,15 +480,21 @@ Future<void> otherMenuUi(Store node) async {
Future<void> channelMenuUI(Store node) async { Future<void> channelMenuUI(Store node) async {
bool continueChatMenu = true; bool continueChatMenu = true;
while(continueChatMenu) { while(continueChatMenu) {
int option = showMenu([ 'Show public channels', // 1
//await processNotifications(node); // this takes 300 ms
node.printAllChannelsInfo(20);
int option = showMenu([ 'Show all public channels', // 1
'Enter a public channel', // 2 'Enter a public channel', // 2
'Go back to main menu'], // 3 'Go back to main menu'], // 3
"Public Channels Menu"); // name of menu "Public Channels Menu"); // name of menu
print('You picked: $option'); print('You picked: $option');
switch(option) { switch(option) {
case 1: case 1:
node.printAllChannelsInfo(); node.printAllChannelsInfo(1000);
break; break;
case 2: case 2:
@ -555,18 +561,23 @@ Future<void> channelMenuUI(Store node) async {
Future<void> PrivateMenuUI(Store node) async { Future<void> PrivateMenuUI(Store node) async {
bool continueChatMenu = true; bool continueChatMenu = true;
while(continueChatMenu) { while(continueChatMenu) {
int option = showMenu([ 'See personal Inbox',
await processNotifications(node); // this takes 300 ms
node.printDirectRoomInfo();
int option = showMenu([
'Reply or Send a direct message', 'Reply or Send a direct message',
'Go back to main menu'], // 3 'Go back to main menu'], // 3
"Private Message Menu"); // name of menu "Private Message Menu"); // name of menu
print('You picked: $option'); print('You picked: $option');
switch(option) { switch(option) {
case 1: // case 1:
//print("total direct rooms = ${node.directRooms.length}"); //print("total direct rooms = ${node.directRooms.length}");
node.printDirectRoomInfo(); // break;
break;
case 2: case 1:
// in case the program was invoked with --pubkey, then user can't send messages // in case the program was invoked with --pubkey, then user can't send messages
if( userPrivateKey == "") { if( userPrivateKey == "") {
print("Since no private key has been supplied, messages and replies can't be sent. Invoke with --prikey \n"); print("Since no private key has been supplied, messages and replies can't be sent. Invoke with --prikey \n");
@ -618,7 +629,7 @@ Future<void> PrivateMenuUI(Store node) async {
} }
break; break;
case 3: case 2:
continueChatMenu = false; continueChatMenu = false;
break; break;

View File

@ -249,7 +249,7 @@ class EventData {
} }
// only applicable for kind 42 event // only applicable for kind 42 event
String getChatRoomId() { String getChannelIdForMessage() {
if( kind != 42) { if( kind != 42) {
return ""; return "";
} }

View File

@ -33,6 +33,16 @@ int getLatestMessageTime(List<String> _messageIds) {
return latest; return latest;
} }
Channel? getChannel(List<Channel> channels, String channelId) {
for( int i = 0; i < channels.length; i++) {
if( channels[i].channelId == channelId) {
return channels[i];
}
}
return null;
}
DirectMessageRoom? getDirectRoom(List<DirectMessageRoom> rooms, String otherPubkey) { DirectMessageRoom? getDirectRoom(List<DirectMessageRoom> rooms, String otherPubkey) {
for( int i = 0; i < rooms.length; i++) { for( int i = 0; i < rooms.length; i++) {
if( rooms[i].otherPubkey == otherPubkey) { if( rooms[i].otherPubkey == otherPubkey) {
@ -42,8 +52,7 @@ DirectMessageRoom? getDirectRoom(List<DirectMessageRoom> rooms, String otherPubk
return null; return null;
} }
int scrollableCompareTo(ScrollableMessages a, ScrollableMessages b) {
int directRoomCompareTo(DirectMessageRoom a, DirectMessageRoom b) {
if( gStore == null) if( gStore == null)
return 0; return 0;
@ -63,7 +72,6 @@ int directRoomCompareTo(DirectMessageRoom a, DirectMessageRoom b) {
} }
class ScrollableMessages { class ScrollableMessages {
String topHeader; String topHeader;
List<String> messageIds; List<String> messageIds;
@ -111,23 +119,46 @@ class ScrollableMessages {
} }
} }
class ChatRoom extends ScrollableMessages { class Channel extends ScrollableMessages {
String chatRoomId; // id of the kind 40 start event String channelId; // id of the kind 40 start event
String internalChatRoomName; String internalChatRoomName;
String about; String about;
String picture; String picture;
ChatRoom(this.chatRoomId, this.internalChatRoomName, this.about, this.picture, List<String> messageIds) : Channel(this.channelId, this.internalChatRoomName, this.about, this.picture, List<String> messageIds) :
super ( internalChatRoomName.isEmpty? chatRoomId: internalChatRoomName + "( " + chatRoomId + " )" , super ( internalChatRoomName.isEmpty? channelId: internalChatRoomName + "( " + channelId + " )" ,
messageIds); messageIds);
//addMessageToChannel(eId, tempChildEventsMap, rooms);
void addMessageToChannel(String messageId, Map<String, Tree> tempChildEventsMap) {
int newEventTime = (tempChildEventsMap[messageId]?.event.eventData.createdAt??0);
if(gDebug> 0) print("channel has ${messageIds.length} messages already. adding new one to it. ");
for(int i = 0; i < messageIds.length; i++) {
int eventTime = (tempChildEventsMap[messageIds[i]]?.event.eventData.createdAt??0);
if( newEventTime < eventTime) {
// shift current i and rest one to the right, and put event Time here
if(gDebug> 0) print("In addMessageToChannel: inserted in middle to channel $channelId ");
messageIds.insert(i, messageId);
return;
}
}
if(gDebug> 0) print("In addMessageToChannel: added to channel $channelId ");
// insert at end
messageIds.add(messageId);
return;
}
String get chatRoomName { String get chatRoomName {
return internalChatRoomName; return internalChatRoomName;
} }
void set chatRoomName(String newName){ void set chatRoomName(String newName){
internalChatRoomName = newName; internalChatRoomName = newName;
super.topHeader = newName + " (${chatRoomId.substring(0,6)})"; super.topHeader = newName + " (${channelId.substring(0,6)})";
} }
} }
@ -161,7 +192,7 @@ void addMessageToDirectRoom(String messageId, Map<String, Tree> tempChildEventsM
room.messageIds.add(messageId); room.messageIds.add(messageId);
return; return;
} }
bool isPrivateMessageRoom() { bool isPrivateMessageRoom() {
@ -429,10 +460,10 @@ class Store {
Map<String, Tree> allChildEventsMap; // has events of kind typesInEventMap Map<String, Tree> allChildEventsMap; // has events of kind typesInEventMap
List<String> eventsWithoutParent; List<String> eventsWithoutParent;
Map<String, ChatRoom> chatRooms = {}; List<Channel> channels = [];
List<DirectMessageRoom> directRooms = []; List<DirectMessageRoom> directRooms = [];
Store(this.topPosts, this.allChildEventsMap, this.eventsWithoutParent, this.chatRooms, this.directRooms) { Store(this.topPosts, this.allChildEventsMap, this.eventsWithoutParent, this.channels, this.directRooms) {
allChildEventsMap.forEach((eventId, tree) { allChildEventsMap.forEach((eventId, tree) {
if( tree.store == null) { if( tree.store == null) {
tree.setStore(this); tree.setStore(this);
@ -442,7 +473,7 @@ class Store {
static const Set<int> typesInEventMap = {0, 1, 3, 4, 5, 7, 40, 42}; // 0 meta, 1 post, 3 follows list, 7 reactions static const Set<int> typesInEventMap = {0, 1, 3, 4, 5, 7, 40, 42}; // 0 meta, 1 post, 3 follows list, 7 reactions
static void handleChannelEvents( Map<String, ChatRoom> rooms, Map<String, Tree> tempChildEventsMap, Event ce) { static void handleChannelEvents( List<Channel> rooms, Map<String, Tree> tempChildEventsMap, Event ce) {
String eId = ce.eventData.id; String eId = ce.eventData.id;
int eKind = ce.eventData.kind; int eKind = ce.eventData.kind;
@ -450,19 +481,19 @@ class Store {
case 42: case 42:
{ {
if( gCheckEventId == ce.eventData.id) print("In handleChannelEvents: processing $gCheckEventId "); if( gCheckEventId == ce.eventData.id) print("In handleChannelEvents: processing $gCheckEventId ");
String chatRoomId = ce.eventData.getChatRoomId(); String channelId = ce.eventData.getChannelIdForMessage();
if( chatRoomId != "") { // sometimes people may forget to give e tags or give wrong tags like #e if( channelId != "") { // sometimes people may forget to give e tags or give wrong tags like #e
if( rooms.containsKey(chatRoomId)) { Channel? channel = getChannel(rooms, channelId);
if( gDebug > 0) print("chat room already exists = $chatRoomId adding event to it" ); if( channel != null) {
if( gDebug > 0) print("chat room already exists = $channelId adding event to it" );
if( gCheckEventId == ce.eventData.id) print("Adding new message $eId to a chat room $chatRoomId. "); if( gCheckEventId == ce.eventData.id) print("Adding new message $eId to a chat room $channelId. ");
addMessageToChannel(chatRoomId, eId, tempChildEventsMap, rooms); channel.addMessageToChannel(eId, tempChildEventsMap);
} else { } else {
if( gCheckEventId == ce.eventData.id) print("Adding new message $eId to NEW chat room $chatRoomId. "); //if( gCheckEventId == ce.eventData.id) print("Adding new message $eId to NEW chat room $channelId. ");
rooms[chatRoomId] = ChatRoom(chatRoomId, "", "", "", []); Channel newChannel = Channel(channelId, "", "", "", [eId]);
addMessageToChannel(chatRoomId, eId, tempChildEventsMap, rooms); rooms.add( newChannel);
} }
} }
} }
@ -473,10 +504,11 @@ class Store {
String chatRoomId = eId; String chatRoomId = eId;
try { try {
dynamic json = jsonDecode(ce.eventData.content); dynamic json = jsonDecode(ce.eventData.content);
if( rooms.containsKey(chatRoomId)) { Channel? channel = getChannel(rooms, chatRoomId);
if( rooms[chatRoomId]?.chatRoomName == "") { if( channel != null) {
if( channel.chatRoomName == "") {
//if( gDebug > 0) print('Added room name = ${json['name']} for $chatRoomId' ); //if( gDebug > 0) print('Added room name = ${json['name']} for $chatRoomId' );
rooms[chatRoomId]?.chatRoomName = json['name']; channel.chatRoomName = json['name'];
} }
} else { } else {
String roomName = "", roomAbout = ""; String roomName = "", roomAbout = "";
@ -488,9 +520,8 @@ class Store {
roomAbout = json['about']; roomAbout = json['about'];
} }
List<String> emptyMessageList = []; List<String> emptyMessageList = [];
ChatRoom room = ChatRoom(chatRoomId, roomName, roomAbout, "", emptyMessageList); Channel room = Channel(chatRoomId, roomName, roomAbout, "", emptyMessageList);
rooms[chatRoomId] = room; rooms.add( room);
//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 ${ce.eventData.id}. error = $e"); if( gDebug > 0) print("In From Event. Event type 40. Json Decode error for event id ${ce.eventData.id}. error = $e");
@ -553,7 +584,7 @@ class Store {
if( events.isEmpty) { if( events.isEmpty) {
List<DirectMessageRoom> temp = []; List<DirectMessageRoom> temp = [];
return Store( [], {}, [], {}, temp); return Store( [], {}, [], [], temp);
} }
// create a map tempChildEventsMap from list of events, key is eventId and value is event itself // create a map tempChildEventsMap from list of events, key is eventId and value is event itself
@ -573,7 +604,7 @@ class Store {
// once tempChildEventsMap has been created, create connections between them so we get a tree structure from all these events. // once tempChildEventsMap has been created, create connections between them so we get a tree structure from all these events.
List<Tree> topLevelTrees = [];// this will become the children of the main top node. These are events without parents, which are printed at top. List<Tree> topLevelTrees = [];// this will become the children of the main top node. These are events without parents, which are printed at top.
List<String> tempWithoutParent = []; List<String> tempWithoutParent = [];
Map<String, ChatRoom> rooms = {}; List<Channel> channels = [];
List<DirectMessageRoom> tempDirectRooms = []; List<DirectMessageRoom> tempDirectRooms = [];
@ -585,7 +616,7 @@ class Store {
tempChildEventsMap.forEach((newEventId, tree) { tempChildEventsMap.forEach((newEventId, tree) {
int eKind = tree.event.eventData.kind; int eKind = tree.event.eventData.kind;
if( eKind == 42 || eKind == 40) { if( eKind == 42 || eKind == 40) {
handleChannelEvents(rooms, tempChildEventsMap, tree.event); handleChannelEvents(channels, tempChildEventsMap, tree.event);
} }
if( eKind == 4) { if( eKind == 4) {
@ -640,7 +671,7 @@ class Store {
if(gDebug != 0) print("In Tree FromEvents: number of events without parent in fromEvents = ${tempWithoutParent.length}"); if(gDebug != 0) print("In Tree FromEvents: number of events without parent in fromEvents = ${tempWithoutParent.length}");
// create a dummy top level tree and then create the main Tree object // create a dummy top level tree and then create the main Tree object
return Store( topLevelTrees, tempChildEventsMap, tempWithoutParent, rooms, tempDirectRooms); return Store( topLevelTrees, tempChildEventsMap, tempWithoutParent, channels, tempDirectRooms);
} // end fromEvents() } // end fromEvents()
/***********************************************************************************************************************************/ /***********************************************************************************************************************************/
@ -754,13 +785,16 @@ class Store {
// add 42 chat message event id to its chat room // add 42 chat message event id to its chat room
String channelId = newTree.event.eventData.getParent(); String channelId = newTree.event.eventData.getParent();
if( channelId != "") { if( channelId != "") {
if( chatRooms.containsKey(channelId)) { Channel? channel = getChannel(channels, channelId);
if( channel != null) {
if( gDebug > 0) print("added event to chat room in insert event"); if( gDebug > 0) print("added event to chat room in insert event");
addMessageToChannel(channelId, newTree.event.eventData.id, allChildEventsMap, chatRooms); // adds in order channel.addMessageToChannel(newTree.event.eventData.id, allChildEventsMap); // adds in order
break; break;
} else { } else {
chatRooms[channelId] = ChatRoom(channelId, "", "", "", []);
addMessageToChannel(channelId, newTree.event.eventData.id, allChildEventsMap, chatRooms); Channel newChannel = Channel(channelId, "", "", "", []);
newChannel.addMessageToChannel(newTree.event.eventData.id, allChildEventsMap);
channels.add(newChannel);
} }
} }
break; break;
@ -915,20 +949,30 @@ class Store {
/** /**
* @printAllChennelsInfo Print one line information about all channels, which are type 40 events ( class ChatRoom) * @printAllChennelsInfo Print one line information about all channels, which are type 40 events ( class ChatRoom)
*/ */
void printAllChannelsInfo() { void printAllChannelsInfo(int numToPrint) {
print("\n\nDirect messages inbox:"); channels.sort(scrollableCompareTo);
print("");
if( numToPrint < channels.length) {
print("Showing only $numToPrint/${channels.length} total channels\n");
} else {
print("Showing all ${channels.length} channels\n");
numToPrint = channels.length;
}
//print("\n\nDirect messages inbox:");
printUnderlined(" Channel Name Num of Messages Latest Message "); printUnderlined(" Channel Name Num of Messages Latest Message ");
chatRooms.forEach((key, value) { for(int j = 0; j < numToPrint; j++) {
String name = "direct room name";
if( value.chatRoomName == "") { String name = "";
name = value.chatRoomId.substring(0, 6); if( channels[j].chatRoomName == "") {
name = channels[j].channelId.substring(0, 6);
} else { } else {
name = "${value.chatRoomName} ( ${value.chatRoomId.substring(0, 6)})"; name = "${channels[j].chatRoomName} ( ${channels[j].channelId.substring(0, 6)})";
} }
int numMessages = value.messageIds.length; int numMessages = channels[j].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 = channels[j].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])) {
Event? e = allChildEventsMap[messageIds[i]]?.event; Event? e = allChildEventsMap[messageIds[i]]?.event;
@ -939,10 +983,10 @@ class Store {
} }
} }
print(""); print("");
}); }
} }
void printChannel(ChatRoom room, [int page = 1]) { void printChannel(Channel room, [int page = 1]) {
if( page < 1) { if( page < 1) {
if( gDebug > 0) log.info("In printChannel got page = $page"); if( gDebug > 0) log.info("In printChannel got page = $page");
page = 1; page = 1;
@ -958,30 +1002,29 @@ class Store {
return ""; return "";
} }
// first check channelsId's, in case user has sent a channelId itself
Set<String> fullChannelId = {}; Set<String> fullChannelId = {};
for( String key in chatRooms.keys) { for(int i = 0; i < channels.length; i++) {
if( key.substring(0, channelId.length) == channelId ) { if( channels[i].channelId.substring(0, channelId.length) == channelId ) {
fullChannelId.add(key); fullChannelId.add(channels[i].channelId);
} }
} }
if(fullChannelId.length != 1) { if(fullChannelId.length != 1) {
for( String key in chatRooms.keys) { for(int i = 0; i < channels.length; i++) {
ChatRoom? room = chatRooms[key]; Channel room = channels[i];
if( room != null) { if( room.chatRoomName.length < channelId.length) {
if( room.chatRoomName.length < channelId.length) { continue;
continue; }
} //if( gDebug > 0) print("room = ${room.chatRoomName} channelId = $channelId");
if( gDebug > 0) print("room = ${room.chatRoomName} channelId = $channelId"); if( room.chatRoomName.substring(0, channelId.length) == channelId ) {
if( room.chatRoomName.substring(0, channelId.length) == channelId ) { fullChannelId.add(room.channelId);
fullChannelId.add(key);
}
} }
} // end for } // end for
} }
if( fullChannelId.length == 1) { if( fullChannelId.length == 1) {
ChatRoom? room = chatRooms[fullChannelId.first]; Channel? room = getChannel( channels, fullChannelId.first);
if( room != null) { if( room != null) {
printChannel(room, page); printChannel(room, page);
} }
@ -1002,7 +1045,7 @@ class Store {
* @printDirectRoomInfo Print one line information about chat rooms * @printDirectRoomInfo Print one line information about chat rooms
*/ */
void printDirectRoomInfo() { void printDirectRoomInfo() {
directRooms.sort(directRoomCompareTo); directRooms.sort(scrollableCompareTo);
print("\n\nDirect messages inbox:"); print("\n\nDirect messages inbox:");
printUnderlined(" From Num of Messages Latest Message "); printUnderlined(" From Num of Messages Latest Message ");
for( int j = 0; j < directRooms.length; j++) { for( int j = 0; j < directRooms.length; j++) {
@ -1439,7 +1482,7 @@ void addMessageToChannel(String channelId, String messageId, Map<String, Tree> t
} }
if( chatRooms.containsKey(channelId)) { if( chatRooms.containsKey(channelId)) {
ChatRoom? room = chatRooms[channelId]; Channel? room = chatRooms[channelId];
if( room != null ) { if( room != null ) {
if( room.messageIds.isEmpty) { if( room.messageIds.isEmpty) {
if(gDebug> 0 || gCheckEventId == messageId) print("room is empty. adding new message and returning. "); if(gDebug> 0 || gCheckEventId == messageId) print("room is empty. adding new message and returning. ");
@ -1454,12 +1497,12 @@ void addMessageToChannel(String channelId, String messageId, Map<String, Tree> t
if( newEventTime < eventTime) { if( newEventTime < eventTime) {
// shift current i and rest one to the right, and put event Time here // shift current i and rest one to the right, and put event Time here
if(gDebug> 0 || gCheckEventId == messageId ) if(gDebug> 0 || gCheckEventId == messageId )
print("In addMessageToChannel: inserted event $messageId at position $i to channel ${room.chatRoomId} "); print("In addMessageToChannel: inserted event $messageId at position $i to channel ${room.channelId} ");
room.messageIds.insert(i, messageId); room.messageIds.insert(i, messageId);
return; return;
} }
} }
if(gDebug> 0 || gCheckEventId == messageId) print("In addMessageToChannel: added to channel ${room.chatRoomId} at end"); if(gDebug> 0 || gCheckEventId == messageId) print("In addMessageToChannel: added to channel ${room.channelId} at end");
// insert at end // insert at end
room.messageIds.add(messageId); room.messageIds.add(messageId);
@ -1511,7 +1554,7 @@ Store getTree(Set<Event> events) {
if(gDebug > 0) log.info("Warning: In printEventsAsTree: events length = 0"); if(gDebug > 0) log.info("Warning: In printEventsAsTree: events length = 0");
List<DirectMessageRoom> temp =[]; List<DirectMessageRoom> temp =[];
return Store([], {}, [], {}, temp); return Store([], {}, [], [], temp);
} }
// remove all events other than kind 0 (meta data), 1(posts replies likes), 3 (contact list), 7(reactions), 40 and 42 (chat rooms) // remove all events other than kind 0 (meta data), 1(posts replies likes), 3 (contact list), 7(reactions), 40 and 42 (chat rooms)