From 7ba9838a2d38e69d37300926dd79be3f3285fb5a Mon Sep 17 00:00:00 2001 From: DrKLO Date: Fri, 9 Apr 2021 16:17:32 +0300 Subject: [PATCH] Update to 7.6.1 (2274) --- TMessagesProj/build.gradle | 4 +- .../jni/voip/tgcalls/AudioDeviceHelper.cpp | 9 +- .../voip/tgcalls/FakeAudioDeviceModule.cpp | 66 +- .../jni/voip/tgcalls/FakeAudioDeviceModule.h | 2 + TMessagesProj/jni/voip/tgcalls/Message.h | 12 +- .../jni/voip/tgcalls/StaticThreads.cpp | 6 + .../jni/voip/tgcalls/StaticThreads.h | 7 + .../tgcalls/group/GroupInstanceCustomImpl.cpp | 152 ++-- .../voip/tgcalls/group/GroupInstanceImpl.h | 5 +- .../jni/voip/tgcalls/group/StreamingPart.cpp | 9 +- .../telegram/messenger/AndroidUtilities.java | 2 +- .../messenger/AutoMessageHeardReceiver.java | 2 +- .../messenger/AutoMessageReplyReceiver.java | 2 +- .../org/telegram/messenger/BuildVars.java | 2 +- .../org/telegram/messenger/ChatObject.java | 101 ++- .../org/telegram/messenger/ImageLoader.java | 2 +- .../org/telegram/messenger/ImageReceiver.java | 5 + .../org/telegram/messenger/MessageObject.java | 54 +- .../messenger/MessagesController.java | 61 +- .../telegram/messenger/MessagesStorage.java | 6 +- .../NotificationCallbackReceiver.java | 3 + .../NotificationDismissReceiver.java | 3 + .../messenger/NotificationRepeat.java | 10 +- .../messenger/PopupReplyReceiver.java | 6 +- .../org/telegram/messenger/SharedConfig.java | 10 + .../org/telegram/messenger/UserConfig.java | 4 + .../messenger/VideoEncodingService.java | 4 + .../telegram/messenger/WearReplyReceiver.java | 2 +- .../messenger/voip/VoIPBaseService.java | 86 +- .../telegram/messenger/voip/VoIPService.java | 144 ++-- .../main/java/org/telegram/tgnet/TLRPC.java | 299 ++++--- .../telegram/ui/ActionBar/SimpleTextView.java | 99 ++- .../ui/Adapters/DialogsSearchAdapter.java | 9 +- .../org/telegram/ui/Adapters/FiltersView.java | 4 +- .../telegram/ui/Adapters/MentionsAdapter.java | 20 +- .../telegram/ui/Adapters/SearchAdapter.java | 6 +- .../ui/Adapters/SearchAdapterHelper.java | 20 +- .../java/org/telegram/ui/ArticleViewer.java | 3 + .../ui/AvatarPreviewPagerIndicator.java | 383 +++++++++ .../java/org/telegram/ui/BubbleActivity.java | 6 +- .../telegram/ui/Cells/ChatMessageCell.java | 4 +- .../ui/Cells/GroupCallInvitedCell.java | 4 + .../telegram/ui/Cells/GroupCallUserCell.java | 73 +- .../telegram/ui/ChannelAdminLogActivity.java | 19 +- .../java/org/telegram/ui/ChatActivity.java | 60 +- .../telegram/ui/ChatRightsEditActivity.java | 2 +- .../org/telegram/ui/ChatUsersActivity.java | 304 ++++--- .../ui/Components/AdminLogFilterAlert.java | 7 +- .../telegram/ui/Components/AlertsCreator.java | 6 +- .../ui/Components/BackupImageView.java | 5 + .../org/telegram/ui/Components/Bulletin.java | 2 +- .../ui/Components/CircularViewPager.java | 4 +- .../ui/Components/FragmentContextView.java | 2 +- .../ui/Components/GroupVoipInviteAlert.java | 25 +- .../telegram/ui/Components/ImageUpdater.java | 38 +- .../Components/InviteMembersBottomSheet.java | 10 +- .../telegram/ui/Components/JoinCallAlert.java | 16 +- .../telegram/ui/Components/PipVideoView.java | 12 +- .../ui/Components/ProfileGalleryView.java | 191 ++++- .../telegram/ui/Components/ShareAlert.java | 133 ++- .../ui/Components/SharedMediaLayout.java | 8 +- .../org/telegram/ui/Components/UndoView.java | 20 +- .../ui/Components/VideoForwardDrawable.java | 27 + .../ui/Components/VideoPlayerSeekBar.java | 28 +- .../ui/Components/ViewPagerFixed.java | 4 + .../java/org/telegram/ui/DialogsActivity.java | 30 +- .../org/telegram/ui/FilterUsersActivity.java | 6 +- .../org/telegram/ui/FilteredSearchView.java | 8 +- .../org/telegram/ui/GroupCallActivity.java | 774 +++++++++++++----- .../org/telegram/ui/GroupCreateActivity.java | 8 +- .../java/org/telegram/ui/LaunchActivity.java | 94 ++- .../NotificationsCustomSettingsActivity.java | 4 +- .../org/telegram/ui/PassportActivity.java | 14 +- .../org/telegram/ui/PeopleNearbyActivity.java | 4 +- .../java/org/telegram/ui/PhotoViewer.java | 29 +- .../ui/PopupNotificationActivity.java | 3 + .../java/org/telegram/ui/ProfileActivity.java | 35 +- .../org/telegram/ui/StatisticActivity.java | 50 +- .../ui/TooManyCommunitiesActivity.java | 2 +- .../java/org/telegram/ui/VoIPFragment.java | 23 +- .../webrtc/voiceengine/WebRtcAudioTrack.java | 19 +- .../main/res/drawable-hdpi/msg_msgbubble3.png | Bin 0 -> 949 bytes .../main/res/drawable-mdpi/msg_msgbubble3.png | Bin 0 -> 653 bytes .../res/drawable-xhdpi/msg_msgbubble3.png | Bin 0 -> 1220 bytes .../res/drawable-xxhdpi/msg_msgbubble3.png | Bin 0 -> 1881 bytes TMessagesProj/src/main/res/values/strings.xml | 6 +- 86 files changed, 2799 insertions(+), 944 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/msg_msgbubble3.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/msg_msgbubble3.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/msg_msgbubble3.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/msg_msgbubble3.png diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 1b1f6e225..68e83acd4 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -288,7 +288,7 @@ android { } } - defaultConfig.versionCode = 2264 + defaultConfig.versionCode = 2274 applicationVariants.all { variant -> variant.outputs.all { output -> @@ -307,7 +307,7 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 29 - versionName "7.6.0" + versionName "7.6.1" vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] diff --git a/TMessagesProj/jni/voip/tgcalls/AudioDeviceHelper.cpp b/TMessagesProj/jni/voip/tgcalls/AudioDeviceHelper.cpp index e3866e4b6..a6f0151b2 100644 --- a/TMessagesProj/jni/voip/tgcalls/AudioDeviceHelper.cpp +++ b/TMessagesProj/jni/voip/tgcalls/AudioDeviceHelper.cpp @@ -49,11 +49,13 @@ void SetAudioInputDeviceById(webrtc::AudioDeviceModule *adm, const std::string & RTC_LOG(LS_ERROR) << "setAudioInputDevice(" << id << "): Could not get recording devices count: " << count << "."; return finish(); } - for (auto i = 0; i != count; ++i) { + + int16_t order = !id.empty() && id[0] == '#' ? static_cast(std::stoi(id.substr(1))) : -1; + for (auto i = 0; i != count; ++i) { char name[webrtc::kAdmMaxDeviceNameSize + 1] = { 0 }; char guid[webrtc::kAdmMaxGuidSize + 1] = { 0 }; adm->RecordingDeviceName(i, name, guid); - if (!SkipDefaultDevice(name) && id == guid) { + if ((!SkipDefaultDevice(name) && id == guid) || order == i) { const auto result = adm->SetRecordingDevice(i); if (result != 0) { RTC_LOG(LS_ERROR) << "setAudioInputDevice(" << id << ") name '" << std::string(name) << "' failed: " << result << "."; @@ -95,11 +97,12 @@ void SetAudioOutputDeviceById(webrtc::AudioDeviceModule *adm, const std::string RTC_LOG(LS_ERROR) << "setAudioOutputDevice(" << id << "): Could not get playout devices count: " << count << "."; return finish(); } + int16_t order = !id.empty() && id[0] == '#' ? static_cast(std::stoi(id.substr(1))) : -1; for (auto i = 0; i != count; ++i) { char name[webrtc::kAdmMaxDeviceNameSize + 1] = { 0 }; char guid[webrtc::kAdmMaxGuidSize + 1] = { 0 }; adm->PlayoutDeviceName(i, name, guid); - if (!SkipDefaultDevice(name) && id == guid) { + if ((!SkipDefaultDevice(name) && id == guid) || order == i) { const auto result = adm->SetPlayoutDevice(i); if (result != 0) { RTC_LOG(LS_ERROR) << "setAudioOutputDevice(" << id << ") name '" << std::string(name) << "' failed: " << result << "."; diff --git a/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.cpp b/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.cpp index 4c5d7d66e..787cd6a4c 100644 --- a/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.cpp +++ b/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.cpp @@ -6,6 +6,8 @@ #include "rtc_base/time_utils.h" #include +#include +#include namespace tgcalls { class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleDefault { @@ -19,7 +21,20 @@ class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleD FakeAudioDeviceModuleImpl(webrtc::TaskQueueFactory*, FakeAudioDeviceModule::Options options, std::shared_ptr renderer) - : num_channels_{options.num_channels}, samples_per_sec_{options.samples_per_sec}, renderer_(std::move(renderer)) { + : num_channels_{options.num_channels}, samples_per_sec_{options.samples_per_sec}, scheduler_(options.scheduler_), renderer_(std::move(renderer)) { + if (!scheduler_) { + scheduler_ = [](auto f) { + std::thread([f = std::move(f)]() { + while (true) { + double wait = f(); + if (wait < 0) { + return; + } + std::this_thread::sleep_for(std::chrono::microseconds (static_cast(wait * 1000000))); + } + }).detach(); + }; + } RTC_CHECK(num_channels_ == 1 || num_channels_ == 2); auto good_sample_rate = [](size_t sr) { return sr == 8000 || sr == 16000 || sr == 32000 || sr == 44100 || sr == 48000; @@ -65,22 +80,22 @@ class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleD } int32_t RegisterAudioCallback(webrtc::AudioTransport* callback) override { - webrtc::MutexLock lock(&lock_); + std::unique_lock lock(mutex_); audio_callback_ = callback; return 0; } int32_t StartPlayout() override { - webrtc::MutexLock lock(&lock_); + std::unique_lock lock(mutex_); RTC_CHECK(renderer_); if (rendering_) { return 0; } + need_rendering_ = true; rendering_ = true; - renderThread_ = std::make_unique( - RenderThreadFunction, this, "webrtc_fake_audio_module_capture_thread", rtc::kRealtimePriority); - renderThread_->Start(); - + scheduler_([this]{ + return Render() / 1000000.0; + }); return 0; } @@ -88,15 +103,11 @@ class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleD if (!rendering_) { return 0; } - decltype(renderThread_) thread; - { - webrtc::MutexLock lock(&lock_); - thread = std::move(renderThread_); - rendering_ = false; - } + need_rendering_ = false; + std::unique_lock lock(mutex_); + cond_.wait(lock, [this]{ return !rendering_; }); - thread->Stop(); return 0; } @@ -105,22 +116,15 @@ class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleD } private: - static void RenderThreadFunction(void* pThis) { - auto* device = static_cast(pThis); - while (true) { - int wait_for_us = device->Render(); - if (wait_for_us < 0) { - break; - } - std::this_thread::sleep_for(std::chrono::microseconds(wait_for_us)); - } - } int32_t Render() { - webrtc::MutexLock lock(&lock_); - if (!rendering_) { + std::unique_lock lock(mutex_); + if (!need_rendering_) { + rendering_ = false; + cond_.notify_all(); return -1; } + size_t samples_out = 0; int64_t elapsed_time_ms = -1; int64_t ntp_time_ms = -1; @@ -157,13 +161,17 @@ class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleD const uint32_t samples_per_sec_; size_t samples_per_frame_{0}; - mutable webrtc::Mutex lock_; + std::function scheduler_; + + mutable std::mutex mutex_; + std::atomic need_rendering_{false}; std::atomic rendering_{false}; + std::condition_variable cond_; std::unique_ptr renderThread_; webrtc::AudioTransport* audio_callback_{nullptr}; - const std::shared_ptr renderer_ RTC_GUARDED_BY(lock_); - std::vector playout_buffer_ RTC_GUARDED_BY(lock_); + const std::shared_ptr renderer_; + std::vector playout_buffer_; }; std::function(webrtc::TaskQueueFactory*)> FakeAudioDeviceModule::Creator( diff --git a/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.h b/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.h index e383389a1..b0d5ffe8e 100644 --- a/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.h +++ b/TMessagesProj/jni/voip/tgcalls/FakeAudioDeviceModule.h @@ -32,9 +32,11 @@ class FakeAudioDeviceModule { return 10000; } }; + using Task = std::function; struct Options { uint32_t samples_per_sec{48000}; uint32_t num_channels{2}; + std::function scheduler_; }; static std::function(webrtc::TaskQueueFactory *)> Creator( std::shared_ptr renderer, Options options); diff --git a/TMessagesProj/jni/voip/tgcalls/Message.h b/TMessagesProj/jni/voip/tgcalls/Message.h index 850e861ac..62add213b 100644 --- a/TMessagesProj/jni/voip/tgcalls/Message.h +++ b/TMessagesProj/jni/voip/tgcalls/Message.h @@ -19,18 +19,14 @@ struct PeerIceParameters { std::string ufrag; std::string pwd; - PeerIceParameters() { - } - + PeerIceParameters() = default; + PeerIceParameters(const PeerIceParameters &other) = default; + PeerIceParameters(std::string ufrag_, std::string pwd_) : ufrag(ufrag_), pwd(pwd_) { } - - PeerIceParameters(const PeerIceParameters &other) : - ufrag(other.ufrag), - pwd(other.pwd) { - } + }; struct CandidatesListMessage { diff --git a/TMessagesProj/jni/voip/tgcalls/StaticThreads.cpp b/TMessagesProj/jni/voip/tgcalls/StaticThreads.cpp index 4ed2a594a..5db98dc2f 100644 --- a/TMessagesProj/jni/voip/tgcalls/StaticThreads.cpp +++ b/TMessagesProj/jni/voip/tgcalls/StaticThreads.cpp @@ -1,6 +1,7 @@ #include "StaticThreads.h" #include "rtc_base/thread.h" +#include "call/call.h" #include #include @@ -63,6 +64,7 @@ public: media_ = create("tgc-media" + suffix); worker_ = create("tgc-work" + suffix); process_ = create("tgc-process" + suffix); + shared_module_thread_ = webrtc::SharedModuleThread::Create(webrtc::ProcessThread::Create("tgc-module"), nullptr); } rtc::Thread *getNetworkThread() override { @@ -77,12 +79,16 @@ public: rtc::Thread *getProcessThread() override { return process_.get(); } + rtc::scoped_refptr getSharedModuleThread() override { + return shared_module_thread_; + } private: Thread network_; Thread media_; Thread worker_; Thread process_; + rtc::scoped_refptr shared_module_thread_; static Thread create(const std::string &name) { return init(std::unique_ptr(rtc::Thread::Create()), name); diff --git a/TMessagesProj/jni/voip/tgcalls/StaticThreads.h b/TMessagesProj/jni/voip/tgcalls/StaticThreads.h index f396a1501..08c8a9814 100644 --- a/TMessagesProj/jni/voip/tgcalls/StaticThreads.h +++ b/TMessagesProj/jni/voip/tgcalls/StaticThreads.h @@ -5,6 +5,11 @@ namespace rtc { class Thread; +template +class scoped_refptr; +} +namespace webrtc { +class SharedModuleThread; } namespace tgcalls { @@ -16,6 +21,7 @@ public: virtual rtc::Thread *getMediaThread() = 0; virtual rtc::Thread *getWorkerThread() = 0; virtual rtc::Thread *getProcessThread() = 0; + virtual rtc::scoped_refptr getSharedModuleThread() = 0; // it is not possible to decrease pool size static void setPoolSize(size_t size); @@ -27,6 +33,7 @@ rtc::Thread *getNetworkThread(); rtc::Thread *getMediaThread(); rtc::Thread *getWorkerThread(); rtc::Thread *getProcessThread(); +rtc::scoped_refptr getSharedMoudleThread(); std::shared_ptr &getThreads(); } diff --git a/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp b/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp index 11da1c7e1..9b2e078b8 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp @@ -255,35 +255,46 @@ private: std::function _sendPacket; }; -static const int kVadResultHistoryLength = 8; +static const int kVadResultHistoryLength = 6; class CombinedVad { private: webrtc::VadLevelAnalyzer _vadWithLevel; float _vadResultHistory[kVadResultHistoryLength]; + std::atomic _waitingFramesToProcess{0}; + bool _countFrames; public: - CombinedVad() { + CombinedVad(bool count = false) { for (float & i : _vadResultHistory) { i = 0.0f; } + _countFrames = count; } ~CombinedVad() = default; + bool incWaitingFrames() { + if (_waitingFramesToProcess > 5) { + return false; + } + _waitingFramesToProcess++; + return true; + } + bool update(webrtc::AudioBuffer *buffer) { - float speech_probability; if (buffer) { webrtc::AudioFrameView frameView(buffer->channels(), buffer->num_channels(), buffer->num_frames()); auto result = _vadWithLevel.AnalyzeFrame(frameView); - speech_probability = result.speech_probability; - } else { - speech_probability = std::min(1.0f, _vadResultHistory[kVadResultHistoryLength - 1] * 1.2f); + float speech_probability = result.speech_probability; + for (int i = 1; i < kVadResultHistoryLength; i++) { + _vadResultHistory[i - 1] = _vadResultHistory[i]; + } + _vadResultHistory[kVadResultHistoryLength - 1] = speech_probability; + if (_countFrames) { + _waitingFramesToProcess--; + } } - for (int i = 1; i < kVadResultHistoryLength; i++) { - _vadResultHistory[i - 1] = _vadResultHistory[i]; - } - _vadResultHistory[kVadResultHistoryLength - 1] = speech_probability; float movingAverage = 0.0f; for (float i : _vadResultHistory) { @@ -291,12 +302,7 @@ public: } movingAverage /= (float)kVadResultHistoryLength; - bool vadResult = false; - if (movingAverage > 0.8f) { - vadResult = true; - } - - return vadResult; + return movingAverage > 0.6f; } }; @@ -316,7 +322,7 @@ public: AudioSinkImpl(std::function update, ChannelId channel_id, std::function onAudioFrame) : _update(update), _channel_id(channel_id), _onAudioFrame(std::move(onAudioFrame)) { - _vad = std::make_shared(); + _vad = std::make_shared(true); } virtual ~AudioSinkImpl() { @@ -334,8 +340,8 @@ public: frame.ntp_time_ms = 0; _onAudioFrame(_channel_id.actualSsrc, frame); } - if (audio.channels == 1) { - const auto samples = (const int16_t *) audio.data; + if (_update && audio.channels == 1) { + const int16_t *samples = (const int16_t *)audio.data; int numberOfSamplesInFrame = (int)audio.samples_per_channel; for (int i = 0; i < numberOfSamplesInFrame; i++) { @@ -355,7 +361,7 @@ public: _peakCount = 0; webrtc::AudioBuffer *buffer; - if (!_skipNextSampleProcess) { + if (_vad->incWaitingFrames()) { buffer = new webrtc::AudioBuffer(audio.sample_rate, 1, 48000, 1, 48000, 1); webrtc::StreamConfig config(audio.sample_rate, 1); buffer->CopyFrom(samples, config); @@ -364,7 +370,6 @@ public: } _update(Update(level, buffer, _vad)); - _skipNextSampleProcess = !_skipNextSampleProcess; } } } @@ -377,7 +382,6 @@ private: int _peakCount = 0; uint16_t _peak = 0; - bool _skipNextSampleProcess = false; }; class VideoSinkImpl : public rtc::VideoSinkInterface { @@ -563,9 +567,7 @@ public: outgoingAudioDescription.reset(); incomingAudioDescription.reset(); - std::unique_ptr audioLevelSink(new AudioSinkImpl([onAudioLevelUpdated = std::move(onAudioLevelUpdated)](AudioSinkImpl::Update update) { - onAudioLevelUpdated(update); - }, _ssrc, std::move(onAudioFrame))); + std::unique_ptr audioLevelSink(new AudioSinkImpl(onAudioLevelUpdated, _ssrc, std::move(onAudioFrame))); _audioChannel->media_channel()->SetRawAudioSink(ssrc.networkSsrc, std::move(audioLevelSink)); _audioChannel->SignalSentPacket().connect(this, &IncomingAudioChannel::OnSentPacket_w); @@ -801,6 +803,8 @@ public: _participantDescriptionsRequired(descriptor.participantDescriptionsRequired), _requestBroadcastPart(descriptor.requestBroadcastPart), _videoCapture(descriptor.videoCapture), + _disableIncomingChannels(descriptor.disableIncomingChannels), + _useDummyChannel(descriptor.useDummyChannel), _eventLog(std::make_unique()), _taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory()), _createAudioDeviceModule(descriptor.createAudioDeviceModule), @@ -850,6 +854,7 @@ public: webrtc::field_trial::InitFieldTrialsFromString( "WebRTC-Audio-Allocation/min:32kbps,max:32kbps/" "WebRTC-Audio-OpusMinPacketLossRate/Enabled-1/" +// "WebRTC-TaskQueuePacer/Enabled/" ); _networkManager.reset(new ThreadLocalObject(_threads->getNetworkThread(), [weak, threads = _threads] () mutable { @@ -902,20 +907,23 @@ public: mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(_platformContext); mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(_platformContext); - auto analyzer = new AudioCaptureAnalyzer([weak, threads = _threads](GroupLevelValue const &level) { - threads->getProcessThread()->PostTask(RTC_FROM_HERE, [weak, level](){ - auto strong = weak.lock(); - if (!strong) { - return; - } - strong->_myAudioLevel = level; + if (_audioLevelsUpdated) { + auto analyzer = new AudioCaptureAnalyzer([weak, threads = _threads](GroupLevelValue const &level) { + threads->getMediaThread()->PostTask(RTC_FROM_HERE, [weak, level, threads]() { + auto strong = weak.lock(); + if (!strong) { + return; + } + strong->_myAudioLevel = level; + threads->getMediaThread()->Invoke(RTC_FROM_HERE, [strong] {}); + }); }); - }); - webrtc::AudioProcessingBuilder builder; - builder.SetCaptureAnalyzer(std::unique_ptr(analyzer)); + webrtc::AudioProcessingBuilder builder; + builder.SetCaptureAnalyzer(std::unique_ptr(analyzer)); - mediaDeps.audio_processing = builder.Create(); + mediaDeps.audio_processing = builder.Create(); + } _audioDeviceModule = createAudioDeviceModule(); if (!_audioDeviceModule) { @@ -937,6 +945,7 @@ public: callConfig.task_queue_factory = _taskQueueFactory.get(); callConfig.trials = &_fieldTrials; callConfig.audio_state = _channelManager->media_engine()->voice().GetAudioState(); + //_call.reset(webrtc::Call::Create(callConfig, _threads->getSharedModuleThread())); _call.reset(webrtc::Call::Create(callConfig)); _uniqueRandomIdGenerator.reset(new rtc::UniqueRandomIdGenerator()); @@ -956,7 +965,9 @@ public: //_outgoingVideoChannel->UpdateRtpTransport(nullptr); } - beginLevelsTimer(50); + if (_audioLevelsUpdated) { + beginLevelsTimer(50); + } if (_videoCapture) { setVideoCapture(_videoCapture, [](GroupJoinPayload) {}, true); @@ -964,7 +975,9 @@ public: adjustBitratePreferences(true); - addIncomingAudioChannel("_dummy", ChannelId(1), true); + if (_useDummyChannel) { + addIncomingAudioChannel("_dummy", ChannelId(1), true); + } beginNetworkStatusTimer(0); } @@ -1043,7 +1056,7 @@ public: void beginLevelsTimer(int timeoutMs) { const auto weak = std::weak_ptr(shared_from_this()); - _threads->getProcessThread()->PostDelayedTask(RTC_FROM_HERE, [weak]() { + _threads->getMediaThread()->PostDelayedTask(RTC_FROM_HERE, [weak]() { auto strong = weak.lock(); if (!strong) { return; @@ -2029,25 +2042,33 @@ public: const auto weak = std::weak_ptr(shared_from_this()); - std::unique_ptr channel(new IncomingAudioChannel( - _channelManager.get(), - _call.get(), - _rtpTransport, - _uniqueRandomIdGenerator.get(), - isRawPcm, - ssrc, - [weak, ssrc = ssrc, threads = _threads](AudioSinkImpl::Update update) { - threads->getProcessThread()->PostTask(RTC_FROM_HERE, [weak, ssrc, update]() { + std::function onAudioSinkUpdate; + if (_audioLevelsUpdated) { + onAudioSinkUpdate = [weak, ssrc = ssrc, threads = _threads](AudioSinkImpl::Update update) { + threads->getProcessThread()->PostTask(RTC_FROM_HERE, [weak, ssrc, update, threads]() { + bool voice = update.vad->update(update.buffer.get()); + threads->getMediaThread()->PostTask(RTC_FROM_HERE, [weak, ssrc, update, voice]() { auto strong = weak.lock(); if (!strong) { return; } GroupLevelValue mappedUpdate; mappedUpdate.level = update.level; - mappedUpdate.voice = update.vad->update(update.buffer.get()); + mappedUpdate.voice = voice; strong->_audioLevels[ssrc] = mappedUpdate; }); - }, + }); + }; + } + + std::unique_ptr channel(new IncomingAudioChannel( + _channelManager.get(), + _call.get(), + _rtpTransport, + _uniqueRandomIdGenerator.get(), + isRawPcm, + ssrc, + std::move(onAudioSinkUpdate), _onAudioFrame, *_threads )); @@ -2179,6 +2200,7 @@ private: std::function(std::shared_ptr, int64_t, int64_t, std::function)> _requestBroadcastPart; std::shared_ptr _videoCapture; bool _disableIncomingChannels = false; + bool _useDummyChannel{true}; int64_t _lastUnknownSsrcsReport = 0; std::set _pendingUnknownSsrcs; @@ -2353,5 +2375,35 @@ void GroupInstanceCustomImpl::setFullSizeVideoSsrc(uint32_t ssrc) { internal->setFullSizeVideoSsrc(ssrc); }); } +std::vector GroupInstanceInterface::getAudioDevices(AudioDevice::Type type) { + auto result = std::vector(); +#ifdef WEBRTC_LINUX //Not needed for ios, and some crl::sync stuff is needed for windows + const auto resolve = [&] { + const auto queueFactory = webrtc::CreateDefaultTaskQueueFactory(); + const auto info = webrtc::AudioDeviceModule::Create( + webrtc::AudioDeviceModule::kPlatformDefaultAudio, + queueFactory.get()); + if (!info || info->Init() < 0) { + return; + } + const auto count = type == AudioDevice::Type::Input ? info->RecordingDevices() : info->PlayoutDevices(); + if (count <= 0) { + return; + } + for (auto i = int16_t(); i != count; ++i) { + char name[webrtc::kAdmMaxDeviceNameSize + 1] = { 0 }; + char id[webrtc::kAdmMaxGuidSize + 1] = { 0 }; + if (type == AudioDevice::Type::Input) { + info->RecordingDeviceName(i, name, id); + } else { + info->PlayoutDeviceName(i, name, id); + } + result.push_back({ id, name }); + } + }; + resolve(); +#endif + return result; +} } // namespace tgcalls diff --git a/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceImpl.h b/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceImpl.h index 75df4876d..a752652d7 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceImpl.h +++ b/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceImpl.h @@ -85,7 +85,8 @@ struct GroupInstanceDescriptor { std::function onAudioFrame; std::string initialInputDeviceId; std::string initialOutputDeviceId; - bool debugIgnoreMissingSsrcs = false; + bool useDummyChannel{true}; + bool disableIncomingChannels{false}; std::function(webrtc::TaskQueueFactory*)> createAudioDeviceModule; std::shared_ptr videoCapture; std::function const &)> incomingVideoSourcesUpdated; @@ -197,7 +198,7 @@ public: std::string name; std::string guid; }; - + static std::vector getAudioDevices(AudioDevice::Type type); }; } // namespace tgcalls diff --git a/TMessagesProj/jni/voip/tgcalls/group/StreamingPart.cpp b/TMessagesProj/jni/voip/tgcalls/group/StreamingPart.cpp index 4b84f55eb..1b8dbf113 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/StreamingPart.cpp +++ b/TMessagesProj/jni/voip/tgcalls/group/StreamingPart.cpp @@ -12,6 +12,7 @@ extern "C" { #include #include #include +#include namespace tgcalls { @@ -288,6 +289,10 @@ public: } private: + static int16_t sampleFloatToInt16(float sample) { + return av_clip_int16 (static_cast(lrint(sample*32767))); + } + void fillPcmBuffer() { _pcmBufferSampleSize = 0; _pcmBufferSampleOffset = 0; @@ -356,7 +361,7 @@ private: case AV_SAMPLE_FMT_FLT: { float *floatData = (float *)&_frame->data[0]; for (int i = 0; i < _frame->nb_samples * _frame->channels; i++) { - _pcmBuffer[i] = (int16_t)(floatData[i] * INT16_MAX); + _pcmBuffer[i] = sampleFloatToInt16(floatData[i]); } } break; @@ -365,7 +370,7 @@ private: for (int sample = 0; sample < _frame->nb_samples; ++sample) { for (int channel = 0; channel < _frame->channels; ++channel) { float *floatChannel = (float*)_frame->data[channel]; - *to++ = (int16_t)(floatChannel[sample] * INT16_MAX); + *to++ = sampleFloatToInt16(floatChannel[sample]); } } } break; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 6e842ac87..d4038df6a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -3468,7 +3468,7 @@ public class AndroidUtilities { return ""; } - private static char[] characters = new char[] {' ', '!', '"', '#', '%', '&', '\'', '(', ')', '*', ',', '-', '.', '/', ':', ';', '?', '@', '[', '\\', ']', '_', '{', '}', '¡', '§', '«', '¶', '·', '»', '¿', ';', '·', '՚', '՛', '՜', '՝', '՞', '՟', '։', '֊', '־', '׀', '׃', '׆', '׳', '״', '؉', '؊', '،', '؍', '؛', '؞', '؟', '٪', '٫', '٬', '٭', '۔', '܀', '܁', '܂', '܃', '܄', '܅', '܆', '܇', '܈', '܉', '܊', '܋', '܌', '܍', '߷', '߸', '߹', '࠰', '࠱', '࠲', '࠳', '࠴', '࠵', '࠶', '࠷', '࠸', '࠹', '࠺', '࠻', '࠼', '࠽', '࠾', '࡞', '।', '॥', '॰', '৽', '੶', '૰', '౷', '಄', '෴', '๏', '๚', '๛', '༄', '༅', '༆', '༇', '༈', '༉', '༊', '་', '༌', '།', '༎', '༏', '༐', '༑', '༒', '༔', '༺', '༻', '༼', '༽', '྅', '࿐', '࿑', '࿒', '࿓', '࿔', '࿙', '࿚', '၊', '။', '၌', '၍', '၎', '၏', '჻', '፠', '፡', '።', '፣', '፤', '፥', '፦', '፧', '፨', '᐀', '᙮', '᚛', '᚜', '᛫', '᛬', '᛭', '᜵', '᜶', '។', '៕', '៖', '៘', '៙', '៚', '᠀', '᠁', '᠂', '᠃', '᠄', '᠅', '᠆', '᠇', '᠈', '᠉', '᠊', '᥄', '᥅', '᨞', '᨟', '᪠', '᪡', '᪢', '᪣', '᪤', '᪥', '᪦', '᪨', '᪩', '᪪', '᪫', '᪬', '᪭', '᭚', '᭛', '᭜', '᭝', '᭞', '᭟', '᭠', '᯼', '᯽', '᯾', '᯿', '᰻', '᰼', '᰽', '᰾', '᰿', '᱾', '᱿', '᳀', '᳁', '᳂', '᳃', '᳄', '᳅', '᳆', '᳇', '᳓', '‐', '‑', '‒', '–', '—', '―', '‖', '‗', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '†', '‡', '•', '‣', '․', '‥', '…', '‧', '‰', '‱', '′', '″', '‴', '‵', '‶', '‷', '‸', '‹', '›', '※', '‼', '‽', '‾', '‿', '⁀', '⁁', '⁂', '⁃', '⁅', '⁆', '⁇', '⁈', '⁉', '⁊', '⁋', '⁌', '⁍', '⁎', '⁏', '⁐', '⁑', '⁓', '⁔', '⁕', '⁖', '⁗', '⁘', '⁙', '⁚', '⁛', '⁜', '⁝', '⁞', '⁽', '⁾', '₍', '₎', '⌈', '⌉', '⌊', '⌋', '〈', '〉', '❨', '❩', '❪', '❫', '❬', '❭', '❮', '❯', '❰', '❱', '❲', '❳', '❴', '❵', '⟅', '⟆', '⟦', '⟧', '⟨', '⟩', '⟪', '⟫', '⟬', '⟭', '⟮', '⟯', '⦃', '⦄', '⦅', '⦆', '⦇', '⦈', '⦉', '⦊', '⦋', '⦌', '⦍', '⦎', '⦏', '⦐', '⦑', '⦒', '⦓', '⦔', '⦕', '⦖', '⦗', '⦘', '⧘', '⧙', '⧚', '⧛', '⧼', '⧽', '⳹', '⳺', '⳻', '⳼', '⳾', '⳿', '⵰', '⸀', '⸁', '⸂', '⸃', '⸄', '⸅', '⸆', '⸇', '⸈', '⸉', '⸊', '⸋', '⸌', '⸍', '⸎', '⸏', '⸐', '⸑', '⸒', '⸓', '⸔', '⸕', '⸖', '⸗', '⸘', '⸙', '⸚', '⸛', '⸜', '⸝', '⸞', '⸟', '⸠', '⸡', '⸢', '⸣', '⸤', '⸥', '⸦', '⸧', '⸨', '⸩', '⸪', '⸫', '⸬', '⸭', '⸮', '⸰', '⸱', '⸲', '⸳', '⸴', '⸵', '⸶', '⸷', '⸸', '⸹', '⸺', '⸻', '⸼', '⸽', '⸾', '⸿', '⹀', '⹁', '⹂', '⹃', '⹄', '⹅', '⹆', '⹇', '⹈', '⹉', '⹊', '⹋', '⹌', '⹍', '⹎', '⹏', '、', '。', '〃', '〈', '〉', '《', '》', '「', '」', '『', '』', '【', '】', '〔', '〕', '〖', '〗', '〘', '〙', '〚', '〛', '〜', '〝', '〞', '〟', '〰', '〽', '゠', '・', '꓾', '꓿', '꘍', '꘎', '꘏', '꙳', '꙾', '꛲', '꛳', '꛴', '꛵', '꛶', '꛷', '꡴', '꡵', '꡶', '꡷', '꣎', '꣏', '꣸', '꣹', '꣺', '꣼', '꤮', '꤯', '꥟', '꧁', '꧂', '꧃', '꧄', '꧅', '꧆', '꧇', '꧈', '꧉', '꧊', '꧋', '꧌', '꧍', '꧞', '꧟', '꩜', '꩝', '꩞', '꩟', '꫞', '꫟', '꫰', '꫱', '꯫', '﴾', '﴿', '︐', '︑', '︒', '︓', '︔', '︕', '︖', '︗', '︘', '︙', '︰', '︱', '︲', '︳', '︴', '︵', '︶', '︷', '︸', '︹', '︺', '︻', '︼', '︽', '︾', '︿', '﹀', '﹁', '﹂', '﹃', '﹄', '﹅', '﹆', '﹇', '﹈', '﹉', '﹊', '﹋', '﹌', '﹍', '﹎', '﹏', '﹐', '﹑', '﹒', '﹔', '﹕', '﹖', '﹗', '﹘', '﹙', '﹚', '﹛', '﹜', '﹝', '﹞', '﹟', '﹠', '﹡', '﹣', '﹨', '﹪', '﹫', '!', '"', '#', '%', '&', ''', '(', ')', '*', ',', '-', '.', '/', ':', ';', '?', '@', '[', '\', ']', '_', '{', '}', '⦅', '⦆', '。', '「', '」', '、', '・'}; + private static char[] characters = new char[] {' ', ' ', '!', '"', '#', '%', '&', '\'', '(', ')', '*', ',', '-', '.', '/', ':', ';', '?', '@', '[', '\\', ']', '_', '{', '}', '¡', '§', '«', '¶', '·', '»', '¿', ';', '·', '՚', '՛', '՜', '՝', '՞', '՟', '։', '֊', '־', '׀', '׃', '׆', '׳', '״', '؉', '؊', '،', '؍', '؛', '؞', '؟', '٪', '٫', '٬', '٭', '۔', '܀', '܁', '܂', '܃', '܄', '܅', '܆', '܇', '܈', '܉', '܊', '܋', '܌', '܍', '߷', '߸', '߹', '࠰', '࠱', '࠲', '࠳', '࠴', '࠵', '࠶', '࠷', '࠸', '࠹', '࠺', '࠻', '࠼', '࠽', '࠾', '࡞', '।', '॥', '॰', '৽', '੶', '૰', '౷', '಄', '෴', '๏', '๚', '๛', '༄', '༅', '༆', '༇', '༈', '༉', '༊', '་', '༌', '།', '༎', '༏', '༐', '༑', '༒', '༔', '༺', '༻', '༼', '༽', '྅', '࿐', '࿑', '࿒', '࿓', '࿔', '࿙', '࿚', '၊', '။', '၌', '၍', '၎', '၏', '჻', '፠', '፡', '።', '፣', '፤', '፥', '፦', '፧', '፨', '᐀', '᙮', '᚛', '᚜', '᛫', '᛬', '᛭', '᜵', '᜶', '។', '៕', '៖', '៘', '៙', '៚', '᠀', '᠁', '᠂', '᠃', '᠄', '᠅', '᠆', '᠇', '᠈', '᠉', '᠊', '᥄', '᥅', '᨞', '᨟', '᪠', '᪡', '᪢', '᪣', '᪤', '᪥', '᪦', '᪨', '᪩', '᪪', '᪫', '᪬', '᪭', '᭚', '᭛', '᭜', '᭝', '᭞', '᭟', '᭠', '᯼', '᯽', '᯾', '᯿', '᰻', '᰼', '᰽', '᰾', '᰿', '᱾', '᱿', '᳀', '᳁', '᳂', '᳃', '᳄', '᳅', '᳆', '᳇', '᳓', '‐', '‑', '‒', '–', '—', '―', '‖', '‗', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '†', '‡', '•', '‣', '․', '‥', '…', '‧', '‰', '‱', '′', '″', '‴', '‵', '‶', '‷', '‸', '‹', '›', '※', '‼', '‽', '‾', '‿', '⁀', '⁁', '⁂', '⁃', '⁅', '⁆', '⁇', '⁈', '⁉', '⁊', '⁋', '⁌', '⁍', '⁎', '⁏', '⁐', '⁑', '⁓', '⁔', '⁕', '⁖', '⁗', '⁘', '⁙', '⁚', '⁛', '⁜', '⁝', '⁞', '⁽', '⁾', '₍', '₎', '⌈', '⌉', '⌊', '⌋', '〈', '〉', '❨', '❩', '❪', '❫', '❬', '❭', '❮', '❯', '❰', '❱', '❲', '❳', '❴', '❵', '⟅', '⟆', '⟦', '⟧', '⟨', '⟩', '⟪', '⟫', '⟬', '⟭', '⟮', '⟯', '⦃', '⦄', '⦅', '⦆', '⦇', '⦈', '⦉', '⦊', '⦋', '⦌', '⦍', '⦎', '⦏', '⦐', '⦑', '⦒', '⦓', '⦔', '⦕', '⦖', '⦗', '⦘', '⧘', '⧙', '⧚', '⧛', '⧼', '⧽', '⳹', '⳺', '⳻', '⳼', '⳾', '⳿', '⵰', '⸀', '⸁', '⸂', '⸃', '⸄', '⸅', '⸆', '⸇', '⸈', '⸉', '⸊', '⸋', '⸌', '⸍', '⸎', '⸏', '⸐', '⸑', '⸒', '⸓', '⸔', '⸕', '⸖', '⸗', '⸘', '⸙', '⸚', '⸛', '⸜', '⸝', '⸞', '⸟', '⸠', '⸡', '⸢', '⸣', '⸤', '⸥', '⸦', '⸧', '⸨', '⸩', '⸪', '⸫', '⸬', '⸭', '⸮', '⸰', '⸱', '⸲', '⸳', '⸴', '⸵', '⸶', '⸷', '⸸', '⸹', '⸺', '⸻', '⸼', '⸽', '⸾', '⸿', '⹀', '⹁', '⹂', '⹃', '⹄', '⹅', '⹆', '⹇', '⹈', '⹉', '⹊', '⹋', '⹌', '⹍', '⹎', '⹏', '、', '。', '〃', '〈', '〉', '《', '》', '「', '」', '『', '』', '【', '】', '〔', '〕', '〖', '〗', '〘', '〙', '〚', '〛', '〜', '〝', '〞', '〟', '〰', '〽', '゠', '・', '꓾', '꓿', '꘍', '꘎', '꘏', '꙳', '꙾', '꛲', '꛳', '꛴', '꛵', '꛶', '꛷', '꡴', '꡵', '꡶', '꡷', '꣎', '꣏', '꣸', '꣹', '꣺', '꣼', '꤮', '꤯', '꥟', '꧁', '꧂', '꧃', '꧄', '꧅', '꧆', '꧇', '꧈', '꧉', '꧊', '꧋', '꧌', '꧍', '꧞', '꧟', '꩜', '꩝', '꩞', '꩟', '꫞', '꫟', '꫰', '꫱', '꯫', '﴾', '﴿', '︐', '︑', '︒', '︓', '︔', '︕', '︖', '︗', '︘', '︙', '︰', '︱', '︲', '︳', '︴', '︵', '︶', '︷', '︸', '︹', '︺', '︻', '︼', '︽', '︾', '︿', '﹀', '﹁', '﹂', '﹃', '﹄', '﹅', '﹆', '﹇', '﹈', '﹉', '﹊', '﹋', '﹌', '﹍', '﹎', '﹏', '﹐', '﹑', '﹒', '﹔', '﹕', '﹖', '﹗', '﹘', '﹙', '﹚', '﹛', '﹜', '﹝', '﹞', '﹟', '﹠', '﹡', '﹣', '﹨', '﹪', '﹫', '!', '"', '#', '%', '&', ''', '(', ')', '*', ',', '-', '.', '/', ':', ';', '?', '@', '[', '\', ']', '_', '{', '}', '⦅', '⦆', '。', '「', '」', '、', '・'}; //private static String[] longCharacters = new String[] {"𐄀", "𐄁", "𐄂", "𐎟", "𐏐", "𐕯", "𐡗", "𐤟", "𐤿", "𐩐", "𐩑", "𐩒", "𐩓", "𐩔", "𐩕", "𐩖", "𐩗", "𐩘", "𐩿", "𐫰", "𐫱", "𐫲", "𐫳", "𐫴", "𐫵", "𐫶", "𐬹", "𐬺", "𐬻", "𐬼", "𐬽", "𐬾", "𐬿", "𐮙", "𐮚", "𐮛", "𐮜", "𐽕", "𐽖", "𐽗", "𐽘", "𐽙", "𑁇", "𑁈", "𑁉", "𑁊", "𑁋", "𑁌", "𑁍", "𑂻", "𑂼", "𑂾", "𑂿", "𑃀", "𑃁", "𑅀", "𑅁", "𑅂", "𑅃", "𑅴", "𑅵", "𑇅", "𑇆", "𑇇", "𑇈", "𑇍", "𑇛", "𑇝", "𑇞", "𑇟", "𑈸", "𑈹", "𑈺", "𑈻", "𑈼", "𑈽", "𑊩", "𑑋", "𑑌", "𑑍", "𑑎", "𑑏", "𑑛", "𑑝", "𑓆", "𑗁", "𑗂", "𑗃", "𑗄", "𑗅", "𑗆", "𑗇", "𑗈", "𑗉", "𑗊", "𑗋", "𑗌", "𑗍", "𑗎", "𑗏", "𑗐", "𑗑", "𑗒", "𑗓", "𑗔", "𑗕", "𑗖", "𑗗", "𑙁", "𑙂", "𑙃", "𑙠", "𑙡", "𑙢", "𑙣", "𑙤", "𑙥", "𑙦", "𑙧", "𑙨", "𑙩", "𑙪", "𑙫", "𑙬", "𑜼", "𑜽", "𑜾", "𑠻", "𑧢", "𑨿", "𑩀", "𑩁", "𑩂", "𑩃", "𑩄", "𑩅", "𑩆", "𑪚", "𑪛", "𑪜", "𑪞", "𑪟", "𑪠", "𑪡", "𑪢", "𑱁", "𑱂", "𑱃", "𑱄", "𑱅", "𑱰", "𑱱", "𑻷", "𑻸", "𑿿", "𒑰", "𒑱", "𒑲", "𒑳", "𒑴", "𖩮", "𖩯", "𖫵", "𖬷", "𖬸", "𖬹", "𖬺", "𖬻", "𖭄", "𖺗", "𖺘", "𖺙", "𖺚", "𖿢", "𛲟", "𝪇", "𝪈", "𝪉", "𝪊", "𝪋", "𞥞", "𞥟"}; private static HashSet charactersMap; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java index db24c63e8..dba269aa0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java @@ -22,7 +22,7 @@ public class AutoMessageHeardReceiver extends BroadcastReceiver { long dialog_id = intent.getLongExtra("dialog_id", 0); int max_id = intent.getIntExtra("max_id", 0); int currentAccount = intent.getIntExtra("currentAccount", 0); - if (dialog_id == 0 || max_id == 0) { + if (dialog_id == 0 || max_id == 0 || !UserConfig.isValidAccount(currentAccount)) { return; } int lowerId = (int) dialog_id; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java index 6198a5dc2..7608e37db 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java @@ -30,7 +30,7 @@ public class AutoMessageReplyReceiver extends BroadcastReceiver { long dialog_id = intent.getLongExtra("dialog_id", 0); int max_id = intent.getIntExtra("max_id", 0); int currentAccount = intent.getIntExtra("currentAccount", 0); - if (dialog_id == 0 || max_id == 0) { + if (dialog_id == 0 || max_id == 0 || !UserConfig.isValidAccount(currentAccount)) { return; } SendMessagesHelper.getInstance(currentAccount).sendMessage(text.toString(), dialog_id, null, null, null, true, null, null, null, true, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 82964772a..fc2b16a07 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -18,7 +18,7 @@ public class BuildVars { public static boolean LOGS_ENABLED = false; public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = true; - public static int BUILD_VERSION = 2264; + public static int BUILD_VERSION = 2274; public static String BUILD_VERSION_STRING = "7.6.0"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index 78b71872b..43512c885 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -100,6 +100,27 @@ public class ChatObject { loadMembers(true); } + public void addSelfDummyParticipant() { + int selfId = getSelfId(); + if (participants.indexOfKey(selfId) >= 0) { + return; + } + TLRPC.TL_groupCallParticipant selfDummyParticipant = new TLRPC.TL_groupCallParticipant(); + selfDummyParticipant.peer = selfPeer; + selfDummyParticipant.muted = true; + selfDummyParticipant.self = true; + selfDummyParticipant.can_self_unmute = !call.join_muted; + selfDummyParticipant.date = currentAccount.getConnectionsManager().getCurrentTime(); + TLRPC.Chat chat = currentAccount.getMessagesController().getChat(chatId); + if (ChatObject.canManageCalls(chat) || !ChatObject.isChannel(chat) || chat.megagroup || selfDummyParticipant.can_self_unmute) { + selfDummyParticipant.active_date = currentAccount.getConnectionsManager().getCurrentTime(); + } + participants.put(selfId, selfDummyParticipant); + sortedParticipants.add(selfDummyParticipant); + sortParticipants(); + currentAccount.getNotificationCenter().postNotificationName(NotificationCenter.groupCallUpdated, chatId, call.id, false); + } + public void migrateToChat(TLRPC.Chat chat) { chatId = chat.id; VoIPService voIPService = VoIPService.getSharedInstance(); @@ -108,6 +129,15 @@ public class ChatObject { } } + private int getSelfId() { + int selfId; + if (selfPeer != null) { + return MessageObject.getPeerId(selfPeer); + } else { + return currentAccount.getUserConfig().getClientUserId(); + } + } + public void loadMembers(boolean fromBegin) { if (fromBegin) { if (reloadingMembers) { @@ -137,12 +167,7 @@ public class ChatObject { currentAccount.getMessagesController().putUsers(groupParticipants.users, false); currentAccount.getMessagesController().putChats(groupParticipants.chats, false); SparseArray old = null; - int selfId; - if (selfPeer != null) { - selfId = MessageObject.getPeerId(selfPeer); - } else { - selfId = currentAccount.getUserConfig().getClientUserId(); - } + int selfId = getSelfId(); TLRPC.TL_groupCallParticipant oldSelf = participants.get(selfId); if (TextUtils.isEmpty(req.offset)) { if (participants.size() != 0) { @@ -162,6 +187,9 @@ public class ChatObject { if (TextUtils.isEmpty(req.offset)) { call.version = groupParticipants.version; call.participants_count = groupParticipants.count; + if (BuildVars.LOGS_ENABLED) { + FileLog.d("new participants count " + call.participants_count); + } } long time = SystemClock.elapsedRealtime(); currentAccount.getNotificationCenter().postNotificationName(NotificationCenter.applyGroupCallVisibleParticipants, time); @@ -186,14 +214,22 @@ public class ChatObject { if (oldParticipant.source != 0) { participantsBySources.remove(oldParticipant.source); } - participant.lastTypingDate = Math.max(participant.active_date, oldParticipant.active_date); + if (oldParticipant.self) { + participant.lastTypingDate = oldParticipant.active_date; + } else { + participant.lastTypingDate = Math.max(participant.active_date, oldParticipant.active_date); + } if (time != participant.lastVisibleDate) { participant.active_date = participant.lastTypingDate; } } else if (old != null) { oldParticipant = old.get(MessageObject.getPeerId(participant.peer)); if (oldParticipant != null) { - participant.lastTypingDate = Math.max(participant.active_date, oldParticipant.active_date); + if (oldParticipant.self) { + participant.lastTypingDate = oldParticipant.active_date; + } else { + participant.lastTypingDate = Math.max(participant.active_date, oldParticipant.active_date); + } if (time != participant.lastVisibleDate) { participant.active_date = participant.lastTypingDate; } else { @@ -371,13 +407,7 @@ public class ChatObject { for (int a = 0; a < ssrc.length; a++) { TLRPC.TL_groupCallParticipant participant; if (ssrc[a] == 0) { - int selfId; - if (selfPeer != null) { - selfId = MessageObject.getPeerId(selfPeer); - } else { - selfId = currentAccount.getUserConfig().getClientUserId(); - } - participant = participants.get(selfId); + participant = participants.get(getSelfId()); } else { participant = participantsBySources.get(ssrc[a]); } @@ -400,7 +430,7 @@ public class ChatObject { } else { participant.amplitude = 0; } - } else { + } else if (ssrc[a] != 0) { if (participantsToLoad == null) { participantsToLoad = new ArrayList<>(); } @@ -537,6 +567,9 @@ public class ChatObject { currentAccount.getMessagesController().putChats(res.chats, false); if (call.participants_count != res.count) { call.participants_count = res.count; + if (BuildVars.LOGS_ENABLED) { + FileLog.d("new participants reload count " + call.participants_count); + } currentAccount.getNotificationCenter().postNotificationName(NotificationCenter.groupCallUpdated, chatId, call.id, false); } } @@ -572,6 +605,9 @@ public class ChatObject { return; } if (versioned && update.version < call.version) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("ignore processParticipantsUpdate because of version"); + } return; } } @@ -579,12 +615,7 @@ public class ChatObject { boolean updated = false; boolean selfUpdated = false; boolean changedOrAdded = false; - int selfId; - if (selfPeer != null) { - selfId = MessageObject.getPeerId(selfPeer); - } else { - selfId = currentAccount.getUserConfig().getClientUserId(); - } + int selfId = getSelfId(); long time = SystemClock.elapsedRealtime(); int lastParticipantDate; if (!sortedParticipants.isEmpty()) { @@ -596,9 +627,15 @@ public class ChatObject { for (int a = 0, N = update.participants.size(); a < N; a++) { TLRPC.TL_groupCallParticipant participant = update.participants.get(a); int pid = MessageObject.getPeerId(participant.peer); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("process participant " + pid + " left = " + participant.left + " versioned " + participant.versioned + " flags = " + participant.flags + " self = " + selfId + " volume = " + participant.volume); + } TLRPC.TL_groupCallParticipant oldParticipant = participants.get(pid); if (participant.left) { if (oldParticipant == null && update.version == call.version) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("unknowd participant left, reload call"); + } reloadCall = true; } if (oldParticipant != null) { @@ -620,6 +657,9 @@ public class ChatObject { invitedUsers.remove(id); } if (oldParticipant != null) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("new participant, update old"); + } oldParticipant.muted = participant.muted; if (!participant.min) { oldParticipant.volume = participant.volume; @@ -657,6 +697,13 @@ public class ChatObject { call.participants_count++; if (update.version == call.version) { reloadCall = true; + if (BuildVars.LOGS_ENABLED) { + FileLog.d("new participant, just joned, reload call"); + } + } else { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("new participant, just joned"); + } } } if (participant.raise_hand_rating != 0) { @@ -689,6 +736,9 @@ public class ChatObject { if (call.participants_count < participants.size()) { call.participants_count = participants.size(); } + if (BuildVars.LOGS_ENABLED) { + FileLog.d("new participants count after update " + call.participants_count); + } if (reloadCall) { loadGroupCall(); } @@ -720,12 +770,7 @@ public class ChatObject { private void sortParticipants() { TLRPC.Chat chat = currentAccount.getMessagesController().getChat(chatId); boolean isAdmin = ChatObject.canManageCalls(chat); - int selfId; - if (selfPeer != null) { - selfId = MessageObject.getPeerId(selfPeer); - } else { - selfId = currentAccount.getUserConfig().getClientUserId(); - } + int selfId = getSelfId(); Collections.sort(sortedParticipants, (o1, o2) -> { if (o1.active_date != 0 && o2.active_date != 0) { return Integer.compare(o2.active_date, o1.active_date); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 8678ac410..c14c62425 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -1398,7 +1398,7 @@ public class ImageLoader { } } - private static Bitmap getStrippedPhotoBitmap(byte[] photoBytes, String filter) { + public static Bitmap getStrippedPhotoBitmap(byte[] photoBytes, String filter) { int len = photoBytes.length - 3 + Bitmaps.header.length + Bitmaps.footer.length; byte[] bytes = bytesLocal.get(); byte[] data = bytes != null && bytes.length >= len ? bytes : null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 30b0665ef..c5ce9f6db 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -31,6 +31,8 @@ import org.telegram.ui.Components.RecyclableDrawable; import androidx.annotation.Keep; +import com.google.android.exoplayer2.util.Log; + public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate { public interface ImageReceiverDelegate { @@ -410,6 +412,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } else { strippedLoc = mediaLocation != null ? mediaLocation : imageLocation; } + if (strippedLoc == null) { + strippedLoc = thumbLocation; + } String thumbKey = thumbLocation != null ? thumbLocation.getKey(parentObject, strippedLoc, false) : null; if (thumbKey != null && thumbFilter != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 8e025968a..5dcce812e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -1108,8 +1108,14 @@ public class MessageObject { TLRPC.TL_channelAdminLogEventActionParticipantInvite action = (TLRPC.TL_channelAdminLogEventActionParticipantInvite) event.action; messageOwner = new TLRPC.TL_messageService(); messageOwner.action = new TLRPC.TL_messageActionChatAddUser(); - TLRPC.User whoUser = MessagesController.getInstance(currentAccount).getUser(action.participant.user_id); - if (messageOwner.from_id instanceof TLRPC.TL_peerUser && action.participant.user_id == messageOwner.from_id.user_id) { + int peerId = getPeerId(action.participant.peer); + TLObject whoUser; + if (peerId > 0) { + whoUser = MessagesController.getInstance(currentAccount).getUser(peerId); + } else { + whoUser = MessagesController.getInstance(currentAccount).getChat(-peerId); + } + if (messageOwner.from_id instanceof TLRPC.TL_peerUser && peerId == messageOwner.from_id.user_id) { if (chat.megagroup) { messageText = replaceWithLink(LocaleController.getString("EventLogGroupJoined", R.string.EventLogGroupJoined), "un1", fromUser); } else { @@ -1133,7 +1139,13 @@ public class MessageObject { new_participant = action.new_participant; } messageOwner = new TLRPC.TL_message(); - TLRPC.User whoUser = MessagesController.getInstance(currentAccount).getUser(prev_participant.user_id); + int peerId = MessageObject.getPeerId(prev_participant.peer); + TLObject whoUser; + if (peerId > 0) { + whoUser = MessagesController.getInstance(currentAccount).getUser(peerId); + } else { + whoUser = MessagesController.getInstance(currentAccount).getUser(-peerId); + } StringBuilder rights; if (!(prev_participant instanceof TLRPC.TL_channelParticipantCreator) && new_participant instanceof TLRPC.TL_channelParticipantCreator) { String str = LocaleController.getString("EventLogChangedOwnership", R.string.EventLogChangedOwnership); @@ -1294,7 +1306,13 @@ public class MessageObject { } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionParticipantToggleBan) { TLRPC.TL_channelAdminLogEventActionParticipantToggleBan action = (TLRPC.TL_channelAdminLogEventActionParticipantToggleBan) event.action; messageOwner = new TLRPC.TL_message(); - TLRPC.User whoUser = MessagesController.getInstance(currentAccount).getUser(action.prev_participant.user_id); + int peerId = getPeerId(action.prev_participant.peer); + TLObject whoUser; + if (peerId > 0) { + whoUser = MessagesController.getInstance(currentAccount).getUser(peerId); + } else { + whoUser = MessagesController.getInstance(currentAccount).getChat(-peerId); + } TLRPC.TL_chatBannedRights o = action.prev_participant.banned_rights; TLRPC.TL_chatBannedRights n = action.new_participant.banned_rights; if (chat.megagroup && (n == null || !n.view_messages || o != null && n.until_date != o.until_date)) { @@ -1828,29 +1846,41 @@ public class MessageObject { checkMediaExistance(); } - private String getUserName(TLRPC.User user, ArrayList entities, int offset) { + private String getUserName(TLObject object, ArrayList entities, int offset) { String name; - if (user == null) { + String username; + int id; + if (object == null) { name = ""; - } else { + username = null; + id = 0; + } else if (object instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) object; name = ContactsController.formatName(user.first_name, user.last_name); + username = user.username; + id = user.id; + } else { + TLRPC.Chat chat = (TLRPC.Chat) object; + name = chat.title; + username = chat.username; + id = -chat.id; } if (offset >= 0) { TLRPC.TL_messageEntityMentionName entity = new TLRPC.TL_messageEntityMentionName(); - entity.user_id = user.id; + entity.user_id = id; entity.offset = offset; entity.length = name.length(); entities.add(entity); } - if (!TextUtils.isEmpty(user.username)) { + if (!TextUtils.isEmpty(username)) { if (offset >= 0) { TLRPC.TL_messageEntityMentionName entity = new TLRPC.TL_messageEntityMentionName(); - entity.user_id = user.id; + entity.user_id = id; entity.offset = offset + name.length() + 2; - entity.length = user.username.length() + 1; + entity.length = username.length() + 1; entities.add(entity); } - return String.format("%1$s (@%2$s)", name, user.username); + return String.format("%1$s (@%2$s)", name, username); } return name; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 8fa742a6a..2850da41d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -3165,7 +3165,7 @@ public class MessagesController extends BaseController implements NotificationCe final SparseArray array1 = new SparseArray<>(participants.participants.size()); for (int a = 0; a < participants.participants.size(); a++) { TLRPC.ChannelParticipant participant = participants.participants.get(a); - array1.put(participant.user_id, participant); + array1.put(MessageObject.getPeerId(participant.peer), participant); } processLoadedChannelAdmins(array1, chatId, false); } @@ -3867,13 +3867,17 @@ public class MessagesController extends BaseController implements NotificationCe }); } - public void setUserBannedRole(final int chatId, TLRPC.User user, TLRPC.TL_chatBannedRights rights, final boolean isChannel, final BaseFragment parentFragment) { - if (user == null || rights == null) { + public void setParticipantBannedRole(final int chatId, TLRPC.User user, TLRPC.Chat chat, TLRPC.TL_chatBannedRights rights, final boolean isChannel, final BaseFragment parentFragment) { + if (user == null && chat == null || rights == null) { return; } final TLRPC.TL_channels_editBanned req = new TLRPC.TL_channels_editBanned(); req.channel = getInputChannel(chatId); - req.user_id = getInputUser(user); + if (user != null) { + req.participant = getInputPeer(user); + } else { + req.participant = getInputPeer(chat); + } req.banned_rights = rights; getConnectionsManager().sendRequest(req, (response, error) -> { if (error == null) { @@ -4691,7 +4695,7 @@ public class MessagesController extends BaseController implements NotificationCe if (onlyHistory == 0 || onlyHistory == 3) { getNotificationCenter().postNotificationName(NotificationCenter.dialogDeleted, did); getNotificationsController().deleteNotificationChannel(did); - JoinCallAlert.processDeletedChat(did); + JoinCallAlert.processDeletedChat(currentAccount, did); } if (onlyHistory == 0) { getMediaDataController().cleanDraft(did, 0, false); @@ -4944,7 +4948,8 @@ public class MessagesController extends BaseController implements NotificationCe if (error == null) { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; putUsers(res.users, false); - getMessagesStorage().putUsersAndChats(res.users, null, true, true); + putChats(res.chats, false); + getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); getMessagesStorage().updateChannelUsers(chat_id, res.participants); loadedFullParticipants.add(chat_id); } @@ -9028,33 +9033,38 @@ public class MessagesController extends BaseController implements NotificationCe }); } - public void deleteUserFromChat(final int chat_id, final TLRPC.User user, final TLRPC.ChatFull info) { - deleteUserFromChat(chat_id, user, info, false, false); + public void deleteParticipantFromChat(int chat_id, TLRPC.User user, TLRPC.ChatFull info) { + deleteParticipantFromChat(chat_id, user, null, info, false, false); } - public void deleteUserFromChat(final int chat_id, final TLRPC.User user, final TLRPC.ChatFull info, boolean forceDelete, boolean revoke) { - if (user == null) { + public void deleteParticipantFromChat(int chat_id, TLRPC.User user, TLRPC.Chat chat, TLRPC.ChatFull info, boolean forceDelete, boolean revoke) { + if (user == null && chat == null) { return; } - final TLRPC.InputUser inputUser = getInputUser(user); + TLRPC.InputPeer inputPeer; + if (user != null) { + inputPeer = getInputPeer(user); + } else { + inputPeer = getInputPeer(chat); + } TLObject request; - TLRPC.Chat chat = getChat(chat_id); - final boolean isChannel = ChatObject.isChannel(chat); + TLRPC.Chat ownerChat = getChat(chat_id); + final boolean isChannel = ChatObject.isChannel(ownerChat); if (isChannel) { - if (inputUser instanceof TLRPC.TL_inputUserSelf) { - if (chat.creator && forceDelete) { + if (UserObject.isUserSelf(user)) { + if (ownerChat.creator && forceDelete) { TLRPC.TL_channels_deleteChannel req = new TLRPC.TL_channels_deleteChannel(); - req.channel = getInputChannel(chat); + req.channel = getInputChannel(ownerChat); request = req; } else { TLRPC.TL_channels_leaveChannel req = new TLRPC.TL_channels_leaveChannel(); - req.channel = getInputChannel(chat); + req.channel = getInputChannel(ownerChat); request = req; } } else { TLRPC.TL_channels_editBanned req = new TLRPC.TL_channels_editBanned(); - req.channel = getInputChannel(chat); - req.user_id = inputUser; + req.channel = getInputChannel(ownerChat); + req.participant = inputPeer; req.banned_rights = new TLRPC.TL_chatBannedRights(); req.banned_rights.view_messages = true; req.banned_rights.send_media = true; @@ -9085,7 +9095,7 @@ public class MessagesController extends BaseController implements NotificationCe req.revoke_history = true; request = req; } - if (user.id == getUserConfig().getClientUserId()) { + if (UserObject.isUserSelf(user)) { deleteDialog(-chat_id, 0, revoke); } getConnectionsManager().sendRequest(request, (response, error) -> { @@ -9094,7 +9104,7 @@ public class MessagesController extends BaseController implements NotificationCe } final TLRPC.Updates updates = (TLRPC.Updates) response; processUpdates(updates, false); - if (isChannel && !(inputUser instanceof TLRPC.TL_inputUserSelf)) { + if (isChannel && !UserObject.isUserSelf(user)) { AndroidUtilities.runOnUIThread(() -> loadFullChat(chat_id, 0, true), 1000); } }, ConnectionsManager.RequestFlagInvokeAfter); @@ -10647,15 +10657,18 @@ public class MessagesController extends BaseController implements NotificationCe gettingChatInviters.put(chatId, true); TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); req.channel = getInputChannel(chatId); - req.user_id = new TLRPC.TL_inputUserSelf(); + req.participant = getInputPeer(getUserConfig().getClientUserId()); getConnectionsManager().sendRequest(req, (response, error) -> { final TLRPC.TL_channels_channelParticipant res = (TLRPC.TL_channels_channelParticipant) response; if (res != null && res.participant instanceof TLRPC.TL_channelParticipantSelf && res.participant.inviter_id != getUserConfig().getClientUserId()) { if (chat.megagroup && getMessagesStorage().isMigratedChat(chat.id)) { return; } - AndroidUtilities.runOnUIThread(() -> putUsers(res.users, false)); - getMessagesStorage().putUsersAndChats(res.users, null, true, true); + AndroidUtilities.runOnUIThread(() -> { + putUsers(res.users, false); + putChats(res.chats, false); + }); + getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); ArrayList pushMessages; if (createMessage && !getMessagesStorage().hasInviteMeMessage(chatId)) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index ec78a3182..027d952bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -4745,7 +4745,7 @@ public class MessagesStorage extends BaseController { TLRPC.ChannelParticipant participant = participants.get(a); state.requery(); state.bindLong(1, did); - state.bindInteger(2, participant.user_id); + state.bindInteger(2, MessageObject.getPeerId(participant.peer)); state.bindInteger(3, date); data = new NativeByteBuffer(participant.getObjectSize()); participant.serializeToStream(data); @@ -5372,7 +5372,7 @@ public class MessagesStorage extends BaseController { loadedUsers.add(user); participant.date = cursor.intValue(3); TLRPC.TL_chatChannelParticipant chatChannelParticipant = new TLRPC.TL_chatChannelParticipant(); - chatChannelParticipant.user_id = participant.user_id; + chatChannelParticipant.user_id = MessageObject.getPeerId(participant.peer); chatChannelParticipant.date = participant.date; chatChannelParticipant.inviter_id = participant.inviter_id; chatChannelParticipant.channelParticipant = participant; @@ -11542,7 +11542,7 @@ public class MessagesStorage extends BaseController { } - public void localSearch(int dialogsType, String query, ArrayList resultArray, ArrayList resultArrayNames, ArrayList encUsers, int folderId) { + public void localSearch(int dialogsType, String query, ArrayList resultArray, ArrayList resultArrayNames, ArrayList encUsers, int folderId) { int selfUserId = UserConfig.getInstance(currentAccount).getClientUserId(); try { String search1 = query.trim().toLowerCase(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCallbackReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCallbackReceiver.java index 652df15b4..792752833 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCallbackReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCallbackReceiver.java @@ -21,6 +21,9 @@ public class NotificationCallbackReceiver extends BroadcastReceiver { } ApplicationLoader.postInitApplication(); int currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); + if (!UserConfig.isValidAccount(currentAccount)) { + return; + } long did = intent.getLongExtra("did", 777000); byte[] data = intent.getByteArrayExtra("data"); int mid = intent.getIntExtra("mid", 0); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java index 845de4751..a01db8628 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationDismissReceiver.java @@ -20,6 +20,9 @@ public class NotificationDismissReceiver extends BroadcastReceiver { return; } int currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); + if (!UserConfig.isValidAccount(currentAccount)) { + return; + } long dialogId = intent.getLongExtra("dialogId", 0); int date = intent.getIntExtra("messageDate", 0); if (dialogId == 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java index 344349106..77419b282 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java @@ -23,11 +23,9 @@ public class NotificationRepeat extends IntentService { return; } final int currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationsController.getInstance(currentAccount).repeatNotificationMaybe(); - } - }); + if (!UserConfig.isValidAccount(currentAccount)) { + return; + } + AndroidUtilities.runOnUIThread(() -> NotificationsController.getInstance(currentAccount).repeatNotificationMaybe()); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PopupReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/PopupReplyReceiver.java index 2be38a07c..c0b36ce03 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PopupReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PopupReplyReceiver.java @@ -20,6 +20,10 @@ public class PopupReplyReceiver extends BroadcastReceiver { return; } ApplicationLoader.postInitApplication(); - NotificationsController.getInstance(intent.getIntExtra("currentAccount", UserConfig.selectedAccount)).forceShowPopupForReply(); + int currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); + if (!UserConfig.isValidAccount(currentAccount)) { + return; + } + NotificationsController.getInstance(currentAccount).forceShowPopupForReply(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index f335f8adc..d4fa6b1d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -68,6 +68,7 @@ public class SharedConfig { public static boolean searchMessagesAsListUsed; public static boolean stickersReorderingHintUsed; public static boolean disableVoiceAudioEffects; + public static boolean useMediaStream; private static int lastLocalId = -210000; public static String storageCacheDir; @@ -294,6 +295,7 @@ public class SharedConfig { lockRecordAudioVideoHint = preferences.getInt("lockRecordAudioVideoHint", 0); disableVoiceAudioEffects = preferences.getBoolean("disableVoiceAudioEffects", false); chatSwipeAction = preferences.getInt("ChatSwipeAction", -1); + useMediaStream = preferences.getBoolean("useMediaStream", false); preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true); @@ -557,6 +559,14 @@ public class SharedConfig { editor.commit(); } + public static void toggleUseMediaStream() { + useMediaStream = !useMediaStream; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("useMediaStream", useMediaStream); + editor.commit(); + } + public static void toggleLoopStickers() { loopStickers = !loopStickers; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index 9fc0140bd..69f4aa902 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -241,6 +241,10 @@ public class UserConfig extends BaseController { } } + public static boolean isValidAccount(int num) { + return num >= 0 && num < UserConfig.MAX_ACCOUNT_COUNT && getInstance(num).isClientActivated(); + } + public boolean isClientActivated() { synchronized (sync) { return currentUser != null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index 805b4016e..75afc0d2a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -75,6 +75,10 @@ public class VideoEncodingService extends Service implements NotificationCenter. path = intent.getStringExtra("path"); int oldAccount = currentAccount; currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); + if (!UserConfig.isValidAccount(currentAccount)) { + stopSelf(); + return Service.START_NOT_STICKY; + } if (oldAccount != currentAccount) { NotificationCenter.getInstance(oldAccount).removeObserver(this, NotificationCenter.FileUploadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.FileUploadProgressChanged); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java index e0c4abd54..7677b95c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java @@ -34,7 +34,7 @@ public class WearReplyReceiver extends BroadcastReceiver { long dialog_id = intent.getLongExtra("dialog_id", 0); int max_id = intent.getIntExtra("max_id", 0); int currentAccount = intent.getIntExtra("currentAccount", 0); - if (dialog_id == 0 || max_id == 0) { + if (dialog_id == 0 || max_id == 0 || !UserConfig.isValidAccount(currentAccount)) { return; } int lowerId = (int) dialog_id; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java index 4f8920f2c..e3d56498e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java @@ -78,6 +78,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.StatsController; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -90,6 +91,7 @@ import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.LaunchActivity; import org.telegram.ui.VoIPPermissionActivity; +import org.webrtc.voiceengine.WebRtcAudioTrack; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -178,6 +180,8 @@ public abstract class VoIPBaseService extends Service implements SensorEventList protected Runnable onDestroyRunnable; + protected Runnable switchingStreamTimeoutRunnable; + protected boolean playedConnectedSound; protected boolean switchingStream; @@ -202,6 +206,8 @@ public abstract class VoIPBaseService extends Service implements SensorEventList protected long videoCapturer; protected Runnable timeoutRunnable; + protected int currentStreamType; + private Boolean mHasEarpiece; private boolean wasEstablished; protected int signalBarCount; @@ -439,9 +445,15 @@ public abstract class VoIPBaseService extends Service implements SensorEventList if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; req.participant = MessagesController.getInputPeer(user); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("edit group call part id = " + req.participant.user_id + " access_hash = " + req.participant.user_id); + } } else if (object instanceof TLRPC.Chat) { TLRPC.Chat chat = (TLRPC.Chat) object; req.participant = MessagesController.getInputPeer(chat); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("edit group call part id = " + (req.participant.chat_id != 0 ? req.participant.chat_id : req.participant.channel_id) + " access_hash = " + req.participant.access_hash); + } } req.muted = mute; if (volume >= 0) { @@ -452,6 +464,9 @@ public abstract class VoIPBaseService extends Service implements SensorEventList req.raise_hand = raiseHand; req.flags |= 4; } + if (BuildVars.LOGS_ENABLED) { + FileLog.d("edit group call flags = " + req.flags); + } int account = currentAccount; AccountInstance.getInstance(account).getConnectionsManager().sendRequest(req, (response, error) -> { if (response != null) { @@ -694,7 +709,13 @@ public abstract class VoIPBaseService extends Service implements SensorEventList boolean needRing = am.getRingerMode() != AudioManager.RINGER_MODE_SILENT; if (needRing) { ringtonePlayer = new MediaPlayer(); - ringtonePlayer.setOnPreparedListener(mediaPlayer -> ringtonePlayer.start()); + ringtonePlayer.setOnPreparedListener(mediaPlayer -> { + try { + ringtonePlayer.start(); + } catch (Throwable e) { + FileLog.e(e); + } + }); ringtonePlayer.setLooping(true); if (isHeadsetPlugged) { ringtonePlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); @@ -762,6 +783,10 @@ public abstract class VoIPBaseService extends Service implements SensorEventList Utilities.globalQueue.cancelRunnable(updateNotificationRunnable); updateNotificationRunnable = null; } + if (switchingStreamTimeoutRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(switchingStreamTimeoutRunnable); + switchingStreamTimeoutRunnable = null; + } unregisterReceiver(receiver); if (timeoutRunnable != null) { AndroidUtilities.cancelRunOnUIThread(timeoutRunnable); @@ -903,19 +928,6 @@ public abstract class VoIPBaseService extends Service implements SensorEventList } registerReceiver(receiver, filter); fetchBluetoothDeviceName(); - Utilities.globalQueue.postRunnable(() -> { - soundPool = new SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0); - spConnectingId = soundPool.load(this, R.raw.voip_connecting, 1); - spRingbackID = soundPool.load(this, R.raw.voip_ringback, 1); - spFailedID = soundPool.load(this, R.raw.voip_failed, 1); - spEndId = soundPool.load(this, R.raw.voip_end, 1); - spBusyId = soundPool.load(this, R.raw.voip_busy, 1); - spVoiceChatEndId = soundPool.load(this, R.raw.voicechat_leave, 1); - spVoiceChatStartId = soundPool.load(this, R.raw.voicechat_join, 1); - spVoiceChatConnecting = soundPool.load(this, R.raw.voicechat_connecting, 1); - spAllowTalkId = soundPool.load(this, R.raw.voip_onallowtalk, 1); - spStartRecordId = soundPool.load(this, R.raw.voip_recordstart, 1); - }); am.registerMediaButtonEventReceiver(new ComponentName(this, VoIPMediaButtonReceiver.class)); @@ -952,6 +964,34 @@ public abstract class VoIPBaseService extends Service implements SensorEventList } } + protected void loadResources() { + if (chat != null && SharedConfig.useMediaStream) { + currentStreamType = AudioManager.STREAM_MUSIC; + if (Build.VERSION.SDK_INT >= 21) { + WebRtcAudioTrack.setAudioTrackUsageAttribute(AudioAttributes.USAGE_MEDIA); + } + } else { + currentStreamType = AudioManager.STREAM_VOICE_CALL; + if (Build.VERSION.SDK_INT >= 21) { + WebRtcAudioTrack.setAudioTrackUsageAttribute(AudioAttributes.USAGE_VOICE_COMMUNICATION); + } + } + WebRtcAudioTrack.setAudioStreamType(currentStreamType); + Utilities.globalQueue.postRunnable(() -> { + soundPool = new SoundPool(1, currentStreamType, 0); + spConnectingId = soundPool.load(this, R.raw.voip_connecting, 1); + spRingbackID = soundPool.load(this, R.raw.voip_ringback, 1); + spFailedID = soundPool.load(this, R.raw.voip_failed, 1); + spEndId = soundPool.load(this, R.raw.voip_end, 1); + spBusyId = soundPool.load(this, R.raw.voip_busy, 1); + spVoiceChatEndId = soundPool.load(this, R.raw.voicechat_leave, 1); + spVoiceChatStartId = soundPool.load(this, R.raw.voicechat_join, 1); + spVoiceChatConnecting = soundPool.load(this, R.raw.voicechat_connecting, 1); + spAllowTalkId = soundPool.load(this, R.raw.voip_onallowtalk, 1); + spStartRecordId = soundPool.load(this, R.raw.voip_recordstart, 1); + }); + } + protected void dispatchStateChanged(int state) { if (BuildVars.LOGS_ENABLED) { FileLog.d("== Call " + getCallID() + " state changed to " + state + " =="); @@ -994,14 +1034,16 @@ public abstract class VoIPBaseService extends Service implements SensorEventList needPlayEndSound = true; AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); if (!USE_CONNECTION_SERVICE) { - Utilities.globalQueue.postRunnable(() -> { - try { - am.setMode(AudioManager.MODE_IN_COMMUNICATION); - } catch (Exception e) { - FileLog.e(e); - } - }); - am.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN); + if (currentStreamType == AudioManager.STREAM_VOICE_CALL) { + Utilities.globalQueue.postRunnable(() -> { + try { + am.setMode(AudioManager.MODE_IN_COMMUNICATION); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + am.requestAudioFocus(this, currentStreamType, AudioManager.AUDIOFOCUS_GAIN); if (isBluetoothHeadsetConnected() && hasEarpiece()) { switch (audioRouteToSet) { case AUDIO_ROUTE_BLUETOOTH: diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java index 9fdf5a98f..f9b4b203d 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java @@ -54,6 +54,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.XiaomiUtilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Components.JoinCallAlert; import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.LaunchActivity; import org.telegram.ui.VoIPFeedbackActivity; @@ -250,6 +251,7 @@ public class VoIPService extends VoIPBaseService { MessagesController.getInstance(currentAccount).startShortPoll(chat, classGuid, false); } } + loadResources(); localSink = new ProxyVideoSink(); remoteSink = new ProxyVideoSink(); try { @@ -1027,12 +1029,14 @@ public class VoIPService extends VoIPBaseService { } boolean newModeStreaming = false; JSONObject object = null; - try { - TLRPC.TL_dataJSON json = call.params; - object = new JSONObject(json.data); - newModeStreaming = object.optBoolean("stream"); - } catch (Exception e) { - FileLog.e(e); + if (call.params != null) { + try { + TLRPC.TL_dataJSON json = call.params; + object = new JSONObject(json.data); + newModeStreaming = object.optBoolean("stream"); + } catch (Exception e) { + FileLog.e(e); + } } if ((currentState == STATE_WAIT_INIT || newModeStreaming != currentGroupModeStreaming) && call.params != null) { if (playedConnectedSound && newModeStreaming != currentGroupModeStreaming) { @@ -1414,11 +1418,27 @@ public class VoIPService extends VoIPBaseService { } MessagesController.getInstance(currentAccount).processUpdates(updates, false); AndroidUtilities.runOnUIThread(() -> groupCall.loadMembers(create)); + startGroupCheckShortpoll(); } else { AndroidUtilities.runOnUIThread(() -> { - if ("GROUPCALL_SSRC_DUPLICATE_MUCH".equals(error.text)) { + if ("JOIN_AS_PEER_INVALID".equals(error.text)) { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(chat.id); + if (chatFull != null) { + if (chatFull instanceof TLRPC.TL_chatFull) { + chatFull.flags &=~ 32768; + } else { + chatFull.flags &=~ 67108864; + } + chatFull.groupcall_default_join_as = null; + JoinCallAlert.resetCache(); + } + hangUp(2); + } else if ("GROUPCALL_SSRC_DUPLICATE_MUCH".equals(error.text)) { createGroupInstance(false); } else { + if ("GROUPCALL_INVALID".equals(error.text)) { + MessagesController.getInstance(currentAccount).loadFullChat(chat.id, 0, true); + } NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needShowAlert, 6, error.text); hangUp(0); } @@ -1589,10 +1609,10 @@ public class VoIPService extends VoIPBaseService { AndroidUtilities.runOnUIThread(() -> createGroupInstance(false)); } else { int status; - if ("TIME_INVALID".equals(error.text) || "TIME_TOO_BIG".equals(error.text) || "TIME_TOO_SMALL".equals(error.text)) { - status = -1; - } else { + if ("TIME_TOO_BIG".equals(error.text) || error.text.startsWith("FLOOD_WAIT")) { status = 0; + } else { + status = -1; } tgVoip.onStreamPartAvailable(timestamp, null, status, responseTime); } @@ -1604,55 +1624,71 @@ public class VoIPService extends VoIPBaseService { currentStreamRequestId = 0; } }); - tgVoip.setOnStateUpdatedListener((state, inTransition) -> { - dispatchStateChanged(state == 1 || switchingStream ? STATE_ESTABLISHED : STATE_RECONNECTING); - if (state == 0) { - startGroupCheckShortpoll(); - if (playedConnectedSound && spPlayId == 0 && !switchingStream) { - Utilities.globalQueue.postRunnable(() -> { - if (spPlayId != 0) { - soundPool.stop(spPlayId); - } - spPlayId = soundPool.play(spVoiceChatConnecting, 1.0f, 1.0f, 0, -1, 1); - }); - } - } else { - cancelGroupCheckShortPoll(); - if (!inTransition) { - switchingStream = false; - } - if (playedConnectedSound) { - Utilities.globalQueue.postRunnable(() -> { - if (spPlayId != 0) { - soundPool.stop(spPlayId); - spPlayId = 0; - } - }); - if (connectingSoundRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(connectingSoundRunnable); - connectingSoundRunnable = null; - } - } else { - Utilities.globalQueue.postRunnable(() -> soundPool.play(spVoiceChatStartId, 1.0f, 1.0f, 0, 0, 1)); - playedConnectedSound = true; - } - if (!wasConnected) { - wasConnected = true; - NativeInstance instance = tgVoip; - if (instance != null) { - if (!micMute) { - tgVoip.setMuteMicrophone(false); - } - } - setParticipantsVolume(); - } - } - }); + tgVoip.setOnStateUpdatedListener(this::updateConnectionState); } tgVoip.resetGroupInstance(false); dispatchStateChanged(STATE_WAIT_INIT); } + private void updateConnectionState(int state, boolean inTransition) { + dispatchStateChanged(state == 1 || switchingStream ? STATE_ESTABLISHED : STATE_RECONNECTING); + if (switchingStream && (state == 0 || state == 1 && inTransition)) { + AndroidUtilities.runOnUIThread(switchingStreamTimeoutRunnable = () -> { + if (switchingStreamTimeoutRunnable == null) { + return; + } + switchingStream = false; + updateConnectionState(0, true); + switchingStreamTimeoutRunnable = null; + }, 3000); + } + if (state == 0) { + startGroupCheckShortpoll(); + if (playedConnectedSound && spPlayId == 0 && !switchingStream) { + Utilities.globalQueue.postRunnable(() -> { + if (spPlayId != 0) { + soundPool.stop(spPlayId); + } + spPlayId = soundPool.play(spVoiceChatConnecting, 1.0f, 1.0f, 0, -1, 1); + }); + } + } else { + cancelGroupCheckShortPoll(); + if (!inTransition) { + switchingStream = false; + } + if (switchingStreamTimeoutRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(switchingStreamTimeoutRunnable); + switchingStreamTimeoutRunnable = null; + } + if (playedConnectedSound) { + Utilities.globalQueue.postRunnable(() -> { + if (spPlayId != 0) { + soundPool.stop(spPlayId); + spPlayId = 0; + } + }); + if (connectingSoundRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(connectingSoundRunnable); + connectingSoundRunnable = null; + } + } else { + Utilities.globalQueue.postRunnable(() -> soundPool.play(spVoiceChatStartId, 1.0f, 1.0f, 0, 0, 1)); + playedConnectedSound = true; + } + if (!wasConnected) { + wasConnected = true; + NativeInstance instance = tgVoip; + if (instance != null) { + if (!micMute) { + tgVoip.setMuteMicrophone(false); + } + } + setParticipantsVolume(); + } + } + } + public void setParticipantsVolume() { NativeInstance instance = tgVoip; if (instance != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 16da619c1..82cad21d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -62,7 +62,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800; public static final int MESSAGE_FLAG_EDITED = 0x00008000; - public static final int LAYER = 125; + public static final int LAYER = 126; public static class TL_stats_megagroupStats extends TLObject { public static int constructor = 0xef7ff916; @@ -3968,9 +3968,10 @@ public class TLRPC { } public static class TL_channels_channelParticipant extends TLObject { - public static int constructor = 0xd0d9b163; + public static int constructor = 0xdfb80317; public ChannelParticipant participant; + public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); public static TL_channels_channelParticipant TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -3996,6 +3997,21 @@ public class TLRPC { return; } int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); for (int a = 0; a < count; a++) { User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { @@ -4009,7 +4025,13 @@ public class TLRPC { stream.writeInt32(constructor); participant.serializeToStream(stream); stream.writeInt32(0x1cb5c415); - int count = users.size(); + int count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); stream.writeInt32(count); for (int a = 0; a < count; a++) { users.get(a).serializeToStream(stream); @@ -30402,7 +30424,7 @@ public class TLRPC { } public static abstract class ChannelParticipant extends TLObject { - public int user_id; + public Peer peer; public int kicked_by; public int date; public TL_channelBannedRights_layer92 banned_rights_layer92; @@ -30421,10 +30443,13 @@ public class TLRPC { ChannelParticipant result = null; switch (constructor) { case 0x1c0facaf: - result = new TL_channelParticipantBanned(); + result = new TL_channelParticipantBanned_layer125(); + break; + case 0x1b03f006: + result = new TL_channelParticipantLeft(); break; case 0xc3c6796b: - result = new TL_channelParticipantLeft(); + result = new TL_channelParticipantLeft_layer125(); break; case 0x222c1886: result = new TL_channelParticipantBanned_layer92(); @@ -30461,6 +30486,9 @@ public class TLRPC { break; case 0x5daa6e23: result = new TL_channelParticipantAdmin_layer103(); + break; + case 0x50a1dfd6: + result = new TL_channelParticipantBanned(); break; } if (result == null && exception) { @@ -30473,14 +30501,15 @@ public class TLRPC { } } - public static class TL_channelParticipantBanned extends ChannelParticipant { + public static class TL_channelParticipantBanned_layer125 extends TL_channelParticipantBanned { public static int constructor = 0x1c0facaf; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); left = (flags & 1) != 0; - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); kicked_by = stream.readInt32(exception); date = stream.readInt32(exception); banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -30490,7 +30519,7 @@ public class TLRPC { stream.writeInt32(constructor); flags = left ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(kicked_by); stream.writeInt32(date); banned_rights.serializeToStream(stream); @@ -30498,16 +30527,55 @@ public class TLRPC { } public static class TL_channelParticipantLeft extends ChannelParticipant { - public static int constructor = 0xc3c6796b; + public static int constructor = 0x1b03f006; public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(user_id); + peer.serializeToStream(stream); + } + } + + public static class TL_channelParticipantLeft_layer125 extends TL_channelParticipantLeft { + public static int constructor = 0xc3c6796b; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(peer.user_id); + } + } + + public static class TL_channelParticipantBanned extends ChannelParticipant { + public static int constructor = 0x50a1dfd6; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + left = (flags & 1) != 0; + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + kicked_by = stream.readInt32(exception); + date = stream.readInt32(exception); + banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = left ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(kicked_by); + stream.writeInt32(date); + banned_rights.serializeToStream(stream); } } @@ -30516,12 +30584,13 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); } } @@ -30530,13 +30599,14 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); date = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(date); } } @@ -30546,14 +30616,15 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); kicked_by = stream.readInt32(exception); date = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(kicked_by); stream.writeInt32(date); } @@ -30564,14 +30635,15 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); inviter_id = stream.readInt32(exception); date = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(inviter_id); stream.writeInt32(date); } @@ -30585,7 +30657,8 @@ public class TLRPC { flags = stream.readInt32(exception); can_edit = (flags & 1) != 0; self = (flags & 2) != 0; - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); if ((flags & 2) != 0) { inviter_id = stream.readInt32(exception); } @@ -30602,7 +30675,7 @@ public class TLRPC { flags = can_edit ? (flags | 1) : (flags &~ 1); flags = self ? (flags | 2) : (flags &~ 2); stream.writeInt32(flags); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); if ((flags & 2) != 0) { stream.writeInt32(inviter_id); } @@ -30621,7 +30694,8 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); if ((flags & 1) != 0) { rank = stream.readString(exception); } @@ -30630,7 +30704,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(flags); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); if ((flags & 1) != 0) { stream.writeString(rank); } @@ -30643,7 +30717,8 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception); if ((flags & 1) != 0) { rank = stream.readString(exception); @@ -30653,7 +30728,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(flags); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); admin_rights.serializeToStream(stream); if ((flags & 1) != 0) { stream.writeString(rank); @@ -30666,14 +30741,15 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); inviter_id = stream.readInt32(exception); date = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(inviter_id); stream.writeInt32(date); } @@ -30684,14 +30760,15 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); inviter_id = stream.readInt32(exception); date = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(inviter_id); stream.writeInt32(date); } @@ -30704,7 +30781,8 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); can_edit = (flags & 1) != 0; - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); inviter_id = stream.readInt32(exception); promoted_by = stream.readInt32(exception); date = stream.readInt32(exception); @@ -30716,7 +30794,7 @@ public class TLRPC { stream.writeInt32(constructor); flags = can_edit ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(inviter_id); stream.writeInt32(promoted_by); stream.writeInt32(date); @@ -30732,7 +30810,8 @@ public class TLRPC { flags = stream.readInt32(exception); can_edit = (flags & 1) != 0; self = (flags & 2) != 0; - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); if ((flags & 2) != 0) { inviter_id = stream.readInt32(exception); } @@ -30746,7 +30825,7 @@ public class TLRPC { flags = can_edit ? (flags | 1) : (flags &~ 1); flags = self ? (flags | 2) : (flags &~ 2); stream.writeInt32(flags); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); if ((flags & 2) != 0) { stream.writeInt32(inviter_id); } @@ -30816,9 +30895,9 @@ public class TLRPC { public static channels_ChannelParticipants TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { channels_ChannelParticipants result = null; switch (constructor) { - case 0xf56ee2a8: - result = new TL_channels_channelParticipants(); - break; + case 0x9ab0feaf: + result = new TL_channels_channelParticipants(); + break; case 0xf0173fe9: result = new TL_channels_channelParticipantsNotModified(); break; @@ -30833,61 +30912,86 @@ public class TLRPC { } } - public static class TL_channels_channelParticipants extends channels_ChannelParticipants { - public static int constructor = 0xf56ee2a8; + public static class TL_channels_channelParticipants extends channels_ChannelParticipants { + public static int constructor = 0x9ab0feaf; + public int count; + public ArrayList participants = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); - public void readParams(AbstractSerializedData stream, boolean exception) { - count = stream.readInt32(exception); - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - ChannelParticipant object = ChannelParticipant.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - participants.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + count = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + ChannelParticipant object = ChannelParticipant.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + participants.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(count); - stream.writeInt32(0x1cb5c415); - int count = participants.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - participants.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(count); + stream.writeInt32(0x1cb5c415); + int count = participants.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + participants.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } public static class TL_channels_channelParticipantsNotModified extends channels_ChannelParticipants { public static int constructor = 0xf0173fe9; @@ -33920,7 +34024,8 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); left = (flags & 1) != 0; - user_id = stream.readInt32(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = stream.readInt32(exception); kicked_by = stream.readInt32(exception); date = stream.readInt32(exception); banned_rights_layer92 = TL_channelBannedRights_layer92.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -33931,7 +34036,7 @@ public class TLRPC { stream.writeInt32(constructor); flags = left ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); - stream.writeInt32(user_id); + stream.writeInt32(peer.user_id); stream.writeInt32(kicked_by); stream.writeInt32(date); banned_rights_layer92.serializeToStream(stream); @@ -44404,10 +44509,10 @@ public class TLRPC { } public static class TL_channels_getParticipant extends TLObject { - public static int constructor = 0x546dd7a6; + public static int constructor = 0xa0ab6cc6; public InputChannel channel; - public InputUser user_id; + public InputPeer participant; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return TL_channels_channelParticipant.TLdeserialize(stream, constructor, exception); @@ -44416,7 +44521,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); channel.serializeToStream(stream); - user_id.serializeToStream(stream); + participant.serializeToStream(stream); } } @@ -44704,10 +44809,10 @@ public class TLRPC { } public static class TL_channels_editBanned extends TLObject { - public static int constructor = 0x72796912; + public static int constructor = 0x96e6cd81; public InputChannel channel; - public InputUser user_id; + public InputPeer participant; public TL_chatBannedRights banned_rights; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -44717,7 +44822,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); channel.serializeToStream(stream); - user_id.serializeToStream(stream); + participant.serializeToStream(stream); banned_rights.serializeToStream(stream); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java index d9c410e97..bd8f3e4db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java @@ -28,6 +28,8 @@ import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.Components.EmptyStubSpan; import org.telegram.ui.Components.StaticLayoutEx; public class SimpleTextView extends View implements Drawable.Callback { @@ -75,6 +77,9 @@ public class SimpleTextView extends View implements Drawable.Callback { private static final int DIST_BETWEEN_SCROLLING_TEXT = 16; private static final int SCROLL_DELAY_MS = 500; private static final int SCROLL_SLOWDOWN_PX = 100; + private int fullLayoutAdditionalWidth; + private int fullLayoutLeftOffset; + private boolean crosfadeFullLayout; public SimpleTextView(Context context) { super(context); @@ -173,8 +178,7 @@ public class SimpleTextView extends View implements Drawable.Callback { if (layout.getLineCount() > 0) { textWidth = (int) Math.ceil(layout.getLineWidth(0)); if (fullLayout != null) { - textHeight = layout.getLineBottom(0); - textHeight += fullLayout.getLineBottom(fullLayout.getLineCount() - 1); + textHeight = fullLayout.getLineBottom(fullLayout.getLineCount() - 1); } else if (maxLines > 1 && layout.getLineCount() > 0) { textHeight = layout.getLineBottom(layout.getLineCount() - 1); } else { @@ -184,13 +188,21 @@ public class SimpleTextView extends View implements Drawable.Callback { if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL) { offsetX = (width - textWidth) / 2; } else if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) { - if (firstLineLayout != null) { + if (crosfadeFullLayout) { + offsetX = 0; + } else if (firstLineLayout != null) { offsetX = -(int) firstLineLayout.getLineLeft(0); } else { offsetX = -(int) layout.getLineLeft(0); } } else if (layout.getLineLeft(0) == 0) { - offsetX = width - textWidth; + if (crosfadeFullLayout) { + offsetX = 0; + } else if (firstLineLayout != null) { + offsetX = (int) (width - firstLineLayout.getLineWidth(0)); + } else { + offsetX = width - textWidth; + } } else { offsetX = -AndroidUtilities.dp(8); } @@ -211,28 +223,38 @@ public class SimpleTextView extends View implements Drawable.Callback { width -= dw; width -= drawablePadding; } + crosfadeFullLayout = false; if (buildFullLayout) { CharSequence string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END); if (!string.equals(text)) { fullLayout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, 3, false); if (fullLayout != null) { - int end = fullLayout.getLineEnd(0); - int start = fullLayout.getLineStart(1); - CharSequence substr = text.subSequence(0, end); - CharSequence full = text.subSequence(start, text.length()); - CharSequence part; - if (end < string.length()) { - part = string.subSequence(end, string.length()); + if (LocaleController.isRTL || fullLayout.isRtlCharAt(0) && fullLayoutAdditionalWidth != 0) { + layout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, maxLines, false); + fullLayout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width + fullLayoutAdditionalWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width + fullLayoutAdditionalWidth, 3, false); + partLayout = null; + firstLineLayout = null; + crosfadeFullLayout = true; } else { - part = "…"; + int end = fullLayout.getLineEnd(0); + int start = fullLayout.getLineStart(1); + CharSequence substr = text.subSequence(0, end); + SpannableStringBuilder full = SpannableStringBuilder.valueOf(text); + full.setSpan(new EmptyStubSpan(), 0, start, 0); + CharSequence part; + if (end < string.length()) { + part = string.subSequence(end, string.length()); + } else { + part = "…"; + } + firstLineLayout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + layout = new StaticLayout(substr, 0, substr.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (layout.getLineLeft(0) != 0) { + part = "\u200F" + part; + } + partLayout = new StaticLayout(part, 0, part.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + fullLayout = StaticLayoutEx.createStaticLayout(full, 0, full.length(), textPaint, width + fullLayoutAdditionalWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width + fullLayoutAdditionalWidth, 3, false); } - firstLineLayout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - layout = new StaticLayout(substr, 0, substr.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - if (layout.getLineLeft(0) != 0) { - part = "\u200F" + part; - } - partLayout = new StaticLayout(part, 0, part.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - fullLayout = StaticLayoutEx.createStaticLayout(full, 0, full.length(), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, 2, false); } } else { layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); @@ -547,7 +569,7 @@ public class SimpleTextView extends View implements Drawable.Callback { //canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); } } - layout.draw(canvas); + drawLayout(canvas); if (partLayout != null && fullAlpha < 1.0f) { int prevAlpha = textPaint.getAlpha(); textPaint.setAlpha((int) (255 * (1.0f - fullAlpha))); @@ -557,6 +579,7 @@ public class SimpleTextView extends View implements Drawable.Callback { } else { canvas.translate(layout.getLineWidth(0) - (partLayout.getText().length() == 1 ? AndroidUtilities.dp(4) : 0), 0); } + canvas.translate(-fullLayoutLeftOffset * fullAlpha, 0); partLayout.draw(canvas); canvas.restore(); textPaint.setAlpha(prevAlpha); @@ -564,17 +587,17 @@ public class SimpleTextView extends View implements Drawable.Callback { if (fullLayout != null && fullAlpha > 0) { int prevAlpha = textPaint.getAlpha(); textPaint.setAlpha((int) (255 * fullAlpha)); + if (layout.getLineLeft(0) != 0) { - canvas.translate(-offsetX, layout.getLineBottom(0)); - } else { - canvas.translate(0, layout.getLineBottom(0)); + canvas.translate(-offsetX, 0); } + canvas.translate(-fullLayoutLeftOffset * fullAlpha, 0); fullLayout.draw(canvas); textPaint.setAlpha(prevAlpha); } if (scrollingOffset != 0) { canvas.translate(nextScrollX, 0); - layout.draw(canvas); + drawLayout(canvas); } if (offsetX + textOffsetX != 0 || offsetY != 0 || scrollingOffset != 0) { canvas.restore(); @@ -601,6 +624,25 @@ public class SimpleTextView extends View implements Drawable.Callback { } } + private void drawLayout(Canvas canvas) { + if (crosfadeFullLayout && fullAlpha > 0) { + int prevAlpha = textPaint.getAlpha(); + textPaint.setAlpha((int) (255 * (1f - fullAlpha))); + canvas.save(); + canvas.translate(-fullLayoutLeftOffset * fullAlpha, 0); + layout.draw(canvas); + textPaint.setAlpha(prevAlpha); + canvas.restore(); + } else if (fullAlpha > 0 && fullLayoutLeftOffset != 0) { + canvas.save(); + canvas.translate(-fullLayoutLeftOffset * fullAlpha, 0); + layout.draw(canvas); + canvas.restore(); + } else { + layout.draw(canvas); + } + } + private void updateScrollAnimation() { if (!scrollNonFitText || !textDoesNotFit && scrollingOffset == 0) { return; @@ -654,4 +696,13 @@ public class SimpleTextView extends View implements Drawable.Callback { info.setClassName("android.widget.TextView"); info.setText(text); } + + public void setFullLayoutAdditionalWidth(int fullLayoutAdditionalWidth, int fullLayoutLeftOffset) { + if (this.fullLayoutAdditionalWidth != fullLayoutAdditionalWidth || this.fullLayoutLeftOffset != fullLayoutLeftOffset) { + this.fullLayoutAdditionalWidth = fullLayoutAdditionalWidth; + this.fullLayoutLeftOffset = fullLayoutLeftOffset; + createLayout(getMeasuredWidth()); + } + + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index 06639ace9..04830f06f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -62,7 +62,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; private Runnable searchRunnable; private Runnable searchRunnable2; - private ArrayList searchResult = new ArrayList<>(); + private ArrayList searchResult = new ArrayList<>(); private ArrayList searchResultNames = new ArrayList<>(); private ArrayList searchResultMessages = new ArrayList<>(); private ArrayList searchResultHashtags = new ArrayList<>(); @@ -556,7 +556,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { return; } MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { - ArrayList resultArray = new ArrayList<>(); + ArrayList resultArray = new ArrayList<>(); ArrayList resultArrayNames = new ArrayList<>(); ArrayList encUsers = new ArrayList<>(); MessagesStorage.getInstance(currentAccount).localSearch(dialogsType, q, resultArray, resultArrayNames, encUsers, -1); @@ -571,7 +571,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } - private void updateSearchResults(final ArrayList result, final ArrayList names, final ArrayList encUsers, final int searchId) { + private void updateSearchResults(final ArrayList result, final ArrayList names, final ArrayList encUsers, final int searchId) { AndroidUtilities.runOnUIThread(() -> { waitingResponseCount--; if (searchId != lastSearchId) { @@ -586,7 +586,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } searchWas = true; for (int a = 0; a < result.size(); a++) { - TLObject obj = result.get(a); + Object obj = result.get(a); if (obj instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) obj; MessagesController.getInstance(currentAccount).putUser(user, true); @@ -982,7 +982,6 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { String foundUserName = searchAdapterHelper.getLastFoundUsername(); if (!TextUtils.isEmpty(foundUserName)) { String nameSearch = null; - String nameSearchLower = null; int index; if (user != null) { nameSearch = ContactsController.formatName(user.first_name, user.last_name); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java index 732484fa4..cbbf4cff1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java @@ -218,13 +218,13 @@ public class FiltersView extends RecyclerListView { return usersFilters.get(i); } - public void setUsersAndDates(ArrayList localUsers, ArrayList dates) { + public void setUsersAndDates(ArrayList localUsers, ArrayList dates) { oldItems.clear(); oldItems.addAll(usersFilters); usersFilters.clear(); if (localUsers != null) { for (int i = 0; i < localUsers.size(); i++) { - TLObject object = localUsers.get(i); + Object object = localUsers.get(i); if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; String title; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java index 4769604c5..524c9346f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -840,19 +840,29 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { if (error == null) { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; messagesController.putUsers(res.users, false); + messagesController.putChats(res.chats, false); boolean hasResults = !searchResultUsernames.isEmpty(); if (!res.participants.isEmpty()) { int currentUserId = UserConfig.getInstance(currentAccount).getClientUserId(); for (int a = 0; a < res.participants.size(); a++) { TLRPC.ChannelParticipant participant = res.participants.get(a); - if (searchResultUsernamesMap.indexOfKey(participant.user_id) >= 0 || !isSearchingMentions && participant.user_id == currentUserId) { + int peerId = MessageObject.getPeerId(participant.peer); + if (searchResultUsernamesMap.indexOfKey(peerId) >= 0 || !isSearchingMentions && peerId == currentUserId) { continue; } - TLRPC.User user = messagesController.getUser(participant.user_id); - if (user == null) { - return; + if (peerId > 0) { + TLRPC.User user = messagesController.getUser(peerId); + if (user == null) { + return; + } + searchResultUsernames.add(user); + } else { + TLRPC.Chat chat = messagesController.getChat(-peerId); + if (chat == null) { + return; + } + searchResultUsernames.add(chat); } - searchResultUsernames.add(user); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index 39ee4ae6f..1193ab185 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -46,7 +46,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; private SparseArray ignoreUsers; - private ArrayList searchResult = new ArrayList<>(); + private ArrayList searchResult = new ArrayList<>(); private ArrayList searchResultNames = new ArrayList<>(); private SearchAdapterHelper searchAdapterHelper; private SparseArray checkedMap; @@ -156,7 +156,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { search[1] = search2; } - ArrayList resultArray = new ArrayList<>(); + ArrayList resultArray = new ArrayList<>(); ArrayList resultArrayNames = new ArrayList<>(); for (int a = 0; a < contactsCopy.size(); a++) { @@ -206,7 +206,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { }); } - private void updateSearchResults(int searchReqIdFinal, final ArrayList users, final ArrayList names) { + private void updateSearchResults(int searchReqIdFinal, final ArrayList users, final ArrayList names) { AndroidUtilities.runOnUIThread(() -> { if (searchReqIdFinal == searchReqId) { searchResult = users; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java index 49608be8f..58ae29ac2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java @@ -17,6 +17,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.UserConfig; @@ -24,6 +25,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ChatUsersActivity; +import org.telegram.ui.Components.ShareAlert; import java.util.ArrayList; import java.util.Collections; @@ -70,7 +72,7 @@ public class SearchAdapterHelper { private SparseArray groupSearchMap = new SparseArray<>(); private SparseArray phoneSearchMap = new SparseArray<>(); private ArrayList phonesSearch = new ArrayList<>(); - private ArrayList localSearchResults; + private ArrayList localSearchResults; private int currentAccount = UserConfig.selectedAccount; @@ -149,17 +151,19 @@ public class SearchAdapterHelper { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; lastFoundChannel = query.toLowerCase(); MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); groupSearch.clear(); groupSearchMap.clear(); groupSearch.addAll(res.participants); int currentUserId = UserConfig.getInstance(currentAccount).getClientUserId(); for (int a = 0, N = res.participants.size(); a < N; a++) { TLRPC.ChannelParticipant participant = res.participants.get(a); - if (!allowSelf && participant.user_id == currentUserId) { + int peerId = MessageObject.getPeerId(participant.peer); + if (!allowSelf && peerId == currentUserId) { groupSearch.remove(participant); continue; } - groupSearchMap.put(participant.user_id, participant); + groupSearchMap.put(peerId, participant); } removeGroupSearchFromGlobal(); if (localSearchResults != null) { @@ -383,20 +387,24 @@ public class SearchAdapterHelper { if (object instanceof TLRPC.ChatParticipant) { groupSearchMap.put(((TLRPC.ChatParticipant) object).user_id, object); } else if (object instanceof TLRPC.ChannelParticipant) { - groupSearchMap.put(((TLRPC.ChannelParticipant) object).user_id, object); + groupSearchMap.put(MessageObject.getPeerId(((TLRPC.ChannelParticipant) object).peer), object); } } removeGroupSearchFromGlobal(); } - public void mergeResults(ArrayList localResults) { + public void mergeResults(ArrayList localResults) { localSearchResults = localResults; if (globalSearchMap.size() == 0 || localResults == null) { return; } int count = localResults.size(); for (int a = 0; a < count; a++) { - TLObject obj = localResults.get(a); + Object obj = localResults.get(a); + if (obj instanceof ShareAlert.DialogSearchResult) { + ShareAlert.DialogSearchResult searchResult = (ShareAlert.DialogSearchResult) obj; + obj = searchResult.object; + } if (obj instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) obj; TLRPC.User u = (TLRPC.User) globalSearchMap.get(user.id); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index b7779c74e..9a975dd7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -3966,6 +3966,9 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } float heightDiff = maxHeight - minHeight; + if (heightDiff == 0) { + heightDiff = 1; + } currentHeaderHeight = newHeight; float scale = 0.8f + (currentHeaderHeight - minHeight) / heightDiff * 0.2f; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java new file mode 100644 index 000000000..1e9fcfab6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java @@ -0,0 +1,383 @@ +package org.telegram.ui; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.graphics.drawable.GradientDrawable; +import android.os.Build; +import android.os.SystemClock; +import android.text.TextPaint; +import android.view.View; + +import com.google.android.exoplayer2.util.Log; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.ProfileGalleryView; + +import java.util.Arrays; + +public class AvatarPreviewPagerIndicator extends View implements ProfileGalleryView.Callback { + + private final RectF indicatorRect = new RectF(); + + private final int statusBarHeight = 0; + private int overlayCountVisible = 1; + + private final Rect topOverlayRect = new Rect(); + private final Rect bottomOverlayRect = new Rect(); + private final RectF rect = new RectF(); + + private final GradientDrawable topOverlayGradient; + private final GradientDrawable bottomOverlayGradient; + private final ValueAnimator animator; + private final float[] animatorValues = new float[]{0f, 1f}; + private final Paint backgroundPaint; + private final Paint barPaint; + private final Paint selectedBarPaint; + + Path path = new Path(); + RectF rectF = new RectF(); + + private final GradientDrawable[] pressedOverlayGradient = new GradientDrawable[2]; + private final boolean[] pressedOverlayVisible = new boolean[2]; + private final float[] pressedOverlayAlpha = new float[2]; + + private boolean isOverlaysVisible; + private float currentAnimationValue; + private float alpha = 0f; + private float[] alphas = null; + private long lastTime; + private float previousSelectedProgress; + private int previousSelectedPotision = -1; + private float currentProgress; + private int selectedPosition; + + private float currentLoadingAnimationProgress; + private int currentLoadingAnimationDirection = 1; + + ProfileGalleryView profileGalleryView; + + TextPaint textPaint; + private float progressToCounter; + + public AvatarPreviewPagerIndicator(Context context) { + super(context); + + barPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + barPaint.setColor(0x55ffffff); + selectedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + selectedBarPaint.setColor(0xffffffff); + + topOverlayGradient = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x42000000, 0}); + topOverlayGradient.setShape(GradientDrawable.RECTANGLE); + + bottomOverlayGradient = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, new int[] {0x42000000, 0}); + bottomOverlayGradient.setShape(GradientDrawable.RECTANGLE); + + for (int i = 0; i < 2; i++) { + final GradientDrawable.Orientation orientation = i == 0 ? GradientDrawable.Orientation.LEFT_RIGHT : GradientDrawable.Orientation.RIGHT_LEFT; + pressedOverlayGradient[i] = new GradientDrawable(orientation, new int[] {0x32000000, 0}); + pressedOverlayGradient[i].setShape(GradientDrawable.RECTANGLE); + } + + backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + backgroundPaint.setColor(Color.BLACK); + backgroundPaint.setAlpha(66); + animator = ValueAnimator.ofFloat(0f, 1f); + animator.setDuration(250); + animator.setInterpolator(CubicBezierInterpolator.EASE_BOTH); + animator.addUpdateListener(anim -> { + float value = AndroidUtilities.lerp(animatorValues, currentAnimationValue = anim.getAnimatedFraction()); + setAlphaValue(value, true); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (!isOverlaysVisible) { + setVisibility(GONE); + } + } + + @Override + public void onAnimationStart(Animator animation) { + setVisibility(VISIBLE); + } + }); + + + textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(Color.WHITE); + textPaint.setTypeface(Typeface.SANS_SERIF); + textPaint.setTextAlign(Paint.Align.CENTER); + textPaint.setTextSize(AndroidUtilities.dpf2(15f)); + } + + public void saveCurrentPageProgress() { + previousSelectedProgress = currentProgress; + previousSelectedPotision = selectedPosition; + currentLoadingAnimationProgress = 0.0f; + currentLoadingAnimationDirection = 1; + } + + public void setAlphaValue(float value, boolean self) { + if (Build.VERSION.SDK_INT > 18) { + int alpha = (int) (255 * value); + topOverlayGradient.setAlpha(alpha); + bottomOverlayGradient.setAlpha(alpha); + backgroundPaint.setAlpha((int) (66 * value)); + barPaint.setAlpha((int) (0x55 * value)); + selectedBarPaint.setAlpha(alpha); + this.alpha = value; + } else { + setAlpha(value); + } + if (!self) { + currentAnimationValue = value; + } + invalidate(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + path.reset(); + rectF.set(0, 0, getMeasuredHeight(), getMeasuredWidth()); + path.addRoundRect(rectF, new float[]{AndroidUtilities.dp(13), AndroidUtilities.dp(13), AndroidUtilities.dp(13), AndroidUtilities.dp(13), 0, 0, 0, 0}, Path.Direction.CCW); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + final int actionBarHeight = statusBarHeight + ActionBar.getCurrentActionBarHeight(); + final float k = 0.5f; + topOverlayRect.set(0, 0, w, (int) (actionBarHeight * k)); + bottomOverlayRect.set(0, (int) (h - AndroidUtilities.dp(72f) * k), w, h); + topOverlayGradient.setBounds(0, topOverlayRect.bottom, w, actionBarHeight + AndroidUtilities.dp(16f)); + bottomOverlayGradient.setBounds(0, h - AndroidUtilities.dp(72f) - AndroidUtilities.dp(24f), w, bottomOverlayRect.top); + pressedOverlayGradient[0].setBounds(0, 0, w / 5, h); + pressedOverlayGradient[1].setBounds(w - (w / 5), 0, w, h); + } + + @Override + protected void onDraw(Canvas canvas) { +// canvas.save(); +// canvas.clipPath(path); + + for (int i = 0; i < 2; i++) { + if (pressedOverlayAlpha[i] > 0f) { + pressedOverlayGradient[i].setAlpha((int) (pressedOverlayAlpha[i] * 255)); + pressedOverlayGradient[i].draw(canvas); + } + } + + topOverlayGradient.draw(canvas); + canvas.drawRect(topOverlayRect, backgroundPaint); + //canvas.restore(); + + + int count = profileGalleryView.getRealCount(); + selectedPosition = profileGalleryView.getRealPosition(); + + if (alphas == null || alphas.length != count) { + alphas = new float[count]; + Arrays.fill(alphas, 0.0f); + } + + boolean invalidate = false; + + long newTime = SystemClock.elapsedRealtime(); + long dt = (newTime - lastTime); + if (dt < 0 || dt > 20) { + dt = 17; + } + lastTime = newTime; + + if (count > 1 && count <= 20) { + if (overlayCountVisible == 0) { + alpha = 0.0f; + overlayCountVisible = 3; + } else if (overlayCountVisible == 1) { + alpha = 0.0f; + overlayCountVisible = 2; + } + if (overlayCountVisible == 2) { + barPaint.setAlpha((int) (0x55 * alpha)); + selectedBarPaint.setAlpha((int) (0xff * alpha)); + } + int width = (getMeasuredWidth() - AndroidUtilities.dp(5 * 2) - AndroidUtilities.dp(2 * (count - 1))) / count; + int y = AndroidUtilities.dp(8); + for (int a = 0; a < count; a++) { + int x = AndroidUtilities.dp(5 + a * 2) + width * a; + float progress; + int baseAlpha = 0x55; + if (a == previousSelectedPotision && Math.abs(previousSelectedProgress - 1.0f) > 0.0001f) { + progress = previousSelectedProgress; + canvas.save(); + canvas.clipRect(x + width * progress, y, x + width, y + AndroidUtilities.dp(2)); + rect.set(x, y, x + width, y + AndroidUtilities.dp(2)); + barPaint.setAlpha((int) (0x55 * alpha)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), barPaint); + baseAlpha = 0x50; + canvas.restore(); + invalidate = true; + } else if (a == selectedPosition) { + if (profileGalleryView.isCurrentItemVideo()) { + progress = currentProgress = profileGalleryView.getCurrentItemProgress(); + if (progress <= 0 && profileGalleryView.isLoadingCurrentVideo() || currentLoadingAnimationProgress > 0.0f) { + currentLoadingAnimationProgress += currentLoadingAnimationDirection * dt / 500.0f; + if (currentLoadingAnimationProgress > 1.0f) { + currentLoadingAnimationProgress = 1.0f; + currentLoadingAnimationDirection *= -1; + } else if (currentLoadingAnimationProgress <= 0) { + currentLoadingAnimationProgress = 0.0f; + currentLoadingAnimationDirection *= -1; + } + } + rect.set(x, y, x + width, y + AndroidUtilities.dp(2)); + barPaint.setAlpha((int) ((0x55 + 0x30 * currentLoadingAnimationProgress) * alpha)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), barPaint); + invalidate = true; + baseAlpha = 0x50; + } else { + progress = currentProgress = 1.0f; + } + } else { + progress = 1.0f; + } + rect.set(x, y, x + width * progress, y + AndroidUtilities.dp(2)); + + if (a != selectedPosition) { + if (overlayCountVisible == 3) { + barPaint.setAlpha((int) (AndroidUtilities.lerp(baseAlpha, 0xff, CubicBezierInterpolator.EASE_BOTH.getInterpolation(alphas[a])) * alpha)); + } + } else { + alphas[a] = 0.75f; + } + canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), a == selectedPosition ? selectedBarPaint : barPaint); + } + + if (overlayCountVisible == 2) { + if (alpha < 1.0f) { + alpha += dt / 180.0f; + if (alpha > 1.0f) { + alpha = 1.0f; + } + invalidate = true; + } else { + overlayCountVisible = 3; + } + } else if (overlayCountVisible == 3) { + for (int i = 0; i < alphas.length; i++) { + if (i != selectedPosition && alphas[i] > 0.0f) { + alphas[i] -= dt / 500.0f; + if (alphas[i] <= 0.0f) { + alphas[i] = 0.0f; + if (i == previousSelectedPotision) { + previousSelectedPotision = -1; + } + } + invalidate = true; + } else if (i == previousSelectedPotision) { + previousSelectedPotision = -1; + } + } + } + } + if (count > 20 || progressToCounter != 0) { + final float textWidth = textPaint.measureText(getCurrentTitle()); + indicatorRect.right = getMeasuredWidth() - AndroidUtilities.dp(8f); + indicatorRect.left = indicatorRect.right - (textWidth + AndroidUtilities.dpf2(16f)); + indicatorRect.top = AndroidUtilities.dp(8f); + indicatorRect.bottom = indicatorRect.top + AndroidUtilities.dp(26); + + final float radius = AndroidUtilities.dpf2(12); + canvas.save(); + boolean showCounter = count > 20; + if (showCounter && progressToCounter != 1f) { + progressToCounter += dt / 150f; + } else if (!showCounter && progressToCounter != 0f) { + progressToCounter -= dt / 150f; + } + if (progressToCounter >= 1f) { + progressToCounter = 1f; + } else if (progressToCounter <= 0) { + progressToCounter = 0f; + } else { + invalidate(); + } + canvas.scale(progressToCounter, progressToCounter, indicatorRect.centerX(), indicatorRect.centerY()); + canvas.drawRoundRect(indicatorRect, radius, radius, backgroundPaint); + canvas.drawText(getCurrentTitle(), indicatorRect.centerX(), indicatorRect.top + AndroidUtilities.dpf2(18.5f), textPaint); + canvas.restore(); + } + + for (int i = 0; i < 2; i++) { + if (pressedOverlayVisible[i]) { + if (pressedOverlayAlpha[i] < 1f) { + pressedOverlayAlpha[i] += dt / 180.0f; + if (pressedOverlayAlpha[i] > 1f) { + pressedOverlayAlpha[i] = 1f; + } + invalidate = true; + } + } else { + if (pressedOverlayAlpha[i] > 0f) { + pressedOverlayAlpha[i] -= dt / 180.0f; + if (pressedOverlayAlpha[i] < 0f) { + pressedOverlayAlpha[i] = 0f; + } + invalidate = true; + } + } + } + + if (invalidate) { + postInvalidateOnAnimation(); + } + } + + int lastCurrentItem = -1; + String title; + + private String getCurrentTitle() { + if (lastCurrentItem != profileGalleryView.getCurrentItem()) { + title = profileGalleryView.getAdapter().getPageTitle(profileGalleryView.getCurrentItem()).toString(); + lastCurrentItem = profileGalleryView.getCurrentItem(); + } + return title; + } + + @Override + public void onDown(boolean left) { + pressedOverlayVisible[left ? 0 : 1] = true; + postInvalidateOnAnimation(); + } + + @Override + public void onRelease() { + Arrays.fill(pressedOverlayVisible, false); + postInvalidateOnAnimation(); + } + + @Override + public void onPhotosLoaded() { + } + + @Override + public void onVideoSet() { + invalidate(); + } + + public void setProfileGalleryView(ProfileGalleryView profileGalleryView) { + this.profileGalleryView = profileGalleryView; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/BubbleActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/BubbleActivity.java index 819a0692a..7c737e989 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/BubbleActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/BubbleActivity.java @@ -146,8 +146,12 @@ public class BubbleActivity extends Activity implements ActionBarLayout.ActionBa return false; } currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); + if (!UserConfig.isValidAccount(currentAccount)) { + finish(); + return false; + } BaseFragment chatActivity = null; - if (intent.getAction().startsWith("com.tmessages.openchat")) { + if (intent.getAction() != null && intent.getAction().startsWith("com.tmessages.openchat")) { int chatId = intent.getIntExtra("chatId", 0); int userId = intent.getIntExtra("userId", 0); Bundle args = new Bundle(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 0c178db4d..a94138042 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -9288,7 +9288,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate forwardedNameLayout[1] = null; replyPanelIsForward = false; forwardedNameWidth = 0; - if (drawForwardedName && messageObject.needDrawForwarded() && (currentPosition == null || currentPosition.minY == 0)) { + if (messageObject.isForwarded()) { if (messageObject.messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel) { currentForwardChannel = MessagesController.getInstance(currentAccount).getChat(messageObject.messageOwner.fwd_from.from_id.channel_id); } else if (messageObject.messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChat) { @@ -9296,6 +9296,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (messageObject.messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerUser) { currentForwardUser = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.fwd_from.from_id.user_id); } + } + if (drawForwardedName && messageObject.needDrawForwarded() && (currentPosition == null || currentPosition.minY == 0)) { if (messageObject.messageOwner.fwd_from.from_name != null) { currentForwardName = messageObject.messageOwner.fwd_from.from_name; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallInvitedCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallInvitedCell.java index ef7f25aa5..e7a5e73ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallInvitedCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallInvitedCell.java @@ -112,6 +112,10 @@ public class GroupCallInvitedCell extends FrameLayout { return currentUser; } + public boolean hasAvatarSet() { + return avatarImageView.getImageReceiver().hasNotThumb(); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(58), MeasureSpec.EXACTLY)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallUserCell.java index 18ac8ffff..bbfd123fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCallUserCell.java @@ -46,6 +46,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.WaveDrawable; +import org.telegram.ui.ProfileActivity; import java.util.ArrayList; @@ -136,6 +137,36 @@ public class GroupCallUserCell extends FrameLayout { private AnimatorSet animatorSet; + private float progressToAvatarPreview; + + public void setProgressToAvatarPreview(float progressToAvatarPreview) { + this.progressToAvatarPreview = progressToAvatarPreview; + nameTextView.setTranslationX((LocaleController.isRTL ? AndroidUtilities.dp(53) : -AndroidUtilities.dp(53)) * progressToAvatarPreview); + for (int i = 0; i < statusTextView.length; i++) { + if (!TextUtils.isEmpty(statusTextView[4].getText()) && statusTextView[4].getLineCount() > 1) { + statusTextView[i].setFullLayoutAdditionalWidth(AndroidUtilities.dp(92), LocaleController.isRTL ? AndroidUtilities.dp(48) : AndroidUtilities.dp(53)); + statusTextView[i].setFullAlpha(progressToAvatarPreview); + statusTextView[i].setTranslationX(0); + statusTextView[i].invalidate(); + } else { + statusTextView[i].setTranslationX((LocaleController.isRTL ? AndroidUtilities.dp(53) : -AndroidUtilities.dp(53)) * progressToAvatarPreview); + statusTextView[i].setFullLayoutAdditionalWidth(0, 0); + } + } + avatarImageView.setAlpha(progressToAvatarPreview == 0 ? 1f : 0); + avatarWavesDrawable.setShowWaves(isSpeaking && progressToAvatarPreview == 0, this); + + + muteButton.setAlpha(1f - progressToAvatarPreview); + muteButton.setScaleX(0.6f + 0.4f * (1f - progressToAvatarPreview)); + muteButton.setScaleY(0.6f + 0.4f * (1f - progressToAvatarPreview)); + invalidate(); + } + + public AvatarWavesDrawable getAvatarWavesDrawable() { + return avatarWavesDrawable; + } + private static class VerifiedDrawable extends Drawable { private Drawable[] drawables = new Drawable[2]; @@ -342,6 +373,10 @@ public class GroupCallUserCell extends FrameLayout { return nameTextView.getText(); } + public boolean hasAvatarSet() { + return avatarImageView.getImageReceiver().hasNotThumb(); + } + public void setData(AccountInstance account, TLRPC.TL_groupCallParticipant groupCallParticipant, ChatObject.Call call, int self) { currentCall = call; accountInstance = account; @@ -441,6 +476,7 @@ public class GroupCallUserCell extends FrameLayout { progress = 0; } statusTextView[4].setFullAlpha(progress); + statusTextView[4].setFullLayoutAdditionalWidth(0, 0); invalidate(); } @@ -510,6 +546,7 @@ public class GroupCallUserCell extends FrameLayout { int newStatus; currentIconGray = false; AndroidUtilities.cancelRunOnUIThread(checkRaiseRunnable); + if (participant.muted && !isSpeaking || myted_by_me) { if (!participant.can_self_unmute || myted_by_me) { if (newRaisedHand = !participant.can_self_unmute && participant.raise_hand_rating != 0) { @@ -540,7 +577,16 @@ public class GroupCallUserCell extends FrameLayout { currentIconGray = true; } } - if (hasAbout) { + + if (isSelfUser()) { + statusTextView[4].setTextColor(Theme.getColor(Theme.key_voipgroup_listeningText)); + } else { + statusTextView[4].setTextColor(Theme.getColor(grayIconColor)); + } + + if (isSelfUser()) { + statusTextView[4].setText(LocaleController.getString("ThisIsYou", R.string.ThisIsYou)); + } else if (hasAbout) { statusTextView[4].setText(AndroidUtilities.replaceNewLines(participant.about)); } else { statusTextView[4].setText(""); @@ -586,7 +632,9 @@ public class GroupCallUserCell extends FrameLayout { statusTextView[1].setText(LocaleController.getString("Speaking", R.string.Speaking)); } } - if (!animated || newStatus != currentStatus || somethingChanged) { + if (isSelfUser()) { + applyStatus(4); + } else if (!animated || newStatus != currentStatus || somethingChanged) { if (animated) { if (animators == null) { animators = new ArrayList<>(); @@ -620,7 +668,9 @@ public class GroupCallUserCell extends FrameLayout { animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - applyStatus(newStatus); + if (!isSelfUser()) { + applyStatus(newStatus); + } animatorSet = null; } }); @@ -672,7 +722,7 @@ public class GroupCallUserCell extends FrameLayout { if (!isSpeaking) { avatarWavesDrawable.setAmplitude(0); } - avatarWavesDrawable.setShowWaves(isSpeaking, this); + avatarWavesDrawable.setShowWaves(isSpeaking && progressToAvatarPreview == 0, this); } private void applyStatus(int newStatus) { @@ -699,14 +749,20 @@ public class GroupCallUserCell extends FrameLayout { @Override protected void dispatchDraw(Canvas canvas) { if (needDivider) { - dividerPaint.setAlpha((int) ((1.0f - statusTextView[4].getFullAlpha()) * 255)); + if (progressToAvatarPreview != 0) { + dividerPaint.setAlpha((int) ((1.0f - progressToAvatarPreview) * 255)); + } else { + dividerPaint.setAlpha((int) ((1.0f - statusTextView[4].getFullAlpha()) * 255)); + } canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(68), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(68) : 0), getMeasuredHeight() - 1, dividerPaint); } int cx = avatarImageView.getLeft() + avatarImageView.getMeasuredWidth() / 2; int cy = avatarImageView.getTop() + avatarImageView.getMeasuredHeight() / 2; avatarWavesDrawable.update(); - avatarWavesDrawable.draw(canvas, cx, cy, this); + if (progressToAvatarPreview == 0) { + avatarWavesDrawable.draw(canvas, cx, cy, this); + } avatarImageView.setScaleX(avatarWavesDrawable.getAvatarScale()); avatarImageView.setScaleY(avatarWavesDrawable.getAvatarScale()); @@ -810,7 +866,6 @@ public class GroupCallUserCell extends FrameLayout { if (wavesEnter != 0) { parentView.invalidate(); } - } public float getAvatarScale() { @@ -854,6 +909,10 @@ public class GroupCallUserCell extends FrameLayout { } } + public BackupImageView getAvatarImageView() { + return avatarImageView; + } + @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 8273e548b..0ed2568ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -1640,7 +1640,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (error == null) { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; - MessagesController.getInstance(currentAccount).putUsers(res.users, false); + getMessagesController().putUsers(res.users, false); + getMessagesController().putChats(res.chats, false); admins = res.participants; if (visibleDialog instanceof AdminLogFilterAlert) { ((AdminLogFilterAlert) visibleDialog).setCurrentAdmins(admins); @@ -1961,7 +1962,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } for (int a = 0; a < admins.size(); a++) { TLRPC.ChannelParticipant channelParticipant = admins.get(a); - if (channelParticipant.user_id == uid) { + if (MessageObject.getPeerId(channelParticipant.peer) == uid) { if (!channelParticipant.can_edit) { return; } @@ -2165,9 +2166,17 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio ((URLSpanMono) url).copyToClipboard(); Toast.makeText(getParentActivity(), LocaleController.getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show(); } else if (url instanceof URLSpanUserMention) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(Utilities.parseInt(((URLSpanUserMention) url).getURL())); - if (user != null) { - MessagesController.openChatOrProfileWith(user, null, ChannelAdminLogActivity.this, 0, false); + int peerId = Utilities.parseInt(((URLSpanUserMention) url).getURL()); + if (peerId > 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(peerId); + if (user != null) { + MessagesController.openChatOrProfileWith(user, null, ChannelAdminLogActivity.this, 0, false); + } + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-peerId); + if (chat != null) { + MessagesController.openChatOrProfileWith(null, chat, ChannelAdminLogActivity.this, 0, false); + } } } else if (url instanceof URLSpanNoUnderline) { String str = ((URLSpanNoUnderline) url).getURL(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 88f6ad0e6..1fe23d464 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -659,6 +659,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean swipeBackEnabled = true; public static Pattern publicMsgUrlPattern; + public static Pattern voiceChatUrlPattern; public static Pattern privateMsgUrlPattern; private boolean waitingForSendingMessageLoad; private ValueAnimator changeBoundAnimator; @@ -3040,7 +3041,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not emptyViewContainer.setOnTouchListener((v, event) -> true); int distance = getArguments().getInt("nearby_distance", -1); - if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null) { + if ((distance >= 0 || preloadedGreetingsSticker != null) && currentUser != null && !userBlocked) { greetingsViewContainer = new ChatGreetingsView(context, currentUser, distance, currentAccount, preloadedGreetingsSticker); greetingsViewContainer.setListener((sticker) -> { animatingDocuments.put(sticker, 0); @@ -3066,7 +3067,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not emptyMessage = LocaleController.getString("NoScheduledMessages", R.string.NoScheduledMessages); } else if (currentUser != null && currentUser.id != 777000 && currentUser.id != 429000 && currentUser.id != 4244000 && MessagesController.isSupportUser(currentUser)) { emptyMessage = LocaleController.getString("GotAQuestion", R.string.GotAQuestion); - } else if (currentUser == null || currentUser.self || currentUser.deleted) { + } else if (currentUser == null || currentUser.self || currentUser.deleted || userBlocked) { emptyMessage = LocaleController.getString("NoMessages", R.string.NoMessages); } if (emptyMessage == null) { @@ -5499,7 +5500,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int[] size = MessageObject.getInlineResultWidthAndHeight(result); EmbedBottomSheet.show(getParentActivity(), result.title != null ? result.title : "", result.description, result.content.url, result.content.url, size[0], size[1], isKeyboardVisible()); } else { - processExternalUrl(0, result.content.url); + processExternalUrl(0, result.content.url, false); } } })); @@ -12070,7 +12071,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (!found) { - BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("MessageNotFound", R.string.MessageNotFound)).show(); + if (isThreadChat()) { + Bundle bundle = new Bundle(); + if (currentEncryptedChat != null) { + bundle.putInt("enc_id", currentEncryptedChat.id); + } else if (currentChat != null) { + bundle.putInt("chat_id", currentChat.id); + } else { + bundle.putInt("user_id", currentUser.id); + } + bundle.putInt("message_id", postponedScrollMessageId); + presentFragment(new ChatActivity(bundle), true); + } else { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString("MessageNotFound", R.string.MessageNotFound)).show(); + } return; } showScrollToMessageError = false; @@ -17970,10 +17984,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void hideActionMode() { - if (!actionBar.isActionModeShowed()) { - return; - } if (actionBar != null) { + if (!actionBar.isActionModeShowed()) { + return; + } actionBar.hideActionMode(); } cantDeleteMessagesCount = 0; @@ -20521,22 +20535,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not presentFragment(fragment); } } else { - processExternalUrl(0, str); + processExternalUrl(0, str, false); } } - private void processExternalUrl(int type, String url) { + private void processExternalUrl(int type, String url, boolean forceAlert) { try { Uri uri = Uri.parse(url); String host = uri.getHost() != null ? uri.getHost().toLowerCase() : ""; - if (getMessagesController().authDomains.contains(host)) { + if ((currentEncryptedChat == null || getMessagesController().secretWebpagePreview == 1) && getMessagesController().authDomains.contains(host)) { getSendMessagesHelper().requestUrlAuth(url, this, type == 0 || type == 2); return; } } catch (Exception e) { FileLog.e(e); } - if (AndroidUtilities.shouldShowUrlInAlert(url)) { + if (forceAlert || AndroidUtilities.shouldShowUrlInAlert(url)) { if (type == 0 || type == 2) { AlertsCreator.showOpenUrlAlert(ChatActivity.this, url, true, true, true); } else if (type == 1) { @@ -20689,7 +20703,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setTitle(urlFinal); builder.setItems(new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { if (which == 0) { - processExternalUrl(1, urlFinal); + processExternalUrl(1, urlFinal, false); } else if (which == 1) { String url1 = urlFinal; boolean tel = false; @@ -20709,10 +20723,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); showDialog(builder.create()); } else { + boolean forceAlert = url instanceof URLSpanReplacement; if (url instanceof URLSpanReplacement && (urlFinal == null || !urlFinal.startsWith("mailto:")) || AndroidUtilities.shouldShowUrlInAlert(urlFinal)) { if (openLinkInternally(urlFinal, messageObject != null ? messageObject.getId() : 0)) { return; } + forceAlert = true; } else { if (messageObject != null && messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.cached_page != null) { String lowerUrl = urlFinal.toLowerCase(); @@ -20727,7 +20743,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } } - processExternalUrl(2, urlFinal); + processExternalUrl(2, urlFinal, forceAlert); } } } @@ -21621,7 +21637,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not hideFieldPanel(false); } } else { - processExternalUrl(0, url); + processExternalUrl(0, url, false); } }); } else if (viewType == 4) { @@ -22287,6 +22303,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not String username = currentChat.username.toLowerCase(); if (publicMsgUrlPattern == null) { publicMsgUrlPattern = Pattern.compile("(https://)?t.me/([0-9a-zA-Z_]+)/([0-9]+)"); + voiceChatUrlPattern = Pattern.compile("(https://)?t.me/([0-9a-zA-Z_]+)\\?(voicechat+)"); } Matcher matcher = publicMsgUrlPattern.matcher(urlFinal); if (matcher.find(2) && matcher.find(3) && username.equals(matcher.group(2).toLowerCase())) { @@ -22326,6 +22343,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return true; } } + } else { + matcher = voiceChatUrlPattern.matcher(urlFinal); + try { + if (matcher.find(2) && matcher.find(3) && username.equals(matcher.group(2).toLowerCase())) { + Uri data = Uri.parse(urlFinal); + String voicechat = data.getQueryParameter("voicechat"); + if (!TextUtils.isEmpty(voicechat)) { + voiceChatHash = voicechat; + checkGroupCallJoin(true); + return true; + } + } + } catch (Exception e) { + FileLog.e(e); + } } } else { if (privateMsgUrlPattern == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java index cb55c7834..4973074a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java @@ -926,7 +926,7 @@ public class ChatRightsEditActivity extends BaseFragment { adminRights.other ? 1 : 0, adminRights, bannedRights, currentRank); } } else if (currentType == TYPE_BANNED) { - MessagesController.getInstance(currentAccount).setUserBannedRole(chatId, currentUser, bannedRights, isChannel, getFragmentForAlert(1)); + MessagesController.getInstance(currentAccount).setParticipantBannedRole(chatId, currentUser, null, bannedRights, isChannel, getFragmentForAlert(1)); int rights; if (bannedRights.send_messages || bannedRights.send_stickers || bannedRights.embed_links || bannedRights.send_media || bannedRights.send_gifs || bannedRights.send_games || bannedRights.send_inline) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index 113847df2..18584bfff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -47,6 +47,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; @@ -197,7 +198,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } - default void didUserKicked(int userId) { + default void didKickParticipant(int userId) { } } @@ -860,11 +861,17 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } @Override - public void didUserKicked(int uid) { + public void didKickParticipant(int uid) { if (participantsMap.get(uid) == null) { DiffCallback diffCallback = saveState(); TLRPC.TL_channelParticipantBanned chatParticipant = new TLRPC.TL_channelParticipantBanned(); - chatParticipant.user_id = uid; + if (uid > 0) { + chatParticipant.peer = new TLRPC.TL_peerUser(); + chatParticipant.peer.user_id = uid; + } else { + chatParticipant.peer = new TLRPC.TL_peerChannel(); + chatParticipant.peer.channel_id = -uid; + } chatParticipant.date = getConnectionsManager().getCurrentTime(); chatParticipant.kicked_by = getAccountInstance().getUserConfig().clientUserId; info.kicked_count++; @@ -914,7 +921,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (participantsMap.get(uid) == null) { DiffCallback diffCallback = saveState(); TLRPC.TL_channelParticipantAdmin chatParticipant = new TLRPC.TL_channelParticipantAdmin(); - chatParticipant.user_id = user.id; + chatParticipant.peer = new TLRPC.TL_peerUser(); + chatParticipant.peer.user_id = user.id; chatParticipant.date = getConnectionsManager().getCurrentTime(); chatParticipant.promoted_by = getAccountInstance().getUserConfig().clientUserId; participants.add(chatParticipant); @@ -950,7 +958,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (ChatObject.isChannel(currentChat)) { TLRPC.TL_channelParticipant channelParticipant1 = new TLRPC.TL_channelParticipant(); channelParticipant1.inviter_id = getUserConfig().getClientUserId(); - channelParticipant1.user_id = user.id; + channelParticipant1.peer = new TLRPC.TL_peerUser(); + channelParticipant1.peer.user_id = user.id; channelParticipant1.date = getConnectionsManager().getCurrentTime(); array.add(k, channelParticipant1); k++; @@ -1110,14 +1119,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente TLRPC.TL_chatAdminRights adminRights = null; String rank = ""; final TLObject participant; - int user_id = 0; + int peerId = 0; int promoted_by = 0; boolean canEditAdmin = false; if (listAdapter) { participant = listViewAdapter.getItem(position); if (participant instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; - user_id = channelParticipant.user_id; + peerId = MessageObject.getPeerId(channelParticipant.peer); bannedRights = channelParticipant.banned_rights; adminRights = channelParticipant.admin_rights; rank = channelParticipant.rank; @@ -1136,7 +1145,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } else if (participant instanceof TLRPC.ChatParticipant) { TLRPC.ChatParticipant chatParticipant = (TLRPC.ChatParticipant) participant; - user_id = chatParticipant.user_id; + peerId = chatParticipant.user_id; canEditAdmin = currentChat.creator; if (participant instanceof TLRPC.TL_chatParticipantCreator) { adminRights = new TLRPC.TL_chatAdminRights(); @@ -1153,7 +1162,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; getMessagesController().putUser(user, false); - participant = getAnyParticipant(user_id = user.id); + participant = getAnyParticipant(peerId = user.id); } else if (object instanceof TLRPC.ChannelParticipant || object instanceof TLRPC.ChatParticipant) { participant = object; } else { @@ -1161,14 +1170,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } if (participant instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; - user_id = channelParticipant.user_id; + peerId = MessageObject.getPeerId(channelParticipant.peer); canEditAdmin = !(channelParticipant instanceof TLRPC.TL_channelParticipantAdmin || channelParticipant instanceof TLRPC.TL_channelParticipantCreator) || channelParticipant.can_edit; bannedRights = channelParticipant.banned_rights; adminRights = channelParticipant.admin_rights; rank = channelParticipant.rank; } else if (participant instanceof TLRPC.ChatParticipant) { TLRPC.ChatParticipant chatParticipant = (TLRPC.ChatParticipant) participant; - user_id = chatParticipant.user_id; + peerId = chatParticipant.user_id; canEditAdmin = currentChat.creator; bannedRights = null; adminRights = null; @@ -1176,11 +1185,11 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente canEditAdmin = true; } } - if (user_id != 0) { + if (peerId != 0) { if (selectType != 0) { if (selectType == 3 || selectType == 1) { if (selectType != 1 && canEditAdmin && (participant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin)) { - final TLRPC.User user = getMessagesController().getUser(user_id); + final TLRPC.User user = getMessagesController().getUser(peerId); final TLRPC.TL_chatBannedRights br = bannedRights; final TLRPC.TL_chatAdminRights ar = adminRights; final boolean canEdit = canEditAdmin; @@ -1192,24 +1201,28 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } else { - openRightsEdit(user_id, participant, adminRights, bannedRights, rank, canEditAdmin, selectType == 1 ? 0 : 1, selectType == 1 || selectType == 3); + openRightsEdit(peerId, participant, adminRights, bannedRights, rank, canEditAdmin, selectType == 1 ? 0 : 1, selectType == 1 || selectType == 3); } } else { - removeUser(user_id); + removeParticipant(peerId); } } else { boolean canEdit = false; if (type == TYPE_ADMIN) { - canEdit = user_id != getUserConfig().getClientUserId() && (currentChat.creator || canEditAdmin); + canEdit = peerId != getUserConfig().getClientUserId() && (currentChat.creator || canEditAdmin); } else if (type == TYPE_BANNED || type == TYPE_KICKED) { canEdit = ChatObject.canBlockUsers(currentChat); } if (type == TYPE_BANNED || type != TYPE_ADMIN && isChannel || type == TYPE_USERS && selectType == 0) { - if (user_id == getUserConfig().getClientUserId()) { + if (peerId == getUserConfig().getClientUserId()) { return; } Bundle args = new Bundle(); - args.putInt("user_id", user_id); + if (peerId > 0) { + args.putInt("user_id", peerId); + } else { + args.putInt("chat_id", -peerId); + } presentFragment(new ProfileActivity(args)); } else { if (bannedRights == null) { @@ -1227,7 +1240,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente bannedRights.invite_users = true; bannedRights.change_info = true; } - ChatRightsEditActivity fragment = new ChatRightsEditActivity(user_id, chatId, adminRights, defaultBannedRights, bannedRights, rank, type == TYPE_ADMIN ? ChatRightsEditActivity.TYPE_ADMIN : ChatRightsEditActivity.TYPE_BANNED, canEdit, participant == null); + ChatRightsEditActivity fragment = new ChatRightsEditActivity(peerId, chatId, adminRights, defaultBannedRights, bannedRights, rank, type == TYPE_ADMIN ? ChatRightsEditActivity.TYPE_ADMIN : ChatRightsEditActivity.TYPE_BANNED, canEdit, participant == null); fragment.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { @@ -1293,7 +1306,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente return -1; } if (lhs instanceof TLRPC.ChannelParticipant && rhs instanceof TLRPC.ChannelParticipant) { - return ((TLRPC.ChannelParticipant) lhs).user_id - ((TLRPC.ChannelParticipant) rhs).user_id; + return MessageObject.getPeerId(((TLRPC.ChannelParticipant) lhs).peer) - MessageObject.getPeerId(((TLRPC.ChannelParticipant) rhs).peer); } return 0; }); @@ -1386,7 +1399,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente TLObject object = map.get(user.id); if (object instanceof TLRPC.ChannelParticipant) { TLRPC.TL_channelParticipantCreator creator = new TLRPC.TL_channelParticipantCreator(); - creator.user_id = user.id; + creator.peer = new TLRPC.TL_peerUser(); + creator.peer.user_id = user.id; map.put(user.id, creator); int index = arrayList.indexOf(object); if (index >= 0) { @@ -1399,7 +1413,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente object = map.get(selfUserId); if (object instanceof TLRPC.ChannelParticipant) { TLRPC.TL_channelParticipantAdmin admin = new TLRPC.TL_channelParticipantAdmin(); - admin.user_id = selfUserId; + admin.peer = new TLRPC.TL_peerUser(); + admin.peer.user_id = selfUserId; admin.self = true; admin.inviter_id = selfUserId; admin.promoted_by = selfUserId; @@ -1434,7 +1449,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } if (!foundAny) { TLRPC.TL_channelParticipantCreator creator = new TLRPC.TL_channelParticipantCreator(); - creator.user_id = user.id; + creator.peer = new TLRPC.TL_peerUser(); + creator.peer.user_id = user.id; participantsMap.put(user.id, creator); participants.add(creator); sortAdmins(participants); @@ -1446,16 +1462,23 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } - private void openRightsEdit2(int userId, int date, TLObject participant, TLRPC.TL_chatAdminRights adminRights, TLRPC.TL_chatBannedRights bannedRights, String rank, boolean canEditAdmin, int type, boolean removeFragment) { + private void openRightsEdit2(int peerId, int date, TLObject participant, TLRPC.TL_chatAdminRights adminRights, TLRPC.TL_chatBannedRights bannedRights, String rank, boolean canEditAdmin, int type, boolean removeFragment) { boolean[] needShowBulletin = new boolean[1]; final boolean isAdmin = participant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin; - ChatRightsEditActivity fragment = new ChatRightsEditActivity(userId, chatId, adminRights, defaultBannedRights, bannedRights, rank, type, true, false) { + ChatRightsEditActivity fragment = new ChatRightsEditActivity(peerId, chatId, adminRights, defaultBannedRights, bannedRights, rank, type, true, false) { @Override protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) { if (!isOpen && backward && needShowBulletin[0] && BulletinFactory.canShowBulletin(ChatUsersActivity.this)) { - final TLRPC.User user = getMessagesController().getUser(userId); - if (user != null) { - BulletinFactory.createPromoteToAdminBulletin(ChatUsersActivity.this, user.first_name).show(); + if (peerId > 0) { + TLRPC.User user = getMessagesController().getUser(peerId); + if (user != null) { + BulletinFactory.createPromoteToAdminBulletin(ChatUsersActivity.this, user.first_name).show(); + } + } else { + TLRPC.Chat chat = getMessagesController().getChat(-peerId); + if (chat != null) { + BulletinFactory.createPromoteToAdminBulletin(ChatUsersActivity.this, chat.title).show(); + } } } } @@ -1468,7 +1491,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente TLObject p = participants.get(a); if (p instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) p; - if (p2.user_id == userId) { + if (MessageObject.getPeerId(p2.peer) == peerId) { TLRPC.ChannelParticipant newPart; if (rights == 1) { newPart = new TLRPC.TL_channelParticipantAdmin(); @@ -1478,7 +1501,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente newPart.admin_rights = rightsAdmin; newPart.banned_rights = rightsBanned; newPart.inviter_id = getUserConfig().getClientUserId(); - newPart.user_id = userId; + if (peerId > 0) { + newPart.peer = new TLRPC.TL_peerUser(); + newPart.peer.user_id = peerId; + } else { + newPart.peer = new TLRPC.TL_peerChannel(); + newPart.peer.channel_id = -peerId; + } newPart.date = date; newPart.flags |= 4; newPart.rank = rank; @@ -1508,7 +1537,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } else if (type == 1) { if (rights == 0) { - removeParticipants(userId); + removeParticipants(peerId); } } } @@ -1555,14 +1584,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente presentFragment(fragment, removeFragment); } - private void removeUser(int userId) { + private void removeParticipant(int userId) { if (!ChatObject.isChannel(currentChat)) { return; } TLRPC.User user = getMessagesController().getUser(userId); - getMessagesController().deleteUserFromChat(chatId, user, null); + getMessagesController().deleteParticipantFromChat(chatId, user, null); if (delegate != null) { - delegate.didUserKicked(userId); + delegate.didKickParticipant(userId); } finishFragment(); } @@ -1591,11 +1620,11 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente removeParticipants(chatParticipant.user_id); } else if (object instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) object; - removeParticipants(channelParticipant.user_id); + removeParticipants(MessageObject.getPeerId(channelParticipant.peer)); } } - private void removeParticipants(int userId) { + private void removeParticipants(int peerId) { boolean updated = false; DiffCallback savedState = saveState(); for (int a = 0; a < 3; a++) { @@ -1611,9 +1640,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente map = participantsMap; arrayList = participants; } - TLObject p = map.get(userId); + TLObject p = map.get(peerId); if (p != null) { - map.remove(userId); + map.remove(peerId); arrayList.remove(p); updated = true; if (type == TYPE_BANNED) { @@ -1625,7 +1654,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente updateListAnimated(savedState); } if (listView.getAdapter() == searchListViewAdapter) { - searchListViewAdapter.removeUserId(userId); + searchListViewAdapter.removeUserId(peerId); } } @@ -1640,7 +1669,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else { map = participantsMap; } - TLObject p = map.get(channelParticipant.user_id); + TLObject p = map.get(MessageObject.getPeerId(channelParticipant.peer)); if (p instanceof TLRPC.ChannelParticipant) { channelParticipant = (TLRPC.ChannelParticipant) p; channelParticipant.admin_rights = rightsAdmin; @@ -1660,7 +1689,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (participant == null || selectType != 0) { return false; } - int userId; + int peerId; boolean canEdit; int date; TLRPC.TL_chatBannedRights bannedRights; @@ -1668,7 +1697,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente String rank; if (participant instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; - userId = channelParticipant.user_id; + peerId = MessageObject.getPeerId(channelParticipant.peer); canEdit = channelParticipant.can_edit; bannedRights = channelParticipant.banned_rights; adminRights = channelParticipant.admin_rights; @@ -1676,25 +1705,25 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente rank = channelParticipant.rank; } else if (participant instanceof TLRPC.ChatParticipant) { TLRPC.ChatParticipant chatParticipant = (TLRPC.ChatParticipant) participant; - userId = chatParticipant.user_id; + peerId = chatParticipant.user_id; date = chatParticipant.date; canEdit = ChatObject.canAddAdmins(currentChat); bannedRights = null; adminRights = null; rank = ""; } else { - userId = 0; + peerId = 0; canEdit = false; bannedRights = null; adminRights = null; date = 0; rank = null; } - if (userId == 0 || userId == getUserConfig().getClientUserId()) { + if (peerId == 0 || peerId == getUserConfig().getClientUserId()) { return false; } if (type == TYPE_USERS) { - final TLRPC.User user = getMessagesController().getUser(userId); + final TLRPC.User user = getMessagesController().getUser(peerId); boolean allowSetAdmin = ChatObject.canAddAdmins(currentChat) && (participant instanceof TLRPC.TL_channelParticipant || participant instanceof TLRPC.TL_channelParticipantBanned || participant instanceof TLRPC.TL_chatParticipant || canEdit); boolean canEditAdmin = !(participant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_channelParticipantCreator || participant instanceof TLRPC.TL_chatParticipantCreator || participant instanceof TLRPC.TL_chatParticipantAdmin) || canEdit; boolean editingAdmin = participant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin; @@ -1750,8 +1779,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setItems(items.toArray(new CharSequence[actions.size()]), AndroidUtilities.toIntArray(icons), (dialogInterface, i) -> { if (actions.get(i) == 2) { - getMessagesController().deleteUserFromChat(chatId, user, null); - removeParticipants(userId); + getMessagesController().deleteParticipantFromChat(chatId, user, null); + removeParticipants(peerId); if (currentChat != null && user != null && BulletinFactory.canShowBulletin(this)) { BulletinFactory.createRemoveFromChatBulletin(this, user, currentChat.title).show(); } @@ -1760,11 +1789,11 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente AlertDialog.Builder builder2 = new AlertDialog.Builder(getParentActivity()); builder2.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder2.setMessage(LocaleController.formatString("AdminWillBeRemoved", R.string.AdminWillBeRemoved, UserObject.getUserName(user))); - builder2.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> openRightsEdit2(userId, date, participant, adminRights, bannedRights, rank, canEditAdmin, actions.get(i), false)); + builder2.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> openRightsEdit2(peerId, date, participant, adminRights, bannedRights, rank, canEditAdmin, actions.get(i), false)); builder2.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder2.create()); } else { - openRightsEdit2(userId, date, participant, adminRights, bannedRights, rank, canEditAdmin, actions.get(i), false); + openRightsEdit2(peerId, date, participant, adminRights, bannedRights, rank, canEditAdmin, actions.get(i), false); } } }); @@ -1791,7 +1820,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente return true; } items = new CharSequence[]{ - ChatObject.canAddUsers(currentChat) ? (isChannel ? LocaleController.getString("ChannelAddToChannel", R.string.ChannelAddToChannel) : LocaleController.getString("ChannelAddToGroup", R.string.ChannelAddToGroup)) : null, + ChatObject.canAddUsers(currentChat) && peerId > 0 ? (isChannel ? LocaleController.getString("ChannelAddToChannel", R.string.ChannelAddToChannel) : LocaleController.getString("ChannelAddToGroup", R.string.ChannelAddToGroup)) : null, LocaleController.getString("ChannelDeleteFromList", R.string.ChannelDeleteFromList)}; icons = new int[]{ R.drawable.actions_addmember2, @@ -1824,7 +1853,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente builder.setItems(items, icons, (dialogInterface, i) -> { if (type == TYPE_ADMIN) { if (i == 0 && items.length == 2) { - ChatRightsEditActivity fragment = new ChatRightsEditActivity(userId, chatId, adminRights, null, null, rank, ChatRightsEditActivity.TYPE_ADMIN, true, false); + ChatRightsEditActivity fragment = new ChatRightsEditActivity(peerId, chatId, adminRights, null, null, rank, ChatRightsEditActivity.TYPE_ADMIN, true, false); fragment.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { @@ -1844,13 +1873,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente }); presentFragment(fragment); } else { - getMessagesController().setUserAdminRole(chatId, getMessagesController().getUser(userId), new TLRPC.TL_chatAdminRights(), "", !isChannel, ChatUsersActivity.this, false); - removeParticipants(userId); + getMessagesController().setUserAdminRole(chatId, getMessagesController().getUser(peerId), new TLRPC.TL_chatAdminRights(), "", !isChannel, ChatUsersActivity.this, false); + removeParticipants(peerId); } } else if (type == TYPE_BANNED || type == TYPE_KICKED) { if (i == 0) { if (type == TYPE_KICKED) { - ChatRightsEditActivity fragment = new ChatRightsEditActivity(userId, chatId, null, defaultBannedRights, bannedRights, rank, ChatRightsEditActivity.TYPE_BANNED, true, false); + ChatRightsEditActivity fragment = new ChatRightsEditActivity(peerId, chatId, null, defaultBannedRights, bannedRights, rank, ChatRightsEditActivity.TYPE_BANNED, true, false); fragment.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { @Override public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { @@ -1870,12 +1899,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente }); presentFragment(fragment); } else if (type == TYPE_BANNED) { - TLRPC.User user = getMessagesController().getUser(userId); - getMessagesController().addUserToChat(chatId, user, 0, null, ChatUsersActivity.this, null); + if (peerId > 0) { + TLRPC.User user = getMessagesController().getUser(peerId); + getMessagesController().addUserToChat(chatId, user, 0, null, ChatUsersActivity.this, null); + } } } else if (i == 1) { TLRPC.TL_channels_editBanned req = new TLRPC.TL_channels_editBanned(); - req.user_id = getMessagesController().getInputUser(userId); + req.participant = getMessagesController().getInputPeer(peerId); req.channel = getMessagesController().getInputChannel(chatId); req.banned_rights = new TLRPC.TL_chatBannedRights(); getConnectionsManager().sendRequest(req, (response, error) -> { @@ -1896,7 +1927,16 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } else { if (i == 0) { - getMessagesController().deleteUserFromChat(chatId, getMessagesController().getUser(userId), null); + TLRPC.User user; + TLRPC.Chat chat; + if (peerId > 0) { + user = getMessagesController().getUser(peerId); + chat = null; + } else { + user = null; + chat = getMessagesController().getChat(-peerId); + } + getMessagesController().deleteParticipantFromChat(chatId, user, chat, null, false, false); } } }); @@ -2244,10 +2284,11 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente getMessagesController().processLoadedAdminsResponse(chatId, (TLRPC.TL_channels_channelParticipants) response); } getMessagesController().putUsers(res.users, false); + getMessagesController().putChats(res.chats, false); int selfId = getUserConfig().getClientUserId(); if (selectType != 0) { for (int a = 0; a < res.participants.size(); a++) { - if (res.participants.get(a).user_id == selfId) { + if (MessageObject.getPeerId(res.participants.get(a).peer) == selfId) { res.participants.remove(a); break; } @@ -2276,7 +2317,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente objects.addAll(res.participants); for (int a = 0, size = res.participants.size(); a < size; a++) { TLRPC.ChannelParticipant participant = res.participants.get(a); - map.put(participant.user_id, participant); + map.put(MessageObject.getPeerId(participant.peer), participant); } if (type == TYPE_USERS) { for (int a = 0, N = participants.size(); a < N; a++) { @@ -2288,17 +2329,18 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente continue; } TLRPC.ChannelParticipant participant = (TLRPC.ChannelParticipant) object; + int peerId = MessageObject.getPeerId(participant.peer); boolean remove = false; - if (contactsMap.get(participant.user_id) != null || botsMap.get(participant.user_id) != null) { + if (contactsMap.get(peerId) != null || botsMap.get(peerId) != null) { remove = true; - } else if (selectType == 1 && UserObject.isDeleted(getMessagesController().getUser(participant.user_id))) { + } else if (selectType == 1 && peerId > 0 && UserObject.isDeleted(getMessagesController().getUser(peerId))) { remove = true; - } else if (ignoredUsers != null && ignoredUsers.indexOfKey(participant.user_id) >= 0) { + } else if (ignoredUsers != null && ignoredUsers.indexOfKey(peerId) >= 0) { remove = true; } if (remove) { participants.remove(a); - participantsMap.remove(participant.user_id); + participantsMap.remove(peerId); a--; N--; } @@ -2339,23 +2381,33 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente Collections.sort(objects, (lhs, rhs) -> { TLRPC.ChannelParticipant p1 = (TLRPC.ChannelParticipant) lhs; TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) rhs; - TLRPC.User user1 = getMessagesController().getUser(p1.user_id); - TLRPC.User user2 = getMessagesController().getUser(p2.user_id); + int peer1 = MessageObject.getPeerId(p1.peer); + int peer2 = MessageObject.getPeerId(p2.peer); int status1 = 0; - int status2 = 0; - if (user1 != null && user1.status != null) { - if (user1.self) { - status1 = currentTime + 50000; - } else { - status1 = user1.status.expires; + if (peer1 > 0) { + TLRPC.User user1 = getMessagesController().getUser(MessageObject.getPeerId(p1.peer)); + if (user1 != null && user1.status != null) { + if (user1.self) { + status1 = currentTime + 50000; + } else { + status1 = user1.status.expires; + } } + } else { + status1 = -100; } - if (user2 != null && user2.status != null) { - if (user2.self) { - status2 = currentTime + 50000; - } else { - status2 = user2.status.expires; + int status2 = 0; + if (peer2 > 0) { + TLRPC.User user2 = getMessagesController().getUser(MessageObject.getPeerId(p2.peer)); + if (user2 != null && user2.status != null) { + if (user2.self) { + status2 = currentTime + 50000; + } else { + status2 = user2.status.expires; + } } + } else { + status2 = -100; } if (status1 > 0 && status2 > 0) { if (status1 > status2) { @@ -2433,7 +2485,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente private class SearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; - private ArrayList searchResult = new ArrayList<>(); + private ArrayList searchResult = new ArrayList<>(); private SparseArray searchResultMap = new SparseArray<>(); private ArrayList searchResultNames = new ArrayList<>(); private SearchAdapterHelper searchAdapterHelper; @@ -2506,28 +2558,43 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (search2 != null) { search[1] = search2; } - ArrayList resultArray = new ArrayList<>(); + ArrayList resultArray = new ArrayList<>(); SparseArray resultMap = new SparseArray<>(); ArrayList resultArrayNames = new ArrayList<>(); ArrayList resultArray2 = new ArrayList<>(); if (participantsCopy != null) { for (int a = 0, N = participantsCopy.size(); a < N; a++) { - int userId; + int peerId; TLObject o = participantsCopy.get(a); if (o instanceof TLRPC.ChatParticipant) { - userId = ((TLRPC.ChatParticipant) o).user_id; + peerId = ((TLRPC.ChatParticipant) o).user_id; } else if (o instanceof TLRPC.ChannelParticipant) { - userId = ((TLRPC.ChannelParticipant) o).user_id; + peerId = MessageObject.getPeerId(((TLRPC.ChannelParticipant) o).peer); } else { continue; } - TLRPC.User user = getMessagesController().getUser(userId); - if (user.id == getUserConfig().getClientUserId()) { - continue; + String name; + String username; + String firstName; + String lastName; + if (peerId > 0) { + TLRPC.User user = getMessagesController().getUser(peerId); + if (user.id == getUserConfig().getClientUserId()) { + continue; + } + name = UserObject.getUserName(user).toLowerCase(); + username = user.username; + firstName = user.first_name; + lastName = user.last_name; + } else { + TLRPC.Chat chat = getMessagesController().getChat(-peerId); + name = chat.title.toLowerCase(); + username = chat.username; + firstName = chat.title; + lastName = null; } - String name = UserObject.getUserName(user).toLowerCase(); String tName = LocaleController.getInstance().getTranslitString(name); if (name.equals(tName)) { tName = null; @@ -2537,15 +2604,15 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente for (String q : search) { if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) { found = 1; - } else if (user.username != null && user.username.startsWith(q)) { + } else if (username != null && username.startsWith(q)) { found = 2; } if (found != 0) { if (found == 1) { - resultArrayNames.add(AndroidUtilities.generateSearchName(user.first_name, user.last_name, q)); + resultArrayNames.add(AndroidUtilities.generateSearchName(firstName, lastName, q)); } else { - resultArrayNames.add(AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q)); + resultArrayNames.add(AndroidUtilities.generateSearchName("@" + username, null, "@" + q)); } resultArray2.add(o); break; @@ -2598,7 +2665,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente }); } - private void updateSearchResults(final ArrayList users, final SparseArray usersMap, final ArrayList names, final ArrayList participants) { + private void updateSearchResults(final ArrayList users, final SparseArray usersMap, final ArrayList names, final ArrayList participants) { AndroidUtilities.runOnUIThread(() -> { if (!searching) { return; @@ -2697,7 +2764,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (i == 0) { return null; } else { - return searchResult.get(i - 1); + return (TLObject) searchResult.get(i - 1); } } else { i -= count + 1; @@ -2747,18 +2814,27 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente switch (holder.getItemViewType()) { case 0: { TLObject object = getItem(position); - TLRPC.User user; + TLObject peerObject; + String un = null; if (object instanceof TLRPC.User) { - user = (TLRPC.User) object; + peerObject = object; } else if (object instanceof TLRPC.ChannelParticipant) { - user = getMessagesController().getUser(((TLRPC.ChannelParticipant) object).user_id); + int peerId = MessageObject.getPeerId(((TLRPC.ChannelParticipant) object).peer); + if (peerId > 0) { + TLRPC.User user = getMessagesController().getUser(peerId); + un = user.username; + peerObject = user; + } else { + TLRPC.Chat chat = getMessagesController().getChat(-peerId); + un = chat.username; + peerObject = chat; + } } else if (object instanceof TLRPC.ChatParticipant) { - user = getMessagesController().getUser(((TLRPC.ChatParticipant) object).user_id); + peerObject = getMessagesController().getUser(((TLRPC.ChatParticipant) object).user_id); } else { return; } - String un = user.username; CharSequence username = null; CharSequence name = null; @@ -2821,10 +2897,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } - if (nameSearch != null) { - String u = UserObject.getUserName(user); - name = new SpannableStringBuilder(u); - int idx = AndroidUtilities.indexOfIgnoreCase(u, nameSearch); + if (nameSearch != null && un != null) { + name = new SpannableStringBuilder(un); + int idx = AndroidUtilities.indexOfIgnoreCase(un, nameSearch); if (idx != -1) { ((SpannableStringBuilder) name).setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), idx, idx + nameSearch.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -2832,7 +2907,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente ManageChatUserCell userCell = (ManageChatUserCell) holder.itemView; userCell.setTag(position); - userCell.setData(user, name, username, false); + userCell.setData(peerObject, name, username, false); break; } @@ -3036,7 +3111,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente lastRow = botEndRow; } - int userId; + int peerId; int kickedBy; int promotedBy; TLRPC.TL_chatBannedRights bannedRights; @@ -3046,7 +3121,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente int joined; if (item instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant participant = (TLRPC.ChannelParticipant) item; - userId = participant.user_id; + peerId = MessageObject.getPeerId(participant.peer); kickedBy = participant.kicked_by; promotedBy = participant.promoted_by; bannedRights = participant.banned_rights; @@ -3056,7 +3131,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente admin = participant instanceof TLRPC.TL_channelParticipantAdmin; } else if (item instanceof TLRPC.ChatParticipant) { TLRPC.ChatParticipant participant = (TLRPC.ChatParticipant) item; - userId = participant.user_id; + peerId = participant.user_id; joined = participant.date; kickedBy = 0; promotedBy = 0; @@ -3067,10 +3142,15 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else { return; } - TLRPC.User user = getMessagesController().getUser(userId); - if (user != null) { + TLObject object; + if (peerId > 0) { + object = getMessagesController().getUser(peerId); + } else { + object = getMessagesController().getChat(-peerId); + } + if (object != null) { if (type == TYPE_KICKED) { - userCell.setData(user, null, formatUserPermissions(bannedRights), position != lastRow - 1); + userCell.setData(object, null, formatUserPermissions(bannedRights), position != lastRow - 1); } else if (type == TYPE_BANNED) { String role = null; if (banned) { @@ -3079,7 +3159,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente role = LocaleController.formatString("UserRemovedBy", R.string.UserRemovedBy, UserObject.getUserName(user1)); } } - userCell.setData(user, null, role, position != lastRow - 1); + userCell.setData(object, null, role, position != lastRow - 1); } else if (type == TYPE_ADMIN) { String role = null; if (creator) { @@ -3087,14 +3167,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else if (admin) { TLRPC.User user1 = getMessagesController().getUser(promotedBy); if (user1 != null) { - if (user1.id == user.id) { + if (user1.id == peerId) { role = LocaleController.getString("ChannelAdministrator", R.string.ChannelAdministrator); } else { role = LocaleController.formatString("EditAdminPromotedBy", R.string.EditAdminPromotedBy, UserObject.getUserName(user1)); } } } - userCell.setData(user, null, role, position != lastRow - 1); + userCell.setData(object, null, role, position != lastRow - 1); } else if (type == TYPE_USERS) { CharSequence status; if (showJoined && joined != 0) { @@ -3102,7 +3182,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else { status = null; } - userCell.setData(user, null, status, position != lastRow - 1); + userCell.setData(object, null, status, position != lastRow - 1); } } break; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java index 9746851f6..5acbb3542 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java @@ -24,6 +24,7 @@ import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; @@ -314,7 +315,7 @@ public class AdminLogFilterAlert extends BottomSheet { ((CheckBoxCell) holder.itemView).setChecked(false, true); } for (int a = 0; a < currentAdmins.size(); a++) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(currentAdmins.get(a).user_id); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(MessageObject.getPeerId(currentAdmins.get(a).peer)); selectedAdmins.put(user.id, user); } } @@ -465,7 +466,7 @@ public class AdminLogFilterAlert extends BottomSheet { } case 2: { CheckBoxUserCell userCell = (CheckBoxUserCell) holder.itemView; - int userId = currentAdmins.get(position - allAdminsRow - 1).user_id; + int userId = MessageObject.getPeerId(currentAdmins.get(position - allAdminsRow - 1).peer); userCell.setChecked(selectedAdmins == null || selectedAdmins.indexOfKey(userId) >= 0, false); break; } @@ -510,7 +511,7 @@ public class AdminLogFilterAlert extends BottomSheet { } case 2: { CheckBoxUserCell userCell = (CheckBoxUserCell) holder.itemView; - int userId = currentAdmins.get(position - allAdminsRow - 1).user_id; + int userId = MessageObject.getPeerId(currentAdmins.get(position - allAdminsRow - 1).peer); userCell.setUser(MessagesController.getInstance(currentAccount).getUser(userId), selectedAdmins == null || selectedAdmins.indexOfKey(userId) >= 0, position != getItemCount() - 1); break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java index a7ed5d8c4..a573767a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -673,7 +673,7 @@ public class AlertsCreator { if (ChatObject.isNotInChat(currentChat)) { accountInstance.getMessagesController().deleteDialog(dialog_id, 0); } else { - accountInstance.getMessagesController().deleteUserFromChat((int) -dialog_id, accountInstance.getMessagesController().getUser(accountInstance.getUserConfig().getClientUserId()), null); + accountInstance.getMessagesController().deleteParticipantFromChat((int) -dialog_id, accountInstance.getMessagesController().getUser(accountInstance.getUserConfig().getClientUserId()), null); } } else { accountInstance.getMessagesController().deleteDialog(dialog_id, 0); @@ -3673,7 +3673,7 @@ public class AlertsCreator { TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); req.channel = MessagesController.getInputChannel(chat); - req.user_id = MessagesController.getInstance(currentAccount).getInputUser(actionUser); + req.participant = MessagesController.getInputPeer(actionUser); int requestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { try { progressDialog[0].dismiss(); @@ -3866,7 +3866,7 @@ public class AlertsCreator { } if (userFinal != null) { if (checks[0]) { - MessagesController.getInstance(currentAccount).deleteUserFromChat(chat.id, userFinal, chatInfo); + MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat.id, userFinal, chatInfo); } if (checks[1]) { TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index 8df253c00..cd197aabb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -135,6 +135,11 @@ public class BackupImageView extends View { invalidate(); } + public void setRoundRadius(int tl, int tr, int bl, int br) { + imageReceiver.setRoundRadius(tl, tr, bl ,br); + invalidate(); + } + public int[] getRoundRadius() { return imageReceiver.getRoundRadius(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java index b9ea93597..a18de5f14 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -139,7 +139,7 @@ public final class Bulletin { } public Bulletin show() { - if (!showing) { + if (!showing && containerLayout != null) { showing = true; if (layout.getParent() != parentLayout) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularViewPager.java index 55b9c5faa..1a45e5663 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularViewPager.java @@ -69,7 +69,9 @@ public class CircularViewPager extends ViewPager { public void setAdapter(Adapter adapter) { this.adapter = adapter; super.setAdapter(adapter); - setCurrentItem(adapter.getExtraCount(), false); + if (adapter != null) { + setCurrentItem(adapter.getExtraCount(), false); + } } public static abstract class Adapter extends PagerAdapter { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java index d421e92a6..8dccba721 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java @@ -1683,7 +1683,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent ((LayoutParams) getLayoutParams()).topMargin = -AndroidUtilities.dp(getStyleHeight()); } final int currentAccount = account; - animationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(animationIndex, null); + animationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(animationIndex, new int[]{NotificationCenter.messagesDidLoad}); animatorSet.playTogether(ObjectAnimator.ofFloat(this, "topPadding", AndroidUtilities.dp2(getStyleHeight()))); animatorSet.setDuration(220); animatorSet.setInterpolator(CubicBezierInterpolator.DEFAULT); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupVoipInviteAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupVoipInviteAlert.java index 1cb6b70ac..e9e4cf4ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupVoipInviteAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupVoipInviteAlert.java @@ -23,6 +23,7 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; @@ -308,9 +309,10 @@ public class GroupVoipInviteAlert extends UsersAlertBase { if (error == null) { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); int selfId = UserConfig.getInstance(currentAccount).getClientUserId(); for (int a = 0; a < res.participants.size(); a++) { - if (res.participants.get(a).user_id == selfId) { + if (MessageObject.getPeerId(res.participants.get(a).peer) == selfId) { res.participants.remove(a); break; } @@ -329,23 +331,24 @@ public class GroupVoipInviteAlert extends UsersAlertBase { objects.addAll(res.participants); for (int a = 0, size = res.participants.size(); a < size; a++) { TLRPC.ChannelParticipant participant = res.participants.get(a); - map.put(participant.user_id, participant); + map.put(MessageObject.getPeerId(participant.peer), participant); } for (int a = 0, N = participants.size(); a < N; a++) { TLRPC.ChannelParticipant participant = (TLRPC.ChannelParticipant) participants.get(a); + int peerId = MessageObject.getPeerId(participant.peer); boolean remove = false; - if (contactsMap.get(participant.user_id) != null) { + if (contactsMap.get(peerId) != null) { remove = true; - } else if (ignoredUsers != null && ignoredUsers.indexOfKey(participant.user_id) >= 0) { + } else if (ignoredUsers != null && ignoredUsers.indexOfKey(peerId) >= 0) { remove = true; } - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(participant.user_id); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(peerId); if (user != null && user.bot) { remove = true; } if (remove) { participants.remove(a); - participantsMap.remove(participant.user_id); + participantsMap.remove(peerId); a--; N--; } @@ -356,8 +359,8 @@ public class GroupVoipInviteAlert extends UsersAlertBase { Collections.sort(objects, (lhs, rhs) -> { TLRPC.ChannelParticipant p1 = (TLRPC.ChannelParticipant) lhs; TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) rhs; - TLRPC.User user1 = MessagesController.getInstance(currentAccount).getUser(p1.user_id); - TLRPC.User user2 = MessagesController.getInstance(currentAccount).getUser(p2.user_id); + TLRPC.User user1 = MessagesController.getInstance(currentAccount).getUser(MessageObject.getPeerId(p1.peer)); + TLRPC.User user2 = MessagesController.getInstance(currentAccount).getUser(MessageObject.getPeerId(p2.peer)); int status1 = 0; int status2 = 0; if (user1 != null && user1.status != null) { @@ -533,7 +536,7 @@ public class GroupVoipInviteAlert extends UsersAlertBase { if (o instanceof TLRPC.ChatParticipant) { userId = ((TLRPC.ChatParticipant) o).user_id; } else if (o instanceof TLRPC.ChannelParticipant) { - userId = ((TLRPC.ChannelParticipant) o).user_id; + userId = MessageObject.getPeerId(((TLRPC.ChannelParticipant) o).peer); } else { continue; } @@ -682,7 +685,7 @@ public class GroupVoipInviteAlert extends UsersAlertBase { if (object instanceof TLRPC.User) { user = (TLRPC.User) object; } else if (object instanceof TLRPC.ChannelParticipant) { - user = MessagesController.getInstance(currentAccount).getUser(((TLRPC.ChannelParticipant) object).user_id); + user = MessagesController.getInstance(currentAccount).getUser(MessageObject.getPeerId(((TLRPC.ChannelParticipant) object).peer)); } else if (object instanceof TLRPC.ChatParticipant) { user = MessagesController.getInstance(currentAccount).getUser(((TLRPC.ChatParticipant) object).user_id); } else { @@ -876,7 +879,7 @@ public class GroupVoipInviteAlert extends UsersAlertBase { userId = user.id; } else if (item instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant participant = (TLRPC.ChannelParticipant) item; - userId = participant.user_id; + userId = MessageObject.getPeerId(participant.peer); } else { TLRPC.ChatParticipant participant = (TLRPC.ChatParticipant) item; userId = participant.user_id; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java index 502aa463b..31eb257ca 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java @@ -578,25 +578,27 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega } private void startCrop(String path, Uri uri) { - try { - LaunchActivity activity = (LaunchActivity) parentFragment.getParentActivity(); - if (activity == null) { - return; + AndroidUtilities.runOnUIThread(() -> { + try { + LaunchActivity activity = (LaunchActivity) parentFragment.getParentActivity(); + if (activity == null) { + return; + } + Bundle args = new Bundle(); + if (path != null) { + args.putString("photoPath", path); + } else if (uri != null) { + args.putParcelable("photoUri", uri); + } + PhotoCropActivity photoCropActivity = new PhotoCropActivity(args); + photoCropActivity.setDelegate(this); + activity.presentFragment(photoCropActivity); + } catch (Exception e) { + FileLog.e(e); + Bitmap bitmap = ImageLoader.loadBitmap(path, uri, 800, 800, true); + processBitmap(bitmap, null); } - Bundle args = new Bundle(); - if (path != null) { - args.putString("photoPath", path); - } else if (uri != null) { - args.putParcelable("photoUri", uri); - } - PhotoCropActivity photoCropActivity = new PhotoCropActivity(args); - photoCropActivity.setDelegate(this); - activity.presentFragment(photoCropActivity); - } catch (Exception e) { - FileLog.e(e); - Bitmap bitmap = ImageLoader.loadBitmap(path, uri, 800, 800, true); - processBitmap(bitmap, null); - } + }); } public void openPhotoForEdit(String path, String thumb, int orientation, boolean isVideo) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java index 182226f53..980aa2443 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java @@ -158,7 +158,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica position--; if (position >= 0 && position < localCount) { - object = searchAdapter.searchResult.get(position); + object = (TLObject) searchAdapter.searchResult.get(position); } else if (position >= localCount && position < localServerCount + localCount) { object = searchAdapter.searchAdapterHelper.getLocalServerSearch().get(position - localCount); } else if (position > localCount + localServerCount && position <= globalCount + localCount + localServerCount) { @@ -684,7 +684,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica private class SearchAdapter extends RecyclerListView.SelectionAdapter { - private ArrayList searchResult = new ArrayList<>(); + private ArrayList searchResult = new ArrayList<>(); private ArrayList searchResultNames = new ArrayList<>(); private final SearchAdapterHelper searchAdapterHelper; private int currentItemsCount; @@ -760,7 +760,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica position--; if (position >= 0 && position < localCount) { - object = searchResult.get(position); + object = (TLObject) searchResult.get(position); } else if (position >= localCount && position < localServerCount + localCount) { object = searchAdapterHelper.getLocalServerSearch().get(position - localCount); } else if (position > localCount + localServerCount && position <= globalCount + localCount + localServerCount) { @@ -873,7 +873,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica return count; } - private void updateSearchResults(final ArrayList users, final ArrayList names) { + private void updateSearchResults(final ArrayList users, final ArrayList names) { AndroidUtilities.runOnUIThread(() -> { searchRunnable = null; searchResult = users; @@ -922,7 +922,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica search[1] = search2; } - ArrayList resultArray = new ArrayList<>(); + ArrayList resultArray = new ArrayList<>(); ArrayList resultArrayNames = new ArrayList<>(); for (int a = 0; a < contacts.size(); a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java index 82a47416c..4022e1699 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java @@ -81,8 +81,12 @@ public class JoinCallAlert extends BottomSheet { private static long lastCacheDid; private static int lastCachedAccount; - public static void processDeletedChat(long did) { - if (cachedChats == null || did > 0) { + public static void resetCache() { + cachedChats = null; + } + + public static void processDeletedChat(int account, long did) { + if (lastCachedAccount != account || cachedChats == null || did > 0) { return; } for (int a = 0, N = cachedChats.size(); a < N; a++) { @@ -441,8 +445,10 @@ public class JoinCallAlert extends BottomSheet { doneButton.setBackground(null); doneButton.background.setOnClickListener(v -> { TLRPC.InputPeer peer = MessagesController.getInstance(currentAccount).getInputPeer(MessageObject.getPeerId(selectedPeer)); - if (selectedPeer != currentPeer && currentType == TYPE_DISPLAY) { - delegate.didSelectChat(peer, chats.size() > 1); + if (currentType == TYPE_DISPLAY) { + if (selectedPeer != currentPeer) { + delegate.didSelectChat(peer, chats.size() > 1); + } } else { selectAfterDismiss = peer; } @@ -459,7 +465,7 @@ public class JoinCallAlert extends BottomSheet { doneButton.setText(LocaleController.formatString("VoipGroupContinueAs", R.string.VoipGroupContinueAs, UserObject.getFirstName(user)), animated); } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-did); - doneButton.setText(LocaleController.formatString("VoipGroupContinueAs", R.string.VoipGroupContinueAs, chat.title), animated); + doneButton.setText(LocaleController.formatString("VoipGroupContinueAs", R.string.VoipGroupContinueAs, chat != null ? chat.title : ""), animated); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java index c9003660e..83531a329 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java @@ -623,13 +623,21 @@ public class PipVideoView { @Keep public void setX(int value) { windowLayoutParams.x = value; - windowManager.updateViewLayout(windowView, windowLayoutParams); + try { + windowManager.updateViewLayout(windowView, windowLayoutParams); + } catch (Exception ignore) { + + } } @Keep public void setY(int value) { windowLayoutParams.y = value; - windowManager.updateViewLayout(windowView, windowLayoutParams); + try { + windowManager.updateViewLayout(windowView, windowLayoutParams); + } catch (Exception ignore) { + + } } @Keep diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java index cfb750afe..0686f3e09 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java @@ -4,12 +4,16 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.PointF; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.text.TextUtils; +import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; import android.view.View; @@ -24,6 +28,7 @@ import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ProfileActivity; @@ -35,22 +40,28 @@ import androidx.recyclerview.widget.RecyclerView; public class ProfileGalleryView extends CircularViewPager implements NotificationCenter.NotificationCenterDelegate { - private final Callback callback; private final PointF downPoint = new PointF(); private final int touchSlop; + private final ActionBar parentActionBar; private boolean isScrollingListView = true; private boolean isSwipingViewPager = true; private final RecyclerListView parentListView; - private final ViewPagerAdapter adapter; + private ViewPagerAdapter adapter; private final int parentClassGuid; - private final long dialogId; + private long dialogId; private TLRPC.ChatFull chatInfo; + private final Callback callback; private boolean scrolledByUser; private boolean isDownReleased; + private final boolean isProfileFragment; private int currentAccount = UserConfig.selectedAccount; + Path path = new Path(); + RectF rect = new RectF(); + float[] radii = new float[8]; + private ImageLocation prevImageLocation; private ArrayList videoFileNames = new ArrayList<>(); private ArrayList thumbsFileNames = new ArrayList<>(); @@ -77,16 +88,93 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio void onVideoSet(); } + private int roundTopRadius; + private int roundBottomRadius; + + public ProfileGalleryView(Context context, ActionBar parentActionBar, RecyclerListView parentListView, Callback callback) { + super(context); + setOffscreenPageLimit(2); + + this.isProfileFragment = false; + this.parentListView = parentListView; + this.parentClassGuid = ConnectionsManager.generateClassGuid(); + this.parentActionBar = parentActionBar; + this.touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + this.callback = callback; + + addOnPageChangeListener(new OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if (positionOffsetPixels == 0) { + position = adapter.getRealPosition(position); + BackupImageView currentView = getCurrentItemView(); + int count = getChildCount(); + for (int a = 0; a < count; a++) { + View child = getChildAt(a); + if (!(child instanceof BackupImageView)) { + continue; + } + int p = adapter.getRealPosition(adapter.imageViews.indexOf(child)); + BackupImageView imageView = (BackupImageView) child; + ImageReceiver imageReceiver = imageView.getImageReceiver(); + boolean currentAllow = imageReceiver.getAllowStartAnimation(); + if (p == position) { + if (!currentAllow) { + imageReceiver.setAllowStartAnimation(true); + imageReceiver.startAnimation(); + } + ImageLocation location = videoLocations.get(p); + if (location != null) { + FileLoader.getInstance(currentAccount).setForceStreamLoadingFile(location.location, "mp4"); + } + } else { + if (currentAllow) { + AnimatedFileDrawable fileDrawable = imageReceiver.getAnimation(); + if (fileDrawable != null) { + ImageLocation location = videoLocations.get(p); + if (location != null) { + fileDrawable.seekTo(location.videoSeekTo, false, true); + } + } + imageReceiver.setAllowStartAnimation(false); + imageReceiver.stopAnimation(); + } + } + } + } + } + + @Override + public void onPageSelected(int position) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + setAdapter(adapter = new ViewPagerAdapter(getContext(), null, parentActionBar)); + + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogPhotosLoaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.FileLoadProgressChanged); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.reloadDialogPhotos); + } + public ProfileGalleryView(Context context, long dialogId, ActionBar parentActionBar, RecyclerListView parentListView, ProfileActivity.AvatarImageView parentAvatarImageView, int parentClassGuid, Callback callback) { super(context); setVisibility(View.GONE); setOverScrollMode(View.OVER_SCROLL_NEVER); setOffscreenPageLimit(2); + this.isProfileFragment = true; this.dialogId = dialogId; this.parentListView = parentListView; this.parentClassGuid = parentClassGuid; - setAdapter(adapter = new ViewPagerAdapter(context, parentAvatarImageView, parentActionBar)); + this.parentActionBar = parentActionBar; + setAdapter(adapter = new ViewPagerAdapter(getContext(), parentAvatarImageView, parentActionBar)); this.touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); this.callback = callback; @@ -150,6 +238,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio MessagesController.getInstance(currentAccount).loadDialogPhotos((int) dialogId, 80, 0, true, parentClassGuid); } + public void onDestroy() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogPhotosLoaded); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidLoad); @@ -172,7 +261,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } public void setAnimatedFileMaybe(AnimatedFileDrawable drawable) { - if (drawable == null) { + if (drawable == null || adapter == null) { return; } int count = getChildCount(); @@ -202,6 +291,9 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio @Override public boolean onTouchEvent(MotionEvent ev) { + if (adapter == null) { + return false; + } if (parentListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE && !isScrollingListView && isSwipingViewPager) { isSwipingViewPager = false; final MotionEvent cancelEvent = MotionEvent.obtain(ev); @@ -325,6 +417,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio photos.add(null); imagesLocationsSizes.add(-1); getAdapter().notifyDataSetChanged(); + resetCurrentItem(); return true; } @@ -537,7 +630,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio if (id == NotificationCenter.dialogPhotosLoaded) { int guid = (Integer) args[3]; int did = (Integer) args[0]; - if (did == dialogId && parentClassGuid == guid) { + if (did == dialogId && parentClassGuid == guid && adapter != null) { boolean fromCache = (Boolean) args[2]; ArrayList arrayList = (ArrayList) args[4]; thumbsFileNames.clear(); @@ -629,9 +722,16 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } loadNeighboringThumbs(); getAdapter().notifyDataSetChanged(); - if (!scrolledByUser) { + if (isProfileFragment) { + if (!scrolledByUser) { + resetCurrentItem(); + } + } else { resetCurrentItem(); + getAdapter().notifyDataSetChanged(); } + + if (fromCache) { MessagesController.getInstance(currentAccount).loadDialogPhotos(did, 80, 0, false, parentClassGuid); } @@ -685,7 +785,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio private final Context context; private final Paint placeholderPaint; - private final ProfileActivity.AvatarImageView parentAvatarImageView; + private BackupImageView parentAvatarImageView; private final ActionBar parentActionBar; public ViewPagerAdapter(Context context, ProfileActivity.AvatarImageView parentAvatarImageView, ActionBar parentActionBar) { @@ -732,7 +832,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio final int realPosition = getRealPosition(position); boolean needProgress = false; if (realPosition == 0) { - Drawable drawable = parentAvatarImageView.getImageReceiver().getDrawable(); + Drawable drawable = parentAvatarImageView == null ? null : parentAvatarImageView.getImageReceiver().getDrawable(); if (drawable instanceof AnimatedFileDrawable && ((AnimatedFileDrawable) drawable).hasBitmap()) { AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable; setImageDrawable(drawable); @@ -743,12 +843,13 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio isVideo = videoLocation != null; needProgress = true; String filter; - if (videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION) { + if (isProfileFragment && videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION) { filter = ImageLoader.AUTOPLAY_FILTER; } else { filter = null; } - setImageMedia(videoLocations.get(realPosition), filter, imagesLocations.get(realPosition), null, parentAvatarImageView.getImageReceiver().getBitmap(), imagesLocationsSizes.get(realPosition), 1, "avatar_" + dialogId); + Bitmap thumb = parentAvatarImageView == null ? null : parentAvatarImageView.getImageReceiver().getBitmap(); + setImageMedia(videoLocations.get(realPosition), filter, imagesLocations.get(realPosition), null, thumb, imagesLocationsSizes.get(realPosition), 1, "avatar_" + dialogId); } } else { final ImageLocation videoLocation = videoLocations.get(realPosition); @@ -756,7 +857,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio needProgress = true; ImageLocation location = thumbsLocations.get(realPosition); String filter = location.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null; - setImageMedia(videoLocation, null, imagesLocations.get(realPosition), null, thumbsLocations.get(realPosition), filter, null, imagesLocationsSizes.get(realPosition), 1, "avatar_" + dialogId); + setImageMedia(videoLocation, null, imagesLocations.get(realPosition), null, thumbsLocations.get(realPosition), filter, null, imagesLocationsSizes.get(realPosition), 1, location); } if (needProgress) { radialProgress = radialProgresses.get(realPosition); @@ -834,9 +935,22 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } postInvalidateOnAnimation(); } - canvas.drawRect(0, 0, getWidth(), getHeight(), placeholderPaint); + if (roundTopRadius == 0 && roundBottomRadius == 0) { + canvas.drawRect(0, 0, getWidth(), getHeight(), placeholderPaint); + } else if (roundTopRadius == roundBottomRadius) { + rect.set(0, 0, getWidth(), getHeight()); + canvas.drawRoundRect(rect, roundTopRadius, roundTopRadius, placeholderPaint); + } else { + path.reset(); + rect.set(0, 0, getWidth(), getHeight()); + for (int i = 0; i < 4; i++) { + radii[i] = roundTopRadius; + radii[4 + i] = roundBottomRadius; + } + path.addRoundRect(rect, radii, Path.Direction.CW); + canvas.drawPath(path, placeholderPaint); + } } - super.onDraw(canvas); if (radialProgress != null && radialProgress.getOverrideAlpha() > 0f) { @@ -851,6 +965,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio container.addView(item.imageView); } + item.imageView.setRoundRadius(roundTopRadius, roundTopRadius, roundBottomRadius, roundBottomRadius); + return item; } @@ -863,6 +979,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio ((AnimatedFileDrawable) drawable).removeSecondParentView(imageView); } } + imageView.setRoundRadius(0); container.removeView(imageView); } @@ -874,7 +991,13 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio @Override public void notifyDataSetChanged() { + for (int i = 0; i < imageViews.size(); i++) { + if (imageViews.get(i) != null) { + imageViews.get(i).getImageReceiver().cancelLoadImage(); + } + } objects.clear(); + imageViews.clear(); for (int a = 0, N = imagesLocations.size() + getExtraCount() * 2; a < N; a++) { objects.add(new Item()); imageViews.add(null); @@ -892,4 +1015,44 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } } } + + public void setData(long dialogId) { + if (this.dialogId == dialogId) { + resetCurrentItem(); + return; + } + reset(); + this.dialogId = dialogId; + MessagesController.getInstance(currentAccount).loadDialogPhotos((int) dialogId, 80, 0, true, parentClassGuid); + } + + private void reset() { + videoFileNames.clear(); + thumbsFileNames.clear(); + photos.clear(); + videoLocations.clear(); + imagesLocations.clear(); + thumbsLocations.clear(); + imagesLocationsSizes.clear(); + adapter.notifyDataSetChanged(); + resetCurrentItem(); + } + + public void setRoundRadius(int topRadius, int bottomRadius) { + this.roundTopRadius = topRadius; + this.roundBottomRadius = bottomRadius; + if (adapter != null) { + for (int i = 0; i < adapter.objects.size(); i++) { + if (adapter.objects.get(i).imageView != null) { + adapter.objects.get(i).imageView.setRoundRadius(roundTopRadius, roundTopRadius, roundBottomRadius, roundBottomRadius); + } + } + } + } + + public void setParentAvatarImage(BackupImageView parentImageView) { + if (adapter != null) { + adapter.parentAvatarImageView = parentImageView; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index ad632a412..2baca1604 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -28,6 +28,8 @@ import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Editable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; @@ -59,6 +61,7 @@ import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; @@ -79,6 +82,7 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Adapters.SearchAdapterHelper; import org.telegram.ui.Cells.ShareDialogCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.DialogsActivity; @@ -1629,25 +1633,48 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } } + public static class DialogSearchResult { + public TLRPC.Dialog dialog = new TLRPC.TL_dialog(); + public TLObject object; + public int date; + public CharSequence name; + } + public class ShareSearchAdapter extends RecyclerListView.SelectionAdapter { private Context context; - private ArrayList searchResult = new ArrayList<>(); + private ArrayList searchResult = new ArrayList<>(); + private SearchAdapterHelper searchAdapterHelper; private Runnable searchRunnable; + private Runnable searchRunnable2; private String lastSearchText; private int reqId; private int lastReqId; private int lastSearchId; - private class DialogSearchResult { - public TLRPC.Dialog dialog = new TLRPC.TL_dialog(); - public TLObject object; - public int date; - public CharSequence name; - } + private int waitingResponseCount; + private int lastGlobalSearchId; + private int lastLocalSearchId; public ShareSearchAdapter(Context context) { this.context = context; + searchAdapterHelper = new SearchAdapterHelper(false); + searchAdapterHelper.setDelegate(new SearchAdapterHelper.SearchAdapterHelperDelegate() { + @Override + public void onDataSetChanged(int searchId) { + waitingResponseCount--; + lastGlobalSearchId = searchId; + if (lastLocalSearchId != searchId) { + searchResult.clear(); + } + notifyDataSetChanged(); + } + + @Override + public boolean canApplySearchResults(int searchId) { + return searchId == lastSearchId; + } + }); } private void searchDialogsInternal(final String query, final int searchId) { @@ -1772,7 +1799,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi cursor.dispose(); } - ArrayList searchResults = new ArrayList<>(resultCount); + ArrayList searchResults = new ArrayList<>(resultCount); for (int a = 0; a < dialogsResult.size(); a++) { DialogSearchResult dialogSearchResult = dialogsResult.valueAt(a); if (dialogSearchResult.object != null && dialogSearchResult.name != null) { @@ -1828,9 +1855,11 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi cursor.dispose(); Collections.sort(searchResults, (lhs, rhs) -> { - if (lhs.date < rhs.date) { + DialogSearchResult res1 = (DialogSearchResult) lhs; + DialogSearchResult res2 = (DialogSearchResult) rhs; + if (res1.date < res2.date) { return 1; - } else if (lhs.date > rhs.date) { + } else if (res1.date > res2.date) { return -1; } return 0; @@ -1843,18 +1872,22 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi }); } - private void updateSearchResults(final ArrayList result, final int searchId) { + private void updateSearchResults(final ArrayList result, final int searchId) { AndroidUtilities.runOnUIThread(() -> { if (searchId != lastSearchId) { return; } + lastLocalSearchId = searchId; + if (lastGlobalSearchId != searchId) { + searchAdapterHelper.clear(); + } if (gridView.getAdapter() != searchAdapter) { topBeforeSwitch = getCurrentTop(); gridView.setAdapter(searchAdapter); searchAdapter.notifyDataSetChanged(); } for (int a = 0; a < result.size(); a++) { - DialogSearchResult obj = result.get(a); + DialogSearchResult obj = (DialogSearchResult) result.get(a); if (obj.object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) obj.object; MessagesController.getInstance(currentAccount).putUser(user, true); @@ -1868,6 +1901,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi if (becomeEmpty) { topBeforeSwitch = getCurrentTop(); } + searchAdapterHelper.mergeResults(searchResult); searchResult = result; notifyDataSetChanged(); if (!isEmpty && !becomeEmpty && topBeforeSwitch > 0) { @@ -1887,21 +1921,37 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi Utilities.searchQueue.cancelRunnable(searchRunnable); searchRunnable = null; } + if (searchRunnable2 != null) { + AndroidUtilities.cancelRunOnUIThread(searchRunnable2); + searchRunnable2 = null; + } if (TextUtils.isEmpty(query)) { searchResult.clear(); + searchAdapterHelper.mergeResults(null); + searchAdapterHelper.queryServerSearch(null, true, true, true, true, false, 0, false, 0, 0); topBeforeSwitch = getCurrentTop(); lastSearchId = -1; notifyDataSetChanged(); } else { final int searchId = ++lastSearchId; - searchRunnable = () -> searchDialogsInternal(query, searchId); - Utilities.searchQueue.postRunnable(searchRunnable, 300); + Utilities.searchQueue.postRunnable(searchRunnable = () -> { + searchRunnable = null; + searchDialogsInternal(query, searchId); + AndroidUtilities.runOnUIThread(searchRunnable2 = () -> { + searchRunnable2 = null; + if (searchId != lastSearchId) { + return; + } + searchAdapterHelper.queryServerSearch(query, true, true, true, true, false, 0, false, 0, searchId); + }); + }, 300); } } @Override public int getItemCount() { int count = searchResult.size(); + count += searchAdapterHelper.getLocalServerSearch().size(); if (count != 0) { count++; } @@ -1910,10 +1960,26 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi public TLRPC.Dialog getItem(int position) { position--; - if (position < 0 || position >= searchResult.size()) { + if (position < 0) { return null; } - return searchResult.get(position).dialog; + if (position < searchResult.size()) { + return ((DialogSearchResult) searchResult.get(position)).dialog; + } else { + position -= searchResult.size(); + } + ArrayList arrayList = searchAdapterHelper.getLocalServerSearch(); + if (position < arrayList.size()) { + TLObject object = arrayList.get(position); + TLRPC.Dialog dialog = new TLRPC.TL_dialog(); + if (object instanceof TLRPC.User) { + dialog.id = ((TLRPC.User) object).id; + } else { + dialog.id = -((TLRPC.Chat) object).id; + } + return dialog; + } + return null; } @Override @@ -1936,7 +2002,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi case 1: default: { view = new View(context); - view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(darkTheme ? 109 : 56))); + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(darkTheme && linkToCopy[1] != null ? 109 : 56))); break; } } @@ -1946,9 +2012,38 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder.getItemViewType() == 0) { + position--; ShareDialogCell cell = (ShareDialogCell) holder.itemView; - DialogSearchResult result = searchResult.get(position - 1); - cell.setDialog((int) result.dialog.id, selectedDialogs.indexOfKey(result.dialog.id) >= 0, result.name); + CharSequence name; + long id; + if (position < searchResult.size()) { + DialogSearchResult result = (DialogSearchResult) searchResult.get(position); + id = result.dialog.id; + name = result.name; + } else { + position -= searchResult.size(); + ArrayList arrayList = searchAdapterHelper.getLocalServerSearch(); + TLObject object = arrayList.get(position); + if (object instanceof TLRPC.User) { + TLRPC.User user = (TLRPC.User) object; + id = user.id; + name = ContactsController.formatName(user.first_name, user.last_name); + } else { + TLRPC.Chat chat = (TLRPC.Chat) object; + id = -chat.id; + name = chat.title; + } + String foundUserName = searchAdapterHelper.getLastFoundUsername(); + if (!TextUtils.isEmpty(foundUserName)) { + int index; + if (name != null && (index = AndroidUtilities.indexOfIgnoreCase(name.toString(), foundUserName)) != -1) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(name); + spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + foundUserName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + name = spannableStringBuilder; + } + } + } + cell.setDialog((int) id, selectedDialogs.indexOfKey(id) >= 0, name); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java index 0cac29eca..bea492f20 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -1090,7 +1090,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter TLObject object = groupUsersSearchAdapter.getItem(position); if (object instanceof TLRPC.ChannelParticipant) { TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) object; - user_id = channelParticipant.user_id; + user_id = MessageObject.getPeerId(channelParticipant.peer); } else if (object instanceof TLRPC.ChatParticipant) { TLRPC.ChatParticipant chatParticipant = (TLRPC.ChatParticipant) object; user_id = chatParticipant.user_id; @@ -4258,7 +4258,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; TLRPC.TL_chatChannelParticipant p = new TLRPC.TL_chatChannelParticipant(); p.channelParticipant = channelParticipant; - p.user_id = channelParticipant.user_id; + p.user_id = MessageObject.getPeerId(channelParticipant.peer); p.inviter_id = channelParticipant.inviter_id; p.date = channelParticipant.date; participant = p; @@ -4321,7 +4321,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (o instanceof TLRPC.ChatParticipant) { userId = ((TLRPC.ChatParticipant) o).user_id; } else if (o instanceof TLRPC.ChannelParticipant) { - userId = ((TLRPC.ChannelParticipant) o).user_id; + userId = MessageObject.getPeerId(((TLRPC.ChannelParticipant) o).peer); } else { continue; } @@ -4446,7 +4446,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter TLObject object = getItem(position); TLRPC.User user; if (object instanceof TLRPC.ChannelParticipant) { - user = profileActivity.getMessagesController().getUser(((TLRPC.ChannelParticipant) object).user_id); + user = profileActivity.getMessagesController().getUser(MessageObject.getPeerId(((TLRPC.ChannelParticipant) object).peer)); } else if (object instanceof TLRPC.ChatParticipant) { user = profileActivity.getMessagesController().getUser(((TLRPC.ChatParticipant) object).user_id); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java index b9bf09dff..845862e02 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java @@ -124,6 +124,8 @@ public class UndoView extends FrameLayout { public final static int ACTION_VOIP_RECORDING_STARTED = 39; public final static int ACTION_VOIP_RECORDING_FINISHED = 40; public final static int ACTION_VOIP_INVITE_LINK_SENT = 41; + public final static int ACTION_VOIP_SOUND_MUTED = 42; + public final static int ACTION_VOIP_SOUND_UNMUTED = 43; public final static int ACTION_IMPORT_NOT_MUTUAL = 45; public final static int ACTION_IMPORT_GROUP_NOT_ADMIN = 46; @@ -278,7 +280,7 @@ public class UndoView extends FrameLayout { currentAction == ACTION_CHAT_UNARCHIVED || currentAction == ACTION_VOIP_MUTED || currentAction == ACTION_VOIP_UNMUTED || currentAction == ACTION_VOIP_REMOVED || currentAction == ACTION_VOIP_LINK_COPIED || currentAction == ACTION_VOIP_INVITED || currentAction == ACTION_VOIP_MUTED_FOR_YOU || currentAction == ACTION_VOIP_UNMUTED_FOR_YOU || currentAction == ACTION_REPORT_SENT || currentAction == ACTION_VOIP_USER_CHANGED || currentAction == ACTION_VOIP_CAN_NOW_SPEAK || currentAction == ACTION_VOIP_RECORDING_STARTED || - currentAction == ACTION_VOIP_RECORDING_FINISHED; + currentAction == ACTION_VOIP_RECORDING_FINISHED || currentAction == ACTION_VOIP_SOUND_MUTED || currentAction == ACTION_VOIP_SOUND_UNMUTED; } private boolean hasSubInfo() { @@ -511,6 +513,16 @@ public class UndoView extends FrameLayout { subInfoText = null; icon = R.raw.voip_allow_talk; timeLeft = 3000; + } else if (action == ACTION_VOIP_SOUND_MUTED) { + infoText = AndroidUtilities.replaceTags(LocaleController.getString("VoipGroupSoundMuted", R.string.VoipGroupSoundMuted)); + subInfoText = null; + icon = R.raw.ic_mute; + timeLeft = 3000; + } else if (action == ACTION_VOIP_SOUND_UNMUTED) { + infoText = AndroidUtilities.replaceTags(LocaleController.getString("VoipGroupSoundUnmuted", R.string.VoipGroupSoundUnmuted)); + subInfoText = null; + icon = R.raw.ic_unmute; + timeLeft = 3000; } else if (currentAction == ACTION_VOIP_RECORDING_STARTED) { infoText = AndroidUtilities.replaceTags(LocaleController.getString("VoipGroupAudioRecordStarted", R.string.VoipGroupAudioRecordStarted)); subInfoText = null; @@ -528,7 +540,11 @@ public class UndoView extends FrameLayout { if (index1 >= 0 && index2 >= 0 && index1 != index2) { builder.replace(index2, index2 + 2, ""); builder.replace(index1, index1 + 2, ""); - builder.setSpan(new URLSpanNoUnderline("tg://openmessage?user_id=" + UserConfig.getInstance(currentAccount).getClientUserId()), index1, index2 - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + try { + builder.setSpan(new URLSpanNoUnderline("tg://openmessage?user_id=" + UserConfig.getInstance(currentAccount).getClientUserId()), index1, index2 - 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } catch (Exception e) { + FileLog.e(e); + } } infoText = builder; } else if (action == ACTION_VOIP_UNMUTED_FOR_YOU) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java index 4ac83c6eb..4b9539dd8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java @@ -6,12 +6,15 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; +import android.text.TextPaint; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; public class VideoForwardDrawable extends Drawable { private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private Path path1 = new Path(); private boolean leftSide; @@ -23,6 +26,9 @@ public class VideoForwardDrawable extends Drawable { private long lastAnimationTime; private VideoForwardDrawableDelegate delegate; + long time; + String timeStr; + public interface VideoForwardDrawableDelegate { void onAnimationEnd(); void invalidate(); @@ -30,6 +36,9 @@ public class VideoForwardDrawable extends Drawable { public VideoForwardDrawable() { paint.setColor(0xffffffff); + textPaint.setColor(0xffffffff); + textPaint.setTextSize(AndroidUtilities.dp(12)); + textPaint.setTextAlign(Paint.Align.CENTER); path1.reset(); for (int a = 0; a < playPath.length / 2; a++) { @@ -56,6 +65,10 @@ public class VideoForwardDrawable extends Drawable { if (leftSide == value && animationProgress >= 1.0f) { return; } + if (leftSide != value) { + time = 0; + timeStr = null; + } leftSide = value; startAnimation(); } @@ -67,6 +80,7 @@ public class VideoForwardDrawable extends Drawable { @Override public void setAlpha(int alpha) { paint.setAlpha(alpha); + textPaint.setAlpha(alpha); } @Override @@ -99,12 +113,18 @@ public class VideoForwardDrawable extends Drawable { canvas.clipRect(rect.left, rect.top, rect.right, rect.bottom); if (animationProgress <= 0.7f) { paint.setAlpha((int) (80 * Math.min(1.0f, animationProgress / 0.3f))); + textPaint.setAlpha((int) (255 * Math.min(1.0f, animationProgress / 0.3f))); } else { paint.setAlpha((int) (80 * (1.0f - (animationProgress - 0.7f) / 0.3f))); + textPaint.setAlpha((int) (255 * (1.0f - (animationProgress - 0.7f) / 0.3f))); } canvas.drawCircle(x + Math.max(rect.width(), rect.height()) / 4 * (leftSide ? -1 : 1), y + AndroidUtilities.dp(16), Math.max(rect.width(), rect.height()) / 2, paint); canvas.restore(); + if (timeStr != null) { + canvas.drawText(timeStr, x + getIntrinsicWidth() * (leftSide ? -1 : 1), y + getIntrinsicHeight() + AndroidUtilities.dp(15), textPaint); + } + canvas.save(); if (leftSide) { canvas.rotate(180, x, y + getIntrinsicHeight() / 2); @@ -152,6 +172,8 @@ public class VideoForwardDrawable extends Drawable { if (animationProgress >= 1.0f) { animationProgress = 0.0f; animating = false; + time = 0; + timeStr = null; if (delegate != null) { delegate.onAnimationEnd(); } @@ -184,4 +206,9 @@ public class VideoForwardDrawable extends Drawable { public int getMinimumHeight() { return AndroidUtilities.dp(32); } + + public void addTime(long time) { + this.time += time; + timeStr = LocaleController.formatPluralString("Seconds", (int) (this.time / 1000)); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java index 5d73a48cc..67fd64bb6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java @@ -57,6 +57,9 @@ public class VideoPlayerSeekBar { private int horizontalPadding; private int smallLineColor; + private int fromThumbX = 0; + private float animateThumbProgress = 1f; + public VideoPlayerSeekBar(View parent) { if (paint == null) { paint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -129,7 +132,11 @@ public class VideoPlayerSeekBar { this.smallLineColor = smallLineColor; } - public void setProgress(float progress) { + public void setProgress(float progress, boolean animated) { + if (animated) { + animateThumbProgress = 0; + fromThumbX = thumbX; + } thumbX = (int) Math.ceil((width - thumbWidth) * progress); if (thumbX < 0) { thumbX = 0; @@ -138,6 +145,10 @@ public class VideoPlayerSeekBar { } } + public void setProgress(float progress) { + setProgress(progress, false); + } + public void setBufferedProgress(float value) { bufferedProgress = value; } @@ -187,12 +198,23 @@ public class VideoPlayerSeekBar { this.horizontalPadding = horizontalPadding; } - public void draw(Canvas canvas) { + public void draw(Canvas canvas, View view) { final float radius = AndroidUtilities.lerp(thumbWidth / 2f, smallLineHeight / 2f, transitionProgress); rect.left = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f, 0, transitionProgress); rect.top = AndroidUtilities.lerp((height - lineHeight) / 2f, height - AndroidUtilities.dp(3) - smallLineHeight, transitionProgress); rect.bottom = AndroidUtilities.lerp((height + lineHeight) / 2f, height - AndroidUtilities.dp(3), transitionProgress); + float currentThumbX = thumbX; + if (animateThumbProgress != 1f) { + animateThumbProgress += 16 / 150f; + if (animateThumbProgress >= 1f) { + animateThumbProgress = 1f; + } else { + view.invalidate(); + float progressInterpolated = CubicBezierInterpolator.DEFAULT.getInterpolation(animateThumbProgress); + currentThumbX = fromThumbX * (1f - progressInterpolated) + thumbX * progressInterpolated; + } + } // background rect.right = horizontalPadding + AndroidUtilities.lerp(width - thumbWidth / 2f, parentView.getWidth() - horizontalPadding * 2f, transitionProgress); setPaintColor(selected ? backgroundSelectedColor : backgroundColor, 1f - transitionProgress); @@ -206,7 +228,7 @@ public class VideoPlayerSeekBar { } // progress - rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + (pressed ? draggingThumbX : thumbX), (parentView.getWidth() - horizontalPadding * 2f) * getProgress(), transitionProgress); + rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + (pressed ? draggingThumbX : currentThumbX), (parentView.getWidth() - horizontalPadding * 2f) * getProgress(), transitionProgress); if (transitionProgress > 0f && rect.width() > 0) { // progress stroke strokePaint.setAlpha((int) (transitionProgress * 255 * 0.2f)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java index 34cd52aa7..91616fd8a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java @@ -180,6 +180,10 @@ public class ViewPagerFixed extends FrameLayout { } else { viewsByType.remove(viewTypes[index]); } + if (v.getParent() != null) { + ViewGroup parent = (ViewGroup) v.getParent(); + parent.removeView(v); + } addView(v); viewPages[index] = v; adapter.bindView(viewPages[index], adapterPosition, viewTypes[index]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 838d91a78..895d8db23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -1867,7 +1867,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override public void setTranslationY(float translationY) { - if (translationY != getTranslationY()) { + if (translationY != getTranslationY() && fragmentView != null) { fragmentView.invalidate(); } super.setTranslationY(translationY); @@ -2676,7 +2676,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { - if (BuildVars.DEBUG_VERSION) { + if (BuildVars.DEBUG_PRIVATE_VERSION) { try { super.onLayoutChildren(recycler, state); } catch (IndexOutOfBoundsException e) { @@ -3357,7 +3357,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override public void setAlpha(float alpha) { super.setAlpha(alpha); - fragmentView.invalidate(); + if (fragmentView != null) { + fragmentView.invalidate(); + } } }; blurredView.setVisibility(View.GONE); @@ -3437,7 +3439,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } - private void updateFiltersView(boolean showMediaFilters, ArrayList users, ArrayList dates, boolean animated) { + private void updateFiltersView(boolean showMediaFilters, ArrayList users, ArrayList dates, boolean animated) { if (!searchIsShowed || onlySelect) { return; } @@ -3460,7 +3462,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. boolean hasUsersOrDates = (users != null && !users.isEmpty()) || (dates != null && !dates.isEmpty()); if (!hasMediaFilter && !hasUsersOrDates && showMediaFilters) { } else if (hasUsersOrDates) { - ArrayList finalUsers = (users != null && !users.isEmpty() && !hasUserFilter) ? users : null; + ArrayList finalUsers = (users != null && !users.isEmpty() && !hasUserFilter) ? users : null; ArrayList finalDates = (dates != null && !dates.isEmpty() && !hasDataFilter) ? dates : null; if (finalUsers != null || finalDates != null) { visible = true; @@ -4937,7 +4939,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. actionBar.getChildAt(i).setAlpha(1f - progressToActionMode); } } - fragmentView.invalidate(); + if (fragmentView != null) { + fragmentView.invalidate(); + } }); actionBarColorAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); actionBarColorAnimator.setDuration(200); @@ -5299,7 +5303,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. getMessagesController().deleteDialog(selectedDialog, 0, param); } else { TLRPC.User currentUser = getMessagesController().getUser(getUserConfig().getClientUserId()); - getMessagesController().deleteUserFromChat((int) -selectedDialog, currentUser, null, param, false); + getMessagesController().deleteParticipantFromChat((int) -selectedDialog, currentUser, null, null, param, false); } } else { getMessagesController().deleteDialog(selectedDialog, 0, param); @@ -5353,7 +5357,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. getMessagesController().deleteDialog(selectedDialog, 0, false); } else { TLRPC.User currentUser = getMessagesController().getUser(getUserConfig().getClientUserId()); - getMessagesController().deleteUserFromChat((int) -selectedDialog, currentUser, null); + getMessagesController().deleteParticipantFromChat((int) -selectedDialog, currentUser, null); } } else { getMessagesController().deleteDialog(selectedDialog, 0, false); @@ -5488,9 +5492,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. animate = true; } else if (currentDialogIndex >= 0 && selectedDialogIndex == currentDialogIndex) { animate = true; - AndroidUtilities.runOnUIThread(() -> { - setDialogsListFrozen(false); - }, 200); + AndroidUtilities.runOnUIThread(() -> setDialogsListFrozen(false), 200); } } if (!animate) { @@ -5781,7 +5783,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. actionBar.getChildAt(i).setAlpha(1f - progressToActionMode); } } - fragmentView.invalidate(); + if (fragmentView != null) { + fragmentView.invalidate(); + } }); actionBarColorAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); actionBarColorAnimator.setDuration(200); @@ -6212,7 +6216,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (ChatObject.isNotInChat(chat)) { getMessagesController().deleteDialog(dialogId, 0, revoke); } else { - getMessagesController().deleteUserFromChat((int) -dialogId, getMessagesController().getUser(getUserConfig().getClientUserId()), null, revoke, revoke); + getMessagesController().deleteParticipantFromChat((int) -dialogId, getMessagesController().getUser(getUserConfig().getClientUserId()), null, null, revoke, revoke); } } else { getMessagesController().deleteDialog(dialogId, 0, revoke); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java index 1405dee51..90f69a956 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java @@ -957,7 +957,7 @@ public class FilterUsersActivity extends BaseFragment implements NotificationCen public class GroupCreateAdapter extends RecyclerListView.FastScrollAdapter { private Context context; - private ArrayList searchResult = new ArrayList<>(); + private ArrayList searchResult = new ArrayList<>(); private ArrayList searchResultNames = new ArrayList<>(); private SearchAdapterHelper searchAdapterHelper; private Runnable searchRunnable; @@ -1269,7 +1269,7 @@ public class FilterUsersActivity extends BaseFragment implements NotificationCen search[1] = search2; } - ArrayList resultArray = new ArrayList<>(); + ArrayList resultArray = new ArrayList<>(); ArrayList resultArrayNames = new ArrayList<>(); for (int a = 0; a < contacts.size(); a++) { @@ -1333,7 +1333,7 @@ public class FilterUsersActivity extends BaseFragment implements NotificationCen } } - private void updateSearchResults(final ArrayList users, final ArrayList names) { + private void updateSearchResults(final ArrayList users, final ArrayList names) { AndroidUtilities.runOnUIThread(() -> { if (!searching) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index 143a943a9..9dd811e2b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -124,7 +124,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente private int searchIndex; - ArrayList localTipChats = new ArrayList<>(); + ArrayList localTipChats = new ArrayList<>(); ArrayList localTipDates = new ArrayList<>(); Runnable clearCurrentResultsRunnable = new Runnable() { @@ -510,7 +510,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente AndroidUtilities.runOnUIThread(searchRunnable = () -> { TLObject request; - ArrayList resultArray = null; + ArrayList resultArray = null; if (dialogId != 0) { final TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.q = query; @@ -574,7 +574,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente lastMessagesSearchString = query; lastSearchFilterQueryString = currentSearchFilterQueryString; - ArrayList finalResultArray = resultArray; + ArrayList finalResultArray = resultArray; final ArrayList dateData = new ArrayList<>(); FiltersView.fillTipDates(lastMessagesSearchString, dateData); ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { @@ -1623,7 +1623,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente } public interface Delegate { - void updateFiltersView(boolean showMediaFilters, ArrayList users, ArrayList dates); + void updateFiltersView(boolean showMediaFilters, ArrayList users, ArrayList dates); } public interface UiCallback { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index 214249dca..b3fea4957 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -8,6 +8,7 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; @@ -22,6 +23,7 @@ import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; @@ -41,6 +43,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.OvershootInterpolator; @@ -59,6 +62,7 @@ import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.ViewPager; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; @@ -101,11 +105,12 @@ import org.telegram.ui.Components.CheckBoxSquare; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.FillLastLinearLayoutManager; -import org.telegram.ui.Components.GroupVoipInviteAlert; import org.telegram.ui.Components.GroupCallPip; +import org.telegram.ui.Components.GroupVoipInviteAlert; import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.JoinCallAlert; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.ProfileGalleryView; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RadialProgressView; @@ -138,6 +143,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter public static GroupCallActivity groupCallInstance; public static boolean groupCallUiVisible; + private final ProfileGalleryView avatarsViewPager; private AccountInstance accountInstance; @@ -179,7 +185,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private boolean scrolling; - private TLRPC.TL_groupCallParticipant selfDummyParticipant; + private TLRPC.Peer selfPeer; private TLObject userSwitchObject; private Paint listViewBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -249,6 +255,13 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private boolean invalidateColors = true; private final int[] colorsTmp = new int[3]; + View blurredView; + + private float progressToAvatarPreview; + + private View scrimPopupLayout; + private boolean avatarsPreviewShowed; + private Runnable unmuteRunnable = () -> { if (VoIPService.getSharedInstance() == null) { return; @@ -278,6 +291,8 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter return object.getColorProgress(); } }; + private final FrameLayout avatarPreviewContainer; + private final AvatarPreviewPagerIndicator avatarPagerIndicator; private static class SmallRecordCallDrawable extends Drawable { @@ -628,8 +643,11 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter object = MessagesController.getInstance(currentAccount).getChat(-id); } if (currentParticipant.volume == 0) { - scrimPopupWindow.dismiss(); - scrimPopupWindow = null; + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + scrimPopupWindow = null; + } + dismissAvatarPreview(true); processSelectedOption(currentParticipant, id, ChatObject.canManageCalls(currentChat) ? 0 : 5); } else { VoIPService.getSharedInstance().editCallMember(object, false, currentParticipant.volume, null); @@ -656,10 +674,16 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } else { currentColor = 0xff4DA6DF; } - int color = AndroidUtilities.getOffsetColor(oldColor, prevColor, colorChangeProgress, 1.0f); - if (prevColor != 0 && prevColor != currentColor) { - colorChangeProgress = 0.0f; - oldColor = color; + int color; + if (prevColor == 0) { + color = currentColor; + colorChangeProgress = 1f; + } else { + color = AndroidUtilities.getOffsetColor(oldColor, prevColor, colorChangeProgress, 1.0f); + if (prevColor != currentColor) { + colorChangeProgress = 0.0f; + oldColor = color; + } } paint.setColor(color); long newTime = SystemClock.elapsedRealtime(); @@ -826,6 +850,31 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } } + private void prepareBlurBitmap() { + if (blurredView == null) { + return; + } + int w = (int) ((containerView.getMeasuredWidth() - backgroundPaddingLeft * 2) / 6.0f); + int h = (int) ((containerView.getMeasuredHeight() - AndroidUtilities.statusBarHeight) / 6.0f); + Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.scale(1.0f / 6.0f, 1.0f / 6.0f); + + canvas.save(); + canvas.translate(0, -AndroidUtilities.statusBarHeight); + parentActivity.getActionBarLayout().draw(canvas); + canvas.drawColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.3f))); + canvas.restore(); + canvas.save(); + canvas.translate(containerView.getX(), -AndroidUtilities.statusBarHeight); + containerView.draw(canvas); + + Utilities.stackBlurBitmap(bitmap, Math.max(7, Math.max(w, h) / 180)); + blurredView.setBackground(new BitmapDrawable(bitmap)); + blurredView.setAlpha(0.0f); + blurredView.setVisibility(View.VISIBLE); + } + @Override protected boolean canDismissWithSwipe() { return false; @@ -880,7 +929,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (actionBar != null) { int count = call.call.participants_count + (listAdapter.addSelfToCounter() ? 1 : 0); - actionBar.setSubtitle(LocaleController.formatPluralString("Members", count)); + actionBar.setSubtitle(LocaleController.formatPluralString("Participants", count)); } boolean selfUpdate = (Boolean) args[2]; boolean raisedHand = muteButtonState == MUTE_BUTTON_STATE_RAISED_HAND; @@ -898,7 +947,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter float amplitude = (float) args[0]; setAmplitude(amplitude * 4000.0f); if (listView != null) { - TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfDummyParticipant.peer)); + TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfPeer)); if (participant != null) { ArrayList array = delayedGroupCallUpdated ? oldParticipants : call.sortedParticipants; int idx = array.indexOf(participant); @@ -966,10 +1015,13 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } private void applyCallParticipantUpdates() { - int selfPeer = MessageObject.getPeerId(call.selfPeer); - int dummyPeer = MessageObject.getPeerId(selfDummyParticipant.peer); - if (selfPeer != dummyPeer && call.participants.get(selfPeer) != null) { - selfDummyParticipant.peer = call.selfPeer; + if (delayedGroupCallUpdated) { + return; + } + int self = MessageObject.getPeerId(call.selfPeer); + int dummyPeer = MessageObject.getPeerId(selfPeer); + if (self != dummyPeer && call.participants.get(self) != null) { + selfPeer = call.selfPeer; } int count = listView.getChildCount(); View minChild = null; @@ -986,7 +1038,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } try { UpdateCallback updateCallback = new UpdateCallback(listAdapter); - setOldRows(listAdapter.addMemberRow, listAdapter.selfUserRow, listAdapter.usersStartRow, listAdapter.usersEndRow, listAdapter.invitedStartRow, listAdapter.invitedEndRow); + setOldRows(listAdapter.addMemberRow, listAdapter.usersStartRow, listAdapter.usersEndRow, listAdapter.invitedStartRow, listAdapter.invitedEndRow); listAdapter.updateRows(); DiffUtil.calculateDiff(diffUtilsCallback).dispatchUpdatesTo(updateCallback); } catch (Exception e) { @@ -1081,7 +1133,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (!anyVisible) { anyVisible = true; accountSwitchImageView.getImageReceiver().setCurrentAccount(currentAccount); - int peerId = MessageObject.getPeerId(selfDummyParticipant.peer); + int peerId = MessageObject.getPeerId(selfPeer); if (peerId > 0) { TLRPC.User user = accountInstance.getMessagesController().getUser(peerId); accountSwitchAvatarDrawable.setInfo(user); @@ -1098,7 +1150,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter accountSwitchImageView.setVisibility(View.GONE); accountSelectCell.setVisibility(View.VISIBLE); accountGap.setVisibility(View.VISIBLE); - int peerId = MessageObject.getPeerId(selfDummyParticipant.peer); + int peerId = MessageObject.getPeerId(selfPeer); TLObject object; if (peerId > 0) { object = accountInstance.getMessagesController().getUser(peerId); @@ -1180,12 +1232,13 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (chat == null) { return; } + call.addSelfDummyParticipant(); groupCallInstance = new GroupCallActivity(activity, account, call, chat); groupCallInstance.parentActivity = activity; groupCallInstance.show(); } - public GroupCallActivity(Context context, AccountInstance account, ChatObject.Call call, TLRPC.Chat chat) { + private GroupCallActivity(Context context, AccountInstance account, ChatObject.Call call, TLRPC.Chat chat) { super(context, false); this.accountInstance = account; this.call = call; @@ -1221,24 +1274,20 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter oldParticipants.addAll(call.sortedParticipants); oldInvited.addAll(call.invitedUsers); - selfDummyParticipant = new TLRPC.TL_groupCallParticipant(); TLRPC.InputPeer peer = VoIPService.getSharedInstance().getGroupCallPeer(); if (peer == null) { - selfDummyParticipant.peer = new TLRPC.TL_peerUser(); - selfDummyParticipant.peer.user_id = accountInstance.getUserConfig().getClientUserId(); + selfPeer = new TLRPC.TL_peerUser(); + selfPeer.user_id = accountInstance.getUserConfig().getClientUserId(); } else if (peer instanceof TLRPC.TL_inputPeerChannel) { - selfDummyParticipant.peer = new TLRPC.TL_peerChannel(); - selfDummyParticipant.peer.channel_id = peer.channel_id; + selfPeer = new TLRPC.TL_peerChannel(); + selfPeer.channel_id = peer.channel_id; } else if (peer instanceof TLRPC.TL_inputPeerUser) { - selfDummyParticipant.peer = new TLRPC.TL_peerUser(); - selfDummyParticipant.peer.user_id = peer.user_id; - }else if (peer instanceof TLRPC.TL_inputPeerChat) { - selfDummyParticipant.peer = new TLRPC.TL_peerChat(); - selfDummyParticipant.peer.chat_id = peer.chat_id; + selfPeer = new TLRPC.TL_peerUser(); + selfPeer.user_id = peer.user_id; + } else if (peer instanceof TLRPC.TL_inputPeerChat) { + selfPeer = new TLRPC.TL_peerChat(); + selfPeer.chat_id = peer.chat_id; } - selfDummyParticipant.muted = true; - selfDummyParticipant.can_self_unmute = true; - selfDummyParticipant.date = accountInstance.getConnectionsManager().getCurrentTime(); currentCallState = VoIPService.getSharedInstance().getCallState(); @@ -1279,6 +1328,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private boolean ignoreLayout = false; private RectF rect = new RectF(); + private int lastSize; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @@ -1304,6 +1354,11 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter ignoreLayout = false; } super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY)); + int currentSize = getMeasuredHeight() + (getMeasuredWidth() << 16); + if (currentSize != lastSize) { + lastSize = currentSize; + dismissAvatarPreview(false); + } } @Override @@ -1314,6 +1369,23 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter @Override public boolean onInterceptTouchEvent(MotionEvent ev) { + if (scrimView != null && ev.getAction() == MotionEvent.ACTION_DOWN) { + float x = ev.getX(); + float y = ev.getY(); + boolean dismissScrim = true; + rect.set(scrimPopupLayout.getX(), scrimPopupLayout.getY(), scrimPopupLayout.getX() + scrimPopupLayout.getMeasuredWidth(), scrimPopupLayout.getY() + scrimPopupLayout.getMeasuredHeight()); + if (rect.contains(x, y)) { + dismissScrim = false; + } + rect.set(avatarPreviewContainer.getX(), avatarPreviewContainer.getY(), avatarPreviewContainer.getX() + avatarPreviewContainer.getMeasuredWidth(), avatarPreviewContainer.getY() + avatarPreviewContainer.getMeasuredWidth() + scrimView.getMeasuredHeight()); + if (rect.contains(x, y)) { + dismissScrim = false; + } + if (dismissScrim) { + dismissAvatarPreview(true); + return true; + } + } if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY - AndroidUtilities.dp(37) && actionBar.getAlpha() == 0.0f) { dismiss(); return true; @@ -1321,6 +1393,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter return super.onInterceptTouchEvent(ev); } + @Override public boolean onTouchEvent(MotionEvent e) { return !isDismissed() && super.onTouchEvent(e); @@ -1370,46 +1443,138 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); - if (scrimView != null) { - canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); - float listTop = listView.getY(); + if (avatarsPreviewShowed) { + if (scrimView != null) { + float listTop = listView.getY(); - boolean groupedBackgroundWasDraw = false; + float[] radii = new float[8]; + Path roundPath = new Path(); - int count = listView.getChildCount(); - for (int num = 0; num < count; num++) { - View child = listView.getChildAt(num); - if (child != scrimView) { - continue; - } + int count = listView.getChildCount(); + float viewClipTop = listTop; + float viewClipBottom = listView.getY() + listView.getMeasuredHeight(); - float viewClipLeft = Math.max(listView.getLeft(), listView.getLeft() + child.getX()); - float viewClipTop = Math.max(listTop, listView.getTop() + child.getY()); - float viewClipRight = Math.min(listView.getRight(), listView.getLeft() + child.getX() + child.getMeasuredWidth()); - float viewClipBottom = Math.min(listView.getY() + listView.getMeasuredHeight(), listView.getY() + child.getY() + scrimView.getClipHeight()); - - if (viewClipTop < viewClipBottom) { - if (child.getAlpha() != 1f) { - canvas.saveLayerAlpha(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom, (int) (255 * child.getAlpha()), Canvas.ALL_SAVE_FLAG); - } else { - canvas.save(); + for (int num = 0; num < count; num++) { + View child = listView.getChildAt(num); + if (child != scrimView) { + continue; } - canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, getMeasuredHeight()); - canvas.translate(listView.getLeft() + child.getX(), listView.getY() + child.getY()); - float progress = scrimPaint.getAlpha() / 100.0f; - float pr = 1.0f - CubicBezierInterpolator.EASE_OUT.getInterpolation(1.0f - progress); - int h = (int) (scrimView.getMeasuredHeight() + (scrimView.getClipHeight() - scrimView.getMeasuredHeight()) * pr); - rect.set(0, 0, child.getMeasuredWidth(), h); - scrimView.setAboutVisibleProgress(listViewBackgroundPaint.getColor(), progress); - canvas.drawRoundRect(rect, AndroidUtilities.dp(13), AndroidUtilities.dp(13), listViewBackgroundPaint); - child.draw(canvas); - canvas.restore(); + + if (viewClipTop < viewClipBottom) { +// + canvas.save(); + canvas.clipRect(0, viewClipTop * (1f - progressToAvatarPreview), getMeasuredWidth(), viewClipBottom * (1f - progressToAvatarPreview) + getMeasuredHeight() * progressToAvatarPreview); + + float childY = (listView.getY() + child.getY()) * (1f - progressToAvatarPreview) + (avatarPreviewContainer.getTop() + avatarPreviewContainer.getMeasuredWidth()) * progressToAvatarPreview; + float childX = (listView.getLeft() + child.getX()) * (1f - progressToAvatarPreview) + avatarPreviewContainer.getLeft() * progressToAvatarPreview; + canvas.translate(childX, childY); + float progress = progressToAvatarPreview; + float pr = 1.0f - CubicBezierInterpolator.EASE_OUT.getInterpolation(1.0f - progress); + int h = (int) (scrimView.getMeasuredHeight() + (scrimView.getClipHeight() - scrimView.getMeasuredHeight()) * pr); + rect.set(0, 0, child.getMeasuredWidth(), h); + //scrimView.setAboutVisibleProgress(listViewBackgroundPaint.getColor(), progressToAvatarPreview); + scrimView.setProgressToAvatarPreview(progressToAvatarPreview); + for (int i = 0; i < 4; i++) { + radii[i] = AndroidUtilities.dp(13) * (1f - progressToAvatarPreview); + radii[4 + i] = AndroidUtilities.dp(13); + } + + roundPath.reset(); + roundPath.addRoundRect(rect, radii, Path.Direction.CW); + roundPath.close(); + canvas.drawPath(roundPath, listViewBackgroundPaint); + child.draw(canvas); + canvas.restore(); + + if (scrimPopupLayout != null) { + float y = childY + h; + float x = getMeasuredWidth() - scrimPopupLayout.getMeasuredWidth() - AndroidUtilities.dp(14); + if (progressToAvatarPreview != 1f) { + canvas.saveLayerAlpha(x, y, x + scrimPopupLayout.getMeasuredWidth(), y + scrimPopupLayout.getMeasuredHeight(), (int) (255 * progressToAvatarPreview), Canvas.ALL_SAVE_FLAG); + } else { + canvas.save(); + } + scrimPopupLayout.setTranslationX(x - scrimPopupLayout.getLeft()); + scrimPopupLayout.setTranslationY(y - scrimPopupLayout.getTop()); + float scale = 0.8f + 0.2f * progressToAvatarPreview; + canvas.scale(scale, scale, x + scrimPopupLayout.getMeasuredWidth() / 2f, y); + + canvas.translate(x, y); + scrimPopupLayout.draw(canvas); + canvas.restore(); + } + } + } + + canvas.save(); + canvas.clipRect(0, viewClipTop * (1f - progressToAvatarPreview), getMeasuredWidth(), viewClipBottom * (1f - progressToAvatarPreview) + getMeasuredHeight() * progressToAvatarPreview); + canvas.scale(avatarPreviewContainer.getScaleX(), avatarPreviewContainer.getScaleY(), avatarPreviewContainer.getX(), avatarPreviewContainer.getY()); + canvas.translate(avatarPreviewContainer.getX(), avatarPreviewContainer.getY()); + avatarPreviewContainer.draw(canvas); + canvas.restore(); + } + } else { + if (scrimView != null) { + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + + float listTop = listView.getY(); + float listBottom = listView.getY() + listView.getMeasuredHeight(); + + int count = listView.getChildCount(); + for (int num = 0; num < count; num++) { + View child = listView.getChildAt(num); + if (child != scrimView) { + continue; + } + + float viewClipLeft = Math.max(listView.getLeft(), listView.getLeft() + child.getX()); + float viewClipTop = Math.max(listTop, listView.getTop() + child.getY()); + float viewClipRight = Math.min(listView.getRight(), listView.getLeft() + child.getX() + child.getMeasuredWidth()); + float viewClipBottom = Math.min(listView.getY() + listView.getMeasuredHeight(), listView.getY() + child.getY() + scrimView.getClipHeight()); + + if (viewClipTop < viewClipBottom) { + if (child.getAlpha() != 1f) { + canvas.saveLayerAlpha(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom, (int) (255 * child.getAlpha()), Canvas.ALL_SAVE_FLAG); + } else { + canvas.save(); + } + + canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, getMeasuredHeight()); + canvas.translate(listView.getLeft() + child.getX(), listView.getY() + child.getY()); + float progress = scrimPaint.getAlpha() / 100.0f; + float pr = 1.0f - CubicBezierInterpolator.EASE_OUT.getInterpolation(1.0f - progress); + int h = (int) (scrimView.getMeasuredHeight() + (scrimView.getClipHeight() - scrimView.getMeasuredHeight()) * pr); + rect.set(0, 0, child.getMeasuredWidth(), h); + scrimView.setAboutVisibleProgress(listViewBackgroundPaint.getColor(), progress); + canvas.drawRoundRect(rect, AndroidUtilities.dp(13), AndroidUtilities.dp(13), listViewBackgroundPaint); + child.draw(canvas); + canvas.restore(); + } } } } } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == avatarPreviewContainer || child == scrimPopupLayout) { + return true; + } + return super.drawChild(canvas, child, drawingTime); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (scrimView != null && keyCode == KeyEvent.KEYCODE_BACK) { + dismissAvatarPreview(true); + return true; + } + return super.onKeyDown(keyCode, event); + } }; + containerView.setFocusable(true); + containerView.setFocusableInTouchMode(true); containerView.setWillNotDraw(false); containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); containerView.setKeepScreenOn(true); @@ -1516,6 +1681,9 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } Bundle args = new Bundle(); args.putInt("user_id", cell.getUser().id); + if (cell.hasAvatarSet()) { + args.putBoolean("expandPhoto", true); + } parentActivity.presentFragment(new ProfileActivity(args)); dismiss(); } else if (position == listAdapter.addMemberRow) { @@ -1693,7 +1861,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter boolean showWaves = false; boolean showLighting = false; if (currentState != null) { - showWaves = currentState.currentState == MUTE_BUTTON_STATE_MUTE || currentState.currentState == MUTE_BUTTON_STATE_UNMUTE; + showWaves = currentState.currentState == MUTE_BUTTON_STATE_MUTE || currentState.currentState == MUTE_BUTTON_STATE_UNMUTE || currentState.currentState == MUTE_BUTTON_STATE_RAISED_HAND || currentState.currentState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN; showLighting = currentState.currentState != MUTE_BUTTON_STATE_CONNECTING; } @@ -1763,9 +1931,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter float radius = AndroidUtilities.dp(52) / 2f; canvas.drawCircle(leaveButton.getX() + leaveButton.getMeasuredWidth() / 2f, leaveButton.getY() + radius, radius, leaveBackgroundPaint); - canvas.save(); - canvas.scale(BlobDrawable.GLOBAL_SCALE, BlobDrawable.GLOBAL_SCALE, cx, cy); canvas.save(); @@ -2024,7 +2190,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter handDrawables.setCurrentFrame(startFrame); muteButton.playAnimation(); if (muteButtonState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN) { - TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfDummyParticipant.peer)); + TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfPeer)); TLObject object; int peerId = MessageObject.getPeerId(participant.peer); if (peerId > 0) { @@ -2304,7 +2470,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (VoIPService.getSharedInstance() == null || !hasFewPeers) { return; } - TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfDummyParticipant.peer)); + TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfPeer)); VoIPService.getSharedInstance().setGroupCallPeer(peer1); if (peer1 instanceof TLRPC.TL_inputPeerUser) { userSwitchObject = accountInstance.getMessagesController().getUser(peer1.user_id); @@ -2376,7 +2542,6 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } }; - actionBarBackground = new View(context) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @@ -2462,6 +2627,80 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter showRecordHint(actionBar.getTitleTextView()); } }); + + + avatarPagerIndicator = new AvatarPreviewPagerIndicator(context); + avatarsViewPager = new ProfileGalleryView(context, actionBar, listView, avatarPagerIndicator); + avatarPagerIndicator.setProfileGalleryView(avatarsViewPager); + avatarPreviewContainer = new FrameLayout(context) { + + RectF rectF = new RectF(); + Path path = new Path(); + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); + super.onMeasure( MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(size + getPaddingBottom(), MeasureSpec.EXACTLY)); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (progressToAvatarPreview != 1) { + if (scrimView != null) { + canvas.save(); + float s = getMeasuredHeight() / (float) scrimView.getAvatarImageView().getMeasuredHeight(); + + + float fromRadius = scrimView.getAvatarImageView().getMeasuredHeight() / 2f * s; + int topRad = (int) ((fromRadius * (1f - progressToAvatarPreview) + (AndroidUtilities.dp(13) * progressToAvatarPreview))); + int bottomRad = (int) (fromRadius * (1f - progressToAvatarPreview)); + scrimView.getAvatarWavesDrawable().draw(canvas, scrimView.getAvatarImageView().getMeasuredHeight() / 2, scrimView.getAvatarImageView().getMeasuredHeight() / 2, this); + scrimView.getAvatarImageView().getImageReceiver().setImageCoords(0, 0, getMeasuredWidth(), getMeasuredHeight()); + scrimView.getAvatarImageView().setRoundRadius(topRad, topRad, bottomRad, bottomRad); + scrimView.getAvatarImageView().getImageReceiver().draw(canvas); + scrimView.getAvatarImageView().setRoundRadius(scrimView.getAvatarImageView().getMeasuredHeight() / 2); + canvas.restore(); + } + avatarsViewPager.setAlpha(progressToAvatarPreview); + } + + path.reset(); + rectF.set(0, 0, getMeasuredHeight(), getMeasuredWidth()); + path.addRoundRect(rectF, new float[]{AndroidUtilities.dp(13), AndroidUtilities.dp(13), AndroidUtilities.dp(13), AndroidUtilities.dp(13), 0, 0, 0, 0}, Path.Direction.CCW); + canvas.save(); + canvas.clipPath(path); + super.dispatchDraw(canvas); + canvas.restore(); + } + }; + avatarPreviewContainer.setVisibility(View.GONE); + + avatarsViewPager.setVisibility(View.VISIBLE); + avatarsViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + int realPosition = avatarsViewPager.getRealPosition(position); + avatarPagerIndicator.saveCurrentPageProgress(); + avatarPagerIndicator.invalidate(); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + blurredView = new View(context); + containerView.addView(blurredView); + + avatarPreviewContainer.addView(avatarsViewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + avatarPreviewContainer.addView(avatarPagerIndicator, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, 0, 0)); + containerView.addView(avatarPreviewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 14, 14, 14, 14)); } @Override @@ -2588,6 +2827,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } private String[] invites = new String[2]; + private void getLink(boolean copy) { TLRPC.Chat newChat = accountInstance.getMessagesController().getChat(currentChat.id); if (newChat != null && TextUtils.isEmpty(newChat.username)) { @@ -2651,7 +2891,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter boolean keyboardIsOpen = false; if (parentActivity != null) { BaseFragment fragment = parentActivity.getActionBarLayout().fragmentsStack.get(parentActivity.getActionBarLayout().fragmentsStack.size() - 1); - if (fragment instanceof ChatActivity) { + if (fragment instanceof ChatActivity) { keyboardIsOpen = ((ChatActivity) fragment).needEnterText(); anyEnterEventSent = true; enterEventSent = true; @@ -2873,7 +3113,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter getUndoView().showWithAction(0, UndoView.ACTION_VOIP_USER_CHANGED, userSwitchObject); userSwitchObject = null; } - TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfDummyParticipant.peer)); + TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfPeer)); if (participant != null && !participant.can_self_unmute && participant.muted && !ChatObject.canManageCalls(currentChat)) { cancelMutePress(); if (participant.raise_hand_rating != 0) { @@ -2962,7 +3202,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter newSubtext = LocaleController.getString("VoipMutedTapedForSpeakInfo", R.string.VoipMutedTapedForSpeakInfo); changed = bigMicDrawable.setCustomEndFrame(84); } else { - TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfDummyParticipant.peer)); + TLRPC.TL_groupCallParticipant participant = call.participants.get(MessageObject.getPeerId(selfPeer)); if (mutedByAdmin = participant != null && !participant.can_self_unmute && participant.muted && !ChatObject.canManageCalls(currentChat)) { changed = bigMicDrawable.setCustomEndFrame(84); } else { @@ -3096,7 +3336,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter states[muteButtonState].shader = null; } else { if (muteButtonState == MUTE_BUTTON_STATE_MUTED_BY_ADMIN || muteButtonState == MUTE_BUTTON_STATE_RAISED_HAND) { - states[muteButtonState].shader = new LinearGradient(0,400, 400, 0, new int[]{Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient), Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient3), Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient2)}, null, Shader.TileMode.CLAMP); + states[muteButtonState].shader = new LinearGradient(0, 400, 400, 0, new int[]{Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient), Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient3), Theme.getColor(Theme.key_voipgroup_mutedByAdminGradient2)}, null, Shader.TileMode.CLAMP); } else if (muteButtonState == MUTE_BUTTON_STATE_MUTE) { states[muteButtonState].shader = new RadialGradient(200, 200, 200, new int[]{Theme.getColor(Theme.key_voipgroup_muteButton), Theme.getColor(Theme.key_voipgroup_muteButton3)}, null, Shader.TileMode.CLAMP); } else { @@ -3223,6 +3463,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private Paint scrimPaint; private GroupCallUserCell scrimView; + private boolean avatarPriviewTransitionInProgress; private int popupAnimationIndex = -1; private AnimatorSet scrimAnimatorSet; private ActionBarPopupWindow scrimPopupWindow; @@ -3286,7 +3527,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); textView.setEllipsize(TextUtils.TruncateAt.END); if (option == 2) { - textView.setText(LocaleController.getString("VoipGroupRemoveMemberAlertTitle", R.string.VoipGroupRemoveMemberAlertTitle)); + textView.setText(LocaleController.getString("VoipGroupRemoveMemberAlertTitle2", R.string.VoipGroupRemoveMemberAlertTitle2)); messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("VoipGroupRemoveMemberAlertText2", R.string.VoipGroupRemoveMemberAlertText2, name, currentChat.title))); } else { textView.setText(LocaleController.getString("VoipGroupAddMemberTitle", R.string.VoipGroupAddMemberTitle)); @@ -3300,10 +3541,12 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter builder.setPositiveButton(LocaleController.getString("VoipGroupUserRemove", R.string.VoipGroupUserRemove), (dialogInterface, i) -> { if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; - accountInstance.getMessagesController().deleteUserFromChat(currentChat.id, user, null); + accountInstance.getMessagesController().deleteParticipantFromChat(currentChat.id, user, null); getUndoView().showWithAction(0, UndoView.ACTION_VOIP_REMOVED, user, null, null, null); } else { - + TLRPC.Chat chat = (TLRPC.Chat) object; + accountInstance.getMessagesController().deleteParticipantFromChat(currentChat.id, null, chat, null, false, false); + getUndoView().showWithAction(0, UndoView.ACTION_VOIP_REMOVED, chat, null, null, null); } }); } else if (object instanceof TLRPC.User) { @@ -3330,7 +3573,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } else { args.putInt("chat_id", -peerId); } - parentActivity.presentFragment(new ProfileActivity(args)); + parentActivity.presentFragment(new ChatActivity(args)); dismiss(); } else if (option == 8) { BaseFragment fragment = parentActivity.getActionBarLayout().fragmentsStack.get(parentActivity.getActionBarLayout().fragmentsStack.size() - 1); @@ -3371,12 +3614,20 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } private boolean showMenuForCell(GroupCallUserCell view) { + if (itemAnimator.isRunning()) { + return false; + } + if (avatarPriviewTransitionInProgress || avatarsPreviewShowed) { + dismissAvatarPreview(true); + return false; + } if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); scrimPopupWindow = null; return false; } + boolean showWithAvatarPreview = containerView.getMeasuredHeight() > containerView.getMeasuredWidth() && !AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow; TLRPC.TL_groupCallParticipant participant = view.getParticipant(); Rect rect = new Rect(); @@ -3433,9 +3684,10 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter linearLayout.setOrientation(LinearLayout.VERTICAL); VolumeSlider volumeSlider = null; + int color = AndroidUtilities.getOffsetColor(Theme.getColor(Theme.key_voipgroup_listViewBackgroundUnscrolled), Theme.getColor(Theme.key_voipgroup_listViewBackground), colorProgress, 1.0f); if (!participant.muted_by_you && (!participant.muted || participant.can_self_unmute)) { Drawable shadowDrawable = getContext().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor, PorterDuff.Mode.MULTIPLY)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); volumeLayout.setBackgroundDrawable(shadowDrawable); linearLayout.addView(volumeLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 0)); @@ -3446,7 +3698,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter buttonsLayout.setMinimumWidth(AndroidUtilities.dp(240)); buttonsLayout.setOrientation(LinearLayout.VERTICAL); Drawable shadowDrawable = getContext().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor, PorterDuff.Mode.MULTIPLY)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); buttonsLayout.setBackgroundDrawable(shadowDrawable); linearLayout.addView(buttonsLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, volumeSlider != null ? -8 : 0, 0, 0)); @@ -3494,6 +3746,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter items.add(LocaleController.getString("VoipGroupCancelRaiseHand", R.string.VoipGroupCancelRaiseHand)); icons.add(R.drawable.msg_handdown); options.add(7); + showWithAvatarPreview = false; } else if (ChatObject.canManageCalls(currentChat)) { if (!isAdmin || !participant.muted) { if (!participant.muted || participant.can_self_unmute) { @@ -3519,7 +3772,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter icons.add(R.drawable.msg_openprofile); options.add(6); } - if (!isAdmin && ChatObject.canBlockUsers(currentChat) && peerId > 0) { + if (!isAdmin && ChatObject.canBlockUsers(currentChat)) { items.add(LocaleController.getString("VoipGroupUserRemove", R.string.VoipGroupUserRemove)); icons.add(R.drawable.msg_block2); options.add(2); @@ -3536,11 +3789,11 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } if (participant.peer.channel_id != 0 && !ChatObject.isMegagroup(currentAccount, participant.peer.channel_id)) { items.add(LocaleController.getString("VoipGroupOpenChannel", R.string.VoipGroupOpenChannel)); - icons.add(R.drawable.msg_channel); + icons.add(R.drawable.msg_msgbubble3); options.add(8); } else { - items.add(LocaleController.getString("VoipGroupOpenProfile", R.string.VoipGroupOpenProfile)); - icons.add(R.drawable.msg_openprofile); + items.add(LocaleController.getString("VoipGroupOpenChat", R.string.VoipGroupOpenChat)); + icons.add(R.drawable.msg_msgbubble3); options.add(6); } } @@ -3564,60 +3817,13 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter processSelectedOption(participant, MessageObject.getPeerId(participant.peer), options.get(i)); if (scrimPopupWindow != null) { scrimPopupWindow.dismiss(); + } else { + dismissAvatarPreview(true); } }); } scrollView.addView(linearLayout, LayoutHelper.createScroll(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); - scrimPopupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { - @Override - public void dismiss() { - super.dismiss(); - if (scrimPopupWindow != this) { - return; - } - scrimPopupWindow = null; - if (scrimAnimatorSet != null) { - scrimAnimatorSet.cancel(); - scrimAnimatorSet = null; - } - layoutManager.setCanScrollVertically(true); - scrimAnimatorSet = new AnimatorSet(); - ArrayList animators = new ArrayList<>(); - animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0)); - scrimAnimatorSet.playTogether(animators); - scrimAnimatorSet.setDuration(220); - scrimAnimatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (scrimView != null) { - scrimView.setAboutVisible(false); - scrimView = null; - } - containerView.invalidate(); - listView.invalidate(); - if (delayedGroupCallUpdated) { - delayedGroupCallUpdated = false; - applyCallParticipantUpdates(); - } - } - }); - scrimAnimatorSet.start(); - } - }; - scrimPopupWindow.setPauseNotifications(true); - scrimPopupWindow.setDismissAnimationDuration(220); - scrimPopupWindow.setOutsideTouchable(true); - scrimPopupWindow.setClippingEnabled(true); - scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); - scrimPopupWindow.setFocusable(true); - popupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); - scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - scrimPopupWindow.getContentView().setFocusableInTouchMode(true); - int popupX = AndroidUtilities.dp(14) + listView.getMeasuredWidth() + AndroidUtilities.dp(8) - popupLayout.getMeasuredWidth(); - int popupY = (int) (listView.getY() + view.getY() + view.getClipHeight()); - scrimPopupWindow.showAtLocation(listView, Gravity.LEFT | Gravity.TOP, popupX, popupY); listView.stopScroll(); layoutManager.setCanScrollVertically(false); scrimView = view; @@ -3627,15 +3833,224 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (scrimAnimatorSet != null) { scrimAnimatorSet.cancel(); } - scrimAnimatorSet = new AnimatorSet(); - ArrayList animators = new ArrayList<>(); - animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0, 100)); - scrimAnimatorSet.playTogether(animators); - scrimAnimatorSet.setDuration(150); - scrimAnimatorSet.start(); + + scrimPopupLayout = popupLayout; + + final ImageLocation imageLocation; + final ImageLocation thumbLocation; + if (peerId > 0) { + TLRPC.User currentUser = accountInstance.getMessagesController().getUser(peerId); + imageLocation = ImageLocation.getForUser(currentUser, true); + thumbLocation = ImageLocation.getForUser(currentUser, false); + } else { + TLRPC.Chat currentChat = accountInstance.getMessagesController().getChat(-peerId); + imageLocation = ImageLocation.getForChat(currentChat, true); + thumbLocation = ImageLocation.getForChat(currentChat, false); + } + + if (imageLocation == null) { + showWithAvatarPreview = false; + } else { + avatarsViewPager.setParentAvatarImage(scrimView.getAvatarImageView()); + avatarsViewPager.setData(peerId); + avatarsViewPager.initIfEmpty(imageLocation, thumbLocation); + } + + if (showWithAvatarPreview) { + avatarsPreviewShowed = true; + popupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + containerView.addView(scrimPopupLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + prepareBlurBitmap(); + avatarPriviewTransitionInProgress = true; + avatarPreviewContainer.setVisibility(View.VISIBLE); + VolumeSlider finalVolumeSlider = volumeSlider; + + avatarPreviewContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + if (finalVolumeSlider != null) { + finalVolumeSlider.invalidate(); + } + avatarPreviewContainer.getViewTreeObserver().removeOnPreDrawListener(this); + runAvatarPreviewTransition(true, view); + return false; + } + }); + } else { + avatarsPreviewShowed = false; + scrimPopupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { + @Override + public void dismiss() { + super.dismiss(); + if (scrimPopupWindow != this) { + return; + } + scrimPopupWindow = null; + if (scrimAnimatorSet != null) { + scrimAnimatorSet.cancel(); + scrimAnimatorSet = null; + } + layoutManager.setCanScrollVertically(true); + scrimAnimatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0)); + scrimAnimatorSet.playTogether(animators); + scrimAnimatorSet.setDuration(220); + scrimAnimatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (scrimView != null) { + scrimView.setAboutVisible(false); + scrimView = null; + } + containerView.invalidate(); + listView.invalidate(); + if (delayedGroupCallUpdated) { + delayedGroupCallUpdated = false; + applyCallParticipantUpdates(); + } + } + }); + scrimAnimatorSet.start(); + } + }; + + scrimPopupWindow.setPauseNotifications(true); + scrimPopupWindow.setDismissAnimationDuration(220); + scrimPopupWindow.setOutsideTouchable(true); + scrimPopupWindow.setClippingEnabled(true); + scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); + scrimPopupWindow.setFocusable(true); + popupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + scrimPopupWindow.getContentView().setFocusableInTouchMode(true); + int popupX = AndroidUtilities.dp(14) + listView.getMeasuredWidth() + AndroidUtilities.dp(8) - popupLayout.getMeasuredWidth(); + int popupY = (int) (listView.getY() + view.getY() + view.getClipHeight()); + + scrimPopupWindow.showAtLocation(listView, Gravity.LEFT | Gravity.TOP, popupX, popupY); + scrimAnimatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0, 100)); + scrimAnimatorSet.playTogether(animators); + scrimAnimatorSet.setDuration(150); + scrimAnimatorSet.start(); + } + return true; } + private void runAvatarPreviewTransition(boolean enter, GroupCallUserCell view) { + float fromX = view.getAvatarImageView().getX() + view.getX() + listView.getX() - avatarPreviewContainer.getLeft(); + float fromY = view.getAvatarImageView().getY() + view.getY() + listView.getY() - avatarPreviewContainer.getTop(); + + float fromScale = view.getAvatarImageView().getMeasuredHeight() / (float) avatarPreviewContainer.getMeasuredWidth(); + + if (enter) { + avatarPreviewContainer.setScaleX(fromScale); + avatarPreviewContainer.setScaleY(fromScale); + avatarPreviewContainer.setTranslationX(fromX); + avatarPreviewContainer.setTranslationY(fromY); + avatarPagerIndicator.setAlpha(0); + } + + int fromRadius = (int) ((view.getAvatarImageView().getMeasuredHeight() >> 1) / fromScale); + + avatarsViewPager.setRoundRadius(fromRadius, fromRadius); + + if (enter) { + blurredView.setAlpha(0f); + } + blurredView.animate().alpha(enter ? 1f : 0).setDuration(220).start(); + avatarPreviewContainer.animate() + .scaleX(enter ? 1f : fromScale) + .scaleY(enter ? 1f : fromScale) + .translationY(enter ? 0 : fromY) + .translationX(enter ? 0 : fromX).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(220).start(); + + avatarPagerIndicator.animate().alpha(enter ? 1f : 0).setDuration(220).start(); + ValueAnimator valueAnimator = ValueAnimator.ofFloat(enter ? 0 : 1f, enter ? 1f : 0); + valueAnimator.addUpdateListener((valueAnimator1) -> { + progressToAvatarPreview = (float) valueAnimator1.getAnimatedValue(); + avatarPreviewContainer.invalidate(); + containerView.invalidate(); + avatarsViewPager.setRoundRadius((int) (fromRadius * (1f - progressToAvatarPreview)), (int) (fromRadius * (1f - progressToAvatarPreview))); + }); + popupAnimationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(popupAnimationIndex, new int[]{NotificationCenter.dialogPhotosLoaded, NotificationCenter.fileDidLoad, NotificationCenter.messagesDidLoad}); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + NotificationCenter.getInstance(currentAccount).onAnimationFinish(popupAnimationIndex); + avatarPriviewTransitionInProgress = false; + progressToAvatarPreview = enter ? 1f : 0f; + if (!enter) { + if (scrimView != null) { + scrimView.setProgressToAvatarPreview(0f); + scrimView.setAboutVisible(false); + scrimView = null; + } + if (scrimPopupLayout.getParent() != null) { + containerView.removeView(scrimPopupLayout); + } + scrimPopupLayout = null; + avatarPreviewContainer.setVisibility(View.GONE); + avatarsPreviewShowed = false; + layoutManager.setCanScrollVertically(true); + + blurredView.setVisibility(View.GONE); + + if (delayedGroupCallUpdated) { + delayedGroupCallUpdated = false; + applyCallParticipantUpdates(); + } + } else { + avatarPreviewContainer.animate().cancel(); + avatarPreviewContainer.setAlpha(1f); + avatarPreviewContainer.setScaleX(1f); + avatarPreviewContainer.setScaleY(1f); + avatarPreviewContainer.setTranslationX(1f); + avatarPreviewContainer.setTranslationY(1f); + } + containerView.invalidate(); + avatarsViewPager.invalidate(); + listView.invalidate(); + } + }); + valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + valueAnimator.setDuration(220); + valueAnimator.start(); + } + + private void dismissAvatarPreview(boolean animated) { + if (avatarPriviewTransitionInProgress || !avatarsPreviewShowed) { + return; + } + if (animated) { + avatarPriviewTransitionInProgress = true; + runAvatarPreviewTransition(false, scrimView); + } else { + if (scrimView != null) { + scrimView.setProgressToAvatarPreview(0f); + scrimView.setAboutVisible(false); + scrimView = null; + } + containerView.removeView(scrimPopupLayout); + scrimPopupLayout = null; + avatarPreviewContainer.setVisibility(View.GONE); + containerView.invalidate(); + avatarsPreviewShowed = false; + layoutManager.setCanScrollVertically(true); + listView.invalidate(); + blurredView.setVisibility(View.GONE); + + if (delayedGroupCallUpdated) { + delayedGroupCallUpdated = false; + applyCallParticipantUpdates(); + } + } + } + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -3644,19 +4059,17 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private int invitedStartRow; private int invitedEndRow; private int addMemberRow; - private int selfUserRow; private int lastRow; private int rowsCount; + private boolean hasSelfUser; + public ListAdapter(Context context) { mContext = context; } public boolean addSelfToCounter() { - if (selfUserRow < 0) { - return false; - } - if (VoIPService.getSharedInstance() == null) { + if (hasSelfUser || VoIPService.getSharedInstance() == null) { return false; } return !VoIPService.getSharedInstance().isJoined(); @@ -3677,11 +4090,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } else { addMemberRow = -1; } - if (call.participants.indexOfKey(MessageObject.getPeerId(selfDummyParticipant.peer)) < 0) { - selfUserRow = rowsCount++; - } else { - selfUserRow = -1; - } + hasSelfUser = call.participants.indexOfKey(MessageObject.getPeerId(selfPeer)) >= 0; usersStartRow = rowsCount; rowsCount += call.sortedParticipants.size(); usersEndRow = rowsCount; @@ -3781,32 +4190,29 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter textCell.setColors(color, color); textCell.setTextAndIcon(LocaleController.getString("VoipGroupInviteMember", R.string.VoipGroupInviteMember), R.drawable.actions_addmember2, true); break; - case 1: + case 1: { GroupCallUserCell userCell = (GroupCallUserCell) holder.itemView; TLRPC.TL_groupCallParticipant participant; - if (position == selfUserRow) { - participant = selfDummyParticipant; - } else { - int row = position - usersStartRow; - if (delayedGroupCallUpdated) { - if (row >= 0 && row < oldParticipants.size()) { - participant = oldParticipants.get(row); - } else { - participant = null; - } + int row = position - usersStartRow; + if (delayedGroupCallUpdated) { + if (row >= 0 && row < oldParticipants.size()) { + participant = oldParticipants.get(row); } else { - if (row >= 0 && row < call.sortedParticipants.size()) { - participant = call.sortedParticipants.get(row); - } else { - participant = null; - } + participant = null; + } + } else { + if (row >= 0 && row < call.sortedParticipants.size()) { + participant = call.sortedParticipants.get(row); + } else { + participant = null; } } if (participant != null) { - userCell.setData(accountInstance, participant, call, MessageObject.getPeerId(selfDummyParticipant.peer)); + userCell.setData(accountInstance, participant, call, MessageObject.getPeerId(selfPeer)); } break; - case 2: + } + case 2: { GroupCallInvitedCell invitedCell = (GroupCallInvitedCell) holder.itemView; Integer uid; int row = position - invitedStartRow; @@ -3827,6 +4233,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter invitedCell.setData(currentAccount, uid); } break; + } } } @@ -3877,7 +4284,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (position == addMemberRow) { return 0; } - if (position == selfUserRow || position >= usersStartRow && position < usersEndRow) { + if (position >= usersStartRow && position < usersEndRow) { return 1; } return 2; @@ -3885,15 +4292,13 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } private int oldAddMemberRow; - private int oldSelfUserRow; private int oldUsersStartRow; private int oldUsersEndRow; private int oldInvitedStartRow; private int oldInvitedEndRow; - public void setOldRows(int addMemberRow, int selfUserRow, int usersStartRow, int usersEndRow, int invitedStartRow, int invitedEndRow) { + public void setOldRows(int addMemberRow, int usersStartRow, int usersEndRow, int invitedStartRow, int invitedEndRow) { oldAddMemberRow = addMemberRow; - oldSelfUserRow = selfUserRow; oldUsersStartRow = usersStartRow; oldUsersEndRow = usersEndRow; oldInvitedStartRow = invitedStartRow; @@ -3927,21 +4332,11 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } else if (oldItemPosition == oldCount - 1 || newItemPosition == listAdapter.rowsCount - 1) { return false; } - if ((newItemPosition == listAdapter.selfUserRow || newItemPosition >= listAdapter.usersStartRow && newItemPosition < listAdapter.usersEndRow) && - (oldItemPosition == oldSelfUserRow || oldItemPosition >= oldUsersStartRow && oldItemPosition < oldUsersEndRow)) { - TLRPC.TL_groupCallParticipant oldItem; - TLRPC.TL_groupCallParticipant newItem; - if (oldItemPosition == oldSelfUserRow) { - oldItem = selfDummyParticipant; - } else { - oldItem = oldParticipants.get(oldItemPosition - oldUsersStartRow); - } - if (newItemPosition == listAdapter.selfUserRow) { - newItem = selfDummyParticipant; - } else { - newItem = call.sortedParticipants.get(newItemPosition - listAdapter.usersStartRow); - } - return MessageObject.getPeerId(oldItem.peer) == MessageObject.getPeerId(newItem.peer) && oldItem.lastActiveDate == oldItem.active_date; + if ((newItemPosition >= listAdapter.usersStartRow && newItemPosition < listAdapter.usersEndRow) && + (oldItemPosition >= oldUsersStartRow && oldItemPosition < oldUsersEndRow)) { + TLRPC.TL_groupCallParticipant oldItem = oldParticipants.get(oldItemPosition - oldUsersStartRow); + TLRPC.TL_groupCallParticipant newItem = call.sortedParticipants.get(newItemPosition - listAdapter.usersStartRow); + return MessageObject.getPeerId(oldItem.peer) == MessageObject.getPeerId(newItem.peer) && (oldItemPosition == newItemPosition || oldItem.lastActiveDate == oldItem.active_date); } else if (newItemPosition >= listAdapter.invitedStartRow && newItemPosition < listAdapter.invitedEndRow && oldItemPosition >= oldInvitedStartRow && oldItemPosition < oldInvitedEndRow) { Integer oldItem = oldInvited.get(oldItemPosition - oldInvitedStartRow); @@ -3960,7 +4355,6 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private static class UpdateCallback implements ListUpdateCallback { final RecyclerView.Adapter adapter; - boolean changed; private UpdateCallback(RecyclerView.Adapter adapter) { this.adapter = adapter; @@ -3968,19 +4362,16 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter @Override public void onInserted(int position, int count) { - changed = true; adapter.notifyItemRangeInserted(position, count); } @Override public void onRemoved(int position, int count) { - changed = true; adapter.notifyItemRangeRemoved(position, count); } @Override public void onMoved(int fromPosition, int toPosition) { - changed = true; adapter.notifyItemMoved(fromPosition, toPosition); } @@ -4006,4 +4397,13 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter public ArrayList getThemeDescriptions() { return new ArrayList<>(); } + + @Override + public void onBackPressed() { + if (avatarsPreviewShowed) { + dismissAvatarPreview(true); + return; + } + super.onBackPressed(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 0fa383593..160acfaa5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -1132,7 +1132,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen public class GroupCreateAdapter extends RecyclerListView.FastScrollAdapter { private Context context; - private ArrayList searchResult = new ArrayList<>(); + private ArrayList searchResult = new ArrayList<>(); private ArrayList searchResultNames = new ArrayList<>(); private SearchAdapterHelper searchAdapterHelper; private Runnable searchRunnable; @@ -1336,7 +1336,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen int localServerCount = searchAdapterHelper.getLocalServerSearch().size(); if (position >= 0 && position < localCount) { - object = searchResult.get(position); + object = (TLObject) searchResult.get(position); } else if (position >= localCount && position < localServerCount + localCount) { object = searchAdapterHelper.getLocalServerSearch().get(position - localCount); } else if (position > localCount + localServerCount && position <= globalCount + localCount + localServerCount) { @@ -1493,7 +1493,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen search[1] = search2; } - ArrayList resultArray = new ArrayList<>(); + ArrayList resultArray = new ArrayList<>(); ArrayList resultArrayNames = new ArrayList<>(); for (int a = 0; a < contacts.size(); a++) { @@ -1547,7 +1547,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen } } - private void updateSearchResults(final ArrayList users, final ArrayList names) { + private void updateSearchResults(final ArrayList users, final ArrayList names) { AndroidUtilities.runOnUIThread(() -> { if (!searching) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index e1093172c..3fdbf4626 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -28,6 +28,7 @@ import android.graphics.Point; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.location.LocationManager; +import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -134,6 +135,7 @@ import org.telegram.ui.Components.ThemeEditorView; import org.telegram.ui.Components.UndoView; import org.telegram.ui.Components.UpdateAppAlertDialog; import org.telegram.ui.Components.voip.VoIPHelper; +import org.webrtc.voiceengine.WebRtcAudioTrack; import java.io.BufferedReader; import java.io.File; @@ -169,7 +171,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa private ActionMode visibleActionMode; - private boolean wasMutedByAdmin; + private boolean wasMutedByAdminRaisedHand; private ImageView themeSwitchImageView; private View themeSwitchSunView; @@ -890,7 +892,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } public void switchToAccount(int account, boolean removeAll) { - if (account == UserConfig.selectedAccount) { + if (account == UserConfig.selectedAccount || !UserConfig.isValidAccount(account)) { return; } @@ -2360,7 +2362,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (isVoipIntent) { VoIPFragment.show(this, intentAccount[0]); } - if (!showGroupVoip && GroupCallActivity.groupCallInstance != null) { + if (!showGroupVoip && GroupCallActivity.groupCallInstance != null && (intent == null || !Intent.ACTION_MAIN.equals(intent.getAction()))) { GroupCallActivity.groupCallInstance.dismiss(); } @@ -4404,7 +4406,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa private void checkWasMutedByAdmin(boolean checkOnly) { VoIPService voIPService = VoIPService.getSharedInstance(); if (voIPService != null && voIPService.groupCall != null) { - boolean wasMuted = wasMutedByAdmin; + boolean wasMuted = wasMutedByAdminRaisedHand; ChatObject.Call call = voIPService.groupCall; TLRPC.InputPeer peer = voIPService.getGroupCallPeer(); int did; @@ -4420,32 +4422,41 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa did = UserConfig.getInstance(currentAccount).clientUserId; } TLRPC.TL_groupCallParticipant participant = call.participants.get(did); - wasMutedByAdmin = participant != null && !participant.can_self_unmute && participant.muted && participant.raise_hand_rating != 0; + boolean mutedByAdmin = participant != null && !participant.can_self_unmute && participant.muted; + wasMutedByAdminRaisedHand = mutedByAdmin && participant.raise_hand_rating != 0; - if (!checkOnly && wasMuted && !wasMutedByAdmin && GroupCallActivity.groupCallInstance == null) { - if (!mainFragmentsStack.isEmpty()) { - TLRPC.Chat chat = voIPService.getChat(); - BaseFragment fragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1); - if (fragment instanceof ChatActivity) { - ChatActivity chatActivity = (ChatActivity) fragment; - if (chatActivity.getDialogId() == -chat.id) { - chat = null; - } - chatActivity.getUndoView().showWithAction(0, UndoView.ACTION_VOIP_CAN_NOW_SPEAK, chat); - } else if (fragment instanceof DialogsActivity) { - DialogsActivity dialogsActivity = (DialogsActivity) fragment; - dialogsActivity.getUndoView().showWithAction(0, UndoView.ACTION_VOIP_CAN_NOW_SPEAK, chat); - } else if (fragment instanceof ProfileActivity) { - ProfileActivity profileActivity = (ProfileActivity) fragment; - profileActivity.getUndoView().showWithAction(0, UndoView.ACTION_VOIP_CAN_NOW_SPEAK, chat); - } - if (VoIPService.getSharedInstance() != null) { - VoIPService.getSharedInstance().playAllowTalkSound(); - } - } + if (!checkOnly && wasMuted && !wasMutedByAdminRaisedHand && !mutedByAdmin && GroupCallActivity.groupCallInstance == null) { + showVoiceChatTooltip(UndoView.ACTION_VOIP_CAN_NOW_SPEAK); } } else { - wasMutedByAdmin = false; + wasMutedByAdminRaisedHand = false; + } + } + + private void showVoiceChatTooltip(int action) { + VoIPService voIPService = VoIPService.getSharedInstance(); + if (voIPService == null || mainFragmentsStack.isEmpty() || voIPService.groupCall == null) { + return; + } + if (!mainFragmentsStack.isEmpty()) { + TLRPC.Chat chat = voIPService.getChat(); + BaseFragment fragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1); + if (fragment instanceof ChatActivity) { + ChatActivity chatActivity = (ChatActivity) fragment; + if (chatActivity.getDialogId() == -chat.id) { + chat = null; + } + chatActivity.getUndoView().showWithAction(0, action, chat); + } else if (fragment instanceof DialogsActivity) { + DialogsActivity dialogsActivity = (DialogsActivity) fragment; + dialogsActivity.getUndoView().showWithAction(0, action, chat); + } else if (fragment instanceof ProfileActivity) { + ProfileActivity profileActivity = (ProfileActivity) fragment; + profileActivity.getUndoView().showWithAction(0, action, chat); + } + if (action == UndoView.ACTION_VOIP_CAN_NOW_SPEAK && VoIPService.getSharedInstance() != null) { + VoIPService.getSharedInstance().playAllowTalkSound(); + } } } @@ -4946,20 +4957,33 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public boolean dispatchKeyEvent(KeyEvent event) { int keyCode = event.getKeyCode(); - if (VoIPService.getSharedInstance() == null && !mainFragmentsStack.isEmpty() && (!PhotoViewer.hasInstance() || !PhotoViewer.getInstance().isVisible()) && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_DOWN && (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)) { - BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); - if (fragment instanceof ChatActivity) { - if (((ChatActivity) fragment).maybePlayVisibleVideo()) { - return true; + if (event.getAction() == KeyEvent.ACTION_DOWN && (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)) { + if (VoIPService.getSharedInstance() != null) { + if (Build.VERSION.SDK_INT >= 31 && !SharedConfig.useMediaStream) { + boolean oldValue = WebRtcAudioTrack.isSpeakerMuted(); + AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); + int minVolume = am.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); + boolean mute = am.getStreamVolume(AudioManager.STREAM_VOICE_CALL) == minVolume && event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN; + WebRtcAudioTrack.setSpeakerMute(mute); + if (oldValue != WebRtcAudioTrack.isSpeakerMuted()) { + showVoiceChatTooltip(mute ? UndoView.ACTION_VOIP_SOUND_MUTED : UndoView.ACTION_VOIP_SOUND_UNMUTED); + } } - } - if (AndroidUtilities.isTablet() && !rightFragmentsStack.isEmpty()) { - fragment = rightFragmentsStack.get(rightFragmentsStack.size() - 1); + } else if (!mainFragmentsStack.isEmpty() && (!PhotoViewer.hasInstance() || !PhotoViewer.getInstance().isVisible()) && event.getRepeatCount() == 0) { + BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); if (fragment instanceof ChatActivity) { if (((ChatActivity) fragment).maybePlayVisibleVideo()) { return true; } } + if (AndroidUtilities.isTablet() && !rightFragmentsStack.isEmpty()) { + fragment = rightFragmentsStack.get(rightFragmentsStack.size() - 1); + if (fragment instanceof ChatActivity) { + if (((ChatActivity) fragment).maybePlayVisibleVideo()) { + return true; + } + } + } } } return super.dispatchKeyEvent(event); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index 62004b223..74e7d552d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -922,7 +922,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { search[1] = search2; } - ArrayList resultArray = new ArrayList<>(); + ArrayList resultArray = new ArrayList<>(); ArrayList exceptionsArray = new ArrayList<>(); ArrayList resultArrayNames = new ArrayList<>(); @@ -1002,7 +1002,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { }); } - private void updateSearchResults(final ArrayList result, final ArrayList exceptions, final ArrayList names) { + private void updateSearchResults(final ArrayList result, final ArrayList exceptions, final ArrayList names) { AndroidUtilities.runOnUIThread(() -> { if (!searching) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java index 9568906aa..347929365 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java @@ -4873,7 +4873,19 @@ public class PassportActivity extends BaseFragment implements NotificationCenter } SecureDocument document1 = (SecureDocument) v.getTag(); PhotoViewer.getInstance().setParentActivity(getParentActivity()); - if (type == UPLOADING_TYPE_DOCUMENTS) { + if (type == UPLOADING_TYPE_SELFIE) { + ArrayList arrayList = new ArrayList<>(); + arrayList.add(selfieDocument); + PhotoViewer.getInstance().openPhoto(arrayList, 0, provider); + } else if (type == UPLOADING_TYPE_FRONT) { + ArrayList arrayList = new ArrayList<>(); + arrayList.add(frontDocument); + PhotoViewer.getInstance().openPhoto(arrayList, 0, provider); + } else if (type == UPLOADING_TYPE_REVERSE) { + ArrayList arrayList = new ArrayList<>(); + arrayList.add(reverseDocument); + PhotoViewer.getInstance().openPhoto(arrayList, 0, provider); + } else if (type == UPLOADING_TYPE_DOCUMENTS) { PhotoViewer.getInstance().openPhoto(documents, documents.indexOf(document1), provider); } else { PhotoViewer.getInstance().openPhoto(translationDocuments, translationDocuments.indexOf(document1), provider); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java index 3e1bae3af..205238cb3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java @@ -691,7 +691,7 @@ public class PeopleNearbyActivity extends BaseFragment implements NotificationCe if (ChatObject.isNotInChat(chat)) { getMessagesController().deleteDialog(dialogId, 0, revoke); } else { - getMessagesController().deleteUserFromChat((int) -dialogId, getMessagesController().getUser(getUserConfig().getClientUserId()), null, revoke, revoke); + getMessagesController().deleteParticipantFromChat((int) -dialogId, getMessagesController().getUser(getUserConfig().getClientUserId()), null, null, revoke, revoke); } } else { getMessagesController().deleteDialog(dialogId, 0, revoke); @@ -741,7 +741,7 @@ public class PeopleNearbyActivity extends BaseFragment implements NotificationCe } } - public class HeaderCellProgress extends HeaderCell { + public static class HeaderCellProgress extends HeaderCell { private RadialProgressView progressView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 6d9fe2f75..abe0c4b6b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -156,7 +156,6 @@ import org.telegram.messenger.MediaController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -616,6 +615,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat seekToProgressPending = seconds / (float) currentMessageObject.getDuration(); } else { videoPlayer.seekTo(seconds * 1000L); + videoPlayerSeekbar.setProgress(seconds * 1000L / (float) videoPlayer.getDuration(), true); + videoPlayerSeekbarView.invalidate(); } } } else if (url.startsWith("#")) { @@ -4158,7 +4159,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public boolean canOpenMenu() { - if (currentMessageObject != null) { + if (currentMessageObject != null || currentSecureDocument != null) { return true; } else if (currentFileLocationVideo != null) { File f = FileLoader.getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); @@ -6169,7 +6170,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoPlayerSeekbarView = new View(containerView.getContext()) { @Override protected void onDraw(Canvas canvas) { - videoPlayerSeekbar.draw(canvas); + videoPlayerSeekbar.draw(canvas, this); } }; videoPlayerSeekbarView.setAccessibilityDelegate(accessibilityDelegate); @@ -7479,6 +7480,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentIndex < 0 || currentIndex >= imagesArrLocals.size()) { return; } + Object object = imagesArrLocals.get(currentIndex); + if (!(object instanceof MediaController.MediaEditState)) { + return; + } Bitmap bitmap = null; Bitmap[] paintThumbBitmap = new Bitmap[1]; ArrayList stickers = null; @@ -9877,6 +9882,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat groupedPhotosListView.fillList(); } else if (!secureDocuments.isEmpty()) { allowShare = false; + menuItem.showSubItem(gallery_menu_delete); menuItem.hideSubItem(gallery_menu_save); nameTextView.setText(""); dateTextView.setText(""); @@ -13897,16 +13903,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat current -= 10000; } if (old != current) { + boolean apply = true; if (current > total) { current = total; } else if (current < 0) { + if (current < -9000) { + apply = false; + } current = 0; } - videoForwardDrawable.setLeftSide(x < width / 3); - videoPlayer.seekTo(current); - containerView.invalidate(); - videoPlayerSeekbar.setProgress(current / (float) total); - videoPlayerSeekbarView.invalidate(); + if (apply) { + videoForwardDrawable.setLeftSide(x < width / 3); + videoForwardDrawable.addTime(10000); + videoPlayer.seekTo(current); + containerView.invalidate(); + videoPlayerSeekbar.setProgress(current / (float) total, true); + videoPlayerSeekbarView.invalidate(); + } return true; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index e28aebc67..f9677b3b0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -1180,6 +1180,9 @@ public class PopupNotificationActivity extends Activity implements NotificationC popupMessages.clear(); if (isReply) { int account = intent != null ? intent.getIntExtra("currentAccount", UserConfig.selectedAccount) : UserConfig.selectedAccount; + if (!UserConfig.isValidAccount(account)) { + return; + } popupMessages.addAll(NotificationsController.getInstance(account).popupReplyMessages); } else { for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 6f18775df..bb4b9e885 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -479,7 +479,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }; private boolean fragmentOpened; - public class AvatarImageView extends BackupImageView { + public static class AvatarImageView extends BackupImageView { private final RectF rect = new RectF(); private final Paint placeholderPaint; @@ -488,6 +488,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private float foregroundAlpha; private ImageReceiver.BitmapHolder drawableHolder; + ProfileGalleryView avatarsViewPager; + + public void setAvatarsViewPager(ProfileGalleryView avatarsViewPager) { + this.avatarsViewPager = avatarsViewPager; + } + public AvatarImageView(Context context) { super(context); foregroundImageReceiver = new ImageReceiver(this); @@ -526,7 +532,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public void clearForeground() { AnimatedFileDrawable drawable = foregroundImageReceiver.getAnimation(); if (drawable != null) { - drawable.removeSecondParentView(avatarImage); + drawable.removeSecondParentView(this); } foregroundImageReceiver.clearImage(); if (drawableHolder != null) { @@ -2645,7 +2651,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. SharedConfig.pauseMusicOnRecord ? LocaleController.getString("DebugMenuDisablePauseMusic", R.string.DebugMenuDisablePauseMusic) : LocaleController.getString("DebugMenuEnablePauseMusic", R.string.DebugMenuEnablePauseMusic), BuildVars.DEBUG_VERSION && !AndroidUtilities.isTablet() && Build.VERSION.SDK_INT >= 23 ? (SharedConfig.smoothKeyboard ? LocaleController.getString("DebugMenuDisableSmoothKeyboard", R.string.DebugMenuDisableSmoothKeyboard) : LocaleController.getString("DebugMenuEnableSmoothKeyboard", R.string.DebugMenuEnableSmoothKeyboard)) : null, BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.disableVoiceAudioEffects ? "Enable voip audio effects" : "Disable voip audio effects") : null, - Build.VERSION.SDK_INT >= 21 ? (SharedConfig.noStatusBar ? "Show status bar background" : "Hide status bar background") : null + Build.VERSION.SDK_INT >= 21 ? (SharedConfig.noStatusBar ? "Show status bar background" : "Hide status bar background") : null, + SharedConfig.useMediaStream ? "Use call stream in voice chats" : "User media stream in voice chats" }; builder.setItems(items, (dialog, which) -> { if (which == 0) { @@ -2700,6 +2707,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getParentActivity().getWindow().setStatusBarColor(0x33000000); } } + } else if (which == 15) { + SharedConfig.toggleUseMediaStream(); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -2813,7 +2822,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (currentChannelParticipant == null) { TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); req.channel = MessagesController.getInputChannel(chat); - req.user_id = getMessagesController().getInputUser(user_id); + req.participant = getMessagesController().getInputPeer(user_id); getConnectionsManager().sendRequest(req, (response, error) -> { if (response != null) { AndroidUtilities.runOnUIThread(() -> currentChannelParticipant = ((TLRPC.TL_channels_channelParticipant) response).participant); @@ -2963,6 +2972,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. avatarsViewPager.setChatInfo(chatInfo); avatarContainer2.addView(avatarsViewPager); avatarContainer2.addView(overlaysView); + avatarImage.setAvatarsViewPager(avatarsViewPager); avatarsViewPagerIndicatorView = new PagerIndicatorView(context); avatarContainer2.addView(avatarsViewPagerIndicatorView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); @@ -3460,7 +3470,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. channelParticipant1.channelParticipant = new TLRPC.TL_channelParticipant(); } channelParticipant1.channelParticipant.inviter_id = getUserConfig().getClientUserId(); - channelParticipant1.channelParticipant.user_id = participant.user_id; + channelParticipant1.channelParticipant.peer = new TLRPC.TL_peerUser(); + channelParticipant1.channelParticipant.peer.user_id = participant.user_id; channelParticipant1.channelParticipant.date = participant.date; channelParticipant1.channelParticipant.banned_rights = rightsBanned; channelParticipant1.channelParticipant.admin_rights = rightsAdmin; @@ -3489,7 +3500,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. boolean changed = false; for (int a = 0; a < chatInfo.participants.participants.size(); a++) { TLRPC.ChannelParticipant p = ((TLRPC.TL_chatChannelParticipant) chatInfo.participants.participants.get(a)).channelParticipant; - if (p.user_id == participant.user_id) { + if (MessageObject.getPeerId(p.peer) == participant.user_id) { chatInfo.participants_count--; chatInfo.participants.participants.remove(a); changed = true; @@ -3665,20 +3676,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (error == null) { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; getMessagesController().putUsers(res.users, false); + getMessagesController().putChats(res.chats, false); if (res.users.size() < 200) { usersEndReached = true; } if (req.offset == 0) { participantsMap.clear(); chatInfo.participants = new TLRPC.TL_chatParticipants(); - getMessagesStorage().putUsersAndChats(res.users, null, true, true); + getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); getMessagesStorage().updateChannelUsers(chat_id, res.participants); } for (int a = 0; a < res.participants.size(); a++) { TLRPC.TL_chatChannelParticipant participant = new TLRPC.TL_chatChannelParticipant(); participant.channelParticipant = res.participants.get(a); participant.inviter_id = participant.channelParticipant.inviter_id; - participant.user_id = participant.channelParticipant.user_id; + participant.user_id = MessageObject.getPeerId(participant.channelParticipant.peer); participant.date = participant.channelParticipant.date; if (participantsMap.indexOfKey(participant.user_id) < 0) { if (chatInfo.participants == null) { @@ -3879,7 +3891,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. TLRPC.TL_chatChannelParticipant channelParticipant1 = new TLRPC.TL_chatChannelParticipant(); channelParticipant1.channelParticipant = new TLRPC.TL_channelParticipant(); channelParticipant1.channelParticipant.inviter_id = getUserConfig().getClientUserId(); - channelParticipant1.channelParticipant.user_id = user.id; + channelParticipant1.channelParticipant.peer = new TLRPC.TL_peerUser(); + channelParticipant1.channelParticipant.peer.user_id = user.id; channelParticipant1.channelParticipant.date = getConnectionsManager().getCurrentTime(); channelParticipant1.user_id = user.id; chatInfo.participants.participants.add(channelParticipant1); @@ -5116,7 +5129,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private void kickUser(int uid, TLRPC.ChatParticipant participant) { if (uid != 0) { TLRPC.User user = getMessagesController().getUser(uid); - getMessagesController().deleteUserFromChat(chat_id, user, chatInfo); + getMessagesController().deleteParticipantFromChat(chat_id, user, chatInfo); if (currentChat != null && user != null && BulletinFactory.canShowBulletin(this)) { BulletinFactory.createRemoveFromChatBulletin(this, user, currentChat.title).show(); } @@ -5130,7 +5143,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { getNotificationCenter().postNotificationName(NotificationCenter.closeChats); } - getMessagesController().deleteUserFromChat(chat_id, getMessagesController().getUser(getUserConfig().getClientUserId()), chatInfo); + getMessagesController().deleteParticipantFromChat(chat_id, getMessagesController().getUser(getUserConfig().getClientUserId()), chatInfo); playProfileAnimation = 0; finishFragment(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index 6e2db298b..fe5ab48c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -1305,12 +1305,8 @@ public class StatisticActivity extends BaseFragment implements NotificationCente chartView.legendSignatureView.showProgress(false, false); chartView.legendSignatureView.setOnTouchListener(new RecyclerListView.FoucsableOnTouchListener()); - chartView.legendSignatureView.setOnClickListener(v -> { - onZoomed(); - }); - zoomedChartView.legendSignatureView.setOnClickListener(v -> { - zoomedChartView.animateLegend(false); - }); + chartView.legendSignatureView.setOnClickListener(v -> onZoomed()); + zoomedChartView.legendSignatureView.setOnClickListener(v -> zoomedChartView.animateLegend(false)); chartView.setVisibility(VISIBLE); zoomedChartView.setVisibility(INVISIBLE); chartView.setHeader(chartHeaderView); @@ -2580,7 +2576,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } TLRPC.TL_channels_getParticipant request = new TLRPC.TL_channels_getParticipant(); request.channel = MessagesController.getInstance(UserConfig.selectedAccount).getInputChannel(chat.id); - request.user_id = MessagesController.getInstance(UserConfig.selectedAccount).getInputUser(user.id); + request.participant = MessagesController.getInputPeer(user); ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> { AndroidUtilities.runOnUIThread(() -> { if (fragment.isFinishing() || fragment.getFragmentView() == null) { @@ -2611,27 +2607,25 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } TLRPC.TL_channels_getParticipant request = new TLRPC.TL_channels_getParticipant(); request.channel = MessagesController.getInstance(UserConfig.selectedAccount).getInputChannel(chat.id); - request.user_id = MessagesController.getInstance(UserConfig.selectedAccount).getInputUser(UserConfig.getInstance(UserConfig.selectedAccount).clientUserId); - ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> { - AndroidUtilities.runOnUIThread(() -> { - if (fragment.isFinishing() || fragment.getFragmentView() == null) { - return; - } - if (progressDialog[0] == null) { - return; - } - if (error == null) { - TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; - TLRPC.TL_chatChannelParticipant chatChannelParticipant = new TLRPC.TL_chatChannelParticipant(); - chatChannelParticipant.channelParticipant = participant.participant; - chatChannelParticipant.user_id = UserConfig.getInstance(UserConfig.selectedAccount).clientUserId; - chat.participants.participants.add(0, chatChannelParticipant); - onLongClick(chat, fragment, progressDialog); - } else { - onLongClick(chat, fragment, progressDialog, false); - } - }); - }); + request.participant = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(UserConfig.getInstance(UserConfig.selectedAccount).clientUserId); + ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (fragment.isFinishing() || fragment.getFragmentView() == null) { + return; + } + if (progressDialog[0] == null) { + return; + } + if (error == null) { + TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; + TLRPC.TL_chatChannelParticipant chatChannelParticipant = new TLRPC.TL_chatChannelParticipant(); + chatChannelParticipant.channelParticipant = participant.participant; + chatChannelParticipant.user_id = UserConfig.getInstance(UserConfig.selectedAccount).clientUserId; + chat.participants.participants.add(0, chatChannelParticipant); + onLongClick(chat, fragment, progressDialog); + } else { + onLongClick(chat, fragment, progressDialog, false); + } + })); return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java index 8f2f86754..66ad2c979 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java @@ -267,7 +267,7 @@ public class TooManyCommunitiesActivity extends BaseFragment { for (int i = 0; i < chats.size(); i++) { TLRPC.Chat chat = chats.get(i); getMessagesController().putChat(chat, false); - getMessagesController().deleteUserFromChat(chat.id, currentUser, null); + getMessagesController().deleteParticipantFromChat(chat.id, currentUser, null); } finishFragment(); }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java index 814adaf7b..5a876ec85 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java @@ -333,21 +333,20 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification } public static void clearInstance() { - if (VoIPService.getSharedInstance() != null) { - int h = instance.windowView.getMeasuredHeight(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH && instance.lastInsets != null) { - h -= instance.lastInsets.getSystemWindowInsetBottom(); - } - if (instance.canSwitchToPip) { - VoIPPiPView.show(instance.activity, instance.currentAccount, instance.windowView.getMeasuredWidth(), h, VoIPPiPView.ANIMATION_ENTER_TYPE_SCALE); + if (instance != null) { + if (VoIPService.getSharedInstance() != null) { + int h = instance.windowView.getMeasuredHeight(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH && instance.lastInsets != null) { - VoIPPiPView.topInset = instance.lastInsets.getSystemWindowInsetTop(); - VoIPPiPView.bottomInset = instance.lastInsets.getSystemWindowInsetBottom(); + h -= instance.lastInsets.getSystemWindowInsetBottom(); + } + if (instance.canSwitchToPip) { + VoIPPiPView.show(instance.activity, instance.currentAccount, instance.windowView.getMeasuredWidth(), h, VoIPPiPView.ANIMATION_ENTER_TYPE_SCALE); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH && instance.lastInsets != null) { + VoIPPiPView.topInset = instance.lastInsets.getSystemWindowInsetTop(); + VoIPPiPView.bottomInset = instance.lastInsets.getSystemWindowInsetBottom(); + } } } - } - - if (instance != null) { instance.callingUserTextureView.renderer.release(); instance.currentUserTextureView.renderer.release(); instance.callingUserMiniTextureRenderer.release(); diff --git a/TMessagesProj/src/main/java/org/webrtc/voiceengine/WebRtcAudioTrack.java b/TMessagesProj/src/main/java/org/webrtc/voiceengine/WebRtcAudioTrack.java index 11adb8293..60d087511 100644 --- a/TMessagesProj/src/main/java/org/webrtc/voiceengine/WebRtcAudioTrack.java +++ b/TMessagesProj/src/main/java/org/webrtc/voiceengine/WebRtcAudioTrack.java @@ -49,6 +49,7 @@ public class WebRtcAudioTrack { // corresponding to voice communications, such as telephony or VoIP. private static final int DEFAULT_USAGE = getDefaultUsageAttribute(); private static int usageAttribute = DEFAULT_USAGE; + private static int streamType = AudioManager.STREAM_VOICE_CALL; // This method overrides the default usage attribute and allows the user // to set it to something else than AudioAttributes.USAGE_VOICE_COMMUNICATION. @@ -61,6 +62,10 @@ public class WebRtcAudioTrack { usageAttribute = usage; } + public static synchronized void setAudioStreamType(int type) { + streamType = type; + } + private static int getDefaultUsageAttribute() { if (Build.VERSION.SDK_INT >= 21) { return AudioAttributes.USAGE_VOICE_COMMUNICATION; @@ -350,7 +355,7 @@ public class WebRtcAudioTrack { threadChecker.checkIsOnValidThread(); Logging.d(TAG, "getStreamMaxVolume"); assertTrue(audioManager != null); - return audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL); + return audioManager.getStreamMaxVolume(streamType); } // Set current volume level for a phone call audio stream. @@ -362,7 +367,7 @@ public class WebRtcAudioTrack { Logging.e(TAG, "The device implements a fixed volume policy."); return false; } - audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, volume, 0); + audioManager.setStreamVolume(streamType, volume, 0); return true; } @@ -377,7 +382,7 @@ public class WebRtcAudioTrack { threadChecker.checkIsOnValidThread(); Logging.d(TAG, "getStreamVolume"); assertTrue(audioManager != null); - return audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); + return audioManager.getStreamVolume(streamType); } private void logMainParameters() { @@ -399,7 +404,7 @@ public class WebRtcAudioTrack { // TODO(henrika): use setPerformanceMode(int) with PERFORMANCE_MODE_LOW_LATENCY to control // performance when Android O is supported. Add some logging in the mean time. final int nativeOutputSampleRate = - AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_VOICE_CALL); + AudioTrack.getNativeOutputSampleRate(streamType); Logging.d(TAG, "nativeOutputSampleRate: " + nativeOutputSampleRate); if (sampleRateInHz != nativeOutputSampleRate) { Logging.w(TAG, "Unable to use fast mode since requested sample rate is not native"); @@ -426,7 +431,7 @@ public class WebRtcAudioTrack { @SuppressWarnings("deprecation") // Deprecated in API level 25. private static AudioTrack createAudioTrackOnLowerThanLollipop( int sampleRateInHz, int channelConfig, int bufferSizeInBytes) { - return new AudioTrack(AudioManager.STREAM_VOICE_CALL, sampleRateInHz, channelConfig, + return new AudioTrack(streamType, sampleRateInHz, channelConfig, AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes, AudioTrack.MODE_STREAM); } @@ -493,6 +498,10 @@ public class WebRtcAudioTrack { speakerMute = mute; } + public static boolean isSpeakerMuted() { + return speakerMute; + } + // Releases the native AudioTrack resources. private void releaseAudioResources() { Logging.d(TAG, "releaseAudioResources"); diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_msgbubble3.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_msgbubble3.png new file mode 100644 index 0000000000000000000000000000000000000000..aca3c3dd0d1f65d9d6239c64eb7356acf96a853f GIT binary patch literal 949 zcmV;m14{gfP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uz0A4x<(R9Fe^m(NQSVHn3}&CH-e zf>O*58AXI9UMeAoAm~yT38JV&1QGp!l00=;{{q3T9m8X{ereqzDzQtEMWIINN*ROz&THkZq7Aae-p08I*< zH=`KC52aG6&k{_;7@{6r1kb=9P|k!ST&by#Z79TQRCEeoXuk-203!-nORUhORtBr7 zYA^&E!9(EM8xHzF7g$l)Kw_E`j&NNQt;WKdP{$N@f{ddk;>SVg|5CVG;|?}WtTWUQ zMxvk<%mA|+ELK}Ss+U?I8fK#18cGLZ19)qd_)DP*Ly$zv(Ul$zWy>H9I7R8Q1rZ5o zryc!)lI0NF!JHNhmn2t_M1NR&NU!!lDUyRq%;M#tmxzfrkRD=#zD-ETjW;U{?4~a% z#-Q}bcUtIK{DUFctpst0W9;oKMUNv+ziuPB&y)@g&f|xSkf6Vhw)7IS-kv*9%RFL})_ci7-<7|nxGu5CI#r&v4(=tJ*5D>f{s(WD z>ZA2?2O8I)Y#rN;kd&v#Hni8O{-pJB2fA%R{J)=}6N`I!%n`iftQVI|{X(A&@9--Z zGx4rO8`uW^JWw6dIbe1j|=L8}G42V(LOaKMLF9D>**6>70;v}knzyKh9gx43ga1agy9s9g)7 zg$kol3*?LAr|OC84^?a=3Qju3do6CBT-gsyIPyF@3nqZsZx&Zg$Il1dP$!i96+dEy zh{-!}8k}Z5ihlwoz!xCTH2I2^eQ6))0`6y$Ja|vBsXoSsHyUjP_GOxX=jC`KxB@Od&TV?TuqOz|JXCRcyY2?vQGiO&Agq@=X{?lXR{gwV|Fid%^U~~` z`BifMO_|dcVk7r`&9`kWg~n$Naf)z#HMtye!uAWFfR92%L)4A-(i?2CJDtie@h`r> zI^E#pU7d-GnLk$s$Q+btiED|uvRU%1)-&b1k{-X3=WTb*>yfFumhw&6W3h)_wyo@? z7j4lVj(3BX?@-S4(e8g|BYMBTrZVu*R}ra;;5T*AKd7A=a&;1 zR3s<4@-AoH?5hc$(;P2O&@E?5t@~+f(eB@POj_*HA$yOfCpG$-lML5KrZ`63KlpiH zn^(pw$uOUGJ{OUTXMUVoQQq0u!n@YBf;H;QYt>k@yLvl6m^l|8VOu_j`?cQ>rk(fO z9&@ceJ5k@^qwK4>dM3sngty3Vb>z-?eNF7qqaNnkly@mdKI;Vst05yvS8UO$Q literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_msgbubble3.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_msgbubble3.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb3812235b4e20a73130781d4d7eedb1706d6 GIT binary patch literal 1220 zcmV;#1UvhQP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NGE=fc|RA>e5nOUe!Q5eVXam{7u z8WS>89;j<584_hEL!Oi|;gJlbB!zgC7jAe`9=v!(88VkhBt?e%;BsBO7|VG5{_N#` z);)W=XK&}G`_;eot+l`J|NYlG>+G}F*%cLS*0usAtw5oq>>#8DMz{D$YdcCt%Qn!CEyOo%ETqk)DuaS zK!LH$@;DeDGTYaTUjlVN+eMIRO9=zP4A2J@vpWnfXKURrcCn-}#IFP&fp4`8>;Tmu zc0m*q#44v2_@){wOA>37A*%#O{VMbygEgRojZfn%H{cMLZ>m|DhOcNWB)<3`jO_!u z^JHS;3OL1W?Py5_VA^fj@Lz#BC6PuXi#w=6^T&2aq=a80U3=b|#E%Tm$mR+)Mgi5b zmhL-2W)*m27~bPg$VOs3i)sPYbS5oT@tHvc!8I;3Xcr_-&M1(&3p@=qiKs~$2fmx+ zlZg^@2ttE?shvsFxY#lT+11xQd2nn}P64V7>~Bx>r$Dgo`SuHRFehz^Y0+~KIBUQO z|83ynY!?}{QxjLpDG(jgJWaDhOA&a$1V6)%eKZIq%jkkM0BLb{z*4uf9sHrDf0>7> zM$<2g8)&#}id&5p{si>2=qV0zHi4x5h8GYqfN@V*D+n zv#T?mXx-qM z?qN^E^4KI7Kw>*^(<9jKuIJrScb8ZDYU-L03@(6($hKA{U50pbH_n7mn61iiPZ%1 zGlbZG!{`>ZtBkG%Eq+6j+YAt;!^~IUOkd_&a0=`M!*VO0lDOy=5=S6XZzXlie89*4 iN#kwSwgUgz3j73-L?10Nh$2}40000Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91NT34%1ONa40RR91NB{r;0FW_8?*IS>!%0LzRCodHoLP(%RTPGM*hEE) zqG&|1QBXu8F>b^$CMu#)6SqgjC8H+#0vL%=V+_U(C6akCBPtPnF*>}UA#n-Dg^50B z+=6HnP#lf2DliDbFn&K%12eZyRo||u>h9|FN&ZyVsk8j&bk(g}OLw8rkVXd@9cXl* zdL3x0R_dOfp2Nv~8kh*ifKdTh6m|yK%yKPQ*VNSXFUyKc#TrCICQ;qx;1bXbioiF2 z54OL64zLP*NW*?&nQx&fMes2A8l)|Xso2HbbqUhVU>Vp4vKHk~F71`IEs&fBJ^u#W<#01e_=4h254AEPB; zF5^^}k3*(5G-nD}4SZxhMs47Fpayt}Yy%(pt_MCMPE))RWMu?_Szu=gwwu`g2skq> z9*PyjRO~nrw^?cB^^QZ*k>KSxW^DTtJOFg~Wg?0l|kWRz#F5$f?{>BF@7zB}9TI@Ol&j^qQNTktvCo;L06vU}1{5r*dL4X%KvYnYLHC zm_=oFW0PI4QXGJ|M9G2}_vD+%HYXzEUi7ylkDQICI0139WOk}q$uJY_H!?|gd#cG& z3?^&+cq6DAr+TaRuV+ifWr2_VCo;-0ntXT|v+B3{f*?;v8^iF+kcAktBqs z^VR^@nkZlmI8jgQfY$V`sK)XygK)BrTTSVYu7O$;Q4n`vU6zzLo)TmPur37WBw|)W zPSj=1=Tz$mZ<-j-0Iuvpag2A68Z}f6K()9s!=fB@bL(oucsVzqwi)_dse&4o8>Fq8 zBk%rQX#`kd=<=$vYO!h#*T;UR@yEJ`85_3Fr-u5*y2n>gbLnvi!>NXIXFgjI&6*lJ zjXI~g9@ZFS%?Vb!j&-nZ)fB4TYLIoN+E51#aZAt>6<0#FTMe?VaJRdW>R|mJqlQrJ zR)dZ(9CsVKysLH@1%zt18e}=v%^9p;Q>>>gUH!Hn_-HjqPdHr}=PK%8-MXd>4JB5C zHW|gAWa#p)I@Ks(i>tF5^n+`}dOhwzXB%}|wGT97@}viY)=XM25!8iH-#BBExCh-Z zx4_UI#KqiRjJ|RWS-;WH4GIiax`wRZWa#p$y3Qc}zM->K>}r=8 zyP$4O=6#F^AKQN%spzD=SoFg4;jt*16^qRi7gC=r;R{*d*Xyx z#~R)U_v67_VQ?J^z67pl?o;%QW7-kmDK~1c{szljJbs3!b!e%K zXU(F^Q4&P2x2;t)L*|zgs~Wa&woW!G*li$x^}_GD(;qC|vaXUBBIkk_Qun z^>ZQPFrbm&l?i?kvbBPghJtl2xqj=dnKB^Jh5eHCeY9?{Wy-@14v{h7Nnm|>eLUaf zL$+t#fJ9%yzUA94;YzJTK$i~BfVdaPHEznr_s1~F>67Gp;L6=T5pg=q$F7tOaWv^` z28%!!h?6aBytY)#RJN1oT!V?eofG2{uw8cs?gf8?HQ*(1CpZgu?ef@-2Q5Ia1a1R9 z@)<_s?`ip`eF%oj^Csw+7H%y-}d= z_hP39pILax9;}`Rj|F!}y_^PRM4_5ZTi;xZ6&Tx-!BU_rCd4-W(V@1gZ_w)Of&(DELU^=)6SWh=mheW?+T?0D6 zD)2E)*~~I?@hR}02o^rRa#bOZgEop%Qx8b6XX*@iEYLqMXelV}fPY@V?=N(?~v`{h>SWEz5#j? z`w4iD!(ltix)GlSeL=Oa0G%l|g5N=BfM02d{&=JzjSe(A(C9#;1C0(;z61XQtcXF# T@3End Mute microphone Are you sure you want to mute **%1$s** in this voice chat? - Remove member + Remove participant Do you want to remove %1$s from the voice chat and ban them in %2$s? **%1$s** removed from the group. **%1$s** can now speak. @@ -3551,6 +3551,8 @@ JOIN AS LISTENER Join Voice Chat Are sure you want to appear in this voice chat as your personal account? + Voice chat sound muted. + Voice chat sound unmuted. Manage Invite Links You can create additional invite links that have a limited time or number of uses @@ -4320,4 +4322,6 @@ Unpin Pin Cancel Forwarding + this is you + Open Chat