TizenRefApp-9346 Refactor MsgComposer 68/150768/2
authorDenis Dolzhenko <d.dolzhenko@samsung.com>
Mon, 18 Sep 2017 11:10:25 +0000 (14:10 +0300)
committerDenis Dolzhenko <d.dolzhenko@samsung.com>
Mon, 18 Sep 2017 12:05:20 +0000 (15:05 +0300)
Change-Id: I294babd6a5c99ec4bc69a19531cc4aec64329382
Signed-off-by: Denis Dolzhenko <d.dolzhenko@samsung.com>
20 files changed:
src/Common/AppControl/inc/InputSelector.h
src/Common/AppControl/src/InputSelector.cpp
src/Common/Controller/inc/App.h
src/Common/Controller/inc/NaviFrameController.h
src/Common/Controller/src/NaviFrameController.cpp
src/Composer/Controller/inc/Composer.h [deleted file]
src/Composer/Controller/inc/MsgComposerController.h [new file with mode: 0644]
src/Composer/Controller/inc/MsgInputController.h [new file with mode: 0644]
src/Composer/Controller/inc/MsgInputSelector.h [deleted file]
src/Composer/Controller/inc/MsgSenderController.h [new file with mode: 0644]
src/Composer/Controller/inc/RecipFrame.h
src/Composer/Controller/src/Composer.cpp [deleted file]
src/Composer/Controller/src/MsgComposerController.cpp [new file with mode: 0644]
src/Composer/Controller/src/MsgInputController.cpp [new file with mode: 0644]
src/Composer/Controller/src/MsgInputSelector.cpp [deleted file]
src/Composer/Controller/src/MsgSenderController.cpp [new file with mode: 0644]
src/Composer/Controller/src/RecipFrame.cpp
src/Conversation/Controller/src/ConvFrame.cpp
src/Conversation/Controller/src/ConvListItem.cpp
src/MsgThread/Controller/src/MsgThreadFrame.cpp

index 1e1806b380e8aaa4f7ccbc15df36b837ee092f92..e4e0d516ac5163945209b91d199c8f3a50dfa1e9 100644 (file)
@@ -45,17 +45,9 @@ namespace Msg {
                        bool launch(InputType type);
                        bool launch();
 
-               protected:
-                       virtual void onKeyboardReply(const std::string &text, int cursorPos) {};
-                       virtual void onTemplateReply(const std::string &text) {};
-                       virtual void onVoiceReply(const std::string &text, const std::list<std::string> &filePath) {};
-                       virtual void onEmoticonReply(const std::string &emoticon) {};
-                       virtual void onTerminate() {};
-
-                       void terminateHandler();
-
                private:
                        void onReply(app_control_h request, app_control_h reply, app_control_result_e result) override;
+                       void terminateHandler();
                        void clear();
 
                private:
@@ -66,6 +58,10 @@ namespace Msg {
                public:
                        virtual ~IInputSelectorListener() {}
                        virtual void onTerminate(InputSelector &) {};
+                       virtual void onKeyboardReply(const std::string &text, int cursorPos) {};
+                       virtual void onTemplateReply(const std::string &text) {};
+                       virtual void onVoiceReply(const std::string &text, const std::list<std::string> &filePath) {};
+                       virtual void onEmoticonReply(const std::string &emoticon) {};
        };
 }
 
