Update to 7.6.1 (2274)

This commit is contained in:
DrKLO 2021-04-09 16:17:32 +03:00
parent ca13bc972d
commit 7ba9838a2d
86 changed files with 2799 additions and 944 deletions

View file

@ -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']

View file

@ -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<int16_t>(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<int16_t>(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 << ".";

View file

@ -6,6 +6,8 @@
#include "rtc_base/time_utils.h"
#include <thread>
#include <mutex>
#include <condition_variable>
namespace tgcalls {
class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleDefault<webrtc::AudioDeviceModule> {
@ -19,7 +21,20 @@ class FakeAudioDeviceModuleImpl : public webrtc::webrtc_impl::AudioDeviceModuleD
FakeAudioDeviceModuleImpl(webrtc::TaskQueueFactory*, FakeAudioDeviceModule::Options options,
std::shared_ptr<FakeAudioDeviceModule::Renderer> 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<int64_t>(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<std::mutex> lock(mutex_);
audio_callback_ = callback;
return 0;
}
int32_t StartPlayout() override {
webrtc::MutexLock lock(&lock_);
std::unique_lock<std::mutex> lock(mutex_);
RTC_CHECK(renderer_);
if (rendering_) {
return 0;
}
need_rendering_ = true;
rendering_ = true;
renderThread_ = std::make_unique<rtc::PlatformThread>(
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<std::mutex> 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<FakeAudioDeviceModuleImpl*>(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<std::mutex> 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<void(FakeAudioDeviceModule::Task)> scheduler_;
mutable std::mutex mutex_;
std::atomic<bool> need_rendering_{false};
std::atomic<bool> rendering_{false};
std::condition_variable cond_;
std::unique_ptr<rtc::PlatformThread> renderThread_;
webrtc::AudioTransport* audio_callback_{nullptr};
const std::shared_ptr<FakeAudioDeviceModule::Renderer> renderer_ RTC_GUARDED_BY(lock_);
std::vector<int16_t> playout_buffer_ RTC_GUARDED_BY(lock_);
const std::shared_ptr<FakeAudioDeviceModule::Renderer> renderer_;
std::vector<int16_t> playout_buffer_;
};
std::function<rtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory*)> FakeAudioDeviceModule::Creator(

View file

@ -32,9 +32,11 @@ class FakeAudioDeviceModule {
return 10000;
}
};
using Task = std::function<double()>;
struct Options {
uint32_t samples_per_sec{48000};
uint32_t num_channels{2};
std::function<void(Task)> scheduler_;
};
static std::function<rtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory *)> Creator(
std::shared_ptr<Renderer> renderer, Options options);

View file

@ -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 {

View file

@ -1,6 +1,7 @@
#include "StaticThreads.h"
#include "rtc_base/thread.h"
#include "call/call.h"
#include <mutex>
#include <algorithm>
@ -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<webrtc::SharedModuleThread> getSharedModuleThread() override {
return shared_module_thread_;
}
private:
Thread network_;
Thread media_;
Thread worker_;
Thread process_;
rtc::scoped_refptr<webrtc::SharedModuleThread> shared_module_thread_;
static Thread create(const std::string &name) {
return init(std::unique_ptr<rtc::Thread>(rtc::Thread::Create()), name);

View file

@ -5,6 +5,11 @@
namespace rtc {
class Thread;
template <class T>
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<webrtc::SharedModuleThread> 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<webrtc::SharedModuleThread> getSharedMoudleThread();
std::shared_ptr<Threads> &getThreads();
}

View file

@ -255,35 +255,46 @@ private:
std::function<void(rtc::CopyOnWriteBuffer const *, rtc::SentPacket)> _sendPacket;
};
static const int kVadResultHistoryLength = 8;
static const int kVadResultHistoryLength = 6;
class CombinedVad {
private:
webrtc::VadLevelAnalyzer _vadWithLevel;
float _vadResultHistory[kVadResultHistoryLength];
std::atomic<int32_t> _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<float> 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<void(Update)> update,
ChannelId channel_id, std::function<void(uint32_t, const AudioFrame &)> onAudioFrame) :
_update(update), _channel_id(channel_id), _onAudioFrame(std::move(onAudioFrame)) {
_vad = std::make_shared<CombinedVad>();
_vad = std::make_shared<CombinedVad>(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<webrtc::VideoFrame> {
@ -563,9 +567,7 @@ public:
outgoingAudioDescription.reset();
incomingAudioDescription.reset();
std::unique_ptr<AudioSinkImpl> audioLevelSink(new AudioSinkImpl([onAudioLevelUpdated = std::move(onAudioLevelUpdated)](AudioSinkImpl::Update update) {
onAudioLevelUpdated(update);
}, _ssrc, std::move(onAudioFrame)));
std::unique_ptr<AudioSinkImpl> 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<webrtc::RtcEventLogNull>()),
_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<GroupNetworkManager>(_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<void>(RTC_FROM_HERE, [strong] {});
});
});
});
webrtc::AudioProcessingBuilder builder;
builder.SetCaptureAnalyzer(std::unique_ptr<AudioCaptureAnalyzer>(analyzer));
webrtc::AudioProcessingBuilder builder;
builder.SetCaptureAnalyzer(std::unique_ptr<AudioCaptureAnalyzer>(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<GroupInstanceCustomInternal>(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<GroupInstanceCustomInternal>(shared_from_this());
std::unique_ptr<IncomingAudioChannel> 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<void(AudioSinkImpl::Update)> 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<IncomingAudioChannel> 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<BroadcastPartTask>(std::shared_ptr<PlatformContext>, int64_t, int64_t, std::function<void(BroadcastPart &&)>)> _requestBroadcastPart;
std::shared_ptr<VideoCaptureInterface> _videoCapture;
bool _disableIncomingChannels = false;
bool _useDummyChannel{true};
int64_t _lastUnknownSsrcsReport = 0;
std::set<uint32_t> _pendingUnknownSsrcs;
@ -2353,5 +2375,35 @@ void GroupInstanceCustomImpl::setFullSizeVideoSsrc(uint32_t ssrc) {
internal->setFullSizeVideoSsrc(ssrc);
});
}
std::vector<GroupInstanceInterface::AudioDevice> GroupInstanceInterface::getAudioDevices(AudioDevice::Type type) {
auto result = std::vector<AudioDevice>();
#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

View file

@ -85,7 +85,8 @@ struct GroupInstanceDescriptor {
std::function<void(uint32_t, const AudioFrame &)> onAudioFrame;
std::string initialInputDeviceId;
std::string initialOutputDeviceId;
bool debugIgnoreMissingSsrcs = false;
bool useDummyChannel{true};
bool disableIncomingChannels{false};
std::function<rtc::scoped_refptr<webrtc::AudioDeviceModule>(webrtc::TaskQueueFactory*)> createAudioDeviceModule;
std::shared_ptr<VideoCaptureInterface> videoCapture;
std::function<void(std::vector<uint32_t> const &)> incomingVideoSourcesUpdated;
@ -197,7 +198,7 @@ public:
std::string name;
std::string guid;
};
static std::vector<GroupInstanceInterface::AudioDevice> getAudioDevices(AudioDevice::Type type);
};
} // namespace tgcalls

View file

@ -12,6 +12,7 @@ extern "C" {
#include <string>
#include <set>
#include <map>
#include <stdint.h>
namespace tgcalls {
@ -288,6 +289,10 @@ public:
}
private:
static int16_t sampleFloatToInt16(float sample) {
return av_clip_int16 (static_cast<int32_t>(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;

View file

@ -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<Character> charactersMap;

View file

@ -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;

View file

@ -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);

View file

@ -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";

View file

@ -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<TLRPC.TL_groupCallParticipant> 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);

View file

@ -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;

View file

@ -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) {

View file

@ -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<TLRPC.MessageEntity> entities, int offset) {
private String getUserName(TLObject object, ArrayList<TLRPC.MessageEntity> 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;
}

View file

@ -3165,7 +3165,7 @@ public class MessagesController extends BaseController implements NotificationCe
final SparseArray<TLRPC.ChannelParticipant> 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<MessageObject> pushMessages;
if (createMessage && !getMessagesStorage().hasInviteMeMessage(chatId)) {

View file

@ -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<TLObject> resultArray, ArrayList<CharSequence> resultArrayNames, ArrayList<TLRPC.User> encUsers, int folderId) {
public void localSearch(int dialogsType, String query, ArrayList<Object> resultArray, ArrayList<CharSequence> resultArrayNames, ArrayList<TLRPC.User> encUsers, int folderId) {
int selfUserId = UserConfig.getInstance(currentAccount).getClientUserId();
try {
String search1 = query.trim().toLowerCase();

View file

@ -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);

View file

@ -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) {

View file

@ -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());
}
}

View file

@ -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();
}
}

View file

@ -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();

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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:

View file

@ -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) {

View file

@ -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<Chat> chats = new ArrayList<>();
public ArrayList<User> 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<ChannelParticipant> participants = new ArrayList<>();
public ArrayList<Chat> chats = new ArrayList<>();
public ArrayList<User> 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);
}
}

