Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b7fe41c
improve
null-nick Jul 31, 2024
650cd6d
Merge branch 'main' into improvements/chatActionBar
null-nick Jul 31, 2024
6f6920d
indent fixes
null-nick Jul 31, 2024
769dfc4
indent fixed
null-nick Jul 31, 2024
b0c9818
updated .gitignore
null-nick Jul 31, 2024
c830e68
WIP
null-nick Aug 4, 2024
65288a9
some fixes
null-nick Aug 4, 2024
e5183f3
some fixes + Fixed dismiss icon on pinned message + Fixed topbar cont…
null-nick Aug 5, 2024
3262e2b
Merge branch 'main' into improvements/chatActionBar
null-nick Aug 16, 2024
755d4c8
Merge branch 'main' into improvements/chatActionBar
null-nick Aug 19, 2024
5fa76fe
Merge branch 'main' into improvements/chatActionBar
null-nick Sep 8, 2024
19ff441
Merge branch 'main' into improvements/chatActionBar
null-nick Oct 29, 2024
d01d094
Merge branch 'main' into improvements/chatActionBar
null-nick Nov 16, 2024
99078ed
Merge branch 'main' into improvements/chatActionBar
null-nick Dec 10, 2024
c4cf222
Merge branch 'main' into improvements/chatActionBar
null-nick Mar 9, 2025
dba582b
padding fixes
null-nick Mar 9, 2025
3370cba
another padding fixes
null-nick Mar 9, 2025
f8ae4e3
another padding fixes + string fixes
null-nick Mar 9, 2025
2332515
indent fixes
null-nick Mar 9, 2025
bdc0181
little fixes
null-nick Mar 10, 2025
b1b0c52
Merge branch 'main' into improvements/chatActionBar
null-nick Mar 17, 2025
ed287f7
Merge branch 'main' into improvements/chatActionBar
null-nick May 29, 2025
be53627
Merge branch 'main' into improvements/chatActionBar
null-nick Jul 28, 2025
b44b456
Merge branch 'main' into improvements/chatActionBar
null-nick Aug 26, 2025
8ecc9f6
Merge branch 'main' into improvements/chatActionBar
null-nick Aug 31, 2025
a66d493
Merge remote-tracking branch 'upstream/main' into improvements/chatAc…
null-nick Oct 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.thunderdog.challegram.component.chat;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import android.view.Gravity;
Expand All @@ -24,6 +25,7 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;

import org.thunderdog.challegram.R;
import org.thunderdog.challegram.core.Lang;
Expand All @@ -38,7 +40,8 @@