index aed142401454b0893a566ebd67ba6bd421db6311..9c88471be2c41d1d7c389ce0e44520a402558dfb 100644 (file)
@@ -49,7 +49,6 @@ void InputSelector::clear()
 
 void InputSelector::terminateHandler()
 {
-       onTerminate();
        if (m_pListener)
                m_pListener->onTerminate(*this);
        clear();
@@ -94,16 +93,18 @@ void InputSelector::onReply(app_control_h request, app_control_h reply, app_cont
 
                MSG_LOG("replyType = ", replyType);
 
-               if(replyType == "keyboard") {
-                       int pos = AppControlUtils::getExtraDataInt(reply, "cursor_position_get");
-                       onKeyboardReply(text, pos);
-               } else if (replyType == "emoticon") {
-                        onEmoticonReply(text);
-               } else if (replyType == "voice") {
-                       auto fileList = AppControlUtils::getExtraDataArray(reply, APP_CONTROL_DATA_PATH);
-                       onVoiceReply(text, fileList);
-               } else if (replyType == "template") {
-                        onTemplateReply(text);
+               if (m_pListener) {
+                       if(replyType == "keyboard") {
+                               int pos = AppControlUtils::getExtraDataInt(reply, "cursor_position_get");
+                               m_pListener->onKeyboardReply(text, pos);
+                       } else if (replyType == "emoticon") {
+                               m_pListener->onEmoticonReply(text);
+                       } else if (replyType == "voice") {
+                               auto fileList = AppControlUtils::getExtraDataArray(reply, APP_CONTROL_DATA_PATH);
+                               m_pListener->onVoiceReply(text, fileList);
+                       } else if (replyType == "template") {
+                               m_pListener->onTemplateReply(text);
+                       }
                }
        }
        if (result != APP_CONTROL_RESULT_APP_STARTED)
index bfb235c7018a666306bfcc20d40a4c48583a6a9b..84a42d099c3a3f377937f1fa88905e5a779c5276 100644 (file)
@@ -31,7 +31,6 @@ namespace Msg {
        class ContactManager;
        class SystemSettingsManager;
        class AppControlLauncher;
-       class MsgInputSelector;
 
        class App {
                public:
index 563ee05946ea0d68e03691b3bc2506e847a83d63..b691037ec6c24737c800ba1f441590593bbf53b6 100644 (file)
@@ -22,7 +22,6 @@
 #include "AppControlCompose.h"
 #include "AppControlDefault.h"
 #include "AppControlSettings.h"
-#include "MsgInputSelector.h"
 #include "FrameController.h"
 #include "PopupManager.h"
 #include "App.h"
 namespace Msg {
 
        class FrameController;
-       class MsgInputSelector;
+       class MsgComposerController;
        class ConnectivityChecker;
+       class InputSelector;
 
        class NaviFrameController
                : public NaviFrameView
                , private IAppListener
-               , private IInputSelectorListener
                , private IPopupManagerListener {
 
+               friend class MsgInputController;
+
                public:
                        NaviFrameController(App &app);
                        virtual ~NaviFrameController();
@@ -87,7 +88,7 @@ namespace Msg {
                        T *findTopFrame() const;
 
                        FrameController *getTopFrame() const;
-                       MsgInputSelector &getInputSelector();
+                       MsgComposerController &getMsgComposer();
                        ConnectivityChecker &getConnectivityChecker();
                        bool isEmpty() const;
 
@@ -110,15 +111,14 @@ namespace Msg {
                        void onAppPause() override;
                        void onAppResume() override;
 
-                       // IInputSelectorListener:
-                       void onTerminate(InputSelector &sender) override;
+                       void onTerminate(InputSelector &sender);
 
                        // IPopupManagerListener:
                        void onPop(BasePopup &popup) override;
                        void onPush(BasePopup &popup) override;
 
                private:
-                       std::unique_ptr<MsgInputSelector> m_InputSelector;
+                       std::unique_ptr<MsgComposerController> m_MsgComposer;
                        std::unique_ptr<ConnectivityChecker> m_ConnectivityChecker;
                        Ecore_Job *m_pExitJob;
        };
index e51ffb9319d0c499199c5f5ff4d388197829e6c5..4270d63d4ebd5a47779e539ee05fc863c4a64bbc 100644 (file)
@@ -26,8 +26,8 @@
 #include "MsgEngine.h"
 #include "Callback.h"
 #include "ToastPopup.h"
-#include "RecipFrame.h"
 #include "ConnectivityChecker.h"
+#include "MsgComposerController.h"
 
 #include <memory>
 #include <algorithm>
@@ -58,9 +58,9 @@ void NaviFrameController::pop(FrameController &frame)
        MSG_LOG("Is Last frame: ", isLastFrame());
        MSG_LOG("PopupManager isEmpty: ", App::getInst().getPopupManager().isEmpty());
 
-       if (isLastFrame() && App::getInst().getPopupManager().isEmpty())
+       if (isLastFrame() && App::getInst().getPopupManager().isEmpty()) {
                App::getInst().exit();
-       else {
+       else {
                App::getInst().getPopupManager().pop(&frame);
                NaviFrameView::pop(frame);
        }
@@ -165,14 +165,7 @@ void NaviFrameController::execCmd(const AppControlComposeRef &cmd)
                return;
 
        App::getInst().getLauncher().terminate();
-       if (cmd->getRecipientList().empty()) {
-               auto *frame = new RecipFrame(*this);
-               push(*frame);
-               frame->execCmd(cmd);
-       } else {
-               getInputSelector().reset();
-               getInputSelector().execCmd(cmd);
-       };
+       getMsgComposer().execCmd(cmd);
 }
 
 void NaviFrameController::execCmd(const AppControlSettingsRef &cmd)
@@ -195,13 +188,11 @@ FrameController *NaviFrameController::getTopFrame() const
        return static_cast<FrameController*>(NaviFrameView::getTopFrame());
 }
 
-MsgInputSelector &NaviFrameController::getInputSelector()
+MsgComposerController &NaviFrameController::getMsgComposer()
 {
-       if (!m_InputSelector) {
-               m_InputSelector.reset(new MsgInputSelector);
-               m_InputSelector->setListener(this);
-       }
-       return *m_InputSelector;
+       if (!m_MsgComposer)
+               m_MsgComposer.reset(new MsgComposerController(*this));
+       return *m_MsgComposer;
 }
 
 ConnectivityChecker &NaviFrameController::getConnectivityChecker()
@@ -257,7 +248,7 @@ void NaviFrameController::onBeforeDelete(View &view)
        NaviFrameView::onBeforeDelete(view);
        App::getInst().removeListener(*this);
        App::getInst().getPopupManager().removeListener(*this);
-       m_InputSelector.reset();
+       m_MsgComposer.reset();
        m_ConnectivityChecker.reset();
 }
 
diff --git a/src/Composer/Controller/inc/Composer.h b/src/Composer/Controller/inc/Composer.h
deleted file mode 100644 (file)
index a35bf87..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef Composer_h_
-#define Composer_h_
-
-#include "MsgTransport.h"
-#include "MessageMms.h"
-#include "MessageSMS.h"
-#include "Recipient.h"
-#include "SettingsLauncher.h"
-#include "WorkingDir.h"
-#include "AppControlCompose.h"
-#include "ConnectivityChecker.h"
-#include "SendingOptionsFrame.h"
-#include "View.h"
-
-#include <set>
-#include <string>
-#include <list>
-
-namespace Msg {
-
-       class MsgEngine;
-       class IComposerListener;
-       class IconTextPopup;
-       class Popup;
-
-       class Composer
-               : private IMsgTransportListener
-               , private ISendingOptionsFrameListener {
-
-               public:
-                       Composer();
-                       virtual ~Composer();
-
-                       void setListener(IComposerListener *l);
-                       void setRecip(Recipient recip);
-                       const Recipient &getRecip() const;
-                       void setText(std::string text);
-                       bool addFile(const std::string &file);
-                       void send();
-                       ThreadId getThreadId() const;
-                       void reset();
-                       void clear();
-
-               private:
-                       struct SendInfo {
-                               SendInfo ();
-                               void reset();
-                               std::vector<MessageRef> msgs;
-                               std::set<RequestId> requestIdSet;
-                               Message::NetworkStatus status;
-                               ThreadId threadId;
-                               bool inProgress;
-                       };
-
-                       // IMsgTransportListener:
-                       void onMsgTransportSentStatus(const MsgSentStatus &status) override;
-
-                       // ISendingOptionsFrameListener:
-                       void onSendAsText(SendingOptionsFrame &sender) override;
-                       void onSendAsAudio(SendingOptionsFrame &sender) override;
-                       void onDestroy(SendingOptionsFrame &sender) override;
-
-                       void notifyOnSendStart();
-                       void notifyOnSendFinished();
-                       void notifyOnCloseSendPopup();
-
-                       // Popup:
-                       void showSendingProgressPopup();
-                       void showUnableDataRoamingPopup();
-                       void showSentWhenServiceBecomesAvailablePopup();
-                       void showMmsTextLimitExceededPopup(int smsCount, int mmsCount, int maxChars);
-
-                       // Popup callbacks:
-                       void onSendingPopupDestroy(Evas *e, Evas_Object *obj, void *event_info);
-                       void onSendingPopupBackButtonPressed(Evas_Object *obj, void *event_info);
-                       void onMmsTextLimitExceededOkPressed(Popup &popup);
-
-                       bool checkConnectivity(Message::Type type);
-                       bool checkSendingOptions();
-
-                       void sendMessage();
-                       void sendState0();
-                       void sendState1();
-                       void sendState2();
-                       void sendState3();
-                       void sendState4();
-                       void sendStateEnd();
-
-                       std::vector<MessageRef> createMessage();
-                       void sendMessageStep1();
-                       void sendMessageStep2();
-                       void sendMessageStep3();
-
-                       bool readAddress(Message &msg);
-                       void handleSendResult(MsgTransport::SendResult result);
-                       void destroySendingPopup(bool anim = true);
-                       void navigateToSendingOptions();
-
-                       void setText(MessageRef msg, const std::string &text);
-                       void setText(MessageSMS &msg, const std::string &text);
-                       void setText(MessageMms &msg, const std::string &text);
-                       void addFile(MessageMms &msg, const std::string &filePath);
-                       void removeAudioFiles();
-
-                       MsgEngine &getMsgEngine();
-
-               private:
-                       enum SendingState {
-                               SndState0,
-                               SndState1,
-                               SndState2,
-                               SndState3,
-                               SndState4,
-                               SndStateEnd
-                       };
-
-               private:
-                       Recipient m_Recip;
-                       std::string m_Text;
-                       std::list<std::string> m_Files;
-                       IconTextPopup *m_pSendingPopup;
-                       MsgTextMetric m_TextMetric;
-                       SendInfo m_SendInfo;
-                       WorkingDirRef m_WorkingDir;
-                       IComposerListener *m_pListener;
-                       SendingState m_SendingState;
-       };
-
-       class IComposerListener {
-               public:
-                       virtual ~IComposerListener() {}
-                       virtual void onSendStart(Composer &composer) {};
-                       virtual void onSendFinished(Composer &composer) {};
-                       virtual void onCloseSendPopup(Composer &composer) {};
-       };
-}
-
-#endif /* Composer_h_ */
diff --git a/src/Composer/Controller/inc/MsgComposerController.h b/src/Composer/Controller/inc/MsgComposerController.h
new file mode 100644 (file)
index 0000000..fd06d52
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MsgComposerController_h_
+#define MsgComposerController_h_
+
+#include "MsgInputController.h"
+#include "RecipFrame.h"
+#include "AppControlCompose.h"
+#include "AppControlDefault.h"
+#include "MsgSenderController.h"
+
+namespace Msg {
+
+       class NaviFrameController;
+
+       class MsgComposerController
+               : private IRecipFrameListener
+               , private IMsgInputControllerListener
+               , private IMsgSenderControllerListener {
+
+               public:
+                       MsgComposerController(NaviFrameController &navi);
+                       virtual ~MsgComposerController();
+                       MsgComposerController(MsgComposerController&) = delete;
+                       void operator=(MsgComposerController&) = delete;
+
+                       bool execCmd(const AppControlDefault &cmd);
+                       bool execCmd(const AppControlComposeRef &cmd);
+                       bool launchRecipInput();
+                       bool launchMsgInput();
+                       void reset();
+                       void setRecip(Recipient recip);
+                       void setText(std::string text);
+                       bool addFile(const std::string &file);
+                       bool addFiles(const std::list<std::string> &files);
+
+               private:
+                       // IRecipFrameListener:
+                       void onDestroy(RecipFrame&) override;
+                       void onRecipSelected(RecipFrame&) override;
+
+                       // IMsgInputControllerListener:
+                       void onSendRequest(MsgInputController&) override;
+
+                       // IMsgSenderControllerListener:
+                       void onSendStart(MsgSenderController &) override;
+                       void onSendFinished(MsgSenderController &) override;
+                       void onCloseSendPopup(MsgSenderController &) override;
+
+               private:
+                       bool launchConv(ThreadId threadId);
+
+               private:
+                       NaviFrameController &m_Navi;
+                       MsgSenderController m_Sender;
+                       MsgInputController m_MsgInput;
+                       RecipFrame *m_pRecipFrame;
+                       bool m_CloseAfterSent;
+                       AppControlComposeRef m_Cmd;
+       };
+}
+
+#endif /* MsgComposerController_h_ */
diff --git a/src/Composer/Controller/inc/MsgInputController.h b/src/Composer/Controller/inc/MsgInputController.h
new file mode 100644 (file)
index 0000000..dec32f6
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MsgInputController_h_
+#define MsgInputController_h_
+
+#include "InputSelector.h"
+#include "MsgBodyFrame.h"
+
+#include <string>
+#include <list>
+
+namespace Msg {
+
+       class FrameController;
+       class NaviFrameController;
+       class IMsgInputControllerListener;
+
+       class MsgInputController
+               : private IInputSelectorListener
+               , private IMsgBodyFrameListener {
+
+               public:
+                       struct InputData {
+                               std::string text;
+                               std::list<std::string> files;
+                       };
+
+               public:
+                       MsgInputController(NaviFrameController &navi);
+                       virtual ~MsgInputController();
+                       MsgInputController(MsgInputController&) = delete;
+                       void operator =(MsgInputController&) = delete;
+
+                       void setListener(IMsgInputControllerListener *l);
+                       void reset();
+                       const InputData &getInput() const;
+
+                       bool launch(const std::string &text = {});
+                       bool launchSelectView();
+                       bool launchVoiceView();
+                       bool launchEmoticonView();
+                       bool launchTextInputView(const std::string &text);
+
+               private:
+                       void showMsgBody(const std::string &text = {}, int cursorPos = 0);
+                       void notifyOnSendRequest();
+
+                       // IMsgBodyFrameListener:
+                       void onDestroy(MsgBodyFrame &frame) override;
+                       void onSendRequest(MsgBodyFrame &frame) override;
+                       void onPress(MsgBodyFrame &frame) override;
+
+                       // IInputSelectorListener:
+                       void onTemplateReply(const std::string &text) override;
+                       void onKeyboardReply(const std::string &text, int cursorPos) override;
+                       void onVoiceReply(const std::string &text, const std::list<std::string> &fileList) override;
+                       void onEmoticonReply(const std::string &emoticon) override;
+                       void onTerminate(InputSelector &) override;
+
+               private:
+                       NaviFrameController &m_Navi;
+                       MsgBodyFrame *m_pMsgBodyFrame;
+                       InputSelector m_InputSelector;
+                       IMsgInputControllerListener *m_pListener;
+                       InputData m_InputData;
+       };
+
+       class IMsgInputControllerListener {
+               public:
+                       virtual ~IMsgInputControllerListener() {};
+                       virtual void onSendRequest(MsgInputController&) {};
+       };
+}
+
+#endif /* MsgInputController_h_ */
diff --git a/src/Composer/Controller/inc/MsgInputSelector.h b/src/Composer/Controller/inc/MsgInputSelector.h
deleted file mode 100644 (file)
index ae9dad9..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MsgInputSelector_h_
-#define MsgInputSelector_h_
-
-#include "InputSelector.h"
-#include "Recipient.h"
-#include "AppControlCompose.h"
-#include "Composer.h"
-#include "MsgBodyFrame.h"
-#include "MsgTypes.h"
-
-namespace Msg {
-
-       class FrameController;
-       class NaviFrameController;
-
-       class MsgInputSelector
-               : public InputSelector
-               , private IComposerListener
-               , private IMsgBodyFrameListener {
-
-               public:
-                       MsgInputSelector();
-                       virtual ~MsgInputSelector();
-
-                       void setRecip(Recipient recip);
-                       bool execCmd(const AppControlComposeRef &cmd);
-                       void reset();
-
-               protected:
-                       void onTemplateReply(const std::string &text) override;
-                       void onKeyboardReply(const std::string &text, int cursorPos) override;
-                       void onVoiceReply(const std::string &text, const std::list<std::string> &fileList) override;
-                       void onEmoticonReply(const std::string &emoticon) override;
-
-               private:
-                       NaviFrameController &getNavigation();
-                       void showMsgBody(const std::string &text, int cursorPos);
-                       void navigateToConv(ThreadId threadId);
-                       void send();
-                       void addDummyAudio();
-
-                       // IComposerListener:
-                       void onSendStart(Composer &composer) override;
-                       void onSendFinished(Composer &composer) override;
-                       void onCloseSendPopup(Composer &composer) override;
-
-                       // IMsgBodyFrameListener:
-                       void onDestroy(MsgBodyFrame &frame) override;
-                       void onSendRequest(MsgBodyFrame &frame) override;
-                       void onPress(MsgBodyFrame &frame) override;
-
-               private:
-                       Composer m_Composer;
-                       MsgBodyFrame *m_pMsgBodyFrame;
-                       bool m_CloseAfterSent;
-       };
-}
-
-#endif /* MsgInputSelector_h_ */
diff --git a/src/Composer/Controller/inc/MsgSenderController.h b/src/Composer/Controller/inc/MsgSenderController.h
new file mode 100644 (file)
index 0000000..7d2e4da
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MsgSender_h_
+#define MsgSender_h_
+
+#include "MsgTransport.h"
+#include "MessageMms.h"
+#include "MessageSMS.h"
+#include "Recipient.h"
+#include "SettingsLauncher.h"
+#include "WorkingDir.h"
+#include "AppControlCompose.h"
+#include "ConnectivityChecker.h"
+#include "SendingOptionsFrame.h"
+#include "View.h"
+
+#include <set>
+#include <string>
+#include <list>
+
+namespace Msg {
+
+       class MsgEngine;
+       class IMsgSenderControllerListener;
+       class IconTextPopup;
+       class Popup;
+
+       class MsgSenderController
+               : private IMsgTransportListener
+               , private ISendingOptionsFrameListener {
+
+               public:
+                       MsgSenderController();
+                       virtual ~MsgSenderController();
+                       MsgSenderController(MsgSenderController&) = delete;
+                       void operator =(MsgSenderController&) = delete;
+
+                       void setListener(IMsgSenderControllerListener *l);
+                       void setRecip(Recipient recip);
+                       void setText(std::string text);
+                       bool addFile(const std::string &file);
+                       bool addFiles(const std::list<std::string> &files);
+                       const Recipient &getRecip() const;
+                       const std::string &getText() const;
+                       const std::list<std::string> &getFiles() const;
+                       bool isMsgBodyEmpty() const;
+                       void send();
+                       ThreadId getThreadId() const;
+                       void reset();
+                       void clear();
+
+               private:
+                       struct SendInfo {
+                               SendInfo ();
+                               void reset();
+                               std::vector<MessageRef> msgs;
+                               std::set<RequestId> requestIdSet;
+                               Message::NetworkStatus status;
+                               ThreadId threadId;
+                               bool inProgress;
+                       };
+
+                       // IMsgTransportListener:
+                       void onMsgTransportSentStatus(const MsgSentStatus &status) override;
+
+                       // ISendingOptionsFrameListener:
+                       void onSendAsText(SendingOptionsFrame &sender) override;
+                       void onSendAsAudio(SendingOptionsFrame &sender) override;
+                       void onDestroy(SendingOptionsFrame &sender) override;
+
+                       void notifyOnSendStart();
+                       void notifyOnSendFinished();
+                       void notifyOnCloseSendPopup();
+
+                       // Popup:
+                       void showSendingProgressPopup();
+                       void showUnableDataRoamingPopup();
+                       void showSentWhenServiceBecomesAvailablePopup();
+                       void showMmsTextLimitExceededPopup(int smsCount, int mmsCount, int maxChars);
+
+                       // Popup callbacks:
+                       void onSendingPopupDestroy(Evas *e, Evas_Object *obj, void *event_info);
+                       void onSendingPopupBackButtonPressed(Evas_Object *obj, void *event_info);
+                       void onMmsTextLimitExceededOkPressed(Popup &popup);
+
+                       bool checkConnectivity(Message::Type type);
+                       bool checkSendingOptions();
+
+                       void sendMessage();
+                       void sendState0();
+                       void sendState1();
+                       void sendState2();
+                       void sendState3();
+                       void sendState4();
+                       void sendStateEnd();
+
+                       std::vector<MessageRef> createMessage();
+                       void sendMessageStep1();
+                       void sendMessageStep2();
+                       void sendMessageStep3();
+
+                       bool readAddress(Message &msg);
+                       void handleSendResult(MsgTransport::SendResult result);
+                       void destroySendingPopup(bool anim = true);
+                       void navigateToSendingOptions();
+
+                       void setText(MessageRef msg, const std::string &text);
+                       void setText(MessageSMS &msg, const std::string &text);
+                       void setText(MessageMms &msg, const std::string &text);
+                       void addFile(MessageMms &msg, const std::string &filePath);
+                       void removeAudioFiles();
+
+                       MsgEngine &getMsgEngine();
+
+               private:
+                       enum SendingState {
+                               SndState0,
+                               SndState1,
+                               SndState2,
+                               SndState3,
+                               SndState4,
+                               SndStateEnd
+                       };
+
+               private:
+                       Recipient m_Recip;
+                       std::string m_Text;
+                       std::list<std::string> m_Files;
+                       IconTextPopup *m_pSendingPopup;
+                       MsgTextMetric m_TextMetric;
+                       SendInfo m_SendInfo;
+                       WorkingDirRef m_WorkingDir;
+                       IMsgSenderControllerListener *m_pListener;
+                       SendingState m_SendingState;
+       };
+
+       class IMsgSenderControllerListener {
+               public:
+                       virtual ~IMsgSenderControllerListener() {}
+                       virtual void onSendStart(MsgSenderController &sender) {};
+                       virtual void onSendFinished(MsgSenderController &sender) {};
+                       virtual void onCloseSendPopup(MsgSenderController &sender) {};
+       };
+}
+
+#endif /* MsgSender_h_ */
index 830f76c730cf13799e6c7193ca3ec7b0612de2a6..a37419d003b78e6da9bd7de6ed7e2a84c0c6e6c5 100644 (file)
@@ -30,6 +30,7 @@ namespace Msg {
        class BottomButton;
        class RecipLayout;
        class DefaultLayout;
+       class IRecipFrameListener;
 
        class RecipFrame
                : public FrameController
@@ -42,6 +43,9 @@ namespace Msg {
                        virtual ~RecipFrame();
 
                        bool execCmd(const AppControlComposeRef &cmd);
+                       void setListener(IRecipFrameListener *l);
+                       const Recipient &getRecip() const;
+                       void clear();
 
                private:
                        // NaviFrameItem:
@@ -78,7 +82,7 @@ namespace Msg {
                        void setRecip(Recipient recip);
                        void setRecip(std::string address);
                        void clearRecip();
-                       void navigateToMsgInput();
+                       void navigateToMsgComposer();
 
                private:
                        DefaultLayout *m_pBaseLayout;
@@ -89,6 +93,14 @@ namespace Msg {
                        Recipient m_Recip;
                        ContactPicker m_ContactPicker;
                        AppControlComposeRef m_ComposeCmd;
+                       IRecipFrameListener *m_pListener;
+       };
+
+       class IRecipFrameListener {
+               public:
+                       virtual ~IRecipFrameListener() {}
+                       virtual void onDestroy(RecipFrame&) {}
+                       virtual void onRecipSelected(RecipFrame&) {}
        };
 }
 
diff --git a/src/Composer/Controller/src/Composer.cpp b/src/Composer/Controller/src/Composer.cpp
deleted file mode 100644 (file)
index b2e9fd0..0000000
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Composer.h"
-#include "App.h"
-#include "MsgEngine.h"
-#include "MsgUtils.h"
-#include "Message.h"
-#include "SystemSettingsManager.h"
-#include "ConnectivityChecker.h"
-#include "Callback.h"
-#include "IconTextPopup.h"
-#include "ToastPopup.h"
-#include "NaviFrameController.h"
-#include "MediaType.h"
-#include "SendingOptionsFrame.h"
-#include "MediaUtils.h"
-#include "FileUtils.h"
-
-using namespace Msg;
-
-Composer::SendInfo::SendInfo()
-       : requestIdSet()
-       , status(Message::NS_Unknown)
-       , threadId()
-       , inProgress(false)
-{
-}
-
-void Composer::SendInfo::reset()
-{
-       msgs.clear();
-       inProgress = false;
-       requestIdSet.clear();
-       status = Message::NS_Unknown;
-       threadId.reset();
-}
-
-Composer::Composer()
-       : m_pSendingPopup(nullptr)
-       , m_TextMetric()
-       , m_WorkingDir(std::make_shared<WorkingDir>())
-       , m_pListener(nullptr)
-       , m_SendingState(SndState0)
-{
-       App::getInst().getMsgEngine().getTransport().addListener(*this);
-}
-
-Composer::~Composer()
-{
-       MSG_LOG("");
-       destroySendingPopup(false);
-       App::getInst().getMsgEngine().getTransport().removeListener(*this);
-}
-
-MsgEngine &Composer::getMsgEngine()
-{
-       return App::getInst().getMsgEngine();
-}
-
-void Composer::setListener(IComposerListener *l)
-{
-       m_pListener = l;
-}
-
-void Composer::setRecip(Recipient recip)
-{
-       m_Recip = std::move(recip);
-}
-
-const Recipient &Composer::getRecip() const
-{
-       return m_Recip;
-}
-
-void Composer::setText(std::string text)
-{
-       m_Text = std::move(text);
-}
-
-bool Composer::addFile(const std::string &file)
-{
-       std::string newFilePath = m_WorkingDir->addFile(file);
-       bool isValid = !newFilePath.empty();
-       if (isValid)
-               m_Files.push_back(std::move(newFilePath));
-       return isValid;
-}
-
-void Composer::addFile(MessageMms &msg, const std::string &filePath)
-{
-       constexpr int defaultPageDuration = 5000; // msec
-       if (!filePath.empty()) {
-               MsgPage &msgPage = msg.addPage();
-               MediaTypeData mediaData = getMsgMediaTypeByFileExt(filePath);
-               int pageDuration = 0;
-
-               if (mediaData.type == MsgMedia::VideoType || mediaData.type == MsgMedia::AudioType)
-                       pageDuration = MediaUtils::getDuration(filePath);
-
-               if (pageDuration <= 0)
-                       pageDuration = defaultPageDuration;
-
-               msgPage.setPageDuration(pageDuration);
-               MsgMedia &media = msgPage.addMedia();
-               media.setFilePath(filePath);
-       }
-}
-
-void Composer::removeAudioFiles()
-{
-       decltype(m_Files) newFileList;
-       for (std::string &file : m_Files) {
-               if (getMsgMediaTypeByFileExt(file).type != MsgMedia::AudioType)
-                       newFileList.push_back(std::move(file));
-       }
-       m_Files = std::move(newFileList);
-}
-
-void Composer::send()
-{
-       m_SendingState = SndState0;
-       sendMessage();
-}
-
-ThreadId Composer::getThreadId() const
-{
-       return m_SendInfo.threadId;
-}
-
-void Composer::reset()
-{
-       m_SendInfo.reset();
-       // TODO: check popups
-}
-
-void Composer::clear()
-{
-       m_Recip.clear();
-       m_Text.clear();
-       m_Files.clear();
-       if (m_WorkingDir)
-               m_WorkingDir->clear();
-}
-
-bool Composer::readAddress(Message &msg)
-{
-       if(m_Recip.isValid()) {
-               MsgAddress &msgAddr = msg.addAddress();
-               msgAddr.setAddress(m_Recip.getAddress());
-               msgAddr.setRecipientType(MsgAddress::To);
-               msgAddr.setAddressType(MsgAddress::Phone);
-               return true;
-       }
-
-       return false;
-}
-
-void Composer::setText(MessageRef msg, const std::string &text)
-{
-       if (msg && !text.empty()) {
-               if (auto *sms = dynamic_cast<MessageSMS*>(msg.get()))
-                       setText(*sms, text);
-               else if (auto *mms = dynamic_cast<MessageMms*>(msg.get()))
-                       setText(*mms, text);
-       }
-}
-
-void Composer::setText(MessageSMS &msg, const std::string &text)
-{
-       msg.setText(text);
-}
-
-void Composer::setText(MessageMms &msg, const std::string &text)
-{
-       static const int defaultPageDuration = 5000; // msec
-       std::string filePath = m_WorkingDir->addTextFile(text);
-       if (!filePath.empty()) {
-               MsgPage &page = msg.addPage();
-               page.setPageDuration(defaultPageDuration);
-               page.addMedia().setFilePath(filePath);
-       }
-}
-
-bool Composer::checkConnectivity(Message::Type type)
-{
-       auto &checker = App::getInst().getNavigation().getConnectivityChecker();
-       return MsgUtils::isMms(type) ? checker.isReadyToSendMms()
-                                                                : checker.isReadyToSendSms();
-}
-
-void Composer::navigateToSendingOptions()
-{
-       auto &navi = App::getInst().getNavigation();
-       auto *frame = new SendingOptionsFrame(navi);
-       frame->setListener(this);
-       navi.push(*frame);
-}
-
-bool Composer::checkSendingOptions()
-{
-       if (!getMsgEngine().getSettings().getSendAsAudio() || m_Files.empty())
-               return true;
-
-       bool onlyAudio = true;
-       long long msgSize = 0;
-       for (const std::string &file : m_Files) {
-               onlyAudio &= getMsgMediaTypeByFileExt(file).type == MsgMedia::AudioType;
-               if (onlyAudio)
-                       msgSize += FileUtils::getFileSize(file);
-               else
-                       break;
-       }
-
-       if (onlyAudio && msgSize <= getMsgEngine().getSettings().getMaxMmsSize()) {
-               navigateToSendingOptions();
-               return false;
-       }
-       return true;
-}
-
-void Composer::sendMessage()
-{
-       switch (m_SendingState) {
-       case SndState0:
-               m_SendingState = SndState1;
-               sendState0();
-               break;
-       case SndState1:
-               m_SendingState = SndState2;
-               sendState1();
-               break;
-       case SndState2:
-               m_SendingState = SndState3;
-               sendState2();
-               break;
-       case SndState3:
-               m_SendingState = SndState4;
-               sendState3();
-               break;
-       case SndState4:
-               m_SendingState = SndStateEnd;
-               sendState4();
-               break;
-       case SndStateEnd:
-               break;
-       }
-}
-
-void Composer::sendState0()
-{
-       MSG_LOG("");
-       reset();
-       destroySendingPopup(false);
-
-       if (!checkSendingOptions())
-               return;
-
-       removeAudioFiles();
-       sendMessage();
-}
-
-void Composer::sendState1()
-{
-       MSG_LOG("");
-       int smsCount = 0;
-       int mmsCount = 0;
-
-       m_SendInfo.msgs = createMessage();
-
-       MsgTextMetric textMetric;
-       getMsgEngine().getComposer().calculateTextMetric(m_Text, textMetric);
-
-       for (MessageRef msg : m_SendInfo.msgs) {
-               if (msg->getType() == Message::MT_MMS)
-                       ++mmsCount;
-               else if (msg->getType() == Message::MT_SMS)
-                       ++smsCount;
-       }
-       bool isTextMms = mmsCount > 0 && m_Files.empty();
-       if (isTextMms)
-               showMmsTextLimitExceededPopup(smsCount, mmsCount, textMetric.maxSmsLen);
-       else
-               sendMessage();
-}
-
-void Composer::sendState2()
-{
-       MSG_LOG("");
-       sendMessage();
-}
-
-void Composer::sendState3()
-{
-       MSG_LOG("");
-       if (m_SendInfo.msgs.empty()) {
-               MSG_LOG_ERROR("m_SendInfo.msgs is empty")
-               return;
-       }
-
-       // Check connectivity:
-       if (!checkConnectivity(m_SendInfo.msgs[0]->getType()))
-                return;
-
-       sendMessage();
-}
-
-void Composer::sendState4()
-{
-       MSG_LOG("");
-
-       // Send message:
-       MsgTransport::SendResult sendRes = MsgTransport::SendFail;
-       MessageRef lastSentMsg;
-
-       for (MessageRef msg : m_SendInfo.msgs) {
-               lastSentMsg = msg;
-               RequestId reqId;
-               sendRes = getMsgEngine().getTransport().sendMessage(msg, &m_SendInfo.threadId, &reqId);
-
-               MSG_LOG("Send result = ", sendRes);
-               MSG_LOG("Thread id = ", m_SendInfo.threadId);
-               MSG_LOG("Request id = ", reqId);
-
-               if (sendRes != MsgTransport::SendSuccess)
-                       break;
-
-               m_SendInfo.inProgress = true;
-               m_SendInfo.requestIdSet.insert(reqId);
-       }
-
-       if (sendRes == MsgTransport::SendSuccess && m_SendInfo.threadId.isValid()) {
-               showSendingProgressPopup();
-               notifyOnSendStart();
-       } else {
-               notifyOnSendStart();
-               handleSendResult(sendRes);
-       }
-
-       sendMessage();
-}
-
-
-std::vector<MessageRef> Composer::createMessage()
-{
-       std::vector<MessageRef> msgList;
-       auto &msgEngine = getMsgEngine();
-       const int maxMsgSize = msgEngine.getSettings().getMaxMmsSize();
-
-       if (maxMsgSize <= 0) {
-               MSG_LOG_ERROR("getMaxMmsSize() returns 0");
-               return {};
-       }
-
-       MSG_LOG("");
-       if (m_Files.empty()) {
-               MSG_LOG("");
-               // Text messages:
-               auto textList = MsgUtils::splitUtf8String(m_Text, maxMsgSize);
-               for (auto &&text : textList) {
-                       MsgTextMetric metric;
-                       msgEngine.getComposer().calculateTextMetric(m_Text, metric);
-                       Message::Type type = metric.isMms ? Message::MT_MMS : Message::MT_SMS;
-                       auto msg = msgEngine.getComposer().createMessage(type);
-                       if (msg && readAddress(*msg)) {
-                               setText(msg, text);
-                               msgList.push_back(msg);
-                       }
-               }
-       } else {
-               MSG_LOG("");
-               // Create MMS:
-               auto mms = msgEngine.getComposer().createMms();
-               if (mms) {
-                       if (readAddress(*mms)) {
-                               for (const std::string &file : m_Files)
-                                       addFile(*mms, file);
-                               msgList.push_back(mms);
-                       }
-               }
-       }
-       return msgList;
-}
-
-void Composer::notifyOnSendStart()
-{
-       if (m_pListener)
-               m_pListener->onSendStart(*this);
-}
-
-void Composer::notifyOnSendFinished()
-{
-       if (m_pListener)
-               m_pListener->onSendFinished(*this);
-}
-
-void Composer::notifyOnCloseSendPopup()
-{
-       if (m_pListener)
-               m_pListener->onCloseSendPopup(*this);
-}
-
-void Composer::handleSendResult(MsgTransport::SendResult result)
-{
-       notifyOnSendFinished();
-}
-
-void Composer::destroySendingPopup(bool anim)
-{
-       if (m_pSendingPopup) {
-               m_pSendingPopup->destroy(anim);
-               m_pSendingPopup = nullptr;
-       }
-}
-
-void Composer::showSendingProgressPopup()
-{
-       if (!m_pSendingPopup) {
-               m_pSendingPopup = new IconTextPopup;
-               m_pSendingPopup->setDismissByBackButtonFlag(false);
-               m_pSendingPopup->addEventCb(EVAS_CALLBACK_DEL, makeCbFirst(&Composer::onSendingPopupDestroy), this);
-               m_pSendingPopup->addHwButtonEvent(EEXT_CALLBACK_BACK, makeCbFirst(&Composer::onSendingPopupBackButtonPressed), this);
-               m_pSendingPopup->setIcon(IconTextPopup::ProgressIcon);
-               m_pSendingPopup->setText(msgt("IDS_MSG_BODY_SENDING_ING_M_STATUS_ABB"));
-               m_pSendingPopup->show();
-       }
-}
-
-void Composer::showMmsTextLimitExceededPopup(int smsCount, int mmsCount, int maxChars)
-{
-       auto *popup = new StandardPopup(StandardPopup::buttons2Style);
-       std::string popupMessage = msgArgs("WDS_MSG_BODY_MAXIMUM_NUMBER_OF_CHARACTERS_HPD_EXCEEDED", maxChars);
-       popupMessage += "<br>";
-
-       if (smsCount == 0) {
-               if (mmsCount == 1)
-                       popupMessage += msg("WDS_MSG_POP_SEND_AS_MMS_Q");
-               else
-                       popupMessage += msgArgs("WDS_MSG_BODY_MESSAGE_WILL_BE_SENT_AS_PD_MMS_MESSAGES", mmsCount);
-       } else
-               popupMessage += msgArgs("WDS_MSG_BODY_MESSAGE_WILL_BE_SENT_AS_PD_MMS_MESSAGES_AND_1_SMS_MESSAGE", mmsCount);
-
-       popup->setText(popupMessage);
-       popup->addLeftButton(CANCEL_BUTTON_POPUP);
-       popup->addRightButton(OK_BUTTON_POPUP, makeCbLast(&Composer::onMmsTextLimitExceededOkPressed), this);
-       popup->show();
-}
-
-void Composer::showSentWhenServiceBecomesAvailablePopup()
-{
-       auto *popup = new StandardPopup(StandardPopup::buttons1Style);
-       popup->setText(msgt("WDS_MSG_BODY_UNABLE_TO_SEND_MESSAGE_IT_WILL_BE_SENT_WHEN_SERVICE_BECOMES_AVAILABLE"));
-       popup->addBottomButton(msgt("WDS_MSG_ACBUTTON_OK_ABB"));
-       popup->show();
-}
-
-void Composer::onMsgTransportSentStatus(const MsgSentStatus &status)
-{
-       MSG_LOG("");
-       RequestId id = status.getId();
-       Message::NetworkStatus networkStatus    = status.getNetworkStatus();
-
-       MSG_LOG("Id = ", id);
-       MSG_LOG("Network status = ", networkStatus);
-
-       auto reqIdIt = m_SendInfo.requestIdSet.find(id);
-       bool reqFound = reqIdIt != m_SendInfo.requestIdSet.end();
-
-       // Skip unknown request
-       if (!reqFound)
-               return;
-
-       if (networkStatus == Message::NS_Sending)
-               return;
-
-       m_SendInfo.requestIdSet.erase(reqIdIt);
-       bool isLast = m_SendInfo.requestIdSet.empty();
-
-       if (networkStatus == Message::NS_Send_Fail)
-               m_SendInfo.status = Message::NS_Send_Fail;
-       else if (networkStatus == Message::NS_Send_Pending && m_SendInfo.status != Message::NS_Send_Fail)
-               m_SendInfo.status = Message::NS_Send_Pending;
-       else if (m_SendInfo.status == Message::NS_Unknown)
-               m_SendInfo.status = networkStatus;
-
-       if (isLast || m_SendInfo.status == Message::NS_Send_Fail) {
-
-               m_SendInfo.inProgress = false;
-               m_SendInfo.requestIdSet.clear();
-
-               if (m_SendInfo.status == Message::NS_Send_Success) {
-                       m_pSendingPopup->setIcon(IconTextPopup::CheckIcon);
-                       m_pSendingPopup->setText(msgt("WDS_WNOTI_TPOP_SENT_ABB"));
-                       m_pSendingPopup->setTimeOut();
-               } else if (m_SendInfo.status == Message::NS_Send_Fail) {
-                       m_pSendingPopup->setIcon(IconTextPopup::FailedIcon);
-                       m_pSendingPopup->setText(msgt("WDS_MSG_TPOP_SENDING_FAILED_ABB"));
-                       m_pSendingPopup->setTimeOut();
-               } else if (m_SendInfo.status != Message::NS_Send_Pending) {
-                       destroySendingPopup();
-                       showSentWhenServiceBecomesAvailablePopup();
-               }
-
-               notifyOnSendFinished();
-       }
-}
-
-void Composer::onSendingPopupDestroy(Evas *e, Evas_Object *obj, void *event_info)
-{
-       MSG_LOG("");
-       m_pSendingPopup = nullptr;
-       notifyOnCloseSendPopup();
-}
-
-void Composer::onSendingPopupBackButtonPressed(Evas_Object *obj, void *event_info)
-{
-       MSG_LOG("");
-       destroySendingPopup();
-       if (m_SendInfo.inProgress)
-               m_SendInfo.reset();
-}
-
-void Composer::onMmsTextLimitExceededOkPressed(Popup &popup)
-{
-       MSG_LOG("");
-       popup.destroy();
-       sendMessage();
-}
-
-void Composer::onSendAsText(SendingOptionsFrame &sender)
-{
-       MSG_LOG("");
-       removeAudioFiles();
-       sendMessage();
-}
-
-void Composer::onSendAsAudio(SendingOptionsFrame &sender)
-{
-       MSG_LOG("");
-       m_Text.clear();
-       sendMessage();
-}
-
-void Composer::onDestroy(SendingOptionsFrame &sender)
-{
-       MSG_LOG("");
-}
diff --git a/src/Composer/Controller/src/MsgComposerController.cpp b/src/Composer/Controller/src/MsgComposerController.cpp
new file mode 100644 (file)
index 0000000..104be8c
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ConvFrame.h"
+#include "MsgComposerController.h"
+#include "NaviFrameController.h"
+#include "Logger.h"
+
+using namespace Msg;
+
+MsgComposerController::MsgComposerController(NaviFrameController &navi)
+       : m_Navi(navi)
+       , m_Sender()
+       , m_MsgInput(navi)
+       , m_pRecipFrame(nullptr)
+       , m_CloseAfterSent(false)
+       , m_Cmd()
+{
+       m_MsgInput.setListener(this);
+       m_Sender.setListener(this);
+}
+
+MsgComposerController::~MsgComposerController()
+{
+}
+
+bool MsgComposerController::execCmd(const AppControlComposeRef &cmd)
+{
+       m_Cmd = cmd;
+
+       if (!cmd)
+               return false;
+
+       reset();
+       m_CloseAfterSent = true;
+
+       auto &recips = cmd->getRecipientList();
+       if (recips.empty())
+               m_Sender.setRecip({});
+       else
+               m_Sender.setRecip(Recipient(recips.front()));
+
+       std::string text = cmd->getMessageText();
+       m_Sender.setText(text);
+
+       if (recips.empty()) {
+               return launchRecipInput();
+       } else {
+               return m_MsgInput.launch(text);
+       }
+}
+
+void MsgComposerController::reset()
+{
+       m_Cmd.reset();
+       m_Sender.reset();
+       m_MsgInput.reset();
+       m_CloseAfterSent = false;
+}
+
+void MsgComposerController::setRecip(Recipient recip)
+{
+       m_Sender.setRecip(std::move(recip));
+}
+
+void MsgComposerController::setText(std::string text)
+{
+       m_Sender.setText(std::move(text));
+}
+
+bool MsgComposerController::addFile(const std::string &file)
+{
+       return m_Sender.addFile(file);
+}
+
+bool MsgComposerController::addFiles(const std::list<std::string> &files)
+{
+       return m_Sender.addFiles(files);
+}
+
+bool MsgComposerController::launchConv(ThreadId threadId)
+{
+       auto *frame = m_Navi.findTopFrame<ConvFrame>();
+
+       if (frame) {
+               m_Navi.promote(*frame);
+       } else {
+               frame = new ConvFrame(m_Navi);
+               m_Navi.push(*frame);
+       }
+
+       frame->setThreadId(threadId);
+
+       return true;
+}
+
+bool MsgComposerController::launchMsgInput()
+{
+       m_MsgInput.reset();
+       return m_MsgInput.launch();
+}
+
+bool MsgComposerController::launchRecipInput()
+{
+       if (m_pRecipFrame) {
+               m_Navi.promote(*m_pRecipFrame);
+               m_pRecipFrame->clear();
+       } else {
+               auto *frame = new RecipFrame(m_Navi);
+               frame->setListener(this);
+               m_Navi.push(*frame);
+       }
+
+       return true;
+}
+
+void MsgComposerController::onDestroy(RecipFrame &sender)
+{
+       MSG_LOG("");
+       m_pRecipFrame = nullptr;
+}
+
+void MsgComposerController::onRecipSelected(RecipFrame &sender)
+{
+       MSG_LOG("");
+       m_Sender.setRecip(sender.getRecip());
+       m_MsgInput.launch(m_Sender.getText());
+}
+
+void MsgComposerController::onSendRequest(MsgInputController &sender)
+{
+       MSG_LOG("");
+       m_Sender.setText(sender.getInput().text);
+       m_Sender.addFiles(sender.getInput().files);
+       m_Sender.send();
+}
+
+void MsgComposerController::onSendFinished(MsgSenderController &sender)
+{
+       MSG_LOG("");
+}
+
+void MsgComposerController::onCloseSendPopup(MsgSenderController &sender)
+{
+       MSG_LOG("");
+       m_Navi.popGroup(FrameController::ComposerGroup);
+}
+
+void MsgComposerController::onSendStart(MsgSenderController &sender)
+{
+       MSG_LOG("");
+       ThreadId id = sender.getThreadId();
+       if (m_CloseAfterSent || !id.isValid()) {
+               m_Navi.popGroup(FrameController::ComposerGroup);
+       } else {
+               launchConv(id);
+       }
+}
diff --git a/src/Composer/Controller/src/MsgInputController.cpp b/src/Composer/Controller/src/MsgInputController.cpp
new file mode 100644 (file)
index 0000000..ac8722d
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "MsgInputController.h"
+#include "NaviFrameController.h"
+#include "ConvFrame.h"
+#include "App.h"
+#include "Logger.h"
+#include "PathUtils.h"
+
+using namespace Msg;
+
+MsgInputController::MsgInputController(NaviFrameController &navi)
+       : m_Navi(navi)
+       , m_pMsgBodyFrame(nullptr)
+       , m_pListener(nullptr)
+{
+       MSG_LOG("");
+       m_InputSelector.setListener(this);
+}
+
+MsgInputController::~MsgInputController()
+{
+       MSG_LOG("");
+       reset();
+}
+
+void MsgInputController::showMsgBody(const std::string &text, int cursorPos)
+{
+       if (m_pMsgBodyFrame) {
+               m_Navi.promote(*m_pMsgBodyFrame);
+       } else {
+               m_pMsgBodyFrame = new MsgBodyFrame(m_Navi);
+               m_pMsgBodyFrame->setListener(this);
+               m_Navi.push(*m_pMsgBodyFrame);
+       }
+
+       m_pMsgBodyFrame->setText(text);
+       m_pMsgBodyFrame->setCursorPos(cursorPos);
+}
+
+void MsgInputController::reset()
+{
+       m_InputData.files.clear();
+       m_InputData.text.clear();
+       m_InputSelector.terminate();
+       if (m_pMsgBodyFrame) {
+               m_pMsgBodyFrame->setListener(this);
+               m_pMsgBodyFrame->pop();
+               m_pMsgBodyFrame = nullptr;
+       }
+}
+
+const MsgInputController::InputData &MsgInputController::getInput() const
+{
+       return m_InputData;
+}
+
+void MsgInputController::setListener(IMsgInputControllerListener *l)
+{
+       m_pListener = l;
+}
+
+bool MsgInputController::launch(const std::string &text)
+{
+       return text.empty() ? launchSelectView() : launchTextInputView(text);
+}
+
+bool MsgInputController::launchSelectView()
+{
+       return m_InputSelector.launch();
+}
+
+bool MsgInputController::launchVoiceView()
+{
+       return m_InputSelector.launch(InputSelector::VoiceType);
+}
+
+bool MsgInputController::launchEmoticonView()
+{
+       return m_InputSelector.launch(InputSelector::EmoticonType);
+}
+
+bool MsgInputController::launchTextInputView(const std::string &text)
+{
+       showMsgBody(text, text.length());
+       m_InputSelector.terminate();
+       return true;
+}
+
+void MsgInputController::notifyOnSendRequest()
+{
+       if (m_pListener)
+               m_pListener->onSendRequest(*this);
+}
+
+void MsgInputController::onDestroy(MsgBodyFrame &frame)
+{
+       MSG_LOG("");
+       m_pMsgBodyFrame = nullptr;
+}
+
+void MsgInputController::onPress(MsgBodyFrame &frame)
+{
+       m_InputSelector.setText(frame.getRawText());
+       m_InputSelector.setCursorPos(frame.getCursorPos());
+       m_InputSelector.launch(InputSelector::KeyboardType);
+}
+
+void MsgInputController::onSendRequest(MsgBodyFrame &frame)
+{
+       MSG_LOG("");
+       m_InputData.text = frame.getText();
+       notifyOnSendRequest();
+}
+
+void MsgInputController::onKeyboardReply(const std::string &text, int cursorPos)
+{
+       MSG_LOG("");
+       showMsgBody(text, cursorPos);
+}
+
+void MsgInputController::onTemplateReply(const std::string &text)
+{
+       MSG_LOG("");
+       m_InputData.text = text;
+       notifyOnSendRequest();
+}
+
+void MsgInputController::onEmoticonReply(const std::string &emoticon)
+{
+       MSG_LOG("");
+       m_InputData.text = emoticon;
+       notifyOnSendRequest();
+}
+
+void MsgInputController::onVoiceReply(const std::string &text, const std::list<std::string> &fileList)
+{
+       MSG_LOG("");
+
+       // TODO: Dummy file for test
+       #if (0)
+               std::string file = PathUtils::getResourcePath("dummy_res/1.mp3");
+               m_InputData.files.push_back(file);
+               m_InputData.files = fileList;
+       #endif
+
+       notifyOnSendRequest();
+}
+
+void MsgInputController::onTerminate(InputSelector &sender)
+{
+       MSG_LOG("");
+       m_Navi.onTerminate(sender);
+}
diff --git a/src/Composer/Controller/src/MsgInputSelector.cpp b/src/Composer/Controller/src/MsgInputSelector.cpp
deleted file mode 100644 (file)
index 4916b17..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include "MsgInputSelector.h"
-#include "NaviFrameController.h"
-#include "ConvFrame.h"
-#include "App.h"
-#include "Logger.h"
-#include "PathUtils.h"
-
-using namespace Msg;
-
-MsgInputSelector::MsgInputSelector()
-       : m_pMsgBodyFrame(nullptr)
-       , m_CloseAfterSent(false)
-{
-       MSG_LOG("");
-       m_Composer.setListener(this);
-}
-
-MsgInputSelector::~MsgInputSelector()
-{
-       MSG_LOG("");
-       m_Composer.setListener(nullptr);
-       reset();
-}
-
-NaviFrameController &MsgInputSelector::getNavigation()
-{
-       return App::getInst().getNavigation();
-}
-
-void MsgInputSelector::showMsgBody(const std::string &text, int cursorPos)
-{
-       NaviFrameController &navi = getNavigation();
-       if (m_pMsgBodyFrame) {
-               navi.promote(*m_pMsgBodyFrame);
-       } else {
-               m_pMsgBodyFrame = new MsgBodyFrame(navi);
-               m_pMsgBodyFrame->setListener(this);
-               navi.push(*m_pMsgBodyFrame);
-       }
-
-       m_pMsgBodyFrame->setText(text);
-       m_pMsgBodyFrame->setCursorPos(cursorPos);
-}
-
-void MsgInputSelector::setRecip(Recipient recip)
-{
-       m_Composer.setRecip(recip);
-}
-
-bool MsgInputSelector::execCmd(const AppControlComposeRef &cmd)
-{
-       if (!cmd)
-               return false;
-
-       reset();
-       m_CloseAfterSent = true;
-
-       auto &recips = cmd->getRecipientList();
-       if (recips.empty())
-               m_Composer.setRecip({});
-       else
-               m_Composer.setRecip(Recipient(recips.front()));
-
-       std::string text = cmd->getMessageText();
-       bool isEmpty = text.empty();
-       InputSelector::setText(text);
-       m_Composer.setText(std::move(text));
-       if (isEmpty)
-               return launch();
-       else
-               return launch(KeyboardType);
-}
-
-void MsgInputSelector::reset()
-{
-       m_CloseAfterSent = false;
-       m_Composer.reset();
-       m_Composer.clear();
-       if (m_pMsgBodyFrame) {
-               m_pMsgBodyFrame->setListener(this);
-               m_pMsgBodyFrame->pop();
-               m_pMsgBodyFrame = nullptr;
-       }
-}
-
-void MsgInputSelector::navigateToConv(ThreadId threadId)
-{
-       NaviFrameController &navi = getNavigation();
-       auto *frame = navi.findTopFrame<ConvFrame>();
-
-       if (frame) {
-               navi.promote(*frame);
-       } else {
-               frame = new ConvFrame(navi);
-               navi.push(*frame);
-       }
-
-       frame->setThreadId(threadId);
-}
-
-void MsgInputSelector::send()
-{
-       m_Composer.send();
-}
-
-void MsgInputSelector::addDummyAudio()
-{
-       std::string file = PathUtils::getResourcePath("dummy_res/1.mp3");
-       m_Composer.addFile(file);
-}
-
-void MsgInputSelector::onSendStart(Composer &composer)
-{
-       MSG_LOG("");
-       ThreadId id = composer.getThreadId();
-
-       if (m_CloseAfterSent || !id.isValid()) {
-               getNavigation().popGroup(FrameController::ComposerGroup);
-       } else {
-               navigateToConv(id);
-       }
-}
-
-void MsgInputSelector::onSendFinished(Composer &composer)
-{
-       MSG_LOG("");
-}
-
-void MsgInputSelector::onCloseSendPopup(Composer &composer)
-{
-       MSG_LOG("");
-       getNavigation().popGroup(FrameController::ComposerGroup);
-}
-
-void MsgInputSelector::onDestroy(MsgBodyFrame &frame)
-{
-       MSG_LOG("");
-       m_pMsgBodyFrame = nullptr;
-}
-
-void MsgInputSelector::onSendRequest(MsgBodyFrame &frame)
-{
-       MSG_LOG("");
-       m_Composer.setText(frame.getText());
-       send();
-}
-
-void MsgInputSelector::onPress(MsgBodyFrame &frame)
-{
-       setText(frame.getRawText());
-       setCursorPos(frame.getCursorPos());
-       launch(KeyboardType);
-}
-
-void MsgInputSelector::onKeyboardReply(const std::string &text, int cursorPos)
-{
-       MSG_LOG("");
-       showMsgBody(text, cursorPos);
-}
-
-void MsgInputSelector::onTemplateReply(const std::string &text)
-{
-       MSG_LOG("");
-       m_Composer.setText(text);
-       send();
-}
-
-void MsgInputSelector::onEmoticonReply(const std::string &emoticon)
-{
-       MSG_LOG("");
-       m_Composer.setText(emoticon);
-       // addDummyAudio(); // Only for test will be removed
-       send();
-}
-
-void MsgInputSelector::onVoiceReply(const std::string &text, const std::list<std::string> &fileList)
-{
-       MSG_LOG("");
-       m_Composer.setText(text);
-       for (const std::string &file : fileList) {
-               m_Composer.addFile(file);
-       }
-       send();
-}
diff --git a/src/Composer/Controller/src/MsgSenderController.cpp b/src/Composer/Controller/src/MsgSenderController.cpp
new file mode 100644 (file)
index 0000000..e08f375
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MsgSenderController.h"
+#include "App.h"
+#include "MsgEngine.h"
+#include "MsgUtils.h"
+#include "Message.h"
+#include "SystemSettingsManager.h"
+#include "ConnectivityChecker.h"
+#include "Callback.h"
+#include "IconTextPopup.h"
+#include "ToastPopup.h"
+#include "NaviFrameController.h"
+#include "MediaType.h"
+#include "SendingOptionsFrame.h"
+#include "MediaUtils.h"
+#include "FileUtils.h"
+
+using namespace Msg;
+
+MsgSenderController::SendInfo::SendInfo()
+       : requestIdSet()
+       , status(Message::NS_Unknown)
+       , threadId()
+       , inProgress(false)
+{
+}
+
+void MsgSenderController::SendInfo::reset()
+{
+       msgs.clear();
+       inProgress = false;
+       requestIdSet.clear();
+       status = Message::NS_Unknown;
+       threadId.reset();
+}
+
+MsgSenderController::MsgSenderController()
+       : m_pSendingPopup(nullptr)
+       , m_TextMetric()
+       , m_WorkingDir(std::make_shared<WorkingDir>())
+       , m_pListener(nullptr)
+       , m_SendingState(SndState0)
+{
+       App::getInst().getMsgEngine().getTransport().addListener(*this);
+}
+
+MsgSenderController::~MsgSenderController()
+{
+       MSG_LOG("");
+       destroySendingPopup(false);
+       App::getInst().getMsgEngine().getTransport().removeListener(*this);
+}
+
+MsgEngine &MsgSenderController::getMsgEngine()
+{
+       return App::getInst().getMsgEngine();
+}
+
+void MsgSenderController::setListener(IMsgSenderControllerListener *l)
+{
+       m_pListener = l;
+}
+
+void MsgSenderController::setRecip(Recipient recip)
+{
+       m_Recip = std::move(recip);
+}
+
+const Recipient &MsgSenderController::getRecip() const
+{
+       return m_Recip;
+}
+
+const std::string &MsgSenderController::getText() const
+{
+       return m_Text;
+}
+
+const std::list<std::string> &MsgSenderController::getFiles() const
+{
+       return m_Files;
+}
+
+bool MsgSenderController::isMsgBodyEmpty() const
+{
+       return getText().empty() && getFiles().empty();
+}
+
+void MsgSenderController::setText(std::string text)
+{
+       m_Text = std::move(text);
+}
+
+bool MsgSenderController::addFile(const std::string &file)
+{
+       std::string newFilePath = m_WorkingDir->addFile(file);
+       bool isValid = !newFilePath.empty();
+       if (isValid)
+               m_Files.push_back(std::move(newFilePath));
+       return isValid;
+}
+
+bool MsgSenderController::addFiles(const std::list<std::string> &files)
+{
+       bool res = true;
+       for (const std::string &file : files) {
+               res &= addFile(file);
+       }
+       return true;
+}
+
+void MsgSenderController::addFile(MessageMms &msg, const std::string &filePath)
+{
+       constexpr int defaultPageDuration = 5000; // msec
+       if (!filePath.empty()) {
+               MsgPage &msgPage = msg.addPage();
+               MediaTypeData mediaData = getMsgMediaTypeByFileExt(filePath);
+               int pageDuration = 0;
+
+               if (mediaData.type == MsgMedia::VideoType || mediaData.type == MsgMedia::AudioType)
+                       pageDuration = MediaUtils::getDuration(filePath);
+
+               if (pageDuration <= 0)
+                       pageDuration = defaultPageDuration;
+
+               msgPage.setPageDuration(pageDuration);
+               MsgMedia &media = msgPage.addMedia();
+               media.setFilePath(filePath);
+       }
+}
+
+void MsgSenderController::removeAudioFiles()
+{
+       decltype(m_Files) newFileList;
+       for (std::string &file : m_Files) {
+               if (getMsgMediaTypeByFileExt(file).type != MsgMedia::AudioType)
+                       newFileList.push_back(std::move(file));
+       }
+       m_Files = std::move(newFileList);
+}
+
+void MsgSenderController::send()
+{
+       m_SendingState = SndState0;
+       sendMessage();
+}
+
+ThreadId MsgSenderController::getThreadId() const
+{
+       return m_SendInfo.threadId;
+}
+
+void MsgSenderController::reset()
+{
+       m_SendInfo.reset();
+       // TODO: check popups
+}
+
+void MsgSenderController::clear()
+{
+       m_Recip.clear();
+       m_Text.clear();
+       m_Files.clear();
+       if (m_WorkingDir)
+               m_WorkingDir->clear();
+}
+
+bool MsgSenderController::readAddress(Message &msg)
+{
+       if(m_Recip.isValid()) {
+               MsgAddress &msgAddr = msg.addAddress();
+               msgAddr.setAddress(m_Recip.getAddress());
+               msgAddr.setRecipientType(MsgAddress::To);
+               msgAddr.setAddressType(MsgAddress::Phone);
+               return true;
+       }
+
+       return false;
+}
+
+void MsgSenderController::setText(MessageRef msg, const std::string &text)
+{
+       if (msg && !text.empty()) {
+               if (auto *sms = dynamic_cast<MessageSMS*>(msg.get()))
+                       setText(*sms, text);
+               else if (auto *mms = dynamic_cast<MessageMms*>(msg.get()))
+                       setText(*mms, text);
+       }
+}
+
+void MsgSenderController::setText(MessageSMS &msg, const std::string &text)
+{
+       msg.setText(text);
+}
+
+void MsgSenderController::setText(MessageMms &msg, const std::string &text)
+{
+       static const int defaultPageDuration = 5000; // msec
+       std::string filePath = m_WorkingDir->addTextFile(text);
+       if (!filePath.empty()) {
+               MsgPage &page = msg.addPage();
+               page.setPageDuration(defaultPageDuration);
+               page.addMedia().setFilePath(filePath);
+       }
+}
+
+bool MsgSenderController::checkConnectivity(Message::Type type)
+{
+       auto &checker = App::getInst().getNavigation().getConnectivityChecker();
+       return MsgUtils::isMms(type) ? checker.isReadyToSendMms()
+                                                                : checker.isReadyToSendSms();
+}
+
+void MsgSenderController::navigateToSendingOptions()
+{
+       auto &navi = App::getInst().getNavigation();
+       auto *frame = new SendingOptionsFrame(navi);
+       frame->setListener(this);
+       navi.push(*frame);
+}
+
+bool MsgSenderController::checkSendingOptions()
+{
+       if (!getMsgEngine().getSettings().getSendAsAudio() || m_Files.empty())
+               return true;
+
+       bool onlyAudio = true;
+       long long msgSize = 0;
+       for (const std::string &file : m_Files) {
+               onlyAudio &= getMsgMediaTypeByFileExt(file).type == MsgMedia::AudioType;
+               if (onlyAudio)
+                       msgSize += FileUtils::getFileSize(file);
+               else
+                       break;
+       }
+
+       if (onlyAudio && msgSize <= getMsgEngine().getSettings().getMaxMmsSize()) {
+               navigateToSendingOptions();
+               return false;
+       }
+       return true;
+}
+
+void MsgSenderController::sendMessage()
+{
+       switch (m_SendingState) {
+       case SndState0:
+               m_SendingState = SndState1;
+               sendState0();
+               break;
+       case SndState1:
+               m_SendingState = SndState2;
+               sendState1();
+               break;
+       case SndState2:
+               m_SendingState = SndState3;
+               sendState2();
+               break;
+       case SndState3:
+               m_SendingState = SndState4;
+               sendState3();
+               break;
+       case SndState4:
+               m_SendingState = SndStateEnd;
+               sendState4();
+               break;
+       case SndStateEnd:
+               break;
+       }
+}
+
+void MsgSenderController::sendState0()
+{
+       MSG_LOG("");
+       reset();
+       destroySendingPopup(false);
+
+       if (!checkSendingOptions())
+               return;
+
+       removeAudioFiles();
+       sendMessage();
+}
+
+void MsgSenderController::sendState1()
+{
+       MSG_LOG("");
+       int smsCount = 0;
+       int mmsCount = 0;
+
+       m_SendInfo.msgs = createMessage();
+
+       MsgTextMetric textMetric;
+       getMsgEngine().getComposer().calculateTextMetric(m_Text, textMetric);
+
+       for (MessageRef msg : m_SendInfo.msgs) {
+               if (msg->getType() == Message::MT_MMS)
+                       ++mmsCount;
+               else if (msg->getType() == Message::MT_SMS)
+                       ++smsCount;
+       }
+       bool isTextMms = mmsCount > 0 && m_Files.empty();
+       if (isTextMms)
+               showMmsTextLimitExceededPopup(smsCount, mmsCount, textMetric.maxSmsLen);
+       else
+               sendMessage();
+}
+
+void MsgSenderController::sendState2()
+{
+       MSG_LOG("");
+       sendMessage();
+}
+
+void MsgSenderController::sendState3()
+{
+       MSG_LOG("");
+       if (m_SendInfo.msgs.empty()) {
+               MSG_LOG_ERROR("m_SendInfo.msgs is empty")
+               return;
+       }
+
+       // Check connectivity:
+       if (!checkConnectivity(m_SendInfo.msgs[0]->getType()))
+                return;
+
+       sendMessage();
+}
+
+void MsgSenderController::sendState4()
+{
+       MSG_LOG("");
+
+       // Send message:
+       MsgTransport::SendResult sendRes = MsgTransport::SendFail;
+       MessageRef lastSentMsg;
+
+       for (MessageRef msg : m_SendInfo.msgs) {
+               lastSentMsg = msg;
+               RequestId reqId;
+               sendRes = getMsgEngine().getTransport().sendMessage(msg, &m_SendInfo.threadId, &reqId);
+
+               MSG_LOG("Send result = ", sendRes);
+               MSG_LOG("Thread id = ", m_SendInfo.threadId);
+               MSG_LOG("Request id = ", reqId);
+
+               if (sendRes != MsgTransport::SendSuccess)
+                       break;
+
+               m_SendInfo.inProgress = true;
+               m_SendInfo.requestIdSet.insert(reqId);
+       }
+
+       if (sendRes == MsgTransport::SendSuccess && m_SendInfo.threadId.isValid()) {
+               showSendingProgressPopup();
+               notifyOnSendStart();
+       } else {
+               notifyOnSendStart();
+               handleSendResult(sendRes);
+       }
+
+       sendMessage();
+}
+
+
+std::vector<MessageRef> MsgSenderController::createMessage()
+{
+       std::vector<MessageRef> msgList;
+       auto &msgEngine = getMsgEngine();
+       const int maxMsgSize = msgEngine.getSettings().getMaxMmsSize();
+
+       if (maxMsgSize <= 0) {
+               MSG_LOG_ERROR("getMaxMmsSize() returns 0");
+               return {};
+       }
+
+       MSG_LOG("");
+       if (m_Files.empty()) {
+               MSG_LOG("");
+               // Text messages:
+               auto textList = MsgUtils::splitUtf8String(m_Text, maxMsgSize);
+               for (auto &&text : textList) {
+                       MsgTextMetric metric;
+                       msgEngine.getComposer().calculateTextMetric(m_Text, metric);
+                       Message::Type type = metric.isMms ? Message::MT_MMS : Message::MT_SMS;
+                       auto msg = msgEngine.getComposer().createMessage(type);
+                       if (msg && readAddress(*msg)) {
+                               setText(msg, text);
+                               msgList.push_back(msg);
+                       }
+               }
+       } else {
+               MSG_LOG("");
+               // Create MMS:
+               auto mms = msgEngine.getComposer().createMms();
+               if (mms) {
+                       if (readAddress(*mms)) {
+                               for (const std::string &file : m_Files)
+                                       addFile(*mms, file);
+                               msgList.push_back(mms);
+                       }
+               }
+       }
+       return msgList;
+}
+
+void MsgSenderController::notifyOnSendStart()
+{
+       if (m_pListener)
+               m_pListener->onSendStart(*this);
+}
+
+void MsgSenderController::notifyOnSendFinished()
+{
+       if (m_pListener)
+               m_pListener->onSendFinished(*this);
+}
+
+void MsgSenderController::notifyOnCloseSendPopup()
+{
+       if (m_pListener)
+               m_pListener->onCloseSendPopup(*this);
+}
+
+void MsgSenderController::handleSendResult(MsgTransport::SendResult result)
+{
+       notifyOnSendFinished();
+}
+
+void MsgSenderController::destroySendingPopup(bool anim)
+{
+       if (m_pSendingPopup) {
+               m_pSendingPopup->destroy(anim);
+               m_pSendingPopup = nullptr;
+       }
+}
+
+void MsgSenderController::showSendingProgressPopup()
+{
+       if (!m_pSendingPopup) {
+               m_pSendingPopup = new IconTextPopup;
+               m_pSendingPopup->setDismissByBackButtonFlag(false);
+               m_pSendingPopup->addEventCb(EVAS_CALLBACK_DEL, makeCbFirst(&MsgSenderController::onSendingPopupDestroy), this);
+               m_pSendingPopup->addHwButtonEvent(EEXT_CALLBACK_BACK, makeCbFirst(&MsgSenderController::onSendingPopupBackButtonPressed), this);
+               m_pSendingPopup->setIcon(IconTextPopup::ProgressIcon);
+               m_pSendingPopup->setText(msgt("IDS_MSG_BODY_SENDING_ING_M_STATUS_ABB"));
+               m_pSendingPopup->show();
+       }
+}
+
+void MsgSenderController::showMmsTextLimitExceededPopup(int smsCount, int mmsCount, int maxChars)
+{
+       auto *popup = new StandardPopup(StandardPopup::buttons2Style);
+       std::string popupMessage = msgArgs("WDS_MSG_BODY_MAXIMUM_NUMBER_OF_CHARACTERS_HPD_EXCEEDED", maxChars);
+       popupMessage += "<br>";
+
+       if (smsCount == 0) {
+               if (mmsCount == 1)
+                       popupMessage += msg("WDS_MSG_POP_SEND_AS_MMS_Q");
+               else
+                       popupMessage += msgArgs("WDS_MSG_BODY_MESSAGE_WILL_BE_SENT_AS_PD_MMS_MESSAGES", mmsCount);
+       } else {
+               popupMessage += msgArgs("WDS_MSG_BODY_MESSAGE_WILL_BE_SENT_AS_PD_MMS_MESSAGES_AND_1_SMS_MESSAGE", mmsCount);
+       }
+
+       popup->setText(popupMessage);
+       popup->addLeftButton(CANCEL_BUTTON_POPUP);
+       popup->addRightButton(OK_BUTTON_POPUP, makeCbLast(&MsgSenderController::onMmsTextLimitExceededOkPressed), this);
+       popup->show();
+}
+
+void MsgSenderController::showSentWhenServiceBecomesAvailablePopup()
+{
+       auto *popup = new StandardPopup(StandardPopup::buttons1Style);
+       popup->setText(msgt("WDS_MSG_BODY_UNABLE_TO_SEND_MESSAGE_IT_WILL_BE_SENT_WHEN_SERVICE_BECOMES_AVAILABLE"));
+       popup->addBottomButton(msgt("WDS_MSG_ACBUTTON_OK_ABB"));
+       popup->show();
+}
+
+void MsgSenderController::onMsgTransportSentStatus(const MsgSentStatus &status)
+{
+       MSG_LOG("");
+       RequestId id = status.getId();
+       Message::NetworkStatus networkStatus    = status.getNetworkStatus();
+
+       MSG_LOG("Id = ", id);
+       MSG_LOG("Network status = ", networkStatus);
+
+       auto reqIdIt = m_SendInfo.requestIdSet.find(id);
+       bool reqFound = reqIdIt != m_SendInfo.requestIdSet.end();
+
+       // Skip unknown request
+       if (!reqFound)
+               return;
+
+       if (networkStatus == Message::NS_Sending)
+               return;
+
+       m_SendInfo.requestIdSet.erase(reqIdIt);
+       bool isLast = m_SendInfo.requestIdSet.empty();
+
+       if (networkStatus == Message::NS_Send_Fail)
+               m_SendInfo.status = Message::NS_Send_Fail;
+       else if (networkStatus == Message::NS_Send_Pending && m_SendInfo.status != Message::NS_Send_Fail)
+               m_SendInfo.status = Message::NS_Send_Pending;
+       else if (m_SendInfo.status == Message::NS_Unknown)
+               m_SendInfo.status = networkStatus;
+
+       if (isLast || m_SendInfo.status == Message::NS_Send_Fail) {
+
+               m_SendInfo.inProgress = false;
+               m_SendInfo.requestIdSet.clear();
+
+               if (m_SendInfo.status == Message::NS_Send_Success) {
+                       m_pSendingPopup->setIcon(IconTextPopup::CheckIcon);
+                       m_pSendingPopup->setText(msgt("WDS_WNOTI_TPOP_SENT_ABB"));
+                       m_pSendingPopup->setTimeOut();
+               } else if (m_SendInfo.status == Message::NS_Send_Fail) {
+                       m_pSendingPopup->setIcon(IconTextPopup::FailedIcon);
+                       m_pSendingPopup->setText(msgt("WDS_MSG_TPOP_SENDING_FAILED_ABB"));
+                       m_pSendingPopup->setTimeOut();
+               } else if (m_SendInfo.status != Message::NS_Send_Pending) {
+                       destroySendingPopup();
+                       showSentWhenServiceBecomesAvailablePopup();
+               }
+
+               notifyOnSendFinished();
+       }
+}
+
+void MsgSenderController::onSendingPopupDestroy(Evas *e, Evas_Object *obj, void *event_info)
+{
+       MSG_LOG("");
+       m_pSendingPopup = nullptr;
+       notifyOnCloseSendPopup();
+}
+
+void MsgSenderController::onSendingPopupBackButtonPressed(Evas_Object *obj, void *event_info)
+{
+       MSG_LOG("");
+       destroySendingPopup();
+       if (m_SendInfo.inProgress)
+               m_SendInfo.reset();
+}
+
+void MsgSenderController::onMmsTextLimitExceededOkPressed(Popup &popup)
+{
+       MSG_LOG("");
+       popup.destroy();
+       sendMessage();
+}
+
+void MsgSenderController::onSendAsText(SendingOptionsFrame &sender)
+{
+       MSG_LOG("");
+       removeAudioFiles();
+       sendMessage();
+}
+
+void MsgSenderController::onSendAsAudio(SendingOptionsFrame &sender)
+{
+       MSG_LOG("");
+       m_Text.clear();
+       sendMessage();
+}
+
+void MsgSenderController::onDestroy(SendingOptionsFrame &sender)
+{
+       MSG_LOG("");
+}
index 46e7c9e52aaecee1652c0eb3d72974761c4ecc73..d0d519ddf8d8d24658fe2a21f7e9227ef7aab6e0 100644 (file)
@@ -33,6 +33,7 @@ RecipFrame::RecipFrame(NaviFrameController &parent)
        , m_pNextButton(nullptr)
        , m_pRecipField(nullptr)
        , m_pInputFrame(nullptr)
+       , m_pListener(nullptr)
 {
        MSG_LOG("");
 
@@ -61,10 +62,28 @@ bool RecipFrame::execCmd(const AppControlComposeRef &cmd)
        return true;
 }
 
+void RecipFrame::setListener(IRecipFrameListener *l)
+{
+       m_pListener = l;
+}
+
+const Recipient &RecipFrame::getRecip() const
+{
+       return m_Recip;
+}
+
+void RecipFrame::clear()
+{
+       m_pRecipField->getEntry().clear();
+       m_Recip.clear();
+}
+
 RecipFrame::~RecipFrame()
 {
        MSG_LOG("");
        App::getInst().getContactManager().removeListener(*this);
+       if (m_pListener)
+               m_pListener->onDestroy(*this);
 }
 
 void RecipFrame::prepareLayouts()
@@ -142,19 +161,6 @@ void RecipFrame::showInputFrame()
        }
 }
 
-void RecipFrame::navigateToMsgInput()
-{
-       MsgInputSelector &inputSelector = getParent().getInputSelector();
-       inputSelector.reset();
-
-       if (m_ComposeCmd)
-               inputSelector.execCmd(m_ComposeCmd);
-       else
-               inputSelector.launch();
-
-       inputSelector.setRecip(m_Recip);
-}
-
 void RecipFrame::onAttached(ViewItem &item)
 {
        MSG_LOG("");
@@ -171,10 +177,12 @@ void RecipFrame::onHwBackButtonPressed(Evas_Object *obj, void *event_info)
 void RecipFrame::onNextButtonClicked(Evas_Object *obj, void *event)
 {
        MSG_LOG("");
-       if (m_Recip.isValid())
-               navigateToMsgInput();
-       else
+       if (m_Recip.isValid()) {
+               if (m_pListener)
+                       m_pListener->onRecipSelected(*this);
+       } else {
                ToastPopup::toast(msgt("IDS_MSG_HEADER_INVALID_RECIPIENT_ABB"));
+       }
 }
 
 void RecipFrame::onFieldClicked(RecipFieldView &obj)
index 129f08e51f12a7e8798794a387af9b6e3e36525b..f36c9995b8befcd8ec73a715fc708e2128b69d4e 100644 (file)
@@ -27,6 +27,8 @@
 #include "NaviFrameController.h"
 #include "RecipListFrame.h"
 #include "PhoneNumberUtils.h"
+#include "ConnectivityChecker.h"
+#include "MsgComposerController.h"
 
 using namespace Msg;
 
@@ -252,10 +254,10 @@ void ConvFrame::reply()
 {
        ConnectivityChecker &checker = getParent().getConnectivityChecker();
        if (checker.isFlightModeDisabled()) {
-               MsgInputSelector &inputSelector = getParent().getInputSelector();
-               inputSelector.reset();
-               inputSelector.setRecip(m_pList->getRecip());
-               inputSelector.launch();
+               auto &composer = getParent().getMsgComposer();
+               composer.reset();
+               composer.setRecip(m_pList->getRecip());
+               composer.launchMsgInput();
        }
 }
 
index 5b735227139519fbb5138758fcfaedaa5d410c96..6716d2d07b0818650ed615e14808a27985c46a66 100644 (file)
@@ -32,6 +32,7 @@
 #include "BubbleAudioEntity.h"
 #include "BubbleImageEntity.h"
 #include "NaviFrameController.h"
+#include "ConnectivityChecker.h"
 
 #include <algorithm>
 
index cc59c4e464aad610dd89c14cf8a2e5fc77ca7651..c5b99888b659a643315f8c474a8ccade10649efd 100644 (file)
@@ -24,7 +24,6 @@
 #include "LangUtils.h"
 #include "App.h"
 #include "Resource.h"
-#include "RecipFrame.h"
 #include "ConvFrame.h"
 #include "ThreadListItem.h"
 #include "DefaultLayout.h"
@@ -32,6 +31,8 @@
 #include "SelectButton.h"
 #include "MoreOption.h"
 #include "NaviFrameController.h"
+#include "ConnectivityChecker.h"
+#include "MsgComposerController.h"
 
 using namespace Msg;
 
@@ -209,8 +210,8 @@ void MsgThreadFrame::navigateToConvFrame(ThreadId id)
 void MsgThreadFrame::composeMsg()
 {
        if (getParent().getConnectivityChecker().isFlightModeDisabled()) {
-               auto *frame = new RecipFrame(getParent());
-               getParent().push(*frame);
+               getParent().getMsgComposer().reset();
+               getParent().getMsgComposer().launchRecipInput();
        }
 }