View file

@ -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());
}
}
}

View file

@ -62,7 +62,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
private Context mContext;
private Runnable searchRunnable;
private Runnable searchRunnable2;
private ArrayList<TLObject> searchResult = new ArrayList<>();
private ArrayList<Object> searchResult = new ArrayList<>();
private ArrayList<CharSequence> searchResultNames = new ArrayList<>();
private ArrayList<MessageObject> searchResultMessages = new ArrayList<>();
private ArrayList<String> searchResultHashtags = new ArrayList<>();
@ -556,7 +556,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
return;
}
MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> {
ArrayList<TLObject> resultArray = new ArrayList<>();
ArrayList<Object> resultArray = new ArrayList<>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
ArrayList<TLRPC.User> 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<TLObject> result, final ArrayList<CharSequence> names, final ArrayList<TLRPC.User> encUsers, final int searchId) {
private void updateSearchResults(final ArrayList<Object> result, final ArrayList<CharSequence> names, final ArrayList<TLRPC.User> 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);

View file

@ -218,13 +218,13 @@ public class FiltersView extends RecyclerListView {
return usersFilters.get(i);
}
public void setUsersAndDates(ArrayList<TLObject> localUsers, ArrayList<DateData> dates) {
public void setUsersAndDates(ArrayList<Object> localUsers, ArrayList<DateData> 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;

View file

@ -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);
}
}
}

