/** * @file llconversationlog.h * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2012, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LLCONVERSATIONLOG_H_ #define LLCONVERSATIONLOG_H_ #include "llcallingcard.h" #include "llfloaterimsession.h" #include "llimview.h" class LLConversationLogObserver; struct ConversationParams; typedef LLIMModel::LLIMSession::SType SessionType; /* * This class represents a particular session(conversation) of any type(im/voice/p2p/group/...) by storing some of session's data. * Each LLConversation object has a corresponding visual representation in a form of LLConversationLogListItem. */ class LLConversation { public: LLConversation(const ConversationParams& params); LLConversation(const LLIMModel::LLIMSession& session); LLConversation(const LLConversation& conversation); ~LLConversation(); const SessionType& getConversationType() const { return mConversationType; } const std::string& getConversationName() const { return mConversationName; } const std::string& getHistoryFileName() const { return mHistoryFileName; } const LLUUID& getSessionID() const { return mSessionID; } const LLUUID& getParticipantID() const { return mParticipantID; } const std::string& getTimestamp() const { return mTimestamp; } const U64Seconds& getTime() const { return mTime; } bool hasOfflineMessages() const { return mHasOfflineIMs; } void setConversationName(const std::string &conv_name) { mConversationName = conv_name; } void setOfflineMessages(bool new_messages) { mHasOfflineIMs = new_messages; } bool isOlderThan(U32Days days) const; /* * updates last interaction time */ void updateTimestamp(); void updateHistoryFileName(const std::string &new_name) { mHistoryFileName = new_name; } /* * Resets flag of unread offline message to false when im floater with this conversation is opened. */ void onIMFloaterShown(const LLUUID& session_id); /* * returns string representation(in form of: mm/dd/yyyy hh:mm) of time when conversation was started */ static const std::string createTimestamp(const U64Seconds& utc_time); private: /* * If conversation has unread offline messages sets callback for opening LLFloaterIMSession * with this conversation. */ void setListenIMFloaterOpened(); boost::signals2::connection mIMFloaterShowedConnection; U64Seconds mTime; // last interaction time SessionType mConversationType; std::string mConversationName; std::string mHistoryFileName; LLUUID mSessionID; LLUUID mParticipantID; bool mHasOfflineIMs; std::string mTimestamp; // last interaction time in form of: mm/dd/yyyy hh:mm }; /** * LLConversationLog stores all agent's conversations. * This class is responsible for creating and storing LLConversation objects when im or voice session starts. * Also this class saves/retrieves conversations to/from file. * * Also please note that it may be several conversations with the same sessionID stored in the conversation log. * To distinguish two conversations with the same sessionID it's also needed to compare their creation date. */ class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver { LLSINGLETON(LLConversationLog); public: void removeConversation(const LLConversation& conversation); /** * Returns first conversation with matched session_id */ const LLConversation* getConversation(const LLUUID& session_id); const std::vector<LLConversation>& getConversations() { return mConversations; } void addObserver(LLConversationLogObserver* observer); void removeObserver(LLConversationLogObserver* observer); // LLIMSessionObserver triggers virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id, bool has_offline_msg) override; virtual void sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) override {}; // Stub virtual void sessionRemoved(const LLUUID& session_id) override{} // Stub virtual void sessionVoiceOrIMStarted(const LLUUID& session_id) override{}; // Stub virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) override{}; // Stub void notifyObservers(); void onNewMessageReceived(const LLSD& data); /** * public method which is called on viewer exit to save conversation log */ void cache(); // will check if current name is edentical with the one on disk and will rename the one on disk if it isn't void verifyFilename(const LLUUID& session_id, const std::string &expected_filename, const std::string &new_session_name); bool moveLog(const std::string &originDirectory, const std::string &targetDirectory); void getListOfBackupLogs(std::vector<std::string>& list_of_backup_logs); void deleteBackupLogs(); void onClearLog(); void onClearLogResponse(const LLSD& notification, const LLSD& response); bool getIsLoggingEnabled() { return mLoggingEnabled; } bool isLogEmpty() { return mConversations.empty(); } /** * inits connection to per account settings, * loads saved file and inits enabled state */ void initLoggingState(); /** * constructs file name in which conversations log will be saved * file name is conversation.log */ std::string getFileName(); LLConversation* findConversation(const LLIMModel::LLIMSession* session); private: virtual ~LLConversationLog() { if (mAvatarNameCacheConnection.connected()) { mAvatarNameCacheConnection.disconnect(); } } void enableLogging(S32 log_mode); /** * adds conversation to the conversation list and notifies observers */ void logConversation(const LLUUID& session_id, bool has_offline_msg); void notifyParticularConversationObservers(const LLUUID& session_id, U32 mask); bool saveToFile(const std::string& filename); bool loadFromFile(const std::string& filename); void onAvatarNameCache(const LLUUID& participant_id, const LLAvatarName& av_name, const LLIMModel::LLIMSession* session); void createConversation(const LLIMModel::LLIMSession* session); void updateConversationTimestamp(LLConversation* conversation); void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name); void updateOfflineIMs(const LLIMModel::LLIMSession* session, bool new_messages); typedef std::vector<LLConversation> conversations_vec_t; std::vector<LLConversation> mConversations; std::set<LLConversationLogObserver*> mObservers; LLFriendObserver* mFriendObserver; // Observer of the LLAvatarTracker instance boost::signals2::connection mNewMessageSignalConnection; boost::signals2::connection mAvatarNameCacheConnection; bool mLoggingEnabled; }; class LLConversationLogObserver { public: enum EConversationChange { CHANGED_TIME = 1, // last interaction time changed CHANGED_NAME = 2, // conversation name changed CHANGED_OfflineIMs = 3 }; virtual ~LLConversationLogObserver(){} virtual void changed() = 0; virtual void changed(const LLUUID& session_id, U32 mask){}; }; #endif /* LLCONVERSATIONLOG_H_ */