()
+ fun getInstance(instanceId: Int): ServiceLocator {
+ if (locatorMap.containsKey(instanceId)) {
+ return locatorMap[instanceId]!!
+ }
+ locatorMap[instanceId] = ServiceLocator()
+ return locatorMap[instanceId]!!
+ }
+ }
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/logger/DefaultLogger.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/logger/DefaultLogger.kt
new file mode 100644
index 000000000..d5d2bf2cb
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/logger/DefaultLogger.kt
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.logger
+
+import android.util.Log
+
+internal class DefaultLogger : Logger {
+
+ private val tag = "communication.ui"
+
+ override fun info(message: String) {
+ Log.i(tag, message)
+ }
+
+ override fun debug(message: String) {
+ Log.d(tag, message)
+ }
+
+ override fun warning(message: String) {
+ Log.w(tag, message)
+ }
+
+ override fun error(message: String, error: Throwable?) {
+ Log.e(tag, message, error)
+ }
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/logger/Logger.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/logger/Logger.kt
new file mode 100644
index 000000000..15e11fd58
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/logger/Logger.kt
@@ -0,0 +1,11 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.logger
+
+internal interface Logger {
+ fun info(message: String)
+ fun debug(message: String)
+ fun warning(message: String)
+ fun error(message: String, error: Throwable?)
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/models/ChatCompositeLocalOptions.java b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/models/ChatCompositeLocalOptions.java
new file mode 100644
index 000000000..a6155793a
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/models/ChatCompositeLocalOptions.java
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.models;
+
+import com.azure.android.communication.ui.chat.ChatComposite;
+
+/**
+ * ChatCompositeLocalOptions for ChatComposite.launch.
+ *
+ *
+ * Local Options for the Chat Composite. These options are not shared with the server and impact local views only.
+ * E.g. The Local Participant Name if it differs from the display name you'd like to share with the server.
+ *
+ *
+ *
+ * // Initialize the chat composite builder
+ * final ChatCompositeBuilder builder = new ChatCompositeBuilder();
+ *
+ * // Build the chat composite
+ * ChatComposite chatComposite = builder.build();
+ *
+ * // Build the ChatCompositeLocalOptions with {@link ChatCompositeParticipantViewData}
+ * ChatCompositeLocalOptions localOptions = new ChatCompositeLocalOptions(
+ * new ChatCompositeParticipantViewData(...));
+ *
+ * // Launch chat
+ * chatComposite.launch(.., .., localOptions)
+ *
+ *
+ * @see ChatComposite
+ */
+public final class ChatCompositeLocalOptions {
+ private final ChatCompositeParticipantViewData participantViewData;
+
+ /**
+ * Create Local Options.
+ *
+ * @param participantViewData The {@link ChatCompositeParticipantViewData};
+ * @see ChatCompositeParticipantViewData
+ */
+ public ChatCompositeLocalOptions(final ChatCompositeParticipantViewData participantViewData) {
+ this.participantViewData = participantViewData;
+ }
+
+ /**
+ * Get {@link ChatCompositeParticipantViewData}.
+ *
+ * @return The {@link ChatCompositeParticipantViewData};
+ */
+ public ChatCompositeParticipantViewData getParticipantViewData() {
+ return participantViewData;
+ }
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/models/ChatCompositeParticipantViewData.java b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/models/ChatCompositeParticipantViewData.java
new file mode 100644
index 000000000..577418c4c
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/models/ChatCompositeParticipantViewData.java
@@ -0,0 +1,100 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.models;
+
+import android.graphics.Bitmap;
+import android.widget.ImageView;
+
+import com.azure.android.communication.ui.chat.ChatComposite;
+
+/**
+ * ChatCompositeParticipantViewData for participant.
+ *
+ *
+ *
+ * // Initialize the chat composite builder
+ * final ChatCompositeBuilder builder = new ChatCompositeBuilder();
+ *
+ * // Build the chat composite
+ * ChatComposite chatComposite = builder.build();
+ *
+ * // Build the ChatCompositeLocalOptions with {@link ChatCompositeParticipantViewData}
+ * ChatCompositeLocalOptions localOptions = new ChatCompositeLocalOptions(
+ * new ChatCompositeParticipantViewData(...));
+ *
+ * chatComposite.launch(..., ..., localOptions);
+ *
+ *
+ *
+ * @see ChatCompositeLocalOptions
+ */
+public final class ChatCompositeParticipantViewData {
+ private Bitmap avatarBitmap;
+ private String displayName;
+ private ImageView.ScaleType scaleType = ImageView.ScaleType.FIT_XY;
+
+ /**
+ * Set scaleType.
+ *
+ * Will not take affect if called after {@link ChatCompositeParticipantViewData} passed to {@link ChatComposite}
+ *
+ * @return The {@link ChatCompositeParticipantViewData};
+ */
+ public ChatCompositeParticipantViewData setScaleType(final ImageView.ScaleType scaleType) {
+ this.scaleType = scaleType;
+ return this;
+ }
+
+ /**
+ * Get scaleType.
+ *
+ * Will not take affect if called after {@link ChatCompositeParticipantViewData} passed to {@link ChatComposite}
+ *
+ * @return The {@link ImageView.ScaleType};
+ */
+ public ImageView.ScaleType getScaleType() {
+ return scaleType;
+ }
+
+ /**
+ * Set display name.
+ *
+ * @return The {@link ChatCompositeParticipantViewData};
+ */
+ public ChatCompositeParticipantViewData setDisplayName(final String displayName) {
+ this.displayName = displayName;
+ return this;
+ }
+
+ /**
+ * Get display name.
+ *
+ * @return The {@link String};
+ */
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ /**
+ * Get avatar Bitmap.
+ *
+ * @return The {@link Bitmap};
+ */
+ public Bitmap getAvatarBitmap() {
+ return avatarBitmap;
+ }
+
+ /**
+ * Set avatar Bitmap.
+ *
+ * Will not take affect if called after {@link ChatCompositeParticipantViewData} passed to {@link ChatComposite}
+ *
+ * @return The {@link ChatCompositeParticipantViewData};
+ */
+ public ChatCompositeParticipantViewData setAvatarBitmap(final Bitmap avatarBitmap) {
+ this.avatarBitmap = avatarBitmap;
+ return this;
+ }
+
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/package-info.java b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/package-info.java
new file mode 100644
index 000000000..dd7382ae8
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/package-info.java
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+/**
+ * Package containing the classes for chat-composite. Azure android communication chat composite.
+ */
+package com.azure.android.communication.ui.chat;
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/presentation/ChatCompositeActivity.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/presentation/ChatCompositeActivity.kt
new file mode 100644
index 000000000..19b848ecd
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/presentation/ChatCompositeActivity.kt
@@ -0,0 +1,8 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.presentation
+
+import androidx.appcompat.app.AppCompatActivity
+
+internal class ChatCompositeActivity : AppCompatActivity()
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/AppStore.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/AppStore.kt
new file mode 100644
index 000000000..217ac1eb4
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/AppStore.kt
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.redux
+
+import android.os.Handler
+import android.os.Looper
+import com.azure.android.communication.ui.chat.ChatCompositeException
+import com.azure.android.communication.ui.chat.redux.action.Action
+import com.azure.android.communication.ui.chat.redux.reducer.Reducer
+import kotlinx.coroutines.CoroutineExceptionHandler
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.launch
+import kotlin.coroutines.CoroutineContext
+
+internal class AppStore(
+ initialState: S,
+ private val reducer: Reducer,
+ middlewares: MutableList>,
+ dispatcher: CoroutineContext,
+) : Store {
+ // Any exceptions encountered in the reducer are rethrown to crash the app and not get silently ignored.
+ private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
+ Handler(Looper.getMainLooper()).postAtFrontOfQueue {
+ throw ChatCompositeException("App store exception while reducing state", throwable)
+ }
+ // At this point (after an exception) we don't want to accept any more work.
+ scope.cancel()
+ }
+ private val dispatcherWithExceptionHandler = dispatcher + exceptionHandler
+ private val scope = CoroutineScope(dispatcher)
+ private val stateFlow = MutableStateFlow(initialState)
+ private var middlewareMap: List<(Dispatch) -> Dispatch> =
+ middlewares.map { m -> m.invoke(this) }
+
+ private var middlewareDispatch = compose(middlewareMap)(::reduce)
+
+ override fun end() {
+ scope.cancel()
+ middlewareMap = emptyList()
+ middlewareDispatch = compose(middlewareMap)(::reduce)
+ }
+
+ override fun dispatch(action: Action) {
+ scope.launch(dispatcherWithExceptionHandler) {
+ middlewareDispatch(action)
+ }
+ }
+
+ override fun getStateFlow(): MutableStateFlow {
+ return stateFlow
+ }
+
+ override fun getCurrentState(): S {
+ return stateFlow.value
+ }
+
+ private fun reduce(action: Action) {
+ stateFlow.value = reducer.reduce(stateFlow.value, action)
+ }
+
+ private fun compose(functions: List<(Dispatch) -> Dispatch>): (Dispatch) -> Dispatch =
+ { dispatch ->
+ functions.foldRight(
+ dispatch
+ ) { nextDispatch, composed -> nextDispatch(composed) }
+ }
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/CommonTypes.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/CommonTypes.kt
new file mode 100644
index 000000000..4f5b5ab56
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/CommonTypes.kt
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.redux
+
+import com.azure.android.communication.ui.chat.redux.action.Action
+
+internal typealias Dispatch = (Action) -> Unit
+internal typealias Middleware = (store: Store) -> (next: Dispatch) -> Dispatch
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/Store.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/Store.kt
new file mode 100644
index 000000000..ba2e66cb5
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/Store.kt
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.redux
+
+import com.azure.android.communication.ui.chat.redux.action.Action
+import kotlinx.coroutines.flow.MutableStateFlow
+
+internal interface Store {
+ fun dispatch(action: Action)
+ fun getStateFlow(): MutableStateFlow
+ fun getCurrentState(): S
+ fun end()
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/action/Action.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/action/Action.kt
new file mode 100644
index 000000000..b95f0623a
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/action/Action.kt
@@ -0,0 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.redux.action
+
+internal interface Action
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/middleware/ChatMiddleware.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/middleware/ChatMiddleware.kt
new file mode 100644
index 000000000..4d9e1d783
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/middleware/ChatMiddleware.kt
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.redux.middleware
+
+import com.azure.android.communication.ui.chat.redux.Dispatch
+import com.azure.android.communication.ui.chat.redux.Middleware
+import com.azure.android.communication.ui.chat.redux.Store
+import com.azure.android.communication.ui.chat.redux.state.ReduxState
+
+internal interface ChatMiddleware
+
+internal class ChatMiddlewareImpl :
+ Middleware,
+ ChatMiddleware {
+ override fun invoke(store: Store): (next: Dispatch) -> Dispatch {
+ TODO("Not yet implemented")
+ }
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/reducer/Reducer.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/reducer/Reducer.kt
new file mode 100644
index 000000000..c7fa2b4a7
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/reducer/Reducer.kt
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.redux.reducer
+
+import com.azure.android.communication.ui.chat.redux.action.Action
+
+internal interface Reducer {
+ fun reduce(state: S, action: Action): S
+}
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/state/ReduxState.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/state/ReduxState.kt
new file mode 100644
index 000000000..7e3a123ee
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/redux/state/ReduxState.kt
@@ -0,0 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.redux.state
+
+internal interface ReduxState
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/service/ChatService.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/service/ChatService.kt
new file mode 100644
index 000000000..a72169d97
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/service/ChatService.kt
@@ -0,0 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.service
+
+internal class ChatService
diff --git a/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/service/sdk/ChatSDKWrapper.kt b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/service/sdk/ChatSDKWrapper.kt
new file mode 100644
index 000000000..928e511fc
--- /dev/null
+++ b/azure-communication-ui/chat/src/main/java/com/azure/android/communication/ui/chat/service/sdk/ChatSDKWrapper.kt
@@ -0,0 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat.service.sdk
+
+internal class ChatSDKWrapper
diff --git a/azure-communication-ui/chat/src/test/java/com/azure/android/communication/ui/chat/ExampleUnitTest.kt b/azure-communication-ui/chat/src/test/java/com/azure/android/communication/ui/chat/ExampleUnitTest.kt
new file mode 100644
index 000000000..a224ea159
--- /dev/null
+++ b/azure-communication-ui/chat/src/test/java/com/azure/android/communication/ui/chat/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.android.communication.ui.chat
+
+import org.junit.Test
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ }
+}
diff --git a/azure-communication-ui/settings.gradle b/azure-communication-ui/settings.gradle
index 91017e4d0..75712a1d5 100644
--- a/azure-communication-ui/settings.gradle
+++ b/azure-communication-ui/settings.gradle
@@ -1,3 +1,3 @@
include ':calling'
-include ':azure-communication-ui-demo-app'
-
+include ':chat'
+include ':azure-communication-ui-demo-app'
\ No newline at end of file