public class TopBarView extends FrameLayoutFix {
private final ImageView topDismissButton;
private final LinearLayout actionsList;
private final LinearLayout actionsContainer;
private LinearLayout actionsList;

private boolean canDismiss;

Expand All @@ -49,17 +52,43 @@ public interface DismissListener {
public static class Item {
final int id;
final int stringRes;
final CharSequence noticeRes;
final int iconResId;
final View.OnClickListener onClickListener;
final boolean showDismissRight;

boolean isNegative;
boolean noDismiss;

public Item (int id, int stringRes, View.OnClickListener onClickListener) {
public Item (int id, int stringRes, CharSequence noticeRes, int iconResId, boolean showDismissRight, View.OnClickListener onClickListener) {
this.id = id;
this.stringRes = stringRes;
this.noticeRes = noticeRes;
this.iconResId = iconResId;
this.showDismissRight = showDismissRight;
this.onClickListener = onClickListener;
}

public Item (int id, int stringRes, boolean showDismissRight, int iconResId, View.OnClickListener onClickListener) {
this(id, stringRes, null, iconResId, showDismissRight, onClickListener);
}

public Item (int id, int stringRes, boolean showDismissRight, View.OnClickListener onClickListener) {
this(id, stringRes, null, 0, showDismissRight, onClickListener);
}

public Item (int id, int stringRes, View.OnClickListener onClickListener) {
this(id, stringRes, null, 0, false, onClickListener);
}

public Item (CharSequence noticeRes, boolean showDismissRight) {
this(0, 0, noticeRes, 0, showDismissRight, null);
}

public Item (CharSequence noticeRes) {
this(0, 0, noticeRes, 0, false, null);
}

public Item setIsNegative () {
this.isNegative = true;
return this;
Expand All @@ -76,15 +105,21 @@ public Item setNoDismiss () {
public TopBarView (@NonNull Context context) {
super(context);

setLayoutParams(FrameLayoutFix.newParams(ViewGroup.LayoutParams.MATCH_PARENT, Screen.dp(36f)));
setLayoutParams(FrameLayoutFix.newParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
ViewSupport.setThemedBackground(this, ColorId.filling, null);

actionsContainer = new LinearLayout(context);
actionsContainer.setOrientation(LinearLayout.VERTICAL);
actionsContainer.setLayoutParams(FrameLayoutFix.newParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Lang.gravity() | Gravity.TOP));
addView(actionsContainer);

actionsList = new LinearLayout(context);
actionsList.setOrientation(LinearLayout.HORIZONTAL);
actionsList.setLayoutParams(FrameLayoutFix.newParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Lang.gravity() | Gravity.TOP));
addView(actionsList);
actionsList.setLayoutParams(FrameLayoutFix.newParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Lang.gravity() | Gravity.TOP));
actionsContainer.addView(actionsList);

topDismissButton = new ImageView(context) {
topDismissButton = new AppCompatImageView(context) {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent (MotionEvent event) {
return Views.isValid(this) && super.onTouchEvent(event);
Expand All @@ -98,7 +133,6 @@ public boolean onTouchEvent (MotionEvent event) {
topDismissButton.setScaleType(ImageView.ScaleType.CENTER);
topDismissButton.setColorFilter(Theme.iconColor());
topDismissButton.setImageResource(R.drawable.baseline_close_18);
topDismissButton.setLayoutParams(FrameLayoutFix.newParams(Screen.dp(40f), ViewGroup.LayoutParams.MATCH_PARENT, Lang.gravity() | Gravity.TOP));
topDismissButton.setBackgroundResource(R.drawable.bg_btn_header);
Views.setClickable(topDismissButton);
topDismissButton.setVisibility(View.INVISIBLE);
Expand Down Expand Up @@ -127,6 +161,7 @@ public void setCanDismiss (boolean canDismiss) {
}

public void setItems (Item... items) {
actionsList = (LinearLayout) actionsContainer.getChildAt(0);
for (int i = 0; i < actionsList.getChildCount(); i++) {
View view = actionsList.getChildAt(i);
if (view != null && themeProvider != null) {
Expand All @@ -145,19 +180,63 @@ public void setItems (Item... items) {
canDismiss = true;
}
int textColorId = item.isNegative ? ColorId.textNegative : ColorId.textNeutral;
TextView button = Views.newTextView(getContext(), 15f, Theme.getColor(textColorId), Gravity.CENTER, Views.TEXT_FLAG_BOLD | Views.TEXT_FLAG_HORIZONTAL_PADDING);
button.setId(item.id);
if (themeProvider != null) {
themeProvider.addThemeTextColorListener(button, textColorId);

LinearLayout buttonLayout = new LinearLayout(getContext());
buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
buttonLayout.setGravity(Gravity.CENTER);
buttonLayout.setBackgroundResource(R.drawable.bg_btn_header);
buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, 2f));
Views.setClickable(buttonLayout);

topDismissButton.setLayoutParams(FrameLayoutFix.newParams(Screen.dp(40f), ViewGroup.LayoutParams.MATCH_PARENT, (item.showDismissRight ? (Gravity.END | Gravity.CENTER_VERTICAL) : (Lang.gravity() | Gravity.CENTER_VERTICAL))));

LinearLayout noticeItem = new LinearLayout(getContext());
noticeItem.setOrientation(LinearLayout.HORIZONTAL);
noticeItem.setGravity(Gravity.CENTER);
noticeItem.setBackgroundColor(0x00000000);
noticeItem.setPadding(0, 0, 0, 0);
noticeItem.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 2f));

if (item.iconResId != 0) {
ImageView iconView = new ImageView(getContext());
iconView.setImageResource(item.iconResId);
iconView.setColorFilter(Theme.getColor(textColorId));
iconView.setLayoutParams(new LinearLayout.LayoutParams(Screen.dp(24f), Screen.dp(24f)));
buttonLayout.addView(iconView);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) iconView.getLayoutParams();
layoutParams.rightMargin = Screen.dp(8);
iconView.setLayoutParams(layoutParams);
}
button.setEllipsize(TextUtils.TruncateAt.END);
button.setSingleLine(true);
button.setBackgroundResource(R.drawable.bg_btn_header);
button.setOnClickListener(item.onClickListener);
Views.setMediumText(button, Lang.getString(item.stringRes).toUpperCase());
Views.setClickable(button);
button.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, 2f));
actionsList.addView(button);

if (item.stringRes != 0) {
TextView buttonText = Views.newTextView(getContext(), 15f, Theme.getColor(textColorId), Gravity.CENTER, Views.TEXT_FLAG_BOLD | Views.TEXT_FLAG_HORIZONTAL_PADDING);
buttonText.setId(item.id);

if (themeProvider != null) {
themeProvider.addThemeTextColorListener(buttonText, textColorId);
}

buttonText.setEllipsize(TextUtils.TruncateAt.END);
buttonText.setSingleLine(true);
buttonText.setPadding(Screen.dp(8), 0, Screen.dp(8), 0);
buttonText.setText(Lang.getString(item.stringRes).toUpperCase());
buttonText.setOnClickListener(item.onClickListener);
buttonLayout.addView(buttonText);
actionsList.addView(buttonLayout);
}

if (item.noticeRes != null) {
var noticeText = Views.newTextView(getContext(), 15f, Theme.getColor(ColorId.textPlaceholder), ViewGroup.MEASURED_HEIGHT_STATE_SHIFT, Views.TEXT_FLAG_HORIZONTAL_PADDING);
noticeText.setText(item.noticeRes);
noticeText.setGravity(Gravity.START);
noticeText.setPadding(Screen.dp(16), Screen.dp(8), Screen.dp(26), Screen.dp(8));
noticeText.setSingleLine(false);
noticeText.setEllipsize(null);
setLayoutParams(FrameLayoutFix.newParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
noticeItem.addView(noticeText);
actionsList.addView(noticeItem);
}

}
if (items.length > 1) {
View offsetView = new View(getContext());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ protected void onDraw (Canvas c) {
liveLocationView.setLayoutParams(FrameLayoutFix.newParams(ViewGroup.LayoutParams.MATCH_PARENT, liveLocationHeight));
addThemeInvalidateListener(liveLocationView);

int actionBarHeight = Screen.dp(36f);
int actionBarHeight = Screen.dp(46f);
actionView = new TopBarView(context);
actionView.setDismissListener(barView ->
dismissActionBar()
Expand Down Expand Up @@ -942,7 +942,7 @@ public void onCompletelyHidden () {
pinnedMessagesItem,
requestsItem = new CollapseListView.ViewItem(requestsView, requestsViewHeight),
liveLocationItem = new CollapseListView.ViewItem(liveLocationView, liveLocationHeight),
actionItem = new CollapseListView.ViewItem(actionView, actionBarHeight),
actionItem = new CollapseListView.ViewItem(actionView, ViewGroup.LayoutParams.WRAP_CONTENT),
toastAlertItem
}, this);

Expand Down Expand Up @@ -8178,13 +8178,13 @@ private boolean needActionBar () {
}

private TopBarView.Item newAddContactItem (long chatId) {
return new TopBarView.Item(R.id.btn_addContact, R.string.AddContact, v -> {
return new TopBarView.Item(R.id.btn_addContact, R.string.AddContact, true, R.drawable.baseline_person_add_24, v -> {
tdlib.ui().addContact(this, tdlib.chatUser(chatId));
});
}

private TopBarView.Item newUnarchiveItem (long chatId) {
return new TopBarView.Item(R.id.btn_unarchiveChat, R.string.UnarchiveUnmute, v -> {
return new TopBarView.Item(R.id.btn_unarchiveChat, R.string.UnarchiveUnmute, true, R.drawable.baseline_unarchive_24, v -> {
tdlib.client().send(new TdApi.AddChatToList(chatId, new TdApi.ChatListMain()), tdlib.okHandler());
TdApi.ChatNotificationSettings settings = tdlib.chatSettings(chatId);
if (settings != null) {
Expand All @@ -8204,7 +8204,7 @@ private TopBarView.Item newUnarchiveItem (long chatId) {
}

private TopBarView.Item newReportItem (long chatId, boolean isBlock) {
return new TopBarView.Item(R.id.btn_reportChat, isBlock ? R.string.BlockContact : R.string.ReportSpam, v -> {
return new TopBarView.Item(R.id.btn_reportChat, isBlock ? R.string.BlockContact : R.string.ReportSpam, true, isBlock ? R.drawable.baseline_block_24 : R.drawable.baseline_report_24, v -> {
showSettings(new SettingsWrapBuilder(R.id.btn_reportSpam)
.addHeaderItem(new ListItem(ListItem.TYPE_INFO, 0, 0, Lang.getStringBold(R.string.ReportChatSpam, chat.title), false))
.setRawItems(getChatUserId() != 0 ? new ListItem[] {
Expand Down Expand Up @@ -8278,6 +8278,14 @@ private void checkActionBar () {

case TdApi.ChatActionBarReportSpam.CONSTRUCTOR: {
TdApi.ChatActionBarReportSpam reportSpam = (TdApi.ChatActionBarReportSpam) actionBar;
/*
TODO: Add anti-scam notice for custom emojis
var customEmoji = tdlib().cache().user(tdlib.chatUserId(getChatId()));
android.util.Log.e("customEmoji", String.format("customEmoji: %s", customEmoji));
if (customEmoji != null && customEmoji.emojiStatus != null) {
items.add(new TopBarView.Item("Have a custom emoji", true));
}
*/
items.add(newReportItem(chatId, false));
if (reportSpam.canUnarchive) {
items.add(newUnarchiveItem(chatId));
Expand All @@ -8287,6 +8295,14 @@ private void checkActionBar () {

case TdApi.ChatActionBarReportAddBlock.CONSTRUCTOR: {
TdApi.ChatActionBarReportAddBlock reportAddBlock = (TdApi.ChatActionBarReportAddBlock) actionBar;
/*
TODO: Add anti-scam notice for custom emojis
var customEmoji = tdlib().cache().user(tdlib.chatUserId(getChatId()));
android.util.Log.e("customEmoji", String.format("customEmoji: %s", customEmoji));
if (customEmoji != null && customEmoji.emojiStatus != null) {
items.add(new TopBarView.Item("Have a custom emoji", true));
}
*/
items.add(newReportItem(chatId, true));
items.add(newAddContactItem(chatId));
if (reportAddBlock.canUnarchive) {
Expand Down Expand Up @@ -8345,7 +8361,8 @@ public boolean onSenderPick (ContactsController context, View view, TdApi.Messag
}
case TdApi.ChatActionBarJoinRequest.CONSTRUCTOR: {
TdApi.ChatActionBarJoinRequest joinRequest = (TdApi.ChatActionBarJoinRequest) actionBar;
// TODO
int noticeResId = joinRequest.isChannel ? R.string.JoinRequestChannelAdminNotice : R.string.JoinRequestGroupAdminNotice;
items.add(new TopBarView.Item(Strings.replaceBoldTokens(Lang.getString(noticeResId, tdlib.cache().userFirstName(tdlib.chatUserId(getChatId())), joinRequest.title)), true));
break;
}
default: {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5623,6 +5623,9 @@
<string name="PlaybackSpeedHintSwipe">Hold and swipe horizontally for precise adjustment</string>
<string name="PlaybackSpeedHintTemplate">%1$s.\n%2$s.</string>

<string name="JoinRequestChannelAdminNotice">**%1$s** is an admin of **%2$s**, a channel you requested to join</string>
<string name="JoinRequestGroupAdminNotice">**%1$s** is an admin of **%2$s**, a group you requested to join</string>

<string name="DeactivatedBot">deactivated bot</string>

<string name="ReportAd">Report Ad</string>
Expand Down