From 1fe69ef568185fa60b4c1e266399a307880e98eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Baksa?= <62813600+Golbinex@users.noreply.github.com> Date: Thu, 5 Jun 2025 00:04:09 +0200 Subject: [PATCH 01/26] Monet themes PR by @Golbinex (#307) * Add monet themes * Fix theme * Update monet theme Squashed commits: https://github.com/Nekogram/Nekogram/commit/9037375957fd933f9e34d0bf485e7c6541a74aae https://github.com/Nekogram/Nekogram/commit/ccb08bf25f25920121d8f01d6106faf1a0d4610d https://github.com/Nekogram/Nekogram/commit/b36ee3bb704be314d6fa75e85196e3613f58d3e5 https://github.com/Nekogram/Nekogram/commit/a2107fcd9fc5d8d94906f35e51a646fab95db498 * Fix parse of some themes * Update monet theme * Update monet themes Squashed commits: https://github.com/Nekogram/Nekogram/commit/397126c769e657a19f1f8c8455e99e6ca8cfb63d https://github.com/Nekogram/Nekogram/commit/80e7996df654d07d8bd2c90abf41df72ef2123cc https://github.com/Nekogram/Nekogram/commit/e55c456470db803aadda7e3a4fbf35a36a21d4c6 https://github.com/Nekogram/Nekogram/commit/d8b6eb5d6bbe564b477a482dec31fcff076be997 https://github.com/Nekogram/Nekogram/commit/8d30be138e2f4e0cb0ee1a30826a3b4add4a3dd2 https://github.com/Nekogram/Nekogram/commit/204eb2093e409c75db47c908f3d19852f186619f https://github.com/Nekogram/Nekogram/commit/2f277d0529925f1333b55d6f7dca149e6fd4da5d https://github.com/Nekogram/Nekogram/commit/79160c02a407472d8ddfa9c2a4049b16c7991380 https://github.com/Nekogram/Nekogram/commit/a0dc0e6528d55923317190e8ad33c6f0ac2f9df3 https://github.com/Nekogram/Nekogram/commit/d5433fb59d72679260364533642bcf4b9f3999c2 https://github.com/Nekogram/Nekogram/commit/ef98c1429433a6f6c32829e8f2bf66ea64848f94 https://github.com/Nekogram/Nekogram/commit/6e3c35e4b021a2e70deedf744198b9d0619ad4de https://github.com/Nekogram/Nekogram/commit/c5756864f4829e9229e5edce3753bbb90a09bb0f https://github.com/Nekogram/Nekogram/commit/a2e1fa68ab18633b377e1113cf49957c77b5ba2c * Fix resetting wallpaper using monet themes * Update monet themes * Update monet themes --------- Co-authored-by: NekoInverter Co-authored-by: tehcneko <7741672-NekoInverter@users.noreply.gitlab.com> --- .../src/main/assets/monet_dark.attheme | 724 ++++++++++++++++++ .../src/main/assets/monet_light.attheme | 724 ++++++++++++++++++ .../java/org/telegram/ui/ActionBar/Theme.java | 36 +- .../java/org/telegram/ui/LaunchActivity.java | 9 + .../nekogram/helpers/MonetHelper.java | 144 ++++ TMessagesProj/src/main/res/values/colors.xml | 5 + 6 files changed, 1640 insertions(+), 2 deletions(-) create mode 100644 TMessagesProj/src/main/assets/monet_dark.attheme create mode 100644 TMessagesProj/src/main/assets/monet_light.attheme create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java diff --git a/TMessagesProj/src/main/assets/monet_dark.attheme b/TMessagesProj/src/main/assets/monet_dark.attheme new file mode 100644 index 00000000000..75e34cb8bf9 --- /dev/null +++ b/TMessagesProj/src/main/assets/monet_dark.attheme @@ -0,0 +1,724 @@ +actionBarActionModeDefault=n1_900 +actionBarActionModeDefaultIcon=a1_100 +actionBarActionModeDefaultSelector=n1_50 +actionBarActionModeDefaultTop=a1_100 +actionBarActionModeReaction=a1_100 +actionBarActionModeReactionText=n1_900 +actionBarActionModeReactionDot=n1_600 +actionBarBrowser=n1_900 +actionBarDefault=n1_900 +actionBarDefaultArchived=n1_900 +actionBarDefaultArchivedIcon=a1_200 +actionBarDefaultArchivedSearch=a2_400 +actionBarDefaultArchivedSelector=n2_800 +actionBarDefaultArchivedTitle=a1_100 +actionBarDefaultIcon=a1_100 +actionBarDefaultSearch=n1_50 +actionBarDefaultSearchArchivedPlaceholder=a1_1000 +actionBarDefaultSearchPlaceholder=a1_100 +actionBarDefaultSelector=n2_800 +actionBarDefaultSubmenuBackground=n1_900 +actionBarDefaultSubmenuItem=n1_50 +actionBarDefaultSubmenuItemIcon=a1_100 +actionBarDefaultSubmenuSeparator=n1_900 +actionBarDefaultSubtitle=n1_50 +actionBarDefaultTitle=a2_0 +actionBarTabActiveText=a1_100 +actionBarTabLine=a1_100 +actionBarTabSelector=a1_100 +actionBarTabUnactiveText=n1_600 +actionBarWhiteSelector=n2_800 +avatar_actionBarIconBlue=a1_100 +avatar_actionBarSelectorBlue=a1_100 +avatar_backgroundActionBarBlue=n1_900 +avatar_backgroundArchived=n2_800 +avatar_backgroundArchivedHidden=n2_800 +avatar_backgroundBlue=n2_800 +avatar_backgroundCyan=n2_800 +avatar_backgroundGreen=n2_800 +avatar_backgroundInProfileBlue=n2_800 +avatar_backgroundOrange=n2_800 +avatar_backgroundPink=n2_800 +avatar_backgroundRed=n2_800 +avatar_backgroundSaved=n2_800 +avatar_backgroundViolet=n2_800 +avatar_background2Blue=n2_800 +avatar_background2Cyan=n2_800 +avatar_background2Green=n2_800 +avatar_background2Orange=n2_800 +avatar_background2Pink=n2_800 +avatar_background2Red=n2_800 +avatar_background2Saved=n2_800 +avatar_background2Violet=n2_800 +avatar_subtitleInProfileBlue=n1_50 +avatar_text=a1_100 +bot_loadingIcon=a1_100 +calls_callReceivedGreenIcon=monetGreenCall +calls_callReceivedRedIcon=monetRedCall +changephoneinfo_image2=a1_100 +chats_actionBackground=a1_400 +chats_actionIcon=a1_100 +chats_actionMessage=a1_200 +chats_actionPressedBackground=a2_700 +chats_archiveBackground=n2_800 +chats_archiveIcon=a3_200 +chats_archivePinBackground=a2_600 +chats_archivePullDownBackground=a2_800 +chats_archivePullDownBackgroundActive=n1_800 +chats_archiveText=a3_200 +chats_attachMessage=a1_100 +chats_date=n1_50 +chats_draft=a1_400 +chats_mentionIcon=n1_900 +chats_menuBackground=n1_900 +chats_menuItemCheck=a3_200 +chats_menuItemIcon=a1_100 +chats_menuItemText=n1_50 +chats_menuName=a1_100 +chats_menuPhone=n1_50 +chats_menuPhoneCats=n1_50 +chats_menuTopBackground=n1_900 +chats_menuTopBackgroundCats=n1_900 +chats_menuTopShadow=n1_700 +chats_menuTopShadowCats=n1_900 +chats_message=n1_300 +chats_messageArchived=n1_300 +chats_message_threeLines=n1_300 +chats_muteIcon=a1_100 +chats_name=n1_50 +chats_nameArchived=a2_300 +chats_nameMessage=a1_100 +chats_nameMessageArchived=a1_100 +chats_nameMessageArchived_threeLines=n1_200 +chats_nameMessage_threeLines=n1_200 +chats_onlineCircle=a1_200 +chats_pinnedIcon=a1_500 +chats_pinnedOverlay=n1_900 +chats_secretIcon=a1_100 +chats_secretName=a1_100 +chats_sentCheck=a2_100 +chats_sentClock=a2_100 +chats_sentError=n1_800 +chats_sentErrorIcon=monetRedDark +chats_sentReadCheck=a2_100 +chats_tabletSelectedOverlay=268435455 +chats_tabUnreadActiveBackground=a1_100 +chats_tabUnreadUnactiveBackground=n1_600 +chats_unreadCounter=a1_100 +chats_unreadCounterMuted=a2_600 +chats_unreadCounterText=n1_900 +chats_verifiedBackground=a1_100 +chats_verifiedCheck=n1_900 +chat_addContact=a1_100 +chat_adminSelectedText=n1_50 +chat_adminText=n2_50 +chat_attachActiveTab=a1_100 +chat_attachAudioBackground=a1_500 +chat_attachAudioText=a1_100 +chat_attachCheckBoxBackground=a1_200 +chat_attachCheckBoxCheck=n1_900 +chat_attachContactBackground=a1_500 +chat_attachContactText=a1_100 +chat_attachEmptyImage=a1_100 +chat_attachIcon=a1_50 +chat_attachFileBackground=a1_500 +chat_attachFileText=a1_100 +chat_attachGalleryBackground=a1_500 +chat_attachGalleryText=a1_100 +chat_attachLocationBackground=a1_500 +chat_attachLocationText=a1_100 +chat_attachPermissionImage=a1_200 +chat_attachPermissionMark=monetRedDark +chat_attachPermissionText=a1_200 +chat_attachPhotoBackground=333639417 +chat_attachPollBackground=a1_500 +chat_attachPollText=a1_100 +chat_attachUnactiveTab=n1_600 +chat_BlurAlpha=-1694498816 +chat_BlurAlphaSlow=-1694498816 +chat_botButtonText=a1_100 +chat_botKeyboardButtonBackground=n1_500 +chat_botKeyboardButtonBackgroundPressed=n1_800 +chat_botKeyboardButtonText=n1_50 +chat_botSwitchToInlineText=n1_50 +chat_editMediaButton=a1_100 +chat_emojiBottomPanelIcon=a2_400 +chat_emojiPanelBackground=n1_900 +chat_emojiPanelBackspace=a2_300 +chat_emojiPanelEmptyText=n1_50 +chat_emojiPanelIcon=a2_400 +chat_emojiPanelIconSelected=a1_100 +chat_emojiPanelNewTrending=a1_100 +chat_emojiPanelShadowLine=n1_900 +chat_emojiPanelStickerPackSelector=n2_800 +chat_emojiPanelStickerPackSelectorLine=a1_100 +chat_emojiPanelStickerSetName=a2_100 +chat_emojiPanelStickerSetNameHighlight=a3_200 +chat_emojiPanelStickerSetNameIcon=a1_100 +chat_emojiPanelTrendingDescription=n1_900 +chat_emojiPanelTrendingTitle=n1_50 +chat_emojiSearchBackground=n2_800 +chat_emojiSearchIcon=a1_200 +chat_fieldOverlayText=a1_100 +chat_gifSaveHintBackground=n2_900 +chat_gifSaveHintText=a1_100 +chat_goDownButton=n2_800 +chat_goDownButtonCounter=n1_50 +chat_goDownButtonCounterBackground=n2_800 +chat_goDownButtonIcon=n1_50 +chat_inAudioCacheSeekbar=a1_100 +chat_inAudioDurationSelectedText=n1_50 +chat_inAudioDurationText=n1_50 +chat_inAudioPerfomerSelectedText=n1_500 +chat_inAudioPerfomerText=n1_500 +chat_inAudioProgress=a1_100 +chat_inAudioSeekbar=a2_300 +chat_inAudioSeekbarFill=a1_300 +chat_inAudioSeekbarSelected=a1_100 +chat_inAudioSelectedProgress=a1_100 +chat_inAudioTitleText=n1_50 +chat_inBubble=n2_800 +chat_inBubbleSelected=n2_800 +chat_inBubbleShadow=a1_100 +chat_inContactBackground=n1_900 +chat_inContactIcon=a1_100 +chat_inContactNameText=n1_50 +chat_inContactPhoneSelectedText=n1_50 +chat_inContactPhoneText=n1_50 +chat_inDownCall=monetGreenCall +chat_inFileBackground=n1_900 +chat_inFileBackgroundSelected=n1_900 +chat_inFileInfoSelectedText=n1_50 +chat_inFileInfoText=n1_50 +chat_inFileNameText=n1_50 +chat_inFileProgress=a1_100 +chat_inFileProgressSelected=a1_100 +chat_inForwardedNameText=n1_50 +chat_inInstant=a1_100 +chat_inInstantSelected=a1_100 +chat_inlineResultIcon=a1_100 +chat_inLoader=a1_100 +chat_inLoaderPhoto=a1_100 +chat_inLoaderSelected=a1_100 +chat_inLocationBackground=n1_900 +chat_inLocationIcon=a1_100 +chat_inMediaIcon=n1_900 +chat_inMediaIconSelected=n1_900 +chat_inMenu=a1_100 +chat_inMenuSelected=a1_100 +chat_inPollCorrectAnswer=a3_500 +chat_inPollWrongAnswer=a2_500 +chat_inPreviewInstantText=a1_100 +chat_inPreviewLine=n1_900 +chat_inPsaNameText=n1_50 +chat_inReactionButtonBackground=a1_300 +chat_inReactionButtonText=n1_50 +chat_inReactionButtonTextSelected=n1_900 +chat_inReplyLine=a1_100 +chat_inReplyMediaMessageSelectedText=n1_50 +chat_inReplyMediaMessageText=n1_50 +chat_inReplyMessageText=n1_50 +chat_inReplyNameText=n1_50 +chat_inSentClock=n1_50 +chat_inSentClockSelected=n1_50 +chat_inSiteNameText=n1_50 +chat_inTextSelectionHighlight=1237106360 +chat_inTimeSelectedText=n1_50 +chat_inTimeText=n1_50 +chat_inVenueInfoSelectedText=a1_100 +chat_inVenueInfoText=n1_50 +chat_inViaBotNameText=a1_100 +chat_inViews=n1_50 +chat_inViewsSelected=n1_50 +chat_inVoiceSeekbar=a2_200 +chat_inVoiceSeekbarFill=a1_100 +chat_inVoiceSeekbarSelected=a2_300 +chat_linkSelectBackground=n1_300 +chat_lockIcon=a1_100 +chat_mediaInfoText=a1_100 +chat_mediaLoaderPhoto=a1_700 +chat_mediaLoaderPhotoIcon=a1_100 +chat_mediaLoaderPhotoIconSelected=a1_100 +chat_mediaLoaderPhotoSelected=a1_700 +chat_mediaMenu=a1_100 +chat_mediaProgress=a1_100 +chat_mediaSentCheck=n1_50 +chat_mediaSentClock=n1_50 +chat_mediaTimeBackground=a1_600 +chat_mediaTimeText=n1_50 +chat_mediaViews=n1_50 +chat_messageLinkIn=a3_100 +chat_messageLinkOut=a3_500 +chat_messagePanelBackground=n1_900 +chat_messagePanelCancelInlineBot=a1_100 +chat_messagePanelCursor=a1_100 +chat_messagePanelHint=n1_300 +chat_messagePanelIcons=a2_200 +chat_messagePanelSend=a2_200 +chat_messagePanelShadow=n1_900 +chat_messagePanelText=n1_50 +chat_messagePanelVoiceBackground=a1_400 +chat_messagePanelVoiceDelete=a1_100 +chat_messagePanelVoiceDuration=a1_100 +chat_messagePanelVoicePressed=n1_0 +chat_messageTextIn=n1_50 +chat_messageTextOut=n1_800 +chat_muteIcon=a1_100 +chat_outAdminSelectedText=n1_500 +chat_outAdminText=n1_500 +chat_outAudioCacheSeekbar=n1_900 +chat_outAudioDurationSelectedText=n1_900 +chat_outAudioDurationText=n1_900 +chat_outAudioPerfomerSelectedText=n1_900 +chat_outAudioPerfomerText=n1_900 +chat_outAudioProgress=n1_900 +chat_outAudioSeekbar=n1_400 +chat_outAudioSeekbarFill=a1_600 +chat_outAudioSeekbarSelected=n1_900 +chat_outAudioSelectedProgress=n1_900 +chat_outAudioTitleText=n1_900 +chat_outBubble=a1_100 +chat_outBubbleGradient=a1_100 +chat_outBubbleGradient2=a1_100 +chat_outBubbleGradient3=a1_200 +chat_outBubbleGradientAnimated=0 +chat_outBubbleGradientSelectedOverlay=a1_100 +chat_outBubbleSelected=a1_100 +chat_outBubbleShadow=n2_800 +chat_outContactBackground=n1_900 +chat_outContactIcon=n1_900 +chat_outContactNameText=n1_900 +chat_outContactPhoneSelectedText=n1_900 +chat_outContactPhoneText=n1_900 +chat_outFileBackground=n1_900 +chat_outFileBackgroundSelected=a1_100 +chat_outFileInfoSelectedText=n1_900 +chat_outFileInfoText=n1_900 +chat_outFileNameText=n1_900 +chat_outFileProgress=n1_900 +chat_outFileProgressSelected=n1_900 +chat_outForwardedNameText=n1_900 +chat_outInstant=n1_900 +chat_outInstantSelected=n1_900 +chat_outLinkSelectBackground=n1_400 +chat_outLoader=n1_900 +chat_outLoaderSelected=n1_900 +chat_outLocationIcon=n1_900 +chat_outMediaIcon=a1_100 +chat_outMediaIconSelected=a1_100 +chat_outMenu=n1_900 +chat_outMenuSelected=n1_900 +chat_outPollCorrectAnswer=a3_500 +chat_outPollWrongAnswer=a2_500 +chat_outPreviewInstantText=n1_900 +chat_outPreviewLine=n1_900 +chat_outPsaNameText=n1_900 +chat_outReactionButtonBackground=a1_500 +chat_outReactionButtonText=n1_1000 +chat_outReactionButtonTextSelected=n1_0 +chat_outReplyLine=n1_900 +chat_outReplyMediaMessageSelectedText=n1_900 +chat_outReplyMediaMessageText=n1_900 +chat_outReplyMessageText=n1_900 +chat_outReplyNameText=n1_900 +chat_outSentCheck=a1_600 +chat_outSentCheckRead=a1_600 +chat_outSentCheckReadSelected=a1_600 +chat_outSentCheckSelected=a1_600 +chat_outSentClock=a1_600 +chat_outSentClockSelected=a1_600 +chat_outSiteNameText=n1_900 +chat_outTextSelectionCursor=a2_500 +chat_outTextSelectionHighlight=n2_400 +chat_outTimeSelectedText=n1_900 +chat_outTimeText=n1_900 +chat_outUpCall=a1_600 +chat_outVenueInfoSelectedText=n1_900 +chat_outVenueInfoText=n1_900 +chat_outViaBotNameText=n1_900 +chat_outViews=n1_900 +chat_outViewsSelected=n1_900 +chat_outVoiceSeekbar=n2_600 +chat_outVoiceSeekbarFill=n1_900 +chat_outVoiceSeekbarSelected=n1_900 +chat_previewDurationText=n1_50 +chat_previewGameText=n1_50 +chat_recordedVoiceBackground=n2_800 +chat_recordedVoiceDot=a1_100 +chat_recordedVoicePlayPause=a1_100 +chat_recordedVoiceProgress=n2_100 +chat_recordedVoiceProgressInner=a1_100 +chat_recordTime=n1_50 +chat_recordVoiceCancel=a1_100 +chat_replyPanelClose=a1_100 +chat_replyPanelIcons=a1_100 +chat_replyPanelLine=n1_900 +chat_replyPanelName=a1_100 +chat_searchPanelIcons=a1_100 +chat_searchPanelText=n1_50 +chat_secretChatStatusText=n1_50 +chat_secretTimeText=a1_0 +chat_selectedBackground=a2_700 +chat_sentError=n1_800 +chat_sentErrorIcon=monetRedDark +chat_serviceBackground=n2_800 +chat_serviceBackgroundSelected=n1_900 +chat_serviceBackgroundSelector=n1_800 +chat_serviceIcon=a1_100 +chat_serviceLink=a1_100 +chat_serviceText=a1_100 +chat_status=n1_50 +chat_stickerNameText=n1_50 +chat_stickerReplyLine=a2_200 +chat_stickerReplyMessageText=n1_50 +chat_stickerReplyNameText=a2_200 +chat_stickersHintPanel=n1_900 +chat_stickerViaBotNameText=a1_100 +chat_textSelectBackground=n2_200 +chat_TextSelectionCursor=a3_400 +chat_topPanelBackground=n1_900 +chat_topPanelClose=a1_100 +chat_topPanelLine=a1_100 +chat_topPanelMessage=a1_100 +chat_topPanelTitle=a2_200 +chat_unreadMessagesStartArrowIcon=a1_100 +chat_unreadMessagesStartBackground=n1_900 +chat_unreadMessagesStartText=a1_100 +chat_wallpaper=n1_900 +checkbox=a1_100 +checkboxCheck=n1_900 +checkboxDisabled=a2_400 +checkboxSquareBackground=a1_100 +checkboxSquareCheck=n1_900 +checkboxSquareDisabled=a1_100 +checkboxSquareUnchecked=n2_500 +color_blue=-11362305 +color_purple=-7906078 +color_red=-832444 +color_lightblue=-12814100 +color_lightgreen=-7352519 +color_yellow=-2184161 +color_green=-12729793 +color_orange=-881607 +contacts_inviteBackground=a1_100 +contacts_inviteText=a1_1000 +contextProgressInner1=a1_100 +contextProgressInner2=n1_700 +contextProgressInner3=n1_600 +contextProgressInner4=a1_100 +contextProgressOuter1=n1_900 +contextProgressOuter2=a1_200 +contextProgressOuter3=a1_200 +contextProgressOuter4=n1_900 +dialogBackground=n1_900 +dialogBackgroundGray=n1_900 +dialogButton=a1_100 +dialogButtonSelector=a1_100 +dialogCardShadow=n2_800 +dialogCameraIcon=a1_100 +dialogCheckboxSquareBackground=n1_900 +dialogCheckboxSquareCheck=n1_900 +dialogCheckboxSquareDisabled=a1_100 +dialogCheckboxSquareUnchecked=a1_100 +dialogEmptyImage=a1_50 +dialogEmptyText=a1_50 +dialogFloatingButton=a1_200 +dialogFloatingButtonPressed=a2_200 +dialogFloatingIcon=n1_900 +dialogGiftsBackground=n1_900 +dialogGiftsTabText=n1_0 +dialogGrayLine=n1_900 +dialogIcon=a1_100 +dialogInputField=n1_900 +dialogInputFieldActivated=a1_100 +dialogLineProgress=a1_100 +dialogLineProgressBackground=n2_800 +dialogLinkSelection=a1_200 +dialogRadioBackground=a1_300 +dialogRadioBackgroundChecked=a1_100 +dialogReactionMentionBackground=a3_300 +dialogRoundCheckBox=a1_200 +dialogRoundCheckBoxCheck=n1_900 +dialogScrollGlow=n1_800 +dialogSearchBackground=n1_900 +dialogSearchHint=a1_100 +dialogSearchIcon=a1_100 +dialogSearchText=n1_50 +dialogShadowLine=n1_900 +dialogSwipeRemove=a3_700 +dialogTextBlack=n1_50 +dialogTextBlue=a1_100 +dialogTextBlue2=n1_50 +dialogTextBlue4=n1_50 +dialogTextGray=n1_50 +dialogTextGray2=a1_100 +dialogTextGray3=a1_100 +dialogTextGray4=a1_100 +dialogTextHint=n1_300 +dialogTextLink=n1_50 +dialogTopBackground=n1_900 +dialog_inlineProgress=a1_100 +dialog_inlineProgressBackground=n1_900 +dialog_liveLocationProgress=a1_100 +divider=n1_900 +emptyListPlaceholder=n2_100 +fastScrollActive=a1_600 +fastScrollInactive=a1_200 +fastScrollText=n1_50 +featuredStickers_addButton=a1_100 +featuredStickers_addButtonPressed=a2_200 +featuredStickers_addedIcon=a1_100 +featuredStickers_buttonProgress=a1_200 +featuredStickers_buttonText=n1_900 +featuredStickers_removeButtonText=a3_500 +featuredStickers_unread=a1_600 +files_folderIcon=a1_50 +files_folderIconBackground=a1_500 +files_iconText=a1_100 +fill_RedNormal=monetRedCall +fill_RedDark=monetRedCall +gift_ribbon=a1_400 +gift_ribbon_soldout=a3_400 +graySection=n1_900 +groupcreate_cursor=a1_100 +groupcreate_hintText=n1_50 +groupcreate_sectionShadow=n1_0 +groupcreate_sectionText=n1_50 +groupcreate_spanBackground=a2_400 +groupcreate_spanDelete=n1_700 +groupcreate_spanText=n1_900 +inappPlayerBackground=n1_900 +inappPlayerClose=n1_50 +inappPlayerPerformer=n1_0 +inappPlayerPlayPause=a1_300 +inappPlayerTitle=n1_50 +iv_ab_progress=a1_300 +iv_background=n1_900 +iv_backgroundGray=n1_800 +iv_navigationBackground=n1_900 +key_chat_messagePanelVoiceLock=a1_100 +key_chat_messagePanelVoiceLockBackground=n1_800 +key_chat_messagePanelVoiceLockShadow=n2_900 +key_graySectionText=a1_200 +key_player_progressCachedBackground=a2_300 +key_sheet_other=a1_100 +key_sheet_scrollUp=a1_100 +listSelectorSDK21=350681087 +location_actionActiveIcon=a1_300 +location_actionBackground=n1_900 +location_actionIcon=a1_300 +location_actionPressedBackground=n1_900 +location_liveLocationProgress=a1_100 +location_placeLocationBackground=n1_900 +location_sendLiveLocationBackground=a1_300 +location_sendLiveLocationIcon=a1_0 +location_sendLiveLocationText=a2_200 +location_sendLocationBackground=a1_300 +location_sendLocationIcon=a1_0 +location_sendLocationText=a2_200 +login_progressInner=a1_700 +login_progressOuter=a1_300 +passport_authorizeBackground=n1_900 +passport_authorizeBackgroundSelected=n1_900 +passport_authorizeText=n1_50 +picker_badge=n1_50 +picker_badgeText=n1_900 +picker_disabledButton=a1_100 +picker_enabledButton=a1_100 +player_actionBarItems=a1_100 +player_actionBarSelector=n2_800 +player_actionBarSubtitle=n1_50 +player_actionBarTitle=n1_50 +player_background=n1_900 +player_button=a1_100 +player_buttonActive=a1_100 +player_progress=a1_100 +player_progressBackground=a2_300 +player_time=a1_100 +premiumCoinGradient1=a1_300 +premiumCoinGradient2=a1_300 +premiumGradient0=a1_300 +premiumGradient1=a1_300 +premiumGradient2=a1_300 +premiumGradient3=a3_300 +premiumGradient4=a3_300 +premiumGradientBackground1=a3_400 +premiumGradientBackground2=a1_400 +premiumGradientBackground3=a3_400 +premiumGradientBackground4=a3_400 +premiumGradientBackgroundOverlay=n1_0 +premiumGradientBottomSheet1=a3_500 +premiumGradientBottomSheet2=a2_500 +premiumGradientBottomSheet3=a1_500 +premiumStarGradient1=n1_0 +premiumStarGradient2=n1_50 +premiumStartSmallStarsColor=n1_0 +premiumStartSmallStarsColor2=n1_50 +profile_actionBackground=n2_800 +profile_actionIcon=a1_100 +profile_actionPressedBackground=a1_100 +profile_creatorIcon=a1_100 +profile_status=n1_50 +profile_tabSelectedLine=a1_200 +profile_tabSelectedText=a1_200 +profile_tabSelector=n1_900 +profile_tabText=n1_300 +profile_title=n1_50 +profile_verifiedBackground=n1_50 +profile_verifiedCheck=n1_900 +progressCircle=a1_100 +radioBackground=a1_100 +radioBackgroundChecked=a1_100 +reactionStarSelector=n1_900 +returnToCallBackground=n1_900 +returnToCallMutedBackground=n1_300 +returnToCallText=a1_100 +sessions_devicesImage=a1_600 +sharedMedia_linkPlaceholder=a1_100 +sharedMedia_linkPlaceholderText=n1_900 +sharedMedia_photoPlaceholder=n2_800 +sharedMedia_startStopLoadIcon=a1_100 +statisticChartActiveLine=a1_400 +statisticChartActivePickerChart=a1_400 +statisticChartBackZoomColor=a1_100 +statisticChartChevronColor=a1_100 +statisticChartHintLine=a1_100 +statisticChartInactivePickerChart=333639417 +statisticChartLineEmpty=n1_800 +statisticChartLine_blue=a1_400 +statisticChartLine_cyan=a2_600 +statisticChartLine_golden=a1_500 +statisticChartLine_green=a1_700 +statisticChartLine_indigo=a1_200 +statisticChartLine_lightblue=a3_200 +statisticChartLine_lightgreen=a3_700 +statisticChartLine_orange=a3_500 +statisticChartLine_purple=a2_400 +statisticChartLine_red=a3_300 +statisticChartRipple=a1_800 +statisticChartSignature=a1_100 +statisticChartSignatureAlpha=a1_100 +stickers_menu=a1_100 +stickers_menuSelector=n2_700 +stories_circle_closeFriends1=a3_100 +stories_circle_closeFriends2=a3_300 +stories_circle_dialog1=a1_100 +stories_circle_dialog2=a1_300 +stories_circle1=a1_100 +stories_circle2=a1_300 +switch2Track=n2_500 +switch2TrackChecked=a1_100 +switchTrack=n2_500 +switchTrackBlue=a1_100 +switchTrackBlueChecked=a1_100 +switchTrackBlueSelector=a1_100 +switchTrackBlueSelectorChecked=a1_100 +switchTrackBlueThumb=a1_100 +switchTrackBlueThumbChecked=n1_900 +switchTrackChecked=a1_300 +table_background=n1_800 +table_border=n1_300 +text_RedRegular=monetRedDark +text_RedBold=monetRedDark +topics_unreadCounter=a1_100 +topics_unreadCounterMuted=a2_600 +undo_background=n2_800 +undo_cancelColor=a1_100 +undo_infoColor=a1_100 +voipgroup_actionBar=n1_900 +voipgroup_actionBarItems=n1_0 +voipgroup_actionBarItemsSelector=n1_700 +voipgroup_actionBarUnscrolled=n1_900 +voipgroup_checkMenu=a1_200 +voipgroup_connectingProgress=a2_100 +voipgroup_dialogBackground=n1_900 +voipgroup_disabledButton=n2_800 +voipgroup_disabledButtonActive=n2_800 +voipgroup_disabledButtonActiveScrolled=n2_800 +voipgroup_inviteMembersBackground=n1_900 +voipgroup_lastSeenText=n1_200 +voipgroup_lastSeenTextUnscrolled=n1_200 +voipgroup_leaveButton=a3_300 +voipgroup_leaveButtonScrolled=a3_200 +voipgroup_leaveCallMenu=a1_100 +voipgroup_listeningText=a2_300 +voipgroup_listSelector=n1_700 +voipgroup_listViewBackground=n2_800 +voipgroup_listViewBackgroundUnscrolled=n2_800 +voipgroup_muteButton=a1_500 +voipgroup_muteButton2=a2_300 +voipgroup_muteButton3=a1_300 +voipgroup_mutedByAdminGradient=a3_300 +voipgroup_mutedByAdminGradient2=a3_200 +voipgroup_mutedByAdminGradient3=a3_400 +voipgroup_mutedByAdminIcon=a3_400 +voipgroup_mutedByAdminMuteButton=a3_300 +voipgroup_mutedByAdminMuteButtonDisabled=a3_600 +voipgroup_mutedIcon=a2_400 +voipgroup_mutedIconUnscrolled=a2_400 +voipgroup_nameText=n1_0 +voipgroup_overlayAlertGradientMuted=a2_400 +voipgroup_overlayAlertGradientMuted2=a2_200 +voipgroup_overlayAlertGradientUnmuted=a1_400 +voipgroup_overlayAlertGradientUnmuted2=a1_200 +voipgroup_overlayAlertMutedByAdmin=a3_300 +voipgroup_overlayAlertMutedByAdmin2=a3_100 +voipgroup_overlayBlue1=a2_400 +voipgroup_overlayBlue2=a2_200 +voipgroup_overlayGreen1=a1_400 +voipgroup_overlayGreen2=a1_200 +voipgroup_rtmpButton=n2_800 +voipgroup_scrollUp=a1_400 +voipgroup_searchBackground=n2_700 +voipgroup_searchPlaceholder=n2_200 +voipgroup_searchText=n1_0 +voipgroup_soundButton=a3_400 +voipgroup_soundButton2=a1_400 +voipgroup_soundButtonActive=a3_400 +voipgroup_soundButtonActive2=a1_400 +voipgroup_soundButtonActive2Scrolled=a1_400 +voipgroup_soundButtonActiveScrolled=a3_400 +voipgroup_speakingText=a1_100 +voipgroup_topPanelBlue1=n2_600 +voipgroup_topPanelBlue2=n2_300 +voipgroup_topPanelGray=n1_900 +voipgroup_topPanelGreen1=a1_400 +voipgroup_topPanelGreen2=a1_600 +voipgroup_unmuteButton=a2_500 +voipgroup_unmuteButton2=a2_600 +voipgroup_windowBackgroundWhiteInputField=n1_0 +voipgroup_windowBackgroundWhiteInputFieldActivated=n1_0 +windowBackgroundChecked=n1_900 +windowBackgroundCheckText=n1_50 +windowBackgroundGray=n1_900 +windowBackgroundGrayShadow=n1_900 +windowBackgroundUnchecked=n1_900 +windowBackgroundWhite=n1_900 +windowBackgroundWhiteBlackText=n1_50 +windowBackgroundWhiteBlueButton=a1_100 +windowBackgroundWhiteBlueHeader=a1_100 +windowBackgroundWhiteBlueIcon=a1_100 +windowBackgroundWhiteBlueText=n1_50 +windowBackgroundWhiteBlueText2=a2_200 +windowBackgroundWhiteBlueText3=a2_200 +windowBackgroundWhiteBlueText4=a2_200 +windowBackgroundWhiteBlueText5=a2_200 +windowBackgroundWhiteBlueText6=a2_200 +windowBackgroundWhiteBlueText7=a2_200 +windowBackgroundWhiteGrayIcon=a1_100 +windowBackgroundWhiteGrayText=n1_200 +windowBackgroundWhiteGrayText2=n1_200 +windowBackgroundWhiteGrayText3=n1_200 +windowBackgroundWhiteGrayText4=n1_200 +windowBackgroundWhiteGrayText5=n1_200 +windowBackgroundWhiteGrayText6=n1_200 +windowBackgroundWhiteGrayText7=n1_200 +windowBackgroundWhiteGrayText8=n1_200 +windowBackgroundWhiteGreenText=n1_50 +windowBackgroundWhiteGreenText2=n1_50 +windowBackgroundWhiteHintText=n1_50 +windowBackgroundWhiteInputField=a1_200 +windowBackgroundWhiteInputFieldActivated=a1_100 +windowBackgroundWhiteLinkSelection=n1_600 +windowBackgroundWhiteLinkText=a3_100 +windowBackgroundWhiteValueText=a1_100 diff --git a/TMessagesProj/src/main/assets/monet_light.attheme b/TMessagesProj/src/main/assets/monet_light.attheme new file mode 100644 index 00000000000..ff091beb8ba --- /dev/null +++ b/TMessagesProj/src/main/assets/monet_light.attheme @@ -0,0 +1,724 @@ +actionBarActionModeDefault=n1_50 +actionBarActionModeDefaultIcon=a1_600 +actionBarActionModeDefaultSelector=n1_50 +actionBarActionModeDefaultTop=a1_600 +actionBarActionModeReaction=a1_200 +actionBarActionModeReactionText=n1_900 +actionBarActionModeReactionDot=n1_400 +actionBarBrowser=n1_50 +actionBarDefault=n1_50 +actionBarDefaultArchived=n1_50 +actionBarDefaultArchivedIcon=a1_600 +actionBarDefaultArchivedSearch=a2_200 +actionBarDefaultArchivedSelector=n2_800 +actionBarDefaultArchivedTitle=a1_600 +actionBarDefaultIcon=a1_600 +actionBarDefaultSearch=a1_1000 +actionBarDefaultSearchArchivedPlaceholder=a1_0 +actionBarDefaultSearchPlaceholder=a1_600 +actionBarDefaultSelector=n2_800 +actionBarDefaultSubmenuBackground=n1_50 +actionBarDefaultSubmenuItem=a1_1000 +actionBarDefaultSubmenuItemIcon=a1_600 +actionBarDefaultSubmenuSeparator=n1_50 +actionBarDefaultSubtitle=a1_1000 +actionBarDefaultTitle=a1_1000 +actionBarTabActiveText=a1_600 +actionBarTabLine=a1_600 +actionBarTabSelector=a1_700 +actionBarTabUnactiveText=a2_800 +actionBarWhiteSelector=n2_800 +avatar_actionBarIconBlue=n1_1000 +avatar_actionBarSelectorBlue=a1_600 +avatar_backgroundActionBarBlue=n1_50 +avatar_backgroundArchived=a1_600 +avatar_backgroundArchivedHidden=a1_600 +avatar_backgroundBlue=a1_600 +avatar_backgroundCyan=a1_600 +avatar_backgroundGreen=a1_600 +avatar_backgroundInProfileBlue=a1_600 +avatar_backgroundOrange=a1_600 +avatar_backgroundPink=a1_600 +avatar_backgroundRed=a1_600 +avatar_backgroundSaved=a1_600 +avatar_backgroundViolet=a1_600 +avatar_background2Blue=a1_600 +avatar_background2Cyan=a1_600 +avatar_background2Green=a1_600 +avatar_background2Orange=a1_600 +avatar_background2Pink=a1_600 +avatar_background2Red=a1_600 +avatar_background2Saved=a1_600 +avatar_background2Violet=a1_600 +avatar_subtitleInProfileBlue=a1_1000 +avatar_text=n1_50 +bot_loadingIcon=a1_600 +calls_callReceivedGreenIcon=monetGreenCall +calls_callReceivedRedIcon=monetRedCall +changephoneinfo_image2=a1_600 +chats_actionBackground=a1_400 +chats_actionIcon=n1_1000 +chats_actionMessage=a1_800 +chats_actionPressedBackground=a1_200 +chats_archiveBackground=a1_600 +chats_archiveIcon=a3_200 +chats_archivePinBackground=a2_600 +chats_archivePullDownBackground=n1_400 +chats_archivePullDownBackgroundActive=a2_300 +chats_archiveText=a3_200 +chats_attachMessage=a1_1000 +chats_date=a1_600 +chats_draft=a1_600 +chats_mentionIcon=n1_50 +chats_menuBackground=n1_50 +chats_menuItemCheck=a3_200 +chats_menuItemIcon=a1_600 +chats_menuItemText=a1_1000 +chats_menuName=a1_600 +chats_menuPhone=a1_0 +chats_menuPhoneCats=a1_600 +chats_menuTopBackground=n1_50 +chats_menuTopBackgroundCats=n1_50 +chats_menuTopShadow=n1_800 +chats_menuTopShadowCats=n1_50 +chats_message=a1_1000 +chats_messageArchived=a1_1000 +chats_message_threeLines=a1_1000 +chats_muteIcon=a1_600 +chats_name=a1_600 +chats_nameArchived=a1_600 +chats_nameMessage=a1_600 +chats_nameMessageArchived=a1_600 +chats_nameMessageArchived_threeLines=a1_600 +chats_nameMessage_threeLines=a1_600 +chats_onlineCircle=a1_600 +chats_pinnedIcon=a1_600 +chats_pinnedOverlay=n1_50 +chats_secretIcon=a1_600 +chats_secretName=a1_600 +chats_sentCheck=a1_600 +chats_sentClock=a1_600 +chats_sentError=n1_400 +chats_sentErrorIcon=monetRedLight +chats_sentReadCheck=a1_600 +chats_tabletSelectedOverlay=n1_100 +chats_tabUnreadActiveBackground=a1_600 +chats_tabUnreadUnactiveBackground=a2_800 +chats_unreadCounter=a1_600 +chats_unreadCounterMuted=n1_400 +chats_unreadCounterText=n1_50 +chats_verifiedBackground=a1_600 +chats_verifiedCheck=n1_50 +chat_addContact=a1_600 +chat_adminSelectedText=a1_1000 +chat_adminText=a1_1000 +chat_attachActiveTab=a1_600 +chat_attachAudioBackground=a1_600 +chat_attachAudioText=a1_1000 +chat_attachCheckBoxBackground=a1_600 +chat_attachCheckBoxCheck=n1_50 +chat_attachContactBackground=a1_600 +chat_attachContactText=a1_1000 +chat_attachEmptyImage=a1_600 +chat_attachIcon=a1_50 +chat_attachFileBackground=a1_600 +chat_attachFileText=a1_1000 +chat_attachGalleryBackground=a1_600 +chat_attachGalleryText=a1_1000 +chat_attachLocationBackground=a1_600 +chat_attachLocationText=a1_1000 +chat_attachPermissionImage=a1_500 +chat_attachPermissionMark=monetRedLight +chat_attachPermissionText=a1_500 +chat_attachPhotoBackground=662406276 +chat_attachPollBackground=a1_600 +chat_attachPollText=a1_1000 +chat_attachUnactiveTab=n1_300 +chat_BlurAlphaSlow=1845499255 +chat_BlurAlpha=1845499255 +chat_botButtonText=n1_50 +chat_botKeyboardButtonBackground=a1_600 +chat_botKeyboardButtonBackgroundPressed=n1_50 +chat_botKeyboardButtonText=n1_50 +chat_botSwitchToInlineText=n1_50 +chat_editMediaButton=a1_600 +chat_emojiBottomPanelIcon=a2_300 +chat_emojiPanelBackground=n1_50 +chat_emojiPanelBackspace=a2_700 +chat_emojiPanelEmptyText=a1_600 +chat_emojiPanelIcon=a2_300 +chat_emojiPanelIconSelected=a1_600 +chat_emojiPanelNewTrending=a1_600 +chat_emojiPanelShadowLine=n1_50 +chat_emojiPanelStickerPackSelector=n2_800 +chat_emojiPanelStickerPackSelectorLine=a1_600 +chat_emojiPanelStickerSetName=a2_500 +chat_emojiPanelStickerSetNameHighlight=a3_300 +chat_emojiPanelStickerSetNameIcon=a1_600 +chat_emojiPanelTrendingDescription=a1_600 +chat_emojiPanelTrendingTitle=a1_600 +chat_emojiSearchBackground=a1_100 +chat_emojiSearchIcon=a1_600 +chat_fieldOverlayText=a1_600 +chat_gifSaveHintBackground=a1_500 +chat_gifSaveHintText=n1_50 +chat_goDownButton=a1_400 +chat_goDownButtonCounter=n1_50 +chat_goDownButtonCounterBackground=a1_400 +chat_goDownButtonIcon=n1_50 +chat_inAudioCacheSeekbar=a1_600 +chat_inAudioDurationSelectedText=a1_1000 +chat_inAudioDurationText=a1_600 +chat_inAudioPerfomerSelectedText=a1_1000 +chat_inAudioPerfomerText=a1_1000 +chat_inAudioProgress=a1_600 +chat_inAudioSeekbar=a2_300 +chat_inAudioSeekbarFill=a1_600 +chat_inAudioSeekbarSelected=a1_600 +chat_inAudioSelectedProgress=n1_300 +chat_inAudioTitleText=a1_1000 +chat_inBubble=a2_50 +chat_inBubbleSelected=a2_50 +chat_inBubbleShadow=a1_300 +chat_inContactBackground=a1_600 +chat_inContactIcon=a1_600 +chat_inContactNameText=a1_600 +chat_inContactPhoneSelectedText=n1_50 +chat_inContactPhoneText=a1_1000 +chat_inDownCall=a1_600 +chat_inFileBackground=a1_200 +chat_inFileBackgroundSelected=a1_200 +chat_inFileInfoSelectedText=a1_1000 +chat_inFileInfoText=a1_1000 +chat_inFileNameText=a1_600 +chat_inFileProgress=a1_600 +chat_inFileProgressSelected=a1_600 +chat_inForwardedNameText=a1_1000 +chat_inInstant=a1_600 +chat_inInstantSelected=a1_600 +chat_inlineResultIcon=a1_600 +chat_inLoader=a1_600 +chat_inLoaderPhoto=a1_600 +chat_inLoaderSelected=a1_600 +chat_inLocationBackground=n1_50 +chat_inLocationIcon=a1_600 +chat_inMediaIcon=n1_50 +chat_inMediaIconSelected=n1_50 +chat_inMenu=a1_600 +chat_inMenuSelected=a1_600 +chat_inPollCorrectAnswer=a3_600 +chat_inPollWrongAnswer=a2_500 +chat_inPreviewInstantText=n1_1000 +chat_inPreviewLine=a1_600 +chat_inPsaNameText=n1_900 +chat_inReactionButtonBackground=a1_600 +chat_inReactionButtonText=a1_1000 +chat_inReactionButtonTextSelected=n1_50 +chat_inReplyLine=a1_600 +chat_inReplyMediaMessageSelectedText=a1_1000 +chat_inReplyMediaMessageText=a1_1000 +chat_inReplyMessageText=a1_1000 +chat_inReplyNameText=a1_600 +chat_inSentClock=a1_1000 +chat_inSentClockSelected=a1_1000 +chat_inSiteNameText=a1_1000 +chat_inTextSelectionHighlight=1230789978 +chat_inTimeSelectedText=a1_1000 +chat_inTimeText=a1_1000 +chat_inVenueInfoSelectedText=a1_1000 +chat_inVenueInfoText=n1_50 +chat_inViaBotNameText=a1_600 +chat_inViews=a1_1000 +chat_inViewsSelected=a1_1000 +chat_inVoiceSeekbar=n1_300 +chat_inVoiceSeekbarFill=a1_600 +chat_inVoiceSeekbarSelected=n1_300 +chat_linkSelectBackground=n1_400 +chat_lockIcon=a1_600 +chat_mediaInfoText=n1_50 +chat_mediaLoaderPhoto=a1_600 +chat_mediaLoaderPhotoIcon=n1_50 +chat_mediaLoaderPhotoIconSelected=n1_50 +chat_mediaLoaderPhotoSelected=a1_600 +chat_mediaMenu=a1_600 +chat_mediaProgress=a1_600 +chat_mediaSentCheck=n1_50 +chat_mediaSentClock=n1_50 +chat_mediaTimeBackground=a1_600 +chat_mediaTimeText=n1_50 +chat_mediaViews=n1_50 +chat_messageLinkIn=a3_500 +chat_messageLinkOut=a3_200 +chat_messagePanelBackground=n1_50 +chat_messagePanelCancelInlineBot=a1_600 +chat_messagePanelCursor=a1_600 +chat_messagePanelHint=n1_300 +chat_messagePanelIcons=a1_600 +chat_messagePanelSend=a1_600 +chat_messagePanelShadow=n1_50 +chat_messagePanelText=a1_1000 +chat_messagePanelVoiceBackground=a1_600 +chat_messagePanelVoiceDelete=a1_600 +chat_messagePanelVoiceDuration=n1_50 +chat_messagePanelVoicePressed=n1_50 +chat_messageTextIn=a1_1000 +chat_messageTextOut=n1_0 +chat_muteIcon=a1_600 +chat_outAdminSelectedText=n1_0 +chat_outAdminText=n1_0 +chat_outAudioCacheSeekbar=n1_50 +chat_outAudioDurationSelectedText=n1_50 +chat_outAudioDurationText=n1_50 +chat_outAudioPerfomerSelectedText=n1_50 +chat_outAudioPerfomerText=n1_50 +chat_outAudioProgress=a1_200 +chat_outAudioSeekbar=n1_300 +chat_outAudioSeekbarFill=a1_300 +chat_outAudioSeekbarSelected=n1_300 +chat_outAudioSelectedProgress=a1_200 +chat_outAudioTitleText=n1_50 +chat_outBubble=a1_600 +chat_outBubbleGradient=a1_600 +chat_outBubbleGradient2=a1_600 +chat_outBubbleGradient3=a1_700 +chat_outBubbleGradientAnimated=0 +chat_outBubbleGradientSelectedOverlay=a1_600 +chat_outBubbleSelected=a1_600 +chat_outBubbleShadow=n2_800 +chat_outContactBackground=n1_50 +chat_outContactIcon=n1_50 +chat_outContactNameText=n1_50 +chat_outContactPhoneSelectedText=n1_50 +chat_outContactPhoneText=n1_50 +chat_outFileBackground=n1_50 +chat_outFileBackgroundSelected=a1_600 +chat_outFileInfoSelectedText=n1_50 +chat_outFileInfoText=n1_50 +chat_outFileNameText=n1_50 +chat_outFileProgress=n1_50 +chat_outFileProgressSelected=n1_50 +chat_outForwardedNameText=n1_50 +chat_outInstant=a1_10 +chat_outInstantSelected=a1_10 +chat_outLinkSelectBackground=n1_400 +chat_outLoader=n1_50 +chat_outLoaderSelected=n1_50 +chat_outLocationIcon=n1_50 +chat_outMediaIcon=a1_600 +chat_outMediaIconSelected=a1_600 +chat_outMenu=n1_50 +chat_outMenuSelected=n1_50 +chat_outPollCorrectAnswer=a3_300 +chat_outPollWrongAnswer=a2_300 +chat_outPreviewInstantText=n1_50 +chat_outPreviewLine=n1_50 +chat_outPsaNameText=n1_50 +chat_outReactionButtonBackground=a1_200 +chat_outReactionButtonText=n1_0 +chat_outReactionButtonTextSelected=n1_1000 +chat_outReplyLine=n1_50 +chat_outReplyMediaMessageSelectedText=n1_50 +chat_outReplyMediaMessageText=n1_50 +chat_outReplyMessageText=n1_50 +chat_outReplyNameText=n1_50 +chat_outSentCheck=a2_200 +chat_outSentCheckRead=a2_200 +chat_outSentCheckReadSelected=a2_200 +chat_outSentCheckSelected=a2_200 +chat_outSentClock=a2_200 +chat_outSentClockSelected=a2_200 +chat_outSiteNameText=n1_50 +chat_outTextSelectionCursor=a2_300 +chat_outTextSelectionHighlight=n1_700 +chat_outTimeSelectedText=n1_50 +chat_outTimeText=n1_50 +chat_outUpCall=a1_300 +chat_outVenueInfoSelectedText=n1_50 +chat_outVenueInfoText=n1_50 +chat_outViaBotNameText=n1_50 +chat_outViews=n1_50 +chat_outViewsSelected=n1_50 +chat_outVoiceSeekbar=n1_300 +chat_outVoiceSeekbarFill=n1_50 +chat_outVoiceSeekbarSelected=n1_300 +chat_previewDurationText=n1_50 +chat_previewGameText=n1_50 +chat_recordedVoiceBackground=a1_600 +chat_recordedVoiceDot=a1_600 +chat_recordedVoicePlayPause=a1_100 +chat_recordedVoiceProgress=n1_300 +chat_recordedVoiceProgressInner=n1_50 +chat_recordTime=a1_600 +chat_recordVoiceCancel=a1_600 +chat_replyPanelClose=a1_600 +chat_replyPanelIcons=a1_600 +chat_replyPanelLine=n1_50 +chat_replyPanelName=a1_1000 +chat_searchPanelIcons=a1_600 +chat_searchPanelText=a1_1000 +chat_secretChatStatusText=a1_600 +chat_secretTimeText=a1_0 +chat_selectedBackground=n2_100 +chat_sentError=n1_400 +chat_sentErrorIcon=monetRedLight +chat_serviceBackground=a1_600 +chat_serviceBackgroundSelected=a1_600 +chat_serviceBackgroundSelector=a1_700 +chat_serviceIcon=n1_50 +chat_serviceLink=n1_50 +chat_serviceText=n1_50 +chat_status=a1_600 +chat_stickerNameText=n1_50 +chat_stickerReplyLine=n1_50 +chat_stickerReplyMessageText=n1_50 +chat_stickerReplyNameText=n1_50 +chat_stickersHintPanel=n1_50 +chat_stickerViaBotNameText=a1_0 +chat_textSelectBackground=a1_200 +chat_TextSelectionCursor=a3_500 +chat_topPanelBackground=n1_50 +chat_topPanelClose=a1_600 +chat_topPanelLine=a1_600 +chat_topPanelMessage=a1_1000 +chat_topPanelTitle=a1_600 +chat_unreadMessagesStartArrowIcon=a1_600 +chat_unreadMessagesStartBackground=n1_50 +chat_unreadMessagesStartText=a1_1000 +chat_wallpaper=n1_50 +checkbox=a1_600 +checkboxCheck=a1_50 +checkboxDisabled=a2_200 +checkboxSquareBackground=a1_600 +checkboxSquareCheck=n1_50 +checkboxSquareDisabled=a1_600 +checkboxSquareUnchecked=n2_500 +color_blue=-13467675 +color_green=-10369198 +color_lightblue=-10966803 +color_lightgreen=-7352519 +color_orange=-881607 +color_purple=-8422925 +color_red=-2075818 +color_yellow=-1853657 +contacts_inviteBackground=n2_800 +contacts_inviteText=n1_50 +contextProgressInner1=a1_1000 +contextProgressInner2=n1_100 +contextProgressInner3=n1_600 +contextProgressInner4=a1_1000 +contextProgressOuter1=n1_50 +contextProgressOuter2=a1_400 +contextProgressOuter3=a1_200 +contextProgressOuter4=n1_50 +dialogBackground=n1_50 +dialogBackgroundGray=n1_50 +dialogButton=a1_600 +dialogButtonSelector=a1_600 +dialogCardShadow=n2_200 +dialogCameraIcon=a1_600 +dialogCheckboxSquareBackground=a1_600 +dialogCheckboxSquareCheck=n1_50 +dialogCheckboxSquareDisabled=a1_700 +dialogCheckboxSquareUnchecked=a1_600 +dialogEmptyImage=a1_900 +dialogEmptyText=a1_900 +dialogFloatingButton=a1_600 +dialogFloatingButtonPressed=a2_600 +dialogFloatingIcon=n1_50 +dialogGiftsBackground=n1_50 +dialogGiftsTabText=n1_1000 +dialogGrayLine=n1_50 +dialogIcon=a1_600 +dialogInputField=n1_50 +dialogInputFieldActivated=a1_600 +dialogLineProgress=a1_600 +dialogLineProgressBackground=a1_200 +dialogLinkSelection=a1_600 +dialogRadioBackground=a1_600 +dialogRadioBackgroundChecked=a1_600 +dialogReactionMentionBackground=a3_700 +dialogRoundCheckBox=a1_600 +dialogRoundCheckBoxCheck=n1_50 +dialogScrollGlow=n1_100 +dialogSearchBackground=n1_50 +dialogSearchHint=a1_600 +dialogSearchIcon=a1_600 +dialogSearchText=n1_900 +dialogShadowLine=n1_50 +dialogSwipeRemove=a3_700 +dialogTextBlack=a1_1000 +dialogTextBlue=a1_1000 +dialogTextBlue2=a1_600 +dialogTextBlue4=a1_600 +dialogTextGray=a1_600 +dialogTextGray2=a1_600 +dialogTextGray3=a1_600 +dialogTextGray4=a1_600 +dialogTextHint=n1_300 +dialogTextLink=a1_600 +dialogTopBackground=n1_500 +dialog_inlineProgress=a1_600 +dialog_inlineProgressBackground=n1_50 +dialog_liveLocationProgress=a1_600 +divider=n1_50 +emptyListPlaceholder=n2_800 +fastScrollActive=a1_200 +fastScrollInactive=a1_600 +fastScrollText=n1_800 +featuredStickers_addButton=a1_600 +featuredStickers_addButtonPressed=a1_600 +featuredStickers_addedIcon=a1_600 +featuredStickers_buttonProgress=a1_600 +featuredStickers_buttonText=n1_50 +featuredStickers_removeButtonText=a3_500 +featuredStickers_unread=a1_600 +files_folderIcon=a1_0 +files_folderIconBackground=a1_600 +files_iconText=a1_1000 +fill_RedNormal=monetRedCall +fill_RedDark=monetRedCall +gift_ribbon=a1_600 +gift_ribbon_soldout=a3_600 +graySection=n1_50 +groupcreate_cursor=a1_600 +groupcreate_hintText=a1_700 +groupcreate_sectionShadow=n1_0 +groupcreate_sectionText=n1_900 +groupcreate_spanBackground=a2_200 +groupcreate_spanDelete=a1_700 +groupcreate_spanText=a1_0 +inappPlayerBackground=n1_50 +inappPlayerClose=a1_1000 +inappPlayerPerformer=a1_600 +inappPlayerPlayPause=a1_600 +inappPlayerTitle=a1_1000 +iv_ab_progress=a1_700 +iv_background=n1_50 +iv_backgroundGray=n1_50 +iv_navigationBackground=n1_50 +key_chat_messagePanelVoiceLock=n1_50 +key_chat_messagePanelVoiceLockBackground=a1_500 +key_chat_messagePanelVoiceLockShadow=a2_600 +key_graySectionText=a1_600 +key_player_progressCachedBackground=a2_300 +key_sheet_other=a1_600 +key_sheet_scrollUp=a1_600 +listSelectorSDK21=251658240 +location_actionActiveIcon=a1_600 +location_actionBackground=n1_50 +location_actionIcon=a1_600 +location_actionPressedBackground=n1_50 +location_liveLocationProgress=a1_600 +location_placeLocationBackground=n1_50 +location_sendLiveLocationBackground=a1_600 +location_sendLiveLocationIcon=a1_0 +location_sendLiveLocationText=a1_600 +location_sendLocationBackground=a1_600 +location_sendLocationIcon=a1_0 +location_sendLocationText=a1_600 +login_progressInner=a1_100 +login_progressOuter=a1_700 +passport_authorizeBackground=n1_50 +passport_authorizeBackgroundSelected=n1_50 +passport_authorizeText=n1_900 +picker_badge=n1_50 +picker_badgeText=n1_900 +picker_disabledButton=a1_600 +picker_enabledButton=a1_600 +player_actionBarItems=a1_1000 +player_actionBarSelector=a1_600 +player_actionBarSubtitle=a1_600 +player_actionBarTitle=a1_1000 +player_background=n1_50 +player_button=a1_600 +player_buttonActive=a1_600 +player_progress=a1_600 +player_progressBackground=a2_300 +player_time=a1_600 +premiumCoinGradient1=a1_400 +premiumCoinGradient2=a1_400 +premiumGradient0=a1_400 +premiumGradient1=a1_400 +premiumGradient2=a1_400 +premiumGradient3=a3_400 +premiumGradient4=a3_400 +premiumGradientBackground1=a3_400 +premiumGradientBackground2=a1_400 +premiumGradientBackground3=a3_400 +premiumGradientBackground4=a3_400 +premiumGradientBackgroundOverlay=n1_0 +premiumGradientBottomSheet1=a3_200 +premiumGradientBottomSheet2=a2_200 +premiumGradientBottomSheet3=a1_200 +premiumStarGradient1=n1_0 +premiumStarGradient2=n1_50 +premiumStartSmallStarsColor=n1_0 +premiumStartSmallStarsColor2=n1_50 +profile_actionBackground=a1_600 +profile_actionIcon=n1_50 +profile_actionPressedBackground=a1_200 +profile_creatorIcon=a1_600 +profile_status=a1_1000 +profile_tabSelectedLine=a1_700 +profile_tabSelectedText=a1_700 +profile_tabSelector=a1_600 +profile_tabText=n1_500 +profile_title=a1_1000 +profile_verifiedBackground=a1_600 +profile_verifiedCheck=a1_0 +progressCircle=a1_600 +radioBackground=a1_600 +reactionStarSelector=n1_50 +radioBackgroundChecked=a1_600 +returnToCallBackground=n1_50 +returnToCallMutedBackground=n1_600 +returnToCallText=a1_1000 +sessions_devicesImage=a1_100 +sharedMedia_linkPlaceholder=a1_600 +sharedMedia_linkPlaceholderText=n1_50 +sharedMedia_photoPlaceholder=a1_600 +sharedMedia_startStopLoadIcon=a1_600 +statisticChartActiveLine=n1_50 +statisticChartActivePickerChart=a1_600 +statisticChartBackZoomColor=a1_600 +statisticChartChevronColor=a1_600 +statisticChartHintLine=a1_600 +statisticChartInactivePickerChart=662406276 +statisticChartLineEmpty=n1_50 +statisticChartLine_blue=a1_300 +statisticChartLine_cyan=a2_600 +statisticChartLine_golden=a1_500 +statisticChartLine_green=a1_700 +statisticChartLine_indigo=a2_300 +statisticChartLine_lightblue=a3_300 +statisticChartLine_lightgreen=a3_500 +statisticChartLine_orange=a3_700 +statisticChartLine_purple=a2_400 +statisticChartLine_red=a2_500 +statisticChartRipple=a1_300 +statisticChartSignature=a1_600 +statisticChartSignatureAlpha=a1_600 +stickers_menu=a1_600 +stickers_menuSelector=n2_200 +stories_circle_closeFriends1=a3_400 +stories_circle_closeFriends2=a3_600 +stories_circle_dialog1=a1_400 +stories_circle_dialog2=a1_600 +stories_circle1=a1_400 +stories_circle2=a1_600 +switch2Track=n2_500 +switch2TrackChecked=a1_700 +switchTrack=n2_500 +switchTrackBlue=a1_600 +switchTrackBlueChecked=a1_600 +switchTrackBlueSelector=a1_600 +switchTrackBlueSelectorChecked=a1_600 +switchTrackBlueThumb=n1_50 +switchTrackBlueThumbChecked=n1_50 +switchTrackChecked=a1_700 +table_background=n1_100 +table_border=n1_900 +text_RedRegular=monetRedLight +text_RedBold=monetRedLight +topics_unreadCounter=a1_600 +topics_unreadCounterMuted=n1_50 +undo_background=a1_600 +undo_cancelColor=a1_200 +undo_infoColor=n1_50 +voipgroup_actionBar=n1_900 +voipgroup_actionBarItems=n1_0 +voipgroup_actionBarItemsSelector=n1_700 +voipgroup_actionBarUnscrolled=n1_900 +voipgroup_checkMenu=a1_200 +voipgroup_connectingProgress=a2_100 +voipgroup_dialogBackground=n1_900 +voipgroup_disabledButton=n2_800 +voipgroup_disabledButtonActive=n2_800 +voipgroup_disabledButtonActiveScrolled=n2_800 +voipgroup_inviteMembersBackground=n1_900 +voipgroup_lastSeenText=n1_200 +voipgroup_lastSeenTextUnscrolled=n1_200 +voipgroup_leaveButton=a3_300 +voipgroup_leaveButtonScrolled=a3_200 +voipgroup_leaveCallMenu=a1_100 +voipgroup_listeningText=a2_300 +voipgroup_listSelector=n1_700 +voipgroup_listViewBackground=n2_800 +voipgroup_listViewBackgroundUnscrolled=n2_800 +voipgroup_muteButton=a1_500 +voipgroup_muteButton2=a2_300 +voipgroup_muteButton3=a1_300 +voipgroup_mutedByAdminGradient=a3_200 +voipgroup_mutedByAdminGradient2=a3_200 +voipgroup_mutedByAdminGradient3=a3_300 +voipgroup_mutedByAdminIcon=a3_400 +voipgroup_mutedByAdminMuteButton=a3_300 +voipgroup_mutedByAdminMuteButtonDisabled=a3_200 +voipgroup_mutedIcon=a2_400 +voipgroup_mutedIconUnscrolled=a2_400 +voipgroup_nameText=n1_0 +voipgroup_overlayAlertGradientMuted=a2_400 +voipgroup_overlayAlertGradientMuted2=a2_200 +voipgroup_overlayAlertGradientUnmuted=a1_400 +voipgroup_overlayAlertGradientUnmuted2=a1_200 +voipgroup_overlayAlertMutedByAdmin=a3_300 +kvoipgroup_overlayAlertMutedByAdmin2=a3_100 +voipgroup_overlayBlue1=a2_400 +voipgroup_overlayBlue2=a2_200 +voipgroup_overlayGreen1=a1_400 +voipgroup_overlayGreen2=a1_200 +voipgroup_rtmpButton=n2_800 +voipgroup_scrollUp=a1_400 +voipgroup_searchBackground=n2_700 +voipgroup_searchPlaceholder=n2_200 +voipgroup_searchText=n1_0 +voipgroup_soundButton=a3_400 +voipgroup_soundButton2=a1_400 +voipgroup_soundButtonActive=a3_400 +voipgroup_soundButtonActive2=a1_400 +voipgroup_soundButtonActive2Scrolled=a1_400 +voipgroup_soundButtonActiveScrolled=a3_400 +voipgroup_speakingText=a1_100 +voipgroup_topPanelBlue1=n2_50 +voipgroup_topPanelBlue2=n2_200 +voipgroup_topPanelGray=n2_50 +voipgroup_topPanelGreen1=a1_300 +voipgroup_topPanelGreen2=a1_500 +voipgroup_unmuteButton=a2_600 +voipgroup_unmuteButton2=a2_500 +voipgroup_windowBackgroundWhiteInputField=n1_0 +voipgroup_windowBackgroundWhiteInputFieldActivated=n1_0 +windowBackgroundChecked=n1_50 +windowBackgroundCheckText=a1_600 +windowBackgroundGray=n1_50 +windowBackgroundGrayShadow=n1_50 +windowBackgroundUnchecked=n1_50 +windowBackgroundWhite=n1_50 +windowBackgroundWhiteBlackText=a1_1000 +windowBackgroundWhiteBlueButton=a1_600 +windowBackgroundWhiteBlueHeader=a1_600 +windowBackgroundWhiteBlueIcon=a1_600 +windowBackgroundWhiteBlueText=a1_600 +windowBackgroundWhiteBlueText2=a1_700 +windowBackgroundWhiteBlueText3=a1_700 +windowBackgroundWhiteBlueText4=a1_700 +windowBackgroundWhiteBlueText5=a1_700 +windowBackgroundWhiteBlueText6=a1_700 +windowBackgroundWhiteBlueText7=a1_700 +windowBackgroundWhiteGrayIcon=a1_600 +windowBackgroundWhiteGrayText=n1_600 +windowBackgroundWhiteGrayText2=n1_600 +windowBackgroundWhiteGrayText3=n1_600 +windowBackgroundWhiteGrayText4=n1_600 +windowBackgroundWhiteGrayText5=n1_600 +windowBackgroundWhiteGrayText6=n1_600 +windowBackgroundWhiteGrayText7=n1_600 +windowBackgroundWhiteGrayText8=n1_600 +windowBackgroundWhiteGreenText=a1_1000 +windowBackgroundWhiteGreenText2=a1_1000 +windowBackgroundWhiteHintText=a1_1000 +windowBackgroundWhiteInputField=a1_300 +windowBackgroundWhiteInputFieldActivated=a1_600 +windowBackgroundWhiteLinkSelection=n1_200 +windowBackgroundWhiteLinkText=a3_500 +windowBackgroundWhiteValueText=a1_600 diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index 6f7ea6048ec..f21af71845d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -150,6 +150,8 @@ import java.util.Objects; import java.util.concurrent.CountDownLatch; +import tw.nekomimi.nekogram.helpers.MonetHelper; + public class Theme { public static final String DEFAULT_BACKGROUND_SLUG = "d"; @@ -2506,13 +2508,17 @@ public boolean hasAccentColors() { return defaultAccentCount != 0; } + public boolean isMonet() { + return "Monet Dark".equals(name) || "Monet Light".equals(name); + } + public boolean isDark() { if (isDark != UNKNOWN) { return isDark == DARK; } - if ("Dark Blue".equals(name) || "Night".equals(name)) { + if ("Dark Blue".equals(name) || "Night".equals(name) || "Monet Dark".equals(name)) { isDark = DARK; - } else if ("Blue".equals(name) || "Arctic Blue".equals(name) || "Day".equals(name)) { + } else if ("Blue".equals(name) || "Arctic Blue".equals(name) || "Day".equals(name) || "Monet Light".equals(name)) { isDark = LIGHT; } if (isDark == UNKNOWN) { @@ -4727,6 +4733,28 @@ public void run() { themes.add(themeInfo); themesDict.put("Night", themeInfo); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + themeInfo = new ThemeInfo(); + themeInfo.name = "Monet Light"; + themeInfo.assetName = "monet_light.attheme"; + themeInfo.previewBackgroundColor = MonetHelper.getColor("n1_50"); + themeInfo.previewInColor = MonetHelper.getColor("a1_100"); + themeInfo.previewOutColor = MonetHelper.getColor("a1_600"); + themeInfo.sortIndex = 6; + themes.add(themeInfo); + themesDict.put("Monet Light", themeInfo); + + themeInfo = new ThemeInfo(); + themeInfo.name = "Monet Dark"; + themeInfo.assetName = "monet_dark.attheme"; + themeInfo.previewBackgroundColor = MonetHelper.getColor("n1_900"); + themeInfo.previewInColor = MonetHelper.getColor("n2_800"); + themeInfo.previewOutColor = MonetHelper.getColor("a1_100"); + themeInfo.sortIndex = 7; + themes.add(themeInfo); + themesDict.put("Monet Dark", themeInfo); + } + String themesString = themeConfig.getString("themes2", null); int remoteVersion = themeConfig.getInt("remote_version", 0); @@ -4959,6 +4987,8 @@ public void run() { if (accent != null) { info.overrideWallpaper = accent.overrideWallpaper; } + } else if (info.isMonet()) { + info.loadWallpapers(themeConfig); } } if (oldEditor != null) { @@ -8123,6 +8153,8 @@ public static SparseIntArray getThemeFileValues(File file, String assetName, Str } catch (Exception ignore) { value = Utilities.parseInt(param); } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && (param.startsWith("a") || param.startsWith("n"))) { + value = MonetHelper.getColor(param.trim()); } else { value = Utilities.parseInt(param); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 7a3722c55e4..cc21e5066ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -260,6 +260,8 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import tw.nekomimi.nekogram.helpers.MonetHelper; + public class LaunchActivity extends BasePermissionsActivity implements INavigationLayout.INavigationLayoutDelegate, NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, IPipActivity { public final static String EXTRA_FORCE_NOT_INTERNAL_APPS = "force_not_internal_apps"; public final static String EXTRA_FORCE_REQUEST = "force_request"; @@ -1040,6 +1042,10 @@ public void onPreviewOpenAnimationEnd() { } } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + MonetHelper.registerReceiver(this); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { getWindow().getDecorView().addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override @@ -7093,6 +7099,9 @@ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, @Non protected void onDestroy() { isActive = false; unregisterReceiver(batteryReceiver); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + MonetHelper.unregisterReceiver(this); + } if (PhotoViewer.getPipInstance() != null) { PhotoViewer.getPipInstance().destroyPhotoViewer(); } diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java new file mode 100644 index 00000000000..b9c18cfff68 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java @@ -0,0 +1,144 @@ +package tw.nekomimi.nekogram.helpers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.os.PatternMatcher; + +import androidx.annotation.RequiresApi; + +import com.google.android.exoplayer2.util.Log; + +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; + +import java.util.HashMap; + +@RequiresApi(api = Build.VERSION_CODES.S) +public class MonetHelper { + private static final HashMap ids = new HashMap<>(); + private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED"; + private static final OverlayChangeReceiver overlayChangeReceiver = new OverlayChangeReceiver(); + + static { + ids.put("a1_0", android.R.color.system_accent1_0); + ids.put("a1_10", android.R.color.system_accent1_10); + ids.put("a1_50", android.R.color.system_accent1_50); + ids.put("a1_100", android.R.color.system_accent1_100); + ids.put("a1_200", android.R.color.system_accent1_200); + ids.put("a1_300", android.R.color.system_accent1_300); + ids.put("a1_400", android.R.color.system_accent1_400); + ids.put("a1_500", android.R.color.system_accent1_500); + ids.put("a1_600", android.R.color.system_accent1_600); + ids.put("a1_700", android.R.color.system_accent1_700); + ids.put("a1_800", android.R.color.system_accent1_800); + ids.put("a1_900", android.R.color.system_accent1_900); + ids.put("a1_1000", android.R.color.system_accent1_1000); + ids.put("a2_0", android.R.color.system_accent2_0); + ids.put("a2_10", android.R.color.system_accent2_10); + ids.put("a2_50", android.R.color.system_accent2_50); + ids.put("a2_100", android.R.color.system_accent2_100); + ids.put("a2_200", android.R.color.system_accent2_200); + ids.put("a2_300", android.R.color.system_accent2_300); + ids.put("a2_400", android.R.color.system_accent2_400); + ids.put("a2_500", android.R.color.system_accent2_500); + ids.put("a2_600", android.R.color.system_accent2_600); + ids.put("a2_700", android.R.color.system_accent2_700); + ids.put("a2_800", android.R.color.system_accent2_800); + ids.put("a2_900", android.R.color.system_accent2_900); + ids.put("a2_1000", android.R.color.system_accent2_1000); + ids.put("a3_0", android.R.color.system_accent3_0); + ids.put("a3_10", android.R.color.system_accent3_10); + ids.put("a3_50", android.R.color.system_accent3_50); + ids.put("a3_100", android.R.color.system_accent3_100); + ids.put("a3_200", android.R.color.system_accent3_200); + ids.put("a3_300", android.R.color.system_accent3_300); + ids.put("a3_400", android.R.color.system_accent3_400); + ids.put("a3_500", android.R.color.system_accent3_500); + ids.put("a3_600", android.R.color.system_accent3_600); + ids.put("a3_700", android.R.color.system_accent3_700); + ids.put("a3_800", android.R.color.system_accent3_800); + ids.put("a3_900", android.R.color.system_accent3_900); + ids.put("a3_1000", android.R.color.system_accent3_1000); + ids.put("n1_0", android.R.color.system_neutral1_0); + ids.put("n1_10", android.R.color.system_neutral1_10); + ids.put("n1_50", android.R.color.system_neutral1_50); + ids.put("n1_100", android.R.color.system_neutral1_100); + ids.put("n1_200", android.R.color.system_neutral1_200); + ids.put("n1_300", android.R.color.system_neutral1_300); + ids.put("n1_400", android.R.color.system_neutral1_400); + ids.put("n1_500", android.R.color.system_neutral1_500); + ids.put("n1_600", android.R.color.system_neutral1_600); + ids.put("n1_700", android.R.color.system_neutral1_700); + ids.put("n1_800", android.R.color.system_neutral1_800); + ids.put("n1_900", android.R.color.system_neutral1_900); + ids.put("n1_1000", android.R.color.system_neutral1_1000); + ids.put("n2_0", android.R.color.system_neutral2_0); + ids.put("n2_10", android.R.color.system_neutral2_10); + ids.put("n2_50", android.R.color.system_neutral2_50); + ids.put("n2_100", android.R.color.system_neutral2_100); + ids.put("n2_200", android.R.color.system_neutral2_200); + ids.put("n2_300", android.R.color.system_neutral2_300); + ids.put("n2_400", android.R.color.system_neutral2_400); + ids.put("n2_500", android.R.color.system_neutral2_500); + ids.put("n2_600", android.R.color.system_neutral2_600); + ids.put("n2_700", android.R.color.system_neutral2_700); + ids.put("n2_800", android.R.color.system_neutral2_800); + ids.put("n2_900", android.R.color.system_neutral2_900); + ids.put("n2_1000", android.R.color.system_neutral2_1000); + ids.put("monetRedDark", R.color.monetRedDark); + ids.put("monetRedLight", R.color.monetRedLight); + ids.put("monetRedCall", R.color.monetRedCall); + ids.put("monetGreenCall", R.color.monetGreenCall); + } + + public static int getColor(String color) { + return getColor(color, false); + } + + public static int getColor(String color, boolean amoled) { + try { + //noinspection ConstantConditions + int id = ids.getOrDefault(amoled && "n1_900".equals(color) ? "n1_1000" : color, 0); + return ApplicationLoader.applicationContext.getColor(id); + } catch (Exception e) { + Log.e("Theme", "Error loading color " + color); + e.printStackTrace(); + return 0; + } + } + + private static class OverlayChangeReceiver extends BroadcastReceiver { + + public void register(Context context) { + IntentFilter packageFilter = new IntentFilter(ACTION_OVERLAY_CHANGED); + packageFilter.addDataScheme("package"); + packageFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL); + context.registerReceiver(this, packageFilter); + } + + public void unregister(Context context) { + context.unregisterReceiver(this); + } + + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_OVERLAY_CHANGED.equals(intent.getAction())) { + if (Theme.getActiveTheme().isMonet()) { + Theme.applyTheme(Theme.getActiveTheme()); + } + } + } + } + + public static void registerReceiver(Context context) { + overlayChangeReceiver.register(context); + } + + public static void unregisterReceiver(Context context) { + overlayChangeReceiver.unregister(context); + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/colors.xml b/TMessagesProj/src/main/res/values/colors.xml index 191969b526d..67ff1040d3f 100755 --- a/TMessagesProj/src/main/res/values/colors.xml +++ b/TMessagesProj/src/main/res/values/colors.xml @@ -8,4 +8,9 @@ #d9d9d9 #8B8D8F #999999 + + #B3261E + #F2B8B5 + #4CAF50 + #EF5350 \ No newline at end of file From 109b22d7e685ca63622a9a674d50642a034c9b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Baksa?= <62813600+Golbinex@users.noreply.github.com> Date: Thu, 5 Jun 2025 00:04:41 +0200 Subject: [PATCH 02/26] UnifiedPush support PR by @Golbinex (#306) * [TF][PUSH] implemented a simple UnifiedPush support This simple implementation only triggers the networks to resume when an event is received, so Telegram can get the events by itself. This is not like the other push providers where the change information is processed by PushListenerController directly, but it still saves battery since the process disconnects from Telegram servers as soon as the updates are processed. * [MG] add a longclick listener to UnifiedPush Distributors menu This prints informations to know if UnifiedPush is working or not. * [MG] encode the url to pass to p2p.belloworld.it This is needed if urls includes query (like UP-FCM). This also means the proxy had to be a little more complex, since nginx didn't do url decoding: https://gist.github.com/drizzt/93d253bca4f64fae7df2a4544a98c08d --------- Co-authored-by: Timothy Redaelli --- TMessagesProj/build.gradle | 7 ++ TMessagesProj/src/main/AndroidManifest.xml | 9 ++ .../telegram/messenger/ApplicationLoader.java | 7 +- .../messenger/PushListenerController.java | 64 +++++++++- .../messenger/UnifiedPushReceiver.java | 109 ++++++++++++++++++ .../ui/NotificationsSettingsActivity.java | 83 +++++++++++++ TMessagesProj/src/main/res/values/strings.xml | 5 +- TMessagesProj_App/build.gradle | 6 + build.gradle | 2 + 9 files changed, 284 insertions(+), 8 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 3fca1b2bb69..936190f15ef 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -7,6 +7,12 @@ apply plugin: 'kotlin-android' repositories { mavenCentral() google() + maven { + url 'https://www.jitpack.io' + content { + includeModule 'com.github.UnifiedPush', 'android-connector' + } + } } configurations { @@ -55,6 +61,7 @@ dependencies { because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") } } + implementation 'com.github.UnifiedPush:android-connector:2.3.1' implementation 'org.osmdroid:osmdroid-android:6.1.20' } diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index 3889435ce68..48a43e8f6f3 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -639,6 +639,15 @@ e + + + + + + + + + { if (getPushProvider().hasServices()) { @@ -426,7 +425,7 @@ private void initPushServices() { } }, 1000); } - +/* private boolean checkPlayServices() { try { int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index 780c255e1bc..74b1037aa37 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -20,21 +20,26 @@ import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; +import org.unifiedpush.android.connector.UnifiedPush; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Locale; import java.util.concurrent.CountDownLatch; @Keep public class PushListenerController { public static final int PUSH_TYPE_FIREBASE = 2, + PUSH_TYPE_SIMPLE = 4, PUSH_TYPE_HUAWEI = 13; @Retention(RetentionPolicy.SOURCE) @IntDef({ PUSH_TYPE_FIREBASE, + PUSH_TYPE_SIMPLE, PUSH_TYPE_HUAWEI }) public @interface PushType {} @@ -62,7 +67,7 @@ public static void sendRegistrationToServer(@PushType int pushType, String token if (userConfig.getClientUserId() != 0) { final int currentAccount = a; if (sendStat) { - String tag = pushType == PUSH_TYPE_FIREBASE ? "fcm" : "hcm"; + String tag = pushType == PUSH_TYPE_FIREBASE ? "fcm" : (pushType == PUSH_TYPE_HUAWEI ? "hcm" : "up"); TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog(); TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent(); event.time = SharedConfig.pushStringGetTimeStart; @@ -90,7 +95,7 @@ public static void sendRegistrationToServer(@PushType int pushType, String token } public static void processRemoteMessage(@PushType int pushType, String data, long time) { - String tag = pushType == PUSH_TYPE_FIREBASE ? "FCM" : "HCM"; + String tag = pushType == PUSH_TYPE_FIREBASE ? "FCM" : (pushType == PUSH_TYPE_HUAWEI ? "HCM" : "UP"); if (BuildVars.LOGS_ENABLED) { FileLog.d(tag + " PRE START PROCESSING"); } @@ -1689,4 +1694,59 @@ public boolean hasServices() { return hasServices;*/ } } + public final static class UnifiedPushListenerServiceProvider implements IPushListenerServiceProvider { + public final static UnifiedPushListenerServiceProvider INSTANCE = new UnifiedPushListenerServiceProvider(); + + private UnifiedPushListenerServiceProvider(){}; + + @Override + public boolean hasServices() { + return !UnifiedPush.getDistributors(ApplicationLoader.applicationContext, new ArrayList()).isEmpty(); + } + + @Override + public String getLogTitle() { + return "UnifiedPush"; + } + + @Override + public void onRequestPushToken() { + String currentPushString = SharedConfig.pushString; + if (!TextUtils.isEmpty(currentPushString)) { + if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) { + FileLog.d("UnifiedPush endpoint = " + currentPushString); + } + } else { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("No UnifiedPush string found"); + } + } + Utilities.globalQueue.postRunnable(() -> { + try { + SharedConfig.pushStringGetTimeStart = SystemClock.elapsedRealtime(); + SharedConfig.saveConfig(); + if (UnifiedPush.getAckDistributor(ApplicationLoader.applicationContext) == null) { + List distributors = UnifiedPush.getDistributors(ApplicationLoader.applicationContext, new ArrayList<>()); + if (distributors.size() > 0) { + String distributor = distributors.get(0); + UnifiedPush.saveDistributor(ApplicationLoader.applicationContext, distributor); + } + } + UnifiedPush.registerApp( + ApplicationLoader.applicationContext, + "default", + new ArrayList<>(), + "Telegram Simple Push" + ); + } catch (Throwable e) { + FileLog.e(e); + } + }); + } + + @Override + public int getPushType() { + return PUSH_TYPE_SIMPLE; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java new file mode 100644 index 00000000000..78b35f4319c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java @@ -0,0 +1,109 @@ +package org.telegram.messenger; + +import android.content.Context; +import android.os.SystemClock; + +import org.telegram.tgnet.ConnectionsManager; +import org.unifiedpush.android.connector.MessagingReceiver; +import org.unifiedpush.android.connector.UnifiedPush; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.concurrent.CountDownLatch; + +public class UnifiedPushReceiver extends MessagingReceiver { + + private static long lastReceivedNotification = 0; + private static long numOfReceivedNotifications = 0; + + public static long getLastReceivedNotification() { + return lastReceivedNotification; + } + + public static long getNumOfReceivedNotifications() { + return numOfReceivedNotifications; + } + + @Override + public void onNewEndpoint(Context context, String endpoint, String instance){ + Utilities.globalQueue.postRunnable(() -> { + SharedConfig.pushStringGetTimeEnd = SystemClock.elapsedRealtime(); + + String savedDistributor = UnifiedPush.getSavedDistributor(context); + + if (savedDistributor.equals("io.heckel.ntfy")) { + PushListenerController.sendRegistrationToServer(PushListenerController.PUSH_TYPE_SIMPLE, endpoint); + } else { + try { + PushListenerController.sendRegistrationToServer(PushListenerController.PUSH_TYPE_SIMPLE, "https://p2p.belloworld.it/" + URLEncoder.encode(endpoint, "UTF-8")); + } catch (UnsupportedEncodingException e) { + FileLog.e(e); + } + } + }); + } + + @Override + public void onMessage(Context context, byte[] message, String instance){ + final long receiveTime = SystemClock.elapsedRealtime(); + final CountDownLatch countDownLatch = new CountDownLatch(1); + + lastReceivedNotification = SystemClock.elapsedRealtime(); + numOfReceivedNotifications++; + + AndroidUtilities.runOnUIThread(() -> { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("UP PRE INIT APP"); + } + ApplicationLoader.postInitApplication(); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("UP POST INIT APP"); + } + Utilities.stageQueue.postRunnable(() -> { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("UP START PROCESSING"); + } + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + if (UserConfig.getInstance(a).isClientActivated()) { + ConnectionsManager.onInternalPushReceived(a); + ConnectionsManager.getInstance(a).resumeNetworkMaybe(); + } + } + countDownLatch.countDown(); + }); + }); + Utilities.globalQueue.postRunnable(()-> { + try { + countDownLatch.await(); + } catch (Throwable ignore) { + + } + if (BuildVars.DEBUG_VERSION) { + FileLog.d("finished UP service, time = " + (SystemClock.elapsedRealtime() - receiveTime)); + } + }); + } + + @Override + public void onRegistrationFailed(Context context, String instance){ + if (BuildVars.LOGS_ENABLED) { + FileLog.d("Failed to get endpoint"); + } + SharedConfig.pushStringStatus = "__UNIFIEDPUSH_FAILED__"; + Utilities.globalQueue.postRunnable(() -> { + SharedConfig.pushStringGetTimeEnd = SystemClock.elapsedRealtime(); + + PushListenerController.sendRegistrationToServer(PushListenerController.PUSH_TYPE_SIMPLE, null); + }); + } + + @Override + public void onUnregistered(Context context, String instance){ + SharedConfig.pushStringStatus = "__UNIFIEDPUSH_FAILED__"; + Utilities.globalQueue.postRunnable(() -> { + SharedConfig.pushStringGetTimeEnd = SystemClock.elapsedRealtime(); + + PushListenerController.sendRegistrationToServer(PushListenerController.PUSH_TYPE_SIMPLE, null); + }); + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 023ba708f4c..5850bc296c9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -11,6 +11,7 @@ import static org.telegram.messenger.LocaleController.getString; import android.app.Activity; +import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -19,18 +20,23 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; +import android.os.SystemClock; import android.provider.Settings; import android.text.TextUtils; import android.util.LongSparseArray; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.telegram.messenger.UnifiedPushReceiver; +import org.unifiedpush.android.connector.UnifiedPush; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; @@ -56,6 +62,7 @@ import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.NotificationsCheckCell; +import org.telegram.ui.Cells.RadioColorCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextDetailSettingsCell; @@ -70,6 +77,8 @@ import java.util.Comparator; import java.util.HashSet; import java.util.Map; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; public class NotificationsSettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -131,6 +140,7 @@ public static class NotificationException { private int badgeNumberSection2Row; private int androidAutoAlertRow; private int repeatRow; + private int unifiedPushDistributorRow; private int resetSection2Row; private int resetSectionRow; private int resetNotificationsRow; @@ -140,6 +150,7 @@ public static class NotificationException { private boolean updateVibrate; private boolean updateRingtone; private boolean updateRepeatNotifications; + private boolean updateUnifiedPushDistributor; @Override public boolean onFragmentCreate() { @@ -196,6 +207,7 @@ public boolean onFragmentCreate() { notificationsServiceConnectionRow = rowCount++; androidAutoAlertRow = -1; repeatRow = rowCount++; + unifiedPushDistributorRow = rowCount++; resetSection2Row = rowCount++; resetSectionRow = rowCount++; resetNotificationsRow = rowCount++; @@ -756,6 +768,73 @@ public boolean supportsPredictiveItemAnimations() { if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(!enabled); } + else if (position == unifiedPushDistributorRow) { + AtomicReference dialogRef = new AtomicReference<>(); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + List distributors = UnifiedPush.getDistributors(ApplicationLoader.applicationContext, new ArrayList<>()); + CharSequence[] items = distributors.toArray(new CharSequence[distributors.size()]); + + String distributor = UnifiedPush.getAckDistributor(ApplicationLoader.applicationContext); + + for (int i = 0; i < items.length; ++i) { + final int index = i; + RadioColorCell cell = new RadioColorCell(getParentActivity()); + cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); + cell.setTextAndValue(items[index], items[index].equals(distributor)); + cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); + linearLayout.addView(cell); + cell.setOnClickListener(v -> { + UnifiedPush.saveDistributor(ApplicationLoader.applicationContext, items[index].toString()); + UnifiedPush.registerApp(ApplicationLoader.applicationContext, + "default", + new ArrayList(), + "Telegram Simple Push"); + updateUnifiedPushDistributor = true; + adapter.notifyItemChanged(position); + dialogRef.get().dismiss(); + }); + } + + Dialog dialog = new AlertDialog.Builder(getParentActivity()) + .setTitle(LocaleController.getString("UnifiedPushDistributor", R.string.UnifiedPushDistributor)) + .setView(linearLayout) + .setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null) + .create(); + dialogRef.set(dialog); + showDialog(dialog); + } + if (view instanceof TextCheckCell) { + ((TextCheckCell) view).setChecked(!enabled); + } + }); + listView.setOnItemLongClickListener((view, position, x, y) -> { + if (getParentActivity() == null) { + return false; + } + if (position == unifiedPushDistributorRow) { + String txt; + if (UnifiedPushReceiver.getNumOfReceivedNotifications() == 0) { + txt = "You never received notifications with UnifiedPush since Mercurygram was started."; + } else { + txt = String.format("The last received notification with UnifiedPush was %d seconds ago.\n" + + "You received %d notifications since Mercurygram was started.", + (SystemClock.elapsedRealtime() - UnifiedPushReceiver.getLastReceivedNotification()) / 1000, + UnifiedPushReceiver.getNumOfReceivedNotifications()); + } + txt += String.format("\n\nThe current UnifiedPush endpoint is: %s", SharedConfig.pushString); + Dialog dialog = new AlertDialog.Builder(getParentActivity()) + .setTitle("UnifiedPush Notifications") + .setMessage(txt) + .setNegativeButton(LocaleController.getString("OK", R.string.OK), null) + .create(); + showDialog(dialog); + return true; + } + return false; }); return fragmentView; @@ -1135,6 +1214,10 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } textCell.setTextAndValue(getString("RepeatNotifications", R.string.RepeatNotifications), value, updateRepeatNotifications, false); updateRepeatNotifications = false; + } else if (position == unifiedPushDistributorRow) { + String value = UnifiedPush.getAckDistributor(ApplicationLoader.applicationContext); + textCell.setTextAndValue(LocaleController.getString("UnifiedPushDistributor", R.string.UnifiedPushDistributor), value, updateUnifiedPushDistributor, false); + updateUnifiedPushDistributor = false; } break; } diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index a46dcafdce7..f85673001cf 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -2633,6 +2633,7 @@ Automatic Kilometers Miles + UnifiedPush Distributors Scan QR Code Scan QR Code No auth token found @@ -6646,8 +6647,8 @@ Reactions First Reposts First Newest First - Choose the order for the 
list of viewers. - Choose the order for the 
list of reactions. + Choose the order for the list of viewers. + Choose the order for the list of reactions. None of your contacts viewed this story. Viewers You are in Stealth Mode now diff --git a/TMessagesProj_App/build.gradle b/TMessagesProj_App/build.gradle index 04c13530160..aa7f2eda5cd 100644 --- a/TMessagesProj_App/build.gradle +++ b/TMessagesProj_App/build.gradle @@ -4,6 +4,12 @@ apply from: '../utils.gradle' repositories { mavenCentral() google() + maven { + url 'https://www.jitpack.io' + content { + includeModule 'com.github.UnifiedPush', 'android-connector' + } + } } configurations { diff --git a/build.gradle b/build.gradle index e89500514bb..09f944a3c76 100644 --- a/build.gradle +++ b/build.gradle @@ -7,6 +7,8 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:8.6.1' + // This is needed since android-connector:2.2.0 is built with Java 17 + classpath 'com.android.tools:r8:8.2.33' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } From 51941ec0fa2cdd64c6abbd02a95d84808f02b800 Mon Sep 17 00:00:00 2001 From: saintech Date: Tue, 17 Jun 2025 20:24:37 +0400 Subject: [PATCH 03/26] fix invalid path to AndroidManifest*.xml files in TMessagesProj_App/build.gradle (#310) --- TMessagesProj_App/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TMessagesProj_App/build.gradle b/TMessagesProj_App/build.gradle index aa7f2eda5cd..1208e6f2bc1 100644 --- a/TMessagesProj_App/build.gradle +++ b/TMessagesProj_App/build.gradle @@ -48,7 +48,7 @@ android { def fdroid = Utils['isFdroid']() def appSuffix = fdroid ? "" : ".beta" - def flavorsConfig = fdroid ? "config/release" : "config/debug" + def flavorsConfig = fdroid ? "release" : "debug" if (fdroid) { defaultConfig.applicationId = "org.forkgram.messenger" } From cd38eda501dbb4305243b818056fd70706442915 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 29 Jun 2025 10:50:35 +0300 Subject: [PATCH 04/26] Added correspond application name for fdroid build. --- TMessagesProj/build.gradle | 1 + TMessagesProj/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 936190f15ef..1490f6a0121 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -123,6 +123,7 @@ android { buildConfigField 'boolean', 'SKIP_DNS_RESOLVER', (Utils['isFdroid']() ? 'true' : 'false') buildConfigField 'boolean', 'SKIP_INTERNAL_BROWSER_BY_DEFAULT', (Utils['isFdroid']() ? 'true' : 'false') + manifestPlaceholders = [appLabel: Utils['isFdroid']() ? "@string/AppNameFdroid" : "@string/AppName"] externalNativeBuild { cmake { diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index f85673001cf..61f14ad685c 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -2,6 +2,7 @@ Fork Client Fork Client + Forkgram English English English From d72706aaee3ec989ee9980d0b386220242cda8a4 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 29 Jun 2025 10:57:27 +0300 Subject: [PATCH 05/26] Added warning about limitation of SMS verification. --- .../src/main/java/org/telegram/ui/LoginActivity.java | 9 +++++++++ TMessagesProj/src/main/res/values-ar/strings.xml | 1 + TMessagesProj/src/main/res/values-de/strings.xml | 1 + TMessagesProj/src/main/res/values-es/strings.xml | 1 + TMessagesProj/src/main/res/values-it/strings.xml | 2 ++ TMessagesProj/src/main/res/values-ko/strings.xml | 1 + TMessagesProj/src/main/res/values-nl/strings.xml | 1 + TMessagesProj/src/main/res/values-pt-rBR/strings.xml | 1 + TMessagesProj/src/main/res/values-ru/strings.xml | 2 ++ TMessagesProj/src/main/res/values-uk/strings.xml | 1 + TMessagesProj/src/main/res/values/strings.xml | 1 + 11 files changed, 21 insertions(+) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index f7ef5abf0d3..82a78e1a39a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -2126,6 +2126,15 @@ public PhoneView(Context context) { subtitleView.setLineSpacing(dp(2), 1.0f); addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 8, 32, 0)); + TextView warningView = new TextView(context); + warningView.setText(R.string.SmsOnlyOfficialWarning); + warningView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + warningView.setTextColor(Theme.getColor(Theme.key_text_RedRegular)); + warningView.setGravity(Gravity.CENTER); + warningView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + warningView.setPadding(0, AndroidUtilities.dp(8), 0, 0); + addView(warningView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 0, 32, 0)); + countryButton = new TextViewSwitcher(context); countryButton.setFactory(() -> { TextView tv = new TextView(context); diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 59bdf56cfe2..c47a4d7f5ef 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -1304,5 +1304,6 @@ 2560 بكسل لإرسال الصور تعطيل السحب إلى القناة التالية تعطيل الملفات الحديثة + ملاحظة: التحقق عبر الرسائل النصية مقتصر فقط على التطبيقات الرسمية diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index e3ee2abff78..31888184091 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -1436,5 +1436,6 @@ 2560px zum Senden von Fotos Wischen zum nächsten Kanal deaktivieren Neueste Dateien deaktivieren + Hinweis: Die SMS-Verifizierung ist NUR für offizielle mobile Apps verfügbar diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index ab344ad7ff6..b0eb2b7b0aa 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -1377,4 +1377,5 @@ 2560px para enviar fotos Desactivar deslizar al siguiente canal Desactivar archivos recientes + Nota: La verificación por SMS está limitada SOLO a aplicaciones móviles oficiales diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 55af1c6dea0..2252059dfb2 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -1598,4 +1598,6 @@ 2560px per inviare foto Disabilita lo scorrimento al canale successivo Disabilita file recenti + Nota: la verifica SMS è limitata SOLO alle app mobili ufficiali + diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 963f14a4804..570f6398c1b 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -1197,5 +1197,6 @@ 사진 전송을 위한 2560px 다음 채널로 슬라이드 비활성화 최근 파일 비활성화 + 참고: SMS 인증은 공식 모바일 앱에서만 가능합니다 diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 58a1ec3c99a..53507beebcb 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -1145,5 +1145,6 @@ 2560px voor het verzenden van foto\'s Veeg naar het volgende kanaal uitschakelen Recente bestanden uitschakelen + Let op: SMS-verificatie is ALLEEN beschikbaar voor officiële mobiele apps diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index 4e83e4fd900..1afec6b1748 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -1310,5 +1310,6 @@ 2560px para enviar fotos Desativar deslizar para o próximo canal Desativar arquivos recentes + Observação: A verificação por SMS está disponível APENAS para aplicativos oficiais diff --git a/TMessagesProj/src/main/res/values-ru/strings.xml b/TMessagesProj/src/main/res/values-ru/strings.xml index 604fe79225e..4a43cd53f4c 100644 --- a/TMessagesProj/src/main/res/values-ru/strings.xml +++ b/TMessagesProj/src/main/res/values-ru/strings.xml @@ -323,4 +323,6 @@ 2560px для отправки фото Отключить слайд на следующий канал Отключить недавние файлы + Примечание: SMS-подтверждение доступно ТОЛЬКО в официальных мобильных приложениях + diff --git a/TMessagesProj/src/main/res/values-uk/strings.xml b/TMessagesProj/src/main/res/values-uk/strings.xml index e0bc7d26e46..48a2455de0f 100644 --- a/TMessagesProj/src/main/res/values-uk/strings.xml +++ b/TMessagesProj/src/main/res/values-uk/strings.xml @@ -336,5 +336,6 @@ 2560px для надсилання фото Вимкнути прокрутку до наступного каналу Вимкнути недавні файли + Примітка: SMS-підтвердження доступне ЛИШЕ у офіційних мобільних додатках diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 61f14ad685c..d84284496ef 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -10260,4 +10260,5 @@ Please restart after change to apply a new platform for the current bot. Copy every clicked link Open links in system browser + Note: SMS verification is limited to ONLY official mobile apps From c87a6513e921164f3f07ab79c08c102d6eeb8359 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 1 Sep 2025 23:18:05 +0300 Subject: [PATCH 06/26] Fixed build. --- TMessagesProj/build.gradle | 2 ++ TMessagesProj/src/main/AndroidManifest.xml | 1 - TMessagesProj_App/build.gradle | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 1490f6a0121..3cdec268aab 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -24,6 +24,8 @@ configurations.all { } dependencies { + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' + implementation 'androidx.core:core:1.16.0' implementation 'androidx.interpolator:interpolator:1.0.0' implementation 'androidx.fragment:fragment:1.2.0' diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index 48a43e8f6f3..8d913f2748c 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -79,7 +79,6 @@ - diff --git a/TMessagesProj_App/build.gradle b/TMessagesProj_App/build.gradle index 1208e6f2bc1..5275dee38ec 100644 --- a/TMessagesProj_App/build.gradle +++ b/TMessagesProj_App/build.gradle @@ -256,7 +256,7 @@ android { } defaultConfig { - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 35 versionName Utils['getVersionName']() ndkVersion "21.4.7075529" From 0964aeab45f0119d277c251e7837971b4a2888d4 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 19 Sep 2025 23:10:22 +0300 Subject: [PATCH 07/26] Added integration of last.fm. --- .github/workflows/tandroid.yml | 2 + TMessagesProj/build.gradle | 2 + .../org/telegram/messenger/BuildVars.java | 4 + .../org/telegram/messenger/LastFmHelper.java | 349 ++++++++++++++++++ .../telegram/messenger/MediaController.java | 22 ++ .../org/telegram/ui/ForkSettingsActivity.java | 20 +- .../org/telegram/ui/LastFmLoginActivity.java | 271 ++++++++++++++ .../src/main/res/drawable/ic_lastfm.xml | 28 ++ TMessagesProj/src/main/res/values/strings.xml | 1 + gradle.properties | 2 + 10 files changed, 697 insertions(+), 4 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/messenger/LastFmHelper.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/LastFmLoginActivity.java create mode 100644 TMessagesProj/src/main/res/drawable/ic_lastfm.xml diff --git a/.github/workflows/tandroid.yml b/.github/workflows/tandroid.yml index 0870735d424..b273f8a911f 100644 --- a/.github/workflows/tandroid.yml +++ b/.github/workflows/tandroid.yml @@ -68,6 +68,8 @@ jobs: echo "CHECK_UPDATES=${{ matrix.updates }}" >> $vars echo "USER_ID_OWNER=${{ secrets.USER_ID_OWNER }}" >> $vars echo "UPDATE_CHANNEL_USERNAME=${{ secrets.UPDATE_CHANNEL_USERNAME }}" >> $vars + echo "LASTFM_API_KEY=${{ secrets.LASTFM_API_KEY }}" >> $vars + echo "LASTFM_API_SECRET=${{ secrets.LASTFM_API_SECRET }}" >> $vars ### echo $ADDITIONAL_BUILD_NUMBER diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 3cdec268aab..ff6d520c9c3 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -115,6 +115,8 @@ android { buildConfigField 'String', 'USER_REPO', getStringForConfig(USER_REPO) buildConfigField 'int', 'CHECK_UPDATES', CHECK_UPDATES buildConfigField 'String', 'UPDATE_CHANNEL_USERNAME', getStringForConfig(UPDATE_CHANNEL_USERNAME) + buildConfigField 'String', 'LASTFM_API_KEY', getStringForConfig(LASTFM_API_KEY) + buildConfigField 'String', 'LASTFM_API_SECRET', getStringForConfig(LASTFM_API_SECRET) vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 5b914f3b595..37d7f90168d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -36,6 +36,10 @@ public class BuildVars { public static String HUAWEI_STORE_URL = "https://appgallery.huawei.com/app/C101184875"; public static String GOOGLE_AUTH_CLIENT_ID = "760348033671-81kmi3pi84p11ub8hp9a1funsv0rn2p9.apps.googleusercontent.com"; + // Last.fm API constants + public static String LASTFM_API_KEY = BuildConfig.LASTFM_API_KEY; + public static String LASTFM_API_SECRET = BuildConfig.LASTFM_API_SECRET; + public static String LASTFM_API_URL = "https://ws.audioscrobbler.com/2.0/"; public static String UPDATE_CHANNEL_USERNAME = BuildConfig.UPDATE_CHANNEL_USERNAME; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LastFmHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/LastFmHelper.java new file mode 100644 index 00000000000..17765a96fb9 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LastFmHelper.java @@ -0,0 +1,349 @@ +package org.telegram.messenger; + +import android.content.Context; +import android.content.SharedPreferences; + +import java.security.MessageDigest; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +public class LastFmHelper { + + private static LastFmHelper instance; + private SharedPreferences prefs; + private long lastApiCallTime = 0; + private static final long API_CALL_INTERVAL = 30000; // 30 seconds + + public static LastFmHelper getInstance() { + if (instance == null) { + instance = new LastFmHelper(); + } + return instance; + } + + private LastFmHelper() { + if (ApplicationLoader.applicationContext != null) { + prefs = ApplicationLoader.applicationContext.getSharedPreferences("lastfm", Context.MODE_PRIVATE); + } + } + + public boolean isLoggedIn() { + return prefs != null && prefs.getBoolean("logged_in", false); + } + + public String getUsername() { + return prefs != null ? prefs.getString("username", "") : ""; + } + + public void logout() { + if (prefs != null) { + prefs.edit().clear().apply(); + } + } + + public void login(String username, String password, LoginCallback callback) { + Utilities.globalQueue.postRunnable(() -> { + try { + // Step 1: Get token + String token = getToken(); + if (token == null) { + AndroidUtilities.runOnUIThread(() -> callback.onError("Failed to get token")); + return; + } + + // Step 2: Get session + String sessionKey = getSession(username, password, token); + if (sessionKey != null) { + prefs.edit() + .putBoolean("logged_in", true) + .putString("username", username) + .putString("session_key", sessionKey) + .apply(); + AndroidUtilities.runOnUIThread(() -> callback.onSuccess()); + } else { + AndroidUtilities.runOnUIThread(() -> callback.onError("Invalid credentials")); + } + } catch (Exception e) { + FileLog.e(e); + AndroidUtilities.runOnUIThread(() -> callback.onError(e.getMessage())); + } + }); + } + + public interface LoginCallback { + void onSuccess(); + void onError(String error); + } + + public void scrobbleTrack(String artist, String track, String album, long timestamp) { + if (!isLoggedIn() || artist == null || track == null) { + return; + } + + if (!canMakeApiCall()) { + return; + } + + Map params = new HashMap<>(); + params.put("method", "track.scrobble"); + params.put("api_key", BuildVars.LASTFM_API_KEY); + params.put("artist", artist); + params.put("track", track); + if (album != null) { + params.put("album", album); + } + params.put("timestamp", String.valueOf(timestamp)); + params.put("sk", getSessionKey()); + params.put("api_sig", generateApiSignature(params)); + + Utilities.globalQueue.postRunnable(() -> { + try { + sendPostRequestVoid(params); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("Last.fm scrobbled: " + artist + " - " + track); + } + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + public void updateNowPlaying(String artist, String track, String album) { + if (!isLoggedIn() || artist == null || track == null) { + return; + } + + if (!canMakeApiCall()) { + return; + } + + Map params = new HashMap<>(); + params.put("method", "track.updateNowPlaying"); + params.put("api_key", BuildVars.LASTFM_API_KEY); + params.put("artist", artist); + params.put("track", track); + if (album != null) { + params.put("album", album); + } + params.put("sk", getSessionKey()); + params.put("api_sig", generateApiSignature(params)); + + Utilities.globalQueue.postRunnable(() -> { + try { + sendPostRequestVoid(params); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("Last.fm now playing: " + artist + " - " + track); + } + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + private String getSessionKey() { + return prefs != null ? prefs.getString("session_key", "") : ""; + } + + private boolean canMakeApiCall() { + long currentTime = System.currentTimeMillis(); + if (currentTime - lastApiCallTime >= API_CALL_INTERVAL) { + lastApiCallTime = currentTime; + return true; + } + return false; + } + + public String generateApiSignature(Map params) { + TreeMap sortedParams = new TreeMap<>(params); + StringBuilder signature = new StringBuilder(); + + for (Map.Entry entry : sortedParams.entrySet()) { + signature.append(entry.getKey()).append(entry.getValue()); + } + signature.append(BuildVars.LASTFM_API_SECRET); + + return md5(signature.toString()); + } + + private String md5(String input) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] messageDigest = md.digest(input.getBytes()); + StringBuilder hexString = new StringBuilder(); + for (byte b : messageDigest) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (Exception e) { + return ""; + } + } + + private String getToken() { + try { + Map params = new HashMap<>(); + params.put("method", "auth.getToken"); + params.put("api_key", BuildVars.LASTFM_API_KEY); + params.put("api_sig", generateApiSignature(params)); + + String response = sendGetRequest(params); + // Parse XML response to get token + // Simplified implementation - real project needs XML parser + if (response != null && response.contains("")) { + int start = response.indexOf("") + 7; + int end = response.indexOf(""); + if (start > 6 && end > start) { + return response.substring(start, end); + } + } + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + + private String getSession(String username, String password, String token) { + try { + Map params = new HashMap<>(); + params.put("method", "auth.getMobileSession"); + params.put("api_key", BuildVars.LASTFM_API_KEY); + params.put("username", username); + params.put("password", password); + params.put("api_sig", generateApiSignature(params)); + + String response = sendPostRequest(params); + // Parse XML response to get session key + if (response != null && response.contains("")) { + int start = response.indexOf("") + 5; + int end = response.indexOf(""); + if (start > 4 && end > start) { + return response.substring(start, end); + } + } + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + + private String sendGetRequest(Map params) { + try { + StringBuilder urlBuilder = new StringBuilder(BuildVars.LASTFM_API_URL + "?"); + for (Map.Entry entry : params.entrySet()) { + if (urlBuilder.length() > BuildVars.LASTFM_API_URL.length() + 1) { + urlBuilder.append('&'); + } + urlBuilder.append(java.net.URLEncoder.encode(entry.getKey(), "UTF-8")); + urlBuilder.append('='); + urlBuilder.append(java.net.URLEncoder.encode(entry.getValue(), "UTF-8")); + } + + java.net.URL url = new java.net.URL(urlBuilder.toString()); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + + int responseCode = connection.getResponseCode(); + if (responseCode == 200) { + java.io.BufferedReader reader = new java.io.BufferedReader( + new java.io.InputStreamReader(connection.getInputStream())); + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + connection.disconnect(); + return response.toString(); + } + connection.disconnect(); + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + + private String sendPostRequest(Map params) { + try { + java.net.URL url = new java.net.URL(BuildVars.LASTFM_API_URL); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + + StringBuilder postData = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (postData.length() != 0) { + postData.append('&'); + } + postData.append(java.net.URLEncoder.encode(entry.getKey(), "UTF-8")); + postData.append('='); + postData.append(java.net.URLEncoder.encode(entry.getValue(), "UTF-8")); + } + + byte[] postDataBytes = postData.toString().getBytes("UTF-8"); + connection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); + connection.getOutputStream().write(postDataBytes); + + int responseCode = connection.getResponseCode(); + if (responseCode == 200) { + java.io.BufferedReader reader = new java.io.BufferedReader( + new java.io.InputStreamReader(connection.getInputStream())); + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + connection.disconnect(); + return response.toString(); + } + + if (BuildVars.LOGS_ENABLED) { + FileLog.d("Last.fm API response code: " + responseCode); + } + + connection.disconnect(); + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + + private void sendPostRequestVoid(Map params) { + try { + java.net.URL url = new java.net.URL(BuildVars.LASTFM_API_URL); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + + StringBuilder postData = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (postData.length() != 0) { + postData.append('&'); + } + postData.append(java.net.URLEncoder.encode(entry.getKey(), "UTF-8")); + postData.append('='); + postData.append(java.net.URLEncoder.encode(entry.getValue(), "UTF-8")); + } + + byte[] postDataBytes = postData.toString().getBytes("UTF-8"); + connection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); + connection.getOutputStream().write(postDataBytes); + + int responseCode = connection.getResponseCode(); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("Last.fm API response code: " + responseCode); + } + + connection.disconnect(); + } catch (Exception e) { + FileLog.e(e); + } + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 142be2944c8..3003e97bfd8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -3808,6 +3808,18 @@ public void onStateChanged(boolean playWhenReady, int playbackState) { if (playbackState == ExoPlayer.STATE_ENDED || (playbackState == ExoPlayer.STATE_IDLE || playbackState == ExoPlayer.STATE_BUFFERING) && playWhenReady && messageObject.audioProgress >= 0.999f) { messageObject.audioProgress = 1f; NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, messageObject.getId(), 0); + + if (messageObject.isMusic() && messageObject.getDuration() > 30) { + String artist = messageObject.getMusicAuthor(); + String track = messageObject.getMusicTitle(); + String album = null; + if (audioInfo != null && !TextUtils.isEmpty(audioInfo.getAlbum())) { + album = audioInfo.getAlbum(); + } + long timestamp = System.currentTimeMillis() / 1000; + LastFmHelper.getInstance().scrobbleTrack(artist, track, album, timestamp); + } + final boolean restored = restoreMusicPlaylistState(); if (!restored) { if (!playlist.isEmpty() && (playlist.size() > 1 || !messageObject.isVoice())) { @@ -3967,6 +3979,16 @@ public boolean needUpdate() { } startProgressTimer(playingMessageObject); NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingDidStart, messageObject, oldMessageObject); + + if (messageObject.isMusic()) { + String artist = messageObject.getMusicAuthor(); + String track = messageObject.getMusicTitle(); + String album = null; + if (audioInfo != null && !TextUtils.isEmpty(audioInfo.getAlbum())) { + album = audioInfo.getAlbum(); + } + LastFmHelper.getInstance().updateNowPlaying(artist, track, album); + } if (videoPlayer != null) { try { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java index 0ce5b63b7cd..04136dd53b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java @@ -18,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -131,8 +132,8 @@ public void invalidate() { private ListAdapter listAdapter; private ArrayList sectionRows = new ArrayList(); - private String[] sectionStrings = {"General", "ChatList", "FilterChats", "ChatCamera", "StickerSize"}; - private int[] sectionInts = {0, R.string.ChatList, R.string.FilterChats, 0, R.string.StickerSize}; + private String[] sectionStrings = {"General", "ChatList", "FilterChats", "ChatCamera", "StickerSize", "ThirdParty"}; + private int[] sectionInts = {0, R.string.ChatList, R.string.FilterChats, 0, R.string.StickerSize, R.string.ThirdParty}; private int rowCount; @@ -165,6 +166,7 @@ public void invalidate() { private int botSkipShare; private int botSkipFullscreen; private int disableDefaultInAppBrowser; + private int lastFmLoginRow; private int stickerSizeRow; @@ -249,6 +251,11 @@ public boolean onFragmentCreate() { sectionRows.add(rowCount++); stickerSizeRow = rowCount++; + emptyRows.add(rowCount++); + sectionRows.add(rowCount++); + lastFmLoginRow = (BuildVars.LASTFM_API_KEY != null && BuildVars.LASTFM_API_KEY.length() > 2 && + BuildVars.LASTFM_API_SECRET != null && BuildVars.LASTFM_API_SECRET.length() > 2) ? rowCount++ : -1; + return true; } @@ -402,6 +409,8 @@ public boolean supportsPredictiveItemAnimations() { } return null; }); + } else if (position == lastFmLoginRow) { + presentFragment(new LastFmLoginActivity()); } }); @@ -438,6 +447,8 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { String t = LocaleController.getString("EditAdminRank", R.string.EditAdminRank); final String v = MessagesController.getGlobalMainSettings().getString("forkCustomTitle", "Fork Client"); textCell.setTextAndValue(t, v, false); + } else if (position == lastFmLoginRow) { + textCell.setTextAndIcon("Last.fm Login", R.drawable.ic_lastfm, false); } break; } @@ -589,7 +600,8 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { || position == hideBottomButton || position == syncPinsRow || position == showNotificationContent - || position == photoHasStickerRow; + || position == photoHasStickerRow + || position == lastFmLoginRow; return fork; } @@ -627,7 +639,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType public int getItemViewType(int position) { if (emptyRows.contains(position)) { return 1; - } else if (position == customTitleRow) { + } else if (position == customTitleRow || position == lastFmLoginRow) { return 2; } else if (position == squareAvatarsRow || position == hideSensitiveDataRow diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastFmLoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastFmLoginActivity.java new file mode 100644 index 00000000000..b54158926a7 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastFmLoginActivity.java @@ -0,0 +1,271 @@ +package org.telegram.ui; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.AsyncTask; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.MessageDigest; +import java.util.TreeMap; + +public class LastFmLoginActivity extends BaseFragment { + + private static final String API_KEY = BuildVars.LASTFM_API_KEY; + private static final String API_SECRET = BuildVars.LASTFM_API_SECRET; + private TextView loginButton; + private TextView statusText; + private boolean waitingForAuth = false; + private boolean isLoggedIn = false; + + @Override + public View createView(Context context) { + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setAllowOverlayTitle(true); + actionBar.setTitle("Last.fm Login"); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + + checkLoginStatus(); + + fragmentView = new LinearLayout(context); + LinearLayout linearLayout = (LinearLayout) fragmentView; + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + + TextView headerText = new TextView(context); + headerText.setText("Connect your Last.fm account"); + headerText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + headerText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + headerText.setGravity(Gravity.CENTER); + linearLayout.addView(headerText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 24, 24, 12)); + + TextView descText = new TextView(context); + descText.setText("Get authorization token from Last.fm"); + descText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + descText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + descText.setGravity(Gravity.CENTER); + linearLayout.addView(descText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 12, 24, 12)); + + statusText = new TextView(context); + statusText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + statusText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + statusText.setGravity(Gravity.CENTER); + linearLayout.addView(statusText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 12, 24, 12)); + + loginButton = new TextView(context); + loginButton.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); + loginButton.setGravity(Gravity.CENTER); + loginButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + loginButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + loginButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + loginButton.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + updateUI(); + linearLayout.addView(loginButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 42, 24, 24, 24, 0)); + + return fragmentView; + } + + private void checkLoginStatus() { + SharedPreferences prefs = getParentActivity().getSharedPreferences("lastfm", Context.MODE_PRIVATE); + isLoggedIn = prefs.getBoolean("logged_in", false); + } + + private void updateUI() { + if (isLoggedIn) { + statusText.setText("✓ Logged in to Last.fm"); + statusText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGreenText)); + loginButton.setText("Logout"); + loginButton.setOnClickListener(v -> logout()); + } else { + statusText.setText("Not logged in"); + statusText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + loginButton.setText("Get Token"); + loginButton.setOnClickListener(v -> getAuthToken()); + } + } + + private void logout() { + SharedPreferences prefs = getParentActivity().getSharedPreferences("lastfm", Context.MODE_PRIVATE); + prefs.edit().clear().apply(); + isLoggedIn = false; + updateUI(); + } + + private void getAuthToken() { + new GetTokenTask().execute(); + } + + private class GetTokenTask extends AsyncTask { + @Override + protected String doInBackground(Void... params) { + try { + TreeMap apiParams = new TreeMap<>(); + apiParams.put("method", "auth.getToken"); + apiParams.put("api_key", API_KEY); + + String apiSig = generateApiSignature(apiParams); + + String url = "http://ws.audioscrobbler.com/2.0/?method=auth.getToken&api_key=" + + API_KEY + "&api_sig=" + apiSig + "&format=json"; + + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setRequestMethod("GET"); + + BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + + String jsonResponse = response.toString(); + if (jsonResponse.contains("\"token\":\"")) { + int start = jsonResponse.indexOf("\"token\":\"") + 9; + int end = jsonResponse.indexOf("\"", start); + return jsonResponse.substring(start, end); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(String token) { + if (token != null) { + String authUrl = "http://www.last.fm/api/auth/?api_key=" + API_KEY + "&token=" + token; + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)); + getParentActivity().startActivity(intent); + + // Store token for later session creation + SharedPreferences prefs = getParentActivity().getSharedPreferences("lastfm", Context.MODE_PRIVATE); + prefs.edit().putString("auth_token", token).apply(); + + waitingForAuth = true; + loginButton.setText("Waiting for authorization..."); + loginButton.setEnabled(false); + } + } + } + + public void createSession() { + SharedPreferences prefs = getParentActivity().getSharedPreferences("lastfm", Context.MODE_PRIVATE); + String token = prefs.getString("auth_token", null); + if (token != null) { + new GetSessionTask().execute(token); + } + } + + private class GetSessionTask extends AsyncTask { + @Override + protected String doInBackground(String... params) { + String token = params[0]; + try { + TreeMap apiParams = new TreeMap<>(); + apiParams.put("method", "auth.getSession"); + apiParams.put("api_key", API_KEY); + apiParams.put("token", token); + + String apiSig = generateApiSignature(apiParams); + + String url = "http://ws.audioscrobbler.com/2.0/?method=auth.getSession&api_key=" + + API_KEY + "&token=" + token + "&api_sig=" + apiSig + "&format=json"; + + HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); + conn.setRequestMethod("GET"); + + BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + + String jsonResponse = response.toString(); + if (jsonResponse.contains("\"key\":\"")) { + int start = jsonResponse.indexOf("\"key\":\"") + 7; + int end = jsonResponse.indexOf("\"", start); + return jsonResponse.substring(start, end); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(String sessionKey) { + waitingForAuth = false; + if (sessionKey != null) { + SharedPreferences prefs = getParentActivity().getSharedPreferences("lastfm", Context.MODE_PRIVATE); + prefs.edit() + .putString("session_key", sessionKey) + .putBoolean("logged_in", true) + .apply(); + isLoggedIn = true; + updateUI(); + } else { + loginButton.setText("Get Token"); + loginButton.setEnabled(true); + } + } + } + + @Override + public void onResume() { + super.onResume(); + if (waitingForAuth) { + // Try to create session when user returns from browser + AndroidUtilities.runOnUIThread(() -> createSession(), 1000); + } + } + + private String generateApiSignature(TreeMap params) { + StringBuilder sig = new StringBuilder(); + for (String key : params.keySet()) { + sig.append(key).append(params.get(key)); + } + sig.append(API_SECRET); + + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] hash = md.digest(sig.toString().getBytes("UTF-8")); + StringBuilder hexString = new StringBuilder(); + for (byte b : hash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/ic_lastfm.xml b/TMessagesProj/src/main/res/drawable/ic_lastfm.xml new file mode 100644 index 00000000000..a6cf61a525e --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/ic_lastfm.xml @@ -0,0 +1,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index d84284496ef..f3d813af8de 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -10261,4 +10261,5 @@ Copy every clicked link Open links in system browser Note: SMS verification is limited to ONLY official mobile apps + Third-party diff --git a/gradle.properties b/gradle.properties index 6963a7e63e6..12289508daf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,4 +39,6 @@ CHECK_UPDATES=0 ADDITIONAL_BUILD_NUMBER=0 F_DROID=0 UPDATE_CHANNEL_USERNAME=a +LASTFM_API_KEY=a +LASTFM_API_SECRET=a # From 95cb9fcaa7e9e6859196323c4baab9d6d1641d11 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 20 Sep 2025 11:05:36 +0300 Subject: [PATCH 08/26] Reduced long-click time to context menu appearing from sticker preview. --- .../src/main/java/org/telegram/ui/ContentPreviewViewer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index b156b001869..79e6c8b2557 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -1590,7 +1590,7 @@ public void open(TLRPC.Document document, SendMessagesHelper.ImportingSticker st } if ((newSet != null || contentType == CONTENT_TYPE_EMOJI) && (delegate == null || delegate.needMenu())) { AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); - AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); + AndroidUtilities.runOnUIThread(showSheetRunnable, 700); } TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getStickerSet(newSet, true); if (stickerSet != null && stickerSet.documents.isEmpty()) { @@ -1641,7 +1641,7 @@ public void open(TLRPC.Document document, SendMessagesHelper.ImportingSticker st } if (delegate.needMenu()) { AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); - AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); + AndroidUtilities.runOnUIThread(showSheetRunnable, 700); } } } else { From d4b37d44be49f1c0c48de4b41397be3f74ed33c2 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 20 Sep 2025 13:29:25 +0300 Subject: [PATCH 09/26] Added option to delete all user messages in all forum topics at once. --- .../telegram/messenger/forkgram/Dialogs.kt | 95 +++++++++++++++++++ .../java/org/telegram/ui/ChatActivity.java | 14 +++ TMessagesProj/src/main/res/values/strings.xml | 1 + 3 files changed, 110 insertions(+) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/Dialogs.kt b/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/Dialogs.kt index 06b753af6cf..33b81bc3419 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/Dialogs.kt +++ b/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/Dialogs.kt @@ -231,6 +231,101 @@ public fun CreateDeleteAllUnpinnedMessagesAlert( } } +@JvmStatic +public fun CreateDeleteAllYourMessagesInAllTopicsAlert( + currentAccount: Int, + dialogId: Long, + context: Context) { + + val create = { text: String, callback: () -> Unit -> + val builder = AlertDialog.Builder(context); + builder.setTitle(LocaleController.getString( + "DeleteAllYourMessages", + R.string.DeleteAllYourMessages)); + builder.setMessage(AndroidUtilities.replaceTags(text)); + + builder.setPositiveButton( + LocaleController.getString("OK", R.string.OK), + { _: DialogInterface?, _: Int -> callback(); }); + builder.setNegativeButton( + LocaleController.getString("Cancel", R.string.Cancel), + null); + val dialog = builder.show(); + val button = dialog.getButton(DialogInterface.BUTTON_POSITIVE) as TextView; + button.setTextColor(Theme.getColor(Theme.key_text_RedBold)); + }; + + val messagesController = AccountInstance.getInstance(currentAccount).messagesController; + val topicsController = messagesController.topicsController; + val meId = UserConfig.getInstance(UserConfig.selectedAccount).clientUserId; + val chatId = -dialogId; + + val deleteFor = { to: Long, found: ArrayList -> + val messages: java.util.ArrayList = ArrayList(found.map { it.id }); + AndroidUtilities.runOnUIThread { + messagesController.deleteMessages( + messages, + null, + null, + to, + 0, + true, + 0); + }; + }; + + create( + LocaleController.getString( + "DeleteAllYourMessagesInfo", + R.string.DeleteAllYourMessagesInfo) + "\n\n" + + "This will delete your messages in ALL topics of this group." + ) { + create(LocaleController.getString("ReallySure", R.string.ReallySure)) { + val topics = topicsController.getTopics(chatId); + val mePeer = messagesController.getInputPeer(meId); + val dialogPeer = messagesController.getInputPeer(dialogId); + + if (topics != null && topics.isNotEmpty()) { + // Delete messages in each topic + for (topic in topics) { + // Use the main dialog peer but search within specific topic + ForkApi.SearchAllMessages( + currentAccount, + dialogPeer, + mePeer, + { found: ArrayList -> + // Filter messages that belong to this topic + val topicMessages = found.filter { message -> + val topicId = if (message.reply_to != null && message.reply_to.reply_to_top_id != 0) { + message.reply_to.reply_to_top_id + } else if (message.reply_to != null && message.reply_to.reply_to_msg_id != 0) { + message.reply_to.reply_to_msg_id + } else { + message.id + } + topicId == topic.id + } + if (topicMessages.isNotEmpty()) { + deleteFor(dialogId, ArrayList(topicMessages)) + } + }, + {} + ); + } + } else { + // Fallback to main dialog if no topics + ForkApi.SearchAllMessages( + currentAccount, + dialogPeer, + mePeer, + { found: ArrayList -> deleteFor(dialogId, found); }, + {} + ); + } + } + } +} + @JvmStatic public fun CreateFieldAlert( context: Context, diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index cea3c71048f..63db6337093 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -1714,6 +1714,7 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolea private final static int goToFirstMessage = 35; private final static int deleteAllYourMessages = 36; private final static int deleteAllUnpinnedMessages = 37; + private final static int deleteAllYourMessagesInAllTopics = 38; private final static int attach_photo = 0; private final static int attach_gallery = 1; @@ -4191,6 +4192,11 @@ public void run(boolean revoke) { currentAccount, dialog_id, getParentActivity()); + } else if (id == deleteAllYourMessagesInAllTopics) { + org.telegram.messenger.forkgram.ForkDialogs.CreateDeleteAllYourMessagesInAllTopicsAlert( + currentAccount, + dialog_id, + getParentActivity()); } else if (id == deleteAllUnpinnedMessages) { org.telegram.messenger.forkgram.ForkDialogs.CreateDeleteAllUnpinnedMessagesAlert( currentAccount, @@ -4531,6 +4537,14 @@ public void toggleMute() { R.drawable.msg_delete, LocaleController.getString("DeleteAllYourMessages", R.string.DeleteAllYourMessages), themeDelegate); + // Add option to delete messages in all topics for forum groups + if (ChatObject.isForum(currentChat)) { + headerItem.addSubItem( + deleteAllYourMessagesInAllTopics, + R.drawable.msg_delete, + LocaleController.getString("DeleteAllYourMessagesInAllTopics", R.string.DeleteAllYourMessagesInAllTopics), + themeDelegate); + } } if (MessagesController.getGlobalMainSettings().getBoolean("addItemToDeleteAllUnpinnedMessages", false) && ((currentUser != null && currentEncryptedChat == null) || currentChat != null)) { diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index f3d813af8de..6e3a234a7d5 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -10240,6 +10240,7 @@ When app is locked. Can be cause of privacy leaks. Delete all your messages Are you sure you want **delete all your messages** from this chat? + Delete all your messages in all topics Are you **really sure**? Disable Global Search Disable quick reaction From 2fcb58bc784833d6b071d3256d8fb2b87b35d26e Mon Sep 17 00:00:00 2001 From: derivativeoflog7 <100133857+DerivativeOfLog7@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:33:32 +0200 Subject: [PATCH 10/26] Add option for last seen dots --- .../src/main/java/org/telegram/ui/Cells/DialogCell.java | 2 ++ .../main/java/org/telegram/ui/ForkSettingsActivity.java | 9 +++++++++ TMessagesProj/src/main/res/values/strings.xml | 1 + 3 files changed, 12 insertions(+) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index 2f7eb749343..57f579af8db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -4665,6 +4665,8 @@ public boolean drawAvatarOverlays(Canvas canvas) { final int diff = user.status.expires - ConnectionsManager.getInstance(currentAccount).getCurrentTime(); colorOnline = diff > 0 ? Theme.getColor(Theme.key_chats_onlineCircle) + : !MessagesController.getGlobalMainSettings().getBoolean("enableLastSeenDots", true) + ? 0 : diff > -15 * 60 ? android.graphics.Color.argb(255, 234, 234, 30) : diff > -30 * 60 diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java index 04136dd53b7..1448c1595c9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java @@ -153,6 +153,7 @@ public void invalidate() { private int formatWithSeconds; private int disableThumbsInDialogList; private int disableGlobalSearch; + private int enableLastSeenDots; private int customTitleRow; private int fullRecentStickersRow; private int hideSendAsRow; @@ -219,6 +220,7 @@ public boolean onFragmentCreate() { openArchiveOnPull = rowCount++; disableThumbsInDialogList = rowCount++; disableGlobalSearch = rowCount++; + enableLastSeenDots = rowCount++; customTitleRow = rowCount++; emptyRows.add(rowCount++); @@ -378,6 +380,8 @@ public boolean supportsPredictiveItemAnimations() { toggleGlobalMainSetting("disableThumbsInDialogList", view, false); } else if (position == disableGlobalSearch) { toggleGlobalMainSetting("disableGlobalSearch", view, false); + } else if (position == enableLastSeenDots) { + toggleGlobalMainSetting("enableLastSeenDots", view, true); } else if (position == hideBottomButton) { toggleGlobalMainSetting("hideBottomButton", view, false); } else if (position == syncPinsRow) { @@ -542,6 +546,9 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (position == disableGlobalSearch) { String t = LocaleController.getString("DisableGlobalSearch", R.string.DisableGlobalSearch); textCell.setTextAndCheck(t, preferences.getBoolean("disableGlobalSearch", false), false); + } else if (position == enableLastSeenDots) { + String t = "Enable last seen colored dots"; + textCell.setTextAndCheck(t, preferences.getBoolean("enableLastSeenDots", true), false); } else if (position == hideBottomButton) { String t = LocaleController.getString("HideBottomButton", R.string.HideBottomButton); textCell.setTextAndCheck(t, preferences.getBoolean("hideBottomButton", false), false); @@ -596,6 +603,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { || position == formatWithSeconds || position == disableThumbsInDialogList || position == disableGlobalSearch + || position == enableLastSeenDots || position == customTitleRow || position == hideBottomButton || position == syncPinsRow @@ -667,6 +675,7 @@ public int getItemViewType(int position) { || position == formatWithSeconds || position == disableThumbsInDialogList || position == disableGlobalSearch + || position == enableLastSeenDots || position == hideBottomButton || position == showNotificationContent || position == photoHasStickerRow) { diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 6e3a234a7d5..e1f7f807114 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -10263,4 +10263,5 @@ Open links in system browser Note: SMS verification is limited to ONLY official mobile apps Third-party + Enable colored last seen dots From 9fb1221513721ede55444e3d6d10db6fd52c5941 Mon Sep 17 00:00:00 2001 From: derivativeoflog7 <100133857+DerivativeOfLog7@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:36:28 +0200 Subject: [PATCH 11/26] Document colored dots --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index d2ebd9af0fc..dedb2cb2e75 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,10 @@ Fork Client is a fork of the official Telegram for Android application. - Added ability to see unread count when you want to mark as read multiple dialogs. - Option to directly open the archive on pulldown - PiP mode for YouTube's in-app player +- Added an option to show colored dots to quickly see when a person was last online + - Yellow dot: last seen 15 minutes ago or less + - Orange dot: last seen 30 minutes ago or less + - Red dot: last seen 60 minutes ago or less ### Privacy Features: From 090f381198dc4cd80cb7adcf71c081fcc1047f2b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 7 Nov 2025 10:49:59 +0300 Subject: [PATCH 12/26] Added new option to hide archived stories. --- .../src/main/java/org/telegram/ui/DialogsActivity.java | 3 ++- .../main/java/org/telegram/ui/ForkSettingsActivity.java | 9 +++++++++ TMessagesProj/src/main/res/values/strings.xml | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 9619565ac53..a880e733f1d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -12959,7 +12959,8 @@ public void updateStoriesVisibility(boolean animated) { boolean onlySelfStories = !isArchive() && getStoriesController().hasOnlySelfStories(); boolean newVisibility; if (isArchive()) { - newVisibility = !getStoriesController().getHiddenList().isEmpty(); + boolean hideStoriesInArchive = MessagesController.getGlobalMainSettings().getBoolean("hideStoriesInArchive", false); + newVisibility = !hideStoriesInArchive && !getStoriesController().getHiddenList().isEmpty(); } else { newVisibility = !onlySelfStories && getStoriesController().hasStories(); onlySelfStories = getStoriesController().hasOnlySelfStories(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java index 1448c1595c9..ef8e5cd0205 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java @@ -167,6 +167,7 @@ public void invalidate() { private int botSkipShare; private int botSkipFullscreen; private int disableDefaultInAppBrowser; + private int hideStoriesInArchiveRow; private int lastFmLoginRow; private int stickerSizeRow; @@ -218,6 +219,7 @@ public boolean onFragmentCreate() { syncPinsRow = rowCount++; unmutedOnTopRow = rowCount++; openArchiveOnPull = rowCount++; + hideStoriesInArchiveRow = rowCount++; disableThumbsInDialogList = rowCount++; disableGlobalSearch = rowCount++; enableLastSeenDots = rowCount++; @@ -372,6 +374,8 @@ public boolean supportsPredictiveItemAnimations() { toggleGlobalMainSetting("mentionByName", view, false); } else if (position == openArchiveOnPull) { toggleGlobalMainSetting("openArchiveOnPull", view, false); + } else if (position == hideStoriesInArchiveRow) { + toggleGlobalMainSetting("hideStoriesInArchive", view, false); } else if (position == disableFlipPhotos) { toggleGlobalMainSetting("disableFlipPhotos", view, false); } else if (position == formatWithSeconds) { @@ -534,6 +538,9 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (position == openArchiveOnPull) { String t = LocaleController.getString("OpenArchiveOnPull", R.string.OpenArchiveOnPull); textCell.setTextAndCheck(t, preferences.getBoolean("openArchiveOnPull", true), false); + } else if (position == hideStoriesInArchiveRow) { + String t = LocaleController.getString("HideStoriesInArchive", R.string.HideStoriesInArchive); + textCell.setTextAndCheck(t, preferences.getBoolean("hideStoriesInArchive", false), false); } else if (position == disableFlipPhotos) { String t = LocaleController.getString("DisableFlipPhotos", R.string.DisableFlipPhotos); textCell.setTextAndCheck(t, preferences.getBoolean("disableFlipPhotos", false), false); @@ -599,6 +606,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { || position == replaceForward || position == mentionByName || position == openArchiveOnPull + || position == hideStoriesInArchiveRow || position == disableFlipPhotos || position == formatWithSeconds || position == disableThumbsInDialogList @@ -671,6 +679,7 @@ public int getItemViewType(int position) { || position == replaceForward || position == mentionByName || position == openArchiveOnPull + || position == hideStoriesInArchiveRow || position == disableFlipPhotos || position == formatWithSeconds || position == disableThumbsInDialogList diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index e1f7f807114..fa00a12c2e4 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -10264,4 +10264,5 @@ Note: SMS verification is limited to ONLY official mobile apps Third-party Enable colored last seen dots + Hide Stories in Archive From a806fe2548f0d65f8818d8bfadda03ff659dd5dc Mon Sep 17 00:00:00 2001 From: Korb Date: Tue, 21 Oct 2025 15:25:49 +0300 Subject: [PATCH 13/26] Update full_description.txt List markers and bold headings have been added. F-Droid has long announced the addition of basic HTML support, including for lists, but currently the only way to make HTML lists look good is to combine their code into a single line, which makes them difficult to read and edit. --- metadata/en-US/full_description.txt | 106 ++++++++++++++-------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/metadata/en-US/full_description.txt b/metadata/en-US/full_description.txt index 9804297d490..204bfa75f6d 100644 --- a/metadata/en-US/full_description.txt +++ b/metadata/en-US/full_description.txt @@ -1,60 +1,60 @@ Forkgram is a simple fork of the Telegram Messenger with a few minor improvements. -Features - Square avatars (sorry, I love it) - "Delete for everyone" enabled by default - Online colored statuses - Date of forwarded messages - Set rear camera as default for Video Messages - Buttons for backward and forward steps in audio player - Days of week to schedule time picker - A lot of self-destruct timer's options in secret chats - Send Video Messages without white background - "Sync Contacts" is disabled by default in Login activity - Send GIF with pre-written caption in Message Field - Send pre-written text from Message Field before sending sticker - See count of unread messages when selecting multiple dialogs +Features +͏ • Square avatars (sorry, I love it) +͏ • "Delete for everyone" enabled by default +͏ • Online colored statuses +͏ • Date of forwarded messages +͏ • Set rear camera as default for Video Messages +͏ • Buttons for backward and forward steps in audio player +͏ • Days of week to schedule time picker +͏ • A lot of self-destruct timer's options in secret chats +͏ • Send Video Messages without white background +͏ • "Sync Contacts" is disabled by default in Login activity +͏ • Send GIF with pre-written caption in Message Field +͏ • Send pre-written text from Message Field before sending sticker +͏ • See count of unread messages when selecting multiple dialogs -Abilities: - Open archive on pulldown - See profile info from dialogs list via context menu - Select all messages between 2 selections from bar - Hide title and avatar in dialogs - Open calendar from long click on floating date - Jump to the first message in any dialog - Copy ID of dialogs - Open Saved Messages on long click on search top button - Delete all your messages in group - Attach text to Voice Message before sending it - Seek Voice Messages from audio player alert - Set custom title of main view - Copy links without protocol - Mention users by name - Copy Username without long touch - Copy URL from inline button +Abilities +͏ • Open archive on pulldown +͏ • See profile info from dialogs list via context menu +͏ • Select all messages between 2 selections from bar +͏ • Hide title and avatar in dialogs +͏ • Open calendar from long click on floating date +͏ • Jump to the first message in any dialog +͏ • Copy ID of dialogs +͏ • Open Saved Messages on long click on search top button +͏ • Delete all your messages in group +͏ • Attach text to Voice Message before sending it +͏ • Seek Voice Messages from audio player alert +͏ • Set custom title of main view +͏ • Copy links without protocol +͏ • Mention users by name +͏ • Copy Username without long touch +͏ • Copy URL from inline button -Options: - Turn off sync pins to make unlimited number of pinned dialogs - Raise all unmuted messages above muted messages - Disable Global Search - Hide "Send As" button - Disable thumbs in dialog list - Disable premium features - Hide animated locked premium emoji from emoji panel - Disable quick reaction with double tap - Show notifications content when application is locked - Enable time format with seconds for messages - Disable flip through photos by tapping on their edge - Disable sending sticker info in photos - Disable parameters from bot links +Options +͏ • Turn off sync pins to make unlimited number of pinned dialogs +͏ • Raise all unmuted messages above muted messages +͏ • Disable Global Search +͏ • Hide "Send As" button +͏ • Disable thumbs in dialog list +͏ • Disable premium features +͏ • Hide animated locked premium emoji from emoji panel +͏ • Disable quick reaction with double tap +͏ • Show notifications content when application is locked +͏ • Enable time format with seconds for messages +͏ • Disable flip through photos by tapping on their edge +͏ • Disable sending sticker info in photos +͏ • Disable parameters from bot links -Fast Forward: - You can forward any message with Share Alert from Fast Forward menu item. - Share Alert now has two additional buttons: forward as copy (Anon Button) and forward without original caption (No-Text Button). - If you have pre-written comment, then No-Text Button will replace the original caption with your text. - A long press on both the Anon and No-Text buttons will send the message without sound - If a selected chat has Drafted Reply, then both Anon and No-Text buttons will send message to this Reply. +Fast Forward +͏ • You can forward any message with Share Alert from Fast Forward menu item. +͏ • Share Alert now has two additional buttons: forward as copy (Anon Button) and forward without original caption (No-Text Button). +͏ • If you have pre-written comment, then No-Text Button will replace the original caption with your text. +͏ • A long press on both the Anon and No-Text buttons will send the message without sound. +͏ • If a selected chat has Drafted Reply, then both Anon and No-Text buttons will send message to this Reply. - Selected messages can now be forwarded as grouped media. +Selected messages can now be forwarded as grouped media. - Media within webpage previews now can be forwarded as plain media to any chat. Just open the webpage preview and tap the Anon Button from the top. +͏Media within webpage previews now can be forwarded as plain media to any chat. Just open the webpage preview and tap the Anon Button from the top. From 39c9cb1c78bbc3bfb5d779dcb7d13272a28d8b19 Mon Sep 17 00:00:00 2001 From: Korb Date: Wed, 22 Oct 2025 15:38:38 +0300 Subject: [PATCH 14/26] Create ru/short_description.txt --- metadata/ru/full_description.txt | 60 +++++++++++++++++++++++++++++++ metadata/ru/short_description.txt | 1 + 2 files changed, 61 insertions(+) create mode 100644 metadata/ru/full_description.txt create mode 100644 metadata/ru/short_description.txt diff --git a/metadata/ru/full_description.txt b/metadata/ru/full_description.txt new file mode 100644 index 00000000000..aaa642a866c --- /dev/null +++ b/metadata/ru/full_description.txt @@ -0,0 +1,60 @@ +Forkgram — это форк мессенджера Telegram с множеством небольших улучшений. + +Особенности +͏ • Квадратные аватарки (извините, я их обожаю). +͏ • Функция «Удалить у всех» включена по умолчанию. +͏ • Цветные онлайн-статусы. +͏ • Оригинальные даты пересланных сообщений. +͏ • Установка задней камеры по умолчанию для видеосообщений. +͏ • Кнопки «вперёд» и «назад» в аудиоплеере. +͏ • Выбор дней недели при выборе отложенной отправки. +͏ • Множество настроек таймера самоуничтожения в секретных чатах. +͏ • Отправка видеосообщений без белого фона. +͏ • Функция «Синхронизация контактов» по умолчанию отключена. +͏ • Отправка GIF-анимации с подписью одним сообщением. +͏ • Отправка набранного текста перед отправляемым стикером. +͏ • Отображение количества непрочитанных сообщений при выборе нескольких чатов. + +Возможности +͏ • Прямое открытие архива минуя системный менеджер загрузки. +͏ • Доступ к данным профиля через контекстное меню списка чатов. +͏ • Выбор всех сообщений между двумя выделенными сообщениями. +͏ • Скрытие в чатах заголовка и аватарки собеседника. +͏ • Открытие календаря долгим нажатием на плавающем значке даты. +͏ • Быстрый переход к первому сообщению в любом чате. +͏ • Копирование идентификатора (ID) чата. +͏ • Открытие Избранного долгим нажатием на верхнюю кнопку поиска. +͏ • Быстрое удаление всех сообщений чата. + • Прикрепление текста к голосовому сообщению перед его отправкой. +͏ • Поиск голосовых сообщений через интерфейс аудиоплеера. +͏ • Установка заголовка основного экрана приложения. +͏ • Копирование ссылок без префикса протокола. +͏ • Упоминание пользователей по имени. +͏ • Копирование имени пользователя без долгого нажатия. +͏ • Копирование URL специальной кнопкой. + +Настройки +͏ • Отключить синхронизацию закреплённых чатов для отключения лимита на количество закреплённых чатов. +͏ • При сортировке списка чатов с новыми сообщениями показывать чаты с включенными уведомлениями выше чатов с отключенными уведомлениями. +͏ • Отключить глобальный поиск. +͏ • Скрыть кнопку настроек отправки вложения. +͏ • Отключить значки реакций в списке чатов. +͏ • Отключить премиум-функции. +͏ • Скрыть на панели эмодзи анимированные (и недоступные без Premium) Premium-эмодзи. +͏ • Отключить быструю реакцию при двойном нажатии. +͏ • Показывать содержимое сообщений при заблокированном приложении. +͏ • Включить для сообщений формат времени с секундами. +͏ • Отключить перелистывание фотографий касанием по краю экрана. +͏ • Отключить отправку информации о стикерах на фотографиях. +͏ • Удалять параметры отслеживания из ссылок ботов. + +Быстрая пересылка +͏͏ • Вы можете переслать любое сообщение с помощью «Share Alert» из меню «Fast Forward» («Быстрая пересылка»). +͏ • В функции «Share Alert» теперь есть две дополнительные кнопки: пересылка без указания изначального автора (кнопка «Anon Button», аналог «Скрыть имя отправителя» в официальном Telegram-клиенте) и «Переслать без исходного текста» (кнопка «No-Text Button», аналог «Скрыть подпись»). +͏ • Если у вас уже был набран текст, кнопка «No-Text Button» заменит исходный текст на ваш. +͏ • Длительное нажатие кнопок «Anon Button» и «No-Text Button» отправит сообщение без звука. +͏ • Если в чате для пересылки есть черновик ответа, обе кнопки отправят сообщение именно как ранее сохранённый ответ. + +Выбранные сообщения с вложениями теперь можно пересылать как группу (доступна функция их группировки). + +͏Медиафайлы из превью веб-страниц теперь можно пересылать как обычные медиафайлы в любой чат. Просто нажмите на превью веб-страницы и нажмите кнопку «Anon Button», расположенную сверху. diff --git a/metadata/ru/short_description.txt b/metadata/ru/short_description.txt new file mode 100644 index 00000000000..4d298bb48f6 --- /dev/null +++ b/metadata/ru/short_description.txt @@ -0,0 +1 @@ +Forkgram — это форк официального приложения Telegram для Android. From 33783d70126e932561c41bd2e8a8b8032f6d2ea5 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 20 Dec 2025 14:41:35 +0300 Subject: [PATCH 15/26] Disabled new passkeys. --- .../src/main/java/org/telegram/ui/PasskeysActivity.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasskeysActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasskeysActivity.java index 6e51979fdc6..d6f6ae17357 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PasskeysActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PasskeysActivity.java @@ -335,7 +335,9 @@ public static void showLearnSheet(Context context, int currentAccount, Theme.Res BottomSheet sheet = b.create(); ButtonWithCounterView button = new ButtonWithCounterView(context, resourcesProvider); - button.setText(getString(R.string.PasskeyFeatureButton), false); + button.setText("Disabled for non-official apps", false); + button.setEnabled(false); + button.setClickable(false); button.setOnClickListener(v -> { if (button.isLoading()) return; button.setLoading(true); @@ -384,6 +386,8 @@ public static void showLearnSheet(Context context, int currentAccount, Theme.Res } }); }); + button.setOnTouchListener((v, event) -> true); + button.setOnClickListener(null); if (withCreateButton) { linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 16, 0, 8)); From f705f4070360fe6a288e4ea099f101f3cb5791ad Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 20 Dec 2025 14:48:00 +0300 Subject: [PATCH 16/26] Added option to disable trigger video by volume change. --- .../src/main/java/org/telegram/ui/ChatActivity.java | 3 +++ .../main/java/org/telegram/ui/ForkSettingsActivity.java | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 63db6337093..f08ab43c71f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -29988,6 +29988,9 @@ public boolean maybePlayVisibleVideo() { if (chatListView == null) { return false; } + if (org.telegram.messenger.MessagesController.getGlobalMainSettings().getBoolean("disablePlayVisibleVideoOnVolume", false)) { + return false; + } MessageObject playingMessage = MediaController.getInstance().getPlayingMessageObject(); if (playingMessage != null && !playingMessage.isVideo()) { return false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java index ef8e5cd0205..f9df7b921fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java @@ -168,6 +168,7 @@ public void invalidate() { private int botSkipFullscreen; private int disableDefaultInAppBrowser; private int hideStoriesInArchiveRow; + private int disablePlayVisibleVideoOnVolumeRow; private int lastFmLoginRow; private int stickerSizeRow; @@ -241,6 +242,7 @@ public boolean onFragmentCreate() { disableSlideToNextChannel = rowCount++; disableRecentFilesAttachment = rowCount++; disableDefaultInAppBrowser = rowCount++; + disablePlayVisibleVideoOnVolumeRow = rowCount++; emptyRows.add(rowCount++); botSkipShare = rowCount++; @@ -362,6 +364,8 @@ public boolean supportsPredictiveItemAnimations() { toggleGlobalMainSetting("disableRecentFilesAttachment", view, false); } else if (position == disableDefaultInAppBrowser) { toggleGlobalMainSetting("disableDefaultInAppBrowser", view, false); + } else if (position == disablePlayVisibleVideoOnVolumeRow) { + toggleGlobalMainSetting("disablePlayVisibleVideoOnVolume", view, false); } else if (position == botSkipShare) { toggleGlobalMainSetting("botSkipShare", view, false); } else if (position == botSkipFullscreen) { @@ -519,6 +523,9 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (position == disableDefaultInAppBrowser) { String t = LocaleController.getString("DisableDefaultInAppBrowser", R.string.DisableDefaultInAppBrowser); textCell.setTextAndCheck(t, preferences.getBoolean("disableDefaultInAppBrowser", false), false); + } else if (position == disablePlayVisibleVideoOnVolumeRow) { + String t = "Disable play video on volume change"; + textCell.setTextAndCheck(t, preferences.getBoolean("disablePlayVisibleVideoOnVolume", false), false); } else if (position == botSkipShare) { String t = LocaleController.getString("BotSkipShare", R.string.BotSkipShare); textCell.setTextAndCheck(t, preferences.getBoolean("botSkipShare", false), false); @@ -600,6 +607,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { || position == disableSlideToNextChannel || position == disableRecentFilesAttachment || position == disableDefaultInAppBrowser + || position == disablePlayVisibleVideoOnVolumeRow || position == botSkipShare || position == botSkipFullscreen || position == lockPremium @@ -673,6 +681,7 @@ public int getItemViewType(int position) { || position == disableSlideToNextChannel || position == disableRecentFilesAttachment || position == disableDefaultInAppBrowser + || position == disablePlayVisibleVideoOnVolumeRow || position == botSkipShare || position == botSkipFullscreen || position == lockPremium From e746a355585625d203f20c5ee29408ab6245c314 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 20 Dec 2025 15:08:16 +0300 Subject: [PATCH 17/26] Added option for interval of updates check. --- .../telegram/messenger/forkgram/AppUpdater.kt | 5 +- .../org/telegram/ui/ForkSettingsActivity.java | 86 ++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/AppUpdater.kt b/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/AppUpdater.kt index 282e13223cb..f4ac947fa27 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/AppUpdater.kt +++ b/TMessagesProj/src/main/java/org/telegram/messenger/forkgram/AppUpdater.kt @@ -32,7 +32,7 @@ import java.net.HttpURLConnection import java.net.URL object AppUpdater { - private const val kCheckInterval = 30 * 60 * 1000 // 30 minutes. + private const val title = "The latest Forkgram version" private const val desc = "" private const val PREFS_NAME = "AppUpdaterPrefs" @@ -85,7 +85,8 @@ object AppUpdater { manual: Boolean = false) { try { - if (!manual && System.currentTimeMillis() - lastTimestampOfCheck < kCheckInterval) { + val updateInterval = MessagesController.getGlobalMainSettings().getLong("updateForkCheckInterval", 30 * 60 * 1000L) + if (!manual && (updateInterval == 0L || System.currentTimeMillis() - lastTimestampOfCheck < updateInterval)) { return } if (downloadId != 0L) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java index f9df7b921fc..f0ef21d9944 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java @@ -169,6 +169,7 @@ public void invalidate() { private int disableDefaultInAppBrowser; private int hideStoriesInArchiveRow; private int disablePlayVisibleVideoOnVolumeRow; + private int updateCheckIntervalRow; private int lastFmLoginRow; private int stickerSizeRow; @@ -201,6 +202,81 @@ private static String getLocale(String s, int i) { return LocaleController.getString(s, i); } + private String getUpdateIntervalText() { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + long interval = preferences.getLong("updateForkCheckInterval", 30 * 60 * 1000); + + if (interval == 0) { + return "Disabled"; + } else if (interval < 60 * 1000) { + return (interval / 1000) + " sec"; + } else if (interval < 60 * 60 * 1000) { + return (interval / (60 * 1000)) + " min"; + } else if (interval < 24 * 60 * 60 * 1000) { + return (interval / (60 * 60 * 1000)) + " h"; + } else { + return (interval / (24 * 60 * 60 * 1000)) + " d"; + } + } + + private void showUpdateIntervalDialog() { + String[] options = { + "Disabled", + "5 minutes", + "15 minutes", + "30 minutes", + "1 hour", + "2 hours", + "6 hours", + "12 hours", + "24 hours", + "2 days", + "7 days" + }; + + long[] intervals = { + 0, + 5 * 60 * 1000, + 15 * 60 * 1000, + 30 * 60 * 1000, + 60 * 60 * 1000, + 2 * 60 * 60 * 1000, + 6 * 60 * 60 * 1000, + 12 * 60 * 60 * 1000, + 24 * 60 * 60 * 1000, + 2 * 24 * 60 * 60 * 1000, + 7 * 24 * 60 * 60 * 1000 + }; + + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + long currentInterval = preferences.getLong("updateForkCheckInterval", 30 * 60 * 1000); + + int selectedIndex = 3; // default 30 minutes + for (int i = 0; i < intervals.length; i++) { + if (intervals[i] == currentInterval) { + selectedIndex = i; + break; + } + } + + android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(getParentActivity()); + builder.setTitle("Update Check Interval"); + builder.setSingleChoiceItems(options, selectedIndex, (dialog, which) -> { + SharedPreferences.Editor editor = preferences.edit(); + editor.putLong("updateForkCheckInterval", intervals[which]); + editor.commit(); + + RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findViewHolderForAdapterPosition(updateCheckIntervalRow); + if (holder != null && holder.itemView instanceof TextSettingsCell) { + ((TextSettingsCell) holder.itemView).getValueTextView().setText(getUpdateIntervalText()); + } + + dialog.dismiss(); + }); + builder.setNegativeButton("Cancel", null); + builder.show(); + } + @Override public boolean onFragmentCreate() { super.onFragmentCreate(); @@ -225,6 +301,7 @@ public boolean onFragmentCreate() { disableGlobalSearch = rowCount++; enableLastSeenDots = rowCount++; customTitleRow = rowCount++; + updateCheckIntervalRow = rowCount++; emptyRows.add(rowCount++); sectionRows.add(rowCount++); @@ -421,6 +498,8 @@ public boolean supportsPredictiveItemAnimations() { } return null; }); + } else if (position == updateCheckIntervalRow) { + showUpdateIntervalDialog(); } else if (position == lastFmLoginRow) { presentFragment(new LastFmLoginActivity()); } @@ -459,6 +538,10 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { String t = LocaleController.getString("EditAdminRank", R.string.EditAdminRank); final String v = MessagesController.getGlobalMainSettings().getString("forkCustomTitle", "Fork Client"); textCell.setTextAndValue(t, v, false); + } else if (position == updateCheckIntervalRow) { + String t = "Update Check Interval"; + String v = getUpdateIntervalText(); + textCell.setTextAndValue(t, v, false); } else if (position == lastFmLoginRow) { textCell.setTextAndIcon("Last.fm Login", R.drawable.ic_lastfm, false); } @@ -625,6 +708,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { || position == syncPinsRow || position == showNotificationContent || position == photoHasStickerRow + || position == updateCheckIntervalRow || position == lastFmLoginRow; return fork; } @@ -663,7 +747,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType public int getItemViewType(int position) { if (emptyRows.contains(position)) { return 1; - } else if (position == customTitleRow || position == lastFmLoginRow) { + } else if (position == customTitleRow || position == updateCheckIntervalRow || position == lastFmLoginRow) { return 2; } else if (position == squareAvatarsRow || position == hideSensitiveDataRow From e343f8a3b73ec5862957cb3139e2cf3264d49b9d Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 20 Dec 2025 15:26:42 +0300 Subject: [PATCH 18/26] Added offline status timer after MarkAsRead notification action. --- .../messenger/AutoMessageHeardReceiver.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java index 29f60ff7a30..bb63f0dcaf5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java @@ -11,8 +11,11 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.Handler; +import android.os.Looper; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_account; public class AutoMessageHeardReceiver extends BroadcastReceiver { @@ -35,6 +38,7 @@ public void onReceive(Context context, Intent intent) { accountInstance.getMessagesController().putUser(user1, true); MessagesController.getInstance(currentAccount).markDialogAsRead(dialogId, maxId, maxId, 0, false, 0, 0, true, 0); MessagesController.getInstance(currentAccount).markReactionsAsRead(dialogId, 0); + scheduleOfflineStatus(currentAccount); }); }); return; @@ -48,6 +52,7 @@ public void onReceive(Context context, Intent intent) { accountInstance.getMessagesController().putChat(chat1, true); MessagesController.getInstance(currentAccount).markDialogAsRead(dialogId, maxId, maxId, 0, false, 0, 0, true, 0); MessagesController.getInstance(currentAccount).markReactionsAsRead(dialogId, 0); + scheduleOfflineStatus(currentAccount); }); }); return; @@ -55,5 +60,25 @@ public void onReceive(Context context, Intent intent) { } MessagesController.getInstance(currentAccount).markDialogAsRead(dialogId, maxId, maxId, 0, false, 0, 0, true, 0); MessagesController.getInstance(currentAccount).markReactionsAsRead(dialogId, 0); + scheduleOfflineStatus(currentAccount); + } + + private void scheduleOfflineStatus(int currentAccount) { + try { + if (!UserConfig.isValidAccount(currentAccount)) { + return; + } + new Handler(Looper.getMainLooper()).postDelayed(() -> { + try { + TL_account.updateStatus req = new TL_account.updateStatus(); + req.offline = true; + org.telegram.tgnet.ConnectionsManager.getInstance(currentAccount).sendRequest(req, null); + } catch (Exception e) { + FileLog.e(e); + } + }, 5000); + } catch (Exception e) { + FileLog.e(e); + } } } From 78479c2bcd4c67f32be12be264d83113b0889b21 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 20 Dec 2025 15:39:36 +0300 Subject: [PATCH 19/26] Replaced frequent contacts with logged in accounts in App Shortcuts. --- .../messenger/MediaDataController.java | 97 +++++-------------- 1 file changed, 25 insertions(+), 72 deletions(-) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 357ad2ebbc5..adb93f88191 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -4933,15 +4933,17 @@ public void buildShortcuts() { if (Build.VERSION.SDK_INT < 23) { return; } - int maxShortcuts = ShortcutManagerCompat.getMaxShortcutCountPerActivity(ApplicationLoader.applicationContext) - 2; + int maxShortcuts = ShortcutManagerCompat.getMaxShortcutCountPerActivity(ApplicationLoader.applicationContext) - 1; if (maxShortcuts <= 0) { maxShortcuts = 5; } - ArrayList hintsFinal = new ArrayList<>(); - if (SharedConfig.passcodeHash.length() <= 0) { - for (int a = 0; a < hints.size(); a++) { - hintsFinal.add(hints.get(a)); - if (hintsFinal.size() == maxShortcuts - 2) { + + // Get available accounts instead of hints + ArrayList accountsList = new ArrayList<>(); + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + if (UserConfig.getInstance(a).isClientActivated()) { + accountsList.add(a); + if (accountsList.size() >= maxShortcuts) { break; } } @@ -4963,10 +4965,8 @@ public void buildShortcuts() { } else { List currentShortcuts = ShortcutManagerCompat.getDynamicShortcuts(ApplicationLoader.applicationContext); if (currentShortcuts != null && !currentShortcuts.isEmpty()) { - newShortcutsIds.add("compose"); - for (int a = 0; a < hintsFinal.size(); a++) { - TLRPC.TL_topPeer hint = hintsFinal.get(a); - newShortcutsIds.add("did3_" + MessageObject.getPeerId(hint.peer)); + for (int a = 0; a < accountsList.size(); a++) { + newShortcutsIds.add("account_" + accountsList.get(a)); } for (int a = 0; a < currentShortcuts.size(); a++) { String id = currentShortcuts.get(a).getId(); @@ -4985,71 +4985,26 @@ public void buildShortcuts() { } } - Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class); - intent.setAction("new_dialog"); ArrayList arrayList = new ArrayList<>(); - ShortcutInfoCompat shortcut = new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, "compose") - .setShortLabel(LocaleController.getString(R.string.NewConversationShortcut)) - .setLongLabel(LocaleController.getString(R.string.NewConversationShortcut)) - .setIcon(IconCompat.createWithResource(ApplicationLoader.applicationContext, R.drawable.shortcut_compose)) - .setRank(0) - .setIntent(intent) - .build(); - if (recreateShortcuts) { - ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, shortcut); - } else { - arrayList.add(shortcut); - if (shortcutsToUpdate.contains("compose")) { - ShortcutManagerCompat.updateShortcuts(ApplicationLoader.applicationContext, arrayList); - } else { - ShortcutManagerCompat.addDynamicShortcuts(ApplicationLoader.applicationContext, arrayList); - } - arrayList.clear(); - } - - HashSet category = new HashSet<>(1); - category.add(SHORTCUT_CATEGORY); - - for (int a = 0; a < hintsFinal.size(); a++) { - Intent shortcutIntent = new Intent(ApplicationLoader.applicationContext, OpenChatReceiver.class); - TLRPC.TL_topPeer hint = hintsFinal.get(a); + for (int a = 0; a < accountsList.size(); a++) { + int accountNum = accountsList.get(a); + Intent shortcutIntent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class); + shortcutIntent.setAction("switch_account"); + shortcutIntent.putExtra("currentAccount", accountNum); + shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - TLRPC.User user = null; - TLRPC.Chat chat = null; - long peerId = MessageObject.getPeerId(hint.peer); - if (DialogObject.isUserDialog(peerId)) { - shortcutIntent.putExtra("userId", peerId); - user = getMessagesController().getUser(peerId); - } else { - chat = getMessagesController().getChat(-peerId); - shortcutIntent.putExtra("chatId", -peerId); - } - if ((user == null || UserObject.isDeleted(user)) && chat == null) { + TLRPC.User user = UserConfig.getInstance(accountNum).getCurrentUser(); + if (user == null) { continue; } - String name; + String name = ContactsController.formatName(user.first_name, user.last_name); TLRPC.FileLocation photo = null; - - if (user != null) { - name = ContactsController.formatName(user.first_name, user.last_name); - if (user.photo != null) { - photo = user.photo.photo_small; - } - } else { - name = chat.title; - if (chat.photo != null) { - photo = chat.photo.photo_small; - } + if (user.photo != null) { + photo = user.photo.photo_small; } - shortcutIntent.putExtra("currentAccount", currentAccount); - shortcutIntent.setAction("com.tmessages.openchat" + peerId); - shortcutIntent.putExtra("dialogId", peerId); - shortcutIntent.putExtra("hash", SharedConfig.directShareHash); - shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - Bitmap bitmap = null; if (photo != null) { try { @@ -5083,18 +5038,16 @@ public void buildShortcuts() { } } - String id = "did3_" + peerId; + String id = "account_" + accountNum; if (TextUtils.isEmpty(name)) { - name = " "; + name = "Account " + (accountNum + 1); } ShortcutInfoCompat.Builder builder = new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, id) .setShortLabel(name) .setLongLabel(name) - .setRank(1 + a) + .setRank(a) .setIntent(shortcutIntent); - if (SharedConfig.directShare) { - builder.setCategories(category); - } + if (bitmap != null) { builder.setIcon(IconCompat.createWithBitmap(bitmap)); } else { From 462dea1145a69debd4e5f49db837b75c76083f2e Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 9 Dec 2025 08:07:44 +0300 Subject: [PATCH 20/26] Dumped version. --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 12289508daf..b9edf1772f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,8 +13,8 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Sat Mar 12 05:53:50 MSK 2016 -APP_VERSION_CODE=6341 -APP_VERSION_NAME=12.2.10 +APP_VERSION_CODE=6302 +APP_VERSION_NAME=12.2.7 APP_PACKAGE=org.telegram.messenger IS_PRIVATE=false RELEASE_KEY_PASSWORD=android From 44985e595017fdbb6e31110675b70faf8f9aace4 Mon Sep 17 00:00:00 2001 From: Timothy Redaelli Date: Wed, 17 Jan 2024 16:11:40 +0100 Subject: [PATCH 21/26] [MG] add a setting option in order to set a custom PUT to POST gateway --- .../org/telegram/messenger/SharedConfig.java | 10 +++++ .../messenger/UnifiedPushReceiver.java | 2 +- .../ui/NotificationsSettingsActivity.java | 42 ++++++++++++++++--- TMessagesProj/src/main/res/values/strings.xml | 2 + 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index d993f36ec7f..cfb21ee52ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -144,6 +144,14 @@ public static void togglePaymentByInvoice() { .apply(); } + public static void setUnifiedPushGateway(String value) { + unifiedPushGateway = value; + ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) + .edit() + .putString("unifiedPushGateway", unifiedPushGateway) + .apply(); + } + public static void toggleSurfaceInStories() { useSurfaceInStories = !useSurfaceInStories; ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) @@ -262,6 +270,7 @@ private static boolean isWhitelisted(MediaCodecInfo codecInfo) { public static boolean useSurfaceInStories; public static boolean photoViewerBlur = true; public static boolean payByInvoice; + public static String unifiedPushGateway; public static int stealthModeSendMessageConfirm = 2; private static int lastLocalId = -210000; @@ -674,6 +683,7 @@ public static void loadConfig() { multipleReactionsPromoShowed = preferences.getBoolean("multipleReactionsPromoShowed", false); callEncryptionHintDisplayedCount = preferences.getInt("callEncryptionHintDisplayedCount", 0); debugVideoQualities = preferences.getBoolean("debugVideoQualities", false); + unifiedPushGateway = preferences.getString("unifiedPushGateway", "https://p2p.belloworld.it/"); loadDebugConfig(preferences); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java index 78b35f4319c..2f401e3db2e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UnifiedPushReceiver.java @@ -35,7 +35,7 @@ public void onNewEndpoint(Context context, String endpoint, String instance){ PushListenerController.sendRegistrationToServer(PushListenerController.PUSH_TYPE_SIMPLE, endpoint); } else { try { - PushListenerController.sendRegistrationToServer(PushListenerController.PUSH_TYPE_SIMPLE, "https://p2p.belloworld.it/" + URLEncoder.encode(endpoint, "UTF-8")); + PushListenerController.sendRegistrationToServer(PushListenerController.PUSH_TYPE_SIMPLE, SharedConfig.unifiedPushGateway + URLEncoder.encode(endpoint, "UTF-8")); } catch (UnsupportedEncodingException e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 5850bc296c9..7bf604a0dd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -26,6 +26,7 @@ import android.util.LongSparseArray; import android.view.View; import android.view.ViewGroup; +import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; @@ -141,6 +142,7 @@ public static class NotificationException { private int androidAutoAlertRow; private int repeatRow; private int unifiedPushDistributorRow; + private int unifiedPushGatewayRow; private int resetSection2Row; private int resetSectionRow; private int resetNotificationsRow; @@ -151,6 +153,7 @@ public static class NotificationException { private boolean updateRingtone; private boolean updateRepeatNotifications; private boolean updateUnifiedPushDistributor; + private boolean updateUnifiedPushGateway; @Override public boolean onFragmentCreate() { @@ -208,6 +211,7 @@ public boolean onFragmentCreate() { androidAutoAlertRow = -1; repeatRow = rowCount++; unifiedPushDistributorRow = rowCount++; + unifiedPushGatewayRow = rowCount++; resetSection2Row = rowCount++; resetSectionRow = rowCount++; resetNotificationsRow = rowCount++; @@ -806,6 +810,30 @@ else if (position == unifiedPushDistributorRow) { .create(); dialogRef.set(dialog); showDialog(dialog); + } else if (position == unifiedPushGatewayRow) { + final EditText input = new EditText(getParentActivity()); + input.setText(SharedConfig.unifiedPushGateway); + input.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + input.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + Dialog dialog = new AlertDialog.Builder(getParentActivity()) + .setTitle(LocaleController.getString("UnifiedPushGateway", R.string.UnifiedPushGateway)) + .setMessage(LocaleController.getString("UnifiedPushGatewayInfo", R.string.UnifiedPushGatewayInfo)) + .setView(input) + .setPositiveButton(LocaleController.getString("OK", R.string.OK), (di, w) -> { + String value = String.valueOf(input.getText()); + if (!value.endsWith("/")) { + value += "/"; + } + SharedConfig.setUnifiedPushGateway(value); + UnifiedPush.registerApp(ApplicationLoader.applicationContext, + "default", + new ArrayList(), + "Telegram Simple Push"); + updateUnifiedPushGateway = true; + adapter.notifyItemChanged(position); + }).setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null) + .create(); + showDialog(dialog); } if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(!enabled); @@ -1070,6 +1098,14 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { settingsCell.setMultilineDetail(true); if (position == resetNotificationsRow) { settingsCell.setTextAndValue(getString("ResetAllNotifications", R.string.ResetAllNotifications), getString("UndoAllCustom", R.string.UndoAllCustom), false); + } else if (position == unifiedPushDistributorRow) { + String value = UnifiedPush.getAckDistributor(ApplicationLoader.applicationContext); + settingsCell.setTextAndValue(LocaleController.getString("UnifiedPushDistributor", R.string.UnifiedPushDistributor), value, false); + updateUnifiedPushDistributor = false; + } else if (position == unifiedPushGatewayRow) { + String value = SharedConfig.unifiedPushGateway; + settingsCell.setTextAndValue(LocaleController.getString("UnifiedPushGateway", R.string.UnifiedPushGateway), value, false); + updateUnifiedPushGateway = false; } break; } @@ -1214,10 +1250,6 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } textCell.setTextAndValue(getString("RepeatNotifications", R.string.RepeatNotifications), value, updateRepeatNotifications, false); updateRepeatNotifications = false; - } else if (position == unifiedPushDistributorRow) { - String value = UnifiedPush.getAckDistributor(ApplicationLoader.applicationContext); - textCell.setTextAndValue(LocaleController.getString("UnifiedPushDistributor", R.string.UnifiedPushDistributor), value, updateUnifiedPushDistributor, false); - updateUnifiedPushDistributor = false; } break; } @@ -1243,7 +1275,7 @@ public int getItemViewType(int position) { position == badgeNumberShowRow || position == inappPriorityRow || position == inchatSoundRow || position == androidAutoAlertRow || position == accountsAllRow) { return 1; - } else if (position == resetNotificationsRow) { + } else if (position == resetNotificationsRow || position == unifiedPushDistributorRow || position == unifiedPushGatewayRow) { return 2; } else if (position == privateRow || position == groupRow || position == channelsRow || position == storiesRow || position == reactionsRow) { return 3; diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index fa00a12c2e4..876830a3ec1 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -2635,6 +2635,8 @@ Kilometers Miles UnifiedPush Distributors + UnifiedPush PUT to POST gateway + Since Telegram Simple push uses PUT, but UnifiedPush only supports POST, a "PUT to POST" gateway is needed.\n\nPlease insert your gateway (or just keep the default value to use my proxy): Scan QR Code Scan QR Code No auth token found From de0cb99a9e73f23c141777b2b8f48737ff95b252 Mon Sep 17 00:00:00 2001 From: Golbinex <2061409-Golbinex@users.noreply.gitlab.com> Date: Wed, 7 Jan 2026 10:32:14 +0000 Subject: [PATCH 22/26] Add better description to Background Connection option --- .../java/org/telegram/ui/NotificationsSettingsActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 7bf604a0dd1..a104551e3d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -1077,7 +1077,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (position == androidAutoAlertRow) { checkCell.setTextAndCheck("Android Auto", preferences.getBoolean("EnableAutoNotifications", false), true); } else if (position == notificationsServiceConnectionRow) { - checkCell.setTextAndValueAndCheck(getString("NotificationsServiceConnection", R.string.NotificationsServiceConnection), "You won't be notified of new messages, if you disable this", preferences.getBoolean("pushConnection", getMessagesController().backgroundConnection), true, true); + checkCell.setTextAndValueAndCheck(getString("NotificationsServiceConnection", R.string.NotificationsServiceConnection), "If disabled, you won't be notified of new messages unless you enabled UnifiedPush", preferences.getBoolean("pushConnection", getMessagesController().backgroundConnection), true, true); } else if (position == badgeNumberShowRow) { checkCell.setTextAndCheck(getString("BadgeNumberShow", R.string.BadgeNumberShow), getNotificationsController().showBadgeNumber, true); } else if (position == badgeNumberMutedRow) { From 5a21080c34141df736d8949001800c22329df9b7 Mon Sep 17 00:00:00 2001 From: Timothy Redaelli Date: Mon, 25 Dec 2023 23:10:23 +0100 Subject: [PATCH 23/26] [MG] add toggle setting in Debug Menu to disable Unified Push support Co-authored-by: Golbinex <2061409-Golbinex@users.noreply.gitlab.com> --- .../messenger/PushListenerController.java | 59 ++++++++++--------- .../org/telegram/messenger/SharedConfig.java | 2 + .../org/telegram/ui/ForkSettingsActivity.java | 15 ++++- .../ui/NotificationsSettingsActivity.java | 6 +- TMessagesProj/src/main/res/values/strings.xml | 2 + 5 files changed, 53 insertions(+), 31 deletions(-) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index 74b1037aa37..38f68653f88 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -1696,6 +1696,7 @@ public boolean hasServices() { } public final static class UnifiedPushListenerServiceProvider implements IPushListenerServiceProvider { public final static UnifiedPushListenerServiceProvider INSTANCE = new UnifiedPushListenerServiceProvider(); + private final static UnifiedPushReceiver mReceiver = new UnifiedPushReceiver(); private UnifiedPushListenerServiceProvider(){}; @@ -1711,37 +1712,41 @@ public String getLogTitle() { @Override public void onRequestPushToken() { - String currentPushString = SharedConfig.pushString; - if (!TextUtils.isEmpty(currentPushString)) { - if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) { - FileLog.d("UnifiedPush endpoint = " + currentPushString); - } + if (SharedConfig.disableUnifiedPush) { + UnifiedPush.unregisterApp(ApplicationLoader.applicationContext, "default"); } else { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("No UnifiedPush string found"); + String currentPushString = SharedConfig.pushString; + if (!TextUtils.isEmpty(currentPushString)) { + if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) { + FileLog.d("UnifiedPush endpoint = " + currentPushString); + } + } else { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("No UnifiedPush string found"); + } } - } - Utilities.globalQueue.postRunnable(() -> { - try { - SharedConfig.pushStringGetTimeStart = SystemClock.elapsedRealtime(); - SharedConfig.saveConfig(); - if (UnifiedPush.getAckDistributor(ApplicationLoader.applicationContext) == null) { - List distributors = UnifiedPush.getDistributors(ApplicationLoader.applicationContext, new ArrayList<>()); - if (distributors.size() > 0) { - String distributor = distributors.get(0); - UnifiedPush.saveDistributor(ApplicationLoader.applicationContext, distributor); + Utilities.globalQueue.postRunnable(() -> { + try { + SharedConfig.pushStringGetTimeStart = SystemClock.elapsedRealtime(); + SharedConfig.saveConfig(); + if (UnifiedPush.getAckDistributor(ApplicationLoader.applicationContext) == null) { + List distributors = UnifiedPush.getDistributors(ApplicationLoader.applicationContext, new ArrayList<>()); + if (distributors.size() > 0) { + String distributor = distributors.get(0); + UnifiedPush.saveDistributor(ApplicationLoader.applicationContext, distributor); + } } + UnifiedPush.registerApp( + ApplicationLoader.applicationContext, + "default", + new ArrayList<>(), + "Telegram Simple Push" + ); + } catch (Throwable e) { + FileLog.e(e); } - UnifiedPush.registerApp( - ApplicationLoader.applicationContext, - "default", - new ArrayList<>(), - "Telegram Simple Push" - ); - } catch (Throwable e) { - FileLog.e(e); - } - }); + }); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index cfb21ee52ae..a84aca8acc4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -270,6 +270,7 @@ private static boolean isWhitelisted(MediaCodecInfo codecInfo) { public static boolean useSurfaceInStories; public static boolean photoViewerBlur = true; public static boolean payByInvoice; + public static boolean disableUnifiedPush; public static String unifiedPushGateway; public static int stealthModeSendMessageConfirm = 2; private static int lastLocalId = -210000; @@ -683,6 +684,7 @@ public static void loadConfig() { multipleReactionsPromoShowed = preferences.getBoolean("multipleReactionsPromoShowed", false); callEncryptionHintDisplayedCount = preferences.getInt("callEncryptionHintDisplayedCount", 0); debugVideoQualities = preferences.getBoolean("debugVideoQualities", false); + disableUnifiedPush = preferences.getBoolean("disableUnifiedPush", false); unifiedPushGateway = preferences.getString("unifiedPushGateway", "https://p2p.belloworld.it/"); loadDebugConfig(preferences); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java index f0ef21d9944..1d66b7dfcda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ForkSettingsActivity.java @@ -177,6 +177,8 @@ public void invalidate() { private ArrayList emptyRows = new ArrayList(); private int syncPinsRow; + private int disableUnifiedPushRow; + private static int getIntLocale(String str) { try { try { @@ -290,6 +292,7 @@ public boolean onFragmentCreate() { showNotificationContent = rowCount++; hideBottomButton = SharedConfig.isUserOwner() ? rowCount++ : -1; lockPremium = rowCount++; + disableUnifiedPushRow = rowCount++; emptyRows.add(rowCount++); sectionRows.add(rowCount++); @@ -502,6 +505,8 @@ public boolean supportsPredictiveItemAnimations() { showUpdateIntervalDialog(); } else if (position == lastFmLoginRow) { presentFragment(new LastFmLoginActivity()); + } else if (position == disableUnifiedPushRow) { + toggleGlobalMainSetting("disableUnifiedPush", view, false); } }); @@ -657,6 +662,10 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { String t = LocaleController.getString("HideSensitiveData", R.string.HideSensitiveData); String info = LocaleController.getString("SquareAvatarsInfo", R.string.SquareAvatarsInfo); textCell.setTextAndValueAndCheck(t, info, preferences.getBoolean("hideSensitiveData", false), true, false); + } else if (position == disableUnifiedPushRow) { + String t = LocaleController.getString("DisableUnifiedPush", R.string.DisableUnifiedPush); + String info = LocaleController.getString("DisableUnifiedPushInfo", R.string.DisableUnifiedPushInfo); + textCell.setTextAndValueAndCheck(t, info, preferences.getBoolean("disableUnifiedPush", true), true, false); } break; } @@ -709,7 +718,8 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { || position == showNotificationContent || position == photoHasStickerRow || position == updateCheckIntervalRow - || position == lastFmLoginRow; + || position == lastFmLoginRow + || position == disableUnifiedPushRow; return fork; } @@ -780,7 +790,8 @@ public int getItemViewType(int position) { || position == enableLastSeenDots || position == hideBottomButton || position == showNotificationContent - || position == photoHasStickerRow) { + || position == photoHasStickerRow + || position == disableUnifiedPushRow) { return 3; } else if (sectionRows.contains(position)) { return 4; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index a104551e3d0..1ae38bb7874 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -210,8 +210,10 @@ public boolean onFragmentCreate() { notificationsServiceConnectionRow = rowCount++; androidAutoAlertRow = -1; repeatRow = rowCount++; - unifiedPushDistributorRow = rowCount++; - unifiedPushGatewayRow = rowCount++; + if (!SharedConfig.disableUnifiedPush) { + unifiedPushDistributorRow = rowCount++; + unifiedPushGatewayRow = rowCount++; + } resetSection2Row = rowCount++; resetSectionRow = rowCount++; resetNotificationsRow = rowCount++; diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 876830a3ec1..fcee8c975e3 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -2637,6 +2637,8 @@ UnifiedPush Distributors UnifiedPush PUT to POST gateway Since Telegram Simple push uses PUT, but UnifiedPush only supports POST, a "PUT to POST" gateway is needed.\n\nPlease insert your gateway (or just keep the default value to use my proxy): + Disable UnifiedPush + Restart required Scan QR Code Scan QR Code No auth token found From ee7a29383e7796fe2949a93c32ed17c5dbebf122 Mon Sep 17 00:00:00 2001 From: tehcneko Date: Tue, 30 Sep 2025 09:59:53 +0800 Subject: [PATCH 24/26] Update monet themes --- TMessagesProj/src/main/assets/monet_dark.attheme | 1 + TMessagesProj/src/main/assets/monet_light.attheme | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/TMessagesProj/src/main/assets/monet_dark.attheme b/TMessagesProj/src/main/assets/monet_dark.attheme index 75e34cb8bf9..0f19c74b197 100644 --- a/TMessagesProj/src/main/assets/monet_dark.attheme +++ b/TMessagesProj/src/main/assets/monet_dark.attheme @@ -344,6 +344,7 @@ chat_outVoiceSeekbarSelected=n1_900 chat_previewDurationText=n1_50 chat_previewGameText=n1_50 chat_recordedVoiceBackground=n2_800 +chat_recordedVoiceDarkerBackground=a1_600 chat_recordedVoiceDot=a1_100 chat_recordedVoicePlayPause=a1_100 chat_recordedVoiceProgress=n2_100 diff --git a/TMessagesProj/src/main/assets/monet_light.attheme b/TMessagesProj/src/main/assets/monet_light.attheme index ff091beb8ba..ae9bd20b798 100644 --- a/TMessagesProj/src/main/assets/monet_light.attheme +++ b/TMessagesProj/src/main/assets/monet_light.attheme @@ -344,6 +344,7 @@ chat_outVoiceSeekbarSelected=n1_300 chat_previewDurationText=n1_50 chat_previewGameText=n1_50 chat_recordedVoiceBackground=a1_600 +chat_recordedVoiceDarkerBackground=a2_700 chat_recordedVoiceDot=a1_600 chat_recordedVoicePlayPause=a1_100 chat_recordedVoiceProgress=n1_300 @@ -698,7 +699,7 @@ windowBackgroundWhiteBlackText=a1_1000 windowBackgroundWhiteBlueButton=a1_600 windowBackgroundWhiteBlueHeader=a1_600 windowBackgroundWhiteBlueIcon=a1_600 -windowBackgroundWhiteBlueText=a1_600 +windowBackgroundWhiteBlueText=a1_1000 windowBackgroundWhiteBlueText2=a1_700 windowBackgroundWhiteBlueText3=a1_700 windowBackgroundWhiteBlueText4=a1_700 From 2c26beca2d7e26ca98b05b6a70300bbf029f0d92 Mon Sep 17 00:00:00 2001 From: tehcneko Date: Tue, 30 Dec 2025 10:14:47 +0800 Subject: [PATCH 25/26] Refactor monet themes --- .../src/main/assets/monet_dark.attheme | 40 ++-- .../src/main/assets/monet_light.attheme | 42 ++-- .../nekogram/helpers/MonetHelper.java | 203 ++++++++++-------- TMessagesProj/src/main/res/values/colors.xml | 5 - 4 files changed, 159 insertions(+), 131 deletions(-) diff --git a/TMessagesProj/src/main/assets/monet_dark.attheme b/TMessagesProj/src/main/assets/monet_dark.attheme index 0f19c74b197..221757b83c4 100644 --- a/TMessagesProj/src/main/assets/monet_dark.attheme +++ b/TMessagesProj/src/main/assets/monet_dark.attheme @@ -1,6 +1,6 @@ actionBarActionModeDefault=n1_900 actionBarActionModeDefaultIcon=a1_100 -actionBarActionModeDefaultSelector=n1_50 +actionBarActionModeDefaultSelector=n1_50_64 actionBarActionModeDefaultTop=a1_100 actionBarActionModeReaction=a1_100 actionBarActionModeReactionText=n1_900 @@ -10,13 +10,13 @@ actionBarDefault=n1_900 actionBarDefaultArchived=n1_900 actionBarDefaultArchivedIcon=a1_200 actionBarDefaultArchivedSearch=a2_400 -actionBarDefaultArchivedSelector=n2_800 +actionBarDefaultArchivedSelector=n2_800_64 actionBarDefaultArchivedTitle=a1_100 actionBarDefaultIcon=a1_100 actionBarDefaultSearch=n1_50 actionBarDefaultSearchArchivedPlaceholder=a1_1000 actionBarDefaultSearchPlaceholder=a1_100 -actionBarDefaultSelector=n2_800 +actionBarDefaultSelector=n2_800_64 actionBarDefaultSubmenuBackground=n1_900 actionBarDefaultSubmenuItem=n1_50 actionBarDefaultSubmenuItemIcon=a1_100 @@ -25,11 +25,11 @@ actionBarDefaultSubtitle=n1_50 actionBarDefaultTitle=a2_0 actionBarTabActiveText=a1_100 actionBarTabLine=a1_100 -actionBarTabSelector=a1_100 +actionBarTabSelector=a1_100_64 actionBarTabUnactiveText=n1_600 -actionBarWhiteSelector=n2_800 +actionBarWhiteSelector=n2_800_64 avatar_actionBarIconBlue=a1_100 -avatar_actionBarSelectorBlue=a1_100 +avatar_actionBarSelectorBlue=a1_100_64 avatar_backgroundActionBarBlue=n1_900 avatar_backgroundArchived=n2_800 avatar_backgroundArchivedHidden=n2_800 @@ -150,8 +150,8 @@ chat_emojiPanelIcon=a2_400 chat_emojiPanelIconSelected=a1_100 chat_emojiPanelNewTrending=a1_100 chat_emojiPanelShadowLine=n1_900 -chat_emojiPanelStickerPackSelector=n2_800 -chat_emojiPanelStickerPackSelectorLine=a1_100 +chat_emojiPanelStickerPackSelector=n2_800_64 +chat_emojiPanelStickerPackSelectorLine=a1_100_64 chat_emojiPanelStickerSetName=a2_100 chat_emojiPanelStickerSetNameHighlight=a3_200 chat_emojiPanelStickerSetNameIcon=a1_100 @@ -359,12 +359,12 @@ chat_searchPanelIcons=a1_100 chat_searchPanelText=n1_50 chat_secretChatStatusText=n1_50 chat_secretTimeText=a1_0 -chat_selectedBackground=a2_700 +chat_selectedBackground=a2_700_64 chat_sentError=n1_800 chat_sentErrorIcon=monetRedDark chat_serviceBackground=n2_800 chat_serviceBackgroundSelected=n1_900 -chat_serviceBackgroundSelector=n1_800 +chat_serviceBackgroundSelector=n1_800_64 chat_serviceIcon=a1_100 chat_serviceLink=a1_100 chat_serviceText=a1_100 @@ -414,7 +414,7 @@ contextProgressOuter4=n1_900 dialogBackground=n1_900 dialogBackgroundGray=n1_900 dialogButton=a1_100 -dialogButtonSelector=a1_100 +dialogButtonSelector=a1_100_64 dialogCardShadow=n2_800 dialogCameraIcon=a1_100 dialogCheckboxSquareBackground=n1_900 @@ -504,7 +504,7 @@ key_graySectionText=a1_200 key_player_progressCachedBackground=a2_300 key_sheet_other=a1_100 key_sheet_scrollUp=a1_100 -listSelectorSDK21=350681087 +listSelectorSDK21=n2_800_64 location_actionActiveIcon=a1_300 location_actionBackground=n1_900 location_actionIcon=a1_300 @@ -527,7 +527,7 @@ picker_badgeText=n1_900 picker_disabledButton=a1_100 picker_enabledButton=a1_100 player_actionBarItems=a1_100 -player_actionBarSelector=n2_800 +player_actionBarSelector=n2_800_64 player_actionBarSubtitle=n1_50 player_actionBarTitle=n1_50 player_background=n1_900 @@ -562,7 +562,7 @@ profile_creatorIcon=a1_100 profile_status=n1_50 profile_tabSelectedLine=a1_200 profile_tabSelectedText=a1_200 -profile_tabSelector=n1_900 +profile_tabSelector=n1_900_64 profile_tabText=n1_300 profile_title=n1_50 profile_verifiedBackground=n1_50 @@ -570,7 +570,7 @@ profile_verifiedCheck=n1_900 progressCircle=a1_100 radioBackground=a1_100 radioBackgroundChecked=a1_100 -reactionStarSelector=n1_900 +reactionStarSelector=n1_900_64 returnToCallBackground=n1_900 returnToCallMutedBackground=n1_300 returnToCallText=a1_100 @@ -600,7 +600,7 @@ statisticChartRipple=a1_800 statisticChartSignature=a1_100 statisticChartSignatureAlpha=a1_100 stickers_menu=a1_100 -stickers_menuSelector=n2_700 +stickers_menuSelector=n2_700_64 stories_circle_closeFriends1=a3_100 stories_circle_closeFriends2=a3_300 stories_circle_dialog1=a1_100 @@ -612,8 +612,8 @@ switch2TrackChecked=a1_100 switchTrack=n2_500 switchTrackBlue=a1_100 switchTrackBlueChecked=a1_100 -switchTrackBlueSelector=a1_100 -switchTrackBlueSelectorChecked=a1_100 +switchTrackBlueSelector=a1_100_64 +switchTrackBlueSelectorChecked=a1_100_64 switchTrackBlueThumb=a1_100 switchTrackBlueThumbChecked=n1_900 switchTrackChecked=a1_300 @@ -628,7 +628,7 @@ undo_cancelColor=a1_100 undo_infoColor=a1_100 voipgroup_actionBar=n1_900 voipgroup_actionBarItems=n1_0 -voipgroup_actionBarItemsSelector=n1_700 +voipgroup_actionBarItemsSelector=n1_700_64 voipgroup_actionBarUnscrolled=n1_900 voipgroup_checkMenu=a1_200 voipgroup_connectingProgress=a2_100 @@ -643,7 +643,7 @@ voipgroup_leaveButton=a3_300 voipgroup_leaveButtonScrolled=a3_200 voipgroup_leaveCallMenu=a1_100 voipgroup_listeningText=a2_300 -voipgroup_listSelector=n1_700 +voipgroup_listSelector=a1_100_64 voipgroup_listViewBackground=n2_800 voipgroup_listViewBackgroundUnscrolled=n2_800 voipgroup_muteButton=a1_500 diff --git a/TMessagesProj/src/main/assets/monet_light.attheme b/TMessagesProj/src/main/assets/monet_light.attheme index ae9bd20b798..5e5db6bdba2 100644 --- a/TMessagesProj/src/main/assets/monet_light.attheme +++ b/TMessagesProj/src/main/assets/monet_light.attheme @@ -1,6 +1,6 @@ actionBarActionModeDefault=n1_50 actionBarActionModeDefaultIcon=a1_600 -actionBarActionModeDefaultSelector=n1_50 +actionBarActionModeDefaultSelector=n1_50_64 actionBarActionModeDefaultTop=a1_600 actionBarActionModeReaction=a1_200 actionBarActionModeReactionText=n1_900 @@ -10,13 +10,13 @@ actionBarDefault=n1_50 actionBarDefaultArchived=n1_50 actionBarDefaultArchivedIcon=a1_600 actionBarDefaultArchivedSearch=a2_200 -actionBarDefaultArchivedSelector=n2_800 +actionBarDefaultArchivedSelector=n2_800_64 actionBarDefaultArchivedTitle=a1_600 actionBarDefaultIcon=a1_600 actionBarDefaultSearch=a1_1000 actionBarDefaultSearchArchivedPlaceholder=a1_0 actionBarDefaultSearchPlaceholder=a1_600 -actionBarDefaultSelector=n2_800 +actionBarDefaultSelector=n2_800_64 actionBarDefaultSubmenuBackground=n1_50 actionBarDefaultSubmenuItem=a1_1000 actionBarDefaultSubmenuItemIcon=a1_600 @@ -25,11 +25,11 @@ actionBarDefaultSubtitle=a1_1000 actionBarDefaultTitle=a1_1000 actionBarTabActiveText=a1_600 actionBarTabLine=a1_600 -actionBarTabSelector=a1_700 +actionBarTabSelector=a1_700_64 actionBarTabUnactiveText=a2_800 -actionBarWhiteSelector=n2_800 +actionBarWhiteSelector=n2_800_64 avatar_actionBarIconBlue=n1_1000 -avatar_actionBarSelectorBlue=a1_600 +avatar_actionBarSelectorBlue=a1_600_64 avatar_backgroundActionBarBlue=n1_50 avatar_backgroundArchived=a1_600 avatar_backgroundArchivedHidden=a1_600 @@ -101,7 +101,7 @@ chats_sentClock=a1_600 chats_sentError=n1_400 chats_sentErrorIcon=monetRedLight chats_sentReadCheck=a1_600 -chats_tabletSelectedOverlay=n1_100 +chats_tabletSelectedOverlay=n1_100_64 chats_tabUnreadActiveBackground=a1_600 chats_tabUnreadUnactiveBackground=a2_800 chats_unreadCounter=a1_600 @@ -150,8 +150,8 @@ chat_emojiPanelIcon=a2_300 chat_emojiPanelIconSelected=a1_600 chat_emojiPanelNewTrending=a1_600 chat_emojiPanelShadowLine=n1_50 -chat_emojiPanelStickerPackSelector=n2_800 -chat_emojiPanelStickerPackSelectorLine=a1_600 +chat_emojiPanelStickerPackSelector=n2_800_64 +chat_emojiPanelStickerPackSelectorLine=a1_600_64 chat_emojiPanelStickerSetName=a2_500 chat_emojiPanelStickerSetNameHighlight=a3_300 chat_emojiPanelStickerSetNameIcon=a1_600 @@ -359,12 +359,12 @@ chat_searchPanelIcons=a1_600 chat_searchPanelText=a1_1000 chat_secretChatStatusText=a1_600 chat_secretTimeText=a1_0 -chat_selectedBackground=n2_100 +chat_selectedBackground=n2_100_64 chat_sentError=n1_400 chat_sentErrorIcon=monetRedLight chat_serviceBackground=a1_600 chat_serviceBackgroundSelected=a1_600 -chat_serviceBackgroundSelector=a1_700 +chat_serviceBackgroundSelector=a1_700_64 chat_serviceIcon=n1_50 chat_serviceLink=n1_50 chat_serviceText=n1_50 @@ -414,7 +414,7 @@ contextProgressOuter4=n1_50 dialogBackground=n1_50 dialogBackgroundGray=n1_50 dialogButton=a1_600 -dialogButtonSelector=a1_600 +dialogButtonSelector=a1_600_64 dialogCardShadow=n2_200 dialogCameraIcon=a1_600 dialogCheckboxSquareBackground=a1_600 @@ -504,7 +504,7 @@ key_graySectionText=a1_600 key_player_progressCachedBackground=a2_300 key_sheet_other=a1_600 key_sheet_scrollUp=a1_600 -listSelectorSDK21=251658240 +listSelectorSDK21=n1_700_64 location_actionActiveIcon=a1_600 location_actionBackground=n1_50 location_actionIcon=a1_600 @@ -527,7 +527,7 @@ picker_badgeText=n1_900 picker_disabledButton=a1_600 picker_enabledButton=a1_600 player_actionBarItems=a1_1000 -player_actionBarSelector=a1_600 +player_actionBarSelector=a1_600_64 player_actionBarSubtitle=a1_600 player_actionBarTitle=a1_1000 player_background=n1_50 @@ -562,14 +562,14 @@ profile_creatorIcon=a1_600 profile_status=a1_1000 profile_tabSelectedLine=a1_700 profile_tabSelectedText=a1_700 -profile_tabSelector=a1_600 +profile_tabSelector=a1_600_64 profile_tabText=n1_500 profile_title=a1_1000 profile_verifiedBackground=a1_600 profile_verifiedCheck=a1_0 progressCircle=a1_600 radioBackground=a1_600 -reactionStarSelector=n1_50 +reactionStarSelector=n1_50_64 radioBackgroundChecked=a1_600 returnToCallBackground=n1_50 returnToCallMutedBackground=n1_600 @@ -600,7 +600,7 @@ statisticChartRipple=a1_300 statisticChartSignature=a1_600 statisticChartSignatureAlpha=a1_600 stickers_menu=a1_600 -stickers_menuSelector=n2_200 +stickers_menuSelector=n2_200_64 stories_circle_closeFriends1=a3_400 stories_circle_closeFriends2=a3_600 stories_circle_dialog1=a1_400 @@ -612,8 +612,8 @@ switch2TrackChecked=a1_700 switchTrack=n2_500 switchTrackBlue=a1_600 switchTrackBlueChecked=a1_600 -switchTrackBlueSelector=a1_600 -switchTrackBlueSelectorChecked=a1_600 +switchTrackBlueSelector=a1_600_64 +switchTrackBlueSelectorChecked=a1_600_64 switchTrackBlueThumb=n1_50 switchTrackBlueThumbChecked=n1_50 switchTrackChecked=a1_700 @@ -628,7 +628,7 @@ undo_cancelColor=a1_200 undo_infoColor=n1_50 voipgroup_actionBar=n1_900 voipgroup_actionBarItems=n1_0 -voipgroup_actionBarItemsSelector=n1_700 +voipgroup_actionBarItemsSelector=n1_700_64 voipgroup_actionBarUnscrolled=n1_900 voipgroup_checkMenu=a1_200 voipgroup_connectingProgress=a2_100 @@ -643,7 +643,7 @@ voipgroup_leaveButton=a3_300 voipgroup_leaveButtonScrolled=a3_200 voipgroup_leaveCallMenu=a1_100 voipgroup_listeningText=a2_300 -voipgroup_listSelector=n1_700 +voipgroup_listSelector=n1_700_64 voipgroup_listViewBackground=n2_800 voipgroup_listViewBackgroundUnscrolled=n2_800 voipgroup_muteButton=a1_500 diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java index b9c18cfff68..c77e9c68910 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/MonetHelper.java @@ -4,111 +4,144 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.graphics.Color; import android.os.Build; import android.os.PatternMatcher; +import android.util.SparseIntArray; import androidx.annotation.RequiresApi; +import androidx.core.graphics.ColorUtils; import com.google.android.exoplayer2.util.Log; import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.OKLCH; import org.telegram.ui.ActionBar.Theme; -import java.util.HashMap; - @RequiresApi(api = Build.VERSION_CODES.S) public class MonetHelper { - private static final HashMap ids = new HashMap<>(); + private static final SparseIntArray IDS = new SparseIntArray() {{ + put(1_1_0000, android.R.color.system_accent1_0); + put(1_1_0010, android.R.color.system_accent1_10); + put(1_1_0050, android.R.color.system_accent1_50); + put(1_1_0100, android.R.color.system_accent1_100); + put(1_1_0200, android.R.color.system_accent1_200); + put(1_1_0300, android.R.color.system_accent1_300); + put(1_1_0400, android.R.color.system_accent1_400); + put(1_1_0500, android.R.color.system_accent1_500); + put(1_1_0600, android.R.color.system_accent1_600); + put(1_1_0700, android.R.color.system_accent1_700); + put(1_1_0800, android.R.color.system_accent1_800); + put(1_1_0900, android.R.color.system_accent1_900); + put(1_1_1000, android.R.color.system_accent1_1000); + put(1_2_0000, android.R.color.system_accent2_0); + put(1_2_0010, android.R.color.system_accent2_10); + put(1_2_0050, android.R.color.system_accent2_50); + put(1_2_0100, android.R.color.system_accent2_100); + put(1_2_0200, android.R.color.system_accent2_200); + put(1_2_0300, android.R.color.system_accent2_300); + put(1_2_0400, android.R.color.system_accent2_400); + put(1_2_0500, android.R.color.system_accent2_500); + put(1_2_0600, android.R.color.system_accent2_600); + put(1_2_0700, android.R.color.system_accent2_700); + put(1_2_0800, android.R.color.system_accent2_800); + put(1_2_0900, android.R.color.system_accent2_900); + put(1_2_1000, android.R.color.system_accent2_1000); + put(1_3_0000, android.R.color.system_accent3_0); + put(1_3_0010, android.R.color.system_accent3_10); + put(1_3_0050, android.R.color.system_accent3_50); + put(1_3_0100, android.R.color.system_accent3_100); + put(1_3_0200, android.R.color.system_accent3_200); + put(1_3_0300, android.R.color.system_accent3_300); + put(1_3_0400, android.R.color.system_accent3_400); + put(1_3_0500, android.R.color.system_accent3_500); + put(1_3_0600, android.R.color.system_accent3_600); + put(1_3_0700, android.R.color.system_accent3_700); + put(1_3_0800, android.R.color.system_accent3_800); + put(1_3_0900, android.R.color.system_accent3_900); + put(1_3_1000, android.R.color.system_accent3_1000); + put(2_1_0000, android.R.color.system_neutral1_0); + put(2_1_0010, android.R.color.system_neutral1_10); + put(2_1_0050, android.R.color.system_neutral1_50); + put(2_1_0100, android.R.color.system_neutral1_100); + put(2_1_0200, android.R.color.system_neutral1_200); + put(2_1_0300, android.R.color.system_neutral1_300); + put(2_1_0400, android.R.color.system_neutral1_400); + put(2_1_0500, android.R.color.system_neutral1_500); + put(2_1_0600, android.R.color.system_neutral1_600); + put(2_1_0700, android.R.color.system_neutral1_700); + put(2_1_0800, android.R.color.system_neutral1_800); + put(2_1_0900, android.R.color.system_neutral1_900); + put(2_1_1000, android.R.color.system_neutral1_1000); + put(2_2_0000, android.R.color.system_neutral2_0); + put(2_2_0010, android.R.color.system_neutral2_10); + put(2_2_0050, android.R.color.system_neutral2_50); + put(2_2_0100, android.R.color.system_neutral2_100); + put(2_2_0200, android.R.color.system_neutral2_200); + put(2_2_0300, android.R.color.system_neutral2_300); + put(2_2_0400, android.R.color.system_neutral2_400); + put(2_2_0500, android.R.color.system_neutral2_500); + put(2_2_0600, android.R.color.system_neutral2_600); + put(2_2_0700, android.R.color.system_neutral2_700); + put(2_2_0800, android.R.color.system_neutral2_800); + put(2_2_0900, android.R.color.system_neutral2_900); + put(2_2_1000, android.R.color.system_neutral2_1000); + }}; private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED"; private static final OverlayChangeReceiver overlayChangeReceiver = new OverlayChangeReceiver(); - static { - ids.put("a1_0", android.R.color.system_accent1_0); - ids.put("a1_10", android.R.color.system_accent1_10); - ids.put("a1_50", android.R.color.system_accent1_50); - ids.put("a1_100", android.R.color.system_accent1_100); - ids.put("a1_200", android.R.color.system_accent1_200); - ids.put("a1_300", android.R.color.system_accent1_300); - ids.put("a1_400", android.R.color.system_accent1_400); - ids.put("a1_500", android.R.color.system_accent1_500); - ids.put("a1_600", android.R.color.system_accent1_600); - ids.put("a1_700", android.R.color.system_accent1_700); - ids.put("a1_800", android.R.color.system_accent1_800); - ids.put("a1_900", android.R.color.system_accent1_900); - ids.put("a1_1000", android.R.color.system_accent1_1000); - ids.put("a2_0", android.R.color.system_accent2_0); - ids.put("a2_10", android.R.color.system_accent2_10); - ids.put("a2_50", android.R.color.system_accent2_50); - ids.put("a2_100", android.R.color.system_accent2_100); - ids.put("a2_200", android.R.color.system_accent2_200); - ids.put("a2_300", android.R.color.system_accent2_300); - ids.put("a2_400", android.R.color.system_accent2_400); - ids.put("a2_500", android.R.color.system_accent2_500); - ids.put("a2_600", android.R.color.system_accent2_600); - ids.put("a2_700", android.R.color.system_accent2_700); - ids.put("a2_800", android.R.color.system_accent2_800); - ids.put("a2_900", android.R.color.system_accent2_900); - ids.put("a2_1000", android.R.color.system_accent2_1000); - ids.put("a3_0", android.R.color.system_accent3_0); - ids.put("a3_10", android.R.color.system_accent3_10); - ids.put("a3_50", android.R.color.system_accent3_50); - ids.put("a3_100", android.R.color.system_accent3_100); - ids.put("a3_200", android.R.color.system_accent3_200); - ids.put("a3_300", android.R.color.system_accent3_300); - ids.put("a3_400", android.R.color.system_accent3_400); - ids.put("a3_500", android.R.color.system_accent3_500); - ids.put("a3_600", android.R.color.system_accent3_600); - ids.put("a3_700", android.R.color.system_accent3_700); - ids.put("a3_800", android.R.color.system_accent3_800); - ids.put("a3_900", android.R.color.system_accent3_900); - ids.put("a3_1000", android.R.color.system_accent3_1000); - ids.put("n1_0", android.R.color.system_neutral1_0); - ids.put("n1_10", android.R.color.system_neutral1_10); - ids.put("n1_50", android.R.color.system_neutral1_50); - ids.put("n1_100", android.R.color.system_neutral1_100); - ids.put("n1_200", android.R.color.system_neutral1_200); - ids.put("n1_300", android.R.color.system_neutral1_300); - ids.put("n1_400", android.R.color.system_neutral1_400); - ids.put("n1_500", android.R.color.system_neutral1_500); - ids.put("n1_600", android.R.color.system_neutral1_600); - ids.put("n1_700", android.R.color.system_neutral1_700); - ids.put("n1_800", android.R.color.system_neutral1_800); - ids.put("n1_900", android.R.color.system_neutral1_900); - ids.put("n1_1000", android.R.color.system_neutral1_1000); - ids.put("n2_0", android.R.color.system_neutral2_0); - ids.put("n2_10", android.R.color.system_neutral2_10); - ids.put("n2_50", android.R.color.system_neutral2_50); - ids.put("n2_100", android.R.color.system_neutral2_100); - ids.put("n2_200", android.R.color.system_neutral2_200); - ids.put("n2_300", android.R.color.system_neutral2_300); - ids.put("n2_400", android.R.color.system_neutral2_400); - ids.put("n2_500", android.R.color.system_neutral2_500); - ids.put("n2_600", android.R.color.system_neutral2_600); - ids.put("n2_700", android.R.color.system_neutral2_700); - ids.put("n2_800", android.R.color.system_neutral2_800); - ids.put("n2_900", android.R.color.system_neutral2_900); - ids.put("n2_1000", android.R.color.system_neutral2_1000); - ids.put("monetRedDark", R.color.monetRedDark); - ids.put("monetRedLight", R.color.monetRedLight); - ids.put("monetRedCall", R.color.monetRedCall); - ids.put("monetGreenCall", R.color.monetGreenCall); - } - public static int getColor(String color) { return getColor(color, false); } - public static int getColor(String color, boolean amoled) { - try { - //noinspection ConstantConditions - int id = ids.getOrDefault(amoled && "n1_900".equals(color) ? "n1_1000" : color, 0); - return ApplicationLoader.applicationContext.getColor(id); - } catch (Exception e) { - Log.e("Theme", "Error loading color " + color); - e.printStackTrace(); + private static int adaptHue(int baseColor, int hueColor) { + var hueoklch = OKLCH.rgb2oklch(OKLCH.rgb(hueColor)); + var oklch = OKLCH.rgb2oklch(OKLCH.rgb(baseColor)); + oklch[2] = hueoklch[2]; + if (Double.isNaN(hueoklch[2]) || hueoklch[1] < .08f) { + oklch[1] = hueoklch[1]; + } + return OKLCH.rgb(OKLCH.oklch2rgb(oklch)); + } + + public static int getColor(String rawColor, boolean amoled) { + if (rawColor.length() < 4) { return 0; } + var context = ApplicationLoader.applicationContext; + if (rawColor.startsWith("monet")) { + var primaryColor = context.getColor(android.R.color.system_accent1_400); + if (rawColor.startsWith("monetRed")) { + return adaptHue(primaryColor, Color.RED); + } else { + return adaptHue(primaryColor, Color.GREEN); + } + } + var group = rawColor.charAt(0) == 'a' ? 1 : 2; + var palette = Integer.parseInt(rawColor.substring(1, 2)); + var alphaStart = rawColor.indexOf("_", 3); + int shade; + int alpha; + if (alphaStart > 0) { + shade = Integer.parseInt(rawColor.substring(3, alphaStart)); + alpha = Integer.parseInt(rawColor.substring(alphaStart + 1)); + } else { + shade = Integer.parseInt(rawColor.substring(3)); + alpha = -1; + } + if (amoled && group == 2 && palette == 1 && shade == 900) { + shade = 1000; + } + var key = group * 1_0_0000 + palette * 1_0000 + shade; + var id = IDS.get(key); + if (id == 0) { + return 0; + } + var color = context.getColor(id); + if (alpha != -1) { + color = ColorUtils.setAlphaComponent(color, alpha); + } + return color; } private static class OverlayChangeReceiver extends BroadcastReceiver { @@ -128,7 +161,7 @@ public void unregister(Context context) { public void onReceive(Context context, Intent intent) { if (ACTION_OVERLAY_CHANGED.equals(intent.getAction())) { if (Theme.getActiveTheme().isMonet()) { - Theme.applyTheme(Theme.getActiveTheme()); + Theme.applyTheme(Theme.getActiveTheme(), Theme.isCurrentThemeNight()); } } } diff --git a/TMessagesProj/src/main/res/values/colors.xml b/TMessagesProj/src/main/res/values/colors.xml index 67ff1040d3f..191969b526d 100755 --- a/TMessagesProj/src/main/res/values/colors.xml +++ b/TMessagesProj/src/main/res/values/colors.xml @@ -8,9 +8,4 @@ #d9d9d9 #8B8D8F #999999 - - #B3261E - #F2B8B5 - #4CAF50 - #EF5350 \ No newline at end of file From 13728a43ed7721cd2d10dc526ee42ab28e95d7b1 Mon Sep 17 00:00:00 2001 From: Golbinex <2061409-Golbinex@users.noreply.gitlab.com> Date: Sat, 10 Jan 2026 22:37:59 +0100 Subject: [PATCH 26/26] Add building instructions for Debian 13 and bump Java version --- BUILDING.md | 39 ++++++++++++++++++++++++++++++++++++++ README.md | 3 +++ TMessagesProj/build.gradle | 4 ++-- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 BUILDING.md diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 00000000000..09201cef499 --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,39 @@ +## Building instructions for Debian 13 + +1. Install necessary software + - `sudo apt install cmake golang gperf meson ninja-build sdkmanager wget yasm` + - `sudo apt install google-android-platform-35-installer google-android-build-tools-35.0.0-installer google-android-ndk-r21e-installer google-android-ndk-r23c-installer openjdk-21-jdk-headless` + +2. Don't forget to include the submodules when you clone: + - `git clone --recursive https://github.com/forkgram/TelegramAndroid.git` + +3. Build native FFmpeg and BoringSSL dependencies: + - Go to the `TMessagesProj/jni` folder and execute the following (define the paths to your NDK and Ninja): + + ``` + export NDK=/usr/lib/android-sdk/ndk/21.4.7075529 + export NINJA_PATH=/usr/bin/ninja + export ANDROID_SDK=/usr/lib/android-sdk + export ANDROID_HOME=/usr/lib/android-sdk + sudo sdkmanager "cmake;3.22.1" --sdk_root /usr/lib/android-sdk + ./build_libvpx_clang.sh + ./build_ffmpeg_clang.sh + ./patch_ffmpeg.sh + ./patch_boringssl.sh + ./build_boringssl.sh + ``` + +4. If you want to publish a modified version of Telegram: + - You should get **your own API key** here: https://core.telegram.org/api/obtaining_api_id and edit a file called `gradle.properties` in the source root directory. + The contents should look like this: + ``` + APP_ID = 12345 + APP_HASH = aaaaaaaabbbbbbccccccfffffff001122 + ``` + - Do not use the name Telegram and the standard logo (white paper plane in a blue circle) for your app — or make sure your users understand that it is unofficial + - Take good care of your users' data and privacy + - **Please remember to publish your code too in order to comply with the licenses** + +The project can be built with Android Studio or from the command line with gradle: + +`./gradlew assembleAfatRelease` \ No newline at end of file diff --git a/README.md b/README.md index dedb2cb2e75..da7f091675e 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,6 @@ Fork Client is a fork of the official Telegram for Android application. ## Downloads: You can download binaries from Releases or from my [Telegram channel Forkgram](https://t.me/forkgram). + +## Building instructions for Debian 13: +[BUILDING.md](BUILDING.md) \ No newline at end of file diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index ff6d520c9c3..47af7a82403 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -92,8 +92,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 coreLibraryDesugaringEnabled true }