menuItemClickListener) {
+ this.menuItemClickListener = menuItemClickListener;
+ }
+
+ /**
+ * Called when the item of the menu list is clicked.
+ *
+ * @param view The View clicked
+ * @param menu The menu that the clicked item displays
+ * @since 3.1.0
+ */
+ protected void onMenuItemClicked(@NonNull View view, @NonNull ModerationMenu menu) {
+ if (menuItemClickListener != null)
+ menuItemClickListener.onMenuItemClicked(view, menu, null);
+ }
+
+ /**
+ * A collection of parameters, which can be applied to a default View. The values of params are not dynamically applied at runtime.
+ * Params cannot be created directly, and it is automatically created together when components are created.
+ * Since the onCreateView configuring View uses the values of the set Params, we recommend that you set up for Params before the onCreateView is called.
+ *
+ * @see #getParams()
+ * @since 3.1.0
+ */
+ public static class Params {
+ protected Params() {
+ }
+
+ /**
+ * Apply data that matches keys mapped to Params' properties.
+ *
+ * @param context The {@code Context} this component is currently associated with
+ * @param args The sets of arguments to apply at Params.
+ * @return This Params object that applied with given data.
+ * @since 3.1.0
+ */
+ @NonNull
+ protected Params apply(@NonNull Context context, @NonNull Bundle args) {
+ return this;
+ }
+ }
+}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelMutedParticipantListComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelMutedParticipantListComponent.java
new file mode 100644
index 00000000..1e906c42
--- /dev/null
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelMutedParticipantListComponent.java
@@ -0,0 +1,54 @@
+package com.sendbird.uikit.modules.components;
+
+import androidx.annotation.NonNull;
+
+import com.sendbird.android.channel.OpenChannel;
+import com.sendbird.android.user.User;
+import com.sendbird.uikit.activities.adapter.OpenChannelMutedParticipantListAdapter;
+
+import java.util.List;
+
+/**
+ * This class creates and performs a view corresponding the muted participant list area in Sendbird UIKit.
+ *
+ * @since 3.1.0
+ */
+public class OpenChannelMutedParticipantListComponent extends UserTypeListComponent {
+ @NonNull
+ private OpenChannelMutedParticipantListAdapter adapter = new OpenChannelMutedParticipantListAdapter();
+
+ /**
+ * Sets the muted participant list adapter to provide child views on demand. The default is {@code new OpenChannelMutedParticipantListAdapter()}.
+ * When adapter is changed, all existing views are recycled back to the pool. If the pool has only one adapter, it will be cleared.
+ *
+ * @param adapter The adapter to be applied to this list component
+ * @since 3.1.0
+ */
+ public void setAdapter(@NonNull T adapter) {
+ this.adapter = adapter;
+ super.setAdapter(this.adapter);
+ }
+
+ /**
+ * Returns the muted participant list adapter.
+ *
+ * @return The adapter applied to this list component
+ * @since 3.1.0
+ */
+ @NonNull
+ @Override
+ protected OpenChannelMutedParticipantListAdapter getAdapter() {
+ return adapter;
+ }
+
+ /**
+ * Notifies this component that the list of users is changed.
+ *
+ * @param userList The list of users to be displayed on this component
+ * @param openChannel The latest open channel
+ * @since 3.1.0
+ */
+ public void notifyDataSetChanged(@NonNull List userList, @NonNull OpenChannel openChannel) {
+ this.adapter.setItems(userList, openChannel);
+ }
+}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelOperatorListComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelOperatorListComponent.java
new file mode 100644
index 00000000..f5a1a5c1
--- /dev/null
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelOperatorListComponent.java
@@ -0,0 +1,54 @@
+package com.sendbird.uikit.modules.components;
+
+import androidx.annotation.NonNull;
+
+import com.sendbird.android.channel.OpenChannel;
+import com.sendbird.android.user.User;
+import com.sendbird.uikit.activities.adapter.OpenChannelOperatorListAdapter;
+
+import java.util.List;
+
+/**
+ * This class creates and performs a view corresponding the operator list area in Sendbird UIKit.
+ *
+ * @since 3.1.0
+ */
+public class OpenChannelOperatorListComponent extends UserTypeListComponent {
+ @NonNull
+ private OpenChannelOperatorListAdapter adapter = new OpenChannelOperatorListAdapter();
+
+ /**
+ * Returns the operator list adapter.
+ *
+ * @return The adapter applied to this list component
+ * @since 3.1.0
+ */
+ @NonNull
+ @Override
+ protected OpenChannelOperatorListAdapter getAdapter() {
+ return adapter;
+ }
+
+ /**
+ * Sets the operator list adapter to provide child views on demand. The default is {@code new OpenChannelOperatorListAdapter()}.
+ * When adapter is changed, all existing views are recycled back to the pool. If the pool has only one adapter, it will be cleared.
+ *
+ * @param adapter The adapter to be applied to this list component
+ * @since 3.1.0
+ */
+ public void setAdapter(@NonNull T adapter) {
+ this.adapter = adapter;
+ super.setAdapter(this.adapter);
+ }
+
+ /**
+ * Notifies this component that the list of users is changed.
+ *
+ * @param userList The list of users to be displayed on this component
+ * @param openChannel The latest open channel
+ * @since 3.1.0
+ */
+ public void notifyDataSetChanged(@NonNull List userList, @NonNull OpenChannel openChannel) {
+ this.adapter.setItems(userList, openChannel);
+ }
+}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelRegisterOperatorListComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelRegisterOperatorListComponent.java
new file mode 100644
index 00000000..45b9cded
--- /dev/null
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelRegisterOperatorListComponent.java
@@ -0,0 +1,40 @@
+package com.sendbird.uikit.modules.components;
+
+import androidx.annotation.NonNull;
+
+import com.sendbird.android.user.User;
+import com.sendbird.uikit.activities.adapter.OpenChannelRegisterOperatorListAdapter;
+
+/**
+ * This class creates and performs a view corresponding the participant list area when registering operators in Sendbird UIKit.
+ *
+ * @since 3.1.0
+ */
+public class OpenChannelRegisterOperatorListComponent extends SelectUserListComponent {
+ @NonNull
+ private OpenChannelRegisterOperatorListAdapter adapter = new OpenChannelRegisterOperatorListAdapter(null);
+
+ /**
+ * Returns the participant list adapter when registering operators.
+ *
+ * @return The adapter applied to this list component
+ * @since 3.1.0
+ */
+ @NonNull
+ @Override
+ protected OpenChannelRegisterOperatorListAdapter getAdapter() {
+ return adapter;
+ }
+
+ /**
+ * Sets the participant list adapter when registering operators to provide child views on demand. The default is {@code new RegisterOperatorListAdapter()}.
+ * When adapter is changed, all existing views are recycled back to the pool. If the pool has only one adapter, it will be cleared.
+ *
+ * @param adapter The adapter to be applied to this list component
+ * @since 3.1.0
+ */
+ public void setAdapter(@NonNull T adapter) {
+ this.adapter = adapter;
+ super.setAdapter(this.adapter);
+ }
+}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelSettingsMenuComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelSettingsMenuComponent.java
index 56b28404..d12f7097 100644
--- a/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelSettingsMenuComponent.java
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/OpenChannelSettingsMenuComponent.java
@@ -12,6 +12,7 @@
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ContextThemeWrapper;
+import com.sendbird.android.SendbirdChat;
import com.sendbird.android.channel.OpenChannel;
import com.sendbird.uikit.R;
import com.sendbird.uikit.SendbirdUIKit;
@@ -26,7 +27,20 @@
*/
public class OpenChannelSettingsMenuComponent {
public enum Menu {
- PARTICIPANTS, DELETE_CHANNEL
+ /**
+ * A menu of Moderations to users or members control.
+ *
+ * @since 3.1.0
+ */
+ MODERATIONS,
+ /**
+ * A menu for viewing the participants of the current channel.
+ */
+ PARTICIPANTS,
+ /**
+ * A menu to delete the current channel.
+ */
+ DELETE_CHANNEL
}
@NonNull
@@ -88,8 +102,14 @@ public View onCreateView(@NonNull Context context, @NonNull LayoutInflater infla
final LayoutInflater menuInflater = inflater.cloneInContext(menuThemeContext);
final View view = menuInflater.inflate(R.layout.sb_view_open_channel_settings_menu, parent, false);
- SingleMenuItemView participantsItemView = view.findViewById(R.id.participants);
- SingleMenuItemView deleteItemView = view.findViewById(R.id.delete);
+ final SingleMenuItemView moderationsItemView = view.findViewById(R.id.moderations);
+ final SingleMenuItemView participantsItemView = view.findViewById(R.id.participants);
+ final SingleMenuItemView deleteItemView = view.findViewById(R.id.delete);
+
+ moderationsItemView.setName(context.getString(R.string.sb_text_channel_settings_moderations));
+ moderationsItemView.setMenuType(SingleMenuItemView.Type.NEXT);
+ moderationsItemView.setIcon(R.drawable.icon_moderations);
+ moderationsItemView.setVisibility(View.GONE);
participantsItemView.setName(context.getString(R.string.sb_text_header_participants));
participantsItemView.setMenuType(SingleMenuItemView.Type.NEXT);
@@ -99,6 +119,7 @@ public View onCreateView(@NonNull Context context, @NonNull LayoutInflater infla
deleteItemView.setIcon(R.drawable.icon_delete);
deleteItemView.setIconTint(AppCompatResources.getColorStateList(context, SendbirdUIKit.isDarkMode() ? R.color.error_200 : R.color.error_300));
+ moderationsItemView.setOnClickListener(v -> onMenuClicked(v, Menu.MODERATIONS));
participantsItemView.setOnClickListener(v -> onMenuClicked(v, Menu.PARTICIPANTS));
deleteItemView.setOnClickListener(v -> onMenuClicked(v, Menu.DELETE_CHANNEL));
this.menuView = view;
@@ -113,6 +134,10 @@ public View onCreateView(@NonNull Context context, @NonNull LayoutInflater infla
*/
public void notifyChannelChanged(@NonNull OpenChannel channel) {
if (this.menuView == null) return;
+
+ final SingleMenuItemView moderationsItemView = menuView.findViewById(R.id.moderations);
+ moderationsItemView.setVisibility(channel.isOperator(SendbirdChat.getCurrentUser()) ? View.VISIBLE : View.GONE);
+
SingleMenuItemView participantsItemView = menuView.findViewById(R.id.participants);
participantsItemView.setDescription(ChannelUtils.makeMemberCountText(channel.getParticipantCount()).toString());
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/OperatorListComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/OperatorListComponent.java
index f5e334e6..18a0dfca 100644
--- a/uikit/src/main/java/com/sendbird/uikit/modules/components/OperatorListComponent.java
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/OperatorListComponent.java
@@ -1,12 +1,13 @@
package com.sendbird.uikit.modules.components;
-import android.annotation.SuppressLint;
-
import androidx.annotation.NonNull;
+import com.sendbird.android.channel.Role;
import com.sendbird.android.user.User;
import com.sendbird.uikit.activities.adapter.OperatorListAdapter;
+import java.util.List;
+
/**
* This class creates and performs a view corresponding the operator list area in Sendbird UIKit.
*
@@ -23,7 +24,6 @@ public class OperatorListComponent extends UserTypeListComponent {
* @return The adapter applied to this list component
* @since 3.0.0
*/
- @SuppressLint("KotlinPropertyAccess")
@NonNull
@Override
protected OperatorListAdapter getAdapter() {
@@ -41,4 +41,15 @@ public void setAdapter(@NonNull T adapter) {
this.adapter = adapter;
super.setAdapter(this.adapter);
}
+
+ /**
+ * Notifies this component that the list of users is changed.
+ *
+ * @param userList The list of users to be displayed on this component
+ * @param myRole Role of the current user
+ * @since 3.0.0
+ */
+ public void notifyDataSetChanged(@NonNull List userList, @NonNull Role myRole) {
+ this.adapter.setItems(userList, myRole);
+ }
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/ParticipantListComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/ParticipantListComponent.java
index 5c6673db..b5f190e6 100644
--- a/uikit/src/main/java/com/sendbird/uikit/modules/components/ParticipantListComponent.java
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/ParticipantListComponent.java
@@ -1,12 +1,13 @@
package com.sendbird.uikit.modules.components;
-import android.annotation.SuppressLint;
-
import androidx.annotation.NonNull;
+import com.sendbird.android.channel.OpenChannel;
import com.sendbird.android.user.User;
import com.sendbird.uikit.activities.adapter.ParticipantListAdapter;
+import java.util.List;
+
/**
* This class creates and performs a view corresponding the participant list area in Sendbird UIKit.
*
@@ -22,7 +23,6 @@ public class ParticipantListComponent extends UserTypeListComponent {
* @return The adapter applied to this list component
* @since 3.0.0
*/
- @SuppressLint("KotlinPropertyAccess")
@NonNull
@Override
protected ParticipantListAdapter getAdapter() {
@@ -40,4 +40,15 @@ public void setAdapter(@NonNull T adapter) {
this.adapter = adapter;
super.setAdapter(this.adapter);
}
+
+ /**
+ * Notifies this component that the list of users is changed.
+ *
+ * @param userList The list of users to be displayed on this component
+ * @param openChannel The latest open channel
+ * @since 3.1.0
+ */
+ public void notifyDataSetChanged(@NonNull List userList, @NonNull OpenChannel openChannel) {
+ this.adapter.setItems(userList, openChannel);
+ }
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/StateHeaderComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/StateHeaderComponent.java
index 4d32fa71..e51f8b56 100644
--- a/uikit/src/main/java/com/sendbird/uikit/modules/components/StateHeaderComponent.java
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/StateHeaderComponent.java
@@ -1,6 +1,5 @@
package com.sendbird.uikit.modules.components;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
@@ -269,7 +268,6 @@ public String getRightButtonText() {
* @return true
if the right button of the header is used, false
otherwise
* @since 3.0.0
*/
- @SuppressLint("KotlinPropertyAccess")
public boolean shouldUseRightButton() {
return useRightButton;
}
@@ -280,7 +278,6 @@ public boolean shouldUseRightButton() {
* @return true
if the left button of the header is used, false
otherwise
* @since 3.0.0
*/
- @SuppressLint("KotlinPropertyAccess")
public boolean shouldUseLeftButton() {
return useLeftButton;
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/modules/components/UserTypeListComponent.java b/uikit/src/main/java/com/sendbird/uikit/modules/components/UserTypeListComponent.java
index 67201337..ebe547a7 100644
--- a/uikit/src/main/java/com/sendbird/uikit/modules/components/UserTypeListComponent.java
+++ b/uikit/src/main/java/com/sendbird/uikit/modules/components/UserTypeListComponent.java
@@ -1,6 +1,5 @@
package com.sendbird.uikit.modules.components;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -11,7 +10,6 @@
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
-import com.sendbird.android.channel.Role;
import com.sendbird.android.user.User;
import com.sendbird.uikit.R;
import com.sendbird.uikit.activities.adapter.UserTypeListAdapter;
@@ -147,17 +145,6 @@ public void setPagedDataLoader(@NonNull OnPagedDataLoader> pagedDataLoad
if (recyclerView != null) recyclerView.setPager(pagedDataLoader);
}
- /**
- * Notifies this component that the list of users is changed.
- *
- * @param userList The list of users to be displayed on this component
- * @param myRole Role of the current user
- */
- public void notifyDataSetChanged(@NonNull List userList, @NonNull Role myRole) {
- if (this.recyclerView == null) return;
- getAdapter().setItems(userList, myRole);
- }
-
/**
* Called when the profile view of the item is clicked.
*
@@ -188,7 +175,7 @@ protected void onActionItemClicked(@NonNull View view, int position, @NonNull T
*
* @param view The View long-clicked.
* @param position The position long-clicked.
- * @param user The channel that the long-clicked item displays
+ * @param user The user that the long-clicked item displays
* @since 3.0.0
*/
protected void onItemLongClicked(@NonNull View view, int position, @NonNull T user) {
@@ -277,7 +264,6 @@ public void setUseUserProfile(boolean useUserProfile) {
* @return true
if the user profile is shown, false
otherwise
* @since 3.0.0
*/
- @SuppressLint("KotlinPropertyAccess")
public boolean shouldUseUserProfile() {
return useUserProfile;
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/utils/DialogUtils.java b/uikit/src/main/java/com/sendbird/uikit/utils/DialogUtils.java
index 9f5264f7..32d5bd60 100644
--- a/uikit/src/main/java/com/sendbird/uikit/utils/DialogUtils.java
+++ b/uikit/src/main/java/com/sendbird/uikit/utils/DialogUtils.java
@@ -153,6 +153,29 @@ public static AlertDialog showWarningDialog(@NonNull Context context,
@NonNull
public static AlertDialog showWarningDialog(@NonNull Context context,
@NonNull String title,
+ @NonNull String message,
+ @NonNull String warningButtonText,
+ @Nullable View.OnClickListener warningButtonListener,
+ @NonNull String negativeButtonText,
+ @Nullable View.OnClickListener negativeButtonListener) {
+ return showWarningDialog(context, title, message, warningButtonText, warningButtonListener, negativeButtonText, negativeButtonListener, false);
+ }
+
+ @NonNull
+ public static AlertDialog showWarningDialog(@NonNull Context context,
+ @NonNull String title,
+ @NonNull String warningButtonText,
+ @Nullable View.OnClickListener warningButtonListener,
+ @NonNull String negativeButtonText,
+ @Nullable View.OnClickListener negativeButtonListener,
+ boolean useOverlay) {
+ return showWarningDialog(context, title, "", warningButtonText, warningButtonListener, negativeButtonText, negativeButtonListener, useOverlay);
+ }
+
+ @NonNull
+ public static AlertDialog showWarningDialog(@NonNull Context context,
+ @NonNull String title,
+ @NonNull String message,
@NonNull String warningButtonText,
@Nullable View.OnClickListener warningButtonListener,
@NonNull String negativeButtonText,
@@ -174,6 +197,7 @@ public static AlertDialog showWarningDialog(@NonNull Context context,
final Context themeWrapperContext = new ContextThemeWrapper(context, themeResId);
final DialogView dialogView = new DialogView(themeWrapperContext);
dialogView.setTitle(title);
+ dialogView.setMessage(message);
final AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.Sendbird_Dialog);
builder.setView(dialogView);
diff --git a/uikit/src/main/java/com/sendbird/uikit/utils/IntentUtils.java b/uikit/src/main/java/com/sendbird/uikit/utils/IntentUtils.java
index 14b0a6c2..480c46ec 100644
--- a/uikit/src/main/java/com/sendbird/uikit/utils/IntentUtils.java
+++ b/uikit/src/main/java/com/sendbird/uikit/utils/IntentUtils.java
@@ -44,14 +44,24 @@ public static Intent getGalleryIntent() {
@NonNull
private static Intent getGalleryIntent(@NonNull String[] mimetypes) {
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_GET_CONTENT);
- intent.setType("*/*");
- intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
- intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- return Intent.createChooser(intent, null);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ intent.setType("*/*");
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
+ intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ return Intent.createChooser(intent, null);
+ }
+
+ Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ if (mimetypes.length == 1) {
+ // ACTION_PICK_IMAGES supports only two mimetypes.
+ intent.setType(mimetypes[0]);
+ }
+ return intent;
}
+
@NonNull
public static Intent getFileChooserIntent() {
Intent intent = new Intent();
diff --git a/uikit/src/main/java/com/sendbird/uikit/utils/PermissionUtils.java b/uikit/src/main/java/com/sendbird/uikit/utils/PermissionUtils.java
index 58b833c3..a4d8377e 100644
--- a/uikit/src/main/java/com/sendbird/uikit/utils/PermissionUtils.java
+++ b/uikit/src/main/java/com/sendbird/uikit/utils/PermissionUtils.java
@@ -1,25 +1,56 @@
package com.sendbird.uikit.utils;
+import android.Manifest;
import android.app.Activity;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
-import androidx.core.content.PermissionChecker;
+import androidx.core.content.ContextCompat;
+
+import com.sendbird.uikit.log.Logger;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class PermissionUtils {
+ public final static String[] CAMERA_PERMISSION = getCameraPermission();
+ public final static String[] GET_CONTENT_PERMISSION = getGetContentPermission();
+
private PermissionUtils() {
}
+ private static String[] getCameraPermission() {
+ String[] permissions = new String[]{Manifest.permission.CAMERA,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.READ_EXTERNAL_STORAGE};
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
+ permissions = new String[]{Manifest.permission.CAMERA};
+ }
+ return permissions;
+ }
+
+ private static String[] getGetContentPermission() {
+ String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ permissions = new String[] {};
+ } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
+ permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
+ }
+ return permissions;
+ }
+
public static boolean hasPermissions(@NonNull Context context, @NonNull String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (String permission : permissions) {
- if (PermissionChecker.checkSelfPermission(context, permission) != PermissionChecker.PERMISSION_GRANTED) {
+ if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
@@ -29,7 +60,7 @@ public static boolean hasPermissions(@NonNull Context context, @NonNull String..
@NonNull
public static String[] getNotGrantedPermissions(@NonNull Context context, @NonNull String... permissions) {
- ArrayList notGrantedPermissions = new ArrayList<>();
+ List notGrantedPermissions = new ArrayList<>();
for (String perm : permissions) {
if (!PermissionUtils.hasPermissions(context, perm)) {
notGrantedPermissions.add(perm);
@@ -39,15 +70,31 @@ public static String[] getNotGrantedPermissions(@NonNull Context context, @NonNu
}
@NonNull
- public static List getShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String... permissions) {
+ public static List getNotGrantedPermissions(@NonNull Map permissionResults) {
+ final Set keys = permissionResults.keySet();
+ final List notGrantedList = new ArrayList<>();
+ for (String permission : keys) {
+ Logger.d("permissionResults.get(%s) : %s", permission, permissionResults.get(permission));
+ if (Boolean.FALSE.equals(permissionResults.get(permission))) {
+ notGrantedList.add(permission);
+ }
+ }
+ return notGrantedList;
+ }
+
+ @NonNull
+ public static List getExplicitDeniedPermissionList(@NonNull Activity activity, @NonNull Collection permissions) {
List result = new ArrayList<>();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- for (String permission : permissions) {
- if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
- result.add(permission);
- }
+ for (String permission : permissions) {
+ if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
+ result.add(permission);
}
}
return result;
}
+
+ @NonNull
+ public static List getExplicitDeniedPermissionList(@NonNull Activity activity, @NonNull String... permissions) {
+ return getExplicitDeniedPermissionList(activity, Arrays.asList(permissions));
+ }
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/vm/ChannelViewModel.java b/uikit/src/main/java/com/sendbird/uikit/vm/ChannelViewModel.java
index bcfee515..5c009da0 100644
--- a/uikit/src/main/java/com/sendbird/uikit/vm/ChannelViewModel.java
+++ b/uikit/src/main/java/com/sendbird/uikit/vm/ChannelViewModel.java
@@ -86,8 +86,8 @@ public class ChannelViewModel extends BaseViewModel implements OnPagedDataLoader
private final MutableLiveData statusFrame = new MutableLiveData<>();
@NonNull
private final MutableLiveData hugeGapDetected = new MutableLiveData<>();
- @NonNull
- private final MessageListParams messageListParams;
+ @Nullable
+ private MessageListParams messageListParams;
@Nullable
private GroupChannel channel;
@NonNull
@@ -150,8 +150,7 @@ public ChannelViewModel(@NonNull String channelUrl, @Nullable MessageListParams
super();
this.channel = null;
this.channelUrl = channelUrl;
- this.messageListParams = messageListParams == null ? createMessageListParams() : messageListParams;
- this.messageListParams.setReverse(true);
+ this.messageListParams = messageListParams;
this.memberFinder = new MemberFinder(channelUrl, SendbirdUIKit.getUserMentionConfig());
SendbirdChat.addChannelHandler(ID_CHANNEL_EVENT_HANDLER, new GroupChannelHandler() {
@@ -218,7 +217,11 @@ private synchronized void initMessageCollection(final long startingPoint) {
if (this.collection != null) {
disposeMessageCollection();
}
- this.collection = SendbirdChat.createMessageCollection(new MessageCollectionCreateParams(channel, messageListParams, startingPoint, new MessageCollectionHandler() {
+ if (this.messageListParams == null) {
+ this.messageListParams = createMessageListParams();
+ }
+ this.messageListParams.setReverse(true);
+ this.collection = SendbirdChat.createMessageCollection(new MessageCollectionCreateParams(channel, this.messageListParams, startingPoint, new MessageCollectionHandler() {
@UiThread
@Override
public void onMessagesAdded(@NonNull MessageContext context, @NonNull GroupChannel channel, @NonNull List messages) {
@@ -452,7 +455,7 @@ public String getChannelUrl() {
* @return {@link MessageListParams} used in this view model
* @since 3.0.0
*/
- @NonNull
+ @Nullable
public MessageListParams getMessageListParams() {
return messageListParams;
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/vm/MessageSearchViewModel.java b/uikit/src/main/java/com/sendbird/uikit/vm/MessageSearchViewModel.java
index e901f9c7..284f651b 100644
--- a/uikit/src/main/java/com/sendbird/uikit/vm/MessageSearchViewModel.java
+++ b/uikit/src/main/java/com/sendbird/uikit/vm/MessageSearchViewModel.java
@@ -82,7 +82,6 @@ public String getChannelUrl() {
*/
@NonNull
protected MessageSearchQuery createMessageSearchQuery(@NonNull String keyword) {
- final long timestampFrom = channel == null ? 0 : Math.max(channel.getJoinedAt(), channel.getInvitedAt());
final MessageSearchQueryParams params = new MessageSearchQueryParams(keyword);
if (query != null) {
params.setAdvancedQuery(query.isAdvancedQuery());
@@ -92,11 +91,13 @@ protected MessageSearchQuery createMessageSearchQuery(@NonNull String keyword) {
params.setMessageTimestampTo(query.getMessageTimestampTo());
params.setTargetFields(query.getTargetFields());
params.setOrder(query.getOrder());
+ params.setMessageTimestampFrom(query.getMessageTimestampFrom());
} else {
+ final long timestampFrom = channel == null ? 0 : Math.max(channel.getJoinedAt(), channel.getInvitedAt());
+ params.setMessageTimestampFrom(timestampFrom);
params.setOrder(MessageSearchQuery.Order.TIMESTAMP);
}
params.setChannelUrl(channelUrl);
- params.setMessageTimestampFrom(timestampFrom);
params.setReverse(false);
return SendbirdChat.createMessageSearchQuery(params);
}
diff --git a/uikit/src/main/java/com/sendbird/uikit/vm/ModerationViewModel.java b/uikit/src/main/java/com/sendbird/uikit/vm/ModerationViewModel.java
index 42fb8697..1a415006 100644
--- a/uikit/src/main/java/com/sendbird/uikit/vm/ModerationViewModel.java
+++ b/uikit/src/main/java/com/sendbird/uikit/vm/ModerationViewModel.java
@@ -187,7 +187,7 @@ public LiveData getIsChannelDeleted() {
/**
* Returns LiveData that can be observed whether the current user is banned.
*
- * @return LiveData holding the URL of the deleted channel
+ * @return LiveData holding the current user banned or not
* @since 3.0.0
*/
@NonNull
diff --git a/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelBannedUserListViewModel.java b/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelBannedUserListViewModel.java
new file mode 100644
index 00000000..c0bb8e57
--- /dev/null
+++ b/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelBannedUserListViewModel.java
@@ -0,0 +1,38 @@
+package com.sendbird.uikit.vm;
+
+import androidx.annotation.NonNull;
+
+import com.sendbird.android.channel.ChannelType;
+import com.sendbird.android.user.User;
+import com.sendbird.uikit.interfaces.PagedQueryHandler;
+import com.sendbird.uikit.vm.queries.BannedUserListQuery;
+
+/**
+ * ViewModel preparing and managing data related with the list of banned users
+ *
+ * @since 3.1.0
+ */
+public class OpenChannelBannedUserListViewModel extends OpenChannelUserViewModel {
+ /**
+ * Constructor
+ *
+ * @param channelUrl The URL of a channel this view model is currently associated with
+ * @since 3.1.0
+ */
+ public OpenChannelBannedUserListViewModel(@NonNull String channelUrl) {
+ super(channelUrl);
+ }
+
+ /**
+ * Creates banned user list query.
+ *
+ * @param channelUrl The url of {@code OpenChannel} with banned users to be fetched by the query
+ * @return {@code PagedQueryHandler} to retrieve the list of users who are banned
+ * @since 3.1.0
+ */
+ @NonNull
+ @Override
+ protected PagedQueryHandler createQueryHandler(@NonNull String channelUrl) {
+ return new BannedUserListQuery(ChannelType.OPEN, channelUrl);
+ }
+}
diff --git a/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelModerationViewModel.java b/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelModerationViewModel.java
new file mode 100644
index 00000000..83067f26
--- /dev/null
+++ b/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelModerationViewModel.java
@@ -0,0 +1,168 @@
+package com.sendbird.uikit.vm;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+
+import com.sendbird.android.SendbirdChat;
+import com.sendbird.android.channel.BaseChannel;
+import com.sendbird.android.channel.ChannelType;
+import com.sendbird.android.channel.OpenChannel;
+import com.sendbird.android.handler.OpenChannelHandler;
+import com.sendbird.android.message.BaseMessage;
+import com.sendbird.android.user.RestrictedUser;
+import com.sendbird.android.user.User;
+import com.sendbird.uikit.interfaces.AuthenticateHandler;
+import com.sendbird.uikit.log.Logger;
+
+/**
+ * ViewModel preparing and managing data related with the push setting of a channel
+ *
+ * @since 3.1.0
+ */
+public class OpenChannelModerationViewModel extends BaseViewModel {
+ @NonNull
+ private final String CHANNEL_HANDLER_OPEN_CHANNEL_MODERATION = "CHANNEL_HANDLER_OPEN_CHANNEL_MODERATION" + System.currentTimeMillis();
+ @NonNull
+ private final String channelUrl;
+ @Nullable
+ private OpenChannel channel;
+ @NonNull
+ private final MutableLiveData currentUserRegisteredOperator = new MutableLiveData<>();
+ @NonNull
+ private final MutableLiveData channelDeleted = new MutableLiveData<>();
+ @NonNull
+ private final MutableLiveData currentUserBanned = new MutableLiveData<>();
+
+ /**
+ * Constructor
+ *
+ * @param channelUrl The URL of a channel this view model is currently associated with
+ * @since 3.1.0
+ */
+ public OpenChannelModerationViewModel(@NonNull String channelUrl) {
+ super();
+ this.channelUrl = channelUrl;
+ SendbirdChat.addChannelHandler(CHANNEL_HANDLER_OPEN_CHANNEL_MODERATION, new OpenChannelHandler() {
+ @Override
+ public void onMessageReceived(@NonNull BaseChannel baseChannel, @NonNull BaseMessage baseMessage) {}
+
+ @Override
+ public void onChannelDeleted(@NonNull String channelUrl, @NonNull ChannelType channelType) {
+ if (isCurrentChannel(channelUrl)) {
+ Logger.i(">> OpenChannelModerationViewModel::onChannelDeleted()");
+ Logger.d("++ deleted channel url : " + channelUrl);
+ OpenChannelModerationViewModel.this.channelDeleted.setValue(channelUrl);
+ }
+ }
+
+ @Override
+ public void onOperatorUpdated(@NonNull BaseChannel channel) {
+ if (isCurrentChannel(channel.getUrl()) && channel instanceof OpenChannel) {
+ Logger.i(">> OpenChannelModerationViewModel::onOperatorUpdated()");
+ OpenChannelModerationViewModel.this.currentUserRegisteredOperator.setValue(((OpenChannel) channel).isOperator(SendbirdChat.getCurrentUser()));
+ }
+ }
+
+ @Override
+ public void onUserBanned(@NonNull BaseChannel channel, @NonNull RestrictedUser restrictedUser) {
+ final User currentUser = SendbirdChat.getCurrentUser();
+ if (isCurrentChannel(channel.getUrl()) && currentUser != null) {
+ Logger.i(">> OpenChannelModerationViewModel::onUserBanned()");
+ OpenChannelModerationViewModel.this.currentUserBanned.setValue(restrictedUser.getUserId().equals(currentUser.getUserId()));
+ }
+ }
+ });
+ }
+
+ /**
+ * Tries to connect Sendbird Server and retrieve a channel instance.
+ *
+ * @param handler Callback notifying the result of authentication
+ * @since 3.1.0
+ */
+ @Override
+ public void authenticate(@NonNull AuthenticateHandler handler) {
+ connect((user, e) -> {
+ if (user != null) {
+ OpenChannel.getChannel(channelUrl, (channel, e1) -> {
+ OpenChannelModerationViewModel.this.channel = channel;
+ if (e1 != null) {
+ handler.onAuthenticationFailed();
+ } else {
+ handler.onAuthenticated();
+ }
+ });
+ } else {
+ handler.onAuthenticationFailed();
+ }
+ });
+ }
+
+ @Override
+ protected void onCleared() {
+ super.onCleared();
+ SendbirdChat.removeChannelHandler(CHANNEL_HANDLER_OPEN_CHANNEL_MODERATION);
+ }
+
+ /**
+ * Returns LiveData that can be observed whether the current user is banned.
+ *
+ * @return LiveData holding whether the current user is banned or not
+ * @since 3.1.0
+ */
+ @NonNull
+ public LiveData getCurrentUserBanned() {
+ return currentUserBanned;
+ }
+
+ /**
+ * Returns LiveData that can be observed if the current user is operator or not.
+ *
+ * @return LiveData holding whether the current user is registered as operator or not
+ * @since 3.1.0
+ */
+ @NonNull
+ public LiveData getCurrentUserRegisteredOperator() {
+ return currentUserRegisteredOperator;
+ }
+
+ /**
+ * Returns LiveData that can be observed if the channel has been deleted.
+ *
+ * @return LiveData holding the URL of the deleted channel
+ * @since 3.1.0
+ */
+ @NonNull
+ public LiveData getChannelDeleted() {
+ return channelDeleted;
+ }
+
+ /**
+ * Returns {@code OpenChannel}. If the authentication failed, {@code null} is returned.
+ *
+ * @return {@code OpenChannel} this view model is currently associated with
+ * @since 3.1.0
+ */
+ @Nullable
+ public OpenChannel getChannel() {
+ return channel;
+ }
+
+ /**
+ * Returns URL of OpenChannel.
+ *
+ * @return The URL of a channel this view model is currently associated with
+ * @since 3.1.0
+ */
+ @NonNull
+ public String getChannelUrl() {
+ return channelUrl;
+ }
+
+ private boolean isCurrentChannel(@NonNull String channelUrl) {
+ if (channel == null) return false;
+ return channelUrl.equals(channel.getUrl());
+ }
+}
diff --git a/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelMutedParticipantListViewModel.java b/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelMutedParticipantListViewModel.java
new file mode 100644
index 00000000..ea752457
--- /dev/null
+++ b/uikit/src/main/java/com/sendbird/uikit/vm/OpenChannelMutedParticipantListViewModel.java
@@ -0,0 +1,40 @@
+package com.sendbird.uikit.vm;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.sendbird.android.channel.ChannelType;
+import com.sendbird.android.user.User;
+import com.sendbird.uikit.interfaces.PagedQueryHandler;
+import com.sendbird.uikit.vm.queries.MutedUserListQuery;
+
+/**
+ * ViewModel preparing and managing data related with the list of muted participants
+ *
+ * @since 3.1.0
+ */
+public class OpenChannelMutedParticipantListViewModel extends OpenChannelUserViewModel {
+ /**
+ * Constructor
+ *
+ * @param channelUrl The URL of a channel this view model is currently associated with
+ * @param queryHandler A callback to be invoked when a list of data is loaded.
+ * @since 3.1.0
+ */
+ public OpenChannelMutedParticipantListViewModel(@NonNull String channelUrl, @Nullable PagedQueryHandler queryHandler) {
+ super(channelUrl, queryHandler);
+ }
+
+ /**
+ * Creates muted participant list query.
+ *
+ * @param channelUrl The url of {@code OpenChannel} with muted participants to be fetched by the query
+ * @return {@code PagedQueryHandler} to retrieve the list of participants who are muted
+ * @since 3.1.0
+ */
+ @NonNull
+ @Override
+ protected PagedQueryHandler