From 34a97553dd20ad8b1d3d50ddfc0da687081bca6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Fri, 5 Feb 2021 01:59:00 +0800 Subject: [PATCH] Improves --- README.md | 2 + TMessagesProj/build.gradle | 4 +- TMessagesProj/src/main/assets/indigo.attheme | 1 - .../src/main/assets/nekox-indigo.attheme | 442 --- .../messenger/MediaDataController.java | 12 +- .../messenger/NotificationsController.java | 2 +- .../messenger/voip/VoIPBaseService.java | 3435 +++++++++-------- .../java/org/telegram/ui/ArticleViewer.java | 2 +- .../java/org/telegram/ui/AvatarPreviewer.java | 19 +- .../java/org/telegram/ui/CallLogActivity.java | 23 +- .../telegram/ui/ChannelAdminLogActivity.java | 3 +- .../java/org/telegram/ui/ChatActivity.java | 20 +- .../telegram/ui/Components/AlertsCreator.java | 71 +- .../ui/Components/AudioPlayerAlert.java | 4 +- .../org/telegram/ui/Components/EmojiView.java | 147 +- .../ui/Components/GroupCreateSpan.java | 6 +- .../ui/Components/LinkActionView.java | 11 +- .../ui/Components/PagerSlidingTabStrip.java | 10 +- .../ui/Components/SearchViewPager.java | 3 +- .../telegram/ui/Components/ShareAlert.java | 22 +- .../ui/Components/SharedMediaLayout.java | 10 +- .../ui/Components/WallpaperUpdater.java | 18 +- .../java/org/telegram/ui/DialogsActivity.java | 38 +- .../org/telegram/ui/FilteredSearchView.java | 3 +- .../org/telegram/ui/GroupCallActivity.java | 6 +- .../org/telegram/ui/ManageLinksActivity.java | 10 +- .../java/org/telegram/ui/MediaActivity.java | 7 +- .../java/org/telegram/ui/PhotoViewer.java | 28 +- .../java/org/telegram/ui/ProfileActivity.java | 11 +- .../org/telegram/ui/ProxyListActivity.java | 105 +- .../telegram/ui/WallpapersListActivity.java | 8 +- .../tw/nekomimi/nekogram/BottomBuilder.kt | 34 +- .../java/tw/nekomimi/nekogram/NekoConfig.java | 7 +- .../settings/NekoChatSettingsActivity.java | 24 +- .../tw/nekomimi/nekogram/utils/AlertUtil.kt | 5 +- .../tw/nekomimi/nekogram/utils/ProxyUtil.kt | 75 +- .../res/drawable/baseline_done_all_24.xml | 14 +- .../res/drawable/baseline_folder_open_24.xml | 9 + .../src/main/res/values/strings_nekox.xml | 1 + 39 files changed, 2091 insertions(+), 2561 deletions(-) delete mode 100644 TMessagesProj/src/main/assets/nekox-indigo.attheme create mode 100644 TMessagesProj/src/main/res/drawable/baseline_folder_open_24.xml diff --git a/README.md b/README.md index 142e5ae10..cd8550672 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,11 @@ NekoX is an **free and open source** third-party Telegram client, based on Teleg - Option to block others from starting a secret chat with you - Allow create group without invite - Option to upgrade group to supergroup +- Mark dialogs as read using tab menu - Improved session dialog - Improved link long click menu - Text replacer +- Option to disable trending - Tgx style message unpin menu - Built-in Material Design themes / Telegram X style icons diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 4e035cc53..6800d42b6 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -1,8 +1,8 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' -def verName = "7.4.2-rc01" -def verCode = 176 +def verName = "7.4.2-rc02" +def verCode = 178 def officialVer = "7.4.2" def officialCode = 2227 diff --git a/TMessagesProj/src/main/assets/indigo.attheme b/TMessagesProj/src/main/assets/indigo.attheme index ed102f724..bb79a9535 100644 --- a/TMessagesProj/src/main/assets/indigo.attheme +++ b/TMessagesProj/src/main/assets/indigo.attheme @@ -75,7 +75,6 @@ dialogCheckboxSquareUnchecked=-8550769 avatar_actionBarSelectorOrange=-2130706433 avatar_backgroundInProfileRed=-12627531 chat_emojiPanelNewTrending=-12627531 -chat_emojiPanelStickerPackSelector=-12627531 chat_unreadMessagesStartArrowIcon=-12627531 avatar_backgroundActionBarOrange=-12627531 windowBackgroundWhiteBlackText=-12434878 diff --git a/TMessagesProj/src/main/assets/nekox-indigo.attheme b/TMessagesProj/src/main/assets/nekox-indigo.attheme deleted file mode 100644 index 44b05c18f..000000000 --- a/TMessagesProj/src/main/assets/nekox-indigo.attheme +++ /dev/null @@ -1,442 +0,0 @@ -chat_unreadMessagesStartText=-12627531 -chat_inFileBackgroundSelected=-12627531 -chat_editDoneIcon=-12627531 -radioBackgroundChecked=-12627531 -dialogTextBlue=-12627531 -chat_inSentClockSelected=-2143333963 -avatar_backgroundActionBarGreen=-12627531 -chat_goDownButtonCounterBackground=-1 -chat_mediaLoaderPhotoSelected=-2147483648 -actionBarActionModeDefaultTop=0 -actionBarActionModeDefault=-12627531 -dialogCheckboxSquareBackground=-12627531 -chats_menuPhone=-2130706433 -sessions_devicesImage=-8550769 -chat_outViews=-2130706433 -avatar_actionBarSelectorCyan=-2130706433 -chat_secretTimerBackground=-12627531 -chat_botKeyboardButtonText=-1 -chat_outViaBotNameText=-2130706433 -profile_actionPressedBackground=1073741824 -key_chat_messagePanelVoiceLock=-8550769 -chat_secretChatStatusText=-8550769 -switchTrack=-2137088354 -chat_inPreviewInstantSelectedText=-2143333963 -location_sendLocationBackground=-12627531 -avatar_nameInMessageViolet=-12627531 -emptyListPlaceholder=-8550769 -chat_inAudioSelectedProgress=-1 -chats_nameMessage=-12627531 -contacts_inviteBackground=-12627531 -avatar_subtitleInProfileViolet=-2130706433 -chat_messagePanelCancelInlineBot=-2137088354 -checkbox=-12627531 -chat_outAudioSeekbarFill=-1 -actionBarWhiteSelector=1073741824 -chat_botKeyboardButtonBackgroundPressed=-2143333963 -player_time=-12627531 -chat_outTimeSelectedText=-2130706433 -chat_outFileProgressSelected=-12627531 -chat_emojiSearchBackground=-1118482 -chat_inFileProgressSelected=-1 -changephoneinfo_image=-12627531 -avatar_backgroundPink=-12627531 -chat_inAudioPerfomerText=-1069592139 -player_button=-8550769 -login_progressOuter=-12627531 -avatar_backgroundInProfileOrange=-12627531 -chat_inContactNameText=-12627531 -chats_menuPhoneCats=-2130706433 -chat_outPreviewLine=-1 -dialogScrollGlow=-12627531 -chat_messagePanelHint=-8550769 -location_sendLiveLocationBackground=-769226 -windowBackgroundGray=-1118482 -chat_inViaBotNameText=-2143333963 -chat_outVoiceSeekbar=1627389951 -dialogGrayLine=167772160 -player_actionBarTitle=-12627531 -chat_outFileIcon=-12627531 -calls_ratingStar=-8550769 -chat_adminText=-2143333963 -chat_inFileProgress=-1 -dialogIcon=-8550769 -chat_emojiPanelEmptyText=-8550769 -chat_replyPanelClose=-8550769 -chat_emojiPanelBackspace=1621008030 -featuredStickers_addButtonPressed=-2143333963 -chat_outAudioTitleText=-1 -chat_emojiPanelStickerSetNameIcon=-8550769 -chat_emojiPanelBackground=-328966 -chats_unreadCounter=-12627531 -groupcreate_hintText=-8550769 -chat_inReplyMediaMessageSelectedText=-1069592139 -dialogCheckboxSquareUnchecked=-8550769 -avatar_actionBarSelectorOrange=-2130706433 -avatar_backgroundInProfileRed=-12627531 -chat_emojiPanelNewTrending=-12627531 -chat_emojiPanelStickerPackSelector=-12627531 -chat_unreadMessagesStartArrowIcon=-12627531 -avatar_backgroundActionBarOrange=-12627531 -windowBackgroundWhiteBlackText=-12434878 -avatar_backgroundActionBarBlue=-12627531 -dialogTextLink=-12627531 -chat_recordTime=-8550769 -windowBackgroundWhiteBlueHeader=-12627531 -files_folderIconBackground=-12627531 -chat_messagePanelVoiceBackground=-12627531 -groupcreate_onlineText=-12627531 -divider=83886080 -chat_topPanelLine=-12627531 -avatar_backgroundViolet=-12627531 -dialogTopBackground=-12627531 -chat_inReplyMessageText=-12434878 -dialogInputField=-8550769 -windowBackgroundWhiteInputFieldActivated=-12627531 -chat_outInstantSelected=-2130706433 -chat_outSentCheck=-2130706433 -player_placeholder=-2137088354 -chat_outFileSelectedIcon=-12627531 -picker_disabledButton=-2137088354 -groupcreate_spanBackground=-8812853 -dialogButton=-12627531 -contextProgressInner1=-1118482 -contextProgressInner3=-12434878 -chat_inLoaderPhotoIconSelected=-12627531 -actionBarDefaultSubtitle=-2130706433 -contextProgressInner2=-2130706433 -chat_inContactPhoneText=-1069592139 -chat_inlineResultIcon=-12627531 -dialogLineProgress=-12627531 -chats_draft=-12627531 -chat_outPreviewInstantText=-1 -chat_inMenuSelected=-2143333963 -avatar_backgroundOrange=-12627531 -avatar_actionBarSelectorGreen=-2130706433 -chat_outLocationIcon=-12627531 -chat_inLoaderSelected=-12627531 -location_liveLocationProgress=-12627531 -dialogTextRed=-769226 -chat_inBubbleShadow=-16777216 -dialogProgressCircle=-12627531 -chat_outAudioProgress=-12627531 -stickers_menu=-8550769 -avatar_subtitleInProfilePink=-2130706433 -player_progress=-12627531 -chat_inReplyLine=-12627531 -dialogBackground=-328966 -dialogLineProgressBackground=-2137088354 -chat_inReplyNameText=-12627531 -chat_gifSaveHintBackground=-12627531 -actionBarActionModeDefaultIcon=-1 -windowBackgroundWhiteRedText4=-769226 -windowBackgroundWhiteRedText3=-769226 -windowBackgroundWhiteRedText6=-769226 -chat_goDownButtonIcon=-1 -windowBackgroundWhiteRedText5=-769226 -featuredStickers_delButtonPressed=-2131475658 -chat_outAudioSelectedProgress=-12627531 -chat_messageTextOut=-1 -chat_inInstant=-12627531 -groupcreate_cursor=-12627531 -avatar_backgroundSaved=-12627531 -returnToCallBackground=-1 -checkboxSquareUnchecked=-8550769 -dialogCheckboxSquareDisabled=-2143333963 -chat_fieldOverlayText=-12627531 -chat_messagePanelSend=-12627531 -switchThumb=-657931 -windowBackgroundWhiteRedText2=-769226 -chats_nameIcon=-12434878 -avatar_backgroundBlue=-12627531 -chat_inSentClock=-2143333963 -avatar_nameInMessageRed=-12627531 -chat_outLoaderPhoto=-12627531 -chat_botSwitchToInlineText=-12627531 -avatar_backgroundInProfilePink=-12627531 -avatar_nameInMessageOrange=-12627531 -featuredStickers_unread=-12627531 -chats_pinnedIcon=-8550769 -chat_replyPanelLine=167772160 -avatar_subtitleInProfileOrange=-2130706433 -chat_outSentCheckSelected=-2130706433 -chat_inVenueInfoSelectedText=-2143333963 -dialogTextBlue2=-12627531 -dialogTextBlue3=-12627531 -avatar_backgroundGroupCreateSpanBlue=-12627531 -dialogTextBlue4=-12627531 -windowBackgroundWhiteGreenText=-12627531 -chat_topPanelMessage=-8550769 -chat_emojiPanelIcon=1358954496 -chat_emojiPanelTrendingDescription=-8550769 -calls_callReceivedGreenIcon=-12627531 -chats_pinnedOverlay=-657931 -windowBackgroundWhiteInputField=-8550769 -avatar_backgroundRed=-12627531 -chat_emojiPanelIconSelector=-12627531 -chat_inForwardedNameText=-2143333963 -chats_sentError=-769226 -groupcreate_checkbox=-12627531 -chats_actionBackground=-12627531 -avatar_nameInMessageGreen=-12627531 -chat_outContactNameText=-1 -chat_inSiteNameText=-12627531 -chat_linkSelectBackground=-2143333963 -dialogLinkSelection=-2143333963 -windowBackgroundWhiteBlueText=-12627531 -avatar_nameInMessageCyan=-12627531 -chat_mediaLoaderPhotoIconSelected=-1 -chat_inLocationBackground=-12627531 -radioBackground=-2137088354 -contextProgressOuter1=-12627531 -dialogTextGray3=-8550769 -chat_inFileIcon=-1 -avatar_backgroundActionBarPink=-12627531 -dialogTextGray2=-8550769 -dialogTextGray4=-8550769 -chat_searchPanelIcons=-12627531 -windowBackgroundWhiteLinkText=-12627531 -chat_inAudioSeekbarSelected=1077891509 -chat_outVenueInfoText=-1056964609 -chat_outContactPhoneText=-1056964609 -chat_inAudioTitleText=-12627531 -chat_messageLinkIn=-12627531 -chats_menuBackground=-328966 -chat_serviceBackground=1610612736 -windowBackgroundWhiteGrayLine=-8550769 -chats_secretIcon=-12627531 -chat_inFileBackground=-12627531 -chat_inBubbleSelected=-1056964609 -chat_outInstant=-1 -chat_outViewsSelected=-2130706433 -chat_emojiPanelShadowLine=-1118482 -actionBarDefaultSearchPlaceholder=-2130706433 -actionBarActionModeDefaultSelector=-16777216 -chat_outForwardedNameText=-2130706433 -dialogRoundCheckBox=-12627531 -chat_emojiPanelTrendingTitle=-12434878 -featuredStickers_delButton=-769226 -returnToCallText=-12627531 -switchThumbChecked=-12627531 -windowBackgroundWhite=-328966 -chat_outSiteNameText=-1 -groupcreate_offlineText=-8550769 -chat_inVoiceSeekbarSelected=1077891509 -avatar_backgroundCyan=-12627531 -dialogTextGray=-8550769 -chat_messageLinkOut=-1056964609 -chat_emojiPanelStickerSetName=-8550769 -dialogRadioBackgroundChecked=-12627531 -picker_badge=-12627531 -chat_inVenueNameText=-12627531 -chat_outFileInfoSelectedText=-1056964609 -chats_tabletSelectedOverlay=-1118482 -chat_outAudioDurationSelectedText=-2130706433 -avatar_actionBarSelectorPink=-2130706433 -dialogTextHint=-8550769 -chat_topPanelTitle=-12627531 -chat_inAudioCacheSeekbar=-2143333963 -chat_outContactIcon=-12627531 -avatar_subtitleInProfileBlue=-2130706433 -featuredStickers_addButton=-12627531 -chat_inFileInfoText=-1069592139 -chat_inPreviewLine=-12627531 -avatar_backgroundGreen=-12627531 -profile_creatorIcon=-12627531 -avatar_subtitleInProfileGreen=-2130706433 -chats_sentCheck=-12627531 -chat_outVoiceSeekbarFill=-1 -chat_outReplyLine=-1 -chat_inAudioSeekbarFill=-12627531 -chat_messagePanelIcons=-8550769 -inappPlayerTitle=-12434878 -chat_inReplyMediaMessageText=-1069592139 -progressCircle=-12627531 -chat_botKeyboardButtonBackground=-12627531 -chat_emojiPanelIconSelected=-12627531 -chat_inContactBackground=-12627531 -chats_menuItemIcon=-8550769 -chat_outVenueInfoSelectedText=-1056964609 -wallpaperFileOffset=-1 -chat_outVenueNameText=-1 -chat_outBubbleShadow=-15064194 -checkboxSquareBackground=-12627531 -files_folderIcon=-328966 -chats_menuCloudBackgroundCats=-2147483648 -chat_topPanelClose=-8550769 -profile_adminIcon=-2143333963 -chats_verifiedBackground=0 -chat_inTimeSelectedText=-2143333963 -chat_outFileBackgroundSelected=-1 -chat_outVoiceSeekbarSelected=1627389951 -windowBackgroundWhiteGrayIcon=-8550769 -avatar_backgroundActionBarViolet=-12627531 -profile_verifiedCheck=-1 -chat_mediaTimeBackground=-2147483648 -listSelectorSDK21=251658240 -chat_outFileNameText=-1 -picker_enabledButton=-12627531 -avatar_backgroundInProfileViolet=-12627531 -avatar_nameInMessagePink=-12627531 -windowBackgroundWhiteGrayText=-8550769 -musicPicker_buttonBackground=-12627531 -avatar_actionBarSelectorViolet=-2130706433 -avatar_nameInMessageBlue=-12627531 -dialogTextBlack=-12434878 -actionBarDefault=-12627531 -location_placeLocationBackground=-12627531 -profile_actionIcon=-12627531 -actionBarDefaultSelector=-2130706433 -chats_menuTopShadow=-2147483648 -chat_outAudioPerfomerText=-1056964609 -sharedMedia_startStopLoadIcon=-12627531 -chat_serviceBackgroundSelected=-2147483648 -inappPlayerPlayPause=-12627531 -chat_inVenueInfoText=-2143333963 -chat_replyPanelIcons=-12627531 -checkboxSquareDisabled=-2143333963 -fastScrollInactive=-8550769 -chat_outSentClockSelected=-2130706433 -featuredStickers_addedIcon=-12627531 -chat_recordedVoicePlayPausePressed=-2130706433 -chat_goDownButtonCounter=-12627531 -musicPicker_checkbox=-12627531 -chat_outFileBackground=-1 -chats_name=-12434878 -dialogBadgeBackground=-12627531 -chat_outBubbleSelected=-1069592139 -avatar_backgroundInProfileBlue=-12627531 -chat_inFileNameText=-12627531 -inappPlayerPerformer=-12434878 -chat_inInstantSelected=-2143333963 -chat_inLocationIcon=-1 -chat_outFileInfoText=-1056964609 -groupcreate_checkboxCheck=-328966 -chat_unreadMessagesStartBackground=-328966 -chat_inLoaderPhoto=-1 -chat_inFileInfoSelectedText=-1069592139 -chat_wallpaper=-657931 -chat_outMenuSelected=-2130706433 -fastScrollActive=-12627531 -chat_outLoaderPhotoSelected=-12627531 -chat_muteIcon=-2130706433 -chat_selectedBackground=1077891509 -chat_recordedVoiceBackground=-12627531 -chat_inAudioDurationText=-2143333963 -chat_secretTimeText=-1 -groupcreate_sectionText=-8550769 -actionBarDefaultSubmenuItem=-12434878 -dialogInputFieldActivated=-12627531 -login_progressInner=-1118482 -chats_actionMessage=-12627531 -chat_inLoaderPhotoIcon=-12627531 -location_markerX=-2147483648 -avatar_actionBarSelectorBlue=-2130706433 -chat_addContact=-12627531 -player_placeholderBackground=-657931 -switchTrackChecked=-2143333963 -windowBackgroundWhiteHintText=-8550769 -chat_inLoader=-12627531 -chat_adminSelectedText=-2143333963 -groupcreate_spanText=-1 -chat_outPreviewInstantSelectedText=-2130706433 -player_actionBarSelector=-2143333963 -key_player_progressCachedBackground=-2143333963 -chat_outTimeText=-2130706433 -chat_outBubble=-12627531 -avatar_backgroundActionBarCyan=-12627531 -chats_verifiedCheck=-12627531 -chat_emojiPanelMasksIconSelected=-12627531 -chats_menuItemText=-12434878 -chats_message=-9079435 -chat_outReplyNameText=-1 -chat_outReplyMediaMessageText=-1056964609 -chat_textSelectBackground=-8812853 -chat_messagePanelVoiceDelete=-8550769 -chats_date=-8550769 -chat_messagePanelText=-12434878 -player_buttonActive=-12627531 -chat_outLoaderPhotoIcon=-1 -chat_outContactBackground=-1 -sharedMedia_linkPlaceholder=-12627531 -windowBackgroundWhiteBlueText7=-12627531 -windowBackgroundWhiteBlueText6=-12627531 -calls_callReceivedRedIcon=-769226 -chat_outLocationBackground=-1 -windowBackgroundWhiteBlueText3=-12627531 -windowBackgroundWhiteBlueText2=-12627531 -windowBackgroundWhiteBlueText5=-12627531 -windowBackgroundWhiteBlueText4=-12627531 -chat_replyPanelMessage=-12434878 -stickers_menuSelector=-2147483648 -chat_inViewsSelected=-2143333963 -windowBackgroundWhiteLinkSelection=1077891509 -player_background=-328966 -inappPlayerClose=-2137088354 -player_actionBarSubtitle=-2143333963 -chat_outAudioCacheSeekbar=-2143333963 -chats_sentClock=-12627531 -chat_inAudioSeekbar=1077891509 -avatar_subtitleInProfileRed=-2130706433 -avatar_backgroundActionBarRed=-12627531 -chat_inPreviewInstantText=-12627531 -chat_messagePanelVoiceShadow=-12627531 -chat_inViews=-2143333963 -chat_outLoaderSelected=-1 -dialogButtonSelector=251658240 -chats_menuItemCheck=-12627531 -player_actionBarItems=-12627531 -chat_sentError=-769226 -avatar_actionBarSelectorRed=-2130706433 -player_progressBackground=1084137118 -chat_inAudioDurationSelectedText=-2143333963 -windowBackgroundWhiteGrayText2=-8550769 -chat_outAudioSeekbarSelected=1627389951 -chat_outLoaderPhotoIconSelected=-1 -player_actionBarTop=855638016 -windowBackgroundWhiteGrayText7=-8550769 -windowBackgroundWhiteGrayText8=-8550769 -windowBackgroundWhiteGrayText5=-8550769 -windowBackgroundWhiteGrayText6=-8550769 -windowBackgroundWhiteGrayText3=-8550769 -windowBackgroundWhiteGrayText4=-8550769 -chat_inTimeText=-2143333963 -dialogRadioBackground=-8550769 -windowBackgroundWhiteRedText=-769226 -chat_outReplyMessageText=-2130706433 -chat_recordedVoiceDot=-12627531 -chat_recordedVoiceProgress=-2130706433 -chat_inLoaderPhotoSelected=-1 -chat_inVoiceSeekbarFill=-12627531 -graySection=-328966 -chat_outAudioSeekbar=1627389951 -chats_muteIcon=-8550769 -chat_inVoiceSeekbar=1077891509 -profile_verifiedBackground=0 -chat_outFileProgress=-12627531 -chat_outLoader=-1 -chats_actionPressedBackground=1073741824 -windowBackgroundWhiteGreenText2=-12627531 -chat_replyPanelName=-12627531 -windowBackgroundWhiteValueText=-12627531 -chat_outAudioDurationText=-2130706433 -chat_outMenu=-2130706433 -avatar_backgroundInProfileGreen=-12627531 -chat_goDownButton=-12627531 -chats_secretName=-12627531 -chat_inMenu=-2143333963 -chat_recordVoiceCancel=-12627531 -chat_inFileSelectedIcon=-1 -chat_outReplyMediaMessageSelectedText=-1056964609 -chat_mediaLoaderPhoto=-2147483648 -avatar_backgroundInProfileCyan=-12627531 -calls_ratingStarSelected=-12627531 -chat_reportSpam=-769226 -chat_messageTextIn=-12434878 -avatar_subtitleInProfileCyan=-2130706433 -chat_emojiPanelMasksIcon=-8550769 -chats_attachMessage=-12627531 -chat_topPanelBackground=-328966 -chat_searchPanelText=-12434878 -chat_outSentClock=-2130706433 -dialogBackgroundGray=-657931 diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 11c6b06d6..bc3eb7a87 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -36,6 +36,10 @@ import android.util.LongSparseArray; import android.util.SparseArray; import android.widget.Toast; +import androidx.core.content.pm.ShortcutInfoCompat; +import androidx.core.content.pm.ShortcutManagerCompat; +import androidx.core.graphics.drawable.IconCompat; + import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; import org.telegram.SQLite.SQLitePreparedStatement; @@ -71,10 +75,6 @@ import java.util.concurrent.CountDownLatch; import tw.nekomimi.nekogram.NekoConfig; -import androidx.core.content.pm.ShortcutInfoCompat; -import androidx.core.content.pm.ShortcutManagerCompat; -import androidx.core.graphics.drawable.IconCompat; - @SuppressWarnings("unchecked") public class MediaDataController extends BaseController { @@ -1019,7 +1019,7 @@ public class MediaDataController extends BaseController { } public void loadFeaturedStickers(boolean cache, boolean force) { - /*if (loadingFeaturedStickers) { + if (loadingFeaturedStickers || NekoConfig.disableTrending) { return; } loadingFeaturedStickers = true; @@ -1074,7 +1074,7 @@ public class MediaDataController extends BaseController { processLoadedFeaturedStickers(null, null, false, (int) (System.currentTimeMillis() / 1000), req.hash); } })); - }*/ + } } private void processLoadedFeaturedStickers(final ArrayList res, final ArrayList unreadStickers, final boolean cache, final int date, final int hash) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index a395b4752..e9ab929fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -4222,7 +4222,7 @@ public class NotificationsController extends BaseController { msgHeardIntent.putExtra("max_id", max_id); msgHeardIntent.putExtra("currentAccount", currentAccount); PendingIntent readPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, internalId, msgHeardIntent, PendingIntent.FLAG_UPDATE_CURRENT); - NotificationCompat.Action readAction = new NotificationCompat.Action.Builder(R.drawable.deproko_baseline_check_double_24, LocaleController.getString("MarkAsRead", R.string.MarkAsRead), readPendingIntent) + NotificationCompat.Action readAction = new NotificationCompat.Action.Builder(R.drawable.baseline_done_all_24, LocaleController.getString("MarkAsRead", R.string.MarkAsRead), readPendingIntent) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) .setShowsUserInterface(false) .build(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java index b65466dc0..daa470762 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java @@ -96,6 +96,8 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; +import kotlin.Unit; +import tw.nekomimi.nekogram.BottomBuilder; import tw.nekomimi.nekogram.NekoConfig; /** @@ -105,1633 +107,1644 @@ import tw.nekomimi.nekogram.NekoConfig; @SuppressLint("NewApi") public abstract class VoIPBaseService extends Service implements SensorEventListener, AudioManager.OnAudioFocusChangeListener, VoIPController.ConnectionStateListener, NotificationCenter.NotificationCenterDelegate { - protected int currentAccount = -1; - public static final int STATE_WAIT_INIT = Instance.STATE_WAIT_INIT; - public static final int STATE_WAIT_INIT_ACK = Instance.STATE_WAIT_INIT_ACK; - public static final int STATE_ESTABLISHED = Instance.STATE_ESTABLISHED; - public static final int STATE_FAILED = Instance.STATE_FAILED; - public static final int STATE_RECONNECTING = Instance.STATE_RECONNECTING; - public static final int STATE_CREATING = 6; - public static final int STATE_ENDED = 11; - public static final String ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG"; - - protected static final int ID_ONGOING_CALL_NOTIFICATION = 201; - protected static final int ID_INCOMING_CALL_NOTIFICATION = 202; - - public static final int DISCARD_REASON_HANGUP = 1; - public static final int DISCARD_REASON_DISCONNECT = 2; - public static final int DISCARD_REASON_MISSED = 3; - public static final int DISCARD_REASON_LINE_BUSY = 4; - - public static final int AUDIO_ROUTE_EARPIECE = 0; - public static final int AUDIO_ROUTE_SPEAKER = 1; - public static final int AUDIO_ROUTE_BLUETOOTH = 2; - - protected static final boolean USE_CONNECTION_SERVICE = isDeviceCompatibleWithConnectionServiceAPI(); - - protected static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; - protected static VoIPBaseService sharedInstance; - protected static Runnable setModeRunnable; - protected static final Object sync = new Object(); - protected NetworkInfo lastNetInfo; - protected int currentState = 0; - protected Notification ongoingCallNotification; - protected NativeInstance tgVoip; - protected boolean wasConnected; - - protected TLRPC.Chat chat; - - protected boolean isVideoAvailable; - protected boolean notificationsDisabled; - protected boolean switchingCamera; - protected boolean isFrontFaceCamera = true; - protected String lastError; - protected PowerManager.WakeLock proximityWakelock; - protected PowerManager.WakeLock cpuWakelock; - protected boolean isProximityNear; - protected boolean isHeadsetPlugged; - protected int previousAudioOutput; - protected ArrayList stateListeners = new ArrayList<>(); - protected MediaPlayer ringtonePlayer; - protected Vibrator vibrator; - protected SoundPool soundPool; - protected int spRingbackID; - protected int spFailedID; - protected int spEndId; - protected int spVoiceChatEndId; - protected int spVoiceChatStartId; - protected int spVoiceChatConnecting; - protected int spBusyId; - protected int spConnectingId; - protected int spPlayID; - protected boolean needPlayEndSound; - protected boolean hasAudioFocus; - protected boolean micMute; - protected boolean unmutedByHold; - protected BluetoothAdapter btAdapter; - protected Instance.TrafficStats prevTrafficStats; - protected boolean isBtHeadsetConnected; - protected boolean screenOn; - - private Runnable updateNotificationRunnable; - - protected Runnable onDestroyRunnable; - - protected boolean playedConnectedSound; - - protected int videoState = Instance.VIDEO_STATE_INACTIVE; - - public TLRPC.PhoneCall privateCall; - public ChatObject.Call groupCall; - - protected int mySource; - protected boolean createGroupCall; - - protected long callStartTime; - protected boolean playingSound; - protected boolean isOutgoing; - public boolean videoCall; - protected long videoCapturer; - protected Runnable timeoutRunnable; - - private Boolean mHasEarpiece; - private boolean wasEstablished; - protected int signalBarCount; - protected int currentAudioState = Instance.AUDIO_STATE_ACTIVE; - protected int currentVideoState = Instance.VIDEO_STATE_INACTIVE; - protected boolean audioConfigured; - protected int audioRouteToSet = AUDIO_ROUTE_BLUETOOTH; - protected boolean speakerphoneStateToSet; - protected CallConnection systemCallConnection; - protected int callDiscardReason; - protected boolean bluetoothScoActive; - protected boolean needSwitchToBluetoothAfterScoActivates; - protected boolean didDeleteConnectionServiceContact; - protected Runnable connectingSoundRunnable; - - private String currentBluetoothDeviceName; - - public final SharedUIParams sharedUIParams = new SharedUIParams(); - - protected Runnable afterSoundRunnable = new Runnable() { - @Override - public void run() { - - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - am.abandonAudioFocus(VoIPBaseService.this); - am.unregisterMediaButtonEventReceiver(new ComponentName(VoIPBaseService.this, VoIPMediaButtonReceiver.class)); - if (!USE_CONNECTION_SERVICE && sharedInstance == null) { - if (isBtHeadsetConnected) { - am.stopBluetoothSco(); - am.setBluetoothScoOn(false); - bluetoothScoActive = false; - } - am.setSpeakerphoneOn(false); - } - - Utilities.globalQueue.postRunnable(() -> soundPool.release()); - Utilities.globalQueue.postRunnable(setModeRunnable = () -> { - synchronized (sync) { - if (setModeRunnable == null) { - return; - } - setModeRunnable = null; - } - try { - am.setMode(AudioManager.MODE_NORMAL); - } catch (SecurityException x) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Error setting audio more to normal", x); - } - } - }); - } - }; - - boolean fetchingBluetoothDeviceName; - private BluetoothProfile.ServiceListener serviceListener = new BluetoothProfile.ServiceListener() { - @Override - public void onServiceDisconnected(int profile) { - - } - - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - for (BluetoothDevice device : proxy.getConnectedDevices()) { - if (proxy.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) { - continue; - } - currentBluetoothDeviceName = device.getName(); - break; - } - BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy); - fetchingBluetoothDeviceName = false; - } - }; - - protected BroadcastReceiver receiver = new BroadcastReceiver() { - - @Override - public void onReceive(Context context, Intent intent) { - if (ACTION_HEADSET_PLUG.equals(intent.getAction())) { - isHeadsetPlugged = intent.getIntExtra("state", 0) == 1; - if (isHeadsetPlugged && proximityWakelock != null && proximityWakelock.isHeld()) { - proximityWakelock.release(); - } - if (isHeadsetPlugged) { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (am.isSpeakerphoneOn()) { - previousAudioOutput = 0; - } else if (am.isBluetoothScoOn()) { - previousAudioOutput = 2; - } else { - previousAudioOutput = 1; - } - setAudioOutput(1); - } else { - if (previousAudioOutput >= 0) { - setAudioOutput(previousAudioOutput); - previousAudioOutput = -1; - } - } - isProximityNear = false; - updateOutputGainControlState(); - } else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { - updateNetworkType(); - } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("bt headset state = " + intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)); - } - updateBluetoothHeadsetState(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED) == BluetoothProfile.STATE_CONNECTED); - } else if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(intent.getAction())) { - int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Bluetooth SCO state updated: " + state); - } - if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED && isBtHeadsetConnected) { - if (!btAdapter.isEnabled() || btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET) != BluetoothProfile.STATE_CONNECTED) { - updateBluetoothHeadsetState(false); - return; - } - } - bluetoothScoActive = state == AudioManager.SCO_AUDIO_STATE_CONNECTED; - if (bluetoothScoActive) { - fetchBluetoothDeviceName(); - if (needSwitchToBluetoothAfterScoActivates) { - needSwitchToBluetoothAfterScoActivates = false; - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - am.setSpeakerphoneOn(false); - am.setBluetoothScoOn(true); - } - } - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent.getAction())) { - String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); - if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) { - hangUp(); - } - } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { - screenOn = true; - for (int i = 0; i< stateListeners.size(); i++) { - stateListeners.get(i).onScreenOnChange(screenOn); - } - } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { - screenOn = false; - for (int i = 0; i< stateListeners.size(); i++) { - stateListeners.get(i).onScreenOnChange(screenOn); - } - } - } - }; - - public boolean hasEarpiece() { - if (USE_CONNECTION_SERVICE) { - if (systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { - int routeMask = systemCallConnection.getCallAudioState().getSupportedRouteMask(); - return (routeMask & (CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_WIRED_HEADSET)) != 0; - } - } - if (((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getPhoneType() != TelephonyManager.PHONE_TYPE_NONE) { - return true; - } - if (mHasEarpiece != null) { - return mHasEarpiece; - } - - // not calculated yet, do it now - try { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - Method method = AudioManager.class.getMethod("getDevicesForStream", Integer.TYPE); - Field field = AudioManager.class.getField("DEVICE_OUT_EARPIECE"); - int earpieceFlag = field.getInt(null); - int bitmaskResult = (int) method.invoke(am, AudioManager.STREAM_VOICE_CALL); - - // check if masked by the earpiece flag - if ((bitmaskResult & earpieceFlag) == earpieceFlag) { - mHasEarpiece = Boolean.TRUE; - } else { - mHasEarpiece = Boolean.FALSE; - } - } catch (Throwable error) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Error while checking earpiece! ", error); - } - mHasEarpiece = Boolean.TRUE; - } - - return mHasEarpiece; - } - - protected int getStatsNetworkType() { - int netType = StatsController.TYPE_WIFI; - if (lastNetInfo != null) { - if (lastNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) { - netType = lastNetInfo.isRoaming() ? StatsController.TYPE_ROAMING : StatsController.TYPE_MOBILE; - } - } - return netType; - } - - protected void setSwitchingCamera(boolean switching, boolean isFrontFace) { - switchingCamera = switching; - if (!switching) { - isFrontFaceCamera = isFrontFace; - for (int a = 0; a < stateListeners.size(); a++) { - StateListener l = stateListeners.get(a); - l.onCameraSwitch(isFrontFaceCamera); - } - } - } - - public void registerStateListener(StateListener l) { - if (stateListeners.contains(l)) { - return; - } - stateListeners.add(l); - if (currentState != 0) { - l.onStateChanged(currentState); - } - if (signalBarCount != 0) { - l.onSignalBarsCountChanged(signalBarCount); - } - } - - public void unregisterStateListener(StateListener l) { - stateListeners.remove(l); - } - - public void setMicMute(boolean mute, boolean hold, boolean send) { - if (micMute == mute) { - return; - } - micMute = mute; - if (groupCall != null) { - if (!send) { - TLRPC.TL_groupCallParticipant self = groupCall.participants.get(UserConfig.getInstance(currentAccount).getClientUserId()); - if (self != null && self.muted && !self.can_self_unmute) { - send = true; - } - } - if (send) { - editCallMember(UserConfig.getInstance(currentAccount).getCurrentUser(), mute, -1); - Utilities.globalQueue.postRunnable(updateNotificationRunnable = () -> { - if (updateNotificationRunnable == null) { - return; - } - updateNotificationRunnable = null; - showNotification(chat.title, getRoundAvatarBitmap(chat)); - }); - } - } - unmutedByHold = !micMute && hold; - if (tgVoip != null) { - tgVoip.setMuteMicrophone(mute); - } - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } - - public void editCallMember(TLObject object, boolean mute, int volume) { - if (groupCall == null) { - return; - } - TLRPC.TL_phone_editGroupCallMember req = new TLRPC.TL_phone_editGroupCallMember(); - req.call = groupCall.getInputGroupCall(); - if (object instanceof TLRPC.User) { - TLRPC.User user = (TLRPC.User) object; - if (UserObject.isUserSelf(user)) { - req.user_id = new TLRPC.TL_inputUserSelf(); - } else { - req.user_id = new TLRPC.TL_inputUser(); - req.user_id.user_id = user.id; - req.user_id.access_hash = user.access_hash; - } - } - req.muted = mute; - if (volume >= 0) { - req.volume = volume; - req.flags |= 2; - } - int account = currentAccount; - AccountInstance.getInstance(account).getConnectionsManager().sendRequest(req, (response, error) -> { - if (response != null) { - AccountInstance.getInstance(account).getMessagesController().processUpdates((TLRPC.Updates) response, false); - } - }); - } - - public boolean isMicMute() { - return micMute; - } - - public void toggleSpeakerphoneOrShowRouteSheet(Context context, boolean fromOverlayWindow) { - if (isBluetoothHeadsetConnected() && hasEarpiece()) { - BottomSheet.Builder builder = new BottomSheet.Builder(context) - .setTitle(LocaleController.getString("VoipOutputDevices", R.string.VoipOutputDevices), true) - .setItems(new CharSequence[]{ - LocaleController.getString("VoipAudioRoutingSpeaker", R.string.VoipAudioRoutingSpeaker), - isHeadsetPlugged ? LocaleController.getString("VoipAudioRoutingHeadset", R.string.VoipAudioRoutingHeadset) : LocaleController.getString("VoipAudioRoutingEarpiece", R.string.VoipAudioRoutingEarpiece), - currentBluetoothDeviceName != null ? currentBluetoothDeviceName : LocaleController.getString("VoipAudioRoutingBluetooth", R.string.VoipAudioRoutingBluetooth)}, - new int[]{R.drawable.calls_menu_speaker, - isHeadsetPlugged ? R.drawable.calls_menu_headset : R.drawable.calls_menu_phone, - R.drawable.calls_menu_bluetooth}, (dialog, which) -> { - if (getSharedInstance() == null) { - return; - } - setAudioOutput(which); - }); - - BottomSheet bottomSheet = builder.create(); - if (fromOverlayWindow) { - if (Build.VERSION.SDK_INT >= 26) { - bottomSheet.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); - } else { - bottomSheet.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - } - } - builder.show(); - return; - } - if (USE_CONNECTION_SERVICE && systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { - if (hasEarpiece()) { - systemCallConnection.setAudioRoute(systemCallConnection.getCallAudioState().getRoute() == CallAudioState.ROUTE_SPEAKER ? CallAudioState.ROUTE_WIRED_OR_EARPIECE : CallAudioState.ROUTE_SPEAKER); - } else { - systemCallConnection.setAudioRoute(systemCallConnection.getCallAudioState().getRoute() == CallAudioState.ROUTE_BLUETOOTH ? CallAudioState.ROUTE_WIRED_OR_EARPIECE : CallAudioState.ROUTE_BLUETOOTH); - } - } else if (audioConfigured && !USE_CONNECTION_SERVICE) { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (hasEarpiece()) { - am.setSpeakerphoneOn(!am.isSpeakerphoneOn()); - } else { - am.setBluetoothScoOn(!am.isBluetoothScoOn()); - } - updateOutputGainControlState(); - } else { - speakerphoneStateToSet = !speakerphoneStateToSet; - } - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } - - protected void setAudioOutput(int which) { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (USE_CONNECTION_SERVICE && systemCallConnection != null) { - switch (which) { - case 2: - systemCallConnection.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH); - break; - case 1: - systemCallConnection.setAudioRoute(CallAudioState.ROUTE_WIRED_OR_EARPIECE); - break; - case 0: - systemCallConnection.setAudioRoute(CallAudioState.ROUTE_SPEAKER); - break; - } - } else if (audioConfigured && !USE_CONNECTION_SERVICE) { - switch (which) { - case 2: - if (!bluetoothScoActive) { - needSwitchToBluetoothAfterScoActivates = true; - try { - am.startBluetoothSco(); - } catch (Throwable ignore) { - - } - } else { - am.setBluetoothScoOn(true); - am.setSpeakerphoneOn(false); - } - break; - case 1: - if (bluetoothScoActive) { - am.stopBluetoothSco(); - bluetoothScoActive = false; - } - am.setSpeakerphoneOn(false); - am.setBluetoothScoOn(false); - break; - case 0: - if (bluetoothScoActive) { - am.stopBluetoothSco(); - bluetoothScoActive = false; - } - am.setBluetoothScoOn(false); - am.setSpeakerphoneOn(true); - break; - } - updateOutputGainControlState(); - } else { - switch (which) { - case 2: - audioRouteToSet = AUDIO_ROUTE_BLUETOOTH; - speakerphoneStateToSet = false; - break; - case 1: - audioRouteToSet = AUDIO_ROUTE_EARPIECE; - speakerphoneStateToSet = false; - break; - case 0: - audioRouteToSet = AUDIO_ROUTE_SPEAKER; - speakerphoneStateToSet = true; - break; - } - } - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } - - public boolean isSpeakerphoneOn() { - if (USE_CONNECTION_SERVICE && systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { - int route = systemCallConnection.getCallAudioState().getRoute(); - return hasEarpiece() ? route == CallAudioState.ROUTE_SPEAKER : route == CallAudioState.ROUTE_BLUETOOTH; - } else if (audioConfigured && !USE_CONNECTION_SERVICE) { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - return hasEarpiece() ? am.isSpeakerphoneOn() : am.isBluetoothScoOn(); - } - return speakerphoneStateToSet; - } - - public int getCurrentAudioRoute() { - if (USE_CONNECTION_SERVICE) { - if (systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { - switch (systemCallConnection.getCallAudioState().getRoute()) { - case CallAudioState.ROUTE_BLUETOOTH: - return AUDIO_ROUTE_BLUETOOTH; - case CallAudioState.ROUTE_EARPIECE: - case CallAudioState.ROUTE_WIRED_HEADSET: - return AUDIO_ROUTE_EARPIECE; - case CallAudioState.ROUTE_SPEAKER: - return AUDIO_ROUTE_SPEAKER; - } - } - return audioRouteToSet; - } - if (audioConfigured) { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (am.isBluetoothScoOn()) { - return AUDIO_ROUTE_BLUETOOTH; - } else if (am.isSpeakerphoneOn()) { - return AUDIO_ROUTE_SPEAKER; - } else { - return AUDIO_ROUTE_EARPIECE; - } - } - return audioRouteToSet; - } - - public String getDebugString() { - return tgVoip != null ? tgVoip.getDebugInfo() : ""; - } - - public long getCallDuration() { - if (callStartTime == 0) { - return 0; - } - return SystemClock.elapsedRealtime() - callStartTime; - } - - public static VoIPBaseService getSharedInstance() { - return sharedInstance; - } - - public void stopRinging() { - if (ringtonePlayer != null) { - ringtonePlayer.stop(); - ringtonePlayer.release(); - ringtonePlayer = null; - } - if (vibrator != null) { - vibrator.cancel(); - vibrator = null; - } - } - - protected void showNotification(String name, Bitmap photo) { - Intent intent = new Intent(this, LaunchActivity.class).setAction(groupCall != null ? "voip_chat" : "voip"); - if (groupCall != null) { - intent.putExtra("currentAccount", currentAccount); - } - Notification.Builder builder = new Notification.Builder(this) - .setContentTitle(groupCall != null ? LocaleController.getString("VoipVoiceChat", R.string.VoipVoiceChat) : LocaleController.getString("VoipOutgoingCall", R.string.VoipOutgoingCall)) - .setContentText(name) - .setContentIntent(PendingIntent.getActivity(this, 50, intent, 0)); - if (groupCall != null) { - builder.setSmallIcon(isMicMute() ? R.drawable.voicechat_muted : R.drawable.voicechat_active); - } else { - builder.setSmallIcon(R.drawable.notification); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - Intent endIntent = new Intent(this, VoIPActionsReceiver.class); - endIntent.setAction(getPackageName() + ".END_CALL"); - builder.addAction(R.drawable.ic_call_end_white_24dp, groupCall != null ? LocaleController.getString("VoipGroupLeaveAlertTitle", R.string.VoipGroupLeaveAlertTitle) : LocaleController.getString("VoipEndCall", R.string.VoipEndCall), PendingIntent.getBroadcast(this, 0, endIntent, PendingIntent.FLAG_UPDATE_CURRENT)); - builder.setPriority(Notification.PRIORITY_MAX); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - builder.setShowWhen(false); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - builder.setColor(0xff282e31); - builder.setColorized(true); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setColor(0xff2ca5e0); - } - if (Build.VERSION.SDK_INT >= 26) { - NotificationsController.checkOtherNotificationsChannel(); - builder.setChannelId(NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); - } - if (photo != null) { - builder.setLargeIcon(photo); - } - ongoingCallNotification = builder.getNotification(); - startForeground(ID_ONGOING_CALL_NOTIFICATION, ongoingCallNotification); - } - - protected void startRingtoneAndVibration(int chatID) { - SharedPreferences prefs = MessagesController.getNotificationsSettings(currentAccount); - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - boolean needRing = am.getRingerMode() != AudioManager.RINGER_MODE_SILENT; - if (needRing) { - ringtonePlayer = new MediaPlayer(); - ringtonePlayer.setOnPreparedListener(mediaPlayer -> ringtonePlayer.start()); - ringtonePlayer.setLooping(true); - if (isHeadsetPlugged) { - ringtonePlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); - } else { - ringtonePlayer.setAudioStreamType(AudioManager.STREAM_RING); - if (!USE_CONNECTION_SERVICE) { - am.requestAudioFocus(this, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN); - } - } - try { - String notificationUri; - if (prefs.getBoolean("custom_" + chatID, false)) { - notificationUri = prefs.getString("ringtone_path_" + chatID, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString()); - } else { - notificationUri = prefs.getString("CallsRingtonePath", RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString()); - } - ringtonePlayer.setDataSource(this, Uri.parse(notificationUri)); - ringtonePlayer.prepareAsync(); - } catch (Exception e) { - FileLog.e(e); - if (ringtonePlayer != null) { - ringtonePlayer.release(); - ringtonePlayer = null; - } - } - int vibrate; - if (prefs.getBoolean("custom_" + chatID, false)) { - vibrate = prefs.getInt("calls_vibrate_" + chatID, 0); - } else { - vibrate = prefs.getInt("vibrate_calls", 0); - } - if ((vibrate != 2 && vibrate != 4 && (am.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE || am.getRingerMode() == AudioManager.RINGER_MODE_NORMAL)) || (vibrate == 4 && am.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE)) { - vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); - long duration = 700; - if (vibrate == 1) { - duration /= 2; - } else if (vibrate == 3) { - duration *= 2; - } - vibrator.vibrate(new long[]{0, duration, 500}, 0); - } - } - } - - @Override - public void onDestroy() { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("=============== VoIPService STOPPING ==============="); - } - stopForeground(true); - stopRinging(); - if (ApplicationLoader.mainInterfacePaused || !ApplicationLoader.isScreenOn) { - MessagesController.getInstance(currentAccount).ignoreSetOnline = false; - } - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.appDidLogout); - SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); - Sensor proximity = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); - if (proximity != null) { - sm.unregisterListener(this); - } - if (proximityWakelock != null && proximityWakelock.isHeld()) { - proximityWakelock.release(); - } - if (updateNotificationRunnable != null) { - Utilities.globalQueue.cancelRunnable(updateNotificationRunnable); - updateNotificationRunnable = null; - } - unregisterReceiver(receiver); - if (timeoutRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(timeoutRunnable); - timeoutRunnable = null; - } - super.onDestroy(); - sharedInstance = null; - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didEndCall)); - if (tgVoip != null) { - StatsController.getInstance(currentAccount).incrementTotalCallsTime(getStatsNetworkType(), (int) (getCallDuration() / 1000) % 5); - onTgVoipPreStop(); - if (tgVoip.isGroup()) { - NativeInstance instance = tgVoip; - Utilities.globalQueue.postRunnable(instance::stopGroup); - } else { - Instance.FinalState state = tgVoip.stop(); - updateTrafficStats(state.trafficStats); - onTgVoipStop(state); - } - prevTrafficStats = null; - callStartTime = 0; - tgVoip = null; - Instance.destroyInstance(); - } - if (videoCapturer != 0) { - NativeInstance.destroyVideoCapturer(videoCapturer); - videoCapturer = 0; - } - cpuWakelock.release(); - if (!playingSound) { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (!USE_CONNECTION_SERVICE) { - if (isBtHeadsetConnected) { - am.stopBluetoothSco(); - am.setBluetoothScoOn(false); - am.setSpeakerphoneOn(false); - bluetoothScoActive = false; - } - if (onDestroyRunnable == null) { - Utilities.globalQueue.postRunnable(setModeRunnable = () -> { - synchronized (sync) { - if (setModeRunnable == null) { - return; - } - setModeRunnable = null; - } - try { - am.setMode(AudioManager.MODE_NORMAL); - } catch (SecurityException x) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Error setting audio more to normal", x); - } - } - }); - } - am.abandonAudioFocus(this); - } - am.unregisterMediaButtonEventReceiver(new ComponentName(this, VoIPMediaButtonReceiver.class)); - if (hasAudioFocus) { - am.abandonAudioFocus(this); - } - Utilities.globalQueue.postRunnable(() -> soundPool.release()); - } - - if (USE_CONNECTION_SERVICE) { - if (!didDeleteConnectionServiceContact) { - ContactsController.getInstance(currentAccount).deleteConnectionServiceContact(); - } - if (systemCallConnection != null && !playingSound) { - systemCallConnection.destroy(); - } - } - - ConnectionsManager.getInstance(currentAccount).setAppPaused(true, false); - VoIPHelper.lastCallTime = SystemClock.elapsedRealtime(); - } - - public abstract long getCallID(); - public abstract void hangUp(); - public abstract void hangUp(Runnable onDone); - public abstract void acceptIncomingCall(); - public abstract void declineIncomingCall(int reason, Runnable onDone); - public abstract void declineIncomingCall(); - protected abstract Class getUIActivityClass(); - public abstract CallConnection getConnectionAndStartCall(); - protected abstract void startRinging(); - public abstract void startRingtoneAndVibration(); - protected abstract void updateServerConfig(); - protected abstract void showNotification(); - - protected void onTgVoipPreStop() { - - } - - protected void onTgVoipStop(Instance.FinalState finalState) { - - } - - protected void initializeAccountRelatedThings() { - updateServerConfig(); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.appDidLogout); - ConnectionsManager.getInstance(currentAccount).setAppPaused(false, false); - } - - @SuppressLint("InvalidWakeLockTag") - @Override - public void onCreate() { - super.onCreate(); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("=============== VoIPService STARTING ==============="); - } - try { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER) != null) { - int outFramesPerBuffer = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); - Instance.setBufferSize(outFramesPerBuffer); - } else { - Instance.setBufferSize(AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT) / 2); - } - - cpuWakelock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "telegram-voip"); - cpuWakelock.acquire(); - - btAdapter = am.isBluetoothScoAvailableOffCall() ? BluetoothAdapter.getDefaultAdapter() : null; - - IntentFilter filter = new IntentFilter(); - filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); - if (!USE_CONNECTION_SERVICE) { - filter.addAction(ACTION_HEADSET_PLUG); - if (btAdapter != null) { - filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); - } - filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); - filter.addAction(Intent.ACTION_SCREEN_ON); - filter.addAction(Intent.ACTION_SCREEN_OFF); - } - registerReceiver(receiver, filter); - fetchBluetoothDeviceName(); - Utilities.globalQueue.postRunnable(() -> { - soundPool = new SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0); - spConnectingId = soundPool.load(this, R.raw.voip_connecting, 1); - spRingbackID = soundPool.load(this, R.raw.voip_ringback, 1); - spFailedID = soundPool.load(this, R.raw.voip_failed, 1); - spEndId = soundPool.load(this, R.raw.voip_end, 1); - spBusyId = soundPool.load(this, R.raw.voip_busy, 1); - spVoiceChatEndId = soundPool.load(this, R.raw.voicechat_leave, 1); - spVoiceChatStartId = soundPool.load(this, R.raw.voicechat_join, 1); - spVoiceChatConnecting = soundPool.load(this, R.raw.voicechat_connecting, 1); - }); - - am.registerMediaButtonEventReceiver(new ComponentName(this, VoIPMediaButtonReceiver.class)); - - if (!USE_CONNECTION_SERVICE && btAdapter != null && btAdapter.isEnabled()) { - try { - MediaRouter mr = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE); - if (Build.VERSION.SDK_INT < 24) { - int headsetState = btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET); - updateBluetoothHeadsetState(headsetState == BluetoothProfile.STATE_CONNECTED); - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } else { - MediaRouter.RouteInfo ri = mr.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO); - if (ri.getDeviceType() == MediaRouter.RouteInfo.DEVICE_TYPE_BLUETOOTH) { - int headsetState = btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET); - updateBluetoothHeadsetState(headsetState == BluetoothProfile.STATE_CONNECTED); - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } else { - updateBluetoothHeadsetState(false); - } - } - } catch (Throwable e) { - FileLog.e(e); - } - } - } catch (Exception x) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("error initializing voip controller", x); - } - callFailed(); - } - } - - protected void dispatchStateChanged(int state) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("== Call " + getCallID() + " state changed to " + state + " =="); - } - currentState = state; - if (USE_CONNECTION_SERVICE && state == STATE_ESTABLISHED /*&& !wasEstablished*/ && systemCallConnection != null) { - systemCallConnection.setActive(); - } - for (int a = 0; a < stateListeners.size(); a++) { - StateListener l = stateListeners.get(a); - l.onStateChanged(state); - } - } - - protected void updateTrafficStats(Instance.TrafficStats trafficStats) { - if (trafficStats == null) { - trafficStats = tgVoip.getTrafficStats(); - } - final long wifiSentDiff = trafficStats.bytesSentWifi - (prevTrafficStats != null ? prevTrafficStats.bytesSentWifi : 0); - final long wifiRecvdDiff = trafficStats.bytesReceivedWifi - (prevTrafficStats != null ? prevTrafficStats.bytesReceivedWifi : 0); - final long mobileSentDiff = trafficStats.bytesSentMobile - (prevTrafficStats != null ? prevTrafficStats.bytesSentMobile : 0); - final long mobileRecvdDiff = trafficStats.bytesReceivedMobile - (prevTrafficStats != null ? prevTrafficStats.bytesReceivedMobile : 0); - prevTrafficStats = trafficStats; - if (wifiSentDiff > 0) { - StatsController.getInstance(currentAccount).incrementSentBytesCount(StatsController.TYPE_WIFI, StatsController.TYPE_CALLS, wifiSentDiff); - } - if (wifiRecvdDiff > 0) { - StatsController.getInstance(currentAccount).incrementReceivedBytesCount(StatsController.TYPE_WIFI, StatsController.TYPE_CALLS, wifiRecvdDiff); - } - if (mobileSentDiff > 0) { - StatsController.getInstance(currentAccount).incrementSentBytesCount(lastNetInfo != null && lastNetInfo.isRoaming() ? StatsController.TYPE_ROAMING : StatsController.TYPE_MOBILE, StatsController.TYPE_CALLS, mobileSentDiff); - } - if (mobileRecvdDiff > 0) { - StatsController.getInstance(currentAccount).incrementReceivedBytesCount(lastNetInfo != null && lastNetInfo.isRoaming() ? StatsController.TYPE_ROAMING : StatsController.TYPE_MOBILE, StatsController.TYPE_CALLS, mobileRecvdDiff); - } - } - - @SuppressLint("InvalidWakeLockTag") - protected void configureDeviceForCall() { - needPlayEndSound = true; - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (!USE_CONNECTION_SERVICE) { - Utilities.globalQueue.postRunnable(() -> { - try { - am.setMode(AudioManager.MODE_IN_COMMUNICATION); - } catch (Exception e) { - FileLog.e(e); - } - }); - am.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN); - if (isBluetoothHeadsetConnected() && hasEarpiece()) { - switch (audioRouteToSet) { - case AUDIO_ROUTE_BLUETOOTH: - if (!bluetoothScoActive) { - needSwitchToBluetoothAfterScoActivates = true; - try { - am.startBluetoothSco(); - } catch (Throwable ignore) { - - } - } else { - am.setBluetoothScoOn(true); - am.setSpeakerphoneOn(false); - } - break; - case AUDIO_ROUTE_EARPIECE: - am.setBluetoothScoOn(false); - am.setSpeakerphoneOn(false); - break; - case AUDIO_ROUTE_SPEAKER: - am.setBluetoothScoOn(false); - am.setSpeakerphoneOn(true); - break; - } - } else if (isBluetoothHeadsetConnected()) { - am.setBluetoothScoOn(speakerphoneStateToSet); - } else { - am.setSpeakerphoneOn(speakerphoneStateToSet); - } - } - updateOutputGainControlState(); - audioConfigured = true; - - SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); - Sensor proximity = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); - try { - if (proximity != null) { - proximityWakelock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, "telegram-voip-prx"); - sm.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL); - } - } catch (Exception x) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Error initializing proximity sensor", x); - } - } - } - - private void fetchBluetoothDeviceName() { - if (fetchingBluetoothDeviceName) { - return; - } - try { - currentBluetoothDeviceName = null; - fetchingBluetoothDeviceName = true; - BluetoothAdapter.getDefaultAdapter().getProfileProxy(this, serviceListener, BluetoothProfile.HEADSET); - } catch (Throwable e) { - FileLog.e(e); - } - } - - @SuppressLint("NewApi") - @Override - public void onSensorChanged(SensorEvent event) { - if (unmutedByHold || currentVideoState == Instance.VIDEO_STATE_ACTIVE || videoState == Instance.VIDEO_STATE_ACTIVE) { - return; - } - if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) { - AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (isHeadsetPlugged || am.isSpeakerphoneOn() || (isBluetoothHeadsetConnected() && am.isBluetoothScoOn())) { - return; - } - boolean newIsNear = event.values[0] < Math.min(event.sensor.getMaximumRange(), 3); - checkIsNear(newIsNear); - } - } - - protected void checkIsNear() { - if (currentVideoState == Instance.VIDEO_STATE_ACTIVE || videoState == Instance.VIDEO_STATE_ACTIVE) { - checkIsNear(false); - } - } - - private void checkIsNear(boolean newIsNear) { - if (newIsNear != isProximityNear) { - if (NekoConfig.disableProximityEvents) return; - if (BuildVars.LOGS_ENABLED) { - FileLog.d("proximity " + newIsNear); - } - isProximityNear = newIsNear; - try { - if (isProximityNear) { - proximityWakelock.acquire(); - } else { - proximityWakelock.release(1); // this is non-public API before L - } - } catch (Exception x) { - FileLog.e(x); - } - } - } - - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - - } - - public boolean isBluetoothHeadsetConnected() { - if (USE_CONNECTION_SERVICE && systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { - return (systemCallConnection.getCallAudioState().getSupportedRouteMask() & CallAudioState.ROUTE_BLUETOOTH) != 0; - } - return isBtHeadsetConnected; - } - - public void onAudioFocusChange(int focusChange) { - if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { - hasAudioFocus = true; - } else { - hasAudioFocus = false; - } - } - - protected void updateBluetoothHeadsetState(boolean connected) { - if (connected == isBtHeadsetConnected) { - return; - } - if (BuildVars.LOGS_ENABLED) { - FileLog.d("updateBluetoothHeadsetState: " + connected); - } - isBtHeadsetConnected = connected; - final AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - if (connected && !isRinging() && currentState != 0) { - if (bluetoothScoActive) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("SCO already active, setting audio routing"); - } - am.setSpeakerphoneOn(false); - am.setBluetoothScoOn(true); - } else { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("startBluetoothSco"); - } - needSwitchToBluetoothAfterScoActivates = true; - // some devices ignore startBluetoothSco when called immediately after the headset is connected, so delay it - AndroidUtilities.runOnUIThread(() -> { - try { - am.startBluetoothSco(); - } catch (Throwable ignore) { - - } - }, 500); - } - } else { - bluetoothScoActive = false; - } - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } - - public String getLastError() { - return lastError; - } - - public int getCallState() { - return currentState; - } - - protected void updateNetworkType() { - if (tgVoip != null) { - if (tgVoip.isGroup()) { - - } else { - tgVoip.setNetworkType(getNetworkType()); - } - } else { - lastNetInfo = getActiveNetworkInfo(); - } - } - - protected int getNetworkType() { - final NetworkInfo info = lastNetInfo = getActiveNetworkInfo(); - int type = Instance.NET_TYPE_UNKNOWN; - if (info != null) { - switch (info.getType()) { - case ConnectivityManager.TYPE_MOBILE: - switch (info.getSubtype()) { - case TelephonyManager.NETWORK_TYPE_GPRS: - type = Instance.NET_TYPE_GPRS; - break; - case TelephonyManager.NETWORK_TYPE_EDGE: - case TelephonyManager.NETWORK_TYPE_1xRTT: - type = Instance.NET_TYPE_EDGE; - break; - case TelephonyManager.NETWORK_TYPE_UMTS: - case TelephonyManager.NETWORK_TYPE_EVDO_0: - type = Instance.NET_TYPE_3G; - break; - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - type = Instance.NET_TYPE_HSPA; - break; - case TelephonyManager.NETWORK_TYPE_LTE: - type = Instance.NET_TYPE_LTE; - break; - default: - type = Instance.NET_TYPE_OTHER_MOBILE; - break; - } - break; - case ConnectivityManager.TYPE_WIFI: - type = Instance.NET_TYPE_WIFI; - break; - case ConnectivityManager.TYPE_ETHERNET: - type = Instance.NET_TYPE_ETHERNET; - break; - } - } - return type; - } - - protected NetworkInfo getActiveNetworkInfo() { - return ((ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); - } - - protected void callFailed() { - callFailed(tgVoip != null ? tgVoip.getLastError() : Instance.ERROR_UNKNOWN); - } - - protected Bitmap getRoundAvatarBitmap(TLObject userOrChat) { - Bitmap bitmap = null; - if (userOrChat instanceof TLRPC.User) { - TLRPC.User user = (TLRPC.User) userOrChat; - if (user.photo != null && user.photo.photo_small != null) { - BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(user.photo.photo_small, null, "50_50"); - if (img != null) { - bitmap = img.getBitmap().copy(Bitmap.Config.ARGB_8888, true); - } else { - try { - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inMutable = true; - bitmap = BitmapFactory.decodeFile(FileLoader.getPathToAttach(user.photo.photo_small, true).toString(), opts); - } catch (Throwable e) { - FileLog.e(e); - } - } - } - } else { - TLRPC.Chat chat = (TLRPC.Chat) userOrChat; - if (chat.photo != null && chat.photo.photo_small != null) { - BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(chat.photo.photo_small, null, "50_50"); - if (img != null) { - bitmap = img.getBitmap().copy(Bitmap.Config.ARGB_8888, true); - } else { - try { - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inMutable = true; - bitmap = BitmapFactory.decodeFile(FileLoader.getPathToAttach(chat.photo.photo_small, true).toString(), opts); - } catch (Throwable e) { - FileLog.e(e); - } - } - } - } - if (bitmap == null) { - Theme.createDialogsResources(this); - AvatarDrawable placeholder; - if (userOrChat instanceof TLRPC.User) { - placeholder = new AvatarDrawable((TLRPC.User) userOrChat); - } else { - placeholder = new AvatarDrawable((TLRPC.Chat) userOrChat); - } - bitmap = Bitmap.createBitmap(AndroidUtilities.dp(42), AndroidUtilities.dp(42), Bitmap.Config.ARGB_8888); - placeholder.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); - placeholder.draw(new Canvas(bitmap)); - } - - Canvas canvas = new Canvas(bitmap); - Path circlePath = new Path(); - circlePath.addCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, Path.Direction.CW); - circlePath.toggleInverseFillType(); - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - canvas.drawPath(circlePath, paint); - return bitmap; - } - - protected void showIncomingNotification(String name, CharSequence subText, TLObject userOrChat, boolean video, int additionalMemberCount) { - Intent intent = new Intent(this, LaunchActivity.class); - intent.setAction("voip"); - Notification.Builder builder = new Notification.Builder(this) - .setContentTitle(video ? LocaleController.getString("VoipInVideoCallBranding", R.string.VoipInVideoCallBranding) : LocaleController.getString("VoipInCallBranding", R.string.VoipInCallBranding)) - .setContentText(name) - .setSmallIcon(R.drawable.notification) - .setSubText(subText) - .setContentIntent(PendingIntent.getActivity(this, 0, intent, 0)); - Uri soundProviderUri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".call_sound_provider/start_ringing"); - if (Build.VERSION.SDK_INT >= 26) { - SharedPreferences nprefs = MessagesController.getGlobalNotificationsSettings(); - int chanIndex = nprefs.getInt("calls_notification_channel", 0); - NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - NotificationChannel oldChannel = nm.getNotificationChannel("incoming_calls" + chanIndex); - if (oldChannel != null) { - nm.deleteNotificationChannel(oldChannel.getId()); - } - NotificationChannel existingChannel = nm.getNotificationChannel("incoming_calls2" + chanIndex); - boolean needCreate = true; - if (existingChannel != null) { - if (existingChannel.getImportance() < NotificationManager.IMPORTANCE_HIGH || !soundProviderUri.equals(existingChannel.getSound()) || existingChannel.getVibrationPattern() != null || existingChannel.shouldVibrate()) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("User messed up the notification channel; deleting it and creating a proper one"); - } - nm.deleteNotificationChannel("incoming_calls2" + chanIndex); - chanIndex++; - nprefs.edit().putInt("calls_notification_channel", chanIndex).commit(); - } else { - needCreate = false; - } - } - if (needCreate) { - AudioAttributes attrs = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) - .build(); - NotificationChannel chan = new NotificationChannel("incoming_calls2" + chanIndex, LocaleController.getString("IncomingCalls", R.string.IncomingCalls), NotificationManager.IMPORTANCE_HIGH); - chan.setSound(soundProviderUri, attrs); - chan.enableVibration(false); - chan.enableLights(false); - chan.setBypassDnd(true); - try { - nm.createNotificationChannel(chan); - } catch (Exception e) { - FileLog.e(e); - this.stopSelf(); - return; - } - } - builder.setChannelId("incoming_calls2" + chanIndex); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setSound(soundProviderUri, AudioManager.STREAM_RING); - } - Intent endIntent = new Intent(this, VoIPActionsReceiver.class); - endIntent.setAction(getPackageName() + ".DECLINE_CALL"); - endIntent.putExtra("call_id", getCallID()); - CharSequence endTitle = LocaleController.getString("VoipDeclineCall", R.string.VoipDeclineCall); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - endTitle = new SpannableString(endTitle); - ((SpannableString) endTitle).setSpan(new ForegroundColorSpan(0xFFF44336), 0, endTitle.length(), 0); - } - PendingIntent endPendingIntent = PendingIntent.getBroadcast(this, 0, endIntent, PendingIntent.FLAG_CANCEL_CURRENT); - builder.addAction(R.drawable.ic_call_end_white_24dp, endTitle, endPendingIntent); - Intent answerIntent = new Intent(this, VoIPActionsReceiver.class); - answerIntent.setAction(getPackageName() + ".ANSWER_CALL"); - answerIntent.putExtra("call_id", getCallID()); - CharSequence answerTitle = LocaleController.getString("VoipAnswerCall", R.string.VoipAnswerCall); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - answerTitle = new SpannableString(answerTitle); - ((SpannableString) answerTitle).setSpan(new ForegroundColorSpan(0xFF00AA00), 0, answerTitle.length(), 0); - } - PendingIntent answerPendingIntent = PendingIntent.getBroadcast(this, 0, answerIntent, PendingIntent.FLAG_CANCEL_CURRENT); - builder.addAction(R.drawable.ic_call, answerTitle, answerPendingIntent); - builder.setPriority(Notification.PRIORITY_MAX); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - builder.setShowWhen(false); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setColor(0xff2ca5e0); - builder.setVibrate(new long[0]); - builder.setCategory(Notification.CATEGORY_CALL); - builder.setFullScreenIntent(PendingIntent.getActivity(this, 0, intent, 0), true); - if (userOrChat instanceof TLRPC.User) { - TLRPC.User user = (TLRPC.User) userOrChat; - if (!TextUtils.isEmpty(user.phone)) { - builder.addPerson("tel:" + user.phone); - } - } - } - Notification incomingNotification = builder.getNotification(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - RemoteViews customView = new RemoteViews(getPackageName(), LocaleController.isRTL ? R.layout.call_notification_rtl : R.layout.call_notification); - customView.setTextViewText(R.id.name, name); - boolean subtitleVisible = true; - if (TextUtils.isEmpty(subText)) { - customView.setViewVisibility(R.id.subtitle, View.GONE); - if (UserConfig.getActivatedAccountsCount() > 1) { - TLRPC.User self = UserConfig.getInstance(currentAccount).getCurrentUser(); - customView.setTextViewText(R.id.title, video ? LocaleController.formatString("VoipInVideoCallBrandingWithName", R.string.VoipInVideoCallBrandingWithName, ContactsController.formatName(self.first_name, self.last_name)) : LocaleController.formatString("VoipInCallBrandingWithName", R.string.VoipInCallBrandingWithName, ContactsController.formatName(self.first_name, self.last_name))); - } else { - customView.setTextViewText(R.id.title, video ? LocaleController.getString("VoipInVideoCallBranding", R.string.VoipInVideoCallBranding) : LocaleController.getString("VoipInCallBranding", R.string.VoipInCallBranding)); - } - } else { - if (UserConfig.getActivatedAccountsCount() > 1) { - TLRPC.User self = UserConfig.getInstance(currentAccount).getCurrentUser(); - customView.setTextViewText(R.id.subtitle, LocaleController.formatString("VoipAnsweringAsAccount", R.string.VoipAnsweringAsAccount, ContactsController.formatName(self.first_name, self.last_name))); - } else { - customView.setViewVisibility(R.id.subtitle, View.GONE); - } - customView.setTextViewText(R.id.title, subText); - } - Bitmap avatar = getRoundAvatarBitmap(userOrChat); - customView.setTextViewText(R.id.answer_text, LocaleController.getString("VoipAnswerCall", R.string.VoipAnswerCall)); - customView.setTextViewText(R.id.decline_text, LocaleController.getString("VoipDeclineCall", R.string.VoipDeclineCall)); - customView.setImageViewBitmap(R.id.photo, avatar); - customView.setOnClickPendingIntent(R.id.answer_btn, answerPendingIntent); - customView.setOnClickPendingIntent(R.id.decline_btn, endPendingIntent); - builder.setLargeIcon(avatar); - - incomingNotification.headsUpContentView = incomingNotification.bigContentView = customView; - } - startForeground(ID_INCOMING_CALL_NOTIFICATION, incomingNotification); - } - - protected void callFailed(String error) { - try { - throw new Exception("Call " + getCallID() + " failed with error: " + error); - } catch (Exception x) { - FileLog.e(x); - } - lastError = error; - AndroidUtilities.runOnUIThread(() -> dispatchStateChanged(STATE_FAILED)); - if (TextUtils.equals(error, Instance.ERROR_LOCALIZED) && soundPool != null) { - playingSound = true; - Utilities.globalQueue.postRunnable(() -> soundPool.play(spFailedID, 1, 1, 0, 0, 1)); - AndroidUtilities.runOnUIThread(afterSoundRunnable, 1000); - } - if (USE_CONNECTION_SERVICE && systemCallConnection != null) { - systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.ERROR)); - systemCallConnection.destroy(); - systemCallConnection = null; - } - stopSelf(); - } - - void callFailedFromConnectionService() { - if (isOutgoing) { - callFailed(Instance.ERROR_CONNECTION_SERVICE); - } else { - hangUp(); - } - } - - @Override - public void onConnectionStateChanged(int newState) { - if (newState == STATE_FAILED) { - callFailed(); - return; - } - if (newState == STATE_ESTABLISHED) { - if (connectingSoundRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(connectingSoundRunnable); - connectingSoundRunnable = null; - } - Utilities.globalQueue.postRunnable(() -> { - if (spPlayID != 0) { - soundPool.stop(spPlayID); - spPlayID = 0; - } - }); - if (groupCall == null && !wasEstablished) { - wasEstablished = true; - if (!isProximityNear && !privateCall.video) { - Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); - if (vibrator.hasVibrator()) { - vibrator.vibrate(100); - } - } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (tgVoip != null) { - StatsController.getInstance(currentAccount).incrementTotalCallsTime(getStatsNetworkType(), 5); - AndroidUtilities.runOnUIThread(this, 5000); - } - } - }, 5000); - if (isOutgoing) { - StatsController.getInstance(currentAccount).incrementSentItemsCount(getStatsNetworkType(), StatsController.TYPE_CALLS, 1); - } else { - StatsController.getInstance(currentAccount).incrementReceivedItemsCount(getStatsNetworkType(), StatsController.TYPE_CALLS, 1); - } - } - } - if (newState == STATE_RECONNECTING) { - Utilities.globalQueue.postRunnable(() -> { - if (spPlayID != 0) { - soundPool.stop(spPlayID); - } - spPlayID = soundPool.play(groupCall != null ? spVoiceChatConnecting : spConnectingId, 1, 1, 0, -1, 1); - }); - } - dispatchStateChanged(newState); - } - - @Override - public void onSignalBarCountChanged(int newCount) { - AndroidUtilities.runOnUIThread(() -> { - signalBarCount = newCount; - for (int a = 0; a < stateListeners.size(); a++) { - StateListener l = stateListeners.get(a); - l.onSignalBarsCountChanged(newCount); - } - }); - } - - public boolean isBluetoothOn() { - final AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - return am.isBluetoothScoOn(); - } - - public boolean isBluetoothWillOn() { - return needSwitchToBluetoothAfterScoActivates; - } - - public boolean isHeadsetPlugged() { - return isHeadsetPlugged; - } - - public void onMediaStateUpdated(int audioState, int videoState) { - AndroidUtilities.runOnUIThread(() -> { - currentAudioState = audioState; - currentVideoState = videoState; - checkIsNear(); - - for (int a = 0; a < stateListeners.size(); a++) { - StateListener l = stateListeners.get(a); - l.onMediaStateUpdated(audioState, videoState); - } - }); - } - - protected void callEnded() { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("Call " + getCallID() + " ended"); - } - if (groupCall != null && (!playedConnectedSound || onDestroyRunnable != null)) { - needPlayEndSound = false; - } - AndroidUtilities.runOnUIThread(() -> dispatchStateChanged(STATE_ENDED)); - int delay = 700; - Utilities.globalQueue.postRunnable(() -> { - if (spPlayID != 0) { - soundPool.stop(spPlayID); - spPlayID = 0; - } - }); - - if (connectingSoundRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(connectingSoundRunnable); - connectingSoundRunnable = null; - } - if (needPlayEndSound) { - playingSound = true; - if (groupCall == null) { - Utilities.globalQueue.postRunnable(() -> soundPool.play(spEndId, 1, 1, 0, 0, 1)); - } else { - Utilities.globalQueue.postRunnable(() -> soundPool.play(spVoiceChatEndId, 1.0f, 1.0f, 0, 0, 1), 100); - delay = 500; - } - AndroidUtilities.runOnUIThread(afterSoundRunnable, delay); - } - if (timeoutRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(timeoutRunnable); - timeoutRunnable = null; - } - endConnectionServiceCall(needPlayEndSound ? delay : 0); - stopSelf(); - } - - protected void endConnectionServiceCall(long delay) { - if (USE_CONNECTION_SERVICE) { - Runnable r = () -> { - if (systemCallConnection != null) { - switch (callDiscardReason) { - case DISCARD_REASON_HANGUP: - systemCallConnection.setDisconnected(new DisconnectCause(isOutgoing ? DisconnectCause.LOCAL : DisconnectCause.REJECTED)); - break; - case DISCARD_REASON_DISCONNECT: - systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.ERROR)); - break; - case DISCARD_REASON_LINE_BUSY: - systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.BUSY)); - break; - case DISCARD_REASON_MISSED: - systemCallConnection.setDisconnected(new DisconnectCause(isOutgoing ? DisconnectCause.CANCELED : DisconnectCause.MISSED)); - break; - default: - systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE)); - break; - } - systemCallConnection.destroy(); - systemCallConnection = null; - } - }; - if (delay > 0) { - AndroidUtilities.runOnUIThread(r, delay); - } else { - r.run(); - } - } - } - - public boolean isOutgoing() { - return isOutgoing; - } - - public void handleNotificationAction(Intent intent) { - if ((getPackageName() + ".END_CALL").equals(intent.getAction())) { - stopForeground(true); - hangUp(); - } else if ((getPackageName() + ".DECLINE_CALL").equals(intent.getAction())) { - stopForeground(true); - declineIncomingCall(DISCARD_REASON_LINE_BUSY, null); - } else if ((getPackageName() + ".ANSWER_CALL").equals(intent.getAction())) { - acceptIncomingCallFromNotification(); - } - } - - private void acceptIncomingCallFromNotification() { - showNotification(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED || privateCall.video && checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) { - try { - PendingIntent.getActivity(VoIPBaseService.this, 0, new Intent(VoIPBaseService.this, VoIPPermissionActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0).send(); - } catch (Exception x) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Error starting permission activity", x); - } - } - return; - } - acceptIncomingCall(); - try { - PendingIntent.getActivity(VoIPBaseService.this, 0, new Intent(VoIPBaseService.this, getUIActivityClass()).setAction("voip"), 0).send(); - } catch (Exception x) { - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Error starting incall activity", x); - } - } - } - - public void updateOutputGainControlState() { - if (tgVoip != null) { - if (!USE_CONNECTION_SERVICE) { - final AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); - tgVoip.setAudioOutputGainControlEnabled(hasEarpiece() && !am.isSpeakerphoneOn() && !am.isBluetoothScoOn() && !isHeadsetPlugged); - tgVoip.setEchoCancellationStrength(isHeadsetPlugged || (hasEarpiece() && !am.isSpeakerphoneOn() && !am.isBluetoothScoOn() && !isHeadsetPlugged) ? 0 : 1); - } else { - final boolean isEarpiece = systemCallConnection.getCallAudioState().getRoute() == CallAudioState.ROUTE_EARPIECE; - tgVoip.setAudioOutputGainControlEnabled(isEarpiece); - tgVoip.setEchoCancellationStrength(isEarpiece ? 0 : 1); - } - } - } - - public int getAccount() { - return currentAccount; - } - - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.appDidLogout) { - callEnded(); - } - } - - public static boolean isAnyKindOfCallActive() { - if (VoIPService.getSharedInstance() != null) { - return VoIPService.getSharedInstance().getCallState() != VoIPService.STATE_WAITING_INCOMING; - } - return false; - } - - protected boolean isFinished() { - return currentState == STATE_ENDED || currentState == STATE_FAILED; - } - - protected boolean isRinging() { - return false; - } - - public int getCurrentAudioState() { - return currentAudioState; - } - - public int getCurrentVideoState() { - return currentVideoState; - } - - @TargetApi(Build.VERSION_CODES.O) - protected PhoneAccountHandle addAccountToTelecomManager() { - TelecomManager tm = (TelecomManager) getSystemService(TELECOM_SERVICE); - TLRPC.User self = UserConfig.getInstance(currentAccount).getCurrentUser(); - PhoneAccountHandle handle = new PhoneAccountHandle(new ComponentName(this, TelegramConnectionService.class), "" + self.id); - PhoneAccount account = new PhoneAccount.Builder(handle, ContactsController.formatName(self.first_name, self.last_name)) - .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) - .setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher)) - .setHighlightColor(0xff2ca5e0) - .addSupportedUriScheme("sip") - .build(); - tm.registerPhoneAccount(account); - return handle; - } - - private static boolean isDeviceCompatibleWithConnectionServiceAPI() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - return false; - } - // some non-Google devices don't implement the ConnectionService API correctly so, sadly, - // we'll have to whitelist only a handful of known-compatible devices for now - return false;/*"angler".equals(Build.PRODUCT) // Nexus 6P + protected int currentAccount = -1; + public static final int STATE_WAIT_INIT = Instance.STATE_WAIT_INIT; + public static final int STATE_WAIT_INIT_ACK = Instance.STATE_WAIT_INIT_ACK; + public static final int STATE_ESTABLISHED = Instance.STATE_ESTABLISHED; + public static final int STATE_FAILED = Instance.STATE_FAILED; + public static final int STATE_RECONNECTING = Instance.STATE_RECONNECTING; + public static final int STATE_CREATING = 6; + public static final int STATE_ENDED = 11; + public static final String ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG"; + + protected static final int ID_ONGOING_CALL_NOTIFICATION = 201; + protected static final int ID_INCOMING_CALL_NOTIFICATION = 202; + + public static final int DISCARD_REASON_HANGUP = 1; + public static final int DISCARD_REASON_DISCONNECT = 2; + public static final int DISCARD_REASON_MISSED = 3; + public static final int DISCARD_REASON_LINE_BUSY = 4; + + public static final int AUDIO_ROUTE_EARPIECE = 0; + public static final int AUDIO_ROUTE_SPEAKER = 1; + public static final int AUDIO_ROUTE_BLUETOOTH = 2; + + protected static final boolean USE_CONNECTION_SERVICE = isDeviceCompatibleWithConnectionServiceAPI(); + + protected static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; + protected static VoIPBaseService sharedInstance; + protected static Runnable setModeRunnable; + protected static final Object sync = new Object(); + protected NetworkInfo lastNetInfo; + protected int currentState = 0; + protected Notification ongoingCallNotification; + protected NativeInstance tgVoip; + protected boolean wasConnected; + + protected TLRPC.Chat chat; + + protected boolean isVideoAvailable; + protected boolean notificationsDisabled; + protected boolean switchingCamera; + protected boolean isFrontFaceCamera = true; + protected String lastError; + protected PowerManager.WakeLock proximityWakelock; + protected PowerManager.WakeLock cpuWakelock; + protected boolean isProximityNear; + protected boolean isHeadsetPlugged; + protected int previousAudioOutput; + protected ArrayList stateListeners = new ArrayList<>(); + protected MediaPlayer ringtonePlayer; + protected Vibrator vibrator; + protected SoundPool soundPool; + protected int spRingbackID; + protected int spFailedID; + protected int spEndId; + protected int spVoiceChatEndId; + protected int spVoiceChatStartId; + protected int spVoiceChatConnecting; + protected int spBusyId; + protected int spConnectingId; + protected int spPlayID; + protected boolean needPlayEndSound; + protected boolean hasAudioFocus; + protected boolean micMute; + protected boolean unmutedByHold; + protected BluetoothAdapter btAdapter; + protected Instance.TrafficStats prevTrafficStats; + protected boolean isBtHeadsetConnected; + protected boolean screenOn; + + private Runnable updateNotificationRunnable; + + protected Runnable onDestroyRunnable; + + protected boolean playedConnectedSound; + + protected int videoState = Instance.VIDEO_STATE_INACTIVE; + + public TLRPC.PhoneCall privateCall; + public ChatObject.Call groupCall; + + protected int mySource; + protected boolean createGroupCall; + + protected long callStartTime; + protected boolean playingSound; + protected boolean isOutgoing; + public boolean videoCall; + protected long videoCapturer; + protected Runnable timeoutRunnable; + + private Boolean mHasEarpiece; + private boolean wasEstablished; + protected int signalBarCount; + protected int currentAudioState = Instance.AUDIO_STATE_ACTIVE; + protected int currentVideoState = Instance.VIDEO_STATE_INACTIVE; + protected boolean audioConfigured; + protected int audioRouteToSet = AUDIO_ROUTE_BLUETOOTH; + protected boolean speakerphoneStateToSet; + protected CallConnection systemCallConnection; + protected int callDiscardReason; + protected boolean bluetoothScoActive; + protected boolean needSwitchToBluetoothAfterScoActivates; + protected boolean didDeleteConnectionServiceContact; + protected Runnable connectingSoundRunnable; + + private String currentBluetoothDeviceName; + + public final SharedUIParams sharedUIParams = new SharedUIParams(); + + protected Runnable afterSoundRunnable = new Runnable() { + @Override + public void run() { + + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + am.abandonAudioFocus(VoIPBaseService.this); + am.unregisterMediaButtonEventReceiver(new ComponentName(VoIPBaseService.this, VoIPMediaButtonReceiver.class)); + if (!USE_CONNECTION_SERVICE && sharedInstance == null) { + if (isBtHeadsetConnected) { + am.stopBluetoothSco(); + am.setBluetoothScoOn(false); + bluetoothScoActive = false; + } + am.setSpeakerphoneOn(false); + } + + Utilities.globalQueue.postRunnable(() -> soundPool.release()); + Utilities.globalQueue.postRunnable(setModeRunnable = () -> { + synchronized (sync) { + if (setModeRunnable == null) { + return; + } + setModeRunnable = null; + } + try { + am.setMode(AudioManager.MODE_NORMAL); + } catch (SecurityException x) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Error setting audio more to normal", x); + } + } + }); + } + }; + + boolean fetchingBluetoothDeviceName; + private BluetoothProfile.ServiceListener serviceListener = new BluetoothProfile.ServiceListener() { + @Override + public void onServiceDisconnected(int profile) { + + } + + @Override + public void onServiceConnected(int profile, BluetoothProfile proxy) { + for (BluetoothDevice device : proxy.getConnectedDevices()) { + if (proxy.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) { + continue; + } + currentBluetoothDeviceName = device.getName(); + break; + } + BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy); + fetchingBluetoothDeviceName = false; + } + }; + + protected BroadcastReceiver receiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_HEADSET_PLUG.equals(intent.getAction())) { + isHeadsetPlugged = intent.getIntExtra("state", 0) == 1; + if (isHeadsetPlugged && proximityWakelock != null && proximityWakelock.isHeld()) { + proximityWakelock.release(); + } + if (isHeadsetPlugged) { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (am.isSpeakerphoneOn()) { + previousAudioOutput = 0; + } else if (am.isBluetoothScoOn()) { + previousAudioOutput = 2; + } else { + previousAudioOutput = 1; + } + setAudioOutput(1); + } else { + if (previousAudioOutput >= 0) { + setAudioOutput(previousAudioOutput); + previousAudioOutput = -1; + } + } + isProximityNear = false; + updateOutputGainControlState(); + } else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { + updateNetworkType(); + } else if (BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("bt headset state = " + intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0)); + } + updateBluetoothHeadsetState(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED) == BluetoothProfile.STATE_CONNECTED); + } else if (AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED.equals(intent.getAction())) { + int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, AudioManager.SCO_AUDIO_STATE_DISCONNECTED); + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Bluetooth SCO state updated: " + state); + } + if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED && isBtHeadsetConnected) { + if (!btAdapter.isEnabled() || btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET) != BluetoothProfile.STATE_CONNECTED) { + updateBluetoothHeadsetState(false); + return; + } + } + bluetoothScoActive = state == AudioManager.SCO_AUDIO_STATE_CONNECTED; + if (bluetoothScoActive) { + fetchBluetoothDeviceName(); + if (needSwitchToBluetoothAfterScoActivates) { + needSwitchToBluetoothAfterScoActivates = false; + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + am.setSpeakerphoneOn(false); + am.setBluetoothScoOn(true); + } + } + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent.getAction())) { + String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); + if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) { + hangUp(); + } + } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { + screenOn = true; + for (int i = 0; i < stateListeners.size(); i++) { + stateListeners.get(i).onScreenOnChange(screenOn); + } + } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { + screenOn = false; + for (int i = 0; i < stateListeners.size(); i++) { + stateListeners.get(i).onScreenOnChange(screenOn); + } + } + } + }; + + public boolean hasEarpiece() { + if (USE_CONNECTION_SERVICE) { + if (systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { + int routeMask = systemCallConnection.getCallAudioState().getSupportedRouteMask(); + return (routeMask & (CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_WIRED_HEADSET)) != 0; + } + } + if (((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getPhoneType() != TelephonyManager.PHONE_TYPE_NONE) { + return true; + } + if (mHasEarpiece != null) { + return mHasEarpiece; + } + + // not calculated yet, do it now + try { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + Method method = AudioManager.class.getMethod("getDevicesForStream", Integer.TYPE); + Field field = AudioManager.class.getField("DEVICE_OUT_EARPIECE"); + int earpieceFlag = field.getInt(null); + int bitmaskResult = (int) method.invoke(am, AudioManager.STREAM_VOICE_CALL); + + // check if masked by the earpiece flag + if ((bitmaskResult & earpieceFlag) == earpieceFlag) { + mHasEarpiece = Boolean.TRUE; + } else { + mHasEarpiece = Boolean.FALSE; + } + } catch (Throwable error) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Error while checking earpiece! ", error); + } + mHasEarpiece = Boolean.TRUE; + } + + return mHasEarpiece; + } + + protected int getStatsNetworkType() { + int netType = StatsController.TYPE_WIFI; + if (lastNetInfo != null) { + if (lastNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) { + netType = lastNetInfo.isRoaming() ? StatsController.TYPE_ROAMING : StatsController.TYPE_MOBILE; + } + } + return netType; + } + + protected void setSwitchingCamera(boolean switching, boolean isFrontFace) { + switchingCamera = switching; + if (!switching) { + isFrontFaceCamera = isFrontFace; + for (int a = 0; a < stateListeners.size(); a++) { + StateListener l = stateListeners.get(a); + l.onCameraSwitch(isFrontFaceCamera); + } + } + } + + public void registerStateListener(StateListener l) { + if (stateListeners.contains(l)) { + return; + } + stateListeners.add(l); + if (currentState != 0) { + l.onStateChanged(currentState); + } + if (signalBarCount != 0) { + l.onSignalBarsCountChanged(signalBarCount); + } + } + + public void unregisterStateListener(StateListener l) { + stateListeners.remove(l); + } + + public void setMicMute(boolean mute, boolean hold, boolean send) { + if (micMute == mute) { + return; + } + micMute = mute; + if (groupCall != null) { + if (!send) { + TLRPC.TL_groupCallParticipant self = groupCall.participants.get(UserConfig.getInstance(currentAccount).getClientUserId()); + if (self != null && self.muted && !self.can_self_unmute) { + send = true; + } + } + if (send) { + editCallMember(UserConfig.getInstance(currentAccount).getCurrentUser(), mute, -1); + Utilities.globalQueue.postRunnable(updateNotificationRunnable = () -> { + if (updateNotificationRunnable == null) { + return; + } + updateNotificationRunnable = null; + showNotification(chat.title, getRoundAvatarBitmap(chat)); + }); + } + } + unmutedByHold = !micMute && hold; + if (tgVoip != null) { + tgVoip.setMuteMicrophone(mute); + } + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } + + public void editCallMember(TLObject object, boolean mute, int volume) { + if (groupCall == null) { + return; + } + TLRPC.TL_phone_editGroupCallMember req = new TLRPC.TL_phone_editGroupCallMember(); + req.call = groupCall.getInputGroupCall(); + if (object instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) object; + if (UserObject.isUserSelf(user)) { + req.user_id = new TLRPC.TL_inputUserSelf(); + } else { + req.user_id = new TLRPC.TL_inputUser(); + req.user_id.user_id = user.id; + req.user_id.access_hash = user.access_hash; + } + } + req.muted = mute; + if (volume >= 0) { + req.volume = volume; + req.flags |= 2; + } + int account = currentAccount; + AccountInstance.getInstance(account).getConnectionsManager().sendRequest(req, (response, error) -> { + if (response != null) { + AccountInstance.getInstance(account).getMessagesController().processUpdates((TLRPC.Updates) response, false); + } + }); + } + + public boolean isMicMute() { + return micMute; + } + + public void toggleSpeakerphoneOrShowRouteSheet(Context context, boolean fromOverlayWindow) { + if (isBluetoothHeadsetConnected() && hasEarpiece()) { + BottomBuilder builder = new BottomBuilder(context); + builder.addTitle(LocaleController.getString("VoipOutputDevices", R.string.VoipOutputDevices), true); + builder.addItems(new String[]{ + LocaleController.getString("VoipAudioRoutingSpeaker", R.string.VoipAudioRoutingSpeaker), + isHeadsetPlugged ? LocaleController.getString("VoipAudioRoutingHeadset", R.string.VoipAudioRoutingHeadset) : LocaleController.getString("VoipAudioRoutingEarpiece", R.string.VoipAudioRoutingEarpiece), + currentBluetoothDeviceName != null ? currentBluetoothDeviceName : LocaleController.getString("VoipAudioRoutingBluetooth", R.string.VoipAudioRoutingBluetooth) + }, new int[]{ + R.drawable.calls_menu_speaker, + isHeadsetPlugged ? R.drawable.calls_menu_headset : R.drawable.calls_menu_phone, + R.drawable.calls_menu_bluetooth + }, (which, text, cell) -> { + if (getSharedInstance() != null) setAudioOutput(which); + return Unit.INSTANCE; + }); + + BottomSheet bottomSheet = builder.create(); + if (fromOverlayWindow) { + if (Build.VERSION.SDK_INT >= 26) { + bottomSheet.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); + } else { + bottomSheet.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + } + } + builder.show(); + return; + } + if (USE_CONNECTION_SERVICE && systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { + if (hasEarpiece()) { + systemCallConnection.setAudioRoute(systemCallConnection.getCallAudioState().getRoute() == CallAudioState.ROUTE_SPEAKER ? CallAudioState.ROUTE_WIRED_OR_EARPIECE : CallAudioState.ROUTE_SPEAKER); + } else { + systemCallConnection.setAudioRoute(systemCallConnection.getCallAudioState().getRoute() == CallAudioState.ROUTE_BLUETOOTH ? CallAudioState.ROUTE_WIRED_OR_EARPIECE : CallAudioState.ROUTE_BLUETOOTH); + } + } else if (audioConfigured && !USE_CONNECTION_SERVICE) { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (hasEarpiece()) { + am.setSpeakerphoneOn(!am.isSpeakerphoneOn()); + } else { + am.setBluetoothScoOn(!am.isBluetoothScoOn()); + } + updateOutputGainControlState(); + } else { + speakerphoneStateToSet = !speakerphoneStateToSet; + } + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } + + protected void setAudioOutput(int which) { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (USE_CONNECTION_SERVICE && systemCallConnection != null) { + switch (which) { + case 2: + systemCallConnection.setAudioRoute(CallAudioState.ROUTE_BLUETOOTH); + break; + case 1: + systemCallConnection.setAudioRoute(CallAudioState.ROUTE_WIRED_OR_EARPIECE); + break; + case 0: + systemCallConnection.setAudioRoute(CallAudioState.ROUTE_SPEAKER); + break; + } + } else if (audioConfigured && !USE_CONNECTION_SERVICE) { + switch (which) { + case 2: + if (!bluetoothScoActive) { + needSwitchToBluetoothAfterScoActivates = true; + try { + am.startBluetoothSco(); + } catch (Throwable ignore) { + + } + } else { + am.setBluetoothScoOn(true); + am.setSpeakerphoneOn(false); + } + break; + case 1: + if (bluetoothScoActive) { + am.stopBluetoothSco(); + bluetoothScoActive = false; + } + am.setSpeakerphoneOn(false); + am.setBluetoothScoOn(false); + break; + case 0: + if (bluetoothScoActive) { + am.stopBluetoothSco(); + bluetoothScoActive = false; + } + am.setBluetoothScoOn(false); + am.setSpeakerphoneOn(true); + break; + } + updateOutputGainControlState(); + } else { + switch (which) { + case 2: + audioRouteToSet = AUDIO_ROUTE_BLUETOOTH; + speakerphoneStateToSet = false; + break; + case 1: + audioRouteToSet = AUDIO_ROUTE_EARPIECE; + speakerphoneStateToSet = false; + break; + case 0: + audioRouteToSet = AUDIO_ROUTE_SPEAKER; + speakerphoneStateToSet = true; + break; + } + } + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } + + public boolean isSpeakerphoneOn() { + if (USE_CONNECTION_SERVICE && systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { + int route = systemCallConnection.getCallAudioState().getRoute(); + return hasEarpiece() ? route == CallAudioState.ROUTE_SPEAKER : route == CallAudioState.ROUTE_BLUETOOTH; + } else if (audioConfigured && !USE_CONNECTION_SERVICE) { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + return hasEarpiece() ? am.isSpeakerphoneOn() : am.isBluetoothScoOn(); + } + return speakerphoneStateToSet; + } + + public int getCurrentAudioRoute() { + if (USE_CONNECTION_SERVICE) { + if (systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { + switch (systemCallConnection.getCallAudioState().getRoute()) { + case CallAudioState.ROUTE_BLUETOOTH: + return AUDIO_ROUTE_BLUETOOTH; + case CallAudioState.ROUTE_EARPIECE: + case CallAudioState.ROUTE_WIRED_HEADSET: + return AUDIO_ROUTE_EARPIECE; + case CallAudioState.ROUTE_SPEAKER: + return AUDIO_ROUTE_SPEAKER; + } + } + return audioRouteToSet; + } + if (audioConfigured) { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (am.isBluetoothScoOn()) { + return AUDIO_ROUTE_BLUETOOTH; + } else if (am.isSpeakerphoneOn()) { + return AUDIO_ROUTE_SPEAKER; + } else { + return AUDIO_ROUTE_EARPIECE; + } + } + return audioRouteToSet; + } + + public String getDebugString() { + return tgVoip != null ? tgVoip.getDebugInfo() : ""; + } + + public long getCallDuration() { + if (callStartTime == 0) { + return 0; + } + return SystemClock.elapsedRealtime() - callStartTime; + } + + public static VoIPBaseService getSharedInstance() { + return sharedInstance; + } + + public void stopRinging() { + if (ringtonePlayer != null) { + ringtonePlayer.stop(); + ringtonePlayer.release(); + ringtonePlayer = null; + } + if (vibrator != null) { + vibrator.cancel(); + vibrator = null; + } + } + + protected void showNotification(String name, Bitmap photo) { + Intent intent = new Intent(this, LaunchActivity.class).setAction(groupCall != null ? "voip_chat" : "voip"); + if (groupCall != null) { + intent.putExtra("currentAccount", currentAccount); + } + Notification.Builder builder = new Notification.Builder(this) + .setContentTitle(groupCall != null ? LocaleController.getString("VoipVoiceChat", R.string.VoipVoiceChat) : LocaleController.getString("VoipOutgoingCall", R.string.VoipOutgoingCall)) + .setContentText(name) + .setContentIntent(PendingIntent.getActivity(this, 50, intent, 0)); + if (groupCall != null) { + builder.setSmallIcon(isMicMute() ? R.drawable.voicechat_muted : R.drawable.voicechat_active); + } else { + builder.setSmallIcon(R.drawable.notification); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + Intent endIntent = new Intent(this, VoIPActionsReceiver.class); + endIntent.setAction(getPackageName() + ".END_CALL"); + builder.addAction(R.drawable.ic_call_end_white_24dp, groupCall != null ? LocaleController.getString("VoipGroupLeaveAlertTitle", R.string.VoipGroupLeaveAlertTitle) : LocaleController.getString("VoipEndCall", R.string.VoipEndCall), PendingIntent.getBroadcast(this, 0, endIntent, PendingIntent.FLAG_UPDATE_CURRENT)); + builder.setPriority(Notification.PRIORITY_MAX); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + builder.setShowWhen(false); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + builder.setColor(0xff282e31); + builder.setColorized(true); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + builder.setColor(0xff2ca5e0); + } + if (Build.VERSION.SDK_INT >= 26) { + NotificationsController.checkOtherNotificationsChannel(); + builder.setChannelId(NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); + } + if (photo != null) { + builder.setLargeIcon(photo); + } + ongoingCallNotification = builder.getNotification(); + startForeground(ID_ONGOING_CALL_NOTIFICATION, ongoingCallNotification); + } + + protected void startRingtoneAndVibration(int chatID) { + SharedPreferences prefs = MessagesController.getNotificationsSettings(currentAccount); + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + boolean needRing = am.getRingerMode() != AudioManager.RINGER_MODE_SILENT; + if (needRing) { + ringtonePlayer = new MediaPlayer(); + ringtonePlayer.setOnPreparedListener(mediaPlayer -> ringtonePlayer.start()); + ringtonePlayer.setLooping(true); + if (isHeadsetPlugged) { + ringtonePlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); + } else { + ringtonePlayer.setAudioStreamType(AudioManager.STREAM_RING); + if (!USE_CONNECTION_SERVICE) { + am.requestAudioFocus(this, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN); + } + } + try { + String notificationUri; + if (prefs.getBoolean("custom_" + chatID, false)) { + notificationUri = prefs.getString("ringtone_path_" + chatID, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString()); + } else { + notificationUri = prefs.getString("CallsRingtonePath", RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE).toString()); + } + ringtonePlayer.setDataSource(this, Uri.parse(notificationUri)); + ringtonePlayer.prepareAsync(); + } catch (Exception e) { + FileLog.e(e); + if (ringtonePlayer != null) { + ringtonePlayer.release(); + ringtonePlayer = null; + } + } + int vibrate; + if (prefs.getBoolean("custom_" + chatID, false)) { + vibrate = prefs.getInt("calls_vibrate_" + chatID, 0); + } else { + vibrate = prefs.getInt("vibrate_calls", 0); + } + if ((vibrate != 2 && vibrate != 4 && (am.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE || am.getRingerMode() == AudioManager.RINGER_MODE_NORMAL)) || (vibrate == 4 && am.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE)) { + vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); + long duration = 700; + if (vibrate == 1) { + duration /= 2; + } else if (vibrate == 3) { + duration *= 2; + } + vibrator.vibrate(new long[]{0, duration, 500}, 0); + } + } + } + + @Override + public void onDestroy() { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("=============== VoIPService STOPPING ==============="); + } + stopForeground(true); + stopRinging(); + if (ApplicationLoader.mainInterfacePaused || !ApplicationLoader.isScreenOn) { + MessagesController.getInstance(currentAccount).ignoreSetOnline = false; + } + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.appDidLogout); + SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); + Sensor proximity = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); + if (proximity != null) { + sm.unregisterListener(this); + } + if (proximityWakelock != null && proximityWakelock.isHeld()) { + proximityWakelock.release(); + } + if (updateNotificationRunnable != null) { + Utilities.globalQueue.cancelRunnable(updateNotificationRunnable); + updateNotificationRunnable = null; + } + unregisterReceiver(receiver); + if (timeoutRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(timeoutRunnable); + timeoutRunnable = null; + } + super.onDestroy(); + sharedInstance = null; + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didEndCall)); + if (tgVoip != null) { + StatsController.getInstance(currentAccount).incrementTotalCallsTime(getStatsNetworkType(), (int) (getCallDuration() / 1000) % 5); + onTgVoipPreStop(); + if (tgVoip.isGroup()) { + NativeInstance instance = tgVoip; + Utilities.globalQueue.postRunnable(instance::stopGroup); + } else { + Instance.FinalState state = tgVoip.stop(); + updateTrafficStats(state.trafficStats); + onTgVoipStop(state); + } + prevTrafficStats = null; + callStartTime = 0; + tgVoip = null; + Instance.destroyInstance(); + } + if (videoCapturer != 0) { + NativeInstance.destroyVideoCapturer(videoCapturer); + videoCapturer = 0; + } + cpuWakelock.release(); + if (!playingSound) { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (!USE_CONNECTION_SERVICE) { + if (isBtHeadsetConnected) { + am.stopBluetoothSco(); + am.setBluetoothScoOn(false); + am.setSpeakerphoneOn(false); + bluetoothScoActive = false; + } + if (onDestroyRunnable == null) { + Utilities.globalQueue.postRunnable(setModeRunnable = () -> { + synchronized (sync) { + if (setModeRunnable == null) { + return; + } + setModeRunnable = null; + } + try { + am.setMode(AudioManager.MODE_NORMAL); + } catch (SecurityException x) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Error setting audio more to normal", x); + } + } + }); + } + am.abandonAudioFocus(this); + } + am.unregisterMediaButtonEventReceiver(new ComponentName(this, VoIPMediaButtonReceiver.class)); + if (hasAudioFocus) { + am.abandonAudioFocus(this); + } + Utilities.globalQueue.postRunnable(() -> soundPool.release()); + } + + if (USE_CONNECTION_SERVICE) { + if (!didDeleteConnectionServiceContact) { + ContactsController.getInstance(currentAccount).deleteConnectionServiceContact(); + } + if (systemCallConnection != null && !playingSound) { + systemCallConnection.destroy(); + } + } + + ConnectionsManager.getInstance(currentAccount).setAppPaused(true, false); + VoIPHelper.lastCallTime = SystemClock.elapsedRealtime(); + } + + public abstract long getCallID(); + + public abstract void hangUp(); + + public abstract void hangUp(Runnable onDone); + + public abstract void acceptIncomingCall(); + + public abstract void declineIncomingCall(int reason, Runnable onDone); + + public abstract void declineIncomingCall(); + + protected abstract Class getUIActivityClass(); + + public abstract CallConnection getConnectionAndStartCall(); + + protected abstract void startRinging(); + + public abstract void startRingtoneAndVibration(); + + protected abstract void updateServerConfig(); + + protected abstract void showNotification(); + + protected void onTgVoipPreStop() { + + } + + protected void onTgVoipStop(Instance.FinalState finalState) { + + } + + protected void initializeAccountRelatedThings() { + updateServerConfig(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.appDidLogout); + ConnectionsManager.getInstance(currentAccount).setAppPaused(false, false); + } + + @SuppressLint("InvalidWakeLockTag") + @Override + public void onCreate() { + super.onCreate(); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("=============== VoIPService STARTING ==============="); + } + try { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER) != null) { + int outFramesPerBuffer = Integer.parseInt(am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER)); + Instance.setBufferSize(outFramesPerBuffer); + } else { + Instance.setBufferSize(AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT) / 2); + } + + cpuWakelock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "telegram-voip"); + cpuWakelock.acquire(); + + btAdapter = am.isBluetoothScoAvailableOffCall() ? BluetoothAdapter.getDefaultAdapter() : null; + + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + if (!USE_CONNECTION_SERVICE) { + filter.addAction(ACTION_HEADSET_PLUG); + if (btAdapter != null) { + filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); + } + filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); + filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_SCREEN_OFF); + } + registerReceiver(receiver, filter); + fetchBluetoothDeviceName(); + Utilities.globalQueue.postRunnable(() -> { + soundPool = new SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0); + spConnectingId = soundPool.load(this, R.raw.voip_connecting, 1); + spRingbackID = soundPool.load(this, R.raw.voip_ringback, 1); + spFailedID = soundPool.load(this, R.raw.voip_failed, 1); + spEndId = soundPool.load(this, R.raw.voip_end, 1); + spBusyId = soundPool.load(this, R.raw.voip_busy, 1); + spVoiceChatEndId = soundPool.load(this, R.raw.voicechat_leave, 1); + spVoiceChatStartId = soundPool.load(this, R.raw.voicechat_join, 1); + spVoiceChatConnecting = soundPool.load(this, R.raw.voicechat_connecting, 1); + }); + + am.registerMediaButtonEventReceiver(new ComponentName(this, VoIPMediaButtonReceiver.class)); + + if (!USE_CONNECTION_SERVICE && btAdapter != null && btAdapter.isEnabled()) { + try { + MediaRouter mr = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE); + if (Build.VERSION.SDK_INT < 24) { + int headsetState = btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET); + updateBluetoothHeadsetState(headsetState == BluetoothProfile.STATE_CONNECTED); + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } else { + MediaRouter.RouteInfo ri = mr.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO); + if (ri.getDeviceType() == MediaRouter.RouteInfo.DEVICE_TYPE_BLUETOOTH) { + int headsetState = btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET); + updateBluetoothHeadsetState(headsetState == BluetoothProfile.STATE_CONNECTED); + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } else { + updateBluetoothHeadsetState(false); + } + } + } catch (Throwable e) { + FileLog.e(e); + } + } + } catch (Exception x) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("error initializing voip controller", x); + } + callFailed(); + } + } + + protected void dispatchStateChanged(int state) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("== Call " + getCallID() + " state changed to " + state + " =="); + } + currentState = state; + if (USE_CONNECTION_SERVICE && state == STATE_ESTABLISHED /*&& !wasEstablished*/ && systemCallConnection != null) { + systemCallConnection.setActive(); + } + for (int a = 0; a < stateListeners.size(); a++) { + StateListener l = stateListeners.get(a); + l.onStateChanged(state); + } + } + + protected void updateTrafficStats(Instance.TrafficStats trafficStats) { + if (trafficStats == null) { + trafficStats = tgVoip.getTrafficStats(); + } + final long wifiSentDiff = trafficStats.bytesSentWifi - (prevTrafficStats != null ? prevTrafficStats.bytesSentWifi : 0); + final long wifiRecvdDiff = trafficStats.bytesReceivedWifi - (prevTrafficStats != null ? prevTrafficStats.bytesReceivedWifi : 0); + final long mobileSentDiff = trafficStats.bytesSentMobile - (prevTrafficStats != null ? prevTrafficStats.bytesSentMobile : 0); + final long mobileRecvdDiff = trafficStats.bytesReceivedMobile - (prevTrafficStats != null ? prevTrafficStats.bytesReceivedMobile : 0); + prevTrafficStats = trafficStats; + if (wifiSentDiff > 0) { + StatsController.getInstance(currentAccount).incrementSentBytesCount(StatsController.TYPE_WIFI, StatsController.TYPE_CALLS, wifiSentDiff); + } + if (wifiRecvdDiff > 0) { + StatsController.getInstance(currentAccount).incrementReceivedBytesCount(StatsController.TYPE_WIFI, StatsController.TYPE_CALLS, wifiRecvdDiff); + } + if (mobileSentDiff > 0) { + StatsController.getInstance(currentAccount).incrementSentBytesCount(lastNetInfo != null && lastNetInfo.isRoaming() ? StatsController.TYPE_ROAMING : StatsController.TYPE_MOBILE, StatsController.TYPE_CALLS, mobileSentDiff); + } + if (mobileRecvdDiff > 0) { + StatsController.getInstance(currentAccount).incrementReceivedBytesCount(lastNetInfo != null && lastNetInfo.isRoaming() ? StatsController.TYPE_ROAMING : StatsController.TYPE_MOBILE, StatsController.TYPE_CALLS, mobileRecvdDiff); + } + } + + @SuppressLint("InvalidWakeLockTag") + protected void configureDeviceForCall() { + needPlayEndSound = true; + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (!USE_CONNECTION_SERVICE) { + Utilities.globalQueue.postRunnable(() -> { + try { + am.setMode(AudioManager.MODE_IN_COMMUNICATION); + } catch (Exception e) { + FileLog.e(e); + } + }); + am.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN); + if (isBluetoothHeadsetConnected() && hasEarpiece()) { + switch (audioRouteToSet) { + case AUDIO_ROUTE_BLUETOOTH: + if (!bluetoothScoActive) { + needSwitchToBluetoothAfterScoActivates = true; + try { + am.startBluetoothSco(); + } catch (Throwable ignore) { + + } + } else { + am.setBluetoothScoOn(true); + am.setSpeakerphoneOn(false); + } + break; + case AUDIO_ROUTE_EARPIECE: + am.setBluetoothScoOn(false); + am.setSpeakerphoneOn(false); + break; + case AUDIO_ROUTE_SPEAKER: + am.setBluetoothScoOn(false); + am.setSpeakerphoneOn(true); + break; + } + } else if (isBluetoothHeadsetConnected()) { + am.setBluetoothScoOn(speakerphoneStateToSet); + } else { + am.setSpeakerphoneOn(speakerphoneStateToSet); + } + } + updateOutputGainControlState(); + audioConfigured = true; + + SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE); + Sensor proximity = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); + try { + if (proximity != null) { + proximityWakelock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, "telegram-voip-prx"); + sm.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL); + } + } catch (Exception x) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Error initializing proximity sensor", x); + } + } + } + + private void fetchBluetoothDeviceName() { + if (fetchingBluetoothDeviceName) { + return; + } + try { + currentBluetoothDeviceName = null; + fetchingBluetoothDeviceName = true; + BluetoothAdapter.getDefaultAdapter().getProfileProxy(this, serviceListener, BluetoothProfile.HEADSET); + } catch (Throwable e) { + FileLog.e(e); + } + } + + @SuppressLint("NewApi") + @Override + public void onSensorChanged(SensorEvent event) { + if (unmutedByHold || currentVideoState == Instance.VIDEO_STATE_ACTIVE || videoState == Instance.VIDEO_STATE_ACTIVE) { + return; + } + if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) { + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (isHeadsetPlugged || am.isSpeakerphoneOn() || (isBluetoothHeadsetConnected() && am.isBluetoothScoOn())) { + return; + } + boolean newIsNear = event.values[0] < Math.min(event.sensor.getMaximumRange(), 3); + checkIsNear(newIsNear); + } + } + + protected void checkIsNear() { + if (currentVideoState == Instance.VIDEO_STATE_ACTIVE || videoState == Instance.VIDEO_STATE_ACTIVE) { + checkIsNear(false); + } + } + + private void checkIsNear(boolean newIsNear) { + if (newIsNear != isProximityNear) { + if (NekoConfig.disableProximityEvents) return; + if (BuildVars.LOGS_ENABLED) { + FileLog.d("proximity " + newIsNear); + } + isProximityNear = newIsNear; + try { + if (isProximityNear) { + proximityWakelock.acquire(); + } else { + proximityWakelock.release(1); // this is non-public API before L + } + } catch (Exception x) { + FileLog.e(x); + } + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + + } + + public boolean isBluetoothHeadsetConnected() { + if (USE_CONNECTION_SERVICE && systemCallConnection != null && systemCallConnection.getCallAudioState() != null) { + return (systemCallConnection.getCallAudioState().getSupportedRouteMask() & CallAudioState.ROUTE_BLUETOOTH) != 0; + } + return isBtHeadsetConnected; + } + + public void onAudioFocusChange(int focusChange) { + if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { + hasAudioFocus = true; + } else { + hasAudioFocus = false; + } + } + + protected void updateBluetoothHeadsetState(boolean connected) { + if (connected == isBtHeadsetConnected) { + return; + } + if (BuildVars.LOGS_ENABLED) { + FileLog.d("updateBluetoothHeadsetState: " + connected); + } + isBtHeadsetConnected = connected; + final AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + if (connected && !isRinging() && currentState != 0) { + if (bluetoothScoActive) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("SCO already active, setting audio routing"); + } + am.setSpeakerphoneOn(false); + am.setBluetoothScoOn(true); + } else { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("startBluetoothSco"); + } + needSwitchToBluetoothAfterScoActivates = true; + // some devices ignore startBluetoothSco when called immediately after the headset is connected, so delay it + AndroidUtilities.runOnUIThread(() -> { + try { + am.startBluetoothSco(); + } catch (Throwable ignore) { + + } + }, 500); + } + } else { + bluetoothScoActive = false; + } + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } + + public String getLastError() { + return lastError; + } + + public int getCallState() { + return currentState; + } + + protected void updateNetworkType() { + if (tgVoip != null) { + if (tgVoip.isGroup()) { + + } else { + tgVoip.setNetworkType(getNetworkType()); + } + } else { + lastNetInfo = getActiveNetworkInfo(); + } + } + + protected int getNetworkType() { + final NetworkInfo info = lastNetInfo = getActiveNetworkInfo(); + int type = Instance.NET_TYPE_UNKNOWN; + if (info != null) { + switch (info.getType()) { + case ConnectivityManager.TYPE_MOBILE: + switch (info.getSubtype()) { + case TelephonyManager.NETWORK_TYPE_GPRS: + type = Instance.NET_TYPE_GPRS; + break; + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_1xRTT: + type = Instance.NET_TYPE_EDGE; + break; + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_EVDO_0: + type = Instance.NET_TYPE_3G; + break; + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + type = Instance.NET_TYPE_HSPA; + break; + case TelephonyManager.NETWORK_TYPE_LTE: + type = Instance.NET_TYPE_LTE; + break; + default: + type = Instance.NET_TYPE_OTHER_MOBILE; + break; + } + break; + case ConnectivityManager.TYPE_WIFI: + type = Instance.NET_TYPE_WIFI; + break; + case ConnectivityManager.TYPE_ETHERNET: + type = Instance.NET_TYPE_ETHERNET; + break; + } + } + return type; + } + + protected NetworkInfo getActiveNetworkInfo() { + return ((ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); + } + + protected void callFailed() { + callFailed(tgVoip != null ? tgVoip.getLastError() : Instance.ERROR_UNKNOWN); + } + + protected Bitmap getRoundAvatarBitmap(TLObject userOrChat) { + Bitmap bitmap = null; + if (userOrChat instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) userOrChat; + if (user.photo != null && user.photo.photo_small != null) { + BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(user.photo.photo_small, null, "50_50"); + if (img != null) { + bitmap = img.getBitmap().copy(Bitmap.Config.ARGB_8888, true); + } else { + try { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inMutable = true; + bitmap = BitmapFactory.decodeFile(FileLoader.getPathToAttach(user.photo.photo_small, true).toString(), opts); + } catch (Throwable e) { + FileLog.e(e); + } + } + } + } else { + TLRPC.Chat chat = (TLRPC.Chat) userOrChat; + if (chat.photo != null && chat.photo.photo_small != null) { + BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(chat.photo.photo_small, null, "50_50"); + if (img != null) { + bitmap = img.getBitmap().copy(Bitmap.Config.ARGB_8888, true); + } else { + try { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inMutable = true; + bitmap = BitmapFactory.decodeFile(FileLoader.getPathToAttach(chat.photo.photo_small, true).toString(), opts); + } catch (Throwable e) { + FileLog.e(e); + } + } + } + } + if (bitmap == null) { + Theme.createDialogsResources(this); + AvatarDrawable placeholder; + if (userOrChat instanceof TLRPC.User) { + placeholder = new AvatarDrawable((TLRPC.User) userOrChat); + } else { + placeholder = new AvatarDrawable((TLRPC.Chat) userOrChat); + } + bitmap = Bitmap.createBitmap(AndroidUtilities.dp(42), AndroidUtilities.dp(42), Bitmap.Config.ARGB_8888); + placeholder.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight()); + placeholder.draw(new Canvas(bitmap)); + } + + Canvas canvas = new Canvas(bitmap); + Path circlePath = new Path(); + circlePath.addCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, Path.Direction.CW); + circlePath.toggleInverseFillType(); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + canvas.drawPath(circlePath, paint); + return bitmap; + } + + protected void showIncomingNotification(String name, CharSequence subText, TLObject userOrChat, boolean video, int additionalMemberCount) { + Intent intent = new Intent(this, LaunchActivity.class); + intent.setAction("voip"); + Notification.Builder builder = new Notification.Builder(this) + .setContentTitle(video ? LocaleController.getString("VoipInVideoCallBranding", R.string.VoipInVideoCallBranding) : LocaleController.getString("VoipInCallBranding", R.string.VoipInCallBranding)) + .setContentText(name) + .setSmallIcon(R.drawable.notification) + .setSubText(subText) + .setContentIntent(PendingIntent.getActivity(this, 0, intent, 0)); + Uri soundProviderUri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".call_sound_provider/start_ringing"); + if (Build.VERSION.SDK_INT >= 26) { + SharedPreferences nprefs = MessagesController.getGlobalNotificationsSettings(); + int chanIndex = nprefs.getInt("calls_notification_channel", 0); + NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + NotificationChannel oldChannel = nm.getNotificationChannel("incoming_calls" + chanIndex); + if (oldChannel != null) { + nm.deleteNotificationChannel(oldChannel.getId()); + } + NotificationChannel existingChannel = nm.getNotificationChannel("incoming_calls2" + chanIndex); + boolean needCreate = true; + if (existingChannel != null) { + if (existingChannel.getImportance() < NotificationManager.IMPORTANCE_HIGH || !soundProviderUri.equals(existingChannel.getSound()) || existingChannel.getVibrationPattern() != null || existingChannel.shouldVibrate()) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("User messed up the notification channel; deleting it and creating a proper one"); + } + nm.deleteNotificationChannel("incoming_calls2" + chanIndex); + chanIndex++; + nprefs.edit().putInt("calls_notification_channel", chanIndex).commit(); + } else { + needCreate = false; + } + } + if (needCreate) { + AudioAttributes attrs = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) + .build(); + NotificationChannel chan = new NotificationChannel("incoming_calls2" + chanIndex, LocaleController.getString("IncomingCalls", R.string.IncomingCalls), NotificationManager.IMPORTANCE_HIGH); + chan.setSound(soundProviderUri, attrs); + chan.enableVibration(false); + chan.enableLights(false); + chan.setBypassDnd(true); + try { + nm.createNotificationChannel(chan); + } catch (Exception e) { + FileLog.e(e); + this.stopSelf(); + return; + } + } + builder.setChannelId("incoming_calls2" + chanIndex); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + builder.setSound(soundProviderUri, AudioManager.STREAM_RING); + } + Intent endIntent = new Intent(this, VoIPActionsReceiver.class); + endIntent.setAction(getPackageName() + ".DECLINE_CALL"); + endIntent.putExtra("call_id", getCallID()); + CharSequence endTitle = LocaleController.getString("VoipDeclineCall", R.string.VoipDeclineCall); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + endTitle = new SpannableString(endTitle); + ((SpannableString) endTitle).setSpan(new ForegroundColorSpan(0xFFF44336), 0, endTitle.length(), 0); + } + PendingIntent endPendingIntent = PendingIntent.getBroadcast(this, 0, endIntent, PendingIntent.FLAG_CANCEL_CURRENT); + builder.addAction(R.drawable.ic_call_end_white_24dp, endTitle, endPendingIntent); + Intent answerIntent = new Intent(this, VoIPActionsReceiver.class); + answerIntent.setAction(getPackageName() + ".ANSWER_CALL"); + answerIntent.putExtra("call_id", getCallID()); + CharSequence answerTitle = LocaleController.getString("VoipAnswerCall", R.string.VoipAnswerCall); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + answerTitle = new SpannableString(answerTitle); + ((SpannableString) answerTitle).setSpan(new ForegroundColorSpan(0xFF00AA00), 0, answerTitle.length(), 0); + } + PendingIntent answerPendingIntent = PendingIntent.getBroadcast(this, 0, answerIntent, PendingIntent.FLAG_CANCEL_CURRENT); + builder.addAction(R.drawable.ic_call, answerTitle, answerPendingIntent); + builder.setPriority(Notification.PRIORITY_MAX); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + builder.setShowWhen(false); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + builder.setColor(0xff2ca5e0); + builder.setVibrate(new long[0]); + builder.setCategory(Notification.CATEGORY_CALL); + builder.setFullScreenIntent(PendingIntent.getActivity(this, 0, intent, 0), true); + if (userOrChat instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) userOrChat; + if (!TextUtils.isEmpty(user.phone)) { + builder.addPerson("tel:" + user.phone); + } + } + } + Notification incomingNotification = builder.getNotification(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + RemoteViews customView = new RemoteViews(getPackageName(), LocaleController.isRTL ? R.layout.call_notification_rtl : R.layout.call_notification); + customView.setTextViewText(R.id.name, name); + boolean subtitleVisible = true; + if (TextUtils.isEmpty(subText)) { + customView.setViewVisibility(R.id.subtitle, View.GONE); + if (UserConfig.getActivatedAccountsCount() > 1) { + TLRPC.User self = UserConfig.getInstance(currentAccount).getCurrentUser(); + customView.setTextViewText(R.id.title, video ? LocaleController.formatString("VoipInVideoCallBrandingWithName", R.string.VoipInVideoCallBrandingWithName, ContactsController.formatName(self.first_name, self.last_name)) : LocaleController.formatString("VoipInCallBrandingWithName", R.string.VoipInCallBrandingWithName, ContactsController.formatName(self.first_name, self.last_name))); + } else { + customView.setTextViewText(R.id.title, video ? LocaleController.getString("VoipInVideoCallBranding", R.string.VoipInVideoCallBranding) : LocaleController.getString("VoipInCallBranding", R.string.VoipInCallBranding)); + } + } else { + if (UserConfig.getActivatedAccountsCount() > 1) { + TLRPC.User self = UserConfig.getInstance(currentAccount).getCurrentUser(); + customView.setTextViewText(R.id.subtitle, LocaleController.formatString("VoipAnsweringAsAccount", R.string.VoipAnsweringAsAccount, ContactsController.formatName(self.first_name, self.last_name))); + } else { + customView.setViewVisibility(R.id.subtitle, View.GONE); + } + customView.setTextViewText(R.id.title, subText); + } + Bitmap avatar = getRoundAvatarBitmap(userOrChat); + customView.setTextViewText(R.id.answer_text, LocaleController.getString("VoipAnswerCall", R.string.VoipAnswerCall)); + customView.setTextViewText(R.id.decline_text, LocaleController.getString("VoipDeclineCall", R.string.VoipDeclineCall)); + customView.setImageViewBitmap(R.id.photo, avatar); + customView.setOnClickPendingIntent(R.id.answer_btn, answerPendingIntent); + customView.setOnClickPendingIntent(R.id.decline_btn, endPendingIntent); + builder.setLargeIcon(avatar); + + incomingNotification.headsUpContentView = incomingNotification.bigContentView = customView; + } + startForeground(ID_INCOMING_CALL_NOTIFICATION, incomingNotification); + } + + protected void callFailed(String error) { + try { + throw new Exception("Call " + getCallID() + " failed with error: " + error); + } catch (Exception x) { + FileLog.e(x); + } + lastError = error; + AndroidUtilities.runOnUIThread(() -> dispatchStateChanged(STATE_FAILED)); + if (TextUtils.equals(error, Instance.ERROR_LOCALIZED) && soundPool != null) { + playingSound = true; + Utilities.globalQueue.postRunnable(() -> soundPool.play(spFailedID, 1, 1, 0, 0, 1)); + AndroidUtilities.runOnUIThread(afterSoundRunnable, 1000); + } + if (USE_CONNECTION_SERVICE && systemCallConnection != null) { + systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.ERROR)); + systemCallConnection.destroy(); + systemCallConnection = null; + } + stopSelf(); + } + + void callFailedFromConnectionService() { + if (isOutgoing) { + callFailed(Instance.ERROR_CONNECTION_SERVICE); + } else { + hangUp(); + } + } + + @Override + public void onConnectionStateChanged(int newState) { + if (newState == STATE_FAILED) { + callFailed(); + return; + } + if (newState == STATE_ESTABLISHED) { + if (connectingSoundRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(connectingSoundRunnable); + connectingSoundRunnable = null; + } + Utilities.globalQueue.postRunnable(() -> { + if (spPlayID != 0) { + soundPool.stop(spPlayID); + spPlayID = 0; + } + }); + if (groupCall == null && !wasEstablished) { + wasEstablished = true; + if (!isProximityNear && !privateCall.video) { + Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); + if (vibrator.hasVibrator()) { + vibrator.vibrate(100); + } + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (tgVoip != null) { + StatsController.getInstance(currentAccount).incrementTotalCallsTime(getStatsNetworkType(), 5); + AndroidUtilities.runOnUIThread(this, 5000); + } + } + }, 5000); + if (isOutgoing) { + StatsController.getInstance(currentAccount).incrementSentItemsCount(getStatsNetworkType(), StatsController.TYPE_CALLS, 1); + } else { + StatsController.getInstance(currentAccount).incrementReceivedItemsCount(getStatsNetworkType(), StatsController.TYPE_CALLS, 1); + } + } + } + if (newState == STATE_RECONNECTING) { + Utilities.globalQueue.postRunnable(() -> { + if (spPlayID != 0) { + soundPool.stop(spPlayID); + } + spPlayID = soundPool.play(groupCall != null ? spVoiceChatConnecting : spConnectingId, 1, 1, 0, -1, 1); + }); + } + dispatchStateChanged(newState); + } + + @Override + public void onSignalBarCountChanged(int newCount) { + AndroidUtilities.runOnUIThread(() -> { + signalBarCount = newCount; + for (int a = 0; a < stateListeners.size(); a++) { + StateListener l = stateListeners.get(a); + l.onSignalBarsCountChanged(newCount); + } + }); + } + + public boolean isBluetoothOn() { + final AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + return am.isBluetoothScoOn(); + } + + public boolean isBluetoothWillOn() { + return needSwitchToBluetoothAfterScoActivates; + } + + public boolean isHeadsetPlugged() { + return isHeadsetPlugged; + } + + public void onMediaStateUpdated(int audioState, int videoState) { + AndroidUtilities.runOnUIThread(() -> { + currentAudioState = audioState; + currentVideoState = videoState; + checkIsNear(); + + for (int a = 0; a < stateListeners.size(); a++) { + StateListener l = stateListeners.get(a); + l.onMediaStateUpdated(audioState, videoState); + } + }); + } + + protected void callEnded() { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("Call " + getCallID() + " ended"); + } + if (groupCall != null && (!playedConnectedSound || onDestroyRunnable != null)) { + needPlayEndSound = false; + } + AndroidUtilities.runOnUIThread(() -> dispatchStateChanged(STATE_ENDED)); + int delay = 700; + Utilities.globalQueue.postRunnable(() -> { + if (spPlayID != 0) { + soundPool.stop(spPlayID); + spPlayID = 0; + } + }); + + if (connectingSoundRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(connectingSoundRunnable); + connectingSoundRunnable = null; + } + if (needPlayEndSound) { + playingSound = true; + if (groupCall == null) { + Utilities.globalQueue.postRunnable(() -> soundPool.play(spEndId, 1, 1, 0, 0, 1)); + } else { + Utilities.globalQueue.postRunnable(() -> soundPool.play(spVoiceChatEndId, 1.0f, 1.0f, 0, 0, 1), 100); + delay = 500; + } + AndroidUtilities.runOnUIThread(afterSoundRunnable, delay); + } + if (timeoutRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(timeoutRunnable); + timeoutRunnable = null; + } + endConnectionServiceCall(needPlayEndSound ? delay : 0); + stopSelf(); + } + + protected void endConnectionServiceCall(long delay) { + if (USE_CONNECTION_SERVICE) { + Runnable r = () -> { + if (systemCallConnection != null) { + switch (callDiscardReason) { + case DISCARD_REASON_HANGUP: + systemCallConnection.setDisconnected(new DisconnectCause(isOutgoing ? DisconnectCause.LOCAL : DisconnectCause.REJECTED)); + break; + case DISCARD_REASON_DISCONNECT: + systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.ERROR)); + break; + case DISCARD_REASON_LINE_BUSY: + systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.BUSY)); + break; + case DISCARD_REASON_MISSED: + systemCallConnection.setDisconnected(new DisconnectCause(isOutgoing ? DisconnectCause.CANCELED : DisconnectCause.MISSED)); + break; + default: + systemCallConnection.setDisconnected(new DisconnectCause(DisconnectCause.REMOTE)); + break; + } + systemCallConnection.destroy(); + systemCallConnection = null; + } + }; + if (delay > 0) { + AndroidUtilities.runOnUIThread(r, delay); + } else { + r.run(); + } + } + } + + public boolean isOutgoing() { + return isOutgoing; + } + + public void handleNotificationAction(Intent intent) { + if ((getPackageName() + ".END_CALL").equals(intent.getAction())) { + stopForeground(true); + hangUp(); + } else if ((getPackageName() + ".DECLINE_CALL").equals(intent.getAction())) { + stopForeground(true); + declineIncomingCall(DISCARD_REASON_LINE_BUSY, null); + } else if ((getPackageName() + ".ANSWER_CALL").equals(intent.getAction())) { + acceptIncomingCallFromNotification(); + } + } + + private void acceptIncomingCallFromNotification() { + showNotification(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && (checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED || privateCall.video && checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) { + try { + PendingIntent.getActivity(VoIPBaseService.this, 0, new Intent(VoIPBaseService.this, VoIPPermissionActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0).send(); + } catch (Exception x) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Error starting permission activity", x); + } + } + return; + } + acceptIncomingCall(); + try { + PendingIntent.getActivity(VoIPBaseService.this, 0, new Intent(VoIPBaseService.this, getUIActivityClass()).setAction("voip"), 0).send(); + } catch (Exception x) { + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Error starting incall activity", x); + } + } + } + + public void updateOutputGainControlState() { + if (tgVoip != null) { + if (!USE_CONNECTION_SERVICE) { + final AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + tgVoip.setAudioOutputGainControlEnabled(hasEarpiece() && !am.isSpeakerphoneOn() && !am.isBluetoothScoOn() && !isHeadsetPlugged); + tgVoip.setEchoCancellationStrength(isHeadsetPlugged || (hasEarpiece() && !am.isSpeakerphoneOn() && !am.isBluetoothScoOn() && !isHeadsetPlugged) ? 0 : 1); + } else { + final boolean isEarpiece = systemCallConnection.getCallAudioState().getRoute() == CallAudioState.ROUTE_EARPIECE; + tgVoip.setAudioOutputGainControlEnabled(isEarpiece); + tgVoip.setEchoCancellationStrength(isEarpiece ? 0 : 1); + } + } + } + + public int getAccount() { + return currentAccount; + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.appDidLogout) { + callEnded(); + } + } + + public static boolean isAnyKindOfCallActive() { + if (VoIPService.getSharedInstance() != null) { + return VoIPService.getSharedInstance().getCallState() != VoIPService.STATE_WAITING_INCOMING; + } + return false; + } + + protected boolean isFinished() { + return currentState == STATE_ENDED || currentState == STATE_FAILED; + } + + protected boolean isRinging() { + return false; + } + + public int getCurrentAudioState() { + return currentAudioState; + } + + public int getCurrentVideoState() { + return currentVideoState; + } + + @TargetApi(Build.VERSION_CODES.O) + protected PhoneAccountHandle addAccountToTelecomManager() { + TelecomManager tm = (TelecomManager) getSystemService(TELECOM_SERVICE); + TLRPC.User self = UserConfig.getInstance(currentAccount).getCurrentUser(); + PhoneAccountHandle handle = new PhoneAccountHandle(new ComponentName(this, TelegramConnectionService.class), "" + self.id); + PhoneAccount account = new PhoneAccount.Builder(handle, ContactsController.formatName(self.first_name, self.last_name)) + .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) + .setIcon(Icon.createWithResource(this, R.mipmap.ic_launcher)) + .setHighlightColor(0xff2ca5e0) + .addSupportedUriScheme("sip") + .build(); + tm.registerPhoneAccount(account); + return handle; + } + + private static boolean isDeviceCompatibleWithConnectionServiceAPI() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return false; + } + // some non-Google devices don't implement the ConnectionService API correctly so, sadly, + // we'll have to whitelist only a handful of known-compatible devices for now + return false;/*"angler".equals(Build.PRODUCT) // Nexus 6P || "bullhead".equals(Build.PRODUCT) // Nexus 5X || "sailfish".equals(Build.PRODUCT) // Pixel || "marlin".equals(Build.PRODUCT) // Pixel XL @@ -1740,112 +1753,112 @@ public abstract class VoIPBaseService extends Service implements SensorEventList || "blueline".equals(Build.PRODUCT) // Pixel 3 || "crosshatch".equals(Build.PRODUCT) // Pixel 3 XL || MessagesController.getGlobalMainSettings().getBoolean("dbg_force_connection_service", false);*/ - } + } - public interface StateListener { - default void onStateChanged(int state) { + public interface StateListener { + default void onStateChanged(int state) { - } + } - default void onSignalBarsCountChanged(int count) { + default void onSignalBarsCountChanged(int count) { - } + } - default void onAudioSettingsChanged() { + default void onAudioSettingsChanged() { - } + } - default void onMediaStateUpdated(int audioState, int videoState) { + default void onMediaStateUpdated(int audioState, int videoState) { - } + } - default void onCameraSwitch(boolean isFrontFace) { + default void onCameraSwitch(boolean isFrontFace) { - } + } - default void onVideoAvailableChange(boolean isAvailable) { + default void onVideoAvailableChange(boolean isAvailable) { - } + } - default void onScreenOnChange(boolean screenOn) { + default void onScreenOnChange(boolean screenOn) { - } - } + } + } - public class CallConnection extends Connection { - public CallConnection() { - setConnectionProperties(PROPERTY_SELF_MANAGED); - setAudioModeIsVoip(true); - } + public class CallConnection extends Connection { + public CallConnection() { + setConnectionProperties(PROPERTY_SELF_MANAGED); + setAudioModeIsVoip(true); + } - @Override - public void onCallAudioStateChanged(CallAudioState state) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("ConnectionService call audio state changed: " + state); - } - for (StateListener l : stateListeners) { - l.onAudioSettingsChanged(); - } - } + @Override + public void onCallAudioStateChanged(CallAudioState state) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("ConnectionService call audio state changed: " + state); + } + for (StateListener l : stateListeners) { + l.onAudioSettingsChanged(); + } + } - @Override - public void onDisconnect() { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("ConnectionService onDisconnect"); - } - setDisconnected(new DisconnectCause(DisconnectCause.LOCAL)); - destroy(); - systemCallConnection = null; - hangUp(); - } + @Override + public void onDisconnect() { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("ConnectionService onDisconnect"); + } + setDisconnected(new DisconnectCause(DisconnectCause.LOCAL)); + destroy(); + systemCallConnection = null; + hangUp(); + } - @Override - public void onAnswer() { - acceptIncomingCallFromNotification(); - } + @Override + public void onAnswer() { + acceptIncomingCallFromNotification(); + } - @Override - public void onReject() { - needPlayEndSound = false; - declineIncomingCall(DISCARD_REASON_HANGUP, null); - } + @Override + public void onReject() { + needPlayEndSound = false; + declineIncomingCall(DISCARD_REASON_HANGUP, null); + } - @Override - public void onShowIncomingCallUi() { - startRinging(); - } + @Override + public void onShowIncomingCallUi() { + startRinging(); + } - @Override - public void onStateChanged(int state) { - super.onStateChanged(state); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("ConnectionService onStateChanged " + stateToString(state)); - } - if (state == Connection.STATE_ACTIVE) { - ContactsController.getInstance(currentAccount).deleteConnectionServiceContact(); - didDeleteConnectionServiceContact = true; - } - } + @Override + public void onStateChanged(int state) { + super.onStateChanged(state); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("ConnectionService onStateChanged " + stateToString(state)); + } + if (state == Connection.STATE_ACTIVE) { + ContactsController.getInstance(currentAccount).deleteConnectionServiceContact(); + didDeleteConnectionServiceContact = true; + } + } - @Override - public void onCallEvent(String event, Bundle extras) { - super.onCallEvent(event, extras); - if (BuildVars.LOGS_ENABLED) - FileLog.d("ConnectionService onCallEvent " + event); - } + @Override + public void onCallEvent(String event, Bundle extras) { + super.onCallEvent(event, extras); + if (BuildVars.LOGS_ENABLED) + FileLog.d("ConnectionService onCallEvent " + event); + } - //undocumented API - public void onSilence() { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("onSlience"); - } - stopRinging(); - } - } + //undocumented API + public void onSilence() { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("onSlience"); + } + stopRinging(); + } + } - public static class SharedUIParams { - public boolean tapToVideoTooltipWasShowed; - public boolean cameraAlertWasShowed; - public boolean wasVideoCall; - } + public static class SharedUIParams { + public boolean tapToVideoTooltipWasShowed; + public boolean cameraAlertWasShowed; + public boolean wasVideoCall; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 030fe0812..e78d7cfaf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -1190,7 +1190,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg builder.addTitle(urlFinal); builder.addItems( new String[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("ShareQRCode", R.string.ShareQRCode)}, - new Integer[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24,R.drawable.wallet_qr }, (which, text, cell) -> { + new int[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24, R.drawable.wallet_qr}, (which, text, cell) -> { if (parentActivity == null) return Unit.INSTANCE; if (which == 0 || which == 2) { int index; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java index 67fd91bb7..235c665cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java @@ -43,6 +43,9 @@ import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.RadialProgress2; +import kotlin.Unit; +import tw.nekomimi.nekogram.BottomBuilder; + public class AvatarPreviewer { private static AvatarPreviewer INSTANCE; @@ -450,18 +453,20 @@ public class AvatarPreviewer { } private void showBottomSheet() { - final CharSequence[] labels = new CharSequence[menuItems.length]; + final String[] labels = new String[menuItems.length]; final int[] icons = new int[menuItems.length]; for (int i = 0; i < menuItems.length; i++) { labels[i] = LocaleController.getString(menuItems[i].labelKey, menuItems[i].labelResId); icons[i] = menuItems[i].iconResId; } - visibleSheet = new BottomSheet.Builder(getContext()) - .setItems(labels, icons, (dialog, which) -> { - callback.onMenuClick(menuItems[which]); - setShowing(false); - }) - .setDimBehind(false); + BottomBuilder visibleSheetBuilder = new BottomBuilder(getContext()); + visibleSheetBuilder.addItems(labels, icons, (which, text, cell) -> { + callback.onMenuClick(menuItems[which]); + setShowing(false); + return Unit.INSTANCE; + }); + visibleSheet = visibleSheetBuilder.create(); + visibleSheet.setDimBehind(false); visibleSheet.setOnDismissListener(dialog -> { visibleSheet = null; setShowing(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java index 5bb2121dd..a9b42463f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java @@ -66,9 +66,6 @@ import org.telegram.ui.Components.voip.VoIPHelper; import java.util.ArrayList; import java.util.Iterator; -import kotlin.Unit; -import tw.nekomimi.nekogram.BottomBuilder; - public class CallLogActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listViewAdapter; @@ -502,18 +499,18 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. private void createActionMode() { if (actionBar.actionModeIsExist(null)) { return; - } - final ActionBarMenu actionMode = actionBar.createActionMode(); + } + final ActionBarMenu actionMode = actionBar.createActionMode(); - selectedDialogsCountTextView = new NumberTextView(actionMode.getContext()); - selectedDialogsCountTextView.setTextSize(18); - selectedDialogsCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - selectedDialogsCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); - actionMode.addView(selectedDialogsCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0)); - selectedDialogsCountTextView.setOnTouchListener((v, event) -> true); + selectedDialogsCountTextView = new NumberTextView(actionMode.getContext()); + selectedDialogsCountTextView.setTextSize(18); + selectedDialogsCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + selectedDialogsCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); + actionMode.addView(selectedDialogsCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0)); + selectedDialogsCountTextView.setOnTouchListener((v, event) -> true); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); - } + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.baseline_delete_24, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); + } private boolean addOrRemoveSelectedDialog(ArrayList messages, CustomCell cell) { if (messages.isEmpty()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 5492c7afc..60e727e9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -84,7 +84,6 @@ import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -2030,7 +2029,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio builder.addTitle(urlFinal); builder.addItems( new String[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("ShareQRCode", R.string.ShareQRCode)}, - new Integer[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24,R.drawable.wallet_qr }, (which, text, __) -> { + new int[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24, R.drawable.wallet_qr}, (which, text, __) -> { if (which == 0 || which == 2) { if (which == 0) { Browser.openUrl(getParentActivity(), urlFinal); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index d171f1576..0719f5312 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -231,7 +231,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; -import java.lang.reflect.Array; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; @@ -245,7 +244,6 @@ import java.util.regex.Pattern; import cn.hutool.core.util.StrUtil; import kotlin.Unit; -import kotlin.text.StringsKt; import tw.nekomimi.nekogram.BottomBuilder; import tw.nekomimi.nekogram.MessageDetailsActivity; import tw.nekomimi.nekogram.NekoConfig; @@ -18749,12 +18747,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatMode != MODE_SCHEDULED && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { items.add(LocaleController.getString("Forward", R.string.Forward)); options.add(2); - icons.add(R.drawable.msg_forward); + icons.add(R.drawable.baseline_forward_24); } if (!selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { items.add(LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward)); options.add(95); - icons.add(R.drawable.msg_forward_noquote); + icons.add(R.drawable.baseline_forward_24); } if (chatMode != MODE_SCHEDULED) { if (!UserObject.isUserSelf(currentUser) && NekoConfig.showAddToSavedMessages) { @@ -21366,15 +21364,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.addTitle(str); builder.addItems( new String[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), str.startsWith("#") || str.startsWith("$") ? null : LocaleController.getString("ShareQRCode", R.string.ShareQRCode)}, - new Integer[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24,R.drawable.wallet_qr }, (which, text, __) -> { + new int[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24, R.drawable.wallet_qr}, (which, text, __) -> { if (which == 0 || which == 2) { openClickableLink(str, which == 2); - } else if (which == 1) { - AndroidUtilities.addToClipboard(str); - } + } else if (which == 1) { + AndroidUtilities.addToClipboard(str); + } return Unit.INSTANCE; - }); + }); showDialog(builder.create()); } else { openClickableLink(str, false); @@ -21387,7 +21385,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.addTitle(urlFinal); builder.addItems( new String[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("ShareQRCode", R.string.ShareQRCode)}, - new Integer[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24,R.drawable.wallet_qr }, (which, text, __) -> { + new int[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24, R.drawable.wallet_qr}, (which, text, __) -> { if (which == 0 || which == 2) { if (which == 0) { if (AndroidUtilities.shouldShowUrlInAlert(urlFinal)) { @@ -23533,7 +23531,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelTrendingDescription)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBadgeText)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBadgeBackground)); - themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiBottomPanelIcon)); + themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_messagePanelIcons)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiSearchIcon)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerSetNameHighlight)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerPackSelectorLine)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java index 2179b031b..b93cd19c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -26,7 +26,6 @@ import android.graphics.drawable.GradientDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.Vibrator; import android.provider.Settings; import android.text.Html; import android.text.InputType; @@ -109,6 +108,7 @@ import java.util.concurrent.CountDownLatch; import kotlin.Unit; import tw.nekomimi.nekogram.BottomBuilder; import tw.nekomimi.nekogram.NekoConfig; +import tw.nekomimi.nekogram.utils.AlertUtil; import tw.nekomimi.nekogram.utils.VibrateUtil; public class AlertsCreator { @@ -121,7 +121,7 @@ public class AlertsCreator { TLRPC.InputPeer peer; if (request instanceof TLRPC.TL_messages_initHistoryImport) { peer = ((TLRPC.TL_messages_initHistoryImport) request).peer; - } else if (request instanceof TLRPC.TL_messages_startHistoryImport) { + } else if (request instanceof TLRPC.TL_messages_startHistoryImport) { peer = ((TLRPC.TL_messages_startHistoryImport) request).peer; } else { peer = null; @@ -2385,31 +2385,36 @@ public class AlertsCreator { return null; } - BottomSheet.Builder builder = new BottomSheet.Builder(fragment.getParentActivity()); - builder.setTitle(LocaleController.getString("Notifications", R.string.Notifications), true); - CharSequence[] items = new CharSequence[]{ + BottomBuilder builder = new BottomBuilder(fragment.getParentActivity()); + builder.addTitle(LocaleController.getString("Notifications", R.string.Notifications), true); + String[] items = new String[]{ LocaleController.formatString("MuteFor", R.string.MuteFor, LocaleController.formatPluralString("Hours", 1)), LocaleController.formatString("MuteFor", R.string.MuteFor, LocaleController.formatPluralString("Hours", 8)), LocaleController.formatString("MuteFor", R.string.MuteFor, LocaleController.formatPluralString("Days", 2)), LocaleController.getString("MuteDisable", R.string.MuteDisable) }; - builder.setItems(items, (dialogInterface, i) -> { - int setting; - if (i == 0) { - setting = NotificationsController.SETTING_MUTE_HOUR; - } else if (i == 1) { - setting = NotificationsController.SETTING_MUTE_8_HOURS; - } else if (i == 2) { - setting = NotificationsController.SETTING_MUTE_2_DAYS; - } else { - setting = NotificationsController.SETTING_MUTE_FOREVER; - } - NotificationsController.getInstance(UserConfig.selectedAccount).setDialogNotificationsSettings(dialog_id, setting); - if (BulletinFactory.canShowBulletin(fragment)) { - BulletinFactory.createMuteBulletin(fragment, setting).show(); - } - } - ); + builder.addItems(items, new int[]{ + R.drawable.baseline_notifications_paused_24, + R.drawable.baseline_notifications_paused_24, + R.drawable.baseline_notifications_paused_24, + R.drawable.baseline_notifications_paused_24 + }, (i, text, cell) -> { + int setting; + if (i == 0) { + setting = NotificationsController.SETTING_MUTE_HOUR; + } else if (i == 1) { + setting = NotificationsController.SETTING_MUTE_8_HOURS; + } else if (i == 2) { + setting = NotificationsController.SETTING_MUTE_2_DAYS; + } else { + setting = NotificationsController.SETTING_MUTE_FOREVER; + } + NotificationsController.getInstance(UserConfig.selectedAccount).setDialogNotificationsSettings(dialog_id, setting); + if (BulletinFactory.canShowBulletin(fragment)) { + BulletinFactory.createMuteBulletin(fragment, setting).show(); + } + return Unit.INSTANCE; + }); return builder.create(); } @@ -2418,11 +2423,11 @@ public class AlertsCreator { return; } - BottomSheet.Builder builder = new BottomSheet.Builder(context); - builder.setTitle(LocaleController.getString("ReportChat", R.string.ReportChat), true); - CharSequence[] items; + BottomBuilder builder = new BottomBuilder(context); + builder.addTitle(LocaleController.getString("ReportChat", R.string.ReportChat), true); + String[] items; if (messageId != 0) { - items = new CharSequence[]{ + items = new String[]{ LocaleController.getString("ReportChatSpam", R.string.ReportChatSpam), LocaleController.getString("ReportChatViolence", R.string.ReportChatViolence), LocaleController.getString("ReportChatChild", R.string.ReportChatChild), @@ -2430,7 +2435,7 @@ public class AlertsCreator { LocaleController.getString("ReportChatOther", R.string.ReportChatOther) }; } else { - items = new CharSequence[]{ + items = new String[]{ LocaleController.getString("ReportChatSpam", R.string.ReportChatSpam), LocaleController.getString("ReportChatFakeAccount", R.string.ReportChatFakeAccount), LocaleController.getString("ReportChatViolence", R.string.ReportChatViolence), @@ -2439,13 +2444,13 @@ public class AlertsCreator { LocaleController.getString("ReportChatOther", R.string.ReportChatOther) }; } - builder.setItems(items, (dialogInterface, i) -> { + builder.addItems(items, null, (i, text, cell) -> { if (i == 4) { Bundle args = new Bundle(); args.putLong("dialog_id", dialog_id); args.putLong("message_id", messageId); parentFragment.presentFragment(new ReportOtherActivity(args)); - return; + return Unit.INSTANCE; } TLObject req; TLRPC.InputPeer peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer((int) dialog_id); @@ -2479,10 +2484,10 @@ public class AlertsCreator { } req = request; } - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> { - - }); + ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AlertUtil.showToast(error)); Toast.makeText(context, LocaleController.getString("ReportChatSent", R.string.ReportChatSent), Toast.LENGTH_SHORT).show(); + + return Unit.INSTANCE; } ); BottomSheet sheet = builder.create(); @@ -3026,7 +3031,7 @@ public class AlertsCreator { background.setBackground(new BitmapDrawable(SvgHelper.getBitmap(svg, AndroidUtilities.dp(320), AndroidUtilities.dp(320 * aspectRatio), false))); frameLayout.addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, -1, -1, -1, -1)); - frameLayout.addView(button, LayoutHelper.createFrame(117,117)); + frameLayout.addView(button, LayoutHelper.createFrame(117, 117)); builder.setTopView(frameLayout); builder.setTitle(LocaleController.getString("PermissionDrawAboveOtherAppsGroupCallTitle", R.string.PermissionDrawAboveOtherAppsGroupCallTitle)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java index d843c7993..9fb16c6fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java @@ -1012,8 +1012,8 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. optionsButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 1, AndroidUtilities.dp(18))); } bottomView.addView(optionsButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); - optionsButton.addSubItem(1, R.drawable.msg_forward, LocaleController.getString("Forward", R.string.Forward)); - optionsButton.addSubItem(2, R.drawable.msg_shareout, LocaleController.getString("ShareFile", R.string.ShareFile)); + optionsButton.addSubItem(1, R.drawable.baseline_forward_24, LocaleController.getString("Forward", R.string.Forward)); + optionsButton.addSubItem(2, R.drawable.baseline_share_24, LocaleController.getString("ShareFile", R.string.ShareFile)); optionsButton.addSubItem(5, R.drawable.msg_download, LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); optionsButton.addSubItem(4, R.drawable.msg_message, LocaleController.getString("ShowInChat", R.string.ShowInChat)); optionsButton.setShowedFromBottom(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 9537b92c9..0ac7ad265 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -28,22 +28,10 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.ShapeDrawable; import android.os.Build; - -import androidx.annotation.IntDef; -import androidx.annotation.MainThread; -import androidx.annotation.NonNull; -import androidx.core.view.ViewCompat; -import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.LinearSmoothScroller; -import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.SimpleItemAnimator; -import androidx.viewpager.widget.PagerAdapter; -import androidx.viewpager.widget.ViewPager; import android.text.Editable; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.TextWatcher; -import android.util.Log; import android.util.LongSparseArray; import android.util.SparseArray; import android.util.SparseIntArray; @@ -66,19 +54,30 @@ import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.TextView; +import androidx.annotation.IntDef; +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DocumentObject; -import org.telegram.messenger.MediaDataController; import org.telegram.messenger.Emoji; import org.telegram.messenger.EmojiData; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; @@ -323,8 +322,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific public interface DragListener { void onDragStart(); + void onDragEnd(float velocity); + void onDragCancel(); + void onDrag(int offset); } @@ -386,6 +388,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific }; private static final Field superListenerField; + static { Field f = null; try { @@ -999,43 +1002,45 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific public EmojiView(boolean needStickers, boolean needGif, final Context context, boolean needSearch, final TLRPC.ChatFull chatFull) { super(context); - int color = Theme.getColor(Theme.key_chat_emojiBottomPanelIcon); + int color = Theme.getColor(Theme.key_chat_messagePanelIcons); color = Color.argb(30, Color.red(color), Color.green(color), Color.blue(color)); searchFieldHeight = AndroidUtilities.dp(64); needEmojiSearch = needSearch; + // TODO: replace with baseline icons + tabIcons = new Drawable[]{ - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_tab_smiles, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_tab_gif, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_tab_stickers, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)) + Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_emoticon_outline_24, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.deproko_baseline_gif_24, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.msg_sticker, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)) }; emojiIcons = new Drawable[]{ - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_recent, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_smiles, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_cat, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_food, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_activities, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_travel, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_objects, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_other, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_flags, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_recent, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_smiles, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_cat, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_food, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_activities, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_travel, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_objects, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_other, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_flags, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), }; stickerIcons = new Drawable[]{ - Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_recent, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_favorites, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_trending3, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_recent, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_favorites, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_trending3, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), new LayerDrawable(new Drawable[]{ - Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_trending1, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_trending1, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_trending2, Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine), Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)) }) }; gifIcons = new Drawable[]{ - Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_recent, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_gifs_trending, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_recent, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.stickers_gifs_trending, Theme.getColor(Theme.key_chat_messagePanelIcons), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), }; emojiTitles = new String[]{ @@ -1364,7 +1369,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific emojiTabs.setShouldExpand(true); emojiTabs.setIndicatorHeight(-1); emojiTabs.setUnderlineHeight(-1); - emojiTabs.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + emojiTabs.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); emojiContainer.addView(emojiTabs, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38)); emojiTabs.setDelegate(new ScrollSlidingTabStrip.ScrollSlidingTabStripDelegate() { @Override @@ -1509,7 +1514,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific gifTabs.setUnderlineHeight(AndroidUtilities.getShadowHeight()); gifTabs.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)); gifTabs.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); - gifTabs.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + gifTabs.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); gifContainer.addView(gifTabs, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); updateGifTabs(); @@ -1653,7 +1658,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stickersTab.setUnderlineHeight(AndroidUtilities.getShadowHeight()); stickersTab.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)); stickersTab.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); - stickersTab.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + stickersTab.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); stickersContainer.addView(stickersTab, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); updateStickerTabs(); stickersTab.setDelegate(page -> { @@ -1796,7 +1801,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } }; backspaceButton.setImageResource(R.drawable.smiles_tab_clear); - backspaceButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.SRC_IN)); + backspaceButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); backspaceButton.setScaleType(ImageView.ScaleType.CENTER); backspaceButton.setContentDescription(LocaleController.getString("AccDescrBackspace", R.string.AccDescrBackspace)); backspaceButton.setFocusable(true); @@ -1833,7 +1838,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stickerSettingsButton = new ImageView(context); stickerSettingsButton.setImageResource(R.drawable.smiles_tab_settings); - stickerSettingsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.SRC_IN)); + stickerSettingsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); stickerSettingsButton.setScaleType(ImageView.ScaleType.CENTER); stickerSettingsButton.setFocusable(true); if (Build.VERSION.SDK_INT >= 21) { @@ -1920,7 +1925,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific searchButton = new ImageView(context); searchButton.setImageResource(R.drawable.smiles_tab_search); - searchButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.SRC_IN)); + searchButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); searchButton.setScaleType(ImageView.ScaleType.CENTER); searchButton.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchButton.setFocusable(true); @@ -2052,7 +2057,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (parent != null) { float y = getY() - parent.getHeight(); if (getLayoutParams().height > 0) { - y += getLayoutParams().height; + y += getLayoutParams().height; } else { y += getMeasuredHeight(); } @@ -2628,9 +2633,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private ScrollSlidingTabStrip getTabsForType(@Type int type) { switch (type) { - case Type.STICKERS: return stickersTab; - case Type.EMOJIS: return emojiTabs; - case Type.GIFS: return gifTabs; + case Type.STICKERS: + return stickersTab; + case Type.EMOJIS: + return emojiTabs; + case Type.GIFS: + return gifTabs; default: throw new IllegalArgumentException("Unexpected argument: " + type); } @@ -2638,9 +2646,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private RecyclerListView getListViewForType(@Type int type) { switch (type) { - case Type.STICKERS: return stickersGridView; - case Type.EMOJIS: return emojiGridView; - case Type.GIFS: return gifGridView; + case Type.STICKERS: + return stickersGridView; + case Type.EMOJIS: + return emojiGridView; + case Type.GIFS: + return gifGridView; default: throw new IllegalArgumentException("Unexpected argument: " + type); } @@ -2648,9 +2659,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private GridLayoutManager getLayoutManagerForType(@Type int type) { switch (type) { - case Type.STICKERS: return stickersLayoutManager; - case Type.EMOJIS: return emojiLayoutManager; - case Type.GIFS: return gifLayoutManager; + case Type.STICKERS: + return stickersLayoutManager; + case Type.EMOJIS: + return emojiLayoutManager; + case Type.GIFS: + return gifLayoutManager; default: throw new IllegalArgumentException("Unexpected argument: " + type); } @@ -2658,9 +2672,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private SearchField getSearchFieldForType(@Type int type) { switch (type) { - case Type.STICKERS: return stickersSearchField; - case Type.EMOJIS: return emojiSearchField; - case Type.GIFS: return gifSearchField; + case Type.STICKERS: + return stickersSearchField; + case Type.EMOJIS: + return emojiSearchField; + case Type.GIFS: + return gifSearchField; default: throw new IllegalArgumentException("Unexpected argument: " + type); } @@ -3039,8 +3056,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific gifTabs.addIconTab(0, gifIcons[0]).setContentDescription(LocaleController.getString("RecentStickers", R.string.RecentStickers)); } - gifTrendingTabNum = gifTabsCount++; - gifTabs.addIconTab(1, gifIcons[1]).setContentDescription(LocaleController.getString("FeaturedGifs", R.string.FeaturedGifs)); + if (!NekoConfig.disableTrending) { + gifTrendingTabNum = gifTabsCount++; + gifTabs.addIconTab(1, gifIcons[1]).setContentDescription(LocaleController.getString("FeaturedGifs", R.string.FeaturedGifs)); + } gifFirstEmojiTabNum = gifTabsCount; final int hPadding = AndroidUtilities.dp(13); @@ -3114,7 +3133,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } else { setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); if (needEmojiSearch) { - bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); } } @@ -3159,12 +3178,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (stickersTab != null) { stickersTab.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)); stickersTab.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); - stickersTab.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + stickersTab.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); } if (gifTabs != null) { gifTabs.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)); gifTabs.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); - gifTabs.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + gifTabs.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); } if (backspaceButton != null) { backspaceButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.SRC_IN)); @@ -3193,19 +3212,19 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } for (int a = 0; a < tabIcons.length; a++) { - Theme.setEmojiDrawableColor(tabIcons[a], Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), false); + Theme.setEmojiDrawableColor(tabIcons[a], Theme.getColor(Theme.key_chat_messagePanelIcons), false); Theme.setEmojiDrawableColor(tabIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); } for (int a = 0; a < emojiIcons.length; a++) { - Theme.setEmojiDrawableColor(emojiIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIcon), false); + Theme.setEmojiDrawableColor(emojiIcons[a], Theme.getColor(Theme.key_chat_messagePanelIcons), false); Theme.setEmojiDrawableColor(emojiIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); } for (int a = 0; a < stickerIcons.length; a++) { - Theme.setEmojiDrawableColor(stickerIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIcon), false); + Theme.setEmojiDrawableColor(stickerIcons[a], Theme.getColor(Theme.key_chat_messagePanelIcons), false); Theme.setEmojiDrawableColor(stickerIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); } for (int a = 0; a < gifIcons.length; a++) { - Theme.setEmojiDrawableColor(gifIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIcon), false); + Theme.setEmojiDrawableColor(gifIcons[a], Theme.getColor(Theme.key_chat_messagePanelIcons), false); Theme.setEmojiDrawableColor(gifIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); } } @@ -3223,7 +3242,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific setBackgroundResource(R.drawable.smiles_popup); getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackground), PorterDuff.Mode.SRC_IN)); if (needEmojiSearch) { - bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); } currentBackgroundType = 1; } @@ -3236,7 +3255,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); if (needEmojiSearch) { - bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); } currentBackgroundType = 0; } @@ -4300,7 +4319,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public CharSequence getPageTitle(int position) { - switch(position) { + switch (position) { case 0: return LocaleController.getString("Emoji", R.string.Emoji); case 1: diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java index 117b6c28e..b9b1db487 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java @@ -24,6 +24,8 @@ import android.text.TextUtils; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; +import androidx.core.graphics.ColorUtils; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.ImageLocation; @@ -34,8 +36,6 @@ import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; -import androidx.core.graphics.ColorUtils; - public class GroupCreateSpan extends View { private int uid; @@ -67,7 +67,7 @@ public class GroupCreateSpan extends View { super(context); currentContact = contact; - deleteDrawable = getResources().getDrawable(R.drawable.delete); + deleteDrawable = getResources().getDrawable(R.drawable.baseline_delete_24); textPaint.setTextSize(AndroidUtilities.dp(14)); String firstName; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java index 856a8f5bc..1009a57bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java @@ -5,7 +5,6 @@ import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; -import android.graphics.Color; import android.text.SpannableStringBuilder; import android.util.TypedValue; import android.view.Gravity; @@ -90,7 +89,7 @@ public class LinkActionView extends LinearLayout { copyView = new TextView(context); copyView.setGravity(Gravity.CENTER_HORIZONTAL); SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); - spannableStringBuilder.append("..").setSpan(new ColoredImageSpan(ContextCompat.getDrawable(context, R.drawable.msg_copy_filled)), 0, 1, 0); + spannableStringBuilder.append("..").setSpan(new ColoredImageSpan(ContextCompat.getDrawable(context, R.drawable.baseline_content_copy_24)), 0, 1, 0); spannableStringBuilder.setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(8)), 1, 2, 0); spannableStringBuilder.append(LocaleController.getString("CopyLink", R.string.CopyLink)); spannableStringBuilder.append(".").setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(5)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); @@ -104,7 +103,7 @@ public class LinkActionView extends LinearLayout { shareView = new TextView(context); shareView.setGravity(Gravity.CENTER_HORIZONTAL); spannableStringBuilder = new SpannableStringBuilder(); - spannableStringBuilder.append("..").setSpan(new ColoredImageSpan(ContextCompat.getDrawable(context, R.drawable.msg_share_filled)), 0, 1, 0); + spannableStringBuilder.append("..").setSpan(new ColoredImageSpan(ContextCompat.getDrawable(context, R.drawable.baseline_forward_24)), 0, 1, 0); spannableStringBuilder.setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(8)), 1, 2, 0); spannableStringBuilder.append(LocaleController.getString("ShareLink", R.string.ShareLink)); spannableStringBuilder.append(".").setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(5)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); @@ -120,7 +119,7 @@ public class LinkActionView extends LinearLayout { removeView = new TextView(context); removeView.setGravity(Gravity.CENTER_HORIZONTAL); spannableStringBuilder = new SpannableStringBuilder(); - spannableStringBuilder.append("..").setSpan(new ColoredImageSpan(ContextCompat.getDrawable(context, R.drawable.msg_delete)), 0, 1, 0); + spannableStringBuilder.append("..").setSpan(new ColoredImageSpan(ContextCompat.getDrawable(context, R.drawable.baseline_delete_24)), 0, 1, 0); spannableStringBuilder.setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(8)), 1, 2, 0); spannableStringBuilder.append(LocaleController.getString("DeleteLink", R.string.DeleteLink)); spannableStringBuilder.append(".").setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(5)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); @@ -201,7 +200,7 @@ public class LinkActionView extends LinearLayout { ActionBarMenuSubItem subItem; if (!permanent) { subItem = new ActionBarMenuSubItem(context, true, false); - subItem.setTextAndIcon(LocaleController.getString("Edit", R.string.Edit), R.drawable.msg_edit); + subItem.setTextAndIcon(LocaleController.getString("Edit", R.string.Edit), R.drawable.baseline_edit_24); layout.addView(subItem, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); subItem.setOnClickListener(view12 -> { delegate.editLink(); @@ -219,7 +218,7 @@ public class LinkActionView extends LinearLayout { // }); subItem = new ActionBarMenuSubItem(context, false, true); - subItem.setTextAndIcon(LocaleController.getString("RevokeLink", R.string.RevokeLink), R.drawable.msg_delete); + subItem.setTextAndIcon(LocaleController.getString("RevokeLink", R.string.RevokeLink), R.drawable.baseline_delete_24); subItem.setColors(Theme.getColor(Theme.key_windowBackgroundWhiteRedText), Theme.getColor(Theme.key_windowBackgroundWhiteRedText)); subItem.setOnClickListener(view1 -> { revokeLink(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java index 2ee26bc4e..a544ab1db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java @@ -14,9 +14,6 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.drawable.Drawable; -import androidx.viewpager.widget.ViewPager; -import androidx.viewpager.widget.ViewPager.OnPageChangeListener; - import android.graphics.drawable.RippleDrawable; import android.os.Build; import android.view.View; @@ -27,6 +24,9 @@ import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; +import androidx.viewpager.widget.ViewPager; +import androidx.viewpager.widget.ViewPager.OnPageChangeListener; + import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; @@ -138,14 +138,14 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { super.setSelected(selected); Drawable background = getBackground(); if (Build.VERSION.SDK_INT >= 21 && background != null) { - int color = Theme.getColor(selected ? Theme.key_chat_emojiPanelIconSelected : Theme.key_chat_emojiBottomPanelIcon); + int color = Theme.getColor(selected ? Theme.key_chat_emojiPanelIconSelected : Theme.key_chat_messagePanelIcons); Theme.setSelectorDrawableColor(background, Color.argb(30, Color.red(color), Color.green(color), Color.blue(color)), true); } } }; tab.setFocusable(true); if (Build.VERSION.SDK_INT >= 21) { - RippleDrawable rippleDrawable = (RippleDrawable) Theme.createSelectorDrawable(Theme.getColor(Theme.key_chat_emojiBottomPanelIcon)); + RippleDrawable rippleDrawable = (RippleDrawable) Theme.createSelectorDrawable(Theme.getColor(Theme.key_chat_messagePanelIcons)); Theme.setRippleDrawableForceSoftware(rippleDrawable); tab.setBackground(rippleDrawable); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java index e8e3530ef..bdab5eeeb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java @@ -7,7 +7,6 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.os.Bundle; -import android.text.TextUtils; import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; @@ -347,7 +346,7 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); gotoItem = actionMode.addItemWithWidth(gotoItemId, R.drawable.msg_message, AndroidUtilities.dp(54), LocaleController.getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage)); - forwardItem = actionMode.addItemWithWidth(forwardItemId, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward)); + forwardItem = actionMode.addItemWithWidth(forwardItemId, R.drawable.baseline_forward_24, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward)); } if (parent.getActionBar().getBackButton().getDrawable() instanceof MenuDrawable) { parent.getActionBar().setBackButtonDrawable(new BackDrawable(false)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index e2eb64981..e0005dc7a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -48,6 +48,10 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.SQLite.SQLiteCursor; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -82,9 +86,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Locale; -import androidx.core.view.ViewCompat; -import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.RecyclerView; +import tw.nekomimi.nekogram.NekoConfig; public class ShareAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { @@ -1063,19 +1065,29 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi if (sendingMessageObjects != null) { for (int a = 0; a < selectedDialogs.size(); a++) { long key = selectedDialogs.keyAt(a); + if (NekoConfig.sendCommentAfterForward) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingMessageObjects, key, true, 0); + } if (frameLayout2.getTag() != null && commentTextView.length() > 0) { SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingMessageObjects, key, true, 0); + if (!NekoConfig.sendCommentAfterForward) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingMessageObjects, key, true, 0); + } } onSend(selectedDialogs, sendingMessageObjects.size()); } else if (sendingText != null) { for (int a = 0; a < selectedDialogs.size(); a++) { long key = selectedDialogs.keyAt(a); + if (NekoConfig.sendCommentAfterForward) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingText, key, null, null, null, true, null, null, null, true, 0); + } if (frameLayout2.getTag() != null && commentTextView.length() > 0) { SendMessagesHelper.getInstance(currentAccount).sendMessage(commentTextView.getText().toString(), key, null, null, null, true, null, null, null, true, 0); } - SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingText, key, null, null, null, true, null, null, null, true, 0); + if (!NekoConfig.sendCommentAfterForward) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(sendingText, key, null, null, null, true, null, null, null, true, 0); + } } } if (delegate != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java index 8f1415677..9f0e87ad4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -58,7 +58,6 @@ import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; @@ -71,7 +70,6 @@ import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Adapters.SearchAdapterHelper; @@ -871,7 +869,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter gotoItem.setOnClickListener(v -> onActionBarItemClick(gotochat)); forwardNoQuoteItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); - forwardNoQuoteItem.setIcon(R.drawable.msg_forward_noquote); + forwardNoQuoteItem.setIcon(R.drawable.baseline_forward_24); forwardNoQuoteItem.setContentDescription(LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward)); forwardNoQuoteItem.setDuplicateParentStateEnabled(false); actionModeLayout.addView(forwardNoQuoteItem, new LinearLayout.LayoutParams(AndroidUtilities.dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); @@ -879,7 +877,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter forwardNoQuoteItem.setOnClickListener(v -> onActionBarItemClick(forward_noquote)); forwardItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); - forwardItem.setIcon(R.drawable.msg_forward); + forwardItem.setIcon(R.drawable.baseline_forward_24); forwardItem.setContentDescription(LocaleController.getString("Forward", R.string.Forward)); forwardItem.setDuplicateParentStateEnabled(false); actionModeLayout.addView(forwardItem, new LinearLayout.LayoutParams(AndroidUtilities.dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); @@ -887,7 +885,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter forwardItem.setOnClickListener(v -> onActionBarItemClick(forward)); } deleteItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); - deleteItem.setIcon(R.drawable.msg_delete); + deleteItem.setIcon(R.drawable.baseline_delete_24); deleteItem.setContentDescription(LocaleController.getString("Delete", R.string.Delete)); deleteItem.setDuplicateParentStateEnabled(false); actionModeLayout.addView(deleteItem, new LinearLayout.LayoutParams(AndroidUtilities.dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); @@ -3082,7 +3080,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter builder.addTitle(urlFinal); builder.addItems( new String[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("ShareQRCode", R.string.ShareQRCode)}, - new Integer[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24,R.drawable.wallet_qr }, (which, text, __) -> { + new int[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24, R.drawable.wallet_qr}, (which, text, __) -> { if (which == 0 || which == 2) { if (which == 0) { openUrl(urlFinal); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java index 24ac8cb27..5cea0a244 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java @@ -17,6 +17,7 @@ import android.graphics.Point; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; + import androidx.core.content.FileProvider; import org.telegram.messenger.AndroidUtilities; @@ -29,13 +30,15 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.PhotoAlbumPickerActivity; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; +import kotlin.Unit; +import tw.nekomimi.nekogram.BottomBuilder; + public class WallpaperUpdater { private String currentPicturePath; @@ -57,20 +60,20 @@ public class WallpaperUpdater { } public void showAlert(final boolean fromTheme) { - BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity); - builder.setTitle(LocaleController.getString("ChoosePhoto", R.string.ChoosePhoto), true); + BottomBuilder builder = new BottomBuilder(parentActivity); + builder.addTitle(LocaleController.getString("ChoosePhoto", R.string.ChoosePhoto), true); - CharSequence[] items; + String[] items; int[] icons; if (fromTheme) { - items = new CharSequence[]{LocaleController.getString("ChooseTakePhoto", R.string.ChooseTakePhoto), LocaleController.getString("SelectFromGallery", R.string.SelectFromGallery), LocaleController.getString("SelectColor", R.string.SelectColor), LocaleController.getString("Default", R.string.Default)}; + items = new String[]{LocaleController.getString("ChooseTakePhoto", R.string.ChooseTakePhoto), LocaleController.getString("SelectFromGallery", R.string.SelectFromGallery), LocaleController.getString("SelectColor", R.string.SelectColor), LocaleController.getString("Default", R.string.Default)}; icons = null; } else { - items = new CharSequence[]{LocaleController.getString("ChooseTakePhoto", R.string.ChooseTakePhoto), LocaleController.getString("SelectFromGallery", R.string.SelectFromGallery)}; + items = new String[]{LocaleController.getString("ChooseTakePhoto", R.string.ChooseTakePhoto), LocaleController.getString("SelectFromGallery", R.string.SelectFromGallery)}; icons = new int[]{R.drawable.baseline_camera_alt_24, R.drawable.baseline_image_24}; } - builder.setItems(items, icons, (dialogInterface, i) -> { + builder.addItems(items, icons, (i, t, c) -> { try { if (i == 0) { try { @@ -102,6 +105,7 @@ public class WallpaperUpdater { } catch (Exception e) { FileLog.e(e); } + return Unit.INSTANCE; }); builder.show(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 3083bcb0f..7c4175466 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -38,7 +38,6 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.Vibrator; import android.text.TextUtils; import android.util.Property; import android.util.SparseArray; @@ -105,7 +104,6 @@ import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.MenuDrawable; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -166,6 +164,8 @@ import org.telegram.ui.Components.ViewPagerFixed; import java.util.ArrayList; +import kotlin.Unit; +import tw.nekomimi.nekogram.BottomBuilder; import tw.nekomimi.nekogram.NekoConfig; import tw.nekomimi.nekogram.utils.PrivacyUtil; import tw.nekomimi.nekogram.utils.ProxyUtil; @@ -2192,22 +2192,23 @@ private int lastMeasuredTopPadding; linearLayout.setMinimumWidth(AndroidUtilities.dp(200)); linearLayout.setOrientation(LinearLayout.VERTICAL); - scrimPopupWindowItems = new ActionBarMenuSubItem[3]; - for (int a = 0, N = (tabView.getId() == Integer.MAX_VALUE ? 2 : 3); a < N; a++) { + scrimPopupWindowItems = new ActionBarMenuSubItem[4]; + for (int a = 0, N = (tabView.getId() == Integer.MAX_VALUE ? 3 : 4); a < 4; a++) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), a == 0, a == N - 1); if (a == 0) { - if (getMessagesController().dialogFilters.size() <= 1) { - continue; - } + if (getMessagesController().dialogFilters.size() <= 1) continue; cell.setTextAndIcon(LocaleController.getString("FilterReorder", R.string.FilterReorder), R.drawable.tabs_reorder); } else if (a == 1) { - if (N == 2) { + if (N == 3) { cell.setTextAndIcon(LocaleController.getString("FilterEditAll", R.string.FilterEditAll), R.drawable.baseline_edit_24); } else { cell.setTextAndIcon(LocaleController.getString("FilterEdit", R.string.FilterEdit), R.drawable.baseline_edit_24); } - } else { + } else if (a == 2) { + if (N == 3) continue; cell.setTextAndIcon(LocaleController.getString("FilterDeleteItem", R.string.FilterDeleteItem), R.drawable.baseline_delete_24); + } else { + cell.setTextAndIcon(LocaleController.getString("MarkAllAsRead", R.string.MarkAllAsRead), R.drawable.baseline_done_all_24); } scrimPopupWindowItems[a] = cell; linearLayout.addView(cell); @@ -2225,6 +2226,8 @@ private int lastMeasuredTopPadding; } } else if (i == 2) { showDeleteAlert(dialogFilter); + } else { + getMessagesStorage().readAllDialogs(tabView.getId()); } if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); @@ -3378,9 +3381,9 @@ private int lastMeasuredTopPadding; ActionBarMenuItem otherItem = actionMode.addItemWithWidth(0, R.drawable.ic_ab_other, AndroidUtilities.dp(54), LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); archiveItem = otherItem.addSubItem(archive, R.drawable.baseline_archive_24, LocaleController.getString("Archive", R.string.Archive)); pin2Item = otherItem.addSubItem(pin2, R.drawable.deproko_baseline_pin_24, LocaleController.getString("DialogPin", R.string.DialogPin)); - addToFolderItem = otherItem.addSubItem(add_to_folder, R.drawable.msg_addfolder, LocaleController.getString("FilterAddTo", R.string.FilterAddTo)); - removeFromFolderItem = otherItem.addSubItem(remove_from_folder, R.drawable.msg_removefolder, LocaleController.getString("FilterRemoveFrom", R.string.FilterRemoveFrom)); - readItem = otherItem.addSubItem(read, R.drawable.deproko_baseline_check_double_24, LocaleController.getString("MarkAsRead", R.string.MarkAsRead)); + addToFolderItem = otherItem.addSubItem(add_to_folder, R.drawable.baseline_folder_24, LocaleController.getString("FilterAddTo", R.string.FilterAddTo)); + removeFromFolderItem = otherItem.addSubItem(remove_from_folder, R.drawable.baseline_folder_open_24, LocaleController.getString("FilterRemoveFrom", R.string.FilterRemoveFrom)); + readItem = otherItem.addSubItem(read, R.drawable.baseline_done_all_24, LocaleController.getString("MarkAsRead", R.string.MarkAsRead)); clearItem = otherItem.addSubItem(clear, R.drawable.baseline_delete_sweep_24, LocaleController.getString("ClearHistory", R.string.ClearHistory)); blockItem = otherItem.addSubItem(block, R.drawable.baseline_block_24, LocaleController.getString("BlockUser", R.string.BlockUser)); @@ -4618,18 +4621,18 @@ private int lastMeasuredTopPadding; } else { if (dialog instanceof TLRPC.TL_dialogFolder) { view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); + BottomBuilder builder = new BottomBuilder(getParentActivity()); final boolean hasUnread = getMessagesStorage().getArchiveUnreadCount() != 0; int[] icons = new int[]{ - hasUnread ? R.drawable.deproko_baseline_check_double_24 : 0, + hasUnread ? R.drawable.baseline_done_all_24 : 0, SharedConfig.archiveHidden ? R.drawable.deproko_baseline_pin_24 : R.drawable.deproko_baseline_pin_undo_24, }; - CharSequence[] items = new CharSequence[]{ + String[] items = new String[]{ hasUnread ? LocaleController.getString("MarkAllAsRead", R.string.MarkAllAsRead) : null, SharedConfig.archiveHidden ? LocaleController.getString("PinInTheList", R.string.PinInTheList) : LocaleController.getString("HideAboveTheList", R.string.HideAboveTheList) }; - builder.setItems(items, icons, (d, which) -> { + builder.addItems(items, icons, (which, t, c) -> { if (which == 0) { getMessagesStorage().readAllDialogs(1); } else if (which == 1 && viewPages != null) { @@ -4645,6 +4648,7 @@ private int lastMeasuredTopPadding; viewPages[a].listView.toggleArchiveHidden(true, dialogCell); } } + return Unit.INSTANCE; }); showDialog(builder.create()); return false; @@ -5438,7 +5442,7 @@ private int lastMeasuredTopPadding; muteItem.setContentDescription(LocaleController.getString("ChatsMute", R.string.ChatsMute)); } if (canReadCount != 0) { - readItem.setTextAndIcon(LocaleController.getString("MarkAsRead", R.string.MarkAsRead), R.drawable.deproko_baseline_check_double_24); + readItem.setTextAndIcon(LocaleController.getString("MarkAsRead", R.string.MarkAsRead), R.drawable.baseline_done_all_24); } else { readItem.setTextAndIcon(LocaleController.getString("MarkAsUnread", R.string.MarkAsUnread), R.drawable.baseline_unsubscribe_24); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index b7412be1b..fa51e329e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -45,7 +45,6 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Adapters.FiltersView; @@ -1087,7 +1086,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente builder.addTitle(urlFinal); builder.addItems( new String[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("ShareQRCode", R.string.ShareQRCode)}, - new Integer[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24,R.drawable.wallet_qr }, (which, text, __) -> { + new int[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24, R.drawable.wallet_qr}, (which, text, __) -> { if (which == 0 || which == 2) { if (which == 0) { openUrl(urlFinal); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index 25448c05c..53540a59e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -26,8 +26,8 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; -import android.provider.Settings; import android.os.Vibrator; +import android.provider.Settings; import android.text.TextUtils; import android.util.Property; import android.util.TypedValue; @@ -92,8 +92,8 @@ import org.telegram.ui.Components.CheckBoxSquare; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.FillLastLinearLayoutManager; -import org.telegram.ui.Components.GroupVoipInviteAlert; import org.telegram.ui.Components.GroupCallPip; +import org.telegram.ui.Components.GroupVoipInviteAlert; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; @@ -2847,7 +2847,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter options.add(5); } items.add(LocaleController.getString("VoipGroupOpenProfile", R.string.VoipGroupOpenProfile)); - icons.add(R.drawable.msg_openprofile); + icons.add(R.drawable.book_user); options.add(6); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java index 60e5a8b1e..a2f2e4249 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java @@ -845,23 +845,23 @@ public class ManageLinksActivity extends BaseFragment implements NotificationCen if (invite.revoked) { items.add(LocaleController.getString("Delete", R.string.Delete)); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); actions.add(4); } else { items.add(LocaleController.getString("Copy", R.string.Copy)); - icons.add(R.drawable.msg_copy); + icons.add(R.drawable.baseline_content_copy_24); actions.add(0); items.add(LocaleController.getString("Share", R.string.ShareLink)); - icons.add(R.drawable.msg_share); + icons.add(R.drawable.baseline_forward_24); actions.add(1); items.add(LocaleController.getString("Edit", R.string.Edit)); - icons.add(R.drawable.msg_edit); + icons.add(R.drawable.baseline_edit_24); actions.add(2); items.add(LocaleController.getString("RevokeLink", R.string.RevokeLink)); - icons.add(R.drawable.msg_delete); + icons.add(R.drawable.baseline_delete_24); actions.add(3); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index ea5f15c4a..08b1d2399 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -68,7 +68,6 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.GraySectionCell; @@ -662,8 +661,8 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if ((int) dialog_id != 0) { actionModeViews.add(gotoItem = actionMode.addItemWithWidth(gotochat, R.drawable.msg_message, AndroidUtilities.dp(54), LocaleController.getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage))); - actionModeViews.add(actionMode.addItemWithWidth(forward_noquote, R.drawable.msg_forward_noquote, AndroidUtilities.dp(54), LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward))); - actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); + actionModeViews.add(actionMode.addItemWithWidth(forward_noquote, R.drawable.baseline_forward_24, AndroidUtilities.dp(54), LocaleController.getString("NoQuoteForward", R.string.NoQuoteForward))); + actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.baseline_forward_24, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); } actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.baseline_delete_24, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); @@ -2083,7 +2082,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No builder.addTitle(urlFinal); builder.addItems( new String[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("ShareQRCode", R.string.ShareQRCode)}, - new Integer[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24,R.drawable.wallet_qr }, (which, text, __) -> { + new int[]{R.drawable.baseline_open_in_browser_24, R.drawable.baseline_content_copy_24, R.drawable.wallet_qr}, (which, text, __) -> { if (which == 0 || which == 2) { if (which == 0) { openUrl(urlFinal); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 1530c9f35..a9e68c0ca 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -48,25 +48,6 @@ import android.os.Bundle; import android.os.SystemClock; import android.os.Vibrator; import android.provider.Settings; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.collection.ArrayMap; -import androidx.core.content.ContextCompat; -import androidx.core.content.FileProvider; -import androidx.core.graphics.ColorUtils; -import androidx.core.view.ViewCompat; -import androidx.core.widget.NestedScrollView; -import androidx.dynamicanimation.animation.DynamicAnimation; -import androidx.dynamicanimation.animation.SpringAnimation; -import androidx.dynamicanimation.animation.SpringForce; -import androidx.exifinterface.media.ExifInterface; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.LinearSmoothScrollerEnd; -import androidx.recyclerview.widget.RecyclerView; - import android.text.Layout; import android.text.Selection; import android.text.Spannable; @@ -128,11 +109,13 @@ import androidx.annotation.Nullable; import androidx.collection.ArrayMap; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; +import androidx.core.graphics.ColorUtils; import androidx.core.view.ViewCompat; import androidx.core.widget.NestedScrollView; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; +import androidx.exifinterface.media.ExifInterface; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScrollerEnd; @@ -255,6 +238,7 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import kotlin.Unit; +import tw.nekomimi.nekogram.MessageHelper; import tw.nekomimi.nekogram.NekoConfig; import tw.nekomimi.nekogram.NekoXConfig; import tw.nekomimi.nekogram.transtale.TranslateDb; @@ -263,8 +247,6 @@ import tw.nekomimi.nekogram.transtale.TranslatorKt; import tw.nekomimi.nekogram.utils.AlertUtil; import tw.nekomimi.nekogram.utils.ProxyUtil; -import tw.nekomimi.nekogram.MessageHelper; - @SuppressWarnings("unchecked") public class PhotoViewer implements NotificationCenter.NotificationCenterDelegate, GestureDetector2.OnGestureListener, GestureDetector2.OnDoubleTapListener { @@ -4123,9 +4105,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat masksItem.setContentDescription(LocaleController.getString("Masks", R.string.Masks)); pipItem = menu.addItem(gallery_menu_pip, R.drawable.ic_goinline); pipItem.setContentDescription(LocaleController.getString("AccDescrPipMode", R.string.AccDescrPipMode)); - sendNoQuoteItem = menu.addItem(gallery_menu_send_noquote, R.drawable.msg_forward_noquote); + sendNoQuoteItem = menu.addItem(gallery_menu_send_noquote, R.drawable.baseline_forward_24); sendNoQuoteItem.setContentDescription(LocaleController.getString("NoQuoteForward", R.string.Forward)); - sendItem = menu.addItem(gallery_menu_send, R.drawable.msg_forward); + sendItem = menu.addItem(gallery_menu_send, R.drawable.baseline_forward_24); sendItem.setContentDescription(LocaleController.getString("Forward", R.string.Forward)); shareItem = menu.addItem(gallery_menu_share2, R.drawable.share); shareItem.setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index a6c4c96a9..bf54ab5f3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -77,7 +77,6 @@ import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; @@ -121,7 +120,6 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; -import org.telegram.ui.Adapters.SearchAdapter; import org.telegram.ui.Cells.AboutLinkCell; import org.telegram.ui.Cells.DividerCell; import org.telegram.ui.Cells.GraySectionCell; @@ -174,7 +172,6 @@ import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.RuntimeUtil; import cn.hutool.core.util.StrUtil; import kotlin.Unit; -import kotlin.text.StringsKt; import libv2ray.Libv2ray; import tw.nekomimi.nekogram.BottomBuilder; import tw.nekomimi.nekogram.ExternalGcm; @@ -5924,12 +5921,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. otherItem.addSubItem(delete_contact, R.drawable.baseline_delete_24, LocaleController.getString("DeleteContact", R.string.DeleteContact)); } if (!UserObject.isDeleted(user) && !isBot && currentEncryptedChat == null && !userBlocked && user_id != 333000 && user_id != 777000 && user_id != 42777) { - otherItem.addSubItem(start_secret_chat, R.drawable.msg_start_secret, LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat)); + otherItem.addSubItem(start_secret_chat, R.drawable.baseline_lock_24, LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat)); } if (StrUtil.isNotBlank(user.username)) { otherItem.addSubItem(qr_code, R.drawable.wallet_qr, LocaleController.getString("ShareQRCode", R.string.ShareQRCode)); } - otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + otherItem.addSubItem(add_shortcut, R.drawable.baseline_home_24, LocaleController.getString("AddShortcut", R.string.AddShortcut)); } } else if (chat_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(chat_id); @@ -5966,7 +5963,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else { if (!TextUtils.isEmpty(chat.username)) { - otherItem.addSubItem(share, R.drawable.msg_share, LocaleController.getString("BotShare", R.string.BotShare)); + otherItem.addSubItem(share, R.drawable.baseline_forward_24, LocaleController.getString("BotShare", R.string.BotShare)); } if (!currentChat.creator && !currentChat.left && !currentChat.kicked) { otherItem.addSubItem(leave_group, R.drawable.baseline_exit_to_app_24, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)); @@ -6004,7 +6001,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. otherItem.addSubItem(set_as_main, R.drawable.menu_private, LocaleController.getString("SetAsMain", R.string.SetAsMain)); otherItem.addSubItem(gallery_menu_save, R.drawable.baseline_image_24, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); //otherItem.addSubItem(edit_avatar, R.drawable.photo_paint, LocaleController.getString("EditPhoto", R.string.EditPhoto)); - otherItem.addSubItem(delete_avatar, R.drawable.msg_delete, LocaleController.getString("Delete", R.string.Delete)); + otherItem.addSubItem(delete_avatar, R.drawable.baseline_delete_24, LocaleController.getString("Delete", R.string.Delete)); } if (!isPulledDown) { otherItem.hideSubItem(gallery_menu_save); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java index 33bcd37aa..be75c6d23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java @@ -60,7 +60,6 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.HeaderCell; @@ -605,56 +604,14 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente @Override public void didFindQr(String text) { - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); - - boolean isUrl = false; - try { - HttpUrl.parse(text); - - isUrl = true; - Browser.openUrl(getParentActivity(), text); - return; - } catch (Exception ignored) { } - builder.setTitle(text); - - builder.setItems(new String[]{ - - LocaleController.getString("Copy", R.string.Copy), - LocaleController.getString("Cancel", R.string.Cancel) - - }, (v, i) -> { - - if (i == 0) { - - if (Build.VERSION.SDK_INT >= 23) { - if (getParentActivity().checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - getParentActivity().requestPermissions(new String[]{Manifest.permission.CAMERA}, 22); - return; - } - } - - CameraScanActivity.showAsSheet(ProxyListActivity.this, new CameraScanActivity.CameraScanActivityDelegate() { - - @Override - public void didFindQr(String text) { - - ProxyUtil.showLinkAlert(getParentActivity(), text); - - } - }); - - } - - }); - - showDialog(builder.create()); + AlertUtil.showCopyAlert(getParentActivity(), text); } @@ -743,9 +700,9 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente if (position >= proxyStartRow && position < proxyEndRow) { final SharedConfig.ProxyInfo info = SharedConfig.proxyList.get(position - proxyStartRow); - BottomSheet.Builder builder = new BottomSheet.Builder(context); + BottomBuilder builder = new BottomBuilder(context); - builder.setItems(new String[]{ + builder.addItems(new String[]{ info.subId == 1 ? null : LocaleController.getString("EditProxy", R.string.EditProxy), info.subId == 1 ? null : LocaleController.getString("ShareProxy", R.string.ShareProxy), @@ -763,7 +720,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente R.drawable.baseline_delete_24, R.drawable.baseline_cancel_24 - }, (v, i) -> { + }, (i, text, cell) -> { if (i == 0) { @@ -814,6 +771,8 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente } + return Unit.INSTANCE; + }); showDialog(builder.create()); @@ -882,62 +841,26 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente } else { + if (Build.VERSION.SDK_INT >= 23) { + if (getParentActivity().checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.CAMERA}, 22); + return Unit.INSTANCE; + } + } + CameraScanActivity.showAsSheet(this, new CameraScanActivity.CameraScanActivityDelegate() { @Override public void didFindQr(String text) { - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); - - boolean isUrl = false; - try { - HttpUrl.parse(text); - - isUrl = true; - Browser.openUrl(getParentActivity(), text); - return; - } catch (Exception ignored) { } - builder.setTitle(text); - - builder.setItems(new String[]{ - - LocaleController.getString("Copy", R.string.Copy), - LocaleController.getString("Cancel", R.string.Cancel) - - }, (v, i) -> { - - if (i == 0) { - - if (Build.VERSION.SDK_INT >= 23) { - if (getParentActivity().checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - getParentActivity().requestPermissions(new String[]{Manifest.permission.CAMERA}, 22); - return; - } - } - - CameraScanActivity.showAsSheet(ProxyListActivity.this, new CameraScanActivity.CameraScanActivityDelegate() { - - @Override - public void didFindQr(String text) { - - ProxyUtil.showLinkAlert(getParentActivity(), text); - - } - }); - - } - - }); - - showDialog(builder.create()); - + AlertUtil.showCopyAlert(getParentActivity(), text); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java index 23430f3c6..caf128378 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java @@ -39,6 +39,9 @@ import android.widget.EditText; import android.widget.FrameLayout; import android.widget.TextView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; @@ -77,9 +80,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class WallpapersListActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private int rowCount; @@ -532,7 +532,7 @@ public class WallpapersListActivity extends BaseFragment implements Notification selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); - actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); + actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.baseline_forward_24, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.baseline_delete_24, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); selectedWallPapers.clear(); diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/BottomBuilder.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/BottomBuilder.kt index 28fddee9e..4f5ee9c12 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/BottomBuilder.kt +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/BottomBuilder.kt @@ -14,7 +14,6 @@ import org.telegram.ui.Cells.HeaderCell import org.telegram.ui.Cells.RadioButtonCell import org.telegram.ui.Cells.TextCell import org.telegram.ui.Cells.TextCheckCell -import org.telegram.ui.Components.CheckBoxSquare import org.telegram.ui.Components.LayoutHelper import java.util.* @@ -23,10 +22,9 @@ class BottomBuilder(val ctx: Context) { val builder = BottomSheet.Builder(ctx, true) private val rootView = LinearLayout(ctx).apply { - orientation = LinearLayout.VERTICAL - } + private val rtl = (if (LocaleController.isRTL) Gravity.RIGHT else Gravity.LEFT) private val _root = LinearLayout(ctx).apply { @@ -51,7 +49,7 @@ class BottomBuilder(val ctx: Context) { this@BottomBuilder.rootView.addView(this, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.LEFT or Gravity.BOTTOM)) - addView(rightButtonsView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP or Gravity.RIGHT)); + addView(rightButtonsView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP or Gravity.RIGHT)) } @@ -62,7 +60,6 @@ class BottomBuilder(val ctx: Context) { LinearLayout(ctx).apply { orientation = LinearLayout.HORIZONTAL - weightSum = 1F } @@ -224,7 +221,6 @@ class BottomBuilder(val ctx: Context) { } - @JvmOverloads fun addCancelItem() { addItem(LocaleController.getString("Cancel", R.string.Cancel), R.drawable.baseline_cancel_24) {} @@ -260,55 +256,37 @@ class BottomBuilder(val ctx: Context) { setPadding(AndroidUtilities.dp(18f), 0, AndroidUtilities.dp(18f), 0) setText(text) typeface = AndroidUtilities.getTypeface("fonts/rmedium.ttf") - (if (left) buttonsView else rightButtonsView).addView(this, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP or Gravity.LEFT)) + (if (left) buttonsView else rightButtonsView).addView(this, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, rtl)) setOnClickListener { if (!noAutoDismiss) dismiss();listener(this) } } } - fun addItem(): TextCell { - - return TextCell(ctx).apply { - - this@BottomBuilder.rootView.addView(this, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT or Gravity.TOP)) - - } - - } - @JvmOverloads fun addItem(text: String, icon: Int = 0, red: Boolean = false, listener: ((cell: TextCell) -> Unit)?): TextCell { return TextCell(ctx).apply { - textView.setGravity(Gravity.LEFT) - background = Theme.getSelectorDrawable(false) - setTextAndIcon(text, icon, false) setOnClickListener { - dismiss() - listener?.invoke(this) - } if (red) { - setColors("key_dialogTextRed2", "key_dialogTextRed2") - } - this@BottomBuilder.rootView.addView(this, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT or Gravity.TOP)) + this@BottomBuilder.rootView.addView(this, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, rtl)) } } - fun addItems(text: Array, icon: Array?, listener: (index: Int, text: String, cell: TextCell) -> Unit): List { + fun addItems(text: Array, icon: IntArray?, listener: (index: Int, text: String, cell: TextCell) -> Unit): List { val list = mutableListOf() @@ -339,7 +317,7 @@ class BottomBuilder(val ctx: Context) { isFocusable = true setBackgroundDrawable(null) - this@BottomBuilder.rootView.addView(this, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, -2, if (LocaleController.isRTL) Gravity.RIGHT else Gravity.LEFT, AndroidUtilities.dp(6F), 0, 0, 0)) + this@BottomBuilder.rootView.addView(this, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, -2, rtl, AndroidUtilities.dp(6F), 0, 0, 0)) } diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java index 5e129b83c..71e7e15ad 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java @@ -135,6 +135,7 @@ public class NekoConfig { public static boolean avatarBackgroundBlur; public static boolean avatarBackgroundDarken; + public static boolean disableTrending; public static String getOpenPGPAppName() { @@ -288,6 +289,7 @@ public class NekoConfig { sendCommentAfterForward = preferences.getBoolean("sendCommentAfterForward", true); increaseVoiceMessageQuality = preferences.getBoolean("increaseVoiceMessageQuality", true); acceptSecretChat = preferences.getBoolean("acceptSecretChat", true); + disableTrending = preferences.getBoolean("disableTrending", true); } @@ -731,13 +733,16 @@ public class NekoConfig { public static void toggleAcceptSecretChat() { preferences.edit().putBoolean("acceptSecretChat", acceptSecretChat = !acceptSecretChat).apply(); - } public static void setTabletMode(int mode) { preferences.edit().putInt("tabletMode", tabletMode = mode).apply(); } + public static void toggleDisableTrending() { + preferences.edit().putBoolean("disableTrending", disableTrending = !disableTrending).apply(); + } + private static final String EMOJI_FONT_AOSP = "NotoColorEmoji.ttf"; public static Typeface getSystemEmojiTypeface() { diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java index 7b1b1938c..42a47c4b8 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoChatSettingsActivity.java @@ -72,8 +72,9 @@ public class NekoChatSettingsActivity extends BaseFragment implements Notificati private int useChatAttachMediaMenuRow; private int disableLinkPreviewByDefaultRow; private int sendCommentAfterForwardRow; - private int disableProximityEventsRow; + private int disableTrendingRow; + private int mapPreviewRow; private int messageMenuRow; private int chat2Row; @@ -251,6 +252,11 @@ public class NekoChatSettingsActivity extends BaseFragment implements Notificati if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(NekoConfig.disableProximityEvents); } + } else if (position == disableTrendingRow) { + NekoConfig.toggleDisableTrending(); + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(NekoConfig.disableTrending); + } } }); @@ -279,14 +285,16 @@ public class NekoChatSettingsActivity extends BaseFragment implements Notificati disablePhotoSideActionRow = rowCount++; hideKeyboardOnChatScrollRow = rowCount++; - disableVibrationRow = rowCount ++; - skipOpenLinkConfirmRow = rowCount ++; + disableVibrationRow = rowCount++; + skipOpenLinkConfirmRow = rowCount++; rearVideoMessagesRow = rowCount++; confirmAVRow = rowCount++; - useChatAttachMediaMenuRow = rowCount ++; - disableLinkPreviewByDefaultRow = rowCount ++; - sendCommentAfterForwardRow = rowCount ++; - disableProximityEventsRow = rowCount ++; + useChatAttachMediaMenuRow = rowCount++; + disableLinkPreviewByDefaultRow = rowCount++; + sendCommentAfterForwardRow = rowCount++; + disableProximityEventsRow = rowCount++; + disableTrendingRow = rowCount++; + mapPreviewRow = rowCount++; messageMenuRow = rowCount++; chat2Row = rowCount++; @@ -626,6 +634,8 @@ public class NekoChatSettingsActivity extends BaseFragment implements Notificati textCell.setTextAndCheck(LocaleController.getString("DisableVibration", R.string.DisableVibration), NekoConfig.disableVibration, true); } else if (position == disableProximityEventsRow) { textCell.setTextAndCheck(LocaleController.getString("DisableProximityEvents", R.string.DisableProximityEvents), NekoConfig.disableProximityEvents, true); + } else if (position == disableTrendingRow) { + textCell.setTextAndCheck(LocaleController.getString("DisableTrending", R.string.DisableTrending), NekoConfig.disableTrending, true); } break; } diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/AlertUtil.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/AlertUtil.kt index 06462cb71..6115a6053 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/AlertUtil.kt +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/AlertUtil.kt @@ -60,7 +60,10 @@ object AlertUtil { fun showToast(e: Throwable) = showToast(e.message ?: e.javaClass.simpleName) @JvmStatic - fun showToast(e: TLRPC.TL_error) = showToast("${e.code}: ${e.text}") + fun showToast(e: TLRPC.TL_error?) { + if (e == null) return + showToast("${e.code}: ${e.text}") + } @JvmStatic fun showToast(text: String) = UIUtil.runOnUIThread(Runnable { diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/ProxyUtil.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/ProxyUtil.kt index 39b9c877f..3a696368f 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/ProxyUtil.kt +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/utils/ProxyUtil.kt @@ -16,7 +16,6 @@ import android.os.Environment import android.util.Base64 import android.view.Gravity import android.view.View -import android.view.WindowManager import android.widget.ImageView import android.widget.LinearLayout import android.widget.Toast @@ -34,7 +33,8 @@ import com.v2ray.ang.V2RayConfig.VMESS_PROTOCOL import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.telegram.messenger.* import org.telegram.messenger.browser.Browser -import org.telegram.ui.ActionBar.BottomSheet +import tw.nekomimi.nekogram.BottomBuilder +import tw.nekomimi.nekogram.utils.AlertUtil.showToast import java.io.File import java.net.NetworkInterface import java.util.* @@ -134,7 +134,7 @@ object ProxyUtil { error = true - AlertUtil.showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink) + ": ${it.message ?: it.javaClass.simpleName}") + showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink) + ": ${it.message ?: it.javaClass.simpleName}") } @@ -167,7 +167,7 @@ object ProxyUtil { error = true - AlertUtil.showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink) + ": ${it.message ?: it.javaClass.simpleName}") + showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink) + ": ${it.message ?: it.javaClass.simpleName}") } @@ -183,7 +183,7 @@ object ProxyUtil { if (proxies.isNullOrEmpty()) { - if (!error) AlertUtil.showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink)) + if (!error) showToast(LocaleController.getString("BrokenLink", R.string.BrokenLink)) return @@ -255,7 +255,7 @@ object ProxyUtil { } else { - AlertUtil.showToast("${LocaleController.getString("BrokenLink", R.string.BrokenLink)}: ${it.message}") + showToast("${LocaleController.getString("BrokenLink", R.string.BrokenLink)}: ${it.message}") } @@ -386,7 +386,9 @@ object ProxyUtil { setOnLongClickListener { - BottomSheet.Builder(ctx).setItems(arrayOf( + val builder = BottomBuilder(ctx) + + builder.addItems(arrayOf( LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Cancel", R.string.Cancel) @@ -396,7 +398,7 @@ object ProxyUtil { R.drawable.baseline_image_24, R.drawable.baseline_cancel_24 - )) { _, i -> + )) { i, _, _ -> if (i == 0) { @@ -404,7 +406,7 @@ object ProxyUtil { getOwnerActivity(ctx).requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 4) - return@setItems + return@addItems } @@ -423,16 +425,18 @@ object ProxyUtil { } AndroidUtilities.addMediaToGallery(saveTo.path) - AlertUtil.showToast(LocaleController.getString("PhotoSavedHint", R.string.PhotoSavedHint)) + showToast(LocaleController.getString("PhotoSavedHint", R.string.PhotoSavedHint)) }.onFailure { FileLog.e(it) - AlertUtil.showToast(it) + showToast(it) } } - }.show() + } + + builder.show() return@setOnLongClickListener true @@ -494,40 +498,45 @@ object ProxyUtil { } catch (e: Throwable) { - AlertUtil.showToast(LocaleController.getString("NoQrFound", R.string.NoQrFound)) + showToast(LocaleController.getString("NoQrFound", R.string.NoQrFound)) } } @JvmStatic - fun showLinkAlert(ctx: Activity, text: String) { + @JvmOverloads + fun showLinkAlert(ctx: Activity, text: String, tryInternal: Boolean = true) { - val builder = BottomSheet.Builder(ctx) + val builder = BottomBuilder(ctx) - var isUrl = false - - runCatching { - text.replace("tg://", "https://t.me/").toHttpUrlOrNull()!! - if (Browser.isInternalUrl(text, booleanArrayOf(false))) { - Browser.openUrl(ctx, text) - return + if (tryInternal) { + runCatching { + if (Browser.isInternalUrl(text, booleanArrayOf(false))) { + Browser.openUrl(ctx, text) + return + } } - isUrl = true } - builder.setTitle(text) + builder.addTitle(text) - builder.setItems(arrayOf( - if (isUrl) LocaleController.getString("Open", R.string.OpenUrlTitle) else null, + builder.addItems(arrayOf( + LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy), - LocaleController.getString("Cancel", R.string.Cancel) - )) { _, i -> - if (i == 0) { - Browser.openUrl(ctx, text) - } else if (i == 1) { - AndroidUtilities.addToClipboard(text) - Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_LONG).show() + LocaleController.getString("ShareQRCode", R.string.ShareQRCode) + ), intArrayOf( + R.drawable.baseline_open_in_browser_24, + R.drawable.baseline_content_copy_24, + R.drawable.wallet_qr + )) { which, _, _ -> + when (which) { + 0 -> Browser.openUrl(ctx, text) + 1 -> { + AndroidUtilities.addToClipboard(text) + showToast(LocaleController.getString("LinkCopied", R.string.LinkCopied)) + } + else -> showQrDialog(ctx, text) } } diff --git a/TMessagesProj/src/main/res/drawable/baseline_done_all_24.xml b/TMessagesProj/src/main/res/drawable/baseline_done_all_24.xml index be8281830..d123c0830 100644 --- a/TMessagesProj/src/main/res/drawable/baseline_done_all_24.xml +++ b/TMessagesProj/src/main/res/drawable/baseline_done_all_24.xml @@ -1,5 +1,9 @@ - - - - \ No newline at end of file + + + diff --git a/TMessagesProj/src/main/res/drawable/baseline_folder_open_24.xml b/TMessagesProj/src/main/res/drawable/baseline_folder_open_24.xml new file mode 100644 index 000000000..1c2fcc7d8 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/baseline_folder_open_24.xml @@ -0,0 +1,9 @@ + + + diff --git a/TMessagesProj/src/main/res/values/strings_nekox.xml b/TMessagesProj/src/main/res/values/strings_nekox.xml index 0831b9d68..205c12688 100644 --- a/TMessagesProj/src/main/res/values/strings_nekox.xml +++ b/TMessagesProj/src/main/res/values/strings_nekox.xml @@ -274,5 +274,6 @@ Origin Replace Use regex + Disable Trending \ No newline at end of file