Skip to content

Commit

Permalink
Pull request #474: mtokar-MCA-4193_contextual_data_new_strategy
Browse files Browse the repository at this point in the history
Merge in MML/infobip-mobile-messaging-android from mtokar-MCA-4193_contextual_data_new_strategy to master

Squashed commit of the following:

commit 96c3470c87f177006daff8c9a640c397286fc89a
Author: Matus Tokar <[email protected]>
Date:   Wed Dec 18 12:32:34 2024 +0100

    review fixes

commit 108a6ff51e9e024cab318a1e79c602e6923fc0ac
Author: Matus Tokar <[email protected]>
Date:   Sun Dec 15 17:40:10 2024 +0100

    new context data strategy
  • Loading branch information
Matuš Tokar authored and Matuš Tokar committed Dec 19, 2024
1 parent dc58316 commit 9672270
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import androidx.fragment.app.FragmentManager;

import org.infobip.mobile.messaging.MobileMessaging;
import org.infobip.mobile.messaging.chat.core.MultithreadStrategy;
import org.infobip.mobile.messaging.chat.view.InAppChatEventsListener;
import org.infobip.mobile.messaging.chat.view.styles.InAppChatTheme;

Expand Down Expand Up @@ -78,14 +79,16 @@ public synchronized static InAppChat getInstance(Context context) {

/**
* Adds in-app chat Fragment to the Activity or shows it if it was already added and hidden.
*
* @param fragmentManager manager to make interactions with Fragment
* @param containerId identifier of the container in-app chat Fragment is to be placed in
* @param containerId identifier of the container in-app chat Fragment is to be placed in
*/
public abstract void showInAppChatFragment(FragmentManager fragmentManager, int containerId);

/**
* Hides in-app chat Fragment, so that all views, especially in-app chat webView,
* stays in memory and chat connection is active while fragment is hidden.
*
* @param fragmentManager manager to make interactions with Fragment
* @see InAppChat#hideInAppChatFragment(FragmentManager, Boolean)
*/
Expand All @@ -95,13 +98,12 @@ public synchronized static InAppChat getInstance(Context context) {
* Hides in-app chat Fragment, so that all views, especially in-app chat webView, stays in memory.
* You can control whether chat connection stays active while fragment is hidden.
*
* @param fragmentManager manager to make interactions with Fragment
* @param disconnectChatWhenHidden if true disconnects chat connection when fragment is hidden, otherwise chat connection stays active
* @apiNote By chat connection you can control push notifications.
* Push notifications are active only when chat connection is not active.
* Disconnect chat if you want to receive push notifications while fragment is hidden.
* Chat connection is re-established when {@link InAppChat#showInAppChatFragment(FragmentManager, int)} is called.
*
* @param fragmentManager manager to make interactions with Fragment
* @param disconnectChatWhenHidden if true disconnects chat connection when fragment is hidden, otherwise chat connection stays active
* @see InAppChat#hideInAppChatFragment(FragmentManager)
*/
public abstract void hideInAppChatFragment(FragmentManager fragmentManager, Boolean disconnectChatWhenHidden);
Expand Down Expand Up @@ -140,16 +142,29 @@ public synchronized static InAppChat getInstance(Context context) {
*
* @param data contextual data in the form of JSON string
* @param allMultiThreadStrategy multithread strategy flag, true -> ALL, false -> ACTIVE
* @deprecated Use {@link InAppChat#sendContextualData(String, MultithreadStrategy, MobileMessaging.ResultListener)} instead
*/
@Deprecated
public abstract void sendContextualData(@Nullable String data, @Nullable Boolean allMultiThreadStrategy);

/**
* Set contextual data of the Livechat Widget with false (ACTIVE) value for multithread strategy.
* Set contextual data of the Livechat Widget.
* If the function is called when the chat is loaded,
* data will be sent immediately, otherwise they will be sent to the chat once it is loaded.
* Every function invocation will overwrite the previous contextual data.
*
* @param data contextual data in the form of JSON string
* @param data contextual data in the form of JSON string
* @param flag multithread strategy [MultithreadStrategy]
*/
public abstract void sendContextualData(@Nullable String data, @Nullable MultithreadStrategy flag);

/**
* Set contextual data of the Livechat Widget with false (MultithreadStrategy.ACTIVE) value for multithread strategy.
* If the function is called when the chat is loaded,
* data will be sent immediately, otherwise they will be sent to the chat once it is loaded.
* Every function invocation will overwrite the previous contextual data.
*
* @param data contextual data in the form of JSON string
*/
public abstract void sendContextualData(@Nullable String data);

Expand All @@ -163,9 +178,24 @@ public synchronized static InAppChat getInstance(Context context) {
* @param allMultiThreadStrategy multithread strategy flag, true -> ALL, false -> ACTIVE
* @param resultListener listener to report the result on
* @see MobileMessaging.ResultListener
* @deprecated Use {@link InAppChat#sendContextualData(String, MultithreadStrategy, MobileMessaging.ResultListener)} instead
*/
@Deprecated
public abstract void sendContextualData(@Nullable String data, @Nullable Boolean allMultiThreadStrategy, @Nullable MobileMessaging.ResultListener<Void> resultListener);

/**
* Set contextual data of the Livechat Widget.
* If the function is called when the chat is loaded,
* data will be sent immediately, otherwise they will be sent to the chat once it is loaded.
* Every function invocation will overwrite the previous contextual data.
*
* @param data contextual data in the form of JSON string
* @param flag multithread strategy [MultithreadStrategy]
* @param resultListener listener to report the result on
* @see MobileMessaging.ResultListener
*/
public abstract void sendContextualData(@Nullable String data, @Nullable MultithreadStrategy flag, @Nullable MobileMessaging.ResultListener<Void> resultListener);

/**
* Set {@link JwtProvider} to give in-app chat ability to authenticate.
*
Expand All @@ -185,6 +215,7 @@ public synchronized static InAppChat getInstance(Context context) {

/**
* Navigates to THREAD_LIST view in multithread widget if in-app chat is shown as Fragment.
*
* @see org.infobip.mobile.messaging.chat.core.InAppChatWidgetView
*/
public abstract void showThreadsList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.TaskStackBuilder;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import org.infobip.mobile.messaging.Event;
import org.infobip.mobile.messaging.Message;
import org.infobip.mobile.messaging.MessageHandlerModule;
Expand All @@ -21,6 +29,7 @@
import org.infobip.mobile.messaging.app.ActivityLifecycleMonitor;
import org.infobip.mobile.messaging.chat.core.InAppChatBroadcasterImpl;
import org.infobip.mobile.messaging.chat.core.InAppChatScreenImpl;
import org.infobip.mobile.messaging.chat.core.MultithreadStrategy;
import org.infobip.mobile.messaging.chat.core.SessionStorage;
import org.infobip.mobile.messaging.chat.mobileapi.InAppChatSynchronizer;
import org.infobip.mobile.messaging.chat.mobileapi.LivechatRegistrationChecker;
Expand All @@ -45,14 +54,6 @@
import java.util.Locale;
import java.util.concurrent.Executors;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.TaskStackBuilder;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;


public class InAppChatImpl extends InAppChat implements MessageHandlerModule {

Expand Down Expand Up @@ -379,7 +380,7 @@ public void setLanguage(String language, MobileMessaging.ResultListener<String>

@Override
public void sendContextualData(@Nullable String data) {
sendContextualData(data, false, new MobileMessaging.ResultListener<Void>() {
sendContextualData(data, MultithreadStrategy.ACTIVE, new MobileMessaging.ResultListener<Void>() {
@Override
public void onResult(Result<Void, MobileMessagingError> result) {
if (!result.isSuccess()) {
Expand All @@ -401,21 +402,39 @@ public void onResult(Result<Void, MobileMessagingError> result) {
});
}

@Override
public void sendContextualData(@Nullable String data, @Nullable MultithreadStrategy flag) {
sendContextualData(data, flag, new MobileMessaging.ResultListener<Void>() {
@Override
public void onResult(Result<Void, MobileMessagingError> result) {
if (!result.isSuccess()) {
MobileMessagingLogger.e(TAG,"Send contextual data error: " + result.getError().getMessage());
}
}
});
}

@Override
public void sendContextualData(@Nullable String data, @Nullable Boolean allMultiThreadStrategy, @Nullable MobileMessaging.ResultListener<Void> resultListener) {
MultithreadStrategy flag = Boolean.TRUE.equals(allMultiThreadStrategy) ? MultithreadStrategy.ALL : MultithreadStrategy.ACTIVE;
sendContextualData(data, flag, resultListener);
}

@Override
public void sendContextualData(@Nullable String data, @Nullable MultithreadStrategy flag, @Nullable MobileMessaging.ResultListener<Void> resultListener) {
Result<Void, MobileMessagingError> result = null;
try {
if (data == null || data.isEmpty()) {
sessionStorage().setContextualData(null);
result = new Result<>(MobileMessagingError.createFrom(new IllegalArgumentException("Could not send contextual data. Data is null or empty.")));
} else if (allMultiThreadStrategy == null) {
} else if (flag == null) {
sessionStorage().setContextualData(null);
result = new Result<>(MobileMessagingError.createFrom(new IllegalArgumentException("Could not send contextual data. Strategy flag is null.")));
} else if (inAppChatWVFragment != null) {
inAppChatWVFragment.sendContextualData(data, allMultiThreadStrategy);
inAppChatWVFragment.sendContextualData(data, flag);
result = new Result<>(null);
} else {
sessionStorage().setContextualData(new ContextualData(data, allMultiThreadStrategy));
sessionStorage().setContextualData(new ContextualData(data, flag));
MobileMessagingLogger.d(TAG,"Contextual data is stored, will be sent once chat is loaded.");
result = new Result<>(null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ public interface InAppChatClient {
void setLanguage(Locale locale);

/**
* Send contextual metadata of conversation and a InAppChatMultiThreadFlag flag
* Send contextual metadata of conversation and a MultithreadStrategy flag
*
* @param data contextual data in the form of JSON string
* @param multiThreadFlag multithread strategy flag
* @param resultListener result listener
*/
void sendContextualData(String data, InAppChatMultiThreadFlag multiThreadFlag, MobileMessaging.ResultListener<String> resultListener);
void sendContextualData(String data, MultithreadStrategy multiThreadFlag, MobileMessaging.ResultListener<String> resultListener);

/**
* Change destination from thread to list in multiThread widget. For non multiThread widget it does nothing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void setLanguage(Locale locale) {
}

@Override
public void sendContextualData(String data, InAppChatMultiThreadFlag multiThreadFlag, MobileMessaging.ResultListener<String> resultListener) {
public void sendContextualData(String data, MultithreadStrategy multiThreadFlag, MobileMessaging.ResultListener<String> resultListener) {
if (data == null || data.isEmpty()){
resultListener.onResult(new Result<>(MobileMessagingError.createFrom(new IllegalArgumentException("Could not send contextual data. Data is null or empty."))));
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.infobip.mobile.messaging.chat.core;

public enum InAppChatMultiThreadFlag {
public enum MultithreadStrategy {
ACTIVE,
ALL
ALL,
ALL_PLUS_NEW
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.infobip.mobile.messaging.chat.models

import org.infobip.mobile.messaging.chat.core.MultithreadStrategy

internal data class ContextualData(
val data: String,
val allMultiThreadStrategy: Boolean
val allMultiThreadStrategy: MultithreadStrategy
)
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import org.infobip.mobile.messaging.chat.R
import org.infobip.mobile.messaging.chat.attachments.InAppChatAttachmentHelper
import org.infobip.mobile.messaging.chat.attachments.InAppChatMobileAttachment
import org.infobip.mobile.messaging.chat.core.InAppChatWidgetView
import org.infobip.mobile.messaging.chat.core.MultithreadStrategy
import org.infobip.mobile.messaging.chat.core.SessionStorage
import org.infobip.mobile.messaging.chat.databinding.IbFragmentChatBinding
import org.infobip.mobile.messaging.chat.models.ContextualData
Expand Down Expand Up @@ -354,15 +355,34 @@ class InAppChatFragment : Fragment(), InAppChatFragmentActivityResultDelegate.Re
* Every function invocation will overwrite the previous contextual data.
*
*
* @param data contextual data in the form of JSON string
* @param data contextual data in the form of JSON string
* @param allMultiThreadStrategy multithread strategy flag, true -> ALL, false -> ACTIVE
* @see [InAppChatFragment.EventsListener.onChatLoaded] to detect if chat is loaded
*/
@Deprecated("Use sendContextualData(data: String, flag: MultithreadStrategy) instead")
fun sendContextualData(data: String, allMultiThreadStrategy: Boolean) {
val flag = if (allMultiThreadStrategy) MultithreadStrategy.ALL else MultithreadStrategy.ACTIVE
sendContextualData(data, flag)
}

/**
* Set contextual data of the Livechat Widget.
*
* If the function is called when [InAppChatFragment] is attached and the chat is loaded,
* data will be sent immediately, otherwise they will be sent to the chat once it is loaded.
*
* Every function invocation will overwrite the previous contextual data.
*
*
* @param data contextual data in the form of JSON string
* @param flag multithread strategy [MultithreadStrategy]
* @see [InAppChatFragment.EventsListener.onChatLoaded] to detect if chat is loaded
*/
fun sendContextualData(data: String, flag: MultithreadStrategy) {
withBinding(
action = { it.ibLcChat.sendContextualData(data, allMultiThreadStrategy) },
action = { it.ibLcChat.sendContextualData(data, flag) },
fallback = {
SessionStorage.contextualData = ContextualData(data, allMultiThreadStrategy)
SessionStorage.contextualData = ContextualData(data, flag)
MobileMessagingLogger.d(TAG, "Contextual data is stored, will be sent once chat is loaded.")
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,30 @@ class InAppChatView @JvmOverloads constructor(
*
* Every function invocation will overwrite the previous contextual data.
*
* @param data contextual data in the form of JSON string
* @param data contextual data in the form of JSON string
* @param allMultiThreadStrategy multithread strategy flag, true -> ALL, false -> ACTIVE
* @see [InAppChatView.EventsListener.onChatLoaded] to detect if chat is loaded
*/
@Deprecated("Use sendContextualData(data: String, flag: MultithreadStrategy) instead")
fun sendContextualData(data: String, allMultiThreadStrategy: Boolean) {
val flag = if (allMultiThreadStrategy) MultithreadStrategy.ALL else MultithreadStrategy.ACTIVE
sendContextualData(data, flag)
}

/**
* Set contextual data of the Livechat Widget.
*
* If the function is called when the chat is loaded,
* data will be sent immediately, otherwise they will be sent to the chat once it is loaded.
*
* Every function invocation will overwrite the previous contextual data.
*
* @param data contextual data in the form of JSON string
* @param flag multithread strategy [MultithreadStrategy]
* @see [InAppChatView.EventsListener.onChatLoaded] to detect if chat is loaded
*/
fun sendContextualData(data: String, flag: MultithreadStrategy) {
if (isChatLoaded) {
val flag = if (allMultiThreadStrategy) InAppChatMultiThreadFlag.ALL else InAppChatMultiThreadFlag.ACTIVE
val listener = object : ResultListener<String>() {
override fun onResult(result: Result<String, MobileMessagingError>) {
SessionStorage.contextualData = null
Expand All @@ -264,7 +281,7 @@ class InAppChatView @JvmOverloads constructor(
}
inAppChatClient.sendContextualData(data, flag, listener)
} else {
SessionStorage.contextualData = ContextualData(data, allMultiThreadStrategy)
SessionStorage.contextualData = ContextualData(data, flag)
MobileMessagingLogger.d(TAG, "Contextual data is stored, will be sent once chat is loaded.")
}
}
Expand Down

0 comments on commit 9672270

Please sign in to comment.