New binary log format, with color/face support
Binary logs are no longer stored as a single message with a list of strings and int64s ("body", "user_name", "user_id", "when"), but a message with sub-messages (IM_MESSAGE_RECEIVED) verbatim saved. This has the main benefit of preserving message formatting (coloring, bold, italics, etc).
This commit is contained in:
parent
5aeaf9284f
commit
8512e9ad03
|
@ -76,9 +76,8 @@ enum im_what_code {
|
||||||
If chat_id is ommitted, the message is sent to the protocol's system
|
If chat_id is ommitted, the message is sent to the protocol's system
|
||||||
buffer, rather than a specific conversation.
|
buffer, rather than a specific conversation.
|
||||||
face_start and face_length specify the location of formatted text in
|
face_start and face_length specify the location of formatted text in
|
||||||
the body, and "face" is the desired font face. Unsupported in bulk,
|
the body, and "face" is the desired font face.
|
||||||
color_* works much the same, but with colors. Not much else to say.
|
color_* works much the same, but with colors. Not much else to say.
|
||||||
i.e., IM_LOGS_RECEIVED.
|
|
||||||
Requires: String "body"
|
Requires: String "body"
|
||||||
Allows: String "chat_id", String "user_id", String "user_name",
|
Allows: String "chat_id", String "user_id", String "user_name",
|
||||||
int32s "face_start", int32s "face_length", uint16s "face"
|
int32s "face_start", int32s "face_length", uint16s "face"
|
||||||
|
@ -87,9 +86,8 @@ enum im_what_code {
|
||||||
IM_MESSAGE_RECEIVED = 22,
|
IM_MESSAGE_RECEIVED = 22,
|
||||||
|
|
||||||
/*! Logs received →App
|
/*! Logs received →App
|
||||||
Without "when" (a time_t), the logged message will lack a timestamp
|
Should be a message with several sub-messages of IM_MESSAGE_RECEIVED.
|
||||||
Requires: Strings "chat_id", Strings "user_id", Strings "body"
|
Requires: Messages "message" */
|
||||||
Accepts: in64s "when" */
|
|
||||||
IM_LOGS_RECEIVED = 23,
|
IM_LOGS_RECEIVED = 23,
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,6 @@ Conversation::ImMessage(BMessage* msg)
|
||||||
if (icon == NULL)
|
if (icon == NULL)
|
||||||
icon = ProtocolBitmap();
|
icon = ProtocolBitmap();
|
||||||
|
|
||||||
|
|
||||||
BNotification notification(B_INFORMATION_NOTIFICATION);
|
BNotification notification(B_INFORMATION_NOTIFICATION);
|
||||||
notification.SetGroup(BString(APP_NAME));
|
notification.SetGroup(BString(APP_NAME));
|
||||||
notification.SetTitle(notifyTitle);
|
notification.SetTitle(notifyTitle);
|
||||||
|
@ -402,7 +401,6 @@ Conversation::GetView()
|
||||||
BMessage logMsg;
|
BMessage logMsg;
|
||||||
if (_GetChatLogs(&logMsg) == B_OK)
|
if (_GetChatLogs(&logMsg) == B_OK)
|
||||||
fChatView->MessageReceived(&logMsg);
|
fChatView->MessageReceived(&logMsg);
|
||||||
|
|
||||||
return fChatView;
|
return fChatView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,66 +497,42 @@ Conversation::_WarnUser(BString message)
|
||||||
void
|
void
|
||||||
Conversation::_LogChatMessage(BMessage* msg)
|
Conversation::_LogChatMessage(BMessage* msg)
|
||||||
{
|
{
|
||||||
|
// Binary logs
|
||||||
|
// TODO: Don't hardcode 31, expose maximum as a setting
|
||||||
|
const int32 MAX = 31;
|
||||||
|
|
||||||
|
BMessage logMsg(IM_MESSAGE);
|
||||||
|
if (_GetChatLogs(&logMsg) != B_OK) {
|
||||||
|
logMsg.what = IM_MESSAGE;
|
||||||
|
logMsg.AddInt32("im_what", IM_LOGS_RECEIVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessage last;
|
||||||
|
if (logMsg.FindMessage("message", MAX, &last) == B_OK)
|
||||||
|
logMsg.RemoveData("message", 0);
|
||||||
|
msg->AddInt64("when", time(NULL));
|
||||||
|
logMsg.AddMessage("message", msg);
|
||||||
|
|
||||||
|
BFile logFile(fCachePath.Path(), B_READ_WRITE | B_OPEN_AT_END | B_CREATE_FILE);
|
||||||
|
WriteAttributeMessage(&logFile, "Chat:logs", &logMsg);
|
||||||
|
|
||||||
|
// Plain-text logs
|
||||||
|
// Gotta make sure the formatting's pretty!
|
||||||
BString date;
|
BString date;
|
||||||
fDateFormatter.Format(date, time(0), B_SHORT_DATE_FORMAT, B_MEDIUM_TIME_FORMAT);
|
fDateFormatter.Format(date, time(0), B_SHORT_DATE_FORMAT, B_MEDIUM_TIME_FORMAT);
|
||||||
|
|
||||||
BString id = msg->FindString("user_id");
|
BString id = msg->FindString("user_id");
|
||||||
BString name = msg->FindString("user_name");
|
BString name = msg->FindString("user_name");
|
||||||
BString body = msg->FindString("body");
|
BString body = msg->FindString("body");
|
||||||
|
|
||||||
if (id.IsEmpty() == true)
|
if (id.IsEmpty() == true && name.IsEmpty() == true)
|
||||||
return;
|
return;
|
||||||
|
else if (name.IsEmpty() == true) {
|
||||||
if (name.IsEmpty() == true) {
|
|
||||||
User* user = UserById(id);
|
User* user = UserById(id);
|
||||||
if (user == NULL)
|
name = user ? user->GetName() : id;
|
||||||
name = id;
|
|
||||||
else
|
|
||||||
name = user->GetName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary logs
|
|
||||||
// TODO: Don't hardcode 31, expose maximum as a setting
|
|
||||||
int32 max = 31;
|
|
||||||
BStringList user_ids, user_names, bodies;
|
|
||||||
int64 times[max] = { 0 };
|
|
||||||
times[0] = (int64)time(NULL);
|
|
||||||
|
|
||||||
BMessage logMsg;
|
|
||||||
if (_GetChatLogs(&logMsg) == B_OK) {
|
|
||||||
logMsg.FindStrings("body", &bodies);
|
|
||||||
logMsg.FindStrings("user_id", &user_ids);
|
|
||||||
logMsg.FindStrings("user_name", &user_names);
|
|
||||||
|
|
||||||
int64 found;
|
|
||||||
for (int i = 0; i < max; i++)
|
|
||||||
if (logMsg.FindInt64("when", i, &found) == B_OK)
|
|
||||||
times[i + 1] = found;
|
|
||||||
|
|
||||||
bodies.Remove(max);
|
|
||||||
user_ids.Remove(max);
|
|
||||||
user_names.Remove(max);
|
|
||||||
bodies.Add(body, 0);
|
|
||||||
user_ids.Add(id, 0);
|
|
||||||
user_names.Add(name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BMessage newLogMsg(IM_MESSAGE);
|
|
||||||
newLogMsg.AddInt32("im_what", IM_LOGS_RECEIVED);
|
|
||||||
newLogMsg.AddStrings("body", bodies);
|
|
||||||
newLogMsg.AddStrings("user_id", user_ids);
|
|
||||||
newLogMsg.AddStrings("user_name", user_names);
|
|
||||||
newLogMsg.AddInt64("when", time(NULL));
|
|
||||||
for (int i = 0; i < max; i++)
|
|
||||||
newLogMsg.AddInt64("when", times[i]);
|
|
||||||
|
|
||||||
BFile logFile(fCachePath.Path(), B_READ_WRITE | B_OPEN_AT_END | B_CREATE_FILE);
|
|
||||||
WriteAttributeMessage(&logFile, "Chat:logs", &newLogMsg);
|
|
||||||
|
|
||||||
// Plain-text logs
|
|
||||||
BString logLine("[");
|
BString logLine("[");
|
||||||
logLine << date << "] <" << name << "> " << body << "\n";
|
logLine << date << "] <" << name << "> " << body << "\n";
|
||||||
|
|
||||||
logFile.Write(logLine.String(), logLine.Length());
|
logFile.Write(logLine.String(), logLine.Length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,9 +541,7 @@ status_t
|
||||||
Conversation::_GetChatLogs(BMessage* msg)
|
Conversation::_GetChatLogs(BMessage* msg)
|
||||||
{
|
{
|
||||||
_EnsureCachePath();
|
_EnsureCachePath();
|
||||||
|
|
||||||
BFile logFile(fCachePath.Path(), B_READ_WRITE | B_CREATE_FILE);
|
BFile logFile(fCachePath.Path(), B_READ_WRITE | B_CREATE_FILE);
|
||||||
|
|
||||||
return ReadAttributeMessage(&logFile, "Chat:logs", msg);
|
return ReadAttributeMessage(&logFile, "Chat:logs", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +553,6 @@ Conversation::_CacheRoomFlags()
|
||||||
BFile cacheFile(fCachePath.Path(), B_READ_WRITE | B_CREATE_FILE);
|
BFile cacheFile(fCachePath.Path(), B_READ_WRITE | B_CREATE_FILE);
|
||||||
if (cacheFile.InitCheck() != B_OK)
|
if (cacheFile.InitCheck() != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cacheFile.WriteAttr("Chat:flags", B_INT32_TYPE, 0, &fRoomFlags, sizeof(int32));
|
cacheFile.WriteAttr("Chat:flags", B_INT32_TYPE, 0, &fRoomFlags, sizeof(int32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +564,6 @@ Conversation::_LoadRoomFlags()
|
||||||
BFile cacheFile(fCachePath.Path(), B_READ_ONLY);
|
BFile cacheFile(fCachePath.Path(), B_READ_ONLY);
|
||||||
if (cacheFile.InitCheck() != B_OK)
|
if (cacheFile.InitCheck() != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cacheFile.ReadAttr("Chat:flags", B_INT32_TYPE, 0, &fRoomFlags, sizeof(int32));
|
cacheFile.ReadAttr("Chat:flags", B_INT32_TYPE, 0, &fRoomFlags, sizeof(int32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -393,6 +393,15 @@ ConversationView::_AppendOrEnqueueMessage(BMessage* msg)
|
||||||
// later [AttachedToWindow()], since you can't edit an unattached
|
// later [AttachedToWindow()], since you can't edit an unattached
|
||||||
// RenderView.
|
// RenderView.
|
||||||
if (Window() == NULL) {
|
if (Window() == NULL) {
|
||||||
|
// If contains multiple chat messages (e.g., IM_LOGS_RECEIVED), add all
|
||||||
|
int32 i = -1;
|
||||||
|
BMessage text;
|
||||||
|
while (msg->FindMessage("message", i + 1, &text) == B_OK) {
|
||||||
|
fMessageQueue.AddItem(new BMessage(text));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// Else, add the lonely, lonely, single-messaged one
|
||||||
|
if (i == -1)
|
||||||
fMessageQueue.AddItem(new BMessage(*msg));
|
fMessageQueue.AddItem(new BMessage(*msg));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -412,62 +421,7 @@ ConversationView::_AppendMessage(BMessage* msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// … else we're jamming a message into this view no matter what it takes!
|
// Otherwise, it's message time!
|
||||||
if (msg->HasInt32("face_start") || msg->HasInt32("color_start")) {
|
|
||||||
_AppendFormattedMessage(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For unformatted (normal or bulk) messages
|
|
||||||
BStringList user_ids, user_names, bodies;
|
|
||||||
if (msg->FindStrings("body", &bodies) != B_OK)
|
|
||||||
return;
|
|
||||||
msg->FindStrings("user_id", &user_ids);
|
|
||||||
msg->FindStrings("user_name", &user_names);
|
|
||||||
|
|
||||||
for (int i = bodies.CountStrings(); i >= 0; i--) {
|
|
||||||
User* sender = NULL;
|
|
||||||
if (fConversation != NULL)
|
|
||||||
sender = fConversation->UserById(user_ids.StringAt(i));
|
|
||||||
BString sender_id = user_ids.StringAt(i);
|
|
||||||
BString sender_name = user_names.StringAt(i);
|
|
||||||
BString body = bodies.StringAt(i);
|
|
||||||
rgb_color userColor = ui_color(B_PANEL_TEXT_COLOR);
|
|
||||||
int64 timeInt;
|
|
||||||
|
|
||||||
if (msg->FindInt64("when", i, &timeInt) != B_OK)
|
|
||||||
timeInt = (int64)time(NULL);
|
|
||||||
|
|
||||||
if (sender != NULL) {
|
|
||||||
sender_name = sender->GetName();
|
|
||||||
userColor = sender->fItemColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sender_name.IsEmpty() == true && sender_id.IsEmpty() == false)
|
|
||||||
sender_name = sender_id;
|
|
||||||
|
|
||||||
if (sender_id.IsEmpty() == true && sender_name.IsEmpty() == true) {
|
|
||||||
fReceiveView->AppendGeneric(body.String());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (body.StartsWith("/me ")) {
|
|
||||||
BString meMsg = "** ";
|
|
||||||
meMsg << sender_name.String() << " ";
|
|
||||||
meMsg << body.RemoveFirst("/me ");
|
|
||||||
fReceiveView->AppendGeneric(meMsg.String());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fReceiveView->AppendMessage(sender_name.String(), body.String(),
|
|
||||||
userColor, (time_t)timeInt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ConversationView::_AppendFormattedMessage(BMessage* msg)
|
|
||||||
{
|
|
||||||
int64 timeInt;
|
int64 timeInt;
|
||||||
BString user_id;
|
BString user_id;
|
||||||
BString user_name = msg->FindString("user_name");
|
BString user_name = msg->FindString("user_name");
|
||||||
|
@ -496,6 +450,13 @@ ConversationView::_AppendFormattedMessage(BMessage* msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (body.StartsWith("/me ")) {
|
||||||
|
BString meMsg = "** ";
|
||||||
|
meMsg << user_name.String() << " ";
|
||||||
|
meMsg << body.RemoveFirst("/me ");
|
||||||
|
fReceiveView->AppendGeneric(meMsg.String());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fReceiveView->AppendTimestamp(timeInt);
|
fReceiveView->AppendTimestamp(timeInt);
|
||||||
fReceiveView->AppendUserstamp(user_name, userColor);
|
fReceiveView->AppendUserstamp(user_name, userColor);
|
||||||
|
|
|
@ -57,7 +57,6 @@ private:
|
||||||
|
|
||||||
bool _AppendOrEnqueueMessage(BMessage* msg);
|
bool _AppendOrEnqueueMessage(BMessage* msg);
|
||||||
void _AppendMessage(BMessage* msg);
|
void _AppendMessage(BMessage* msg);
|
||||||
void _AppendFormattedMessage(BMessage* msg);
|
|
||||||
|
|
||||||
// Helper functions for _AppendFormattedMessage()
|
// Helper functions for _AppendFormattedMessage()
|
||||||
void _EnableStartingFaces(BMessage* msg, int32 index,
|
void _EnableStartingFaces(BMessage* msg, int32 index,
|
||||||
|
|
Ŝarĝante…
Reference in New Issue