View file

@ -46,7 +46,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter {
private Context mContext;
private SparseArray<TLRPC.User> ignoreUsers;
private ArrayList<TLObject> searchResult = new ArrayList<>();
private ArrayList<Object> searchResult = new ArrayList<>();
private ArrayList<CharSequence> searchResultNames = new ArrayList<>();
private SearchAdapterHelper searchAdapterHelper;
private SparseArray<?> checkedMap;
@ -156,7 +156,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter {
search[1] = search2;
}
ArrayList<TLObject> resultArray = new ArrayList<>();
ArrayList<Object> resultArray = new ArrayList<>();
ArrayList<CharSequence> 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<TLObject> users, final ArrayList<CharSequence> names) {
private void updateSearchResults(int searchReqIdFinal, final ArrayList<Object> users, final ArrayList<CharSequence> names) {
AndroidUtilities.runOnUIThread(() -> {
if (searchReqIdFinal == searchReqId) {
searchResult = users;

View file

@ -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<TLObject> groupSearchMap = new SparseArray<>();
private SparseArray<TLObject> phoneSearchMap = new SparseArray<>();
private ArrayList<Object> phonesSearch = new ArrayList<>();
private ArrayList<TLObject> localSearchResults;
private ArrayList<Object> 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<TLObject> localResults) {
public void mergeResults(ArrayList<Object> 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);

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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));

View file

@ -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);

View file

@ -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();

View file

@ -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) {

View file

@ -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) {

View file

@ -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<TLObject> searchResult = new ArrayList<>();
private ArrayList<Object> searchResult = new ArrayList<>();
private SparseArray<TLObject> searchResultMap = new SparseArray<>();
private ArrayList<CharSequence> searchResultNames = new ArrayList<>();
private SearchAdapterHelper searchAdapterHelper;
@ -2506,28 +2558,43 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
if (search2 != null) {
search[1] = search2;
}
ArrayList<TLObject> resultArray = new ArrayList<>();
ArrayList<Object> resultArray = new ArrayList<>();
SparseArray<TLObject> resultMap = new SparseArray<>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
ArrayList<TLObject> 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<TLObject> users, final SparseArray<TLObject> usersMap, final ArrayList<CharSequence> names, final ArrayList<TLObject> participants) {
private void updateSearchResults(final ArrayList<Object> users, final SparseArray<TLObject> usersMap, final ArrayList<CharSequence> names, final ArrayList<TLObject> 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;

View file

@ -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;
}

View file

@ -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();

View file

@ -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();
}

View file

@ -139,7 +139,7 @@ public final class Bulletin {
}
public Bulletin show() {
if (!showing) {
if (!showing && containerLayout != null) {
showing = true;
if (layout.getParent() != parentLayout) {

View file

@ -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 {

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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<TLObject> searchResult = new ArrayList<>();
private ArrayList<Object> searchResult = new ArrayList<>();
private ArrayList<CharSequence> 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<TLObject> users, final ArrayList<CharSequence> names) {
private void updateSearchResults(final ArrayList<Object> users, final ArrayList<CharSequence> names) {
AndroidUtilities.runOnUIThread(() -> {
searchRunnable = null;
searchResult = users;
@ -922,7 +922,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica
search[1] = search2;
}
ArrayList<TLObject> resultArray = new ArrayList<>();
ArrayList<Object> resultArray = new ArrayList<>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
for (int a = 0; a < contacts.size(); a++) {

View file

@ -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);
}
}

View file

@ -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

View file

@ -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<String> videoFileNames = new ArrayList<>();
private ArrayList<String> 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<TLRPC.Photo> arrayList = (ArrayList<TLRPC.Photo>) 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;
}
}
}

View file

@ -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<DialogSearchResult> searchResult = new ArrayList<>();
private ArrayList<Object> 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<DialogSearchResult> searchResults = new ArrayList<>(resultCount);
ArrayList<Object> 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<DialogSearchResult> result, final int searchId) {
private void updateSearchResults(final ArrayList<Object> 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<TLObject> 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<TLObject> 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);
}
}

View file

@ -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 {

View file

@ -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) {

View file

@ -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));
}
}

View file

@ -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));

View file

@ -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]);

View file

@ -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<TLObject> users, ArrayList<FiltersView.DateData> dates, boolean animated) {
private void updateFiltersView(boolean showMediaFilters, ArrayList<Object> users, ArrayList<FiltersView.DateData> 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<TLObject> finalUsers = (users != null && !users.isEmpty() && !hasUserFilter) ? users : null;
ArrayList<Object> finalUsers = (users != null && !users.isEmpty() && !hasUserFilter) ? users : null;
ArrayList<FiltersView.DateData> 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);

View file

@ -957,7 +957,7 @@ public class FilterUsersActivity extends BaseFragment implements NotificationCen
public class GroupCreateAdapter extends RecyclerListView.FastScrollAdapter {
private Context context;
private ArrayList<TLObject> searchResult = new ArrayList<>();
private ArrayList<Object> searchResult = new ArrayList<>();
private ArrayList<CharSequence> searchResultNames = new ArrayList<>();
private SearchAdapterHelper searchAdapterHelper;
private Runnable searchRunnable;
@ -1269,7 +1269,7 @@ public class FilterUsersActivity extends BaseFragment implements NotificationCen
search[1] = search2;
}
ArrayList<TLObject> resultArray = new ArrayList<>();
ArrayList<Object> resultArray = new ArrayList<>();
ArrayList<CharSequence> 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<TLObject> users, final ArrayList<CharSequence> names) {
private void updateSearchResults(final ArrayList<Object> users, final ArrayList<CharSequence> names) {
AndroidUtilities.runOnUIThread(() -> {
if (!searching) {
return;

View file

@ -124,7 +124,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
private int searchIndex;
ArrayList<TLObject> localTipChats = new ArrayList<>();
ArrayList<Object> localTipChats = new ArrayList<>();
ArrayList<FiltersView.DateData> localTipDates = new ArrayList<>();
Runnable clearCurrentResultsRunnable = new Runnable() {
@ -510,7 +510,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
AndroidUtilities.runOnUIThread(searchRunnable = () -> {
TLObject request;
ArrayList<TLObject> resultArray = null;
ArrayList<Object> 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<TLObject> finalResultArray = resultArray;
ArrayList<Object> finalResultArray = resultArray;
final ArrayList<FiltersView.DateData> 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<TLObject> users, ArrayList<FiltersView.DateData> dates);
void updateFiltersView(boolean showMediaFilters, ArrayList<Object> users, ArrayList<FiltersView.DateData> dates);
}
public interface UiCallback {

View file

@ -1132,7 +1132,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
public class GroupCreateAdapter extends RecyclerListView.FastScrollAdapter {
private Context context;
private ArrayList<TLObject> searchResult = new ArrayList<>();
private ArrayList<Object> searchResult = new ArrayList<>();
private ArrayList<CharSequence> 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<TLObject> resultArray = new ArrayList<>();
ArrayList<Object> resultArray = new ArrayList<>();
ArrayList<CharSequence> 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<TLObject> users, final ArrayList<CharSequence> names) {
private void updateSearchResults(final ArrayList<Object> users, final ArrayList<CharSequence> names) {
AndroidUtilities.runOnUIThread(() -> {
if (!searching) {
return;

View file

@ -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);

View file

@ -922,7 +922,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment {
search[1] = search2;
}
ArrayList<TLObject> resultArray = new ArrayList<>();
ArrayList<Object> resultArray = new ArrayList<>();
ArrayList<NotificationsSettingsActivity.NotificationException> exceptionsArray = new ArrayList<>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
@ -1002,7 +1002,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment {
});
}
private void updateSearchResults(final ArrayList<TLObject> result, final ArrayList<NotificationsSettingsActivity.NotificationException> exceptions, final ArrayList<CharSequence> names) {
private void updateSearchResults(final ArrayList<Object> result, final ArrayList<NotificationsSettingsActivity.NotificationException> exceptions, final ArrayList<CharSequence> names) {
AndroidUtilities.runOnUIThread(() -> {
if (!searching) {
return;

View file

@ -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<SecureDocument> arrayList = new ArrayList<>();
arrayList.add(selfieDocument);
PhotoViewer.getInstance().openPhoto(arrayList, 0, provider);
} else if (type == UPLOADING_TYPE_FRONT) {
ArrayList<SecureDocument> arrayList = new ArrayList<>();
arrayList.add(frontDocument);
PhotoViewer.getInstance().openPhoto(arrayList, 0, provider);
} else if (type == UPLOADING_TYPE_REVERSE) {
ArrayList<SecureDocument> 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);

View file

@ -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;

View file

@ -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<TLRPC.InputDocument> 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;
}
}

View file

@ -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++) {

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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();
});

View file

@ -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();

View file

@ -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");

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -3472,7 +3472,7 @@
<string name="VoipGroupEnd">End</string>
<string name="VoipGroupMuteMemberAlertTitle">Mute microphone</string>
<string name="VoipGroupMuteMemberAlertText">Are you sure you want to mute **%1$s** in this voice chat?</string>
<string name="VoipGroupRemoveMemberAlertTitle">Remove member</string>
<string name="VoipGroupRemoveMemberAlertTitle2">Remove participant</string>
<string name="VoipGroupRemoveMemberAlertText2">Do you want to remove %1$s from the voice chat and ban them in %2$s?</string>
<string name="VoipGroupRemovedFromGroup">**%1$s** removed from the group.</string>
<string name="VoipGroupUserCanNowSpeak">**%1$s** can now speak.</string>
@ -3551,6 +3551,8 @@
<string name="VoipGroupJoinAsLinstener">JOIN AS LISTENER</string>
<string name="VoipGroupJoinVoiceChatUrl">Join Voice Chat</string>
<string name="VoipGroupJoinAnonymouseAlert">Are sure you want to appear in this voice chat as your personal account?</string>
<string name="VoipGroupSoundMuted">Voice chat sound muted.</string>
<string name="VoipGroupSoundUnmuted">Voice chat sound unmuted.</string>
<!--invite links-->
<string name="ManageInviteLinks">Manage Invite Links</string>
<string name="ManageLinksInfoHelp">You can create additional invite links that have a limited time or number of uses</string>
@ -4320,4 +4322,6 @@
<string name="SwipeUnpin">Unpin</string>
<string name="SwipePin">Pin</string>
<string name="CancelForwarding">Cancel Forwarding</string>
<string name="ThisIsYou">this is you</string>
<string name="VoipGroupOpenChat">Open Chat</string>
</resources>